eclipsa 0.1.4 → 0.1.6
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/{action-CgM3EJUS.mjs → action-DqgkV3zb.mjs} +1584 -996
- package/action-DqgkV3zb.mjs.map +1 -0
- package/{client-COjBNTyt.mjs → client-DKPmN-wJ.mjs} +126 -40
- package/client-DKPmN-wJ.mjs.map +1 -0
- package/{component-D_nEtZ69.d.mts → component-yvTtnI00.d.mts} +2 -2
- package/core/client/mod.d.mts +2 -2
- package/core/client/mod.mjs +3 -3
- package/core/dev-client/mod.d.mts +1 -1
- package/core/dev-client/mod.mjs +10 -5
- package/core/dev-client/mod.mjs.map +1 -1
- package/core/internal.d.mts +2 -2
- package/core/internal.mjs +2 -2
- package/core/prod-client/mod.d.mts +3 -3
- package/core/prod-client/mod.mjs +4 -4
- package/{internal-Csbm0Qnv.d.mts → internal-CHYAJznU.d.mts} +116 -72
- package/jsx/jsx-dev-runtime.d.mts +8 -2
- package/jsx/jsx-dev-runtime.mjs +2 -2
- package/jsx/jsx-runtime.d.mts +1 -1
- package/jsx/mod.d.mts +1 -1
- package/jsx/mod.mjs +1 -1
- package/{jsx-dev-runtime-CY60yQJY.mjs → jsx-dev-runtime-DpbWQ4Q0.mjs} +8 -3
- package/jsx-dev-runtime-DpbWQ4Q0.mjs.map +1 -0
- package/{mod-DLb8ple9.d.mts → mod-aLmFvMYF.d.mts} +4 -4
- package/mod.d.mts +20 -38
- package/mod.mjs +19 -145
- package/mod.mjs.map +1 -1
- package/package.json +6 -2
- package/{signal-B7AfIKrr.d.mts → signal-CosyYdtA.d.mts} +1 -1
- package/{signal-CJtquEfo.mjs → signal-DBzloBrN.mjs} +2 -2
- package/{signal-CJtquEfo.mjs.map → signal-DBzloBrN.mjs.map} +1 -1
- package/ssr-CRg57Wn2.mjs +157 -0
- package/ssr-CRg57Wn2.mjs.map +1 -0
- package/ssr-D8F-DtCv.d.mts +37 -0
- package/{types-BCEY9lGp.d.mts → types-Cu9gFlEY.d.mts} +6 -2
- package/{types-DKpefD_u.d.mts → types-DDeNM8UH.d.mts} +1 -1
- package/vite/build/runtime.d.mts +4 -0
- package/vite/build/runtime.mjs +4 -0
- package/vite/mod.mjs +272 -50
- package/vite/mod.mjs.map +1 -1
- package/web-utils/mod.d.mts +1 -1
- package/web-utils/mod.mjs +2 -2
- package/action-CgM3EJUS.mjs.map +0 -1
- package/client-COjBNTyt.mjs.map +0 -1
- package/jsx-dev-runtime-CY60yQJY.mjs.map +0 -1
- /package/{jsx-runtime-BFDPoxFn.d.mts → jsx-runtime-QIK6ADiK.d.mts} +0 -0
|
@@ -246,6 +246,10 @@ type NamespacedIntrinsicElementProps = {
|
|
|
246
246
|
[name: string]: AttributeValue | undefined;
|
|
247
247
|
};
|
|
248
248
|
declare namespace JSX {
|
|
249
|
+
interface SSRRaw {
|
|
250
|
+
__e_ssr_raw: true;
|
|
251
|
+
value: string;
|
|
252
|
+
}
|
|
249
253
|
interface SSRTemplate {
|
|
250
254
|
__e_ssr_template: true;
|
|
251
255
|
strings: readonly string[];
|
|
@@ -259,7 +263,7 @@ declare namespace JSX {
|
|
|
259
263
|
key?: string | number | symbol | null;
|
|
260
264
|
isStatic: boolean;
|
|
261
265
|
metadata?: Metadata;
|
|
262
|
-
} | SSRTemplate | string | number | undefined | null | boolean | ((() => Element) & {
|
|
266
|
+
} | SSRRaw | SSRTemplate | string | number | undefined | null | boolean | ((() => Element) & {
|
|
263
267
|
key?: string | number | symbol;
|
|
264
268
|
});
|
|
265
269
|
interface Metadata {
|
|
@@ -279,4 +283,4 @@ declare namespace JSX {
|
|
|
279
283
|
}
|
|
280
284
|
//#endregion
|
|
281
285
|
export { JSX as i, DelegatedEvent as n, EventHandler as r, BindTarget as t };
|
|
282
|
-
//# sourceMappingURL=types-
|
|
286
|
+
//# sourceMappingURL=types-Cu9gFlEY.d.mts.map
|
|
@@ -8,4 +8,4 @@ type Insertable = string | number | boolean | undefined | null | Node | Insertab
|
|
|
8
8
|
type ClientElementLike = Insertable | Insertable[];
|
|
9
9
|
//#endregion
|
|
10
10
|
export { Insertable as n, ClientElementLike as t };
|
|
11
|
-
//# sourceMappingURL=types-
|
|
11
|
+
//# sourceMappingURL=types-DDeNM8UH.d.mts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { $t as APP_HOOKS_ELEMENT_ID, An as resolveReroute, At as primeActionState, Cn as createRequestFetch, Dn as markPublicError, Dt as getActionFormSubmissionId, Fn as withServerRequestContext, Gn as escapeInlineScriptText, Kn as escapeJSONScriptText, Mn as serializePublicValue, Nn as toPublicError, On as registerClientHooks, Ot as getNormalizedActionInput, Pt as primeLocationState, Q as hasLoader, Sn as attachRequestFetch, Tt as executeAction, Vt as RESUME_FINAL_STATE_ELEMENT_ID, Wn as deserializeValue, Xt as composeRouteMetadata, Z as executeLoader, Zt as renderRouteMetadataHead, _n as ServerHooksModule, an as BaseAppVariables, at as ACTION_CONTENT_TYPE, en as AppContext, fn as PublicError, gn as ResolvedHooks, hn as Reroute, it as resolvePendingLoaders, jn as runHandleError, kt as hasAction, ln as HandleFetch, mn as RequestFetch, nn as AppHooksManifest, nt as primeLoaderState, on as Handle, rn as AppHooksModule, sn as HandleError, wn as deserializePublicValue, xn as WithAppEnv, yn as Transport } from "../../internal-CHYAJznU.mjs";
|
|
2
|
+
import { Fragment, jsxDEV } from "../../jsx/jsx-dev-runtime.mjs";
|
|
3
|
+
import { a as renderSSR, c as serializeResumePayload, i as getStreamingResumeBootstrapScriptContent, o as renderSSRAsync, s as renderSSRStream } from "../../ssr-D8F-DtCv.mjs";
|
|
4
|
+
export { ACTION_CONTENT_TYPE, APP_HOOKS_ELEMENT_ID, type AppContext, type AppHooksManifest, type AppHooksModule, type BaseAppVariables, Fragment, type Handle, type HandleError, type HandleFetch, type PublicError, RESUME_FINAL_STATE_ELEMENT_ID, type RequestFetch, type Reroute, type ResolvedHooks, type ServerHooksModule, type Transport, type WithAppEnv, attachRequestFetch, composeRouteMetadata, createRequestFetch, deserializePublicValue, deserializeValue, escapeInlineScriptText, escapeJSONScriptText, executeAction, executeLoader, getActionFormSubmissionId, getNormalizedActionInput, getStreamingResumeBootstrapScriptContent, hasAction, hasLoader, jsxDEV, markPublicError, primeActionState, primeLoaderState, primeLocationState, registerClientHooks, renderRouteMetadataHead, renderSSR, renderSSRAsync, renderSSRStream, resolvePendingLoaders, resolveReroute, runHandleError, serializePublicValue, serializeResumePayload, toPublicError, withServerRequestContext };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Fn as deserializePublicValue, Hn as runHandleError, Jn as escapeInlineScriptText, Kn as withServerRequestContext, L as primeLocationState, Mn as APP_HOOKS_ELEMENT_ID, Nn as attachRequestFetch, Pn as createRequestFetch, Rn as markPublicError, St as RESUME_FINAL_STATE_ELEMENT_ID, Un as serializePublicValue, Vn as resolveReroute, Wn as toPublicError, Yn as escapeJSONScriptText, bn as renderRouteMetadataHead, c as getActionFormSubmissionId, cn as resolvePendingLoaders, d as primeActionState, en as executeLoader, l as getNormalizedActionInput, o as executeAction, on as primeLoaderState, qn as deserializeValue, t as ACTION_CONTENT_TYPE, tn as hasLoader, u as hasAction, yn as composeRouteMetadata, zn as registerClientHooks } from "../../action-DqgkV3zb.mjs";
|
|
2
|
+
import { a as jsxDEV, t as Fragment } from "../../jsx-dev-runtime-DpbWQ4Q0.mjs";
|
|
3
|
+
import { a as serializeResumePayload, i as renderSSRStream, n as renderSSR, r as renderSSRAsync, t as getStreamingResumeBootstrapScriptContent } from "../../ssr-CRg57Wn2.mjs";
|
|
4
|
+
export { ACTION_CONTENT_TYPE, APP_HOOKS_ELEMENT_ID, Fragment, RESUME_FINAL_STATE_ELEMENT_ID, attachRequestFetch, composeRouteMetadata, createRequestFetch, deserializePublicValue, deserializeValue, escapeInlineScriptText, escapeJSONScriptText, executeAction, executeLoader, getActionFormSubmissionId, getNormalizedActionInput, getStreamingResumeBootstrapScriptContent, hasAction, hasLoader, jsxDEV, markPublicError, primeActionState, primeLoaderState, primeLocationState, registerClientHooks, renderRouteMetadataHead, renderSSR, renderSSRAsync, renderSSRStream, resolvePendingLoaders, resolveReroute, runHandleError, serializePublicValue, serializeResumePayload, toPublicError, withServerRequestContext };
|
package/vite/mod.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Hn as runHandleError, Kn as withServerRequestContext, L as primeLocationState, Mn as APP_HOOKS_ELEMENT_ID, Nn as attachRequestFetch, Pn as createRequestFetch, Rn as markPublicError, Vn as resolveReroute, _n as ROUTE_RPC_URL_HEADER, bn as renderRouteMetadataHead, fn as ROUTE_MANIFEST_ELEMENT_ID, hn as ROUTE_PREFLIGHT_REQUEST_HEADER, ln as ROUTE_DATA_ENDPOINT, mn as ROUTE_PREFLIGHT_ENDPOINT, un as ROUTE_DATA_REQUEST_HEADER, yn as composeRouteMetadata } from "../action-DqgkV3zb.mjs";
|
|
2
|
+
import { a as jsxDEV, t as Fragment } from "../jsx-dev-runtime-DpbWQ4Q0.mjs";
|
|
3
3
|
import { t as RESUME_HMR_EVENT } from "../resume-hmr-qTpLc5o-.mjs";
|
|
4
4
|
import { createServerModuleRunner, transformWithOxc } from "vite";
|
|
5
5
|
import { Hono } from "hono";
|
|
@@ -10,8 +10,8 @@ import path from "node:path";
|
|
|
10
10
|
import ts from "typescript";
|
|
11
11
|
import { runRustAnalyzeCompiler, runRustCompiler } from "@eclipsa/optimizer";
|
|
12
12
|
import { cwd } from "node:process";
|
|
13
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
13
14
|
import { toSSG } from "hono/ssg";
|
|
14
|
-
import { pathToFileURL } from "node:url";
|
|
15
15
|
//#region vite/utils/routing.ts
|
|
16
16
|
const normalizeRoutePath = (pathname) => {
|
|
17
17
|
const normalizedPath = pathname.trim() || "/";
|
|
@@ -386,15 +386,19 @@ const annotateOptimizedRootComponents = (source, id) => {
|
|
|
386
386
|
const insertions = [];
|
|
387
387
|
const visit = (node) => {
|
|
388
388
|
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "__eclipsaComponent") {
|
|
389
|
+
if (node.arguments.length >= 5) return;
|
|
389
390
|
const lastArgument = node.arguments.at(-1);
|
|
390
|
-
insertions.push(
|
|
391
|
+
insertions.push({
|
|
392
|
+
code: node.arguments.length >= 4 ? ", { optimizedRoot: true }" : ", undefined, { optimizedRoot: true }",
|
|
393
|
+
index: lastArgument ? lastArgument.end : node.expression.end + 1
|
|
394
|
+
});
|
|
391
395
|
}
|
|
392
396
|
ts.forEachChild(node, visit);
|
|
393
397
|
};
|
|
394
398
|
visit(sourceFile);
|
|
395
399
|
if (insertions.length === 0) return source;
|
|
396
400
|
let nextSource = source;
|
|
397
|
-
for (const
|
|
401
|
+
for (const insertion of [...insertions].sort((left, right) => right.index - left.index)) nextSource = nextSource.slice(0, insertion.index) + insertion.code + nextSource.slice(insertion.index);
|
|
398
402
|
return nextSource;
|
|
399
403
|
};
|
|
400
404
|
const analyzeModule = async (source, id = "analyze-input.tsx") => {
|
|
@@ -776,13 +780,51 @@ const collectAppSymbols = async (root) => {
|
|
|
776
780
|
}
|
|
777
781
|
return [...symbols.values()];
|
|
778
782
|
};
|
|
783
|
+
const collectReachableAnalyzableFiles = async (entryFiles) => {
|
|
784
|
+
const pending = [...entryFiles];
|
|
785
|
+
const visited = /* @__PURE__ */ new Set();
|
|
786
|
+
const reachable = /* @__PURE__ */ new Set();
|
|
787
|
+
const entryFileSet = new Set(entryFiles.map((filePath) => stripQuery(filePath)));
|
|
788
|
+
while (pending.length > 0) {
|
|
789
|
+
const next = pending.pop();
|
|
790
|
+
if (!next) continue;
|
|
791
|
+
const filePath = stripQuery(next);
|
|
792
|
+
if (visited.has(filePath) || !isAnalyzableSourceFile(filePath)) continue;
|
|
793
|
+
visited.add(filePath);
|
|
794
|
+
let source;
|
|
795
|
+
try {
|
|
796
|
+
source = await fs.readFile(filePath, "utf8");
|
|
797
|
+
} catch (error) {
|
|
798
|
+
const code = error?.code;
|
|
799
|
+
if (entryFileSet.has(filePath) && code !== "ENOENT" && code !== "ENOTDIR") throw error;
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
802
|
+
try {
|
|
803
|
+
await loadAnalyzedModule(filePath, source);
|
|
804
|
+
} catch (error) {
|
|
805
|
+
if (entryFileSet.has(filePath)) throw error;
|
|
806
|
+
continue;
|
|
807
|
+
}
|
|
808
|
+
reachable.add(filePath);
|
|
809
|
+
const imports = ts.preProcessFile(source, true, true).importedFiles;
|
|
810
|
+
for (const imported of imports) {
|
|
811
|
+
const resolvedFilePath = resolveImportedModule(imported.fileName, filePath);
|
|
812
|
+
if (!resolvedFilePath || !isAnalyzableSourceFile(resolvedFilePath)) continue;
|
|
813
|
+
pending.push(resolvedFilePath);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
return [...reachable];
|
|
817
|
+
};
|
|
779
818
|
const collectAppActions = async (root) => {
|
|
780
819
|
const appDir = path$1.join(root, "app");
|
|
781
820
|
const files = await fg(path$1.join(appDir, "**/*.{ts,tsx}").replaceAll("\\", "/"));
|
|
782
821
|
const result = [];
|
|
783
822
|
for (const filePath of files) {
|
|
784
823
|
const analyzed = await loadAnalyzedModule(filePath);
|
|
785
|
-
result.push(...analyzed.actions.values())
|
|
824
|
+
result.push(...[...analyzed.actions.values()].map((action) => ({
|
|
825
|
+
filePath,
|
|
826
|
+
id: action.id
|
|
827
|
+
})));
|
|
786
828
|
}
|
|
787
829
|
return result;
|
|
788
830
|
};
|
|
@@ -792,7 +834,10 @@ const collectAppLoaders = async (root) => {
|
|
|
792
834
|
const result = [];
|
|
793
835
|
for (const filePath of files) {
|
|
794
836
|
const analyzed = await loadAnalyzedModule(filePath);
|
|
795
|
-
result.push(...analyzed.loaders.values())
|
|
837
|
+
result.push(...[...analyzed.loaders.values()].map((loader) => ({
|
|
838
|
+
filePath,
|
|
839
|
+
id: loader.id
|
|
840
|
+
})));
|
|
796
841
|
}
|
|
797
842
|
return result;
|
|
798
843
|
};
|
|
@@ -831,7 +876,7 @@ const shouldInvalidateDevApp = (root, filePath, event) => {
|
|
|
831
876
|
const RESUME_PAYLOAD_PLACEHOLDER = "__ECLIPSA_RESUME_PAYLOAD__";
|
|
832
877
|
const ROUTE_MANIFEST_PLACEHOLDER = "__ECLIPSA_ROUTE_MANIFEST__";
|
|
833
878
|
const APP_HOOKS_PLACEHOLDER = "__ECLIPSA_APP_HOOKS__";
|
|
834
|
-
const replaceHeadPlaceholder = (html, placeholder, value) => html.
|
|
879
|
+
const replaceHeadPlaceholder = (html, placeholder, value) => html.replaceAll(placeholder, value);
|
|
835
880
|
const splitHtmlForStreaming = (html) => {
|
|
836
881
|
const bodyCloseIndex = html.lastIndexOf("</body>");
|
|
837
882
|
if (bodyCloseIndex >= 0) return {
|
|
@@ -848,6 +893,37 @@ const splitHtmlForStreaming = (html) => {
|
|
|
848
893
|
suffix: ""
|
|
849
894
|
};
|
|
850
895
|
};
|
|
896
|
+
const toIdsByFilePath$1 = (entries) => {
|
|
897
|
+
const idsByFilePath = /* @__PURE__ */ new Map();
|
|
898
|
+
for (const entry of entries) {
|
|
899
|
+
const existing = idsByFilePath.get(entry.filePath);
|
|
900
|
+
if (existing) {
|
|
901
|
+
existing.push(entry.id);
|
|
902
|
+
continue;
|
|
903
|
+
}
|
|
904
|
+
idsByFilePath.set(entry.filePath, [entry.id]);
|
|
905
|
+
}
|
|
906
|
+
return idsByFilePath;
|
|
907
|
+
};
|
|
908
|
+
const getRouteReachableEntryFiles$1 = (route) => [
|
|
909
|
+
route.error?.filePath,
|
|
910
|
+
...route.layouts.map((layout) => layout.filePath),
|
|
911
|
+
route.loading?.filePath,
|
|
912
|
+
route.notFound?.filePath,
|
|
913
|
+
route.page?.filePath
|
|
914
|
+
].filter((filePath) => typeof filePath === "string");
|
|
915
|
+
const createRouteServerAccessEntries$1 = async (routes, actions, loaders) => {
|
|
916
|
+
const actionIdsByFilePath = toIdsByFilePath$1(actions);
|
|
917
|
+
const loaderIdsByFilePath = toIdsByFilePath$1(loaders);
|
|
918
|
+
return await Promise.all(routes.map(async (route) => {
|
|
919
|
+
const reachableFiles = await collectReachableAnalyzableFiles(getRouteReachableEntryFiles$1(route));
|
|
920
|
+
return {
|
|
921
|
+
actionIds: new Set(reachableFiles.flatMap((filePath) => actionIdsByFilePath.get(filePath) ?? [])),
|
|
922
|
+
loaderIds: new Set(reachableFiles.flatMap((filePath) => loaderIdsByFilePath.get(filePath) ?? [])),
|
|
923
|
+
route
|
|
924
|
+
};
|
|
925
|
+
}));
|
|
926
|
+
};
|
|
851
927
|
const ROUTE_SLOT_ROUTE_KEY = Symbol.for("eclipsa.route-slot-route");
|
|
852
928
|
const createRouteSlot = (route, startLayoutIndex) => {
|
|
853
929
|
const slot = {
|
|
@@ -983,6 +1059,8 @@ const createDevApp = async (init) => {
|
|
|
983
1059
|
const allSymbols = await deps.collectAppSymbols(init.resolvedConfig.root);
|
|
984
1060
|
const actionModules = new Map(actions.map((action) => [action.id, action.filePath]));
|
|
985
1061
|
const loaderModules = new Map(loaders.map((loader) => [loader.id, loader.filePath]));
|
|
1062
|
+
const routeServerAccessEntries = await createRouteServerAccessEntries$1(routes, actions, loaders);
|
|
1063
|
+
const routeServerAccessByRoute = new Map(routeServerAccessEntries.map((entry) => [entry.route, entry]));
|
|
986
1064
|
const symbolUrls = Object.fromEntries(allSymbols.map((symbol) => [symbol.id, deps.createDevSymbolUrl(init.resolvedConfig.root, symbol.filePath, symbol.id)]));
|
|
987
1065
|
const routeManifest = createRouteManifest(routes, (entry) => deps.createDevModuleUrl(init.resolvedConfig.root, entry));
|
|
988
1066
|
const appHooksPath = path$1.join(init.resolvedConfig.root, "app/+hooks.ts");
|
|
@@ -996,6 +1074,32 @@ const createDevApp = async (init) => {
|
|
|
996
1074
|
return c;
|
|
997
1075
|
};
|
|
998
1076
|
const reroutePathname = (request, pathname, baseUrl) => normalizeRoutePath(resolveReroute(appHooks.reroute, request, pathname, baseUrl));
|
|
1077
|
+
const getRouteServerAccess = (route) => routeServerAccessByRoute.get(route) ?? {
|
|
1078
|
+
actionIds: /* @__PURE__ */ new Set(),
|
|
1079
|
+
loaderIds: /* @__PURE__ */ new Set(),
|
|
1080
|
+
route
|
|
1081
|
+
};
|
|
1082
|
+
const resolveRouteForCurrentUrl = (request, currentUrl) => {
|
|
1083
|
+
const resolvedPathname = reroutePathname(request, normalizeRoutePath(currentUrl.pathname), currentUrl.href);
|
|
1084
|
+
const match = matchRoute(routes, resolvedPathname);
|
|
1085
|
+
if (match?.route.page) return match;
|
|
1086
|
+
const fallback = findSpecialRoute(routes, resolvedPathname, "notFound");
|
|
1087
|
+
if (fallback?.route.notFound) return fallback;
|
|
1088
|
+
return null;
|
|
1089
|
+
};
|
|
1090
|
+
const getRpcCurrentRoute = (requestContext) => {
|
|
1091
|
+
const requestUrl = getRequestUrl(requestContext.req.raw);
|
|
1092
|
+
const routeUrlHeader = requestContext.req.header(ROUTE_RPC_URL_HEADER);
|
|
1093
|
+
if (!routeUrlHeader) return null;
|
|
1094
|
+
let currentUrl;
|
|
1095
|
+
try {
|
|
1096
|
+
currentUrl = new URL(routeUrlHeader, requestUrl);
|
|
1097
|
+
} catch {
|
|
1098
|
+
return null;
|
|
1099
|
+
}
|
|
1100
|
+
if (currentUrl.origin !== requestUrl.origin) return null;
|
|
1101
|
+
return resolveRouteForCurrentUrl(requestContext.req.raw, currentUrl);
|
|
1102
|
+
};
|
|
999
1103
|
const resolveRequest = async (c, handler) => {
|
|
1000
1104
|
const requestContext = prepareRequestContext(c);
|
|
1001
1105
|
const execute = (nextContext = requestContext) => withServerRequestContext(nextContext, {
|
|
@@ -1063,7 +1167,7 @@ const createDevApp = async (init) => {
|
|
|
1063
1167
|
params,
|
|
1064
1168
|
url: getRequestUrl(c.req.raw)
|
|
1065
1169
|
});
|
|
1066
|
-
const document = SSRRoot
|
|
1170
|
+
const document = jsxDEV(SSRRoot, {
|
|
1067
1171
|
children: createRouteElement(pathname, params, Page, Layouts, options?.routeError),
|
|
1068
1172
|
head: {
|
|
1069
1173
|
type: Fragment,
|
|
@@ -1116,7 +1220,7 @@ const createDevApp = async (init) => {
|
|
|
1116
1220
|
}
|
|
1117
1221
|
] }
|
|
1118
1222
|
}
|
|
1119
|
-
});
|
|
1223
|
+
}, null, false, {});
|
|
1120
1224
|
applyRequestParams(c, params);
|
|
1121
1225
|
const { html, payload, chunks } = await renderSSRStream(() => document, {
|
|
1122
1226
|
prepare(container) {
|
|
@@ -1286,19 +1390,25 @@ const createDevApp = async (init) => {
|
|
|
1286
1390
|
const { executeAction, hasAction } = await init.runner.import("eclipsa");
|
|
1287
1391
|
const id = requestContext.req.param("id");
|
|
1288
1392
|
if (!id) return requestContext.text("Not Found", 404);
|
|
1393
|
+
const routeMatch = getRpcCurrentRoute(requestContext);
|
|
1394
|
+
if (!routeMatch) return requestContext.text("Bad Request", 400);
|
|
1395
|
+
if (!getRouteServerAccess(routeMatch.route).actionIds.has(id)) return requestContext.text("Not Found", 404);
|
|
1289
1396
|
const modulePath = actionModules.get(id);
|
|
1290
1397
|
if (!modulePath) return requestContext.text("Not Found", 404);
|
|
1291
1398
|
if (!hasAction(id)) await init.runner.import(modulePath);
|
|
1292
|
-
return executeAction(id, requestContext);
|
|
1399
|
+
return composeRouteMiddlewares(routeMatch.route, requestContext, routeMatch.params, async () => executeAction(id, requestContext));
|
|
1293
1400
|
}));
|
|
1294
1401
|
app.get("/__eclipsa/loader/:id", async (c) => resolveRequest(c, async (requestContext) => {
|
|
1295
1402
|
const { executeLoader, hasLoader } = await init.runner.import("eclipsa");
|
|
1296
1403
|
const id = requestContext.req.param("id");
|
|
1297
1404
|
if (!id) return requestContext.text("Not Found", 404);
|
|
1405
|
+
const routeMatch = getRpcCurrentRoute(requestContext);
|
|
1406
|
+
if (!routeMatch) return requestContext.text("Bad Request", 400);
|
|
1407
|
+
if (!getRouteServerAccess(routeMatch.route).loaderIds.has(id)) return requestContext.text("Not Found", 404);
|
|
1298
1408
|
const modulePath = loaderModules.get(id);
|
|
1299
1409
|
if (!modulePath) return requestContext.text("Not Found", 404);
|
|
1300
1410
|
if (!hasLoader(id)) await init.runner.import(modulePath);
|
|
1301
|
-
return executeLoader(id, requestContext);
|
|
1411
|
+
return composeRouteMiddlewares(routeMatch.route, requestContext, routeMatch.params, async () => executeLoader(id, requestContext));
|
|
1302
1412
|
}));
|
|
1303
1413
|
app.get(ROUTE_PREFLIGHT_ENDPOINT, async (c) => resolveRequest(c, async (requestContext) => {
|
|
1304
1414
|
const href = requestContext.req.query("href");
|
|
@@ -1331,6 +1441,7 @@ const createDevApp = async (init) => {
|
|
|
1331
1441
|
const { ACTION_CONTENT_TYPE, deserializePublicValue, executeAction, getNormalizedActionInput, getActionFormSubmissionId, hasAction, primeActionState } = await init.runner.import("eclipsa");
|
|
1332
1442
|
const actionId = await getActionFormSubmissionId(requestContext);
|
|
1333
1443
|
if (!actionId) return match.route.server ? invokeRouteServer(match.route.server.filePath, requestContext, match.params) : renderMatchedPage(match, requestContext);
|
|
1444
|
+
if (!getRouteServerAccess(match.route).actionIds.has(actionId)) return requestContext.text("Not Found", 404);
|
|
1334
1445
|
const modulePath = actionModules.get(actionId);
|
|
1335
1446
|
if (!modulePath) return requestContext.text("Not Found", 404);
|
|
1336
1447
|
if (!hasAction(actionId)) await init.runner.import(modulePath);
|
|
@@ -1765,18 +1876,49 @@ const createSerializedRoutes = (routes) => JSON.stringify(routes.map((route) =>
|
|
|
1765
1876
|
segments: route.segments,
|
|
1766
1877
|
server: route.server ? createBuildServerModuleUrl(route.server) : null
|
|
1767
1878
|
})));
|
|
1879
|
+
const toIdsByFilePath = (entries) => {
|
|
1880
|
+
const idsByFilePath = /* @__PURE__ */ new Map();
|
|
1881
|
+
for (const entry of entries) {
|
|
1882
|
+
const existing = idsByFilePath.get(entry.filePath);
|
|
1883
|
+
if (existing) {
|
|
1884
|
+
existing.push(entry.id);
|
|
1885
|
+
continue;
|
|
1886
|
+
}
|
|
1887
|
+
idsByFilePath.set(entry.filePath, [entry.id]);
|
|
1888
|
+
}
|
|
1889
|
+
return idsByFilePath;
|
|
1890
|
+
};
|
|
1891
|
+
const getRouteReachableEntryFiles = (route) => [
|
|
1892
|
+
route.error?.filePath,
|
|
1893
|
+
...route.layouts.map((layout) => layout.filePath),
|
|
1894
|
+
route.loading?.filePath,
|
|
1895
|
+
route.notFound?.filePath,
|
|
1896
|
+
route.page?.filePath
|
|
1897
|
+
].filter((filePath) => typeof filePath === "string");
|
|
1898
|
+
const createRouteServerAccessEntries = async (routes, actions, loaders) => {
|
|
1899
|
+
const actionIdsByFilePath = toIdsByFilePath(actions);
|
|
1900
|
+
const loaderIdsByFilePath = toIdsByFilePath(loaders);
|
|
1901
|
+
return await Promise.all(routes.map(async (route) => {
|
|
1902
|
+
const reachableFiles = await collectReachableAnalyzableFiles(getRouteReachableEntryFiles(route));
|
|
1903
|
+
return {
|
|
1904
|
+
actionIds: reachableFiles.flatMap((filePath) => actionIdsByFilePath.get(filePath) ?? []),
|
|
1905
|
+
loaderIds: reachableFiles.flatMap((filePath) => loaderIdsByFilePath.get(filePath) ?? [])
|
|
1906
|
+
};
|
|
1907
|
+
}));
|
|
1908
|
+
};
|
|
1768
1909
|
const createActionTable = (actions) => actions.map((action) => ` ${JSON.stringify(action.id)}: ${JSON.stringify(createBuildServerActionUrl(action.id))},`).join("\n");
|
|
1769
1910
|
const createLoaderTable = (loaders) => loaders.map((loader) => ` ${JSON.stringify(loader.id)}: ${JSON.stringify(createBuildServerLoaderUrl(loader.id))},`).join("\n");
|
|
1770
1911
|
const createPageRouteEntries = (routes) => routes.flatMap((route, routeIndex) => route.page ? toHonoRoutePaths(route.segments).map((honoPath) => ({
|
|
1771
1912
|
path: honoPath,
|
|
1772
1913
|
routeIndex
|
|
1773
1914
|
})) : []);
|
|
1774
|
-
const renderAppModule = (actions, appHooksClientUrl, appHooksServerUrl, loaders, routes, routeManifest, serverHooksUrl, symbolUrls, stylesheetUrls, chunkCacheUrls) => {
|
|
1915
|
+
const renderAppModule = (actions, appHooksClientUrl, appHooksServerUrl, loaders, routes, routeServerAccessEntries, routeManifest, serverHooksUrl, symbolUrls, stylesheetUrls, chunkCacheUrls) => {
|
|
1775
1916
|
const serializedRoutes = createSerializedRoutes(routes);
|
|
1776
1917
|
const serializedPageRouteEntries = JSON.stringify(createPageRouteEntries(routes));
|
|
1777
1918
|
const actionTable = createActionTable(actions);
|
|
1778
1919
|
const loaderTable = createLoaderTable(loaders);
|
|
1779
1920
|
const serializedAppHooksManifest = JSON.stringify({ client: appHooksClientUrl });
|
|
1921
|
+
const serializedRouteServerAccessEntries = JSON.stringify(routeServerAccessEntries);
|
|
1780
1922
|
const serializedAppHooksServerUrl = JSON.stringify(appHooksServerUrl);
|
|
1781
1923
|
const serializedSymbolUrls = JSON.stringify(symbolUrls);
|
|
1782
1924
|
return `import userApp from "./entries/server_entry.mjs";
|
|
@@ -1791,6 +1933,7 @@ const loaders = {
|
|
|
1791
1933
|
${loaderTable}
|
|
1792
1934
|
};
|
|
1793
1935
|
const routes = ${serializedRoutes};
|
|
1936
|
+
const routeServerAccessEntries = ${serializedRouteServerAccessEntries};
|
|
1794
1937
|
const pageRouteEntries = ${serializedPageRouteEntries};
|
|
1795
1938
|
const appHooksManifest = ${serializedAppHooksManifest};
|
|
1796
1939
|
const appHooksServerUrl = ${serializedAppHooksServerUrl};
|
|
@@ -2045,6 +2188,40 @@ const prepareRequestContext = (c, hooks) => {
|
|
|
2045
2188
|
const reroutePathname = (hooks, request, pathname, baseUrl) =>
|
|
2046
2189
|
normalizeRoutePath(resolveReroute(hooks.reroute, request, pathname, baseUrl));
|
|
2047
2190
|
|
|
2191
|
+
const getRouteServerAccess = (route) => {
|
|
2192
|
+
const routeIndex = routes.indexOf(route);
|
|
2193
|
+
const entry = routeIndex >= 0 ? routeServerAccessEntries[routeIndex] : null;
|
|
2194
|
+
return entry ?? { actionIds: [], loaderIds: [] };
|
|
2195
|
+
};
|
|
2196
|
+
|
|
2197
|
+
const resolveRouteForCurrentUrl = (hooks, request, currentUrl) => {
|
|
2198
|
+
const resolvedPathname = reroutePathname(hooks, request, normalizeRoutePath(currentUrl.pathname), currentUrl.href);
|
|
2199
|
+
const match = matchRoute(resolvedPathname);
|
|
2200
|
+
if (match?.route?.page) {
|
|
2201
|
+
return match;
|
|
2202
|
+
}
|
|
2203
|
+
const fallback = findSpecialRoute(resolvedPathname, "notFound");
|
|
2204
|
+
return fallback?.route?.notFound ? fallback : null;
|
|
2205
|
+
};
|
|
2206
|
+
|
|
2207
|
+
const getRpcCurrentRoute = (hooks, c) => {
|
|
2208
|
+
const requestUrl = getRequestUrl(c.req.raw);
|
|
2209
|
+
const routeUrlHeader = c.req.header(${JSON.stringify(ROUTE_RPC_URL_HEADER)});
|
|
2210
|
+
if (!routeUrlHeader) {
|
|
2211
|
+
return null;
|
|
2212
|
+
}
|
|
2213
|
+
let currentUrl;
|
|
2214
|
+
try {
|
|
2215
|
+
currentUrl = new URL(routeUrlHeader, requestUrl);
|
|
2216
|
+
} catch {
|
|
2217
|
+
return null;
|
|
2218
|
+
}
|
|
2219
|
+
if (currentUrl.origin !== requestUrl.origin) {
|
|
2220
|
+
return null;
|
|
2221
|
+
}
|
|
2222
|
+
return resolveRouteForCurrentUrl(hooks, c.req.raw, currentUrl);
|
|
2223
|
+
};
|
|
2224
|
+
|
|
2048
2225
|
const resolveRequest = async (c, handler) => {
|
|
2049
2226
|
const { appHooks, serverHooks } = await hooksPromise;
|
|
2050
2227
|
const requestContext = prepareRequestContext(c, serverHooks);
|
|
@@ -2545,29 +2722,65 @@ for (const pageRouteEntry of pageRouteEntries) {
|
|
|
2545
2722
|
});
|
|
2546
2723
|
}
|
|
2547
2724
|
|
|
2548
|
-
app.post("/__eclipsa/action/:id", async (c) =>
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2725
|
+
app.post("/__eclipsa/action/:id", async (c) =>
|
|
2726
|
+
resolveRequest(c, async (requestContext, appHooks) => {
|
|
2727
|
+
const id = requestContext.req.param("id");
|
|
2728
|
+
if (!id) {
|
|
2729
|
+
return requestContext.text("Not Found", 404);
|
|
2730
|
+
}
|
|
2731
|
+
const routeMatch = getRpcCurrentRoute(appHooks, requestContext);
|
|
2732
|
+
if (!routeMatch) {
|
|
2733
|
+
return requestContext.text("Bad Request", 400);
|
|
2734
|
+
}
|
|
2735
|
+
const routeAccess = getRouteServerAccess(routeMatch.route);
|
|
2736
|
+
if (!routeAccess.actionIds.includes(id)) {
|
|
2737
|
+
return requestContext.text("Not Found", 404);
|
|
2738
|
+
}
|
|
2739
|
+
const moduleUrl = actions[id];
|
|
2740
|
+
if (!moduleUrl) {
|
|
2741
|
+
return requestContext.text("Not Found", 404);
|
|
2742
|
+
}
|
|
2743
|
+
if (!hasAction(id)) {
|
|
2744
|
+
await import(moduleUrl);
|
|
2745
|
+
}
|
|
2746
|
+
return composeRouteMiddlewares(
|
|
2747
|
+
routeMatch.route,
|
|
2748
|
+
requestContext,
|
|
2749
|
+
routeMatch.params,
|
|
2750
|
+
async () => executeAction(id, requestContext),
|
|
2751
|
+
);
|
|
2752
|
+
}),
|
|
2753
|
+
);
|
|
2754
|
+
|
|
2755
|
+
app.get("/__eclipsa/loader/:id", async (c) =>
|
|
2756
|
+
resolveRequest(c, async (requestContext, appHooks) => {
|
|
2757
|
+
const id = requestContext.req.param("id");
|
|
2758
|
+
if (!id) {
|
|
2759
|
+
return requestContext.text("Not Found", 404);
|
|
2760
|
+
}
|
|
2761
|
+
const routeMatch = getRpcCurrentRoute(appHooks, requestContext);
|
|
2762
|
+
if (!routeMatch) {
|
|
2763
|
+
return requestContext.text("Bad Request", 400);
|
|
2764
|
+
}
|
|
2765
|
+
const routeAccess = getRouteServerAccess(routeMatch.route);
|
|
2766
|
+
if (!routeAccess.loaderIds.includes(id)) {
|
|
2767
|
+
return requestContext.text("Not Found", 404);
|
|
2768
|
+
}
|
|
2769
|
+
const moduleUrl = loaders[id];
|
|
2770
|
+
if (!moduleUrl) {
|
|
2771
|
+
return requestContext.text("Not Found", 404);
|
|
2772
|
+
}
|
|
2773
|
+
if (!hasLoader(id)) {
|
|
2774
|
+
await import(moduleUrl);
|
|
2775
|
+
}
|
|
2776
|
+
return composeRouteMiddlewares(
|
|
2777
|
+
routeMatch.route,
|
|
2778
|
+
requestContext,
|
|
2779
|
+
routeMatch.params,
|
|
2780
|
+
async () => executeLoader(id, requestContext),
|
|
2781
|
+
);
|
|
2782
|
+
}),
|
|
2783
|
+
);
|
|
2571
2784
|
|
|
2572
2785
|
app.get(${JSON.stringify(ROUTE_PREFLIGHT_ENDPOINT)}, async (c) => {
|
|
2573
2786
|
const href = c.req.query("href");
|
|
@@ -2632,6 +2845,10 @@ app.all("*", async (c) => {
|
|
|
2632
2845
|
? invokeRouteServer(match.route.server, c, match.params)
|
|
2633
2846
|
: renderMatchedPage(match, c);
|
|
2634
2847
|
}
|
|
2848
|
+
const routeAccess = getRouteServerAccess(match.route);
|
|
2849
|
+
if (!routeAccess.actionIds.includes(actionId)) {
|
|
2850
|
+
return c.text("Not Found", 404);
|
|
2851
|
+
}
|
|
2635
2852
|
const moduleUrl = actions[actionId];
|
|
2636
2853
|
if (!moduleUrl) {
|
|
2637
2854
|
return c.text("Not Found", 404);
|
|
@@ -2782,6 +2999,7 @@ const build = async (builder, userConfig, options) => {
|
|
|
2782
2999
|
const actions = await collectAppActions(root);
|
|
2783
3000
|
const loaders = await collectAppLoaders(root);
|
|
2784
3001
|
const routes = await createRoutes(root);
|
|
3002
|
+
const routeServerAccessEntries = await createRouteServerAccessEntries(routes, actions, loaders);
|
|
2785
3003
|
const staticPageRoutes = routes.filter((route) => route.page && resolveRouteRenderMode(route, options.output) === "static");
|
|
2786
3004
|
const dynamicPageRoutes = routes.filter((route) => route.page && resolveRouteRenderMode(route, options.output) === "dynamic");
|
|
2787
3005
|
if (options.output === "ssg") {
|
|
@@ -2814,7 +3032,7 @@ const build = async (builder, userConfig, options) => {
|
|
|
2814
3032
|
const serverDir = path$1.join(root, "dist/server");
|
|
2815
3033
|
const appModulePath = path$1.join(root, "dist/ssr/eclipsa_app.mjs");
|
|
2816
3034
|
await fs.mkdir(path$1.dirname(appModulePath), { recursive: true });
|
|
2817
|
-
await fs.writeFile(appModulePath, renderAppModule(actions, appHooksClientUrl, appHooksServerUrl, loaders, routes, routeManifest, serverHooksUrl, symbolUrls, stylesheetUrls, chunkCacheAssets.map((asset) => asset.url)));
|
|
3035
|
+
await fs.writeFile(appModulePath, renderAppModule(actions, appHooksClientUrl, appHooksServerUrl, loaders, routes, routeServerAccessEntries, routeManifest, serverHooksUrl, symbolUrls, stylesheetUrls, chunkCacheAssets.map((asset) => asset.url)));
|
|
2818
3036
|
const staticPrerenderTargets = await resolveStaticPrerenderTargets(root, staticPageRoutes);
|
|
2819
3037
|
const prerenderStaticRoutes = async () => {
|
|
2820
3038
|
if (staticPrerenderTargets.concretePaths.size === 0 && staticPrerenderTargets.dynamicParamsByPattern.size === 0) return;
|
|
@@ -2890,6 +3108,7 @@ const createEclipsaNitroConfig = (root, nitroConfig) => {
|
|
|
2890
3108
|
};
|
|
2891
3109
|
//#endregion
|
|
2892
3110
|
//#region vite/config.ts
|
|
3111
|
+
const ECLIPSA_RUNTIME_ENTRY_PATH = fileURLToPath(import.meta.resolve("eclipsa/vite/build/runtime"));
|
|
2893
3112
|
const fileExists = async (filePath) => {
|
|
2894
3113
|
try {
|
|
2895
3114
|
await fs.access(filePath);
|
|
@@ -2920,7 +3139,7 @@ const createConfig = (options) => async (userConfig) => {
|
|
|
2920
3139
|
const ssrInput = Object.fromEntries([
|
|
2921
3140
|
["server_entry", path.join(root, "app/+server-entry.ts")],
|
|
2922
3141
|
["ssr_root", path.join(root, "app/+ssr-root.tsx")],
|
|
2923
|
-
["eclipsa_runtime",
|
|
3142
|
+
["eclipsa_runtime", ECLIPSA_RUNTIME_ENTRY_PATH],
|
|
2924
3143
|
...hasAppHooks ? [["app_hooks", appHooksPath]] : [],
|
|
2925
3144
|
...hasServerHooks ? [["server_hooks", serverHooksPath]] : [],
|
|
2926
3145
|
...actions.map((action) => [`action__${action.id}`, action.filePath]),
|
|
@@ -2950,19 +3169,22 @@ const createConfig = (options) => async (userConfig) => {
|
|
|
2950
3169
|
preserveEntrySignatures: "allow-extension"
|
|
2951
3170
|
}
|
|
2952
3171
|
} },
|
|
2953
|
-
ssr: {
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
3172
|
+
ssr: {
|
|
3173
|
+
resolve: { noExternal: [/^eclipsa(?:\/|$)/] },
|
|
3174
|
+
build: {
|
|
3175
|
+
emptyOutDir: true,
|
|
3176
|
+
outDir: path.join(root, "dist/ssr"),
|
|
3177
|
+
rollupOptions: {
|
|
3178
|
+
input: ssrInput,
|
|
3179
|
+
output: {
|
|
3180
|
+
assetFileNames: "assets/[name]-[hash][extname]",
|
|
3181
|
+
chunkFileNames: "chunks/[name]-[hash].mjs",
|
|
3182
|
+
entryFileNames: "entries/[name].mjs"
|
|
3183
|
+
},
|
|
3184
|
+
preserveEntrySignatures: "allow-extension"
|
|
3185
|
+
}
|
|
2964
3186
|
}
|
|
2965
|
-
}
|
|
3187
|
+
}
|
|
2966
3188
|
},
|
|
2967
3189
|
builder: { async buildApp(builder) {
|
|
2968
3190
|
await build(builder, userConfig, options);
|