@jay-framework/dev-server 0.17.3 → 0.18.0
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/index.d.ts +12 -2
- package/dist/index.js +117 -102
- package/package.json +14 -14
package/dist/index.d.ts
CHANGED
|
@@ -141,6 +141,7 @@ interface RouteInfo {
|
|
|
141
141
|
jayHtmlPath: string;
|
|
142
142
|
compPath: string;
|
|
143
143
|
}
|
|
144
|
+
type DevServerRouteRegistrar = (routes: DevServerRoute[]) => void;
|
|
144
145
|
declare class DevServerService {
|
|
145
146
|
private routes;
|
|
146
147
|
private vite;
|
|
@@ -148,8 +149,17 @@ declare class DevServerService {
|
|
|
148
149
|
private projectBase;
|
|
149
150
|
private jayRollupConfig;
|
|
150
151
|
private _freezeStore?;
|
|
151
|
-
|
|
152
|
+
private rescanRoutes?;
|
|
153
|
+
constructor(routes: DevServerRoute[], vite: ViteDevServer, pagesBase: string, projectBase: string, jayRollupConfig: JayRollupConfig, _freezeStore?: FreezeStore, rescanRoutes?: () => Promise<DevServerRoute[]>);
|
|
154
|
+
private routeRegistrar?;
|
|
152
155
|
get freezeStore(): FreezeStore | undefined;
|
|
156
|
+
/** Register new route handlers with Express (or another HTTP layer). */
|
|
157
|
+
attachRouteRegistrar(registrar: DevServerRouteRegistrar): void;
|
|
158
|
+
/**
|
|
159
|
+
* Rescan the pages directory for new routes and register any that were
|
|
160
|
+
* added since dev-server startup (e.g. after AIditor Add Page).
|
|
161
|
+
*/
|
|
162
|
+
refreshRoutes(): Promise<RouteInfo[]>;
|
|
153
163
|
/** List all page routes in the project. */
|
|
154
164
|
listRoutes(): RouteInfo[];
|
|
155
165
|
/**
|
|
@@ -277,4 +287,4 @@ declare function createViteForCli(options: {
|
|
|
277
287
|
tsConfigFilePath?: string;
|
|
278
288
|
}): Promise<ViteDevServer>;
|
|
279
289
|
|
|
280
|
-
export { ACTION_ENDPOINT_BASE, type ActionBodyParserOptions, type ActionRouterOptions, type CreateViteServerOptions, DEV_SERVER_SERVICE, type DevServer, type DevServerOptions, type DevServerRoute, DevServerService, type FreezeEntry, FreezeStore, type RouteInfo, actionBodyParser, createActionRouter, createViteForCli, createViteServer, mkDevServer };
|
|
290
|
+
export { ACTION_ENDPOINT_BASE, type ActionBodyParserOptions, type ActionRouterOptions, type CreateViteServerOptions, DEV_SERVER_SERVICE, type DevServer, type DevServerOptions, type DevServerRoute, type DevServerRouteRegistrar, DevServerService, type FreezeEntry, FreezeStore, type RouteInfo, actionBodyParser, createActionRouter, createViteForCli, createViteServer, mkDevServer };
|
package/dist/index.js
CHANGED
|
@@ -10,13 +10,13 @@ import { createRequire } from "module";
|
|
|
10
10
|
import "@jay-framework/compiler-shared";
|
|
11
11
|
import * as path from "node:path";
|
|
12
12
|
import path__default from "node:path";
|
|
13
|
-
import { JAY_IMPORT_RESOLVER, injectHeadfullFSTemplates, parseContract, slowRenderTransform,
|
|
13
|
+
import { JAY_IMPORT_RESOLVER, injectHeadfullFSTemplates, parseContract, slowRenderTransform, assignCoordinatesToJayHtml, discoverHeadlessInstances } from "@jay-framework/compiler-jay-html";
|
|
14
14
|
import { getLogger, getDevLogger } from "@jay-framework/logger";
|
|
15
15
|
import { createRequire as createRequire$1 } from "node:module";
|
|
16
16
|
import * as fsSync from "node:fs";
|
|
17
17
|
import fsSync__default from "node:fs";
|
|
18
18
|
import { scanRoutes, createRoute, routeToExpressRoute } from "@jay-framework/stack-route-scanner";
|
|
19
|
-
import { discoverPluginsWithInit, sortPluginsByDependencies, executePluginServerInits, runInitCallbacks, actionRegistry, discoverAndRegisterActions, discoverAllPluginActions, runShutdownCallbacks, clearLifecycleCallbacks, clearServiceRegistry, clearClientInitData, loadPageParts, runLoadParams, DevSlowlyChangingPhase, SlowRenderCache, preparePluginClientInits, registerService, clearServerElementCache, scanPlugins, getServiceRegistry, materializeContracts, renderFastChangingData, mergeHeadTags, generateClientScript, getClientInitData, generateSSRPageHtml, generateFrozenPageHtml,
|
|
19
|
+
import { discoverPluginsWithInit, sortPluginsByDependencies, executePluginServerInits, runInitCallbacks, actionRegistry, discoverAndRegisterActions, discoverAllPluginActions, runShutdownCallbacks, clearLifecycleCallbacks, clearServiceRegistry, clearClientInitData, loadPageParts, runLoadParams, DevSlowlyChangingPhase, SlowRenderCache, preparePluginClientInits, registerService, clearServerElementCache, scanPlugins, getServiceRegistry, materializeContracts, parseCookies, renderFastChangingData, mergeHeadTags, generateClientScript, getClientInitData, generateSSRPageHtml, generateFrozenPageHtml, slowRenderInstances } from "@jay-framework/stack-server-runtime";
|
|
20
20
|
import * as fs from "node:fs/promises";
|
|
21
21
|
import fs__default from "node:fs/promises";
|
|
22
22
|
import { pathToFileURL } from "node:url";
|
|
@@ -1949,8 +1949,6 @@ function getStatusCodeForError(code, isActionError) {
|
|
|
1949
1949
|
return 500;
|
|
1950
1950
|
}
|
|
1951
1951
|
}
|
|
1952
|
-
const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
1953
|
-
const DEFAULT_MAX_FILES = 10;
|
|
1954
1952
|
function mergeDottedMultipartKeys(body) {
|
|
1955
1953
|
const keys = Object.keys(body);
|
|
1956
1954
|
for (const key of keys) {
|
|
@@ -1971,7 +1969,7 @@ function mergeDottedMultipartKeys(body) {
|
|
|
1971
1969
|
cur[parts[parts.length - 1]] = val;
|
|
1972
1970
|
}
|
|
1973
1971
|
}
|
|
1974
|
-
function parseMultipart(req, tempDir
|
|
1972
|
+
function parseMultipart(req, tempDir) {
|
|
1975
1973
|
return new Promise((resolve, reject) => {
|
|
1976
1974
|
fs$1.mkdirSync(tempDir, { recursive: true });
|
|
1977
1975
|
const files = {};
|
|
@@ -1980,11 +1978,7 @@ function parseMultipart(req, tempDir, maxFileSize, maxFiles) {
|
|
|
1980
1978
|
let errored = false;
|
|
1981
1979
|
const pendingWrites = [];
|
|
1982
1980
|
const bb = Busboy({
|
|
1983
|
-
headers: req.headers
|
|
1984
|
-
limits: {
|
|
1985
|
-
fileSize: maxFileSize,
|
|
1986
|
-
files: maxFiles
|
|
1987
|
-
}
|
|
1981
|
+
headers: req.headers
|
|
1988
1982
|
});
|
|
1989
1983
|
bb.on("file", (fieldname, stream, info) => {
|
|
1990
1984
|
if (errored)
|
|
@@ -1993,26 +1987,14 @@ function parseMultipart(req, tempDir, maxFileSize, maxFiles) {
|
|
|
1993
1987
|
const filename = info.filename || `upload-${fileCount}`;
|
|
1994
1988
|
const tempPath = path$1.join(tempDir, `${fileCount}-${filename}`);
|
|
1995
1989
|
let size = 0;
|
|
1996
|
-
let truncated = false;
|
|
1997
1990
|
const writeStream = fs$1.createWriteStream(tempPath);
|
|
1998
1991
|
stream.pipe(writeStream);
|
|
1999
1992
|
stream.on("data", (data) => {
|
|
2000
1993
|
size += data.length;
|
|
2001
1994
|
});
|
|
2002
|
-
stream.on("limit", () => {
|
|
2003
|
-
truncated = true;
|
|
2004
|
-
});
|
|
2005
1995
|
pendingWrites.push(
|
|
2006
1996
|
new Promise((resolveWrite, rejectWrite) => {
|
|
2007
1997
|
writeStream.on("close", () => {
|
|
2008
|
-
if (truncated) {
|
|
2009
|
-
rejectWrite(
|
|
2010
|
-
new Error(
|
|
2011
|
-
`File "${filename}" exceeds maximum size of ${maxFileSize} bytes`
|
|
2012
|
-
)
|
|
2013
|
-
);
|
|
2014
|
-
return;
|
|
2015
|
-
}
|
|
2016
1998
|
const jayFile = {
|
|
2017
1999
|
name: filename,
|
|
2018
2000
|
type: info.mimeType,
|
|
@@ -2099,9 +2081,7 @@ function actionBodyParser(options) {
|
|
|
2099
2081
|
}
|
|
2100
2082
|
const requestId = crypto.randomUUID();
|
|
2101
2083
|
const tempDir = path$1.join(buildFolder, ".tmp", "actions", requestId);
|
|
2102
|
-
|
|
2103
|
-
const maxFiles = action.fileOptions?.maxFiles ?? DEFAULT_MAX_FILES;
|
|
2104
|
-
parseMultipart(req, tempDir, maxFileSize, maxFiles).then(({ body: body2, tempDir: td }) => {
|
|
2084
|
+
parseMultipart(req, tempDir).then(({ body: body2, tempDir: td }) => {
|
|
2105
2085
|
req.body = body2;
|
|
2106
2086
|
req._jayTempDir = td;
|
|
2107
2087
|
next();
|
|
@@ -2215,17 +2195,40 @@ class FreezeStore {
|
|
|
2215
2195
|
}
|
|
2216
2196
|
const DEV_SERVER_SERVICE = createJayService("DevServerService");
|
|
2217
2197
|
class DevServerService {
|
|
2218
|
-
constructor(routes, vite, pagesBase, projectBase, jayRollupConfig, _freezeStore) {
|
|
2198
|
+
constructor(routes, vite, pagesBase, projectBase, jayRollupConfig, _freezeStore, rescanRoutes) {
|
|
2199
|
+
__publicField(this, "routeRegistrar");
|
|
2219
2200
|
this.routes = routes;
|
|
2220
2201
|
this.vite = vite;
|
|
2221
2202
|
this.pagesBase = pagesBase;
|
|
2222
2203
|
this.projectBase = projectBase;
|
|
2223
2204
|
this.jayRollupConfig = jayRollupConfig;
|
|
2224
2205
|
this._freezeStore = _freezeStore;
|
|
2206
|
+
this.rescanRoutes = rescanRoutes;
|
|
2225
2207
|
}
|
|
2226
2208
|
get freezeStore() {
|
|
2227
2209
|
return this._freezeStore;
|
|
2228
2210
|
}
|
|
2211
|
+
/** Register new route handlers with Express (or another HTTP layer). */
|
|
2212
|
+
attachRouteRegistrar(registrar) {
|
|
2213
|
+
this.routeRegistrar = registrar;
|
|
2214
|
+
}
|
|
2215
|
+
/**
|
|
2216
|
+
* Rescan the pages directory for new routes and register any that were
|
|
2217
|
+
* added since dev-server startup (e.g. after AIditor Add Page).
|
|
2218
|
+
*/
|
|
2219
|
+
async refreshRoutes() {
|
|
2220
|
+
if (!this.rescanRoutes) {
|
|
2221
|
+
return this.listRoutes();
|
|
2222
|
+
}
|
|
2223
|
+
const added = await this.rescanRoutes();
|
|
2224
|
+
if (added.length > 0 && this.routeRegistrar) {
|
|
2225
|
+
this.routeRegistrar(added);
|
|
2226
|
+
getLogger().info(
|
|
2227
|
+
`[Routes] Registered ${added.length} new route(s): ${added.map((r) => r.fsRoute.rawRoute).join(", ")}`
|
|
2228
|
+
);
|
|
2229
|
+
}
|
|
2230
|
+
return this.listRoutes();
|
|
2231
|
+
}
|
|
2229
2232
|
/** List all page routes in the project. */
|
|
2230
2233
|
listRoutes() {
|
|
2231
2234
|
return this.routes.map((r) => ({
|
|
@@ -2435,6 +2438,7 @@ function mkRoute(route, vite, slowlyPhase, options, slowRenderCache, freezeStore
|
|
|
2435
2438
|
for (const [key, value] of urlObj.searchParams) {
|
|
2436
2439
|
query[key] = value;
|
|
2437
2440
|
}
|
|
2441
|
+
const cookies = parseCookies(req.headers.cookie);
|
|
2438
2442
|
const freezeId = query["_jay_freeze"];
|
|
2439
2443
|
if (freezeId && freezeStore) {
|
|
2440
2444
|
timing?.annotate("[FROZEN]");
|
|
@@ -2466,7 +2470,8 @@ function mkRoute(route, vite, slowlyPhase, options, slowRenderCache, freezeStore
|
|
|
2466
2470
|
res,
|
|
2467
2471
|
url,
|
|
2468
2472
|
timing,
|
|
2469
|
-
query
|
|
2473
|
+
query,
|
|
2474
|
+
cookies
|
|
2470
2475
|
);
|
|
2471
2476
|
} else {
|
|
2472
2477
|
const cachedEntry = await slowRenderCache.get(
|
|
@@ -2488,7 +2493,8 @@ function mkRoute(route, vite, slowlyPhase, options, slowRenderCache, freezeStore
|
|
|
2488
2493
|
res,
|
|
2489
2494
|
url,
|
|
2490
2495
|
timing,
|
|
2491
|
-
query
|
|
2496
|
+
query,
|
|
2497
|
+
cookies
|
|
2492
2498
|
);
|
|
2493
2499
|
} else {
|
|
2494
2500
|
await handlePreRenderRequest(
|
|
@@ -2505,7 +2511,8 @@ function mkRoute(route, vite, slowlyPhase, options, slowRenderCache, freezeStore
|
|
|
2505
2511
|
res,
|
|
2506
2512
|
url,
|
|
2507
2513
|
timing,
|
|
2508
|
-
query
|
|
2514
|
+
query,
|
|
2515
|
+
cookies
|
|
2509
2516
|
);
|
|
2510
2517
|
}
|
|
2511
2518
|
}
|
|
@@ -2518,7 +2525,7 @@ function mkRoute(route, vite, slowlyPhase, options, slowRenderCache, freezeStore
|
|
|
2518
2525
|
};
|
|
2519
2526
|
return { path: routePath, handler, fsRoute: route };
|
|
2520
2527
|
}
|
|
2521
|
-
async function handleCachedRequest(vite, route, options, cachedEntry, pageParams, pageProps, allPluginClientInits, allPluginsWithInit, projectInit, res, url, timing, query = {}) {
|
|
2528
|
+
async function handleCachedRequest(vite, route, options, cachedEntry, pageParams, pageProps, allPluginClientInits, allPluginsWithInit, projectInit, res, url, timing, query = {}, cookies = {}) {
|
|
2522
2529
|
const loadStart = Date.now();
|
|
2523
2530
|
const pagePartsResult = await loadPageParts(
|
|
2524
2531
|
vite,
|
|
@@ -2564,7 +2571,8 @@ async function handleCachedRequest(vite, route, options, cachedEntry, pageParams
|
|
|
2564
2571
|
forEachInstances,
|
|
2565
2572
|
headlessComps,
|
|
2566
2573
|
cachedEntry.slowViewState,
|
|
2567
|
-
query
|
|
2574
|
+
query,
|
|
2575
|
+
cookies
|
|
2568
2576
|
);
|
|
2569
2577
|
timing?.recordFastRender(Date.now() - fastStart);
|
|
2570
2578
|
if (renderedFast.kind !== "PhaseOutput") {
|
|
@@ -2572,17 +2580,27 @@ async function handleCachedRequest(vite, route, options, cachedEntry, pageParams
|
|
|
2572
2580
|
timing?.end();
|
|
2573
2581
|
return;
|
|
2574
2582
|
}
|
|
2583
|
+
if (renderedFast.responseHeaders) {
|
|
2584
|
+
for (const [key, value] of Object.entries(renderedFast.responseHeaders)) {
|
|
2585
|
+
res.setHeader(key, value);
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2575
2588
|
const fastViewState = renderedFast.rendered;
|
|
2576
2589
|
const fastCarryForward = renderedFast.carryForward;
|
|
2577
2590
|
const headTags = renderedFast.headTags ?? mergeHeadTags(cachedEntry.carryForward?.__slowHeadTags ?? []);
|
|
2591
|
+
const fullViewState = deepMergeViewStates(
|
|
2592
|
+
cachedEntry.slowViewState,
|
|
2593
|
+
fastViewState,
|
|
2594
|
+
clientTrackByMap || {}
|
|
2595
|
+
);
|
|
2578
2596
|
await sendResponse(
|
|
2579
2597
|
vite,
|
|
2580
2598
|
res,
|
|
2581
2599
|
url,
|
|
2582
|
-
|
|
2600
|
+
route.jayHtmlPath,
|
|
2583
2601
|
route.jayHtmlPath,
|
|
2584
2602
|
pageParts,
|
|
2585
|
-
|
|
2603
|
+
fullViewState,
|
|
2586
2604
|
fastCarryForward,
|
|
2587
2605
|
clientTrackByMap,
|
|
2588
2606
|
projectInit,
|
|
@@ -2592,11 +2610,11 @@ async function handleCachedRequest(vite, route, options, cachedEntry, pageParams
|
|
|
2592
2610
|
getRouteDir(route),
|
|
2593
2611
|
cachedEntry.slowViewState,
|
|
2594
2612
|
timing,
|
|
2595
|
-
|
|
2613
|
+
void 0,
|
|
2596
2614
|
headTags
|
|
2597
2615
|
);
|
|
2598
2616
|
}
|
|
2599
|
-
async function handlePreRenderRequest(vite, route, options, slowlyPhase, slowRenderCache, pageParams, pageProps, allPluginClientInits, allPluginsWithInit, projectInit, res, url, timing, query = {}) {
|
|
2617
|
+
async function handlePreRenderRequest(vite, route, options, slowlyPhase, slowRenderCache, pageParams, pageProps, allPluginClientInits, allPluginsWithInit, projectInit, res, url, timing, query = {}, cookies = {}) {
|
|
2600
2618
|
const loadStart = Date.now();
|
|
2601
2619
|
const initialPartsResult = await loadPageParts(
|
|
2602
2620
|
vite,
|
|
@@ -2681,10 +2699,11 @@ async function handlePreRenderRequest(vite, route, options, slowlyPhase, slowRen
|
|
|
2681
2699
|
res,
|
|
2682
2700
|
url,
|
|
2683
2701
|
timing,
|
|
2684
|
-
query
|
|
2702
|
+
query,
|
|
2703
|
+
cookies
|
|
2685
2704
|
);
|
|
2686
2705
|
}
|
|
2687
|
-
async function handleClientOnlyRequest(vite, route, options, slowlyPhase, pageParams, pageProps, allPluginClientInits, allPluginsWithInit, projectInit, res, url, timing, query = {}) {
|
|
2706
|
+
async function handleClientOnlyRequest(vite, route, options, slowlyPhase, pageParams, pageProps, allPluginClientInits, allPluginsWithInit, projectInit, res, url, timing, query = {}, cookies = {}) {
|
|
2688
2707
|
const loadStart = Date.now();
|
|
2689
2708
|
const pagePartsResult = await loadPageParts(
|
|
2690
2709
|
vite,
|
|
@@ -2746,7 +2765,8 @@ async function handleClientOnlyRequest(vite, route, options, slowlyPhase, pagePa
|
|
|
2746
2765
|
forEachInstances,
|
|
2747
2766
|
headlessInstanceComponents,
|
|
2748
2767
|
renderedSlowly.rendered,
|
|
2749
|
-
query
|
|
2768
|
+
query,
|
|
2769
|
+
cookies
|
|
2750
2770
|
);
|
|
2751
2771
|
timing?.recordFastRender(Date.now() - fastStart);
|
|
2752
2772
|
if (renderedFast.kind !== "PhaseOutput") {
|
|
@@ -2754,6 +2774,11 @@ async function handleClientOnlyRequest(vite, route, options, slowlyPhase, pagePa
|
|
|
2754
2774
|
timing?.end();
|
|
2755
2775
|
return;
|
|
2756
2776
|
}
|
|
2777
|
+
if (renderedFast.responseHeaders) {
|
|
2778
|
+
for (const [key, value] of Object.entries(renderedFast.responseHeaders)) {
|
|
2779
|
+
res.setHeader(key, value);
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2757
2782
|
const viewState = deepMergeViewStates(
|
|
2758
2783
|
renderedSlowly.rendered,
|
|
2759
2784
|
renderedFast.rendered,
|
|
@@ -2789,15 +2814,13 @@ async function handleClientOnlyRequest(vite, route, options, slowlyPhase, pagePa
|
|
|
2789
2814
|
async function sendResponse(vite, res, url, jayHtmlPath, sourceJayHtmlPath, pageParts, viewState, carryForward, clientTrackByMap, projectInit, pluginsForPage, options, routePattern, routeDir, slowViewState, timing, preLoadedContent, headTags) {
|
|
2790
2815
|
let pageHtml;
|
|
2791
2816
|
try {
|
|
2792
|
-
let jayHtmlContent = preLoadedContent ?? await fs__default.readFile(jayHtmlPath, "utf-8");
|
|
2793
|
-
const jayHtmlFilename = path__default.basename(jayHtmlPath);
|
|
2794
2817
|
const jayHtmlDir = path__default.dirname(jayHtmlPath);
|
|
2795
|
-
|
|
2796
|
-
jayHtmlContent = injectHeadfullFSTemplates(jayHtmlContent,
|
|
2818
|
+
let jayHtmlContent = preLoadedContent ?? await fs__default.readFile(jayHtmlPath, "utf-8");
|
|
2819
|
+
jayHtmlContent = injectHeadfullFSTemplates(jayHtmlContent, jayHtmlDir, JAY_IMPORT_RESOLVER);
|
|
2797
2820
|
pageHtml = await generateSSRPageHtml(
|
|
2798
2821
|
vite,
|
|
2799
2822
|
jayHtmlContent,
|
|
2800
|
-
|
|
2823
|
+
path__default.basename(jayHtmlPath),
|
|
2801
2824
|
jayHtmlDir,
|
|
2802
2825
|
viewState,
|
|
2803
2826
|
jayHtmlPath,
|
|
@@ -2816,8 +2839,7 @@ async function sendResponse(vite, res, url, jayHtmlPath, sourceJayHtmlPath, page
|
|
|
2816
2839
|
slowViewState,
|
|
2817
2840
|
routePattern
|
|
2818
2841
|
},
|
|
2819
|
-
|
|
2820
|
-
jayHtmlDir !== sourceDir ? sourceDir : void 0,
|
|
2842
|
+
void 0,
|
|
2821
2843
|
headTags
|
|
2822
2844
|
);
|
|
2823
2845
|
} catch (err) {
|
|
@@ -2902,37 +2924,21 @@ async function handleFrozenRequest(vite, route, options, freezeStore, slowRender
|
|
|
2902
2924
|
}
|
|
2903
2925
|
async function preRenderJayHtml(route, slowViewState, headlessContracts, headlessInstanceComponents, partKeys = []) {
|
|
2904
2926
|
const jayHtmlContent = await fs__default.readFile(route.jayHtmlPath, "utf-8");
|
|
2905
|
-
const contractPath = route.jayHtmlPath.replace(".jay-html", ".jay-contract");
|
|
2906
|
-
let contract;
|
|
2907
|
-
try {
|
|
2908
|
-
const contractContent = await fs__default.readFile(contractPath, "utf-8");
|
|
2909
|
-
const parseResult = parseContract(contractContent, path__default.basename(contractPath));
|
|
2910
|
-
if (parseResult.val) {
|
|
2911
|
-
contract = parseResult.val;
|
|
2912
|
-
} else if (parseResult.validations.length > 0) {
|
|
2913
|
-
getLogger().error(
|
|
2914
|
-
`[SlowRender] Contract parse error for ${contractPath}: ${parseResult.validations.join(", ")}`
|
|
2915
|
-
);
|
|
2916
|
-
return void 0;
|
|
2917
|
-
}
|
|
2918
|
-
} catch (error) {
|
|
2919
|
-
if (error.code !== "ENOENT") {
|
|
2920
|
-
getLogger().error(`[SlowRender] Error reading contract ${contractPath}: ${error}`);
|
|
2921
|
-
return void 0;
|
|
2922
|
-
}
|
|
2923
|
-
}
|
|
2924
|
-
const hasPageLevelSlowData = slowViewState && Object.keys(slowViewState).some((k) => !partKeys.includes(k));
|
|
2925
|
-
if (!contract && hasPageLevelSlowData) {
|
|
2926
|
-
getLogger().warn(
|
|
2927
|
-
`[SlowRender] Page ${route.jayHtmlPath} has slow ViewState but no contract. Without a contract, slow bindings cannot be resolved. Move data to withFastRender or add a .jay-contract file with phase annotations.`
|
|
2928
|
-
);
|
|
2929
|
-
}
|
|
2930
2927
|
const sourceDir = path__default.dirname(route.jayHtmlPath);
|
|
2931
2928
|
const jayHtmlWithTemplates = injectHeadfullFSTemplates(
|
|
2932
2929
|
jayHtmlContent,
|
|
2933
2930
|
sourceDir,
|
|
2934
2931
|
JAY_IMPORT_RESOLVER
|
|
2935
2932
|
);
|
|
2933
|
+
let contract;
|
|
2934
|
+
const contractPath = route.jayHtmlPath.replace(".jay-html", ".jay-contract");
|
|
2935
|
+
try {
|
|
2936
|
+
const contractContent = await fs__default.readFile(contractPath, "utf-8");
|
|
2937
|
+
const parseResult = parseContract(contractContent, path__default.basename(contractPath));
|
|
2938
|
+
if (parseResult.val)
|
|
2939
|
+
contract = parseResult.val;
|
|
2940
|
+
} catch {
|
|
2941
|
+
}
|
|
2936
2942
|
const result = slowRenderTransform({
|
|
2937
2943
|
jayHtmlContent: jayHtmlWithTemplates,
|
|
2938
2944
|
slowViewState,
|
|
@@ -2949,28 +2955,19 @@ async function preRenderJayHtml(route, slowViewState, headlessContracts, headles
|
|
|
2949
2955
|
}
|
|
2950
2956
|
return void 0;
|
|
2951
2957
|
}
|
|
2952
|
-
|
|
2958
|
+
const preRenderedJayHtml = result.val.preRenderedJayHtml;
|
|
2953
2959
|
let instancePhaseData;
|
|
2954
2960
|
let forEachInstances;
|
|
2955
2961
|
if (headlessInstanceComponents.length > 0) {
|
|
2956
|
-
const discoveryResult = discoverHeadlessInstances(preRenderedJayHtml);
|
|
2957
|
-
const htmlWithRefs = discoveryResult.preRenderedJayHtml;
|
|
2958
2962
|
const headlessContractNameSet = new Set(
|
|
2959
2963
|
headlessInstanceComponents.map((c2) => c2.contractName)
|
|
2960
2964
|
);
|
|
2961
|
-
|
|
2962
|
-
|
|
2965
|
+
const withCoords = assignCoordinatesToJayHtml(
|
|
2966
|
+
jayHtmlWithTemplates,
|
|
2967
|
+
headlessContractNameSet
|
|
2968
|
+
);
|
|
2969
|
+
const finalDiscovery = discoverHeadlessInstances(withCoords);
|
|
2963
2970
|
if (finalDiscovery.forEachInstances.length > 0) {
|
|
2964
|
-
const validationErrors = validateForEachInstances(
|
|
2965
|
-
finalDiscovery.forEachInstances,
|
|
2966
|
-
headlessInstanceComponents
|
|
2967
|
-
);
|
|
2968
|
-
if (validationErrors.length > 0) {
|
|
2969
|
-
getLogger().error(
|
|
2970
|
-
`[SlowRender] ForEach instance validation failed: ${validationErrors.join(", ")}`
|
|
2971
|
-
);
|
|
2972
|
-
return void 0;
|
|
2973
|
-
}
|
|
2974
2971
|
forEachInstances = finalDiscovery.forEachInstances;
|
|
2975
2972
|
}
|
|
2976
2973
|
if (finalDiscovery.instances.length > 0) {
|
|
@@ -2980,19 +2977,6 @@ async function preRenderJayHtml(route, slowViewState, headlessContracts, headles
|
|
|
2980
2977
|
);
|
|
2981
2978
|
if (slowResult) {
|
|
2982
2979
|
instancePhaseData = slowResult.instancePhaseData;
|
|
2983
|
-
const pass2Result = resolveHeadlessInstances(
|
|
2984
|
-
preRenderedJayHtml,
|
|
2985
|
-
slowResult.resolvedData,
|
|
2986
|
-
JAY_IMPORT_RESOLVER
|
|
2987
|
-
);
|
|
2988
|
-
if (pass2Result.val) {
|
|
2989
|
-
preRenderedJayHtml = pass2Result.val;
|
|
2990
|
-
}
|
|
2991
|
-
if (pass2Result.validations.length > 0) {
|
|
2992
|
-
getLogger().error(
|
|
2993
|
-
`[SlowRender] Instance resolution warnings for ${route.jayHtmlPath}: ${pass2Result.validations.join(", ")}`
|
|
2994
|
-
);
|
|
2995
|
-
}
|
|
2996
2980
|
}
|
|
2997
2981
|
if (!instancePhaseData) {
|
|
2998
2982
|
const componentByContractName = /* @__PURE__ */ new Map();
|
|
@@ -3000,7 +2984,7 @@ async function preRenderJayHtml(route, slowViewState, headlessContracts, headles
|
|
|
3000
2984
|
componentByContractName.set(comp.contractName, comp);
|
|
3001
2985
|
}
|
|
3002
2986
|
instancePhaseData = {
|
|
3003
|
-
discovered:
|
|
2987
|
+
discovered: finalDiscovery.instances.filter((i) => componentByContractName.has(i.contractName)).map((i) => {
|
|
3004
2988
|
const comp = componentByContractName.get(i.contractName);
|
|
3005
2989
|
const contractProps = comp.contract?.props ?? [];
|
|
3006
2990
|
const normalizedProps = {};
|
|
@@ -3105,13 +3089,44 @@ async function mkDevServer(rawOptions) {
|
|
|
3105
3089
|
pluginClientInits
|
|
3106
3090
|
)
|
|
3107
3091
|
);
|
|
3092
|
+
async function rescanAndMergeNewRoutes() {
|
|
3093
|
+
const projectRoutes2 = await initRoutes(options.pagesRootFolder);
|
|
3094
|
+
const filteredProjectRoutes2 = options.buildFolder ? projectRoutes2.filter((route) => !route.jayHtmlPath.startsWith(options.buildFolder)) : projectRoutes2;
|
|
3095
|
+
const pluginRoutes2 = await scanPluginRoutes(
|
|
3096
|
+
options.projectRootFolder,
|
|
3097
|
+
filteredProjectRoutes2
|
|
3098
|
+
);
|
|
3099
|
+
const scannedJayRoutes = [...filteredProjectRoutes2, ...pluginRoutes2];
|
|
3100
|
+
const existingRawRoutes = new Set(devServerRoutes.map((r) => r.fsRoute.rawRoute));
|
|
3101
|
+
const added = [];
|
|
3102
|
+
for (const jayRoute of scannedJayRoutes) {
|
|
3103
|
+
if (existingRawRoutes.has(jayRoute.rawRoute))
|
|
3104
|
+
continue;
|
|
3105
|
+
const devRoute = mkRoute(
|
|
3106
|
+
jayRoute,
|
|
3107
|
+
vite,
|
|
3108
|
+
slowlyPhase,
|
|
3109
|
+
options,
|
|
3110
|
+
slowRenderCache,
|
|
3111
|
+
freezeStore,
|
|
3112
|
+
projectInit,
|
|
3113
|
+
pluginsWithInit,
|
|
3114
|
+
pluginClientInits
|
|
3115
|
+
);
|
|
3116
|
+
devServerRoutes.push(devRoute);
|
|
3117
|
+
existingRawRoutes.add(jayRoute.rawRoute);
|
|
3118
|
+
added.push(devRoute);
|
|
3119
|
+
}
|
|
3120
|
+
return added;
|
|
3121
|
+
}
|
|
3108
3122
|
const service = new DevServerService(
|
|
3109
3123
|
devServerRoutes,
|
|
3110
3124
|
vite,
|
|
3111
3125
|
options.pagesRootFolder,
|
|
3112
3126
|
options.projectRootFolder,
|
|
3113
3127
|
options.jayRollupConfig,
|
|
3114
|
-
freezeStore
|
|
3128
|
+
freezeStore,
|
|
3129
|
+
rescanAndMergeNewRoutes
|
|
3115
3130
|
);
|
|
3116
3131
|
registerService(DEV_SERVER_SERVICE, service);
|
|
3117
3132
|
return {
|
|
@@ -3155,8 +3170,8 @@ function setupServiceHotReload(vite, lifecycleManager) {
|
|
|
3155
3170
|
});
|
|
3156
3171
|
}
|
|
3157
3172
|
function setupActionRouter(vite, buildFolder) {
|
|
3158
|
-
vite.middlewares.use(actionBodyParser({ buildFolder }));
|
|
3159
|
-
vite.middlewares.use(ACTION_ENDPOINT_BASE, createActionRouter());
|
|
3173
|
+
vite.middlewares.use(actionBodyParser({ buildFolder, registry: actionRegistry }));
|
|
3174
|
+
vite.middlewares.use(ACTION_ENDPOINT_BASE, createActionRouter({ registry: actionRegistry }));
|
|
3160
3175
|
getLogger().info(`[Actions] Action router mounted at ${ACTION_ENDPOINT_BASE}`);
|
|
3161
3176
|
}
|
|
3162
3177
|
function setupFreezeEndpoint(vite, freezeStore) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/dev-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,23 +23,23 @@
|
|
|
23
23
|
"test:watch": "vitest"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@jay-framework/compiler-jay-stack": "^0.
|
|
27
|
-
"@jay-framework/compiler-shared": "^0.
|
|
28
|
-
"@jay-framework/component": "^0.
|
|
29
|
-
"@jay-framework/fullstack-component": "^0.
|
|
30
|
-
"@jay-framework/logger": "^0.
|
|
31
|
-
"@jay-framework/runtime": "^0.
|
|
32
|
-
"@jay-framework/stack-client-runtime": "^0.
|
|
33
|
-
"@jay-framework/stack-route-scanner": "^0.
|
|
34
|
-
"@jay-framework/stack-server-runtime": "^0.
|
|
35
|
-
"@jay-framework/view-state-merge": "^0.
|
|
26
|
+
"@jay-framework/compiler-jay-stack": "^0.18.0",
|
|
27
|
+
"@jay-framework/compiler-shared": "^0.18.0",
|
|
28
|
+
"@jay-framework/component": "^0.18.0",
|
|
29
|
+
"@jay-framework/fullstack-component": "^0.18.0",
|
|
30
|
+
"@jay-framework/logger": "^0.18.0",
|
|
31
|
+
"@jay-framework/runtime": "^0.18.0",
|
|
32
|
+
"@jay-framework/stack-client-runtime": "^0.18.0",
|
|
33
|
+
"@jay-framework/stack-route-scanner": "^0.18.0",
|
|
34
|
+
"@jay-framework/stack-server-runtime": "^0.18.0",
|
|
35
|
+
"@jay-framework/view-state-merge": "^0.18.0",
|
|
36
36
|
"busboy": "^1.6.0",
|
|
37
37
|
"vite": "^5.0.11"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@jay-framework/dev-environment": "^0.
|
|
41
|
-
"@jay-framework/jay-cli": "^0.
|
|
42
|
-
"@jay-framework/stack-client-runtime": "^0.
|
|
40
|
+
"@jay-framework/dev-environment": "^0.18.0",
|
|
41
|
+
"@jay-framework/jay-cli": "^0.18.0",
|
|
42
|
+
"@jay-framework/stack-client-runtime": "^0.18.0",
|
|
43
43
|
"@playwright/test": "^1.58.2",
|
|
44
44
|
"@types/busboy": "^1.5.4",
|
|
45
45
|
"@types/express": "^5.0.2",
|