@qelos/plugin-netlify-api 1.0.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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Polyform Shield License 1.0.0
2
+
3
+ Copyright (c) 2025 Velocitech LTD
4
+
5
+ Your use of this software is governed by the Polyform Shield License 1.0.0.
6
+
7
+ You may obtain a copy of the License at:
8
+ https://polyformproject.org/licenses/shield/1.0.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+
12
+ Additional Terms – Exception Notice:
13
+
14
+ The author of this software grants additional permissions beyond the Polyform Shield License 1.0.0:
15
+
16
+ ✅ All uses of the software are permitted — including modification, distribution, commercial use, and sublicensing — as long as the software is not used to create, offer, or operate any product or service that competes directly with Qelos (https://qelos.io), a no-code platform for building AI-assisted SaaS applications.
17
+
18
+ ❌ "Direct competition" includes platforms, tools, or services that enable users to visually or programmatically create SaaS applications with the assistance of artificial intelligence.
19
+
20
+ This exception does not modify the terms of the original Polyform Shield License for other users and applies only by explicit permission of the licensor.
package/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # @qelos/plugin-netlify-api
2
+
3
+ Netlify build plugin for Qelos frontend apps: proxies `/api/*` to your Qelos API and injects config.
4
+
5
+ ## Setup
6
+
7
+ In your site’s `netlify.toml`:
8
+
9
+ ```toml
10
+ [[plugins]]
11
+ package = "@qelos/plugin-netlify-api"
12
+ ```
13
+
14
+ Optional: set the API URL (default `http://159.203.152.168`):
15
+
16
+ ```toml
17
+ [[plugins]]
18
+ package = "@qelos/plugin-netlify-api"
19
+
20
+ [plugins.inputs]
21
+ api_url = "http://159.203.152.168"
22
+ ```
23
+
24
+ Or set the `QELOS_API_IP` environment variable in the Netlify UI (build or runtime).
25
+
26
+ ## What it does
27
+
28
+ - **Environment:** Sets `QELOS_API_IP` for the build (and for the proxy function at runtime).
29
+ - **Redirect:** Adds a rewrite so `/api/*` is served by `/.netlify/functions/qelos-api-proxy` (status 200, force).
30
+ - **Function:** Injects a serverless function `qelos-api-proxy` that forwards requests to the host/port from `QELOS_API_IP` (supports a full URL like `http://159.203.152.168` or a hostname).
31
+
32
+ No need to add redirects or the function file to your repo; the plugin does it at build time.
@@ -0,0 +1,67 @@
1
+ import http from "http";
2
+ import type { Handler } from "@netlify/functions";
3
+
4
+ const raw = process.env.QELOS_API_IP ?? "159.203.152.168";
5
+ const parsed =
6
+ raw.startsWith("http://") || raw.startsWith("https://")
7
+ ? new URL(raw)
8
+ : { hostname: raw, port: "80" };
9
+ const PROXY_HOST = parsed.hostname;
10
+ const PROXY_PORT = parseInt(parsed.port || "80", 10);
11
+
12
+ export const handler: Handler = (event) =>
13
+ new Promise((resolve) => {
14
+ // Build forwarded headers, preserving the original Host header
15
+ const headers: Record<string, string> = {};
16
+ for (const [key, val] of Object.entries(event.headers)) {
17
+ if (val) headers[key] = val;
18
+ }
19
+ headers["host"] = event.headers["host"] ?? PROXY_HOST;
20
+ // Lambda buffers the body, so chunked encoding is not applicable
21
+ delete headers["transfer-encoding"];
22
+
23
+ const targetPath =
24
+ new URL(event.rawUrl).pathname +
25
+ (event.rawQuery ? `?${event.rawQuery}` : "");
26
+
27
+ const body = event.body
28
+ ? Buffer.from(event.body, event.isBase64Encoded ? "base64" : "utf8")
29
+ : undefined;
30
+
31
+ const proxyReq = http.request(
32
+ {
33
+ hostname: PROXY_HOST,
34
+ port: PROXY_PORT,
35
+ path: targetPath,
36
+ method: event.httpMethod,
37
+ headers,
38
+ },
39
+ (proxyRes) => {
40
+ const chunks: Buffer[] = [];
41
+ proxyRes.on("data", (chunk: Buffer) => chunks.push(chunk));
42
+ proxyRes.on("end", () => {
43
+ const resHeaders: Record<string, string> = {};
44
+ for (const [key, val] of Object.entries(proxyRes.headers)) {
45
+ if (val != null && key !== "transfer-encoding") {
46
+ resHeaders[key] = Array.isArray(val) ? val.join(", ") : val;
47
+ }
48
+ }
49
+ resolve({
50
+ statusCode: proxyRes.statusCode ?? 200,
51
+ headers: resHeaders,
52
+ body: Buffer.concat(chunks).toString("base64"),
53
+ isBase64Encoded: true,
54
+ });
55
+ });
56
+ proxyRes.on("error", () =>
57
+ resolve({ statusCode: 502, body: "Bad Gateway" })
58
+ );
59
+ }
60
+ );
61
+
62
+ proxyReq.on("error", () =>
63
+ resolve({ statusCode: 502, body: "Bad Gateway" })
64
+ );
65
+ if (body) proxyReq.write(body);
66
+ proxyReq.end();
67
+ });
package/index.js ADDED
@@ -0,0 +1,31 @@
1
+ const path = require("node:path");
2
+
3
+ const DEFAULT_API_URL = "http://159.203.152.168";
4
+
5
+ module.exports = {
6
+ async onPreBuild({ netlifyConfig, utils, inputs }) {
7
+ const apiUrl = inputs.api_url ?? process.env.QELOS_API_IP ?? DEFAULT_API_URL;
8
+
9
+ // Ensure build.environment exists
10
+ if (!netlifyConfig.build.environment) {
11
+ netlifyConfig.build.environment = {};
12
+ }
13
+ netlifyConfig.build.environment.QELOS_API_IP = apiUrl;
14
+
15
+ // Add redirect: /api/* -> Netlify function (proxy)
16
+ if (!netlifyConfig.redirects) {
17
+ netlifyConfig.redirects = [];
18
+ }
19
+ netlifyConfig.redirects.push({
20
+ from: "/api/*",
21
+ to: "/.netlify/functions/qelos-api-proxy",
22
+ status: 200,
23
+ force: true,
24
+ });
25
+
26
+ // Inject the proxy function (must run in onPreBuild so it's bundled)
27
+ const pluginRoot = __dirname;
28
+ const functionPath = path.join(pluginRoot, "functions", "qelos-api-proxy.ts");
29
+ await utils.functions.add(functionPath);
30
+ },
31
+ };
package/manifest.yml ADDED
@@ -0,0 +1,6 @@
1
+ name: "@qelos/plugin-netlify-api"
2
+ inputs:
3
+ - name: api_url
4
+ required: false
5
+ description: "Qelos API base URL (e.g. http://159.203.152.168). Used as QELOS_API_IP and for /api/* proxy."
6
+ default: "http://159.203.152.168"
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@qelos/plugin-netlify-api",
3
+ "version": "1.0.1",
4
+ "description": "Netlify build plugin: proxy /api/* to Qelos API and inject config",
5
+ "main": "index.js",
6
+ "files": [
7
+ "index.js",
8
+ "manifest.yml",
9
+ "functions"
10
+ ],
11
+ "author": "David Meir-Levy <davidmeirlevy@gmail.com>",
12
+ "license": "MIT",
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "engines": {
17
+ "node": ">=18"
18
+ }
19
+ }