@constela/start 1.4.3 → 1.5.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.
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
// src/runtime/entry-server.ts
|
|
2
2
|
import { renderToString } from "@constela/server";
|
|
3
3
|
async function renderPage(program, ctx) {
|
|
4
|
+
const stateOverrides = {};
|
|
5
|
+
if (ctx.cookies?.["theme"] && program.state?.["theme"]) {
|
|
6
|
+
const themeFromCookie = ctx.cookies["theme"];
|
|
7
|
+
if (themeFromCookie) {
|
|
8
|
+
stateOverrides["theme"] = themeFromCookie;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
4
11
|
const options = {
|
|
5
12
|
route: {
|
|
6
13
|
params: ctx.params,
|
|
@@ -8,6 +15,12 @@ async function renderPage(program, ctx) {
|
|
|
8
15
|
path: ctx.url
|
|
9
16
|
}
|
|
10
17
|
};
|
|
18
|
+
if (ctx.cookies) {
|
|
19
|
+
options.cookies = ctx.cookies;
|
|
20
|
+
}
|
|
21
|
+
if (Object.keys(stateOverrides).length > 0) {
|
|
22
|
+
options.stateOverrides = stateOverrides;
|
|
23
|
+
}
|
|
11
24
|
if (program.importData) {
|
|
12
25
|
options.imports = program.importData;
|
|
13
26
|
}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
generateMetaTags,
|
|
4
4
|
renderPage,
|
|
5
5
|
wrapHtml
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LCCIX5MB.js";
|
|
7
7
|
|
|
8
8
|
// src/router/file-router.ts
|
|
9
9
|
import fg from "fast-glob";
|
|
@@ -1221,6 +1221,207 @@ var DataLoader = class {
|
|
|
1221
1221
|
}
|
|
1222
1222
|
};
|
|
1223
1223
|
|
|
1224
|
+
// src/api/handler.ts
|
|
1225
|
+
var HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH"];
|
|
1226
|
+
function getAllowedMethods(module) {
|
|
1227
|
+
const methods = [];
|
|
1228
|
+
for (const method of HTTP_METHODS) {
|
|
1229
|
+
if (module[method]) {
|
|
1230
|
+
methods.push(method);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
if (module.GET) {
|
|
1234
|
+
methods.push("HEAD");
|
|
1235
|
+
}
|
|
1236
|
+
methods.push("OPTIONS");
|
|
1237
|
+
return methods;
|
|
1238
|
+
}
|
|
1239
|
+
function createMethodNotAllowedResponse(allowedMethods) {
|
|
1240
|
+
return new Response(JSON.stringify({ error: "Method Not Allowed" }), {
|
|
1241
|
+
status: 405,
|
|
1242
|
+
headers: {
|
|
1243
|
+
"Content-Type": "application/json",
|
|
1244
|
+
Allow: allowedMethods.join(", ")
|
|
1245
|
+
}
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
function createInternalErrorResponse(error) {
|
|
1249
|
+
const isDev = process.env["NODE_ENV"] !== "production";
|
|
1250
|
+
const message = isDev && error instanceof Error ? error.message : "Internal Server Error";
|
|
1251
|
+
return new Response(JSON.stringify({ error: message }), {
|
|
1252
|
+
status: 500,
|
|
1253
|
+
headers: {
|
|
1254
|
+
"Content-Type": "application/json"
|
|
1255
|
+
}
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
function createAPIHandler(module) {
|
|
1259
|
+
return async (ctx) => {
|
|
1260
|
+
const method = ctx.request.method.toUpperCase();
|
|
1261
|
+
const allowedMethods = getAllowedMethods(module);
|
|
1262
|
+
if (method === "OPTIONS") {
|
|
1263
|
+
return new Response(null, {
|
|
1264
|
+
status: 204,
|
|
1265
|
+
headers: {
|
|
1266
|
+
Allow: allowedMethods.join(", ")
|
|
1267
|
+
}
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
if (method === "HEAD") {
|
|
1271
|
+
const getHandler = module.GET;
|
|
1272
|
+
if (getHandler) {
|
|
1273
|
+
return new Response(null, { status: 200 });
|
|
1274
|
+
}
|
|
1275
|
+
return createMethodNotAllowedResponse(allowedMethods);
|
|
1276
|
+
}
|
|
1277
|
+
const handler = module[method];
|
|
1278
|
+
if (!handler) {
|
|
1279
|
+
return createMethodNotAllowedResponse(allowedMethods);
|
|
1280
|
+
}
|
|
1281
|
+
try {
|
|
1282
|
+
const response = await handler(ctx);
|
|
1283
|
+
return response;
|
|
1284
|
+
} catch (error) {
|
|
1285
|
+
return createInternalErrorResponse(error);
|
|
1286
|
+
}
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
// src/utils/resolve-page.ts
|
|
1291
|
+
function isPageExportFunction(exported) {
|
|
1292
|
+
return typeof exported === "function";
|
|
1293
|
+
}
|
|
1294
|
+
async function resolvePageExport(pageDefault, params, expectedParams) {
|
|
1295
|
+
if (expectedParams) {
|
|
1296
|
+
for (const key of expectedParams) {
|
|
1297
|
+
if (!(key in params)) {
|
|
1298
|
+
throw new Error(`Missing required route param: ${key}`);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
if (isPageExportFunction(pageDefault)) {
|
|
1303
|
+
return await pageDefault(params);
|
|
1304
|
+
}
|
|
1305
|
+
return pageDefault;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
// src/edge/adapter.ts
|
|
1309
|
+
import { matchRoute } from "@constela/router";
|
|
1310
|
+
import { isCookieInitialExpr } from "@constela/core";
|
|
1311
|
+
async function defaultLoadModule(file) {
|
|
1312
|
+
return import(file);
|
|
1313
|
+
}
|
|
1314
|
+
function isStaticAssetRequest(pathname) {
|
|
1315
|
+
return pathname.startsWith("/_assets/") || pathname.startsWith("/_static/") || pathname.endsWith(".css") || pathname.endsWith(".js") || pathname.endsWith(".map");
|
|
1316
|
+
}
|
|
1317
|
+
function createNotFoundResponse() {
|
|
1318
|
+
return new Response(JSON.stringify({ error: "Not Found" }), {
|
|
1319
|
+
status: 404,
|
|
1320
|
+
headers: { "Content-Type": "application/json" }
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
function createErrorResponse(error) {
|
|
1324
|
+
const message = error instanceof Error ? error.message : "Internal Server Error";
|
|
1325
|
+
return new Response(JSON.stringify({ error: message }), {
|
|
1326
|
+
status: 500,
|
|
1327
|
+
headers: { "Content-Type": "application/json" }
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
function parseCookies(cookieHeader) {
|
|
1331
|
+
if (!cookieHeader) return {};
|
|
1332
|
+
const cookies = {};
|
|
1333
|
+
for (const part of cookieHeader.split(";")) {
|
|
1334
|
+
const [name, ...valueParts] = part.trim().split("=");
|
|
1335
|
+
if (name) {
|
|
1336
|
+
const value = valueParts.join("=").trim();
|
|
1337
|
+
try {
|
|
1338
|
+
cookies[name.trim()] = decodeURIComponent(value);
|
|
1339
|
+
} catch {
|
|
1340
|
+
cookies[name.trim()] = value;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
return cookies;
|
|
1345
|
+
}
|
|
1346
|
+
function createAdapter(options) {
|
|
1347
|
+
const { routes, loadModule = defaultLoadModule } = options;
|
|
1348
|
+
async function fetch2(request) {
|
|
1349
|
+
try {
|
|
1350
|
+
const url = new URL(request.url);
|
|
1351
|
+
let pathname = url.pathname;
|
|
1352
|
+
if (pathname !== "/" && pathname.endsWith("/")) {
|
|
1353
|
+
pathname = pathname.slice(0, -1);
|
|
1354
|
+
}
|
|
1355
|
+
if (isStaticAssetRequest(pathname)) {
|
|
1356
|
+
return createNotFoundResponse();
|
|
1357
|
+
}
|
|
1358
|
+
let matchedRoute = null;
|
|
1359
|
+
let matchedParams = {};
|
|
1360
|
+
for (const route of routes) {
|
|
1361
|
+
const match = matchRoute(route.pattern, pathname);
|
|
1362
|
+
if (match) {
|
|
1363
|
+
matchedRoute = route;
|
|
1364
|
+
matchedParams = match.params;
|
|
1365
|
+
break;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
if (!matchedRoute) {
|
|
1369
|
+
return createNotFoundResponse();
|
|
1370
|
+
}
|
|
1371
|
+
const module = await loadModule(matchedRoute.file);
|
|
1372
|
+
if (matchedRoute.type === "api") {
|
|
1373
|
+
const apiModule = module;
|
|
1374
|
+
const ctx = {
|
|
1375
|
+
params: matchedParams,
|
|
1376
|
+
query: url.searchParams,
|
|
1377
|
+
request
|
|
1378
|
+
};
|
|
1379
|
+
const handler = createAPIHandler(apiModule);
|
|
1380
|
+
return await handler(ctx);
|
|
1381
|
+
} else {
|
|
1382
|
+
const pageModule = module;
|
|
1383
|
+
const program = await resolvePageExport(pageModule.default, matchedParams, matchedRoute.params);
|
|
1384
|
+
const cookieHeader = request.headers.get("Cookie");
|
|
1385
|
+
const cookies = parseCookies(cookieHeader);
|
|
1386
|
+
const content = await renderPage(program, {
|
|
1387
|
+
url: request.url,
|
|
1388
|
+
params: matchedParams,
|
|
1389
|
+
query: url.searchParams,
|
|
1390
|
+
cookies
|
|
1391
|
+
});
|
|
1392
|
+
const routeContext = {
|
|
1393
|
+
params: matchedParams,
|
|
1394
|
+
query: Object.fromEntries(url.searchParams.entries()),
|
|
1395
|
+
path: url.pathname
|
|
1396
|
+
};
|
|
1397
|
+
const hydrationScript = generateHydrationScript(program, void 0, routeContext);
|
|
1398
|
+
const themeState = program.state?.["theme"];
|
|
1399
|
+
let initialTheme;
|
|
1400
|
+
if (themeState) {
|
|
1401
|
+
if (isCookieInitialExpr(themeState.initial)) {
|
|
1402
|
+
const cookieValue = cookies[themeState.initial.key];
|
|
1403
|
+
initialTheme = cookieValue ?? themeState.initial.default;
|
|
1404
|
+
} else if (typeof themeState.initial === "string") {
|
|
1405
|
+
initialTheme = themeState.initial;
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
const html = wrapHtml(content, hydrationScript, void 0, initialTheme ? {
|
|
1409
|
+
theme: initialTheme,
|
|
1410
|
+
defaultTheme: initialTheme,
|
|
1411
|
+
themeStorageKey: "theme"
|
|
1412
|
+
} : void 0);
|
|
1413
|
+
return new Response(html, {
|
|
1414
|
+
status: 200,
|
|
1415
|
+
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
1416
|
+
});
|
|
1417
|
+
}
|
|
1418
|
+
} catch (error) {
|
|
1419
|
+
return createErrorResponse(error);
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
return { fetch: fetch2 };
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1224
1425
|
// src/layout/resolver.ts
|
|
1225
1426
|
import { existsSync as existsSync5, statSync as statSync3, readFileSync as readFileSync3 } from "fs";
|
|
1226
1427
|
import { join as join5, basename as basename2, dirname } from "path";
|
|
@@ -1417,6 +1618,7 @@ import { createServer } from "http";
|
|
|
1417
1618
|
import { createReadStream } from "fs";
|
|
1418
1619
|
import { join as join7, isAbsolute } from "path";
|
|
1419
1620
|
import { createServer as createViteServer } from "vite";
|
|
1621
|
+
import { isCookieInitialExpr as isCookieInitialExpr2 } from "@constela/core";
|
|
1420
1622
|
|
|
1421
1623
|
// src/json-page-loader.ts
|
|
1422
1624
|
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
|
|
@@ -1977,7 +2179,7 @@ var DEFAULT_PORT = 3e3;
|
|
|
1977
2179
|
var DEFAULT_HOST = "localhost";
|
|
1978
2180
|
var DEFAULT_PUBLIC_DIR = "public";
|
|
1979
2181
|
var DEFAULT_ROUTES_DIR = "src/routes";
|
|
1980
|
-
function
|
|
2182
|
+
function matchRoute2(url, routes) {
|
|
1981
2183
|
const normalizedUrl = url === "/" ? "/" : url.replace(/\/$/, "");
|
|
1982
2184
|
const urlSegments = normalizedUrl.split("/").filter(Boolean);
|
|
1983
2185
|
for (const route of routes) {
|
|
@@ -2129,7 +2331,7 @@ async function createDevServer(options = {}) {
|
|
|
2129
2331
|
});
|
|
2130
2332
|
return;
|
|
2131
2333
|
}
|
|
2132
|
-
const match =
|
|
2334
|
+
const match = matchRoute2(pathname, routes);
|
|
2133
2335
|
if (match) {
|
|
2134
2336
|
try {
|
|
2135
2337
|
const projectRoot = process.cwd();
|
|
@@ -2163,10 +2365,12 @@ async function createDevServer(options = {}) {
|
|
|
2163
2365
|
}
|
|
2164
2366
|
}
|
|
2165
2367
|
}
|
|
2368
|
+
const cookies = parseCookies(req.headers.cookie ?? null);
|
|
2166
2369
|
const ssrContext = {
|
|
2167
2370
|
url: pathname,
|
|
2168
2371
|
params: match.params,
|
|
2169
|
-
query: url.searchParams
|
|
2372
|
+
query: url.searchParams,
|
|
2373
|
+
cookies
|
|
2170
2374
|
};
|
|
2171
2375
|
const content = await renderPage(composedProgram, ssrContext);
|
|
2172
2376
|
const routeContext = {
|
|
@@ -2183,7 +2387,15 @@ async function createDevServer(options = {}) {
|
|
|
2183
2387
|
const cssHead = css ? (Array.isArray(css) ? css : [css]).map((p) => `<link rel="stylesheet" href="/${p}">`).join("\n") : "";
|
|
2184
2388
|
const head = [metaTags, cssHead].filter(Boolean).join("\n");
|
|
2185
2389
|
const themeState = composedProgram.state?.["theme"];
|
|
2186
|
-
|
|
2390
|
+
let initialTheme;
|
|
2391
|
+
if (themeState) {
|
|
2392
|
+
if (isCookieInitialExpr2(themeState.initial)) {
|
|
2393
|
+
const cookieValue = cookies[themeState.initial.key];
|
|
2394
|
+
initialTheme = cookieValue ?? themeState.initial.default;
|
|
2395
|
+
} else if (typeof themeState.initial === "string") {
|
|
2396
|
+
initialTheme = themeState.initial;
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2187
2399
|
const importMap = {
|
|
2188
2400
|
"@constela/runtime": "/node_modules/@constela/runtime/dist/index.js",
|
|
2189
2401
|
"@constela/core": "/node_modules/@constela/core/dist/index.js",
|
|
@@ -3142,6 +3354,10 @@ export {
|
|
|
3142
3354
|
loadApi,
|
|
3143
3355
|
generateStaticPaths,
|
|
3144
3356
|
DataLoader,
|
|
3357
|
+
createAPIHandler,
|
|
3358
|
+
isPageExportFunction,
|
|
3359
|
+
resolvePageExport,
|
|
3360
|
+
createAdapter,
|
|
3145
3361
|
scanLayouts,
|
|
3146
3362
|
resolveLayout,
|
|
3147
3363
|
loadLayout,
|
package/dist/cli/index.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -2,11 +2,14 @@ import {
|
|
|
2
2
|
DataLoader,
|
|
3
3
|
LayoutResolver,
|
|
4
4
|
build,
|
|
5
|
+
createAPIHandler,
|
|
6
|
+
createAdapter,
|
|
5
7
|
createDevServer,
|
|
6
8
|
filePathToPattern,
|
|
7
9
|
generateStaticPaths,
|
|
8
10
|
getMimeType,
|
|
9
11
|
hyperlink,
|
|
12
|
+
isPageExportFunction,
|
|
10
13
|
isPathSafe,
|
|
11
14
|
loadApi,
|
|
12
15
|
loadComponentDefinitions,
|
|
@@ -18,44 +21,25 @@ import {
|
|
|
18
21
|
mdxToConstela,
|
|
19
22
|
resolveConfig,
|
|
20
23
|
resolveLayout,
|
|
24
|
+
resolvePageExport,
|
|
21
25
|
resolveStaticFile,
|
|
22
26
|
scanLayouts,
|
|
23
27
|
scanRoutes,
|
|
24
28
|
transformCsv,
|
|
25
29
|
transformMdx,
|
|
26
30
|
transformYaml
|
|
27
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-W6SJTQAP.js";
|
|
28
32
|
import {
|
|
29
33
|
evaluateMetaExpression,
|
|
30
34
|
generateHydrationScript,
|
|
31
35
|
generateMetaTags,
|
|
32
36
|
renderPage,
|
|
33
37
|
wrapHtml
|
|
34
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-LCCIX5MB.js";
|
|
35
39
|
|
|
36
40
|
// src/build/ssg.ts
|
|
37
41
|
import { mkdir, writeFile } from "fs/promises";
|
|
38
42
|
import { join, dirname } from "path";
|
|
39
|
-
|
|
40
|
-
// src/utils/resolve-page.ts
|
|
41
|
-
function isPageExportFunction(exported) {
|
|
42
|
-
return typeof exported === "function";
|
|
43
|
-
}
|
|
44
|
-
async function resolvePageExport(pageDefault, params, expectedParams) {
|
|
45
|
-
if (expectedParams) {
|
|
46
|
-
for (const key of expectedParams) {
|
|
47
|
-
if (!(key in params)) {
|
|
48
|
-
throw new Error(`Missing required route param: ${key}`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
if (isPageExportFunction(pageDefault)) {
|
|
53
|
-
return await pageDefault(params);
|
|
54
|
-
}
|
|
55
|
-
return pageDefault;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// src/build/ssg.ts
|
|
59
43
|
var defaultProgram = {
|
|
60
44
|
version: "1.0",
|
|
61
45
|
state: {},
|
|
@@ -174,72 +158,6 @@ async function generateStaticPages(routes, outDir, options = {}) {
|
|
|
174
158
|
return generatedPaths;
|
|
175
159
|
}
|
|
176
160
|
|
|
177
|
-
// src/api/handler.ts
|
|
178
|
-
var HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH"];
|
|
179
|
-
function getAllowedMethods(module) {
|
|
180
|
-
const methods = [];
|
|
181
|
-
for (const method of HTTP_METHODS) {
|
|
182
|
-
if (module[method]) {
|
|
183
|
-
methods.push(method);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
if (module.GET) {
|
|
187
|
-
methods.push("HEAD");
|
|
188
|
-
}
|
|
189
|
-
methods.push("OPTIONS");
|
|
190
|
-
return methods;
|
|
191
|
-
}
|
|
192
|
-
function createMethodNotAllowedResponse(allowedMethods) {
|
|
193
|
-
return new Response(JSON.stringify({ error: "Method Not Allowed" }), {
|
|
194
|
-
status: 405,
|
|
195
|
-
headers: {
|
|
196
|
-
"Content-Type": "application/json",
|
|
197
|
-
Allow: allowedMethods.join(", ")
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
function createInternalErrorResponse(error) {
|
|
202
|
-
const isDev = process.env["NODE_ENV"] !== "production";
|
|
203
|
-
const message = isDev && error instanceof Error ? error.message : "Internal Server Error";
|
|
204
|
-
return new Response(JSON.stringify({ error: message }), {
|
|
205
|
-
status: 500,
|
|
206
|
-
headers: {
|
|
207
|
-
"Content-Type": "application/json"
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
function createAPIHandler(module) {
|
|
212
|
-
return async (ctx) => {
|
|
213
|
-
const method = ctx.request.method.toUpperCase();
|
|
214
|
-
const allowedMethods = getAllowedMethods(module);
|
|
215
|
-
if (method === "OPTIONS") {
|
|
216
|
-
return new Response(null, {
|
|
217
|
-
status: 204,
|
|
218
|
-
headers: {
|
|
219
|
-
Allow: allowedMethods.join(", ")
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
if (method === "HEAD") {
|
|
224
|
-
const getHandler = module.GET;
|
|
225
|
-
if (getHandler) {
|
|
226
|
-
return new Response(null, { status: 200 });
|
|
227
|
-
}
|
|
228
|
-
return createMethodNotAllowedResponse(allowedMethods);
|
|
229
|
-
}
|
|
230
|
-
const handler = module[method];
|
|
231
|
-
if (!handler) {
|
|
232
|
-
return createMethodNotAllowedResponse(allowedMethods);
|
|
233
|
-
}
|
|
234
|
-
try {
|
|
235
|
-
const response = await handler(ctx);
|
|
236
|
-
return response;
|
|
237
|
-
} catch (error) {
|
|
238
|
-
return createInternalErrorResponse(error);
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
|
|
243
161
|
// src/middleware/index.ts
|
|
244
162
|
function createMiddlewareChain(middlewares) {
|
|
245
163
|
return async (ctx, finalNext) => {
|
|
@@ -254,95 +172,6 @@ function createMiddlewareChain(middlewares) {
|
|
|
254
172
|
return dispatch(0);
|
|
255
173
|
};
|
|
256
174
|
}
|
|
257
|
-
|
|
258
|
-
// src/edge/adapter.ts
|
|
259
|
-
import { matchRoute } from "@constela/router";
|
|
260
|
-
async function defaultLoadModule(file) {
|
|
261
|
-
return import(file);
|
|
262
|
-
}
|
|
263
|
-
function isStaticAssetRequest(pathname) {
|
|
264
|
-
return pathname.startsWith("/_assets/") || pathname.startsWith("/_static/") || pathname.endsWith(".css") || pathname.endsWith(".js") || pathname.endsWith(".map");
|
|
265
|
-
}
|
|
266
|
-
function createNotFoundResponse() {
|
|
267
|
-
return new Response(JSON.stringify({ error: "Not Found" }), {
|
|
268
|
-
status: 404,
|
|
269
|
-
headers: { "Content-Type": "application/json" }
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
function createErrorResponse(error) {
|
|
273
|
-
const message = error instanceof Error ? error.message : "Internal Server Error";
|
|
274
|
-
return new Response(JSON.stringify({ error: message }), {
|
|
275
|
-
status: 500,
|
|
276
|
-
headers: { "Content-Type": "application/json" }
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
function createAdapter(options) {
|
|
280
|
-
const { routes, loadModule = defaultLoadModule } = options;
|
|
281
|
-
async function fetch(request) {
|
|
282
|
-
try {
|
|
283
|
-
const url = new URL(request.url);
|
|
284
|
-
let pathname = url.pathname;
|
|
285
|
-
if (pathname !== "/" && pathname.endsWith("/")) {
|
|
286
|
-
pathname = pathname.slice(0, -1);
|
|
287
|
-
}
|
|
288
|
-
if (isStaticAssetRequest(pathname)) {
|
|
289
|
-
return createNotFoundResponse();
|
|
290
|
-
}
|
|
291
|
-
let matchedRoute = null;
|
|
292
|
-
let matchedParams = {};
|
|
293
|
-
for (const route of routes) {
|
|
294
|
-
const match = matchRoute(route.pattern, pathname);
|
|
295
|
-
if (match) {
|
|
296
|
-
matchedRoute = route;
|
|
297
|
-
matchedParams = match.params;
|
|
298
|
-
break;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
if (!matchedRoute) {
|
|
302
|
-
return createNotFoundResponse();
|
|
303
|
-
}
|
|
304
|
-
const module = await loadModule(matchedRoute.file);
|
|
305
|
-
if (matchedRoute.type === "api") {
|
|
306
|
-
const apiModule = module;
|
|
307
|
-
const ctx = {
|
|
308
|
-
params: matchedParams,
|
|
309
|
-
query: url.searchParams,
|
|
310
|
-
request
|
|
311
|
-
};
|
|
312
|
-
const handler = createAPIHandler(apiModule);
|
|
313
|
-
return await handler(ctx);
|
|
314
|
-
} else {
|
|
315
|
-
const pageModule = module;
|
|
316
|
-
const program = await resolvePageExport(pageModule.default, matchedParams, matchedRoute.params);
|
|
317
|
-
const content = await renderPage(program, {
|
|
318
|
-
url: request.url,
|
|
319
|
-
params: matchedParams,
|
|
320
|
-
query: url.searchParams
|
|
321
|
-
});
|
|
322
|
-
const routeContext = {
|
|
323
|
-
params: matchedParams,
|
|
324
|
-
query: Object.fromEntries(url.searchParams.entries()),
|
|
325
|
-
path: url.pathname
|
|
326
|
-
};
|
|
327
|
-
const hydrationScript = generateHydrationScript(program, void 0, routeContext);
|
|
328
|
-
const themeState = program.state?.["theme"];
|
|
329
|
-
const initialTheme = themeState?.initial;
|
|
330
|
-
const html = wrapHtml(content, hydrationScript, void 0, initialTheme ? {
|
|
331
|
-
theme: initialTheme,
|
|
332
|
-
defaultTheme: initialTheme,
|
|
333
|
-
themeStorageKey: "theme"
|
|
334
|
-
} : void 0);
|
|
335
|
-
return new Response(html, {
|
|
336
|
-
status: 200,
|
|
337
|
-
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
} catch (error) {
|
|
341
|
-
return createErrorResponse(error);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
return { fetch };
|
|
345
|
-
}
|
|
346
175
|
export {
|
|
347
176
|
DataLoader,
|
|
348
177
|
LayoutResolver,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constela/start",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "Meta-framework for Constela applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
"postcss": "^8.5.0",
|
|
44
44
|
"@tailwindcss/postcss": "^4.0.0",
|
|
45
45
|
"tailwindcss": "^4.0.0",
|
|
46
|
-
"@constela/compiler": "0.11.
|
|
47
|
-
"@constela/core": "0.
|
|
48
|
-
"@constela/runtime": "0.
|
|
49
|
-
"@constela/
|
|
50
|
-
"@constela/
|
|
46
|
+
"@constela/compiler": "0.11.1",
|
|
47
|
+
"@constela/core": "0.12.0",
|
|
48
|
+
"@constela/runtime": "0.15.0",
|
|
49
|
+
"@constela/server": "8.0.0",
|
|
50
|
+
"@constela/router": "13.0.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/mdast": "^4.0.4",
|