@llmops/app 0.1.2 → 0.1.3-beta.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.
- package/dist/index.cjs +43 -35
- package/dist/index.mjs +43 -35
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -13388,8 +13388,22 @@ const requestHeadersSchema = object({
|
|
|
13388
13388
|
return baseContentType === CONTENT_TYPES.APPLICATION_JSON || baseContentType === CONTENT_TYPES.MULTIPART_FORM_DATA || baseContentType.startsWith(CONTENT_TYPES.GENERIC_AUDIO_PATTERN);
|
|
13389
13389
|
}, { message: "Invalid content type. Must be application/json, multipart/form-data, or audio/*" }),
|
|
13390
13390
|
"x-llmops-config": string$1({ error: "LLMOps Config ID was not provided." }),
|
|
13391
|
-
|
|
13391
|
+
authorization: string$1({ error: "Authorization header with environment secret is required." })
|
|
13392
13392
|
});
|
|
13393
|
+
/**
|
|
13394
|
+
* Extracts environment secret from Authorization header.
|
|
13395
|
+
* The user passes it in the OpenAI apiKey option which comes as "Bearer <envSecret>"
|
|
13396
|
+
* @param authHeader - The Authorization header value (e.g., "Bearer sk_xxxxx")
|
|
13397
|
+
* @returns The environment secret
|
|
13398
|
+
* @throws Error if the header is missing or invalid
|
|
13399
|
+
*/
|
|
13400
|
+
function extractEnvSecretFromAuth(authHeader) {
|
|
13401
|
+
const match = authHeader.match(/^Bearer\s+(.+)$/i);
|
|
13402
|
+
if (!match) throw new Error("Invalid Authorization header format. Expected: Bearer <environment-secret>");
|
|
13403
|
+
const token = match[1].trim();
|
|
13404
|
+
if (!token) throw new Error("Environment secret cannot be empty");
|
|
13405
|
+
return token;
|
|
13406
|
+
}
|
|
13393
13407
|
const requestValidator = zv("header", requestHeadersSchema);
|
|
13394
13408
|
|
|
13395
13409
|
//#endregion
|
|
@@ -13397,43 +13411,37 @@ const requestValidator = zv("header", requestHeadersSchema);
|
|
|
13397
13411
|
const createRequestGuardMiddleware = () => {
|
|
13398
13412
|
return async (c, next) => {
|
|
13399
13413
|
const headers = await requestHeadersSchema.safeParseAsync(c.req.header());
|
|
13400
|
-
if (headers.success)
|
|
13401
|
-
const origin = c.req.header("origin");
|
|
13402
|
-
const host = c.req.header("host");
|
|
13403
|
-
if (origin) {
|
|
13404
|
-
const originUrl = new URL(origin);
|
|
13405
|
-
const hostWithoutPort = host?.split(":")[0];
|
|
13406
|
-
const originHost = originUrl.hostname;
|
|
13407
|
-
if (originHost !== hostWithoutPort && originHost !== host) return c.json({ message: "Cross-origin requests require an environment ID" }, 403);
|
|
13408
|
-
}
|
|
13409
|
-
c.set("configId", headers["data"]["x-llmops-config"]);
|
|
13410
|
-
c.set("envSec", headers["data"]["x-llmops-environment"]);
|
|
13411
|
-
await next();
|
|
13412
|
-
} else {
|
|
13413
|
-
c.set("configId", headers["data"]["x-llmops-config"]);
|
|
13414
|
-
c.set("envSec", headers["data"]["x-llmops-environment"]);
|
|
13415
|
-
await (0, hono_cors.cors)({
|
|
13416
|
-
origin: "*",
|
|
13417
|
-
allowMethods: [
|
|
13418
|
-
"GET",
|
|
13419
|
-
"POST",
|
|
13420
|
-
"PUT",
|
|
13421
|
-
"DELETE",
|
|
13422
|
-
"OPTIONS"
|
|
13423
|
-
],
|
|
13424
|
-
allowHeaders: [
|
|
13425
|
-
"Content-Type",
|
|
13426
|
-
"Authorization",
|
|
13427
|
-
"x-llmops-config",
|
|
13428
|
-
"x-llmops-environment"
|
|
13429
|
-
]
|
|
13430
|
-
})(c, next);
|
|
13431
|
-
}
|
|
13432
|
-
else
|
|
13414
|
+
if (!headers.success)
|
|
13433
13415
|
/**
|
|
13434
13416
|
* @todo Refactor this to give OpenAI specific response.
|
|
13435
13417
|
*/
|
|
13436
|
-
return c.json({
|
|
13418
|
+
return c.json({
|
|
13419
|
+
message: "Invalid request headers",
|
|
13420
|
+
errors: headers.error.flatten().fieldErrors
|
|
13421
|
+
}, 400);
|
|
13422
|
+
let envSec;
|
|
13423
|
+
try {
|
|
13424
|
+
envSec = extractEnvSecretFromAuth(headers.data["authorization"]);
|
|
13425
|
+
} catch (error$45) {
|
|
13426
|
+
return c.json({ message: error$45 instanceof Error ? error$45.message : "Invalid authorization" }, 401);
|
|
13427
|
+
}
|
|
13428
|
+
c.set("configId", headers.data["x-llmops-config"]);
|
|
13429
|
+
c.set("envSec", envSec);
|
|
13430
|
+
await (0, hono_cors.cors)({
|
|
13431
|
+
origin: "*",
|
|
13432
|
+
allowMethods: [
|
|
13433
|
+
"GET",
|
|
13434
|
+
"POST",
|
|
13435
|
+
"PUT",
|
|
13436
|
+
"DELETE",
|
|
13437
|
+
"OPTIONS"
|
|
13438
|
+
],
|
|
13439
|
+
allowHeaders: [
|
|
13440
|
+
"Content-Type",
|
|
13441
|
+
"Authorization",
|
|
13442
|
+
"x-llmops-config"
|
|
13443
|
+
]
|
|
13444
|
+
})(c, next);
|
|
13437
13445
|
};
|
|
13438
13446
|
};
|
|
13439
13447
|
|
package/dist/index.mjs
CHANGED
|
@@ -13362,8 +13362,22 @@ const requestHeadersSchema = object({
|
|
|
13362
13362
|
return baseContentType === CONTENT_TYPES.APPLICATION_JSON || baseContentType === CONTENT_TYPES.MULTIPART_FORM_DATA || baseContentType.startsWith(CONTENT_TYPES.GENERIC_AUDIO_PATTERN);
|
|
13363
13363
|
}, { message: "Invalid content type. Must be application/json, multipart/form-data, or audio/*" }),
|
|
13364
13364
|
"x-llmops-config": string$1({ error: "LLMOps Config ID was not provided." }),
|
|
13365
|
-
|
|
13365
|
+
authorization: string$1({ error: "Authorization header with environment secret is required." })
|
|
13366
13366
|
});
|
|
13367
|
+
/**
|
|
13368
|
+
* Extracts environment secret from Authorization header.
|
|
13369
|
+
* The user passes it in the OpenAI apiKey option which comes as "Bearer <envSecret>"
|
|
13370
|
+
* @param authHeader - The Authorization header value (e.g., "Bearer sk_xxxxx")
|
|
13371
|
+
* @returns The environment secret
|
|
13372
|
+
* @throws Error if the header is missing or invalid
|
|
13373
|
+
*/
|
|
13374
|
+
function extractEnvSecretFromAuth(authHeader) {
|
|
13375
|
+
const match = authHeader.match(/^Bearer\s+(.+)$/i);
|
|
13376
|
+
if (!match) throw new Error("Invalid Authorization header format. Expected: Bearer <environment-secret>");
|
|
13377
|
+
const token = match[1].trim();
|
|
13378
|
+
if (!token) throw new Error("Environment secret cannot be empty");
|
|
13379
|
+
return token;
|
|
13380
|
+
}
|
|
13367
13381
|
const requestValidator = zv("header", requestHeadersSchema);
|
|
13368
13382
|
|
|
13369
13383
|
//#endregion
|
|
@@ -13371,43 +13385,37 @@ const requestValidator = zv("header", requestHeadersSchema);
|
|
|
13371
13385
|
const createRequestGuardMiddleware = () => {
|
|
13372
13386
|
return async (c, next) => {
|
|
13373
13387
|
const headers = await requestHeadersSchema.safeParseAsync(c.req.header());
|
|
13374
|
-
if (headers.success)
|
|
13375
|
-
const origin = c.req.header("origin");
|
|
13376
|
-
const host = c.req.header("host");
|
|
13377
|
-
if (origin) {
|
|
13378
|
-
const originUrl = new URL(origin);
|
|
13379
|
-
const hostWithoutPort = host?.split(":")[0];
|
|
13380
|
-
const originHost = originUrl.hostname;
|
|
13381
|
-
if (originHost !== hostWithoutPort && originHost !== host) return c.json({ message: "Cross-origin requests require an environment ID" }, 403);
|
|
13382
|
-
}
|
|
13383
|
-
c.set("configId", headers["data"]["x-llmops-config"]);
|
|
13384
|
-
c.set("envSec", headers["data"]["x-llmops-environment"]);
|
|
13385
|
-
await next();
|
|
13386
|
-
} else {
|
|
13387
|
-
c.set("configId", headers["data"]["x-llmops-config"]);
|
|
13388
|
-
c.set("envSec", headers["data"]["x-llmops-environment"]);
|
|
13389
|
-
await cors({
|
|
13390
|
-
origin: "*",
|
|
13391
|
-
allowMethods: [
|
|
13392
|
-
"GET",
|
|
13393
|
-
"POST",
|
|
13394
|
-
"PUT",
|
|
13395
|
-
"DELETE",
|
|
13396
|
-
"OPTIONS"
|
|
13397
|
-
],
|
|
13398
|
-
allowHeaders: [
|
|
13399
|
-
"Content-Type",
|
|
13400
|
-
"Authorization",
|
|
13401
|
-
"x-llmops-config",
|
|
13402
|
-
"x-llmops-environment"
|
|
13403
|
-
]
|
|
13404
|
-
})(c, next);
|
|
13405
|
-
}
|
|
13406
|
-
else
|
|
13388
|
+
if (!headers.success)
|
|
13407
13389
|
/**
|
|
13408
13390
|
* @todo Refactor this to give OpenAI specific response.
|
|
13409
13391
|
*/
|
|
13410
|
-
return c.json({
|
|
13392
|
+
return c.json({
|
|
13393
|
+
message: "Invalid request headers",
|
|
13394
|
+
errors: headers.error.flatten().fieldErrors
|
|
13395
|
+
}, 400);
|
|
13396
|
+
let envSec;
|
|
13397
|
+
try {
|
|
13398
|
+
envSec = extractEnvSecretFromAuth(headers.data["authorization"]);
|
|
13399
|
+
} catch (error$45) {
|
|
13400
|
+
return c.json({ message: error$45 instanceof Error ? error$45.message : "Invalid authorization" }, 401);
|
|
13401
|
+
}
|
|
13402
|
+
c.set("configId", headers.data["x-llmops-config"]);
|
|
13403
|
+
c.set("envSec", envSec);
|
|
13404
|
+
await cors({
|
|
13405
|
+
origin: "*",
|
|
13406
|
+
allowMethods: [
|
|
13407
|
+
"GET",
|
|
13408
|
+
"POST",
|
|
13409
|
+
"PUT",
|
|
13410
|
+
"DELETE",
|
|
13411
|
+
"OPTIONS"
|
|
13412
|
+
],
|
|
13413
|
+
allowHeaders: [
|
|
13414
|
+
"Content-Type",
|
|
13415
|
+
"Authorization",
|
|
13416
|
+
"x-llmops-config"
|
|
13417
|
+
]
|
|
13418
|
+
})(c, next);
|
|
13411
13419
|
};
|
|
13412
13420
|
};
|
|
13413
13421
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llmops/app",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3-beta.1",
|
|
4
4
|
"description": "LLMOps application with server and client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"motion": "^12.23.25",
|
|
65
65
|
"react-aria-components": "^1.13.0",
|
|
66
66
|
"react-hook-form": "^7.68.0",
|
|
67
|
-
"@llmops/core": "^0.1.
|
|
68
|
-
"@llmops/gateway": "^0.1.
|
|
67
|
+
"@llmops/core": "^0.1.3-beta.1",
|
|
68
|
+
"@llmops/gateway": "^0.1.3-beta.1"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
71
|
"react": "^19.2.1",
|