@visgate-ai/server-proxy 0.1.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/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # @visgate-ai/server-proxy
2
+
3
+ Server-side proxy for the [Visgate API](https://visgateai.com). Keeps your API key on the server so the client never sees it.
4
+
5
+ - **Framework-agnostic core:** `proxyToVisgate(request, options)` — use with any Node server.
6
+ - **Next.js:** Drop-in route handlers; one line to mount the proxy.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install @visgate-ai/server-proxy
12
+ ```
13
+
14
+ ## Environment
15
+
16
+ On the server, set:
17
+
18
+ - **VISGATE_API_KEY** (required) — your Visgate API key (`vg-...`).
19
+ - **VISGATE_BASE_URL** (optional) — defaults to `https://visgateai.com/api/v1`.
20
+
21
+ **BYOK (Bring Your Own Key):** To use provider keys on the server (so the client never sends them), set:
22
+
23
+ - **VISGATE_FAL_KEY** or **FAL_KEY** — Fal API key.
24
+ - **VISGATE_REPLICATE_KEY** or **REPLICATE_API_TOKEN** — Replicate API token.
25
+ - **VISGATE_RUNWAY_KEY** or **RUNWAY_API_KEY** — Runway API key.
26
+
27
+ The proxy injects these headers when the client does not send them.
28
+
29
+ ## Next.js (App Router)
30
+
31
+ 1. Create the route file:
32
+
33
+ **`app/api/visgate/[...path]/route.ts`**
34
+
35
+ ```ts
36
+ // Video generation can take several minutes; set maxDuration to avoid 502 Bad Gateway.
37
+ export const maxDuration = 300;
38
+
39
+ export { GET, POST, PUT, DELETE, OPTIONS } from "@visgate-ai/server-proxy/next";
40
+ ```
41
+
42
+ 2. In your client (browser), use the Visgate SDK with `proxyUrl`:
43
+
44
+ ```ts
45
+ import { Client } from "@visgate-ai/client";
46
+
47
+ const client = new Client({ proxyUrl: "/api/visgate" });
48
+ const result = await client.generate("a sunset");
49
+ ```
50
+
51
+ No API key in the client — the proxy adds it on the server.
52
+
53
+ For **video generation**, use a longer client timeout (e.g. 5 minutes) so the request does not abort before the API responds:
54
+
55
+ ```ts
56
+ const client = new Client({ proxyUrl: "/api/visgate", timeout: 300_000 });
57
+ const result = await client.videos.generate("fal-ai/veo3", "a sunset");
58
+ ```
59
+
60
+ ## Core API (any framework)
61
+
62
+ ```ts
63
+ import { proxyToVisgate } from "@visgate-ai/server-proxy";
64
+
65
+ // In your handler (e.g. Express, Hono, etc.):
66
+ const response = await proxyToVisgate(request, {
67
+ pathSegments: ["health"], // or ["videos", "generate"], ["images", "generate"], etc.
68
+ // apiKey: process.env.VISGATE_API_KEY (default)
69
+ // baseUrl: process.env.VISGATE_BASE_URL (default)
70
+ // timeoutMs: 300000 (default 5 min; increase for very long video jobs)
71
+ });
72
+ // Return response to the client
73
+ ```
74
+
75
+ ## License
76
+
77
+ MIT
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Framework-agnostic proxy: forward Request to Visgate and return Response.
3
+ * Uses VISGATE_API_KEY (or options.apiKey) on the server; no key is sent from the client.
4
+ */
5
+ /** Default upstream request timeout (5 min). Use for long-running calls like video generation. */
6
+ declare const DEFAULT_UPSTREAM_TIMEOUT_MS = 300000;
7
+ interface ProxyOptions {
8
+ /** API key (default: process.env.VISGATE_API_KEY) */
9
+ apiKey?: string;
10
+ /** Visgate API base URL (default: https://visgateai.com/api/v1) */
11
+ baseUrl?: string;
12
+ /** Path segments to append to baseUrl (e.g. ["health"] or ["images", "generate"]) */
13
+ pathSegments: string[];
14
+ /** Timeout in ms for the request to Visgate (default: 300000). Set higher for very long video jobs. */
15
+ timeoutMs?: number;
16
+ }
17
+ /**
18
+ * Forward the incoming request to Visgate and return the response.
19
+ * Call this from your framework (Next.js, Express, etc.) with the request and path.
20
+ */
21
+ declare function proxyToVisgate(request: Request, options: ProxyOptions): Promise<Response>;
22
+
23
+ export { DEFAULT_UPSTREAM_TIMEOUT_MS, type ProxyOptions, proxyToVisgate };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Framework-agnostic proxy: forward Request to Visgate and return Response.
3
+ * Uses VISGATE_API_KEY (or options.apiKey) on the server; no key is sent from the client.
4
+ */
5
+ /** Default upstream request timeout (5 min). Use for long-running calls like video generation. */
6
+ declare const DEFAULT_UPSTREAM_TIMEOUT_MS = 300000;
7
+ interface ProxyOptions {
8
+ /** API key (default: process.env.VISGATE_API_KEY) */
9
+ apiKey?: string;
10
+ /** Visgate API base URL (default: https://visgateai.com/api/v1) */
11
+ baseUrl?: string;
12
+ /** Path segments to append to baseUrl (e.g. ["health"] or ["images", "generate"]) */
13
+ pathSegments: string[];
14
+ /** Timeout in ms for the request to Visgate (default: 300000). Set higher for very long video jobs. */
15
+ timeoutMs?: number;
16
+ }
17
+ /**
18
+ * Forward the incoming request to Visgate and return the response.
19
+ * Call this from your framework (Next.js, Express, etc.) with the request and path.
20
+ */
21
+ declare function proxyToVisgate(request: Request, options: ProxyOptions): Promise<Response>;
22
+
23
+ export { DEFAULT_UPSTREAM_TIMEOUT_MS, type ProxyOptions, proxyToVisgate };
package/dist/index.js ADDED
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFAULT_UPSTREAM_TIMEOUT_MS: () => DEFAULT_UPSTREAM_TIMEOUT_MS,
24
+ proxyToVisgate: () => proxyToVisgate
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/proxy.ts
29
+ var DEFAULT_BASE_URL = "https://visgateai.com/api/v1";
30
+ var DEFAULT_UPSTREAM_TIMEOUT_MS = 3e5;
31
+ function corsHeaders(request) {
32
+ const origin = request.headers.get("origin");
33
+ return {
34
+ "Access-Control-Allow-Origin": origin || "*",
35
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
36
+ "Access-Control-Allow-Headers": "Content-Type, Authorization"
37
+ };
38
+ }
39
+ async function proxyToVisgate(request, options) {
40
+ const authHeader = request.headers.get("Authorization");
41
+ const keyFromRequest = authHeader && /^Bearer\s+/i.test(authHeader) ? authHeader.replace(/^Bearer\s+/i, "").trim() : null;
42
+ const apiKey = keyFromRequest ?? options.apiKey ?? process.env.VISGATE_API_KEY;
43
+ if (!apiKey) {
44
+ return new Response(
45
+ JSON.stringify({ error: "VISGATE_API_KEY not set on server and no API key in request" }),
46
+ {
47
+ status: 500,
48
+ headers: { "Content-Type": "application/json", ...corsHeaders(request) }
49
+ }
50
+ );
51
+ }
52
+ const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
53
+ const pathStr = options.pathSegments.join("/");
54
+ const url = `${baseUrl}/${pathStr}`;
55
+ const search = request.url.includes("?") ? request.url.slice(request.url.indexOf("?")) : "";
56
+ const headers = new Headers();
57
+ request.headers.forEach((value, key) => {
58
+ const lower = key.toLowerCase();
59
+ if (lower === "authorization" || lower === "host") return;
60
+ headers.set(key, value);
61
+ });
62
+ headers.set("Authorization", `Bearer ${apiKey}`);
63
+ if (!headers.has("X-Fal-Key")) {
64
+ const falKey = process.env.VISGATE_FAL_KEY ?? process.env.FAL_KEY;
65
+ if (falKey) headers.set("X-Fal-Key", falKey);
66
+ }
67
+ if (!headers.has("X-Replicate-Key")) {
68
+ const replicateKey = process.env.VISGATE_REPLICATE_KEY ?? process.env.REPLICATE_API_TOKEN;
69
+ if (replicateKey) headers.set("X-Replicate-Key", replicateKey);
70
+ }
71
+ if (!headers.has("X-Runway-Key")) {
72
+ const runwayKey = process.env.VISGATE_RUNWAY_KEY ?? process.env.RUNWAY_API_KEY;
73
+ if (runwayKey) headers.set("X-Runway-Key", runwayKey);
74
+ }
75
+ const body = request.method !== "GET" && request.method !== "HEAD" ? await request.text() : void 0;
76
+ const timeoutMs = options.timeoutMs ?? DEFAULT_UPSTREAM_TIMEOUT_MS;
77
+ const controller = new AbortController();
78
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
79
+ let res;
80
+ try {
81
+ res = await fetch(url + search, {
82
+ method: request.method,
83
+ headers,
84
+ body,
85
+ signal: controller.signal
86
+ });
87
+ } catch (err) {
88
+ clearTimeout(timeoutId);
89
+ const message = err instanceof Error ? err.message : String(err);
90
+ const isTimeout = err instanceof Error && err.name === "AbortError";
91
+ return new Response(
92
+ JSON.stringify({
93
+ error: isTimeout ? "GATEWAY_TIMEOUT" : "BAD_GATEWAY",
94
+ message: isTimeout ? `Upstream request timed out after ${timeoutMs}ms` : `Upstream request failed: ${message}`
95
+ }),
96
+ {
97
+ status: isTimeout ? 504 : 502,
98
+ headers: { "Content-Type": "application/json", ...corsHeaders(request) }
99
+ }
100
+ );
101
+ }
102
+ clearTimeout(timeoutId);
103
+ const text = await res.text();
104
+ const resHeaders = new Headers();
105
+ res.headers.forEach((value, key) => {
106
+ const lower = key.toLowerCase();
107
+ if (lower === "transfer-encoding" || lower === "content-encoding" || lower === "content-length") return;
108
+ resHeaders.set(key, value);
109
+ });
110
+ Object.entries(corsHeaders(request)).forEach(([k, v]) => resHeaders.set(k, v));
111
+ return new Response(text, { status: res.status, headers: resHeaders });
112
+ }
113
+ // Annotate the CommonJS export names for ESM import in node:
114
+ 0 && (module.exports = {
115
+ DEFAULT_UPSTREAM_TIMEOUT_MS,
116
+ proxyToVisgate
117
+ });
118
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/proxy.ts"],"sourcesContent":["export {\n proxyToVisgate,\n DEFAULT_UPSTREAM_TIMEOUT_MS,\n type ProxyOptions,\n} from \"./proxy\";\n","/**\n * Framework-agnostic proxy: forward Request to Visgate and return Response.\n * Uses VISGATE_API_KEY (or options.apiKey) on the server; no key is sent from the client.\n */\n\nconst DEFAULT_BASE_URL = \"https://visgateai.com/api/v1\";\n\n/** Default upstream request timeout (5 min). Use for long-running calls like video generation. */\nexport const DEFAULT_UPSTREAM_TIMEOUT_MS = 300_000;\n\nexport interface ProxyOptions {\n /** API key (default: process.env.VISGATE_API_KEY) */\n apiKey?: string;\n /** Visgate API base URL (default: https://visgateai.com/api/v1) */\n baseUrl?: string;\n /** Path segments to append to baseUrl (e.g. [\"health\"] or [\"images\", \"generate\"]) */\n pathSegments: string[];\n /** Timeout in ms for the request to Visgate (default: 300000). Set higher for very long video jobs. */\n timeoutMs?: number;\n}\n\nfunction corsHeaders(request: Request): Record<string, string> {\n const origin = request.headers.get(\"origin\");\n return {\n \"Access-Control-Allow-Origin\": origin || \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n };\n}\n\n/**\n * Forward the incoming request to Visgate and return the response.\n * Call this from your framework (Next.js, Express, etc.) with the request and path.\n */\nexport async function proxyToVisgate(request: Request, options: ProxyOptions): Promise<Response> {\n // Use API key from request (client sends it when using proxy + apiKey), then options, then env\n const authHeader = request.headers.get(\"Authorization\");\n const keyFromRequest =\n authHeader && /^Bearer\\s+/i.test(authHeader) ? authHeader.replace(/^Bearer\\s+/i, \"\").trim() : null;\n const apiKey = keyFromRequest ?? options.apiKey ?? process.env.VISGATE_API_KEY;\n if (!apiKey) {\n return new Response(\n JSON.stringify({ error: \"VISGATE_API_KEY not set on server and no API key in request\" }),\n {\n status: 500,\n headers: { \"Content-Type\": \"application/json\", ...corsHeaders(request) },\n }\n );\n }\n\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n const pathStr = options.pathSegments.join(\"/\");\n const url = `${baseUrl}/${pathStr}`;\n const search = request.url.includes(\"?\") ? request.url.slice(request.url.indexOf(\"?\")) : \"\";\n\n const headers = new Headers();\n request.headers.forEach((value, key) => {\n const lower = key.toLowerCase();\n if (lower === \"authorization\" || lower === \"host\") return;\n headers.set(key, value);\n });\n headers.set(\"Authorization\", `Bearer ${apiKey}`);\n\n // Add provider keys from server env when not sent by client (BYOK for video/image)\n if (!headers.has(\"X-Fal-Key\")) {\n const falKey = process.env.VISGATE_FAL_KEY ?? process.env.FAL_KEY;\n if (falKey) headers.set(\"X-Fal-Key\", falKey);\n }\n if (!headers.has(\"X-Replicate-Key\")) {\n const replicateKey = process.env.VISGATE_REPLICATE_KEY ?? process.env.REPLICATE_API_TOKEN;\n if (replicateKey) headers.set(\"X-Replicate-Key\", replicateKey);\n }\n if (!headers.has(\"X-Runway-Key\")) {\n const runwayKey = process.env.VISGATE_RUNWAY_KEY ?? process.env.RUNWAY_API_KEY;\n if (runwayKey) headers.set(\"X-Runway-Key\", runwayKey);\n }\n\n const body =\n request.method !== \"GET\" && request.method !== \"HEAD\" ? await request.text() : undefined;\n const timeoutMs = options.timeoutMs ?? DEFAULT_UPSTREAM_TIMEOUT_MS;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n let res: Response;\n try {\n res = await fetch(url + search, {\n method: request.method,\n headers,\n body,\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timeoutId);\n const message = err instanceof Error ? err.message : String(err);\n const isTimeout = err instanceof Error && err.name === \"AbortError\";\n return new Response(\n JSON.stringify({\n error: isTimeout ? \"GATEWAY_TIMEOUT\" : \"BAD_GATEWAY\",\n message: isTimeout\n ? `Upstream request timed out after ${timeoutMs}ms`\n : `Upstream request failed: ${message}`,\n }),\n {\n status: isTimeout ? 504 : 502,\n headers: { \"Content-Type\": \"application/json\", ...corsHeaders(request) },\n }\n );\n }\n clearTimeout(timeoutId);\n\n // res.text() decompresses automatically; do not forward Content-Encoding or\n // the browser will try to decode again and fail with ERR_CONTENT_DECODING_FAILED.\n const text = await res.text();\n const resHeaders = new Headers();\n res.headers.forEach((value, key) => {\n const lower = key.toLowerCase();\n if (lower === \"transfer-encoding\" || lower === \"content-encoding\" || lower === \"content-length\") return;\n resHeaders.set(key, value);\n });\n Object.entries(corsHeaders(request)).forEach(([k, v]) => resHeaders.set(k, v));\n\n return new Response(text, { status: res.status, headers: resHeaders });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACKA,IAAM,mBAAmB;AAGlB,IAAM,8BAA8B;AAa3C,SAAS,YAAY,SAA0C;AAC7D,QAAM,SAAS,QAAQ,QAAQ,IAAI,QAAQ;AAC3C,SAAO;AAAA,IACL,+BAA+B,UAAU;AAAA,IACzC,gCAAgC;AAAA,IAChC,gCAAgC;AAAA,EAClC;AACF;AAMA,eAAsB,eAAe,SAAkB,SAA0C;AAE/F,QAAM,aAAa,QAAQ,QAAQ,IAAI,eAAe;AACtD,QAAM,iBACJ,cAAc,cAAc,KAAK,UAAU,IAAI,WAAW,QAAQ,eAAe,EAAE,EAAE,KAAK,IAAI;AAChG,QAAM,SAAS,kBAAkB,QAAQ,UAAU,QAAQ,IAAI;AAC/D,MAAI,CAAC,QAAQ;AACX,WAAO,IAAI;AAAA,MACT,KAAK,UAAU,EAAE,OAAO,8DAA8D,CAAC;AAAA,MACvF;AAAA,QACE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,oBAAoB,GAAG,YAAY,OAAO,EAAE;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,QAAQ,WAAW,kBAAkB,QAAQ,OAAO,EAAE;AACvE,QAAM,UAAU,QAAQ,aAAa,KAAK,GAAG;AAC7C,QAAM,MAAM,GAAG,OAAO,IAAI,OAAO;AACjC,QAAM,SAAS,QAAQ,IAAI,SAAS,GAAG,IAAI,QAAQ,IAAI,MAAM,QAAQ,IAAI,QAAQ,GAAG,CAAC,IAAI;AAEzF,QAAM,UAAU,IAAI,QAAQ;AAC5B,UAAQ,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AACtC,UAAM,QAAQ,IAAI,YAAY;AAC9B,QAAI,UAAU,mBAAmB,UAAU,OAAQ;AACnD,YAAQ,IAAI,KAAK,KAAK;AAAA,EACxB,CAAC;AACD,UAAQ,IAAI,iBAAiB,UAAU,MAAM,EAAE;AAG/C,MAAI,CAAC,QAAQ,IAAI,WAAW,GAAG;AAC7B,UAAM,SAAS,QAAQ,IAAI,mBAAmB,QAAQ,IAAI;AAC1D,QAAI,OAAQ,SAAQ,IAAI,aAAa,MAAM;AAAA,EAC7C;AACA,MAAI,CAAC,QAAQ,IAAI,iBAAiB,GAAG;AACnC,UAAM,eAAe,QAAQ,IAAI,yBAAyB,QAAQ,IAAI;AACtE,QAAI,aAAc,SAAQ,IAAI,mBAAmB,YAAY;AAAA,EAC/D;AACA,MAAI,CAAC,QAAQ,IAAI,cAAc,GAAG;AAChC,UAAM,YAAY,QAAQ,IAAI,sBAAsB,QAAQ,IAAI;AAChE,QAAI,UAAW,SAAQ,IAAI,gBAAgB,SAAS;AAAA,EACtD;AAEA,QAAM,OACJ,QAAQ,WAAW,SAAS,QAAQ,WAAW,SAAS,MAAM,QAAQ,KAAK,IAAI;AACjF,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAEhE,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,QAAQ;AAAA,MAC9B,QAAQ,QAAQ;AAAA,MAChB;AAAA,MACA;AAAA,MACA,QAAQ,WAAW;AAAA,IACrB,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,iBAAa,SAAS;AACtB,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,UAAM,YAAY,eAAe,SAAS,IAAI,SAAS;AACvD,WAAO,IAAI;AAAA,MACT,KAAK,UAAU;AAAA,QACb,OAAO,YAAY,oBAAoB;AAAA,QACvC,SAAS,YACL,oCAAoC,SAAS,OAC7C,4BAA4B,OAAO;AAAA,MACzC,CAAC;AAAA,MACD;AAAA,QACE,QAAQ,YAAY,MAAM;AAAA,QAC1B,SAAS,EAAE,gBAAgB,oBAAoB,GAAG,YAAY,OAAO,EAAE;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AACA,eAAa,SAAS;AAItB,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAM,aAAa,IAAI,QAAQ;AAC/B,MAAI,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAClC,UAAM,QAAQ,IAAI,YAAY;AAC9B,QAAI,UAAU,uBAAuB,UAAU,sBAAsB,UAAU,iBAAkB;AACjG,eAAW,IAAI,KAAK,KAAK;AAAA,EAC3B,CAAC;AACD,SAAO,QAAQ,YAAY,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,WAAW,IAAI,GAAG,CAAC,CAAC;AAE7E,SAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,QAAQ,SAAS,WAAW,CAAC;AACvE;","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,90 @@
1
+ // src/proxy.ts
2
+ var DEFAULT_BASE_URL = "https://visgateai.com/api/v1";
3
+ var DEFAULT_UPSTREAM_TIMEOUT_MS = 3e5;
4
+ function corsHeaders(request) {
5
+ const origin = request.headers.get("origin");
6
+ return {
7
+ "Access-Control-Allow-Origin": origin || "*",
8
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
9
+ "Access-Control-Allow-Headers": "Content-Type, Authorization"
10
+ };
11
+ }
12
+ async function proxyToVisgate(request, options) {
13
+ const authHeader = request.headers.get("Authorization");
14
+ const keyFromRequest = authHeader && /^Bearer\s+/i.test(authHeader) ? authHeader.replace(/^Bearer\s+/i, "").trim() : null;
15
+ const apiKey = keyFromRequest ?? options.apiKey ?? process.env.VISGATE_API_KEY;
16
+ if (!apiKey) {
17
+ return new Response(
18
+ JSON.stringify({ error: "VISGATE_API_KEY not set on server and no API key in request" }),
19
+ {
20
+ status: 500,
21
+ headers: { "Content-Type": "application/json", ...corsHeaders(request) }
22
+ }
23
+ );
24
+ }
25
+ const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
26
+ const pathStr = options.pathSegments.join("/");
27
+ const url = `${baseUrl}/${pathStr}`;
28
+ const search = request.url.includes("?") ? request.url.slice(request.url.indexOf("?")) : "";
29
+ const headers = new Headers();
30
+ request.headers.forEach((value, key) => {
31
+ const lower = key.toLowerCase();
32
+ if (lower === "authorization" || lower === "host") return;
33
+ headers.set(key, value);
34
+ });
35
+ headers.set("Authorization", `Bearer ${apiKey}`);
36
+ if (!headers.has("X-Fal-Key")) {
37
+ const falKey = process.env.VISGATE_FAL_KEY ?? process.env.FAL_KEY;
38
+ if (falKey) headers.set("X-Fal-Key", falKey);
39
+ }
40
+ if (!headers.has("X-Replicate-Key")) {
41
+ const replicateKey = process.env.VISGATE_REPLICATE_KEY ?? process.env.REPLICATE_API_TOKEN;
42
+ if (replicateKey) headers.set("X-Replicate-Key", replicateKey);
43
+ }
44
+ if (!headers.has("X-Runway-Key")) {
45
+ const runwayKey = process.env.VISGATE_RUNWAY_KEY ?? process.env.RUNWAY_API_KEY;
46
+ if (runwayKey) headers.set("X-Runway-Key", runwayKey);
47
+ }
48
+ const body = request.method !== "GET" && request.method !== "HEAD" ? await request.text() : void 0;
49
+ const timeoutMs = options.timeoutMs ?? DEFAULT_UPSTREAM_TIMEOUT_MS;
50
+ const controller = new AbortController();
51
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
52
+ let res;
53
+ try {
54
+ res = await fetch(url + search, {
55
+ method: request.method,
56
+ headers,
57
+ body,
58
+ signal: controller.signal
59
+ });
60
+ } catch (err) {
61
+ clearTimeout(timeoutId);
62
+ const message = err instanceof Error ? err.message : String(err);
63
+ const isTimeout = err instanceof Error && err.name === "AbortError";
64
+ return new Response(
65
+ JSON.stringify({
66
+ error: isTimeout ? "GATEWAY_TIMEOUT" : "BAD_GATEWAY",
67
+ message: isTimeout ? `Upstream request timed out after ${timeoutMs}ms` : `Upstream request failed: ${message}`
68
+ }),
69
+ {
70
+ status: isTimeout ? 504 : 502,
71
+ headers: { "Content-Type": "application/json", ...corsHeaders(request) }
72
+ }
73
+ );
74
+ }
75
+ clearTimeout(timeoutId);
76
+ const text = await res.text();
77
+ const resHeaders = new Headers();
78
+ res.headers.forEach((value, key) => {
79
+ const lower = key.toLowerCase();
80
+ if (lower === "transfer-encoding" || lower === "content-encoding" || lower === "content-length") return;
81
+ resHeaders.set(key, value);
82
+ });
83
+ Object.entries(corsHeaders(request)).forEach(([k, v]) => resHeaders.set(k, v));
84
+ return new Response(text, { status: res.status, headers: resHeaders });
85
+ }
86
+ export {
87
+ DEFAULT_UPSTREAM_TIMEOUT_MS,
88
+ proxyToVisgate
89
+ };
90
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/proxy.ts"],"sourcesContent":["/**\n * Framework-agnostic proxy: forward Request to Visgate and return Response.\n * Uses VISGATE_API_KEY (or options.apiKey) on the server; no key is sent from the client.\n */\n\nconst DEFAULT_BASE_URL = \"https://visgateai.com/api/v1\";\n\n/** Default upstream request timeout (5 min). Use for long-running calls like video generation. */\nexport const DEFAULT_UPSTREAM_TIMEOUT_MS = 300_000;\n\nexport interface ProxyOptions {\n /** API key (default: process.env.VISGATE_API_KEY) */\n apiKey?: string;\n /** Visgate API base URL (default: https://visgateai.com/api/v1) */\n baseUrl?: string;\n /** Path segments to append to baseUrl (e.g. [\"health\"] or [\"images\", \"generate\"]) */\n pathSegments: string[];\n /** Timeout in ms for the request to Visgate (default: 300000). Set higher for very long video jobs. */\n timeoutMs?: number;\n}\n\nfunction corsHeaders(request: Request): Record<string, string> {\n const origin = request.headers.get(\"origin\");\n return {\n \"Access-Control-Allow-Origin\": origin || \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n };\n}\n\n/**\n * Forward the incoming request to Visgate and return the response.\n * Call this from your framework (Next.js, Express, etc.) with the request and path.\n */\nexport async function proxyToVisgate(request: Request, options: ProxyOptions): Promise<Response> {\n // Use API key from request (client sends it when using proxy + apiKey), then options, then env\n const authHeader = request.headers.get(\"Authorization\");\n const keyFromRequest =\n authHeader && /^Bearer\\s+/i.test(authHeader) ? authHeader.replace(/^Bearer\\s+/i, \"\").trim() : null;\n const apiKey = keyFromRequest ?? options.apiKey ?? process.env.VISGATE_API_KEY;\n if (!apiKey) {\n return new Response(\n JSON.stringify({ error: \"VISGATE_API_KEY not set on server and no API key in request\" }),\n {\n status: 500,\n headers: { \"Content-Type\": \"application/json\", ...corsHeaders(request) },\n }\n );\n }\n\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n const pathStr = options.pathSegments.join(\"/\");\n const url = `${baseUrl}/${pathStr}`;\n const search = request.url.includes(\"?\") ? request.url.slice(request.url.indexOf(\"?\")) : \"\";\n\n const headers = new Headers();\n request.headers.forEach((value, key) => {\n const lower = key.toLowerCase();\n if (lower === \"authorization\" || lower === \"host\") return;\n headers.set(key, value);\n });\n headers.set(\"Authorization\", `Bearer ${apiKey}`);\n\n // Add provider keys from server env when not sent by client (BYOK for video/image)\n if (!headers.has(\"X-Fal-Key\")) {\n const falKey = process.env.VISGATE_FAL_KEY ?? process.env.FAL_KEY;\n if (falKey) headers.set(\"X-Fal-Key\", falKey);\n }\n if (!headers.has(\"X-Replicate-Key\")) {\n const replicateKey = process.env.VISGATE_REPLICATE_KEY ?? process.env.REPLICATE_API_TOKEN;\n if (replicateKey) headers.set(\"X-Replicate-Key\", replicateKey);\n }\n if (!headers.has(\"X-Runway-Key\")) {\n const runwayKey = process.env.VISGATE_RUNWAY_KEY ?? process.env.RUNWAY_API_KEY;\n if (runwayKey) headers.set(\"X-Runway-Key\", runwayKey);\n }\n\n const body =\n request.method !== \"GET\" && request.method !== \"HEAD\" ? await request.text() : undefined;\n const timeoutMs = options.timeoutMs ?? DEFAULT_UPSTREAM_TIMEOUT_MS;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n let res: Response;\n try {\n res = await fetch(url + search, {\n method: request.method,\n headers,\n body,\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timeoutId);\n const message = err instanceof Error ? err.message : String(err);\n const isTimeout = err instanceof Error && err.name === \"AbortError\";\n return new Response(\n JSON.stringify({\n error: isTimeout ? \"GATEWAY_TIMEOUT\" : \"BAD_GATEWAY\",\n message: isTimeout\n ? `Upstream request timed out after ${timeoutMs}ms`\n : `Upstream request failed: ${message}`,\n }),\n {\n status: isTimeout ? 504 : 502,\n headers: { \"Content-Type\": \"application/json\", ...corsHeaders(request) },\n }\n );\n }\n clearTimeout(timeoutId);\n\n // res.text() decompresses automatically; do not forward Content-Encoding or\n // the browser will try to decode again and fail with ERR_CONTENT_DECODING_FAILED.\n const text = await res.text();\n const resHeaders = new Headers();\n res.headers.forEach((value, key) => {\n const lower = key.toLowerCase();\n if (lower === \"transfer-encoding\" || lower === \"content-encoding\" || lower === \"content-length\") return;\n resHeaders.set(key, value);\n });\n Object.entries(corsHeaders(request)).forEach(([k, v]) => resHeaders.set(k, v));\n\n return new Response(text, { status: res.status, headers: resHeaders });\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Next.js App Router handlers for Visgate proxy.
3
+ * Use in app/api/visgate/[...path]/route.ts:
4
+ * export { GET, POST, PUT, DELETE, OPTIONS } from "@visgate-ai/server-proxy/next";
5
+ */
6
+ type NextContext = {
7
+ params: Promise<{
8
+ path: string[];
9
+ }>;
10
+ };
11
+ declare function GET(request: Request, context: NextContext): Promise<Response>;
12
+ declare function POST(request: Request, context: NextContext): Promise<Response>;
13
+ declare function PUT(request: Request, context: NextContext): Promise<Response>;
14
+ declare function DELETE(request: Request, context: NextContext): Promise<Response>;
15
+ declare function OPTIONS(): Response;
16
+
17
+ export { DELETE, GET, OPTIONS, POST, PUT };
package/dist/next.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Next.js App Router handlers for Visgate proxy.
3
+ * Use in app/api/visgate/[...path]/route.ts:
4
+ * export { GET, POST, PUT, DELETE, OPTIONS } from "@visgate-ai/server-proxy/next";
5
+ */
6
+ type NextContext = {
7
+ params: Promise<{
8
+ path: string[];
9
+ }>;
10
+ };
11
+ declare function GET(request: Request, context: NextContext): Promise<Response>;
12
+ declare function POST(request: Request, context: NextContext): Promise<Response>;
13
+ declare function PUT(request: Request, context: NextContext): Promise<Response>;
14
+ declare function DELETE(request: Request, context: NextContext): Promise<Response>;
15
+ declare function OPTIONS(): Response;
16
+
17
+ export { DELETE, GET, OPTIONS, POST, PUT };
package/dist/next.js ADDED
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/next.ts
21
+ var next_exports = {};
22
+ __export(next_exports, {
23
+ DELETE: () => DELETE,
24
+ GET: () => GET,
25
+ OPTIONS: () => OPTIONS,
26
+ POST: () => POST,
27
+ PUT: () => PUT
28
+ });
29
+ module.exports = __toCommonJS(next_exports);
30
+
31
+ // src/proxy.ts
32
+ var DEFAULT_BASE_URL = "https://visgateai.com/api/v1";
33
+ var DEFAULT_UPSTREAM_TIMEOUT_MS = 3e5;
34
+ function corsHeaders(request) {
35
+ const origin = request.headers.get("origin");
36
+ return {
37
+ "Access-Control-Allow-Origin": origin || "*",
38
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
39
+ "Access-Control-Allow-Headers": "Content-Type, Authorization"
40
+ };
41
+ }
42
+ async function proxyToVisgate(request, options) {
43
+ const authHeader = request.headers.get("Authorization");
44
+ const keyFromRequest = authHeader && /^Bearer\s+/i.test(authHeader) ? authHeader.replace(/^Bearer\s+/i, "").trim() : null;
45
+ const apiKey = keyFromRequest ?? options.apiKey ?? process.env.VISGATE_API_KEY;
46
+ if (!apiKey) {
47
+ return new Response(
48
+ JSON.stringify({ error: "VISGATE_API_KEY not set on server and no API key in request" }),
49
+ {
50
+ status: 500,
51
+ headers: { "Content-Type": "application/json", ...corsHeaders(request) }
52
+ }
53
+ );
54
+ }
55
+ const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
56
+ const pathStr = options.pathSegments.join("/");
57
+ const url = `${baseUrl}/${pathStr}`;
58
+ const search = request.url.includes("?") ? request.url.slice(request.url.indexOf("?")) : "";
59
+ const headers = new Headers();
60
+ request.headers.forEach((value, key) => {
61
+ const lower = key.toLowerCase();
62
+ if (lower === "authorization" || lower === "host") return;
63
+ headers.set(key, value);
64
+ });
65
+ headers.set("Authorization", `Bearer ${apiKey}`);
66
+ if (!headers.has("X-Fal-Key")) {
67
+ const falKey = process.env.VISGATE_FAL_KEY ?? process.env.FAL_KEY;
68
+ if (falKey) headers.set("X-Fal-Key", falKey);
69
+ }
70
+ if (!headers.has("X-Replicate-Key")) {
71
+ const replicateKey = process.env.VISGATE_REPLICATE_KEY ?? process.env.REPLICATE_API_TOKEN;
72
+ if (replicateKey) headers.set("X-Replicate-Key", replicateKey);
73
+ }
74
+ if (!headers.has("X-Runway-Key")) {
75
+ const runwayKey = process.env.VISGATE_RUNWAY_KEY ?? process.env.RUNWAY_API_KEY;
76
+ if (runwayKey) headers.set("X-Runway-Key", runwayKey);
77
+ }
78
+ const body = request.method !== "GET" && request.method !== "HEAD" ? await request.text() : void 0;
79
+ const timeoutMs = options.timeoutMs ?? DEFAULT_UPSTREAM_TIMEOUT_MS;
80
+ const controller = new AbortController();
81
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
82
+ let res;
83
+ try {
84
+ res = await fetch(url + search, {
85
+ method: request.method,
86
+ headers,
87
+ body,
88
+ signal: controller.signal
89
+ });
90
+ } catch (err) {
91
+ clearTimeout(timeoutId);
92
+ const message = err instanceof Error ? err.message : String(err);
93
+ const isTimeout = err instanceof Error && err.name === "AbortError";
94
+ return new Response(
95
+ JSON.stringify({
96
+ error: isTimeout ? "GATEWAY_TIMEOUT" : "BAD_GATEWAY",
97
+ message: isTimeout ? `Upstream request timed out after ${timeoutMs}ms` : `Upstream request failed: ${message}`
98
+ }),
99
+ {
100
+ status: isTimeout ? 504 : 502,
101
+ headers: { "Content-Type": "application/json", ...corsHeaders(request) }
102
+ }
103
+ );
104
+ }
105
+ clearTimeout(timeoutId);
106
+ const text = await res.text();
107
+ const resHeaders = new Headers();
108
+ res.headers.forEach((value, key) => {
109
+ const lower = key.toLowerCase();
110
+ if (lower === "transfer-encoding" || lower === "content-encoding" || lower === "content-length") return;
111
+ resHeaders.set(key, value);
112
+ });
113
+ Object.entries(corsHeaders(request)).forEach(([k, v]) => resHeaders.set(k, v));
114
+ return new Response(text, { status: res.status, headers: resHeaders });
115
+ }
116
+
117
+ // src/next.ts
118
+ async function handle(request, context) {
119
+ const { path } = await context.params;
120
+ return proxyToVisgate(request, { pathSegments: path });
121
+ }
122
+ var CORS_HEADERS = {
123
+ "Access-Control-Allow-Origin": "*",
124
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
125
+ "Access-Control-Allow-Headers": "Content-Type, Authorization"
126
+ };
127
+ function GET(request, context) {
128
+ return handle(request, context);
129
+ }
130
+ function POST(request, context) {
131
+ return handle(request, context);
132
+ }
133
+ function PUT(request, context) {
134
+ return handle(request, context);
135
+ }
136
+ function DELETE(request, context) {
137
+ return handle(request, context);
138
+ }
139
+ function OPTIONS() {
140
+ return new Response(null, { status: 204, headers: CORS_HEADERS });
141
+ }
142
+ // Annotate the CommonJS export names for ESM import in node:
143
+ 0 && (module.exports = {
144
+ DELETE,
145
+ GET,
146
+ OPTIONS,
147
+ POST,
148
+ PUT
149
+ });
150
+ //# sourceMappingURL=next.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/next.ts","../src/proxy.ts"],"sourcesContent":["/**\n * Next.js App Router handlers for Visgate proxy.\n * Use in app/api/visgate/[...path]/route.ts:\n * export { GET, POST, PUT, DELETE, OPTIONS } from \"@visgate-ai/server-proxy/next\";\n */\n\nimport { proxyToVisgate } from \"./proxy\";\n\ntype NextContext = { params: Promise<{ path: string[] }> };\n\nasync function handle(request: Request, context: NextContext): Promise<Response> {\n const { path } = await context.params;\n return proxyToVisgate(request, { pathSegments: path });\n}\n\nconst CORS_HEADERS = {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n};\n\nexport function GET(request: Request, context: NextContext): Promise<Response> {\n return handle(request, context);\n}\n\nexport function POST(request: Request, context: NextContext): Promise<Response> {\n return handle(request, context);\n}\n\nexport function PUT(request: Request, context: NextContext): Promise<Response> {\n return handle(request, context);\n}\n\nexport function DELETE(request: Request, context: NextContext): Promise<Response> {\n return handle(request, context);\n}\n\nexport function OPTIONS(): Response {\n return new Response(null, { status: 204, headers: CORS_HEADERS });\n}\n","/**\n * Framework-agnostic proxy: forward Request to Visgate and return Response.\n * Uses VISGATE_API_KEY (or options.apiKey) on the server; no key is sent from the client.\n */\n\nconst DEFAULT_BASE_URL = \"https://visgateai.com/api/v1\";\n\n/** Default upstream request timeout (5 min). Use for long-running calls like video generation. */\nexport const DEFAULT_UPSTREAM_TIMEOUT_MS = 300_000;\n\nexport interface ProxyOptions {\n /** API key (default: process.env.VISGATE_API_KEY) */\n apiKey?: string;\n /** Visgate API base URL (default: https://visgateai.com/api/v1) */\n baseUrl?: string;\n /** Path segments to append to baseUrl (e.g. [\"health\"] or [\"images\", \"generate\"]) */\n pathSegments: string[];\n /** Timeout in ms for the request to Visgate (default: 300000). Set higher for very long video jobs. */\n timeoutMs?: number;\n}\n\nfunction corsHeaders(request: Request): Record<string, string> {\n const origin = request.headers.get(\"origin\");\n return {\n \"Access-Control-Allow-Origin\": origin || \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n };\n}\n\n/**\n * Forward the incoming request to Visgate and return the response.\n * Call this from your framework (Next.js, Express, etc.) with the request and path.\n */\nexport async function proxyToVisgate(request: Request, options: ProxyOptions): Promise<Response> {\n // Use API key from request (client sends it when using proxy + apiKey), then options, then env\n const authHeader = request.headers.get(\"Authorization\");\n const keyFromRequest =\n authHeader && /^Bearer\\s+/i.test(authHeader) ? authHeader.replace(/^Bearer\\s+/i, \"\").trim() : null;\n const apiKey = keyFromRequest ?? options.apiKey ?? process.env.VISGATE_API_KEY;\n if (!apiKey) {\n return new Response(\n JSON.stringify({ error: \"VISGATE_API_KEY not set on server and no API key in request\" }),\n {\n status: 500,\n headers: { \"Content-Type\": \"application/json\", ...corsHeaders(request) },\n }\n );\n }\n\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n const pathStr = options.pathSegments.join(\"/\");\n const url = `${baseUrl}/${pathStr}`;\n const search = request.url.includes(\"?\") ? request.url.slice(request.url.indexOf(\"?\")) : \"\";\n\n const headers = new Headers();\n request.headers.forEach((value, key) => {\n const lower = key.toLowerCase();\n if (lower === \"authorization\" || lower === \"host\") return;\n headers.set(key, value);\n });\n headers.set(\"Authorization\", `Bearer ${apiKey}`);\n\n // Add provider keys from server env when not sent by client (BYOK for video/image)\n if (!headers.has(\"X-Fal-Key\")) {\n const falKey = process.env.VISGATE_FAL_KEY ?? process.env.FAL_KEY;\n if (falKey) headers.set(\"X-Fal-Key\", falKey);\n }\n if (!headers.has(\"X-Replicate-Key\")) {\n const replicateKey = process.env.VISGATE_REPLICATE_KEY ?? process.env.REPLICATE_API_TOKEN;\n if (replicateKey) headers.set(\"X-Replicate-Key\", replicateKey);\n }\n if (!headers.has(\"X-Runway-Key\")) {\n const runwayKey = process.env.VISGATE_RUNWAY_KEY ?? process.env.RUNWAY_API_KEY;\n if (runwayKey) headers.set(\"X-Runway-Key\", runwayKey);\n }\n\n const body =\n request.method !== \"GET\" && request.method !== \"HEAD\" ? await request.text() : undefined;\n const timeoutMs = options.timeoutMs ?? DEFAULT_UPSTREAM_TIMEOUT_MS;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n let res: Response;\n try {\n res = await fetch(url + search, {\n method: request.method,\n headers,\n body,\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timeoutId);\n const message = err instanceof Error ? err.message : String(err);\n const isTimeout = err instanceof Error && err.name === \"AbortError\";\n return new Response(\n JSON.stringify({\n error: isTimeout ? \"GATEWAY_TIMEOUT\" : \"BAD_GATEWAY\",\n message: isTimeout\n ? `Upstream request timed out after ${timeoutMs}ms`\n : `Upstream request failed: ${message}`,\n }),\n {\n status: isTimeout ? 504 : 502,\n headers: { \"Content-Type\": \"application/json\", ...corsHeaders(request) },\n }\n );\n }\n clearTimeout(timeoutId);\n\n // res.text() decompresses automatically; do not forward Content-Encoding or\n // the browser will try to decode again and fail with ERR_CONTENT_DECODING_FAILED.\n const text = await res.text();\n const resHeaders = new Headers();\n res.headers.forEach((value, key) => {\n const lower = key.toLowerCase();\n if (lower === \"transfer-encoding\" || lower === \"content-encoding\" || lower === \"content-length\") return;\n resHeaders.set(key, value);\n });\n Object.entries(corsHeaders(request)).forEach(([k, v]) => resHeaders.set(k, v));\n\n return new Response(text, { status: res.status, headers: resHeaders });\n}\n"],"mappings":"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","names":[]}
package/dist/next.mjs ADDED
@@ -0,0 +1,119 @@
1
+ // src/proxy.ts
2
+ var DEFAULT_BASE_URL = "https://visgateai.com/api/v1";
3
+ var DEFAULT_UPSTREAM_TIMEOUT_MS = 3e5;
4
+ function corsHeaders(request) {
5
+ const origin = request.headers.get("origin");
6
+ return {
7
+ "Access-Control-Allow-Origin": origin || "*",
8
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
9
+ "Access-Control-Allow-Headers": "Content-Type, Authorization"
10
+ };
11
+ }
12
+ async function proxyToVisgate(request, options) {
13
+ const authHeader = request.headers.get("Authorization");
14
+ const keyFromRequest = authHeader && /^Bearer\s+/i.test(authHeader) ? authHeader.replace(/^Bearer\s+/i, "").trim() : null;
15
+ const apiKey = keyFromRequest ?? options.apiKey ?? process.env.VISGATE_API_KEY;
16
+ if (!apiKey) {
17
+ return new Response(
18
+ JSON.stringify({ error: "VISGATE_API_KEY not set on server and no API key in request" }),
19
+ {
20
+ status: 500,
21
+ headers: { "Content-Type": "application/json", ...corsHeaders(request) }
22
+ }
23
+ );
24
+ }
25
+ const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
26
+ const pathStr = options.pathSegments.join("/");
27
+ const url = `${baseUrl}/${pathStr}`;
28
+ const search = request.url.includes("?") ? request.url.slice(request.url.indexOf("?")) : "";
29
+ const headers = new Headers();
30
+ request.headers.forEach((value, key) => {
31
+ const lower = key.toLowerCase();
32
+ if (lower === "authorization" || lower === "host") return;
33
+ headers.set(key, value);
34
+ });
35
+ headers.set("Authorization", `Bearer ${apiKey}`);
36
+ if (!headers.has("X-Fal-Key")) {
37
+ const falKey = process.env.VISGATE_FAL_KEY ?? process.env.FAL_KEY;
38
+ if (falKey) headers.set("X-Fal-Key", falKey);
39
+ }
40
+ if (!headers.has("X-Replicate-Key")) {
41
+ const replicateKey = process.env.VISGATE_REPLICATE_KEY ?? process.env.REPLICATE_API_TOKEN;
42
+ if (replicateKey) headers.set("X-Replicate-Key", replicateKey);
43
+ }
44
+ if (!headers.has("X-Runway-Key")) {
45
+ const runwayKey = process.env.VISGATE_RUNWAY_KEY ?? process.env.RUNWAY_API_KEY;
46
+ if (runwayKey) headers.set("X-Runway-Key", runwayKey);
47
+ }
48
+ const body = request.method !== "GET" && request.method !== "HEAD" ? await request.text() : void 0;
49
+ const timeoutMs = options.timeoutMs ?? DEFAULT_UPSTREAM_TIMEOUT_MS;
50
+ const controller = new AbortController();
51
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
52
+ let res;
53
+ try {
54
+ res = await fetch(url + search, {
55
+ method: request.method,
56
+ headers,
57
+ body,
58
+ signal: controller.signal
59
+ });
60
+ } catch (err) {
61
+ clearTimeout(timeoutId);
62
+ const message = err instanceof Error ? err.message : String(err);
63
+ const isTimeout = err instanceof Error && err.name === "AbortError";
64
+ return new Response(
65
+ JSON.stringify({
66
+ error: isTimeout ? "GATEWAY_TIMEOUT" : "BAD_GATEWAY",
67
+ message: isTimeout ? `Upstream request timed out after ${timeoutMs}ms` : `Upstream request failed: ${message}`
68
+ }),
69
+ {
70
+ status: isTimeout ? 504 : 502,
71
+ headers: { "Content-Type": "application/json", ...corsHeaders(request) }
72
+ }
73
+ );
74
+ }
75
+ clearTimeout(timeoutId);
76
+ const text = await res.text();
77
+ const resHeaders = new Headers();
78
+ res.headers.forEach((value, key) => {
79
+ const lower = key.toLowerCase();
80
+ if (lower === "transfer-encoding" || lower === "content-encoding" || lower === "content-length") return;
81
+ resHeaders.set(key, value);
82
+ });
83
+ Object.entries(corsHeaders(request)).forEach(([k, v]) => resHeaders.set(k, v));
84
+ return new Response(text, { status: res.status, headers: resHeaders });
85
+ }
86
+
87
+ // src/next.ts
88
+ async function handle(request, context) {
89
+ const { path } = await context.params;
90
+ return proxyToVisgate(request, { pathSegments: path });
91
+ }
92
+ var CORS_HEADERS = {
93
+ "Access-Control-Allow-Origin": "*",
94
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
95
+ "Access-Control-Allow-Headers": "Content-Type, Authorization"
96
+ };
97
+ function GET(request, context) {
98
+ return handle(request, context);
99
+ }
100
+ function POST(request, context) {
101
+ return handle(request, context);
102
+ }
103
+ function PUT(request, context) {
104
+ return handle(request, context);
105
+ }
106
+ function DELETE(request, context) {
107
+ return handle(request, context);
108
+ }
109
+ function OPTIONS() {
110
+ return new Response(null, { status: 204, headers: CORS_HEADERS });
111
+ }
112
+ export {
113
+ DELETE,
114
+ GET,
115
+ OPTIONS,
116
+ POST,
117
+ PUT
118
+ };
119
+ //# sourceMappingURL=next.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/proxy.ts","../src/next.ts"],"sourcesContent":["/**\n * Framework-agnostic proxy: forward Request to Visgate and return Response.\n * Uses VISGATE_API_KEY (or options.apiKey) on the server; no key is sent from the client.\n */\n\nconst DEFAULT_BASE_URL = \"https://visgateai.com/api/v1\";\n\n/** Default upstream request timeout (5 min). Use for long-running calls like video generation. */\nexport const DEFAULT_UPSTREAM_TIMEOUT_MS = 300_000;\n\nexport interface ProxyOptions {\n /** API key (default: process.env.VISGATE_API_KEY) */\n apiKey?: string;\n /** Visgate API base URL (default: https://visgateai.com/api/v1) */\n baseUrl?: string;\n /** Path segments to append to baseUrl (e.g. [\"health\"] or [\"images\", \"generate\"]) */\n pathSegments: string[];\n /** Timeout in ms for the request to Visgate (default: 300000). Set higher for very long video jobs. */\n timeoutMs?: number;\n}\n\nfunction corsHeaders(request: Request): Record<string, string> {\n const origin = request.headers.get(\"origin\");\n return {\n \"Access-Control-Allow-Origin\": origin || \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n };\n}\n\n/**\n * Forward the incoming request to Visgate and return the response.\n * Call this from your framework (Next.js, Express, etc.) with the request and path.\n */\nexport async function proxyToVisgate(request: Request, options: ProxyOptions): Promise<Response> {\n // Use API key from request (client sends it when using proxy + apiKey), then options, then env\n const authHeader = request.headers.get(\"Authorization\");\n const keyFromRequest =\n authHeader && /^Bearer\\s+/i.test(authHeader) ? authHeader.replace(/^Bearer\\s+/i, \"\").trim() : null;\n const apiKey = keyFromRequest ?? options.apiKey ?? process.env.VISGATE_API_KEY;\n if (!apiKey) {\n return new Response(\n JSON.stringify({ error: \"VISGATE_API_KEY not set on server and no API key in request\" }),\n {\n status: 500,\n headers: { \"Content-Type\": \"application/json\", ...corsHeaders(request) },\n }\n );\n }\n\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n const pathStr = options.pathSegments.join(\"/\");\n const url = `${baseUrl}/${pathStr}`;\n const search = request.url.includes(\"?\") ? request.url.slice(request.url.indexOf(\"?\")) : \"\";\n\n const headers = new Headers();\n request.headers.forEach((value, key) => {\n const lower = key.toLowerCase();\n if (lower === \"authorization\" || lower === \"host\") return;\n headers.set(key, value);\n });\n headers.set(\"Authorization\", `Bearer ${apiKey}`);\n\n // Add provider keys from server env when not sent by client (BYOK for video/image)\n if (!headers.has(\"X-Fal-Key\")) {\n const falKey = process.env.VISGATE_FAL_KEY ?? process.env.FAL_KEY;\n if (falKey) headers.set(\"X-Fal-Key\", falKey);\n }\n if (!headers.has(\"X-Replicate-Key\")) {\n const replicateKey = process.env.VISGATE_REPLICATE_KEY ?? process.env.REPLICATE_API_TOKEN;\n if (replicateKey) headers.set(\"X-Replicate-Key\", replicateKey);\n }\n if (!headers.has(\"X-Runway-Key\")) {\n const runwayKey = process.env.VISGATE_RUNWAY_KEY ?? process.env.RUNWAY_API_KEY;\n if (runwayKey) headers.set(\"X-Runway-Key\", runwayKey);\n }\n\n const body =\n request.method !== \"GET\" && request.method !== \"HEAD\" ? await request.text() : undefined;\n const timeoutMs = options.timeoutMs ?? DEFAULT_UPSTREAM_TIMEOUT_MS;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n let res: Response;\n try {\n res = await fetch(url + search, {\n method: request.method,\n headers,\n body,\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timeoutId);\n const message = err instanceof Error ? err.message : String(err);\n const isTimeout = err instanceof Error && err.name === \"AbortError\";\n return new Response(\n JSON.stringify({\n error: isTimeout ? \"GATEWAY_TIMEOUT\" : \"BAD_GATEWAY\",\n message: isTimeout\n ? `Upstream request timed out after ${timeoutMs}ms`\n : `Upstream request failed: ${message}`,\n }),\n {\n status: isTimeout ? 504 : 502,\n headers: { \"Content-Type\": \"application/json\", ...corsHeaders(request) },\n }\n );\n }\n clearTimeout(timeoutId);\n\n // res.text() decompresses automatically; do not forward Content-Encoding or\n // the browser will try to decode again and fail with ERR_CONTENT_DECODING_FAILED.\n const text = await res.text();\n const resHeaders = new Headers();\n res.headers.forEach((value, key) => {\n const lower = key.toLowerCase();\n if (lower === \"transfer-encoding\" || lower === \"content-encoding\" || lower === \"content-length\") return;\n resHeaders.set(key, value);\n });\n Object.entries(corsHeaders(request)).forEach(([k, v]) => resHeaders.set(k, v));\n\n return new Response(text, { status: res.status, headers: resHeaders });\n}\n","/**\n * Next.js App Router handlers for Visgate proxy.\n * Use in app/api/visgate/[...path]/route.ts:\n * export { GET, POST, PUT, DELETE, OPTIONS } from \"@visgate-ai/server-proxy/next\";\n */\n\nimport { proxyToVisgate } from \"./proxy\";\n\ntype NextContext = { params: Promise<{ path: string[] }> };\n\nasync function handle(request: Request, context: NextContext): Promise<Response> {\n const { path } = await context.params;\n return proxyToVisgate(request, { pathSegments: path });\n}\n\nconst CORS_HEADERS = {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n};\n\nexport function GET(request: Request, context: NextContext): Promise<Response> {\n return handle(request, context);\n}\n\nexport function POST(request: Request, context: NextContext): Promise<Response> {\n return handle(request, context);\n}\n\nexport function PUT(request: Request, context: NextContext): Promise<Response> {\n return handle(request, context);\n}\n\nexport function DELETE(request: Request, context: NextContext): Promise<Response> {\n return handle(request, context);\n}\n\nexport function OPTIONS(): Response {\n return new Response(null, { status: 204, headers: CORS_HEADERS });\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@visgate-ai/server-proxy",
3
+ "version": "0.1.0",
4
+ "description": "Framework-agnostic server proxy for Visgate API — add your API key on the server, keep it out of the client.",
5
+ "license": "MIT",
6
+ "repository": { "type": "git", "url": "git+https://github.com/visgate-ai/visgate-js.git", "directory": "server-proxy" },
7
+ "publishConfig": { "access": "public" },
8
+ "files": ["dist"],
9
+ "main": "dist/index.js",
10
+ "module": "dist/index.mjs",
11
+ "types": "dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.mjs",
16
+ "require": "./dist/index.js"
17
+ },
18
+ "./next": {
19
+ "types": "./dist/next.d.ts",
20
+ "import": "./dist/next.mjs",
21
+ "require": "./dist/next.js"
22
+ }
23
+ },
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "dev": "tsup --watch"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^20",
30
+ "tsup": "^8.3.5",
31
+ "typescript": "^5.7.0"
32
+ },
33
+ "engines": {
34
+ "node": ">=18"
35
+ }
36
+ }