@vesk/adapter 0.2.77 → 0.2.80

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-function.d.ts","sourceRoot":"","sources":["../src/ssr-function.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAkB,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7F;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQlG;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEjF;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEpF;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQvG;AAgED;;;2EAG2E;AAC3E,wBAAgB,qBAAqB,IAAI,MAAM,CA4C9C;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,kBAAkB,GAC3B;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CA+hBtD"}
1
+ {"version":3,"file":"ssr-function.d.ts","sourceRoot":"","sources":["../src/ssr-function.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAkB,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7F;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQlG;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEjF;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEpF;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQvG;AAgED;;;2EAG2E;AAC3E,wBAAgB,qBAAqB,IAAI,MAAM,CA4C9C;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,kBAAkB,GAC3B;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAqftD"}
@@ -1,4 +1,4 @@
1
- import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';
1
+ import { readFileSync, existsSync } from 'node:fs';
2
2
  import { resolve, relative, join } from 'node:path';
3
3
  import { resolveComponentName, precompileFile } from '@vesk/compiler/src/server-codegen';
4
4
  import { resolveCssUrls, hasBuiltGlobalCss } from '@vesk/adapter/src/css';
@@ -163,39 +163,6 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
163
163
  const middlewareCode = options?.middlewareCode || null;
164
164
  const headExtra = options?.headExtra || null;
165
165
  const pagePath = resolve(appDir, routeNode.sourceDir, 'page.vsk');
166
- // Precompiled plans are written to static files and fetched at render time
167
- // instead of being embedded inline. Embedding every page/layout/error plan as
168
- // inline JSON makes each SSR function module large enough to OOM on memory-
169
- // constrained build containers (e.g. Vercel's 2048 MB serverless limit).
170
- const plansDir = resolve(outDir, 'static', 'ssr-plans');
171
- mkdirSync(plansDir, { recursive: true });
172
- function writePlan(planKey, planJSON) {
173
- const fileName = `plan-${planKey}.mjs`;
174
- const planFile = resolve(plansDir, fileName);
175
- writeFileSync(planFile, `export const plan = ${planJSON};\n`, 'utf-8');
176
- // Return a relative path from the SSR function directory so dynamic
177
- // import() inside the generated function resolves to the plan module.
178
- return relative(resolve(outDir, 'server', 'functions'), planFile);
179
- }
180
- /** Generates a lazy getter that imports a precompiled plan module and compiles
181
- * it with hydratePrecompile on first use, caching the result. Import failures
182
- * degrade to null (renderPage falls back to compiling from source).
183
- * The IIFE form is a single expression so it can be placed anywhere — inside
184
- * array literals, object literals, or at module scope — without syntax errors.
185
- */
186
- function planGetterCode(varName, planUrl) {
187
- return `const ${varName} = (() => {
188
- let cache = null;
189
- return async () => {
190
- if (cache) return cache;
191
- try {
192
- const mod = await import(${JSON.stringify(planUrl)});
193
- cache = hydratePrecompile(mod.plan);
194
- } catch { cache = null; }
195
- return cache;
196
- };
197
- })();`;
198
- }
199
166
  const parts = routeNode.fullPath.split('/').filter(Boolean);
200
167
  const name = routeName(parts);
201
168
  const funcDir = resolve(outDir, 'server', 'functions');
@@ -213,15 +180,15 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
213
180
  ...(routeNode.layout ? [{ sourceDir: routeNode.sourceDir, layoutCompName: routeNode.layout }] : []),
214
181
  ];
215
182
  const layoutDecls = [];
216
- for (let li = 0; li < layoutStack.length; li++) {
217
- const entry = layoutStack[li];
183
+ for (const entry of layoutStack) {
218
184
  const entryPath = resolve(appDir, entry.sourceDir, 'layout.vsk');
219
185
  const entrySrc = readFileSync(entryPath, 'utf-8');
220
186
  const entryComp = extractCompName(entrySrc) || 'Layout';
221
187
  const plan = precompilePlan(entryPath);
222
188
  layoutDecls.push({
223
189
  comp: JSON.stringify(entryComp),
224
- planUrl: writePlan('layout-' + name + '-' + li, plan),
190
+ plan,
191
+ compiled: hydrateInvoke(plan),
225
192
  });
226
193
  }
227
194
  const pagePlan = precompilePlan(pagePath);
@@ -229,9 +196,8 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
229
196
  const errorPath = resolveErrorFile(routeNode.sourceDir, appDir);
230
197
  const errorSrc = errorPath ? readFileSync(errorPath, 'utf-8') : null;
231
198
  const errorComp = errorPath ? (extractCompName(errorSrc) || 'Error') : null;
232
- const errorVars = errorPath
233
- ? `const _errorComp = ${JSON.stringify(errorComp)};\n${planGetterCode('_errorCompiled', writePlan('error-' + name, precompilePlan(errorPath)))}\n`
234
- : 'const _errorComp = null;\nasync function _errorCompiled() { return null; }\n';
199
+ const errorCompDecl = errorPath ? `const _errorComp = ${JSON.stringify(errorComp)};\n` : 'const _errorComp = null;\n';
200
+ const errorPlanExpr = errorPath ? hydrateInvoke(precompilePlan(errorPath)) : 'null';
235
201
  // Not-found used to have no server-side resolution at all: a NotFoundError was
236
202
  // re-thrown out of the function and the prod server answered with the ROOT
237
203
  // not-found.vsk. A nested `app/admin/not-found.vsk` therefore did nothing on a
@@ -241,25 +207,24 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
241
207
  const notFoundPath = resolveNotFoundFile(routeNode.sourceDir, appDir);
242
208
  const notFoundSrc = notFoundPath ? readFileSync(notFoundPath, 'utf-8') : null;
243
209
  const notFoundComp = notFoundPath ? (extractCompName(notFoundSrc) || 'NotFound') : null;
244
- const notFoundVars = notFoundPath
245
- ? `const _notFoundComp = ${JSON.stringify(notFoundComp)};\n${planGetterCode('_notFoundCompiled', writePlan('notfound-' + name, precompilePlan(notFoundPath)))}\n`
246
- : 'const _notFoundComp = null;\nasync function _notFoundCompiled() { return null; }\n';
247
- const pagePlanUrl = writePlan('page-' + name, pagePlan);
210
+ const notFoundCompDecl = notFoundPath ? `const _notFoundComp = ${JSON.stringify(notFoundComp)};\n` : 'const _notFoundComp = null;\n';
211
+ const notFoundPlanExpr = notFoundPath ? hydrateInvoke(precompilePlan(notFoundPath)) : 'null';
248
212
  let src = '';
249
213
  if (layoutDecls.length > 0) {
250
- const pageGetter = planGetterCode('_pageCompiled', pagePlanUrl);
251
- const layoutGetters = layoutDecls.map((d, i) => planGetterCode('_layoutCompiled_' + i, d.planUrl));
252
- src = `const _pageComp = ${JSON.stringify(pageComp)};\n`;
253
- src += pageGetter + '\n';
254
- src += layoutGetters.join('\n') + '\n';
214
+ src = errorCompDecl + notFoundCompDecl;
215
+ src += `const _pageComp = ${JSON.stringify(pageComp)};\n`;
216
+ src += `let _pageCompiled = null;\nfunction __getPageCompiled() { if (!_pageCompiled) _pageCompiled = (() => { try { return hydratePrecompile(${pagePlan}); } catch { return null; } })(); return _pageCompiled; }\n`;
255
217
  src += `const _layoutCompList = [${layoutDecls.map((d) => d.comp).join(', ')}];\n`;
256
- src += `const _layoutCompiledList = [${layoutDecls.map((_, i) => '_layoutCompiled_' + i).join(', ')}];\n`;
257
- src += errorVars + notFoundVars;
218
+ src += `let _layoutCompiledList = null;\nfunction __getLayoutCompiledList() { if (!_layoutCompiledList) { _layoutCompiledList = [\n${layoutDecls.map((d) => ' ' + d.compiled + ',').join('\n')}\n]; } return _layoutCompiledList; }\n`;
219
+ src += `let _errorCompiled = null;\nfunction __getErrorCompiled() { if (!_errorCompiled) _errorCompiled = ${errorPlanExpr}; return _errorCompiled; }\n`;
220
+ src += `let _notFoundCompiled = null;\nfunction __getNotFoundCompiled() { if (!_notFoundCompiled) _notFoundCompiled = ${notFoundPlanExpr}; return _notFoundCompiled; }\n`;
258
221
  }
259
222
  else {
260
- src = `const _comp = ${JSON.stringify(pageComp)};\n`;
261
- src += planGetterCode('_compiled', pagePlanUrl) + '\n';
262
- src += errorVars + notFoundVars;
223
+ src = errorCompDecl + notFoundCompDecl;
224
+ src += `const _comp = ${JSON.stringify(pageComp)};\n`;
225
+ src += `let _compiled = null;\nfunction __getCompiled() { if (!_compiled) _compiled = (() => { try { return hydratePrecompile(${pagePlan}); } catch { return null; } })(); return _compiled; }\n`;
226
+ src += `let _errorCompiled = null;\nfunction __getErrorCompiled() { if (!_errorCompiled) _errorCompiled = ${errorPlanExpr}; return _errorCompiled; }\n`;
227
+ src += `let _notFoundCompiled = null;\nfunction __getNotFoundCompiled() { if (!_notFoundCompiled) _notFoundCompiled = ${notFoundPlanExpr}; return _notFoundCompiled; }\n`;
263
228
  }
264
229
  const urlParts = routeNode.fullPath.split('/').filter(Boolean);
265
230
  const paramExprs = buildParamExtraction(routeNode, urlParts);
@@ -272,19 +237,17 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
272
237
  let registryCode = '';
273
238
  const compRegEntries = [];
274
239
  const compMap = componentMap || new Map();
275
- let compCounter = 0;
240
+ const regPlans = [];
276
241
  for (const [compName, compPath] of compMap) {
277
242
  const plan = precompilePlan(compPath);
278
- const compPlanUrl = writePlan('comp-' + name + '-' + compCounter, plan);
279
- const compGetter = '_compiled_' + compCounter;
280
- compCounter++;
281
- compRegEntries.push(` (() => {\n${planGetterCode(compGetter, compPlanUrl)}\n __componentRegistry.set(${JSON.stringify(compName)}, async (props, __registry, __vesk) => {\n const result = await renderPage('', ${JSON.stringify(compName)}, props, __registry, { hydrate: true, cached: await ${compGetter}() });\n return result.body;\n });\n })();`);
243
+ regPlans.push(` __regPlans.set(${JSON.stringify(compName)}, ${JSON.stringify(plan)});`);
244
+ compRegEntries.push(` __componentRegistry.set(${JSON.stringify(compName)}, async (props, __registry, __vesk) => {\n let _compiled = __regCompiled.get(${JSON.stringify(compName)});\n if (!_compiled) { _compiled = hydratePrecompile(__regPlans.get(${JSON.stringify(compName)})); __regCompiled.set(${JSON.stringify(compName)}, _compiled); }\n const result = await renderPage('', ${JSON.stringify(compName)}, props, __registry, { hydrate: true, cached: _compiled });\n return result.body;\n });`);
282
245
  }
283
246
  if (compRegEntries.length > 0) {
284
- registryCode = 'const __componentRegistry = new Map();\n{\n' + compRegEntries.join('\n') + '\n}\n';
247
+ registryCode = 'const __componentRegistry = new Map();\nconst __regPlans = new Map();\nconst __regCompiled = new Map();\n{\n' + regPlans.join('\n') + '\n' + compRegEntries.join('\n') + '\n}\n';
285
248
  }
286
249
  else {
287
- registryCode = 'const __componentRegistry = new Map();\n';
250
+ registryCode = 'const __componentRegistry = new Map();\nconst __regPlans = new Map();\nconst __regCompiled = new Map();\n';
288
251
  }
289
252
  let htmlFnCode;
290
253
  if (layoutDecls.length > 0) {
@@ -292,7 +255,7 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
292
255
  'async function __renderErrorBody(props) {',
293
256
  ' if (!_errorComp) throw props.error || new Error("Internal Server Error");',
294
257
  ' try {',
295
- ' const result = await renderPage(\'\', _errorComp, props, __componentRegistry, { hydrate: true, cached: await _errorCompiled() });',
258
+ ' const result = await renderPage(\'\', _errorComp, props, __componentRegistry, { hydrate: true, cached: __getErrorCompiled() });',
296
259
  ' return result.body;',
297
260
  ' } catch {',
298
261
  ` return ${JSON.stringify(renderDefaultErrorFragment())};`,
@@ -305,7 +268,7 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
305
268
  'async function __renderNotFoundBody(props) {',
306
269
  ' if (!_notFoundComp) return null;',
307
270
  ' try {',
308
- ' const result = await renderPage(\'\', _notFoundComp, props, __componentRegistry, { hydrate: true, cached: await _notFoundCompiled() });',
271
+ ' const result = await renderPage(\'\', _notFoundComp, props, __componentRegistry, { hydrate: true, cached: __getNotFoundCompiled() });',
309
272
  ' return result.body;',
310
273
  ' } catch {',
311
274
  ' return null;',
@@ -319,11 +282,11 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
319
282
  ' let _b = body;',
320
283
  ' let _h = head || "";',
321
284
  ' for (let _i = _layoutCompList.length - 1; _i > 0; _i--) {',
322
- " const _inner = await renderPage('', _layoutCompList[_i], { params, children: _b }, __componentRegistry, { hydrate: true, cached: await _layoutCompiledList[_i]() });",
285
+ " const _inner = await renderPage('', _layoutCompList[_i], { params, children: _b }, __componentRegistry, { hydrate: true, cached: __getLayoutCompiledList()[_i] });",
323
286
  ' _b = _inner.body;',
324
287
  ' if (_inner.head) _h = _inner.head + _h;',
325
288
  ' }',
326
- " return renderFullPage('', _layoutCompList[0], { params, children: _b }, __componentRegistry, { hydrate: true, cached: await _layoutCompiledList[0]()" + bakedOptions + clientScriptOption + dataScriptOption + ", pageHead: _h });",
289
+ " return renderFullPage('', _layoutCompList[0], { params, children: _b }, __componentRegistry, { hydrate: true, cached: __getLayoutCompiledList()[0]" + bakedOptions + clientScriptOption + dataScriptOption + ", pageHead: _h });",
327
290
  '}',
328
291
  '',
329
292
  'async function __renderHtml(params, requestUrl) {',
@@ -334,7 +297,7 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
334
297
  ' let notFound = false;',
335
298
  " const __expose = process.env.NODE_ENV !== 'production';",
336
299
  ' try {',
337
- ' page = await renderPage(\'\', _pageComp, { params }, __componentRegistry, { hydrate: true, cached: await _pageCompiled() });',
300
+ ' page = await renderPage(\'\', _pageComp, { params }, __componentRegistry, { hydrate: true, cached: __getPageCompiled() });',
338
301
  ' } catch (err) {',
339
302
  " if (err && err.name === 'Redirect') throw err;",
340
303
  " if (err && err.name === 'NotFoundError') {",
@@ -372,7 +335,7 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
372
335
  " const message = err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err);",
373
336
  " const stack = err && typeof err === 'object' && 'stack' in err ? String(err.stack) : '';",
374
337
  " const props = { params, statusCode: 500, error: __expose ? message : 'Internal Server Error', stack: __expose ? stack : '', url: requestUrl || '' };",
375
- " return renderFullPage('', _errorComp, props, __componentRegistry, { hydrate: true, cached: await _errorCompiled()" + bakedOptions + clientScriptOption + dataScriptOption + " });",
338
+ " return renderFullPage('', _errorComp, props, __componentRegistry, { hydrate: true, cached: __getErrorCompiled()" + bakedOptions + clientScriptOption + dataScriptOption + " });",
376
339
  '}',
377
340
  '',
378
341
  'async function __renderHtml(params, requestUrl) {',
@@ -387,7 +350,7 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
387
350
  // though it runs outside the ALS scope.
388
351
  " const __streamToken = globalThis.__vsk_ssr_token || '';",
389
352
  ' try {',
390
- " stream = renderPageStream('', _comp, { params }, __componentRegistry, { hydrate: true, cached: await _compiled()" + bakedOptions + clientScriptOption + dataScriptOption + ' });',
353
+ " stream = renderPageStream('', _comp, { params }, __componentRegistry, { hydrate: true, cached: __getCompiled()" + bakedOptions + clientScriptOption + dataScriptOption + ' });',
391
354
  ' } catch (err) {',
392
355
  ' if (err && (err.name === \'NotFoundError\' || err.name === \'Redirect\')) throw err;',
393
356
  ' const html = await __renderErrorFullPage(params, requestUrl, err);',
@@ -474,7 +437,7 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
474
437
  ' try {',
475
438
  ' let dataPage;',
476
439
  ' try {',
477
- " dataPage = await renderPage('', _pageComp, { params }, __componentRegistry, { hydrate: true, cached: await _pageCompiled() });",
440
+ " dataPage = await renderPage('', _pageComp, { params }, __componentRegistry, { hydrate: true, cached: __getPageCompiled() });",
478
441
  ' } catch (err) {',
479
442
  " if (err && (err.name === 'NotFoundError' || err.name === 'Redirect')) throw err;",
480
443
  ' const message = err && typeof err === \'object\' && \'message\' in err ? String(err.message) : String(err);',
@@ -482,7 +445,7 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
482
445
  ' }',
483
446
  ' let _dataHead = dataPage.head || \'\';',
484
447
  ' for (let _i = _layoutCompList.length - 1; _i >= 0; _i--) {',
485
- " const _dl = await renderPage('', _layoutCompList[_i], { params, children: '' }, __componentRegistry, { hydrate: true, cached: await _layoutCompiledList[_i]() });",
448
+ " const _dl = await renderPage('', _layoutCompList[_i], { params, children: '' }, __componentRegistry, { hydrate: true, cached: __getLayoutCompiledList()[_i] });",
486
449
  ' _dataHead = (_dl.head || \'\') + _dataHead;',
487
450
  ' }',
488
451
  " return new Response(JSON.stringify({ path: url.pathname, params, props: dataPage.props || { params }, head: _dataHead }), {",
@@ -501,7 +464,7 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
501
464
  ' try {',
502
465
  ' let dataPage;',
503
466
  ' try {',
504
- " dataPage = await renderPage('', _comp, { params }, __componentRegistry, { hydrate: true, cached: await _compiled() });",
467
+ " dataPage = await renderPage('', _comp, { params }, __componentRegistry, { hydrate: true, cached: __getCompiled() });",
505
468
  ' } catch (err) {',
506
469
  " if (err && (err.name === 'NotFoundError' || err.name === 'Redirect')) throw err;",
507
470
  ' const message = err && typeof err === \'object\' && \'message\' in err ? String(err.message) : String(err);',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesk/adapter",
3
- "version": "0.2.77",
3
+ "version": "0.2.80",
4
4
  "type": "module",
5
5
  "description": "Vesk adapter — builds deployable .vesk/ output for Deno and Node serverless",
6
6
  "main": "./dist/index.js",
@@ -23,9 +23,9 @@
23
23
  "sharp": "^0.35.3"
24
24
  },
25
25
  "dependencies": {
26
- "@vesk/compiler": "^0.2.77",
27
- "@vesk/runtime": "^0.2.77",
28
- "@vesk/types": "^0.2.77"
26
+ "@vesk/compiler": "^0.2.80",
27
+ "@vesk/runtime": "^0.2.80",
28
+ "@vesk/types": "^0.2.80"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/ws": "^8.18.1",