@jxsuite/server 0.35.0 → 0.36.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/package.json +8 -8
- package/src/ai-api.ts +4 -4
- package/src/studio-api.ts +40 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jxsuite/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
4
4
|
"description": "Jx development server with live reload, server-side proxy, and studio integration",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
"test:coverage": "bun test --isolate --coverage"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@jxsuite/compiler": "^0.
|
|
35
|
-
"@jxsuite/create": "^0.
|
|
36
|
-
"@jxsuite/import": "^0.35.
|
|
37
|
-
"@jxsuite/parser": "^0.35.
|
|
38
|
-
"@jxsuite/runtime": "^0.34.
|
|
39
|
-
"@jxsuite/schema": "^0.
|
|
40
|
-
"@jxsuite/starters": "^0.35.
|
|
34
|
+
"@jxsuite/compiler": "^0.35.0",
|
|
35
|
+
"@jxsuite/create": "^0.36.0",
|
|
36
|
+
"@jxsuite/import": "^0.35.1",
|
|
37
|
+
"@jxsuite/parser": "^0.35.1",
|
|
38
|
+
"@jxsuite/runtime": "^0.34.2",
|
|
39
|
+
"@jxsuite/schema": "^0.35.0",
|
|
40
|
+
"@jxsuite/starters": "^0.35.1",
|
|
41
41
|
"chokidar": "^5.0.0",
|
|
42
42
|
"zod": "^4.4.3"
|
|
43
43
|
}
|
package/src/ai-api.ts
CHANGED
|
@@ -385,7 +385,7 @@ export async function handleModels(req: Request): Promise<Response> {
|
|
|
385
385
|
{ id: "gpt-4o-mini", name: "GPT-4o Mini", contextWindow: 128_000 },
|
|
386
386
|
];
|
|
387
387
|
return Response.json(
|
|
388
|
-
{ models: defaults, configured: false },
|
|
388
|
+
{ models: defaults, configured: false, managed: false },
|
|
389
389
|
{
|
|
390
390
|
headers: { "Content-Type": "application/json" },
|
|
391
391
|
},
|
|
@@ -403,7 +403,7 @@ export async function handleModels(req: Request): Promise<Response> {
|
|
|
403
403
|
// Upstream failed — return defaults with configured flag so user can still try.
|
|
404
404
|
const defaults = [{ id: "gpt-4o", name: "GPT-4o", contextWindow: 128_000 }];
|
|
405
405
|
return Response.json(
|
|
406
|
-
{ models: defaults, configured: true, upstreamError: upstreamResp.status },
|
|
406
|
+
{ models: defaults, configured: true, managed: false, upstreamError: upstreamResp.status },
|
|
407
407
|
{
|
|
408
408
|
headers: { "Content-Type": "application/json" },
|
|
409
409
|
},
|
|
@@ -426,7 +426,7 @@ export async function handleModels(req: Request): Promise<Response> {
|
|
|
426
426
|
}));
|
|
427
427
|
|
|
428
428
|
return Response.json(
|
|
429
|
-
{ models, configured: true },
|
|
429
|
+
{ models, configured: true, managed: false },
|
|
430
430
|
{
|
|
431
431
|
headers: { "Content-Type": "application/json" },
|
|
432
432
|
},
|
|
@@ -435,7 +435,7 @@ export async function handleModels(req: Request): Promise<Response> {
|
|
|
435
435
|
// Network error → return defaults.
|
|
436
436
|
const defaults = [{ id: "gpt-4o", name: "GPT-4o", contextWindow: 128_000 }];
|
|
437
437
|
return Response.json(
|
|
438
|
-
{ models: defaults, configured: true, upstreamError: "network" },
|
|
438
|
+
{ models: defaults, configured: true, managed: false, upstreamError: "network" },
|
|
439
439
|
{
|
|
440
440
|
headers: { "Content-Type": "application/json" },
|
|
441
441
|
},
|
package/src/studio-api.ts
CHANGED
|
@@ -1072,6 +1072,46 @@ export async function handleStudioApi(
|
|
|
1072
1072
|
}
|
|
1073
1073
|
|
|
1074
1074
|
// Discover a plugin module's schema for studio form rendering
|
|
1075
|
+
/* Cloudflare API passthrough — the backend of the publish surface's `cfApi`.
|
|
1076
|
+
Stateless: the credential arrives per-request in X-CF-Token (the user's
|
|
1077
|
+
pasted API token, kept client-side) and is never stored. Only account
|
|
1078
|
+
listing and Pages project/deployment paths are reachable. */
|
|
1079
|
+
if (path === "/__studio/cf/proxy" && req.method === "POST") {
|
|
1080
|
+
const CF_PROXY_ALLOWLIST = [
|
|
1081
|
+
/^\/accounts$/,
|
|
1082
|
+
/^\/accounts\/[0-9a-f]{32}\/pages\/projects(?:\/[\w-]+)?$/,
|
|
1083
|
+
/^\/accounts\/[0-9a-f]{32}\/pages\/projects\/[\w-]+\/deployments(?:\/[\w-]+)?$/,
|
|
1084
|
+
/^\/accounts\/[0-9a-f]{32}\/pages\/projects\/[\w-]+\/deployments\/[\w-]+\/retry$/,
|
|
1085
|
+
];
|
|
1086
|
+
const cfToken = req.headers.get("X-CF-Token");
|
|
1087
|
+
if (!cfToken) {
|
|
1088
|
+
return Response.json({ error: "Missing X-CF-Token header" }, { status: 401 });
|
|
1089
|
+
}
|
|
1090
|
+
let payload: { path?: string; method?: string; body?: unknown };
|
|
1091
|
+
try {
|
|
1092
|
+
payload = (await req.json()) as typeof payload;
|
|
1093
|
+
} catch {
|
|
1094
|
+
return Response.json({ error: "Invalid JSON body" }, { status: 400 });
|
|
1095
|
+
}
|
|
1096
|
+
const apiPath = payload.path ?? "";
|
|
1097
|
+
if (!CF_PROXY_ALLOWLIST.some((re) => re.test(apiPath))) {
|
|
1098
|
+
return Response.json({ error: `Path not allowed: ${apiPath}` }, { status: 403 });
|
|
1099
|
+
}
|
|
1100
|
+
const method = payload.method ?? "GET";
|
|
1101
|
+
const upstream = await fetch(`https://api.cloudflare.com/client/v4${apiPath}`, {
|
|
1102
|
+
method,
|
|
1103
|
+
headers: {
|
|
1104
|
+
Authorization: `Bearer ${cfToken}`,
|
|
1105
|
+
...(payload.body === undefined ? {} : { "Content-Type": "application/json" }),
|
|
1106
|
+
},
|
|
1107
|
+
...(payload.body === undefined ? {} : { body: JSON.stringify(payload.body) }),
|
|
1108
|
+
});
|
|
1109
|
+
return new Response(upstream.body, {
|
|
1110
|
+
headers: { "Content-Type": upstream.headers.get("Content-Type") ?? "application/json" },
|
|
1111
|
+
status: upstream.status,
|
|
1112
|
+
});
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1075
1115
|
// Format capability proxy — studio fallback for capabilities whose timing excludes "client".
|
|
1076
1116
|
// Dispatches parse/serialize through the project's format registry by import name.
|
|
1077
1117
|
if (path === "/__studio/format" && req.method === "POST") {
|