@qelos/plugin-netlify-api 1.0.4 → 1.0.5

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 CHANGED
@@ -19,6 +19,19 @@ In your site’s `netlify.toml`, add the plugin next to your existing `[build]`
19
19
  package = "@qelos/plugin-netlify-api"
20
20
  ```
21
21
 
22
+ **Nuxt / static frameworks (required):** Netlify evaluates `dist/_redirects` **before** `netlify.toml`. Nitro’s `netlify-static` preset emits a catch‑all `/*` rule first, so you must prepend the API rewrite **after** `nuxt build`. Add an npm **`postbuild`** script (runs automatically when Netlify runs `npm run build`):
23
+
24
+ ```json
25
+ {
26
+ "scripts": {
27
+ "build": "nuxt build",
28
+ "postbuild": "qelos-netlify-patch-redirects"
29
+ }
30
+ }
31
+ ```
32
+
33
+ If your publish directory is not `dist`, set `QELOS_NETLIFY_PUBLISH` to that folder name (relative to the app root) for the patch script.
34
+
22
35
  Minimal variant (defaults API URL inside the plugin if you omit env):
23
36
 
24
37
  ```toml
@@ -43,7 +56,7 @@ Optional: set the API URL (default `http://159.203.152.168`) and/or enable bypas
43
56
  ## What it does
44
57
 
45
58
  - **Environment:** Sets `QELOS_API_IP` for the build (and for the proxy function at runtime).
46
- - **Redirect:** Adds a rewrite in `netlify.toml` and, **after the site build**, prepends the same rule to **`publish/_redirects`** when that file exists. Netlify applies `_redirects` **before** `netlify.toml`; frameworks (e.g. Nuxt `netlify-static`) often emit `/* → /404.html` first, which would otherwise match `/api/*` and never reach the proxy.
59
+ - **Redirect:** Adds a rewrite in `netlify.toml` and ships **`qelos-netlify-patch-redirects`** to prepend the same line to **`publish/_redirects`** (use the **`postbuild`** script above — do not rely on the build plugin alone for Nuxt).
47
60
  - **Function:** Copies `qelos-api-proxy.ts` from the package into your Netlify **functions directory** (default `netlify/functions`, or `[functions] directory` in `netlify.toml`) during `onPreBuild`, so the bundler sees a normal function file. Forwards requests using `QELOS_API_IP` / `API_HOST` (full URL or hostname).
48
61
 
49
62
  No need to add redirects or commit the proxy yourself; the plugin writes it each build. Optional: add `netlify/functions/qelos-api-proxy.ts` to `.gitignore` if you run local Netlify builds and do not want the copy tracked.
package/index.js CHANGED
@@ -1,17 +1,26 @@
1
1
  const fs = require('node:fs/promises');
2
2
  const path = require('node:path');
3
3
 
4
- const DEFAULT_API_URL = 'http://159.203.152.168';
4
+ const { patchRedirects } = require('./scripts/patch-redirects.cjs');
5
5
 
6
- /** Must appear before any `/*` rule in publish/_redirects — Netlify evaluates that file before netlify.toml. */
7
- const REDIRECTS_FILE_LINE =
8
- '/api/* /.netlify/functions/qelos-api-proxy 200!\n';
6
+ const DEFAULT_API_URL = 'http://159.203.152.168';
9
7
 
10
8
  function resolveFunctionsDirectory(netlifyConfig) {
11
9
  const dir = netlifyConfig.functions?.directory ?? 'netlify/functions';
12
10
  return path.isAbsolute(dir) ? dir : path.join(process.cwd(), dir);
13
11
  }
14
12
 
13
+ function resolvePublishDir(constants, netlifyConfig) {
14
+ if (constants?.PUBLISH_DIR) {
15
+ return constants.PUBLISH_DIR;
16
+ }
17
+ const p = netlifyConfig?.build?.publish;
18
+ if (!p) {
19
+ return path.join(process.cwd(), 'dist');
20
+ }
21
+ return path.isAbsolute(p) ? p : path.join(process.cwd(), p);
22
+ }
23
+
15
24
  module.exports = {
16
25
  async onPreBuild({ netlifyConfig, inputs }) {
17
26
  const apiUrl =
@@ -53,21 +62,14 @@ module.exports = {
53
62
  },
54
63
 
55
64
  /**
56
- * Nuxt/static generators emit `dist/_redirects` with `/* → 404` first. Netlify runs
57
- * `_redirects` rules before `netlify.toml`, so that catch-all wins unless `/api/*` is
58
- * prepended here (after the framework build).
65
+ * Best-effort: some Netlify builds omit logging or skip this hook; the supported fix
66
+ * for Nuxt is `postbuild` → `qelos-netlify-patch-redirects` (see README).
59
67
  */
60
- async onPostBuild({ constants }) {
61
- const publishDir = constants.PUBLISH_DIR;
62
- if (!publishDir) return;
63
- const redirectsPath = path.join(publishDir, '_redirects');
64
- let existing = '';
65
- try {
66
- existing = await fs.readFile(redirectsPath, 'utf8');
67
- } catch (e) {
68
- if (e.code !== 'ENOENT') throw e;
69
- }
70
- if (existing.includes('qelos-api-proxy')) return;
71
- await fs.writeFile(redirectsPath, REDIRECTS_FILE_LINE + existing, 'utf8');
68
+ async onPostBuild({ constants, netlifyConfig }) {
69
+ const publishDir = resolvePublishDir(constants, netlifyConfig);
70
+ const changed = patchRedirects(publishDir);
71
+ console.log(
72
+ `[@qelos/plugin-netlify-api] onPostBuild: ${changed ? 'patched' : 'skipped'} ${path.join(publishDir, '_redirects')}`,
73
+ );
72
74
  },
73
75
  };
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@qelos/plugin-netlify-api",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Netlify build plugin: proxy /api/* to Qelos API and inject config",
5
5
  "main": "index.js",
6
+ "bin": {
7
+ "qelos-netlify-patch-redirects": "./scripts/patch-redirects.cjs"
8
+ },
6
9
  "files": [
7
10
  "index.js",
8
11
  "manifest.yml",
9
- "functions"
12
+ "functions",
13
+ "scripts"
10
14
  ],
11
15
  "author": "David Meir-Levy <davidmeirlevy@gmail.com>",
12
16
  "license": "MIT",
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Prepend `/api/*` → qelos-api-proxy to publish/_redirects *before* Netlify deploy.
6
+ * Netlify evaluates `_redirects` before netlify.toml; Nuxt `netlify-static` emits
7
+ * `/* → /404.html` first — without this line, `/api/*` never reaches the function.
8
+ *
9
+ * Run via npm lifecycle: "postbuild": "qelos-netlify-patch-redirects"
10
+ * (postbuild runs automatically after `nuxt build` when Netlify runs `npm run build`).
11
+ */
12
+
13
+ const fs = require('node:fs');
14
+ const path = require('node:path');
15
+
16
+ const REDIRECT_LINE = '/api/* /.netlify/functions/qelos-api-proxy 200!\n';
17
+
18
+ /**
19
+ * @param {string} publishDir absolute path to the directory Netlify deploys (e.g. …/dist)
20
+ * @returns {boolean} true if the file was written
21
+ */
22
+ function patchRedirects(publishDir) {
23
+ if (!publishDir) return false;
24
+ const redirectsPath = path.join(publishDir, '_redirects');
25
+ let existing = '';
26
+ try {
27
+ existing = fs.readFileSync(redirectsPath, 'utf8');
28
+ } catch (e) {
29
+ if (e.code !== 'ENOENT') throw e;
30
+ }
31
+ if (existing.includes('qelos-api-proxy')) {
32
+ return false;
33
+ }
34
+ fs.writeFileSync(redirectsPath, REDIRECT_LINE + existing, 'utf8');
35
+ return true;
36
+ }
37
+
38
+ function resolvePublishDirFromEnv() {
39
+ const rel = process.env.QELOS_NETLIFY_PUBLISH || 'dist';
40
+ return path.isAbsolute(rel) ? rel : path.join(process.cwd(), rel);
41
+ }
42
+
43
+ if (require.main === module) {
44
+ const abs = resolvePublishDirFromEnv();
45
+ const changed = patchRedirects(abs);
46
+ const target = path.join(abs, '_redirects');
47
+ if (changed) {
48
+ console.log(`[qelos-netlify-patch-redirects] prepended /api/* rewrite → ${target}`);
49
+ } else {
50
+ console.log(
51
+ `[qelos-netlify-patch-redirects] skipped (already has qelos-api-proxy) → ${target}`,
52
+ );
53
+ }
54
+ }
55
+
56
+ module.exports = { patchRedirects, REDIRECT_LINE };