@motherbase/cli 0.2.1 → 0.2.2

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/bin/motherbase.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
4
  const { main } = require('../src/main');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motherbase/cli",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Motherbase operator CLI — drives the Platform Console and linked projects.",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -20,5 +20,8 @@
20
20
  "publishConfig": {
21
21
  "access": "public"
22
22
  },
23
- "license": "MIT"
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "@motherbase/cli": "^0.2.1"
26
+ }
24
27
  }
package/src/api.js CHANGED
@@ -36,6 +36,14 @@ function unwrap(body) {
36
36
  return body;
37
37
  }
38
38
 
39
+ // Non-browser clients send no Origin header. Better Auth (and reverse proxies
40
+ // that inject cookies) then treat the request as CSRF-suspect and reject it with
41
+ // "Missing or null Origin". Sending the target's own origin — which the server
42
+ // keeps in its trustedOrigins (baseURL) — satisfies that check for every route.
43
+ function originFor(url) {
44
+ try { return new URL(url).origin; } catch { return undefined; }
45
+ }
46
+
39
47
  function errorMessage(status, body, text) {
40
48
  const snippet = (body && (body.message || body.error)) || (text ? text.slice(0, 300) : '');
41
49
  if (status === 401) {
@@ -65,6 +73,10 @@ async function parseResponse(res) {
65
73
  async function doFetch(url, { method = 'GET', token, body, headers = {} } = {}) {
66
74
  const finalHeaders = { ...headers };
67
75
  if (token) finalHeaders['authorization'] = `Bearer ${token}`;
76
+ if (!finalHeaders['origin']) {
77
+ const origin = originFor(url);
78
+ if (origin) finalHeaders['origin'] = origin;
79
+ }
68
80
  let payload;
69
81
  if (body !== undefined && body !== null) {
70
82
  finalHeaders['content-type'] = 'application/json';
@@ -94,9 +106,12 @@ async function loginRequest(consoleUrl, email, password) {
94
106
  const url = `${consoleUrl}/api/auth/sign-in/email`;
95
107
  let res;
96
108
  try {
109
+ const headers = { 'content-type': 'application/json' };
110
+ const origin = originFor(url);
111
+ if (origin) headers['origin'] = origin;
97
112
  res = await fetch(url, {
98
113
  method: 'POST',
99
- headers: { 'content-type': 'application/json' },
114
+ headers,
100
115
  body: JSON.stringify({ email, password }),
101
116
  });
102
117
  } catch (err) {
@@ -149,11 +164,14 @@ async function uploadFile(ctx, apiPath, filePath, fields = {}) {
149
164
  for (const [k, v] of Object.entries(fields)) {
150
165
  if (v !== undefined && v !== null) form.append(k, String(v));
151
166
  }
167
+ const uploadHeaders = token ? { authorization: `Bearer ${token}` } : {};
168
+ const uploadOrigin = originFor(url);
169
+ if (uploadOrigin) uploadHeaders['origin'] = uploadOrigin;
152
170
  let res;
153
171
  try {
154
172
  res = await fetch(url, {
155
173
  method: 'POST',
156
- headers: token ? { authorization: `Bearer ${token}` } : {},
174
+ headers: uploadHeaders,
157
175
  body: form,
158
176
  });
159
177
  } catch (err) {
@@ -168,9 +186,12 @@ async function downloadFile(ctx, apiPath, destPath, { query } = {}) {
168
186
  const target = ctx.requireProject();
169
187
  const { base, token } = adminBase(target);
170
188
  const url = `${base}${apiPath}${buildQuery(query)}`;
189
+ const dlHeaders = token ? { authorization: `Bearer ${token}` } : {};
190
+ const dlOrigin = originFor(url);
191
+ if (dlOrigin) dlHeaders['origin'] = dlOrigin;
171
192
  let res;
172
193
  try {
173
- res = await fetch(url, { headers: token ? { authorization: `Bearer ${token}` } : {} });
194
+ res = await fetch(url, { headers: dlHeaders });
174
195
  } catch (err) {
175
196
  throw new CliError(`Cannot reach ${url}: ${err.message}`);
176
197
  }