omnichatkit 0.0.22-b
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/LICENSE +201 -0
- package/README.md +545 -0
- package/dist/index.cjs +6184 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4385 -0
- package/dist/index.d.mts +4385 -0
- package/dist/index.mjs +6125 -0
- package/dist/index.mjs.map +1 -0
- package/dist/server/index.cjs +71 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +64 -0
- package/dist/server/index.d.mts +64 -0
- package/dist/server/index.mjs +70 -0
- package/dist/server/index.mjs.map +1 -0
- package/package.json +106 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let hono = require("hono");
|
|
3
|
+
let hono_vercel = require("hono/vercel");
|
|
4
|
+
let hono_bearer_auth = require("hono/bearer-auth");
|
|
5
|
+
let hono_jwt = require("hono/jwt");
|
|
6
|
+
//#region src/server/index.ts
|
|
7
|
+
/**
|
|
8
|
+
* Creates a single entrypoint route handler for Next.js App Router (or other Vercel platforms)
|
|
9
|
+
* that proxies requests to the OmniChat backend and handles authentication headers.
|
|
10
|
+
*/
|
|
11
|
+
function serveOmniChat(options = {}) {
|
|
12
|
+
const basePath = options.basePath || "/api";
|
|
13
|
+
const backendUrl = options.backendUrl || "";
|
|
14
|
+
const app = new hono.Hono().basePath(basePath);
|
|
15
|
+
if (options.security) {
|
|
16
|
+
const { security } = options;
|
|
17
|
+
if (security.customMiddleware) (Array.isArray(security.customMiddleware) ? security.customMiddleware : [security.customMiddleware]).forEach((m) => app.use("/*", m));
|
|
18
|
+
if (security.apiKey) app.use("/*", async (c, next) => {
|
|
19
|
+
const key = c.req.header("x-api-key");
|
|
20
|
+
if (!key) return c.json({ error: "Unauthorized: Missing x-api-key header" }, 401);
|
|
21
|
+
if (!(typeof security.apiKey === "function" ? await security.apiKey(key) : security.apiKey === key)) return c.json({ error: "Unauthorized: Invalid API Key" }, 401);
|
|
22
|
+
await next();
|
|
23
|
+
});
|
|
24
|
+
if (security.bearerToken) {
|
|
25
|
+
if (typeof security.bearerToken === "function") app.use("/*", (0, hono_bearer_auth.bearerAuth)({ verifyToken: security.bearerToken }));
|
|
26
|
+
else app.use("/*", (0, hono_bearer_auth.bearerAuth)({ token: security.bearerToken }));
|
|
27
|
+
}
|
|
28
|
+
if (security.jwt) app.use("/*", (0, hono_jwt.jwt)({
|
|
29
|
+
secret: security.jwt.secret,
|
|
30
|
+
alg: security.jwt.alg
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
app.all("/*", async (c) => {
|
|
34
|
+
const path = c.req.path.replace(basePath, "");
|
|
35
|
+
let targetUrlString = backendUrl;
|
|
36
|
+
if (targetUrlString.endsWith("/") && path.startsWith("/")) targetUrlString += path.slice(1);
|
|
37
|
+
else if (!targetUrlString.endsWith("/") && !path.startsWith("/")) targetUrlString += "/" + path;
|
|
38
|
+
else targetUrlString += path;
|
|
39
|
+
const targetUrl = new URL(targetUrlString);
|
|
40
|
+
const reqHeaders = new Headers(c.req.raw.headers);
|
|
41
|
+
let id = reqHeaders.get("x-user-id");
|
|
42
|
+
let encodedName = reqHeaders.get("x-user-name");
|
|
43
|
+
if (options.identifyUser) {
|
|
44
|
+
const identity = await options.identifyUser(c.req.raw);
|
|
45
|
+
if (identity.id) id = identity.id;
|
|
46
|
+
if (identity.name) encodedName = encodeURIComponent(identity.name);
|
|
47
|
+
}
|
|
48
|
+
reqHeaders.set("x-user-id", id || "demo-user");
|
|
49
|
+
reqHeaders.set("x-user-name", encodedName ? decodeURIComponent(encodedName) : "Demo User");
|
|
50
|
+
const req = new Request(targetUrl.toString(), {
|
|
51
|
+
method: c.req.method,
|
|
52
|
+
headers: reqHeaders,
|
|
53
|
+
body: c.req.raw.body,
|
|
54
|
+
redirect: "manual",
|
|
55
|
+
duplex: "half"
|
|
56
|
+
});
|
|
57
|
+
return fetch(req);
|
|
58
|
+
});
|
|
59
|
+
const handler = (0, hono_vercel.handle)(app);
|
|
60
|
+
return {
|
|
61
|
+
GET: handler,
|
|
62
|
+
POST: handler,
|
|
63
|
+
PATCH: handler,
|
|
64
|
+
PUT: handler,
|
|
65
|
+
DELETE: handler
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
exports.serveOmniChat = serveOmniChat;
|
|
70
|
+
|
|
71
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["Hono","bearerAuth","jwt","handle"],"sources":["../../src/server/index.ts"],"sourcesContent":["import { Hono } from \"hono\";\r\nimport { handle } from \"hono/vercel\";\r\nimport { bearerAuth } from \"hono/bearer-auth\";\r\nimport { jwt } from \"hono/jwt\";\r\nimport type { MiddlewareHandler } from \"hono\";\r\nimport type { SignatureAlgorithm } from \"hono/utils/jwt/jwa\";\r\n\r\nexport interface OmniChatServerOptions {\r\n /**\r\n * The target backend URL to proxy requests to.\r\n * Defaults to process.env.BACKEND_URL.\r\n */\r\n backendUrl?: string;\r\n /**\r\n * The base path for the API route. Defaults to \"/api\".\r\n */\r\n basePath?: string;\r\n /**\r\n * Optional custom logic to extract user identity from the request.\r\n */\r\n identifyUser?: (req: Request) => { id?: string; name?: string } | Promise<{ id?: string; name?: string }>;\r\n /**\r\n * Security options to protect the API route.\r\n */\r\n security?: {\r\n /**\r\n * Require a specific API Key in the `x-api-key` header.\r\n */\r\n apiKey?: string | ((key: string) => boolean | Promise<boolean>);\r\n /**\r\n * Require a Bearer token in the `Authorization` header.\r\n * Uses `hono/bearer-auth`.\r\n */\r\n bearerToken?: string | ((token: string) => boolean | Promise<boolean>);\r\n /**\r\n * Require a valid JWT token (often used for OAuth).\r\n * Uses `hono/jwt`.\r\n */\r\n jwt?: {\r\n secret: string;\r\n alg: SignatureAlgorithm | \"HS256\";\r\n };\r\n /**\r\n * Custom Hono middleware for custom security logic (e.g. custom OAuth providers, session checks).\r\n */\r\n customMiddleware?: MiddlewareHandler | MiddlewareHandler[];\r\n };\r\n}\r\n\r\n/**\r\n * Creates a single entrypoint route handler for Next.js App Router (or other Vercel platforms)\r\n * that proxies requests to the OmniChat backend and handles authentication headers.\r\n */\r\nexport function serveOmniChat(options: OmniChatServerOptions = {}) {\r\n const basePath = options.basePath || \"/api\";\r\n const backendUrl = options.backendUrl || \"\";\r\n\r\n const app = new Hono().basePath(basePath);\r\n\r\n // Apply Security Middleware\r\n if (options.security) {\r\n const { security } = options;\r\n\r\n // 1. Custom Middleware\r\n if (security.customMiddleware) {\r\n const middlewares = Array.isArray(security.customMiddleware)\r\n ? security.customMiddleware\r\n : [security.customMiddleware];\r\n middlewares.forEach((m) => app.use(\"/*\", m));\r\n }\r\n\r\n // 2. API Key Verification\r\n if (security.apiKey) {\r\n app.use(\"/*\", async (c, next) => {\r\n const key = c.req.header(\"x-api-key\");\r\n if (!key) return c.json({ error: \"Unauthorized: Missing x-api-key header\" }, 401);\r\n\r\n const isValid = typeof security.apiKey === \"function\"\r\n ? await security.apiKey(key)\r\n : security.apiKey === key;\r\n\r\n if (!isValid) return c.json({ error: \"Unauthorized: Invalid API Key\" }, 401);\r\n await next();\r\n });\r\n }\r\n\r\n // 3. Bearer Token Verification\r\n if (security.bearerToken) {\r\n if (typeof security.bearerToken === \"function\") {\r\n app.use(\"/*\", bearerAuth({ verifyToken: security.bearerToken }));\r\n } else {\r\n app.use(\"/*\", bearerAuth({ token: security.bearerToken }));\r\n }\r\n }\r\n\r\n // 4. JWT Validation\r\n if (security.jwt) {\r\n app.use(\"/*\", jwt({\r\n secret: security.jwt.secret,\r\n alg: security.jwt.alg\r\n }));\r\n }\r\n }\r\n\r\n app.all(\"/*\", async (c) => {\r\n // Proxy all requests to the backend URL\r\n const path = c.req.path.replace(basePath, \"\");\r\n\r\n // Ensure URL doesn't have double slashes if backendUrl ends with / and path starts with /\r\n let targetUrlString = backendUrl;\r\n if (targetUrlString.endsWith(\"/\") && path.startsWith(\"/\")) {\r\n targetUrlString += path.slice(1);\r\n } else if (!targetUrlString.endsWith(\"/\") && !path.startsWith(\"/\")) {\r\n targetUrlString += \"/\" + path;\r\n } else {\r\n targetUrlString += path;\r\n }\r\n\r\n const targetUrl = new URL(targetUrlString);\r\n const reqHeaders = new Headers(c.req.raw.headers);\r\n\r\n let id = reqHeaders.get(\"x-user-id\");\r\n let encodedName = reqHeaders.get(\"x-user-name\");\r\n\r\n // Allow overriding identity via custom function\r\n if (options.identifyUser) {\r\n const identity = await options.identifyUser(c.req.raw);\r\n if (identity.id) id = identity.id;\r\n if (identity.name) encodedName = encodeURIComponent(identity.name);\r\n }\r\n\r\n // Forward user identity headers (mimics CopilotKit identifyUser)\r\n reqHeaders.set(\"x-user-id\", id || \"demo-user\");\r\n reqHeaders.set(\"x-user-name\", encodedName ? decodeURIComponent(encodedName) : \"Demo User\");\r\n\r\n const req = new Request(targetUrl.toString(), {\r\n method: c.req.method,\r\n headers: reqHeaders,\r\n // body is a ReadableStream, which can be directly forwarded\r\n body: c.req.raw.body,\r\n redirect: \"manual\",\r\n // Needed for forwarding raw request body in Node.js\r\n // @ts-ignore\r\n duplex: \"half\"\r\n });\r\n\r\n return fetch(req);\r\n });\r\n\r\n const handler = handle(app);\r\n\r\n return {\r\n GET: handler,\r\n POST: handler,\r\n PATCH: handler,\r\n PUT: handler,\r\n DELETE: handler,\r\n };\r\n}\r\n"],"mappings":";;;;;;;;;;AAqDA,SAAgB,cAAc,UAAiC,CAAC,GAAG;CACjE,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,aAAa,QAAQ,cAAc;CAEzC,MAAM,MAAM,IAAIA,KAAAA,KAAK,CAAC,CAAC,SAAS,QAAQ;CAGxC,IAAI,QAAQ,UAAU;EACpB,MAAM,EAAE,aAAa;EAGrB,IAAI,SAAS,kBAIX,CAHoB,MAAM,QAAQ,SAAS,gBAAgB,IACvD,SAAS,mBACT,CAAC,SAAS,gBAAgB,EAAA,CAClB,SAAS,MAAM,IAAI,IAAI,MAAM,CAAC,CAAC;EAI7C,IAAI,SAAS,QACX,IAAI,IAAI,MAAM,OAAO,GAAG,SAAS;GAC/B,MAAM,MAAM,EAAE,IAAI,OAAO,WAAW;GACpC,IAAI,CAAC,KAAK,OAAO,EAAE,KAAK,EAAE,OAAO,yCAAyC,GAAG,GAAG;GAMhF,IAAI,EAJY,OAAO,SAAS,WAAW,aACvC,MAAM,SAAS,OAAO,GAAG,IACzB,SAAS,WAAW,MAEV,OAAO,EAAE,KAAK,EAAE,OAAO,gCAAgC,GAAG,GAAG;GAC3E,MAAM,KAAK;EACb,CAAC;EAIH,IAAI,SAAS,aAAa;GACxB,IAAI,OAAO,SAAS,gBAAgB,YAClC,IAAI,IAAI,OAAA,GAAMC,iBAAAA,WAAAA,CAAW,EAAE,aAAa,SAAS,YAAY,CAAC,CAAC;QAE/D,IAAI,IAAI,OAAA,GAAMA,iBAAAA,WAAAA,CAAW,EAAE,OAAO,SAAS,YAAY,CAAC,CAAC;EAE7D;EAGA,IAAI,SAAS,KACX,IAAI,IAAI,OAAA,GAAMC,SAAAA,IAAAA,CAAI;GAChB,QAAQ,SAAS,IAAI;GACrB,KAAK,SAAS,IAAI;EACpB,CAAC,CAAC;CAEN;CAEA,IAAI,IAAI,MAAM,OAAO,MAAM;EAEzB,MAAM,OAAO,EAAE,IAAI,KAAK,QAAQ,UAAU,EAAE;EAG5C,IAAI,kBAAkB;EACtB,IAAI,gBAAgB,SAAS,GAAG,KAAK,KAAK,WAAW,GAAG,GACtD,mBAAmB,KAAK,MAAM,CAAC;OAC1B,IAAI,CAAC,gBAAgB,SAAS,GAAG,KAAK,CAAC,KAAK,WAAW,GAAG,GAC/D,mBAAmB,MAAM;OAEzB,mBAAmB;EAGrB,MAAM,YAAY,IAAI,IAAI,eAAe;EACzC,MAAM,aAAa,IAAI,QAAQ,EAAE,IAAI,IAAI,OAAO;EAEhD,IAAI,KAAK,WAAW,IAAI,WAAW;EACnC,IAAI,cAAc,WAAW,IAAI,aAAa;EAG9C,IAAI,QAAQ,cAAc;GACxB,MAAM,WAAW,MAAM,QAAQ,aAAa,EAAE,IAAI,GAAG;GACrD,IAAI,SAAS,IAAI,KAAK,SAAS;GAC/B,IAAI,SAAS,MAAM,cAAc,mBAAmB,SAAS,IAAI;EACnE;EAGA,WAAW,IAAI,aAAa,MAAM,WAAW;EAC7C,WAAW,IAAI,eAAe,cAAc,mBAAmB,WAAW,IAAI,WAAW;EAEzF,MAAM,MAAM,IAAI,QAAQ,UAAU,SAAS,GAAG;GAC5C,QAAQ,EAAE,IAAI;GACd,SAAS;GAET,MAAM,EAAE,IAAI,IAAI;GAChB,UAAU;GAGV,QAAQ;EACV,CAAC;EAED,OAAO,MAAM,GAAG;CAClB,CAAC;CAED,MAAM,WAAA,GAAUC,YAAAA,OAAAA,CAAO,GAAG;CAE1B,OAAO;EACL,KAAK;EACL,MAAM;EACN,OAAO;EACP,KAAK;EACL,QAAQ;CACV;AACF"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { MiddlewareHandler } from "hono";
|
|
2
|
+
import { SignatureAlgorithm } from "hono/utils/jwt/jwa";
|
|
3
|
+
//#region src/server/index.d.ts
|
|
4
|
+
interface OmniChatServerOptions {
|
|
5
|
+
/**
|
|
6
|
+
* The target backend URL to proxy requests to.
|
|
7
|
+
* Defaults to process.env.BACKEND_URL.
|
|
8
|
+
*/
|
|
9
|
+
backendUrl?: string;
|
|
10
|
+
/**
|
|
11
|
+
* The base path for the API route. Defaults to "/api".
|
|
12
|
+
*/
|
|
13
|
+
basePath?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Optional custom logic to extract user identity from the request.
|
|
16
|
+
*/
|
|
17
|
+
identifyUser?: (req: Request) => {
|
|
18
|
+
id?: string;
|
|
19
|
+
name?: string;
|
|
20
|
+
} | Promise<{
|
|
21
|
+
id?: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* Security options to protect the API route.
|
|
26
|
+
*/
|
|
27
|
+
security?: {
|
|
28
|
+
/**
|
|
29
|
+
* Require a specific API Key in the `x-api-key` header.
|
|
30
|
+
*/
|
|
31
|
+
apiKey?: string | ((key: string) => boolean | Promise<boolean>);
|
|
32
|
+
/**
|
|
33
|
+
* Require a Bearer token in the `Authorization` header.
|
|
34
|
+
* Uses `hono/bearer-auth`.
|
|
35
|
+
*/
|
|
36
|
+
bearerToken?: string | ((token: string) => boolean | Promise<boolean>);
|
|
37
|
+
/**
|
|
38
|
+
* Require a valid JWT token (often used for OAuth).
|
|
39
|
+
* Uses `hono/jwt`.
|
|
40
|
+
*/
|
|
41
|
+
jwt?: {
|
|
42
|
+
secret: string;
|
|
43
|
+
alg: SignatureAlgorithm | "HS256";
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Custom Hono middleware for custom security logic (e.g. custom OAuth providers, session checks).
|
|
47
|
+
*/
|
|
48
|
+
customMiddleware?: MiddlewareHandler | MiddlewareHandler[];
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Creates a single entrypoint route handler for Next.js App Router (or other Vercel platforms)
|
|
53
|
+
* that proxies requests to the OmniChat backend and handles authentication headers.
|
|
54
|
+
*/
|
|
55
|
+
declare function serveOmniChat(options?: OmniChatServerOptions): {
|
|
56
|
+
GET: (req: Request) => Response | Promise<Response>;
|
|
57
|
+
POST: (req: Request) => Response | Promise<Response>;
|
|
58
|
+
PATCH: (req: Request) => Response | Promise<Response>;
|
|
59
|
+
PUT: (req: Request) => Response | Promise<Response>;
|
|
60
|
+
DELETE: (req: Request) => Response | Promise<Response>;
|
|
61
|
+
};
|
|
62
|
+
//#endregion
|
|
63
|
+
export { OmniChatServerOptions, serveOmniChat };
|
|
64
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { MiddlewareHandler } from "hono";
|
|
2
|
+
import { SignatureAlgorithm } from "hono/utils/jwt/jwa";
|
|
3
|
+
//#region src/server/index.d.ts
|
|
4
|
+
interface OmniChatServerOptions {
|
|
5
|
+
/**
|
|
6
|
+
* The target backend URL to proxy requests to.
|
|
7
|
+
* Defaults to process.env.BACKEND_URL.
|
|
8
|
+
*/
|
|
9
|
+
backendUrl?: string;
|
|
10
|
+
/**
|
|
11
|
+
* The base path for the API route. Defaults to "/api".
|
|
12
|
+
*/
|
|
13
|
+
basePath?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Optional custom logic to extract user identity from the request.
|
|
16
|
+
*/
|
|
17
|
+
identifyUser?: (req: Request) => {
|
|
18
|
+
id?: string;
|
|
19
|
+
name?: string;
|
|
20
|
+
} | Promise<{
|
|
21
|
+
id?: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* Security options to protect the API route.
|
|
26
|
+
*/
|
|
27
|
+
security?: {
|
|
28
|
+
/**
|
|
29
|
+
* Require a specific API Key in the `x-api-key` header.
|
|
30
|
+
*/
|
|
31
|
+
apiKey?: string | ((key: string) => boolean | Promise<boolean>);
|
|
32
|
+
/**
|
|
33
|
+
* Require a Bearer token in the `Authorization` header.
|
|
34
|
+
* Uses `hono/bearer-auth`.
|
|
35
|
+
*/
|
|
36
|
+
bearerToken?: string | ((token: string) => boolean | Promise<boolean>);
|
|
37
|
+
/**
|
|
38
|
+
* Require a valid JWT token (often used for OAuth).
|
|
39
|
+
* Uses `hono/jwt`.
|
|
40
|
+
*/
|
|
41
|
+
jwt?: {
|
|
42
|
+
secret: string;
|
|
43
|
+
alg: SignatureAlgorithm | "HS256";
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Custom Hono middleware for custom security logic (e.g. custom OAuth providers, session checks).
|
|
47
|
+
*/
|
|
48
|
+
customMiddleware?: MiddlewareHandler | MiddlewareHandler[];
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Creates a single entrypoint route handler for Next.js App Router (or other Vercel platforms)
|
|
53
|
+
* that proxies requests to the OmniChat backend and handles authentication headers.
|
|
54
|
+
*/
|
|
55
|
+
declare function serveOmniChat(options?: OmniChatServerOptions): {
|
|
56
|
+
GET: (req: Request) => Response | Promise<Response>;
|
|
57
|
+
POST: (req: Request) => Response | Promise<Response>;
|
|
58
|
+
PATCH: (req: Request) => Response | Promise<Response>;
|
|
59
|
+
PUT: (req: Request) => Response | Promise<Response>;
|
|
60
|
+
DELETE: (req: Request) => Response | Promise<Response>;
|
|
61
|
+
};
|
|
62
|
+
//#endregion
|
|
63
|
+
export { OmniChatServerOptions, serveOmniChat };
|
|
64
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { handle } from "hono/vercel";
|
|
3
|
+
import { bearerAuth } from "hono/bearer-auth";
|
|
4
|
+
import { jwt } from "hono/jwt";
|
|
5
|
+
//#region src/server/index.ts
|
|
6
|
+
/**
|
|
7
|
+
* Creates a single entrypoint route handler for Next.js App Router (or other Vercel platforms)
|
|
8
|
+
* that proxies requests to the OmniChat backend and handles authentication headers.
|
|
9
|
+
*/
|
|
10
|
+
function serveOmniChat(options = {}) {
|
|
11
|
+
const basePath = options.basePath || "/api";
|
|
12
|
+
const backendUrl = options.backendUrl || "";
|
|
13
|
+
const app = new Hono().basePath(basePath);
|
|
14
|
+
if (options.security) {
|
|
15
|
+
const { security } = options;
|
|
16
|
+
if (security.customMiddleware) (Array.isArray(security.customMiddleware) ? security.customMiddleware : [security.customMiddleware]).forEach((m) => app.use("/*", m));
|
|
17
|
+
if (security.apiKey) app.use("/*", async (c, next) => {
|
|
18
|
+
const key = c.req.header("x-api-key");
|
|
19
|
+
if (!key) return c.json({ error: "Unauthorized: Missing x-api-key header" }, 401);
|
|
20
|
+
if (!(typeof security.apiKey === "function" ? await security.apiKey(key) : security.apiKey === key)) return c.json({ error: "Unauthorized: Invalid API Key" }, 401);
|
|
21
|
+
await next();
|
|
22
|
+
});
|
|
23
|
+
if (security.bearerToken) {
|
|
24
|
+
if (typeof security.bearerToken === "function") app.use("/*", bearerAuth({ verifyToken: security.bearerToken }));
|
|
25
|
+
else app.use("/*", bearerAuth({ token: security.bearerToken }));
|
|
26
|
+
}
|
|
27
|
+
if (security.jwt) app.use("/*", jwt({
|
|
28
|
+
secret: security.jwt.secret,
|
|
29
|
+
alg: security.jwt.alg
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
app.all("/*", async (c) => {
|
|
33
|
+
const path = c.req.path.replace(basePath, "");
|
|
34
|
+
let targetUrlString = backendUrl;
|
|
35
|
+
if (targetUrlString.endsWith("/") && path.startsWith("/")) targetUrlString += path.slice(1);
|
|
36
|
+
else if (!targetUrlString.endsWith("/") && !path.startsWith("/")) targetUrlString += "/" + path;
|
|
37
|
+
else targetUrlString += path;
|
|
38
|
+
const targetUrl = new URL(targetUrlString);
|
|
39
|
+
const reqHeaders = new Headers(c.req.raw.headers);
|
|
40
|
+
let id = reqHeaders.get("x-user-id");
|
|
41
|
+
let encodedName = reqHeaders.get("x-user-name");
|
|
42
|
+
if (options.identifyUser) {
|
|
43
|
+
const identity = await options.identifyUser(c.req.raw);
|
|
44
|
+
if (identity.id) id = identity.id;
|
|
45
|
+
if (identity.name) encodedName = encodeURIComponent(identity.name);
|
|
46
|
+
}
|
|
47
|
+
reqHeaders.set("x-user-id", id || "demo-user");
|
|
48
|
+
reqHeaders.set("x-user-name", encodedName ? decodeURIComponent(encodedName) : "Demo User");
|
|
49
|
+
const req = new Request(targetUrl.toString(), {
|
|
50
|
+
method: c.req.method,
|
|
51
|
+
headers: reqHeaders,
|
|
52
|
+
body: c.req.raw.body,
|
|
53
|
+
redirect: "manual",
|
|
54
|
+
duplex: "half"
|
|
55
|
+
});
|
|
56
|
+
return fetch(req);
|
|
57
|
+
});
|
|
58
|
+
const handler = handle(app);
|
|
59
|
+
return {
|
|
60
|
+
GET: handler,
|
|
61
|
+
POST: handler,
|
|
62
|
+
PATCH: handler,
|
|
63
|
+
PUT: handler,
|
|
64
|
+
DELETE: handler
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
export { serveOmniChat };
|
|
69
|
+
|
|
70
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/server/index.ts"],"sourcesContent":["import { Hono } from \"hono\";\r\nimport { handle } from \"hono/vercel\";\r\nimport { bearerAuth } from \"hono/bearer-auth\";\r\nimport { jwt } from \"hono/jwt\";\r\nimport type { MiddlewareHandler } from \"hono\";\r\nimport type { SignatureAlgorithm } from \"hono/utils/jwt/jwa\";\r\n\r\nexport interface OmniChatServerOptions {\r\n /**\r\n * The target backend URL to proxy requests to.\r\n * Defaults to process.env.BACKEND_URL.\r\n */\r\n backendUrl?: string;\r\n /**\r\n * The base path for the API route. Defaults to \"/api\".\r\n */\r\n basePath?: string;\r\n /**\r\n * Optional custom logic to extract user identity from the request.\r\n */\r\n identifyUser?: (req: Request) => { id?: string; name?: string } | Promise<{ id?: string; name?: string }>;\r\n /**\r\n * Security options to protect the API route.\r\n */\r\n security?: {\r\n /**\r\n * Require a specific API Key in the `x-api-key` header.\r\n */\r\n apiKey?: string | ((key: string) => boolean | Promise<boolean>);\r\n /**\r\n * Require a Bearer token in the `Authorization` header.\r\n * Uses `hono/bearer-auth`.\r\n */\r\n bearerToken?: string | ((token: string) => boolean | Promise<boolean>);\r\n /**\r\n * Require a valid JWT token (often used for OAuth).\r\n * Uses `hono/jwt`.\r\n */\r\n jwt?: {\r\n secret: string;\r\n alg: SignatureAlgorithm | \"HS256\";\r\n };\r\n /**\r\n * Custom Hono middleware for custom security logic (e.g. custom OAuth providers, session checks).\r\n */\r\n customMiddleware?: MiddlewareHandler | MiddlewareHandler[];\r\n };\r\n}\r\n\r\n/**\r\n * Creates a single entrypoint route handler for Next.js App Router (or other Vercel platforms)\r\n * that proxies requests to the OmniChat backend and handles authentication headers.\r\n */\r\nexport function serveOmniChat(options: OmniChatServerOptions = {}) {\r\n const basePath = options.basePath || \"/api\";\r\n const backendUrl = options.backendUrl || \"\";\r\n\r\n const app = new Hono().basePath(basePath);\r\n\r\n // Apply Security Middleware\r\n if (options.security) {\r\n const { security } = options;\r\n\r\n // 1. Custom Middleware\r\n if (security.customMiddleware) {\r\n const middlewares = Array.isArray(security.customMiddleware)\r\n ? security.customMiddleware\r\n : [security.customMiddleware];\r\n middlewares.forEach((m) => app.use(\"/*\", m));\r\n }\r\n\r\n // 2. API Key Verification\r\n if (security.apiKey) {\r\n app.use(\"/*\", async (c, next) => {\r\n const key = c.req.header(\"x-api-key\");\r\n if (!key) return c.json({ error: \"Unauthorized: Missing x-api-key header\" }, 401);\r\n\r\n const isValid = typeof security.apiKey === \"function\"\r\n ? await security.apiKey(key)\r\n : security.apiKey === key;\r\n\r\n if (!isValid) return c.json({ error: \"Unauthorized: Invalid API Key\" }, 401);\r\n await next();\r\n });\r\n }\r\n\r\n // 3. Bearer Token Verification\r\n if (security.bearerToken) {\r\n if (typeof security.bearerToken === \"function\") {\r\n app.use(\"/*\", bearerAuth({ verifyToken: security.bearerToken }));\r\n } else {\r\n app.use(\"/*\", bearerAuth({ token: security.bearerToken }));\r\n }\r\n }\r\n\r\n // 4. JWT Validation\r\n if (security.jwt) {\r\n app.use(\"/*\", jwt({\r\n secret: security.jwt.secret,\r\n alg: security.jwt.alg\r\n }));\r\n }\r\n }\r\n\r\n app.all(\"/*\", async (c) => {\r\n // Proxy all requests to the backend URL\r\n const path = c.req.path.replace(basePath, \"\");\r\n\r\n // Ensure URL doesn't have double slashes if backendUrl ends with / and path starts with /\r\n let targetUrlString = backendUrl;\r\n if (targetUrlString.endsWith(\"/\") && path.startsWith(\"/\")) {\r\n targetUrlString += path.slice(1);\r\n } else if (!targetUrlString.endsWith(\"/\") && !path.startsWith(\"/\")) {\r\n targetUrlString += \"/\" + path;\r\n } else {\r\n targetUrlString += path;\r\n }\r\n\r\n const targetUrl = new URL(targetUrlString);\r\n const reqHeaders = new Headers(c.req.raw.headers);\r\n\r\n let id = reqHeaders.get(\"x-user-id\");\r\n let encodedName = reqHeaders.get(\"x-user-name\");\r\n\r\n // Allow overriding identity via custom function\r\n if (options.identifyUser) {\r\n const identity = await options.identifyUser(c.req.raw);\r\n if (identity.id) id = identity.id;\r\n if (identity.name) encodedName = encodeURIComponent(identity.name);\r\n }\r\n\r\n // Forward user identity headers (mimics CopilotKit identifyUser)\r\n reqHeaders.set(\"x-user-id\", id || \"demo-user\");\r\n reqHeaders.set(\"x-user-name\", encodedName ? decodeURIComponent(encodedName) : \"Demo User\");\r\n\r\n const req = new Request(targetUrl.toString(), {\r\n method: c.req.method,\r\n headers: reqHeaders,\r\n // body is a ReadableStream, which can be directly forwarded\r\n body: c.req.raw.body,\r\n redirect: \"manual\",\r\n // Needed for forwarding raw request body in Node.js\r\n // @ts-ignore\r\n duplex: \"half\"\r\n });\r\n\r\n return fetch(req);\r\n });\r\n\r\n const handler = handle(app);\r\n\r\n return {\r\n GET: handler,\r\n POST: handler,\r\n PATCH: handler,\r\n PUT: handler,\r\n DELETE: handler,\r\n };\r\n}\r\n"],"mappings":";;;;;;;;;AAqDA,SAAgB,cAAc,UAAiC,CAAC,GAAG;CACjE,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,aAAa,QAAQ,cAAc;CAEzC,MAAM,MAAM,IAAI,KAAK,CAAC,CAAC,SAAS,QAAQ;CAGxC,IAAI,QAAQ,UAAU;EACpB,MAAM,EAAE,aAAa;EAGrB,IAAI,SAAS,kBAIX,CAHoB,MAAM,QAAQ,SAAS,gBAAgB,IACvD,SAAS,mBACT,CAAC,SAAS,gBAAgB,EAAA,CAClB,SAAS,MAAM,IAAI,IAAI,MAAM,CAAC,CAAC;EAI7C,IAAI,SAAS,QACX,IAAI,IAAI,MAAM,OAAO,GAAG,SAAS;GAC/B,MAAM,MAAM,EAAE,IAAI,OAAO,WAAW;GACpC,IAAI,CAAC,KAAK,OAAO,EAAE,KAAK,EAAE,OAAO,yCAAyC,GAAG,GAAG;GAMhF,IAAI,EAJY,OAAO,SAAS,WAAW,aACvC,MAAM,SAAS,OAAO,GAAG,IACzB,SAAS,WAAW,MAEV,OAAO,EAAE,KAAK,EAAE,OAAO,gCAAgC,GAAG,GAAG;GAC3E,MAAM,KAAK;EACb,CAAC;EAIH,IAAI,SAAS,aAAa;GACxB,IAAI,OAAO,SAAS,gBAAgB,YAClC,IAAI,IAAI,MAAM,WAAW,EAAE,aAAa,SAAS,YAAY,CAAC,CAAC;QAE/D,IAAI,IAAI,MAAM,WAAW,EAAE,OAAO,SAAS,YAAY,CAAC,CAAC;EAE7D;EAGA,IAAI,SAAS,KACX,IAAI,IAAI,MAAM,IAAI;GAChB,QAAQ,SAAS,IAAI;GACrB,KAAK,SAAS,IAAI;EACpB,CAAC,CAAC;CAEN;CAEA,IAAI,IAAI,MAAM,OAAO,MAAM;EAEzB,MAAM,OAAO,EAAE,IAAI,KAAK,QAAQ,UAAU,EAAE;EAG5C,IAAI,kBAAkB;EACtB,IAAI,gBAAgB,SAAS,GAAG,KAAK,KAAK,WAAW,GAAG,GACtD,mBAAmB,KAAK,MAAM,CAAC;OAC1B,IAAI,CAAC,gBAAgB,SAAS,GAAG,KAAK,CAAC,KAAK,WAAW,GAAG,GAC/D,mBAAmB,MAAM;OAEzB,mBAAmB;EAGrB,MAAM,YAAY,IAAI,IAAI,eAAe;EACzC,MAAM,aAAa,IAAI,QAAQ,EAAE,IAAI,IAAI,OAAO;EAEhD,IAAI,KAAK,WAAW,IAAI,WAAW;EACnC,IAAI,cAAc,WAAW,IAAI,aAAa;EAG9C,IAAI,QAAQ,cAAc;GACxB,MAAM,WAAW,MAAM,QAAQ,aAAa,EAAE,IAAI,GAAG;GACrD,IAAI,SAAS,IAAI,KAAK,SAAS;GAC/B,IAAI,SAAS,MAAM,cAAc,mBAAmB,SAAS,IAAI;EACnE;EAGA,WAAW,IAAI,aAAa,MAAM,WAAW;EAC7C,WAAW,IAAI,eAAe,cAAc,mBAAmB,WAAW,IAAI,WAAW;EAEzF,MAAM,MAAM,IAAI,QAAQ,UAAU,SAAS,GAAG;GAC5C,QAAQ,EAAE,IAAI;GACd,SAAS;GAET,MAAM,EAAE,IAAI,IAAI;GAChB,UAAU;GAGV,QAAQ;EACV,CAAC;EAED,OAAO,MAAM,GAAG;CAClB,CAAC;CAED,MAAM,UAAU,OAAO,GAAG;CAE1B,OAAO;EACL,KAAK;EACL,MAAM;EACN,OAAO;EACP,KAAK;EACL,QAAQ;CACV;AACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "omnichatkit",
|
|
3
|
+
"version": "0.0.22-b",
|
|
4
|
+
"description": "A modular React component library for building AG-UI based AI chat interfaces with native Generative UI(A2UI) and Shadcn styling.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"omnichatkit",
|
|
7
|
+
"react",
|
|
8
|
+
"nextjs",
|
|
9
|
+
"ai-chat",
|
|
10
|
+
"generative-ui",
|
|
11
|
+
"chat-components",
|
|
12
|
+
"llm-ui",
|
|
13
|
+
"a2ui",
|
|
14
|
+
"chatbot",
|
|
15
|
+
"conversational-ui",
|
|
16
|
+
"rsc"
|
|
17
|
+
],
|
|
18
|
+
"homepage": "https://github.com/ethan-x11/omnichatkit#readme",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/ethan-x11/omnichatkit/issues"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/ethan-x11/omnichatkit.git"
|
|
25
|
+
},
|
|
26
|
+
"license": "Apache-2.0",
|
|
27
|
+
"author": "ethan-x11",
|
|
28
|
+
"type": "module",
|
|
29
|
+
"main": "./dist/index.cjs",
|
|
30
|
+
"module": "./dist/index.mjs",
|
|
31
|
+
"types": "./dist/index.d.mts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"import": {
|
|
35
|
+
"types": "./dist/index.d.mts",
|
|
36
|
+
"default": "./dist/index.mjs"
|
|
37
|
+
},
|
|
38
|
+
"require": {
|
|
39
|
+
"types": "./dist/index.d.cts",
|
|
40
|
+
"default": "./dist/index.cjs"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"./server": {
|
|
44
|
+
"import": {
|
|
45
|
+
"types": "./dist/server/index.d.mts",
|
|
46
|
+
"default": "./dist/server/index.mjs"
|
|
47
|
+
},
|
|
48
|
+
"require": {
|
|
49
|
+
"types": "./dist/server/index.d.cts",
|
|
50
|
+
"default": "./dist/server/index.cjs"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"files": [
|
|
55
|
+
"dist"
|
|
56
|
+
],
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsdown",
|
|
59
|
+
"dev": "tsdown --watch",
|
|
60
|
+
"lint": "tsc --noEmit",
|
|
61
|
+
"prepublishOnly": "npm pkg delete devDependencies",
|
|
62
|
+
"postpublish": "git checkout -- package.json",
|
|
63
|
+
"prepare": "yarn build"
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"react": "^19.0.0",
|
|
67
|
+
"react-dom": "^19.0.0"
|
|
68
|
+
},
|
|
69
|
+
"dependencies": {
|
|
70
|
+
"@ag-ui/client": "^0.0.59",
|
|
71
|
+
"@ag-ui/core": "^0.0.59",
|
|
72
|
+
"@ai-sdk/react": "^1.1.25",
|
|
73
|
+
"@base-ui/react": "^1.7.0",
|
|
74
|
+
"@radix-ui/react-dialog": "^1.1.1",
|
|
75
|
+
"@radix-ui/react-scroll-area": "^1.1.0",
|
|
76
|
+
"@radix-ui/react-slot": "^1.1.0",
|
|
77
|
+
"@shadcn/react": "^0.3.0",
|
|
78
|
+
"@tailwindcss/typography": "^0.5.20",
|
|
79
|
+
"ai": "^3.1.3",
|
|
80
|
+
"class-variance-authority": "^0.7.0",
|
|
81
|
+
"clsx": "^2.1.1",
|
|
82
|
+
"cmdk": "^1.1.1",
|
|
83
|
+
"embla-carousel-react": "^8.6.0",
|
|
84
|
+
"hono": "^4.13.5",
|
|
85
|
+
"input-otp": "^1.5.0",
|
|
86
|
+
"katex": "^0.18.4",
|
|
87
|
+
"lucide-react": "^0.436.0",
|
|
88
|
+
"overlayscrollbars": "^2.16.0",
|
|
89
|
+
"overlayscrollbars-react": "^0.5.6",
|
|
90
|
+
"react-day-picker": "^10.0.1",
|
|
91
|
+
"react-markdown": "^10.1.0",
|
|
92
|
+
"react-resizable-panels": "^4.12.3",
|
|
93
|
+
"react-syntax-highlighter": "^16.1.1",
|
|
94
|
+
"react-textarea-autosize": "^8.5.9",
|
|
95
|
+
"recharts": "^3.10.1",
|
|
96
|
+
"rehype-katex": "^7.0.1",
|
|
97
|
+
"rehype-raw": "^7.0.0",
|
|
98
|
+
"remark-gfm": "^4.0.1",
|
|
99
|
+
"remark-math": "^6.0.0",
|
|
100
|
+
"sonner": "^2.0.8",
|
|
101
|
+
"tailwind-merge": "^2.5.2",
|
|
102
|
+
"vaul": "^1.1.2",
|
|
103
|
+
"zod": "^3.23.8",
|
|
104
|
+
"zustand": "^4.5.5"
|
|
105
|
+
}
|
|
106
|
+
}
|