@dashnex/cli 0.5.1 → 0.5.4
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/dist/cli.d.ts +2 -0
- package/dist/cli.js +1 -161
- package/dist/client.d.ts +3 -0
- package/dist/client.js +1 -12
- package/dist/commands/create.d.ts +7 -0
- package/dist/commands/create.js +1 -134
- package/dist/commands/delete.d.ts +4 -0
- package/dist/commands/delete.js +1 -51
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.js +1 -68
- package/dist/commands/login.d.ts +8 -0
- package/dist/commands/login.js +1 -262
- package/dist/commands/logout.d.ts +4 -0
- package/dist/commands/logout.js +1 -16
- package/dist/commands/pull.d.ts +4 -0
- package/dist/commands/pull.js +1 -102
- package/dist/commands/push.d.ts +4 -0
- package/dist/commands/push.js +1 -108
- package/dist/commands/version.d.ts +5 -0
- package/dist/commands/version.js +1 -10
- package/dist/commands/whoami.d.ts +4 -0
- package/dist/commands/whoami.js +1 -52
- package/dist/dashnex.json.js +1 -5
- package/dist/lib/api.d.ts +7 -0
- package/dist/lib/api.js +1 -23
- package/dist/lib/debug.d.ts +3 -0
- package/dist/lib/debug.js +1 -45
- package/dist/package.json.js +1 -15
- package/dist/server.d.ts +3 -0
- package/dist/server.js +1 -12
- package/dist/services/auth.d.ts +10 -0
- package/dist/services/auth.js +1 -116
- package/package.json +3 -3
- package/dist/cli.js.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/commands/create.js.map +0 -1
- package/dist/commands/delete.js.map +0 -1
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/logout.js.map +0 -1
- package/dist/commands/pull.js.map +0 -1
- package/dist/commands/push.js.map +0 -1
- package/dist/commands/version.js.map +0 -1
- package/dist/commands/whoami.js.map +0 -1
- package/dist/dashnex.json.js.map +0 -1
- package/dist/lib/api.js.map +0 -1
- package/dist/lib/debug.js.map +0 -1
- package/dist/package.json.js.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/services/auth.js.map +0 -1
package/dist/commands/login.js
CHANGED
|
@@ -1,262 +1 @@
|
|
|
1
|
-
import inquirer from "
|
|
2
|
-
import chalk from "chalk";
|
|
3
|
-
import fs from "fs-extra";
|
|
4
|
-
import path from "path";
|
|
5
|
-
import { debug, debugJson, debugError } from "../lib/debug.js";
|
|
6
|
-
import { getApiBase, apiFetch } from "../lib/api.js";
|
|
7
|
-
import { ensureLoggedIn } from "../services/auth.js";
|
|
8
|
-
const extractErrorMessage = (body) => {
|
|
9
|
-
if (typeof body.error === "string") return body.error;
|
|
10
|
-
if (typeof body.message === "string") return body.message;
|
|
11
|
-
return void 0;
|
|
12
|
-
};
|
|
13
|
-
const handleApiError = (response, body, defaultMessage) => {
|
|
14
|
-
const apiMessage = extractErrorMessage(body);
|
|
15
|
-
let message = defaultMessage;
|
|
16
|
-
if (response.status === 429) {
|
|
17
|
-
message = "Too many requests. Please wait a moment and try again.";
|
|
18
|
-
} else if (response.status >= 500) {
|
|
19
|
-
message = "DashNex API is temporarily unavailable. Please try again later.";
|
|
20
|
-
} else if (apiMessage) {
|
|
21
|
-
message = apiMessage;
|
|
22
|
-
}
|
|
23
|
-
console.error(chalk.red(message));
|
|
24
|
-
process.exit(1);
|
|
25
|
-
};
|
|
26
|
-
class LoginCommand {
|
|
27
|
-
async execute() {
|
|
28
|
-
debug("Login flow started");
|
|
29
|
-
const cwd = process.cwd();
|
|
30
|
-
const dashnexPath = path.join(cwd, ".dashnex");
|
|
31
|
-
const session = await ensureLoggedIn({ exitOnFailure: false, dashnexPath });
|
|
32
|
-
if (session) {
|
|
33
|
-
console.log(chalk.green(`Already logged in as ${session.userName ?? "user"}`));
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
try {
|
|
37
|
-
const { username, password } = await inquirer.prompt([
|
|
38
|
-
{
|
|
39
|
-
type: "input",
|
|
40
|
-
name: "username",
|
|
41
|
-
message: "Email:",
|
|
42
|
-
validate: (input) => input.trim() ? true : "Email is required"
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
type: "password",
|
|
46
|
-
name: "password",
|
|
47
|
-
message: "Password:",
|
|
48
|
-
mask: "*",
|
|
49
|
-
validate: (input) => input ? true : "Password is required"
|
|
50
|
-
}
|
|
51
|
-
]);
|
|
52
|
-
const trimmedUsername = username.trim();
|
|
53
|
-
debug("Email provided");
|
|
54
|
-
debug(`POST ${getApiBase()}/auth/v1/login`);
|
|
55
|
-
const { response: loginResponse, body: loginBody } = await apiFetch(
|
|
56
|
-
`${getApiBase()}/auth/v1/login`,
|
|
57
|
-
{
|
|
58
|
-
method: "POST",
|
|
59
|
-
body: JSON.stringify({ username: trimmedUsername, password })
|
|
60
|
-
}
|
|
61
|
-
);
|
|
62
|
-
debug(`Response: ${loginResponse.status}`);
|
|
63
|
-
debugJson("Login response", loginBody);
|
|
64
|
-
if (!loginResponse.ok) {
|
|
65
|
-
debugError(new Error(`Login failed: ${loginResponse.status} ${JSON.stringify(loginBody)}`));
|
|
66
|
-
if (loginResponse.status === 401) {
|
|
67
|
-
console.error(chalk.red("Invalid username or password."));
|
|
68
|
-
process.exit(1);
|
|
69
|
-
}
|
|
70
|
-
handleApiError(
|
|
71
|
-
loginResponse,
|
|
72
|
-
loginBody,
|
|
73
|
-
"Login failed. Please try again."
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
const loginData = loginBody;
|
|
77
|
-
if (loginData.two_fa_required && loginData.token) {
|
|
78
|
-
debug(`2FA required, type: ${loginData.type || "unknown"}`);
|
|
79
|
-
const token = await this.handle2FA(loginData.token, loginData.type);
|
|
80
|
-
if (!token) process.exit(1);
|
|
81
|
-
await this.completeLogin(token, dashnexPath);
|
|
82
|
-
} else if (loginData.token && loginData.refreshToken) {
|
|
83
|
-
await this.completeLogin(
|
|
84
|
-
{ token: loginData.token, refreshToken: loginData.refreshToken },
|
|
85
|
-
dashnexPath
|
|
86
|
-
);
|
|
87
|
-
} else {
|
|
88
|
-
console.error(chalk.red("Invalid response from server. Please try again."));
|
|
89
|
-
process.exit(1);
|
|
90
|
-
}
|
|
91
|
-
} catch (error) {
|
|
92
|
-
debugError(error);
|
|
93
|
-
console.error(chalk.red("Could not reach DashNex API. Check your connection and try again."));
|
|
94
|
-
process.exit(1);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
async handle2FA(interimToken, type) {
|
|
98
|
-
if (type === "sms") {
|
|
99
|
-
debug(`POST ${getApiBase()}/auth/v1/two-fa/sms`);
|
|
100
|
-
try {
|
|
101
|
-
const { response } = await apiFetch(`${getApiBase()}/auth/v1/two-fa/sms`, {
|
|
102
|
-
method: "POST",
|
|
103
|
-
headers: { Authorization: `Bearer ${interimToken}` },
|
|
104
|
-
body: JSON.stringify({})
|
|
105
|
-
});
|
|
106
|
-
debug(`Response: ${response.status}`);
|
|
107
|
-
} catch (err) {
|
|
108
|
-
debugError(err);
|
|
109
|
-
console.error(chalk.red("Could not send SMS code. Check your connection and try again."));
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
const typeLabel = type === "sms" ? "Check your phone for the code" : "Check your authenticator app for the code";
|
|
114
|
-
const maxAttempts = 3;
|
|
115
|
-
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
116
|
-
const { auth_code } = await inquirer.prompt([
|
|
117
|
-
{
|
|
118
|
-
type: "input",
|
|
119
|
-
name: "auth_code",
|
|
120
|
-
message: `Enter code (${typeLabel}):`,
|
|
121
|
-
validate: (input) => input.trim() ? true : "Code is required"
|
|
122
|
-
}
|
|
123
|
-
]);
|
|
124
|
-
debug(`POST ${getApiBase()}/auth/v1/2fa-check`);
|
|
125
|
-
try {
|
|
126
|
-
const { response, body } = await apiFetch(`${getApiBase()}/auth/v1/2fa-check`, {
|
|
127
|
-
method: "POST",
|
|
128
|
-
headers: { Authorization: `Bearer ${interimToken}` },
|
|
129
|
-
body: JSON.stringify({ auth_code: auth_code.trim() })
|
|
130
|
-
});
|
|
131
|
-
debug(`Response: ${response.status}`);
|
|
132
|
-
debugJson("2FA check response", body);
|
|
133
|
-
if (response.ok) {
|
|
134
|
-
const data = body;
|
|
135
|
-
if (data.token && data.refreshToken) {
|
|
136
|
-
return { token: data.token, refreshToken: data.refreshToken };
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
if (response.status >= 400 && response.status < 500) {
|
|
140
|
-
console.error(chalk.red("Invalid code. Please try again."));
|
|
141
|
-
if (attempt < maxAttempts) {
|
|
142
|
-
const { retry } = await inquirer.prompt([
|
|
143
|
-
{
|
|
144
|
-
type: "confirm",
|
|
145
|
-
name: "retry",
|
|
146
|
-
message: "Try again?",
|
|
147
|
-
default: true
|
|
148
|
-
}
|
|
149
|
-
]);
|
|
150
|
-
if (!retry) return null;
|
|
151
|
-
}
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
handleApiError(response, body, "2FA verification failed. Please try again.");
|
|
155
|
-
} catch (err) {
|
|
156
|
-
debugError(err);
|
|
157
|
-
console.error(chalk.red("Could not reach DashNex API. Check your connection and try again."));
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
return null;
|
|
162
|
-
}
|
|
163
|
-
async completeLogin(tokens, dashnexPath) {
|
|
164
|
-
debug(`GET ${getApiBase()}/users/v1/business/my`);
|
|
165
|
-
const { response: bizResponse, body: bizBody } = await apiFetch(
|
|
166
|
-
`${getApiBase()}/users/v1/business/my`,
|
|
167
|
-
{
|
|
168
|
-
headers: { Authorization: `Bearer ${tokens.token}` }
|
|
169
|
-
}
|
|
170
|
-
);
|
|
171
|
-
debug(`Response: ${bizResponse.status}`);
|
|
172
|
-
debugJson("Businesses response", bizBody);
|
|
173
|
-
if (!bizResponse.ok) {
|
|
174
|
-
debugError(new Error(`Business fetch failed: ${bizResponse.status}`));
|
|
175
|
-
handleApiError(
|
|
176
|
-
bizResponse,
|
|
177
|
-
bizBody,
|
|
178
|
-
"Failed to fetch businesses. Please try again."
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
const businesses = this.parseBusinesses(bizBody);
|
|
182
|
-
debug(`Businesses: ${businesses.length}`);
|
|
183
|
-
if (businesses.length === 0) {
|
|
184
|
-
console.error(chalk.red("No businesses found for your account."));
|
|
185
|
-
process.exit(1);
|
|
186
|
-
}
|
|
187
|
-
let selected;
|
|
188
|
-
if (businesses.length === 1) {
|
|
189
|
-
selected = businesses[0];
|
|
190
|
-
debug(`Selected business: ${selected.id} ${selected.name}`);
|
|
191
|
-
} else {
|
|
192
|
-
const { businessId } = await inquirer.prompt([
|
|
193
|
-
{
|
|
194
|
-
type: "select",
|
|
195
|
-
name: "businessId",
|
|
196
|
-
message: "Select business:",
|
|
197
|
-
choices: businesses.map((b) => ({ name: b.name, value: b.id }))
|
|
198
|
-
}
|
|
199
|
-
]);
|
|
200
|
-
selected = businesses.find((b) => b.id === businessId) || businesses[0];
|
|
201
|
-
debug(`Selected business: ${selected.id} ${selected.name}`);
|
|
202
|
-
}
|
|
203
|
-
debug(`GET ${getApiBase()}/business/v1/login?_switch_business=${selected.id}`);
|
|
204
|
-
const { response: switchResponse, body: switchBody } = await apiFetch(
|
|
205
|
-
`${getApiBase()}/business/v1/login?_switch_business=${selected.id}`,
|
|
206
|
-
{
|
|
207
|
-
headers: { Authorization: `Bearer ${tokens.token}` }
|
|
208
|
-
}
|
|
209
|
-
);
|
|
210
|
-
debug(`Response: ${switchResponse.status}`);
|
|
211
|
-
debugJson("Business login response", switchBody);
|
|
212
|
-
if (!switchResponse.ok) {
|
|
213
|
-
debugError(new Error(`Business login failed: ${switchResponse.status}`));
|
|
214
|
-
handleApiError(
|
|
215
|
-
switchResponse,
|
|
216
|
-
switchBody,
|
|
217
|
-
"Failed to switch to business. Please try again."
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
const switchData = switchBody;
|
|
221
|
-
if (!switchData.token || !switchData.refreshToken) {
|
|
222
|
-
console.error(chalk.red("Invalid response from server. Please try again."));
|
|
223
|
-
process.exit(1);
|
|
224
|
-
}
|
|
225
|
-
const config = {
|
|
226
|
-
token: switchData.token,
|
|
227
|
-
refreshToken: switchData.refreshToken,
|
|
228
|
-
businessId: selected.id
|
|
229
|
-
};
|
|
230
|
-
await fs.writeJson(dashnexPath, config, { spaces: 2 });
|
|
231
|
-
debug("Saved credentials to .dashnex");
|
|
232
|
-
this.ensureGitignore();
|
|
233
|
-
console.log(chalk.green(`Logged in as ${selected.name}`));
|
|
234
|
-
}
|
|
235
|
-
parseBusinesses(body) {
|
|
236
|
-
const arr = Array.isArray(body) ? body : body.items ?? body.data ?? body.businesses ?? [];
|
|
237
|
-
if (!Array.isArray(arr)) return [];
|
|
238
|
-
return arr.map((item) => {
|
|
239
|
-
if (item && typeof item === "object") {
|
|
240
|
-
const o = item;
|
|
241
|
-
const id = String(o.id ?? o.business_id ?? "").trim();
|
|
242
|
-
const name = String(o.name ?? o.companyName ?? o.business_name ?? "Unknown").trim();
|
|
243
|
-
if (id) return { id, name };
|
|
244
|
-
}
|
|
245
|
-
return null;
|
|
246
|
-
}).filter((b) => b !== null);
|
|
247
|
-
}
|
|
248
|
-
async ensureGitignore() {
|
|
249
|
-
const gitignorePath = path.join(process.cwd(), ".gitignore");
|
|
250
|
-
if (!await fs.pathExists(gitignorePath)) return;
|
|
251
|
-
let content = await fs.readFile(gitignorePath, "utf8");
|
|
252
|
-
if (content.includes(".dashnex")) return;
|
|
253
|
-
content = content.trimEnd();
|
|
254
|
-
if (!content.endsWith("\n")) content += "\n";
|
|
255
|
-
content += "\n.dashnex\n";
|
|
256
|
-
await fs.writeFile(gitignorePath, content);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
export {
|
|
260
|
-
LoginCommand
|
|
261
|
-
};
|
|
262
|
-
//# sourceMappingURL=login.js.map
|
|
1
|
+
import e from"inquirer";import s from"chalk";import r from"fs-extra";import t from"path";import{debug as n,debugJson as o,debugError as a}from"../lib/debug.js";import{getApiBase as i,apiFetch as c}from"../lib/api.js";import{ensureLoggedIn as d}from"../services/auth.js";const u=(e,r,t)=>{const n=(e=>"string"==typeof e.error?e.error:"string"==typeof e.message?e.message:void 0)(r);let o=t;429===e.status?o="Too many requests. Please wait a moment and try again.":e.status>=500?o="DashNex API is temporarily unavailable. Please try again later.":n&&(o=n),console.error(s.red(o)),process.exit(1)};class l{async execute(){n("Login flow started");const r=process.cwd(),l=t.join(r,".dashnex"),m=await d({exitOnFailure:!1,dashnexPath:l});if(m)console.log(s.green(`Already logged in as ${m.userName??"user"}`));else try{const{username:r,password:t}=await e.prompt([{type:"input",name:"username",message:"Email:",validate:e=>!!e.trim()||"Email is required"},{type:"password",name:"password",message:"Password:",mask:"*",validate:e=>!!e||"Password is required"}]),d=r.trim();n("Email provided"),n(`POST ${i()}/auth/v1/login`);const{response:m,body:h}=await c(`${i()}/auth/v1/login`,{method:"POST",body:JSON.stringify({username:d,password:t})});n(`Response: ${m.status}`),o("Login response",h),m.ok||(a(new Error(`Login failed: ${m.status} ${JSON.stringify(h)}`)),401===m.status&&(console.error(s.red("Invalid username or password.")),process.exit(1)),u(m,h,"Login failed. Please try again."));const p=h;if(p.two_fa_required&&p.token){n(`2FA required, type: ${p.type||"unknown"}`);const e=await this.handle2FA(p.token,p.type);e||process.exit(1),await this.completeLogin(e,l)}else p.token&&p.refreshToken?await this.completeLogin({token:p.token,refreshToken:p.refreshToken},l):(console.error(s.red("Invalid response from server. Please try again.")),process.exit(1))}catch(h){a(h),console.error(s.red("Could not reach DashNex API. Check your connection and try again.")),process.exit(1)}}async handle2FA(r,t){if("sms"===t){n(`POST ${i()}/auth/v1/two-fa/sms`);try{const{response:e}=await c(`${i()}/auth/v1/two-fa/sms`,{method:"POST",headers:{Authorization:`Bearer ${r}`},body:JSON.stringify({})});n(`Response: ${e.status}`)}catch(l){return a(l),console.error(s.red("Could not send SMS code. Check your connection and try again.")),null}}const d="sms"===t?"Check your phone for the code":"Check your authenticator app for the code";for(let m=1;m<=3;m++){const{auth_code:t}=await e.prompt([{type:"input",name:"auth_code",message:`Enter code (${d}):`,validate:e=>!!e.trim()||"Code is required"}]);n(`POST ${i()}/auth/v1/2fa-check`);try{const{response:a,body:d}=await c(`${i()}/auth/v1/2fa-check`,{method:"POST",headers:{Authorization:`Bearer ${r}`},body:JSON.stringify({auth_code:t.trim()})});if(n(`Response: ${a.status}`),o("2FA check response",d),a.ok){const e=d;if(e.token&&e.refreshToken)return{token:e.token,refreshToken:e.refreshToken}}if(a.status>=400&&a.status<500){if(console.error(s.red("Invalid code. Please try again.")),m<3){const{retry:s}=await e.prompt([{type:"confirm",name:"retry",message:"Try again?",default:!0}]);if(!s)return null}continue}u(a,d,"2FA verification failed. Please try again.")}catch(l){return a(l),console.error(s.red("Could not reach DashNex API. Check your connection and try again.")),null}}return null}async completeLogin(t,d){n(`GET ${i()}/users/v1/business/my`);const{response:l,body:m}=await c(`${i()}/users/v1/business/my`,{headers:{Authorization:`Bearer ${t.token}`}});n(`Response: ${l.status}`),o("Businesses response",m),l.ok||(a(new Error(`Business fetch failed: ${l.status}`)),u(l,m,"Failed to fetch businesses. Please try again."));const h=this.parseBusinesses(m);let p;if(n(`Businesses: ${h.length}`),0===h.length&&(console.error(s.red("No businesses found for your account.")),process.exit(1)),1===h.length)p=h[0],n(`Selected business: ${p.id} ${p.name}`);else{const{businessId:s}=await e.prompt([{type:"select",name:"businessId",message:"Select business:",choices:h.map(e=>({name:e.name,value:e.id}))}]);p=h.find(e=>e.id===s)||h[0],n(`Selected business: ${p.id} ${p.name}`)}n(`GET ${i()}/business/v1/login?_switch_business=${p.id}`);const{response:f,body:y}=await c(`${i()}/business/v1/login?_switch_business=${p.id}`,{headers:{Authorization:`Bearer ${t.token}`}});n(`Response: ${f.status}`),o("Business login response",y),f.ok||(a(new Error(`Business login failed: ${f.status}`)),u(f,y,"Failed to switch to business. Please try again."));const g=y;g.token&&g.refreshToken||(console.error(s.red("Invalid response from server. Please try again.")),process.exit(1));const w={token:g.token,refreshToken:g.refreshToken,businessId:p.id};await r.writeJson(d,w,{spaces:2}),n("Saved credentials to .dashnex"),this.ensureGitignore(),console.log(s.green(`Logged in as ${p.name}`))}parseBusinesses(e){const s=Array.isArray(e)?e:e.items??e.data??e.businesses??[];return Array.isArray(s)?s.map(e=>{if(e&&"object"==typeof e){const s=e,r=String(s.id??s.business_id??"").trim(),t=String(s.name??s.companyName??s.business_name??"Unknown").trim();if(r)return{id:r,name:t}}return null}).filter(e=>null!==e):[]}async ensureGitignore(){const e=t.join(process.cwd(),".gitignore");if(!(await r.pathExists(e)))return;let s=await r.readFile(e,"utf8");s.includes(".dashnex")||(s=s.trimEnd(),s.endsWith("\n")||(s+="\n"),s+="\n.dashnex\n",await r.writeFile(e,s))}}export{l as LoginCommand};
|
package/dist/commands/logout.js
CHANGED
|
@@ -1,16 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import path from "path";
|
|
3
|
-
import chalk from "chalk";
|
|
4
|
-
class LogoutCommand {
|
|
5
|
-
async execute() {
|
|
6
|
-
const dashnexPath = path.join(process.cwd(), ".dashnex");
|
|
7
|
-
if (await fs.pathExists(dashnexPath)) {
|
|
8
|
-
await fs.remove(dashnexPath);
|
|
9
|
-
}
|
|
10
|
-
console.log(chalk.green("Logged out."));
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
export {
|
|
14
|
-
LogoutCommand
|
|
15
|
-
};
|
|
16
|
-
//# sourceMappingURL=logout.js.map
|
|
1
|
+
import o from"fs-extra";import e from"path";import t from"chalk";class a{async execute(){const a=e.join(process.cwd(),".dashnex");await o.pathExists(a)&&await o.remove(a),console.log(t.green("Logged out."))}}export{a as LogoutCommand};
|
package/dist/commands/pull.js
CHANGED
|
@@ -1,102 +1 @@
|
|
|
1
|
-
import chalk from "
|
|
2
|
-
import fs from "fs-extra";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import os from "os";
|
|
5
|
-
import inquirer from "inquirer";
|
|
6
|
-
import AdmZip from "adm-zip";
|
|
7
|
-
import { debug, debugError } from "../lib/debug.js";
|
|
8
|
-
import { getBusinessApiBase } from "../lib/api.js";
|
|
9
|
-
import { ensureLoggedIn } from "../services/auth.js";
|
|
10
|
-
const extractErrorMessage = (body) => {
|
|
11
|
-
if (typeof body.error === "string") return body.error;
|
|
12
|
-
if (typeof body.message === "string") return body.message;
|
|
13
|
-
return void 0;
|
|
14
|
-
};
|
|
15
|
-
const SUCCESS_MESSAGE_NEW = 'Application is successfully pulled. Run "npm install" or "pnpm install" to install dependencies and then "npx dashnex dev" to run it';
|
|
16
|
-
const getSuccessMessageNew = (targetDir, cwd) => {
|
|
17
|
-
if (path.resolve(targetDir) === path.resolve(cwd)) {
|
|
18
|
-
return SUCCESS_MESSAGE_NEW;
|
|
19
|
-
}
|
|
20
|
-
const folder = path.relative(cwd, targetDir);
|
|
21
|
-
return `Application is successfully pulled. Run 'cd ${folder}' then "pnpm install" or "npm install" to install dependencies and then "npx dashnex dev" to run it`;
|
|
22
|
-
};
|
|
23
|
-
class PullCommand {
|
|
24
|
-
async execute() {
|
|
25
|
-
debug("Pull flow started");
|
|
26
|
-
const session = await ensureLoggedIn();
|
|
27
|
-
if (!session) return;
|
|
28
|
-
const cwd = process.cwd();
|
|
29
|
-
const dashnexJsonPath = path.join(cwd, "dashnex.json");
|
|
30
|
-
const hasApp = await fs.pathExists(dashnexJsonPath);
|
|
31
|
-
debug(`Application check (dashnex.json): ${hasApp ? "present" : "absent"}`);
|
|
32
|
-
let targetDir;
|
|
33
|
-
if (hasApp) {
|
|
34
|
-
targetDir = cwd;
|
|
35
|
-
} else {
|
|
36
|
-
debug("No application yet, prompting for folder");
|
|
37
|
-
const { folder } = await inquirer.prompt([
|
|
38
|
-
{
|
|
39
|
-
type: "input",
|
|
40
|
-
name: "folder",
|
|
41
|
-
message: "Which folder to pull the application to?",
|
|
42
|
-
default: "."
|
|
43
|
-
}
|
|
44
|
-
]);
|
|
45
|
-
const resolved = path.resolve(cwd, folder.trim() || ".");
|
|
46
|
-
targetDir = resolved;
|
|
47
|
-
await fs.ensureDir(targetDir);
|
|
48
|
-
debug(`Target folder created/resolved: ${targetDir}`);
|
|
49
|
-
}
|
|
50
|
-
const url = `${getBusinessApiBase()}/business/v1/cli/pull`;
|
|
51
|
-
debug(`GET ${url}`);
|
|
52
|
-
const tempZipPath = path.join(
|
|
53
|
-
os.tmpdir(),
|
|
54
|
-
`dashnex-pull-${Date.now()}-${Math.random().toString(36).slice(2)}.zip`
|
|
55
|
-
);
|
|
56
|
-
try {
|
|
57
|
-
const response = await fetch(url, {
|
|
58
|
-
headers: { Authorization: `Bearer ${session.token}` }
|
|
59
|
-
});
|
|
60
|
-
debug(`Response: ${response.status}`);
|
|
61
|
-
if (!response.ok) {
|
|
62
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
63
|
-
let message = "Failed to pull application.";
|
|
64
|
-
if (response.status === 401 || response.status === 403) {
|
|
65
|
-
message = "Please run 'npx dashnex login' to authenticate.";
|
|
66
|
-
} else if (response.status === 404) {
|
|
67
|
-
message = "Business has no application. Run 'npx dashnex create' to create one.";
|
|
68
|
-
} else if (contentType.includes("application/json")) {
|
|
69
|
-
const body = await response.json().catch(() => ({}));
|
|
70
|
-
const apiMessage = extractErrorMessage(body);
|
|
71
|
-
if (apiMessage) message = apiMessage;
|
|
72
|
-
}
|
|
73
|
-
console.error(chalk.red(message));
|
|
74
|
-
process.exit(1);
|
|
75
|
-
}
|
|
76
|
-
const buffer = Buffer.from(await response.arrayBuffer());
|
|
77
|
-
await fs.writeFile(tempZipPath, buffer);
|
|
78
|
-
debug("Zip written to temp file");
|
|
79
|
-
const zip = new AdmZip(tempZipPath);
|
|
80
|
-
zip.extractAllTo(targetDir, true);
|
|
81
|
-
debug("Extracted to target folder");
|
|
82
|
-
if (hasApp) {
|
|
83
|
-
console.log(chalk.green(`Application pulled to ${targetDir}`));
|
|
84
|
-
} else {
|
|
85
|
-
console.log(chalk.green(getSuccessMessageNew(targetDir, cwd)));
|
|
86
|
-
}
|
|
87
|
-
} catch (error) {
|
|
88
|
-
debugError(error);
|
|
89
|
-
if (error instanceof Error && error.message.startsWith("EXIT:")) throw error;
|
|
90
|
-
console.error(chalk.red("Could not reach DashNex API. Check your connection and try again."));
|
|
91
|
-
process.exit(1);
|
|
92
|
-
} finally {
|
|
93
|
-
await fs.remove(tempZipPath).catch(() => {
|
|
94
|
-
});
|
|
95
|
-
debug("Temp zip removed");
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
export {
|
|
100
|
-
PullCommand
|
|
101
|
-
};
|
|
102
|
-
//# sourceMappingURL=pull.js.map
|
|
1
|
+
import e from"chalk";import t from"fs-extra";import o from"path";import s from"os";import n from"inquirer";import r from"adm-zip";import{debug as a,debugError as i}from"../lib/debug.js";import{getBusinessApiBase as l}from"../lib/api.js";import{ensureLoggedIn as p}from"../services/auth.js";class c{async execute(){a("Pull flow started");const c=await p();if(!c)return;const d=process.cwd(),f=o.join(d,"dashnex.json"),u=await t.pathExists(f);let m;if(a("Application check (dashnex.json): "+(u?"present":"absent")),u)m=d;else{a("No application yet, prompting for folder");const{folder:e}=await n.prompt([{type:"input",name:"folder",message:"Which folder to pull the application to?",default:"."}]);m=o.resolve(d,e.trim()||"."),await t.ensureDir(m),a(`Target folder created/resolved: ${m}`)}const h=`${l()}/business/v1/cli/pull`;a(`GET ${h}`);const x=o.join(s.tmpdir(),`dashnex-pull-${Date.now()}-${Math.random().toString(36).slice(2)}.zip`);try{const s=await fetch(h,{headers:{Authorization:`Bearer ${c.token}`}});if(a(`Response: ${s.status}`),!s.ok){const t=s.headers.get("content-type")??"";let o="Failed to pull application.";if(401===s.status||403===s.status)o="Please run 'npx dashnex login' to authenticate.";else if(404===s.status)o="Business has no application. Run 'npx dashnex create' to create one.";else if(t.includes("application/json")){const e=(e=>"string"==typeof e.error?e.error:"string"==typeof e.message?e.message:void 0)(await s.json().catch(()=>({})));e&&(o=e)}console.error(e.red(o)),process.exit(1)}const n=Buffer.from(await s.arrayBuffer());await t.writeFile(x,n),a("Zip written to temp file");new r(x).extractAllTo(m,!0),a("Extracted to target folder"),u?console.log(e.green(`Application pulled to ${m}`)):console.log(e.green(((e,t)=>o.resolve(e)===o.resolve(t)?'Application is successfully pulled. Run "npm install" or "pnpm install" to install dependencies and then "npx dashnex dev" to run it':`Application is successfully pulled. Run 'cd ${o.relative(t,e)}' then "pnpm install" or "npm install" to install dependencies and then "npx dashnex dev" to run it`)(m,d)))}catch(g){if(i(g),g instanceof Error&&g.message.startsWith("EXIT:"))throw g;console.error(e.red("Could not reach DashNex API. Check your connection and try again.")),process.exit(1)}finally{await t.remove(x).catch(()=>{}),a("Temp zip removed")}}}export{c as PullCommand};
|
package/dist/commands/push.js
CHANGED
|
@@ -1,108 +1 @@
|
|
|
1
|
-
import chalk from "
|
|
2
|
-
import fs from "fs-extra";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import os from "os";
|
|
5
|
-
import AdmZip from "adm-zip";
|
|
6
|
-
import ignore from "ignore";
|
|
7
|
-
import { debug, debugError } from "../lib/debug.js";
|
|
8
|
-
import { getBusinessApiBase } from "../lib/api.js";
|
|
9
|
-
import { ensureLoggedIn } from "../services/auth.js";
|
|
10
|
-
const extractErrorMessage = (body) => {
|
|
11
|
-
if (typeof body.error === "string") return body.error;
|
|
12
|
-
if (typeof body.message === "string") return body.message;
|
|
13
|
-
return void 0;
|
|
14
|
-
};
|
|
15
|
-
const ALWAYS_EXCLUDE = [".dashnex", ".git"];
|
|
16
|
-
const collectFilesToInclude = async (dir, ig) => {
|
|
17
|
-
const result = [];
|
|
18
|
-
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
19
|
-
for (const entry of entries) {
|
|
20
|
-
const relativePath = path.relative(process.cwd(), path.join(dir, entry.name));
|
|
21
|
-
const normalized = relativePath.split(path.sep).join("/");
|
|
22
|
-
if (ALWAYS_EXCLUDE.some((ex) => normalized === ex || normalized.startsWith(`${ex}/`))) {
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
if (ig.ignores(normalized)) {
|
|
26
|
-
continue;
|
|
27
|
-
}
|
|
28
|
-
const fullPath = path.join(dir, entry.name);
|
|
29
|
-
if (entry.isDirectory()) {
|
|
30
|
-
const nested = await collectFilesToInclude(fullPath, ig);
|
|
31
|
-
result.push(...nested);
|
|
32
|
-
} else if (entry.isFile()) {
|
|
33
|
-
result.push(fullPath);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return result;
|
|
37
|
-
};
|
|
38
|
-
class PushCommand {
|
|
39
|
-
async execute() {
|
|
40
|
-
debug("Push flow started");
|
|
41
|
-
const session = await ensureLoggedIn();
|
|
42
|
-
if (!session) return;
|
|
43
|
-
const cwd = process.cwd();
|
|
44
|
-
const gitignorePath = path.join(cwd, ".gitignore");
|
|
45
|
-
const ig = ignore();
|
|
46
|
-
ig.add(ALWAYS_EXCLUDE);
|
|
47
|
-
if (await fs.pathExists(gitignorePath)) {
|
|
48
|
-
const content = await fs.readFile(gitignorePath, "utf8");
|
|
49
|
-
ig.add(content);
|
|
50
|
-
}
|
|
51
|
-
debug("Building file list");
|
|
52
|
-
const files = await collectFilesToInclude(cwd, ig);
|
|
53
|
-
debug(`Including ${files.length} files`);
|
|
54
|
-
const zip = new AdmZip();
|
|
55
|
-
for (const filePath of files) {
|
|
56
|
-
const relativePath = path.relative(cwd, filePath);
|
|
57
|
-
const entryPath = relativePath.split(path.sep).join("/");
|
|
58
|
-
const zipPath = path.dirname(entryPath) === "." ? "" : path.dirname(entryPath);
|
|
59
|
-
const zipName = path.basename(entryPath);
|
|
60
|
-
zip.addLocalFile(filePath, zipPath, zipName);
|
|
61
|
-
}
|
|
62
|
-
const tempZipPath = path.join(
|
|
63
|
-
os.tmpdir(),
|
|
64
|
-
`dashnex-push-${Date.now()}-${Math.random().toString(36).slice(2)}.zip`
|
|
65
|
-
);
|
|
66
|
-
try {
|
|
67
|
-
zip.writeZip(tempZipPath);
|
|
68
|
-
debug(`Zip written to ${tempZipPath}`);
|
|
69
|
-
const url = `${getBusinessApiBase()}/business/v1/cli/push`;
|
|
70
|
-
debug(`POST ${url}`);
|
|
71
|
-
const formData = new FormData();
|
|
72
|
-
formData.append("file", new Blob([await fs.readFile(tempZipPath)]), "archive.zip");
|
|
73
|
-
const response = await fetch(url, {
|
|
74
|
-
method: "POST",
|
|
75
|
-
headers: { Authorization: `Bearer ${session.token}` },
|
|
76
|
-
body: formData
|
|
77
|
-
});
|
|
78
|
-
debug(`Response: ${response.status}`);
|
|
79
|
-
if (!response.ok) {
|
|
80
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
81
|
-
let message = "Failed to push application.";
|
|
82
|
-
if (response.status === 401 || response.status === 403) {
|
|
83
|
-
message = "Please run 'npx dashnex login' to authenticate.";
|
|
84
|
-
} else if (contentType.includes("application/json")) {
|
|
85
|
-
const body = await response.json().catch(() => ({}));
|
|
86
|
-
const apiMessage = extractErrorMessage(body);
|
|
87
|
-
if (apiMessage) message = apiMessage;
|
|
88
|
-
}
|
|
89
|
-
console.error(chalk.red(message));
|
|
90
|
-
process.exit(1);
|
|
91
|
-
}
|
|
92
|
-
console.log(chalk.green("Application pushed successfully."));
|
|
93
|
-
} catch (error) {
|
|
94
|
-
debugError(error);
|
|
95
|
-
if (error instanceof Error && error.message.startsWith("EXIT:")) throw error;
|
|
96
|
-
console.error(chalk.red("Could not reach DashNex API. Check your connection and try again."));
|
|
97
|
-
process.exit(1);
|
|
98
|
-
} finally {
|
|
99
|
-
await fs.remove(tempZipPath).catch(() => {
|
|
100
|
-
});
|
|
101
|
-
debug("Temp zip removed");
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
export {
|
|
106
|
-
PushCommand
|
|
107
|
-
};
|
|
108
|
-
//# sourceMappingURL=push.js.map
|
|
1
|
+
import e from"chalk";import t from"fs-extra";import o from"path";import i from"os";import s from"adm-zip";import a from"ignore";import{debug as n,debugError as r}from"../lib/debug.js";import{getBusinessApiBase as c}from"../lib/api.js";import{ensureLoggedIn as p}from"../services/auth.js";const l=[".dashnex",".git"],d=async(e,i)=>{const s=[],a=await t.readdir(e,{withFileTypes:!0});for(const t of a){const a=o.relative(process.cwd(),o.join(e,t.name)).split(o.sep).join("/");if(l.some(e=>a===e||a.startsWith(`${e}/`)))continue;if(i.ignores(a))continue;const n=o.join(e,t.name);if(t.isDirectory()){const e=await d(n,i);s.push(...e)}else t.isFile()&&s.push(n)}return s};class m{async execute(){n("Push flow started");const m=await p();if(!m)return;const f=process.cwd(),h=o.join(f,".gitignore"),u=a();if(u.add(l),await t.pathExists(h)){const e=await t.readFile(h,"utf8");u.add(e)}n("Building file list");const w=await d(f,u);n(`Including ${w.length} files`);const g=new s;for(const e of w){const t=o.relative(f,e).split(o.sep).join("/"),i="."===o.dirname(t)?"":o.dirname(t),s=o.basename(t);g.addLocalFile(e,i,s)}const y=o.join(i.tmpdir(),`dashnex-push-${Date.now()}-${Math.random().toString(36).slice(2)}.zip`);try{g.writeZip(y),n(`Zip written to ${y}`);const o=`${c()}/business/v1/cli/push`;n(`POST ${o}`);const i=new FormData;i.append("file",new Blob([await t.readFile(y)]),"archive.zip");const s=await fetch(o,{method:"POST",headers:{Authorization:`Bearer ${m.token}`},body:i});if(n(`Response: ${s.status}`),!s.ok){const t=s.headers.get("content-type")??"";let o="Failed to push application.";if(401===s.status||403===s.status)o="Please run 'npx dashnex login' to authenticate.";else if(t.includes("application/json")){const e=(e=>"string"==typeof e.error?e.error:"string"==typeof e.message?e.message:void 0)(await s.json().catch(()=>({})));e&&(o=e)}console.error(e.red(o)),process.exit(1)}console.log(e.green("Application pushed successfully."))}catch(j){if(r(j),j instanceof Error&&j.message.startsWith("EXIT:"))throw j;console.error(e.red("Could not reach DashNex API. Check your connection and try again.")),process.exit(1)}finally{await t.remove(y).catch(()=>{}),n("Temp zip removed")}}}export{m as PushCommand};
|
package/dist/commands/version.js
CHANGED
|
@@ -1,10 +1 @@
|
|
|
1
|
-
class
|
|
2
|
-
async execute(options) {
|
|
3
|
-
const packageJson = await import("../package.json.js");
|
|
4
|
-
console.log(packageJson.default.version);
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
export {
|
|
8
|
-
VersionCommand as default
|
|
9
|
-
};
|
|
10
|
-
//# sourceMappingURL=version.js.map
|
|
1
|
+
class a{async execute(a){const e=await import("../package.json.js");console.log(e.default.version)}}export{a as default};
|
package/dist/commands/whoami.js
CHANGED
|
@@ -1,52 +1 @@
|
|
|
1
|
-
import chalk from "
|
|
2
|
-
import { debug, debugError } from "../lib/debug.js";
|
|
3
|
-
import { getApiBase } from "../lib/api.js";
|
|
4
|
-
import { ensureLoggedIn } from "../services/auth.js";
|
|
5
|
-
const extractErrorMessage = (body) => {
|
|
6
|
-
if (typeof body.error === "string") return body.error;
|
|
7
|
-
if (typeof body.message === "string") return body.message;
|
|
8
|
-
return void 0;
|
|
9
|
-
};
|
|
10
|
-
class WhoamiCommand {
|
|
11
|
-
async execute() {
|
|
12
|
-
debug("Whoami flow started");
|
|
13
|
-
const session = await ensureLoggedIn();
|
|
14
|
-
if (!session) return;
|
|
15
|
-
const url = `${getApiBase()}/users/v1/`;
|
|
16
|
-
debug(`GET ${url}`);
|
|
17
|
-
try {
|
|
18
|
-
const response = await fetch(url, {
|
|
19
|
-
headers: { Authorization: `Bearer ${session.token}` }
|
|
20
|
-
});
|
|
21
|
-
debug(`Response: ${response.status}`);
|
|
22
|
-
if (!response.ok) {
|
|
23
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
24
|
-
let message = "Failed to fetch user info.";
|
|
25
|
-
if (response.status === 401 || response.status === 403) {
|
|
26
|
-
message = "Please run 'npx dashnex login' to authenticate.";
|
|
27
|
-
} else if (contentType.includes("application/json")) {
|
|
28
|
-
const body = await response.json().catch(() => ({}));
|
|
29
|
-
const apiMessage = extractErrorMessage(body);
|
|
30
|
-
if (apiMessage) message = apiMessage;
|
|
31
|
-
}
|
|
32
|
-
console.error(chalk.red(message));
|
|
33
|
-
process.exit(1);
|
|
34
|
-
}
|
|
35
|
-
const data = await response.json().catch(() => ({}));
|
|
36
|
-
const businessName = typeof data.name === "string" ? data.name : typeof data.companyName === "string" ? data.companyName : "Unknown";
|
|
37
|
-
const memberUser = data.memberUser;
|
|
38
|
-
const userName = memberUser && typeof memberUser.fullName === "string" ? memberUser.fullName : memberUser && typeof memberUser.name === "string" ? memberUser.name : "Unknown";
|
|
39
|
-
debug(`Whoami: ${businessName} (${userName})`);
|
|
40
|
-
console.log(chalk.green(`You are logged in as ${businessName} (${userName})`));
|
|
41
|
-
} catch (error) {
|
|
42
|
-
debugError(error);
|
|
43
|
-
if (error instanceof Error && error.message.startsWith("EXIT:")) throw error;
|
|
44
|
-
console.error(chalk.red("Could not reach DashNex API. Check your connection and try again."));
|
|
45
|
-
process.exit(1);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
export {
|
|
50
|
-
WhoamiCommand
|
|
51
|
-
};
|
|
52
|
-
//# sourceMappingURL=whoami.js.map
|
|
1
|
+
import e from"chalk";import{debug as t,debugError as o}from"../lib/debug.js";import{getApiBase as s}from"../lib/api.js";import{ensureLoggedIn as r}from"../services/auth.js";class a{async execute(){t("Whoami flow started");const a=await r();if(!a)return;const n=`${s()}/users/v1/`;t(`GET ${n}`);try{const o=await fetch(n,{headers:{Authorization:`Bearer ${a.token}`}});if(t(`Response: ${o.status}`),!o.ok){const t=o.headers.get("content-type")??"";let s="Failed to fetch user info.";if(401===o.status||403===o.status)s="Please run 'npx dashnex login' to authenticate.";else if(t.includes("application/json")){const e=(e=>"string"==typeof e.error?e.error:"string"==typeof e.message?e.message:void 0)(await o.json().catch(()=>({})));e&&(s=e)}console.error(e.red(s)),process.exit(1)}const s=await o.json().catch(()=>({})),r="string"==typeof s.name?s.name:"string"==typeof s.companyName?s.companyName:"Unknown",i=s.memberUser,c=i&&"string"==typeof i.fullName?i.fullName:i&&"string"==typeof i.name?i.name:"Unknown";t(`Whoami: ${r} (${c})`),console.log(e.green(`You are logged in as ${r} (${c})`))}catch(i){if(o(i),i instanceof Error&&i.message.startsWith("EXIT:"))throw i;console.error(e.red("Could not reach DashNex API. Check your connection and try again.")),process.exit(1)}}}export{a as WhoamiCommand};
|
package/dist/dashnex.json.js
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
declare const getApiBase: () => string;
|
|
2
|
+
declare const getBusinessApiBase: () => string;
|
|
3
|
+
declare const apiFetch: (url: string, options?: RequestInit) => Promise<{
|
|
4
|
+
response: Response;
|
|
5
|
+
body: Record<string, unknown>;
|
|
6
|
+
}>;
|
|
7
|
+
export { getApiBase, getBusinessApiBase, apiFetch };
|
package/dist/lib/api.js
CHANGED
|
@@ -1,23 +1 @@
|
|
|
1
|
-
const
|
|
2
|
-
return process.env.NEXT_PUBLIC_DASHNEX_API_DOMAIN || "https://api.dashnex.com";
|
|
3
|
-
};
|
|
4
|
-
const getBusinessApiBase = () => {
|
|
5
|
-
return process.env.DASHNEX_BUSINESS_API_URL || "https://api.business.dashnex.com";
|
|
6
|
-
};
|
|
7
|
-
const apiFetch = async (url, options = {}) => {
|
|
8
|
-
const response = await fetch(url, {
|
|
9
|
-
...options,
|
|
10
|
-
headers: {
|
|
11
|
-
"Content-Type": "application/json",
|
|
12
|
-
...options.headers
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
const body = await response.json().catch(() => ({}));
|
|
16
|
-
return { response, body };
|
|
17
|
-
};
|
|
18
|
-
export {
|
|
19
|
-
apiFetch,
|
|
20
|
-
getApiBase,
|
|
21
|
-
getBusinessApiBase
|
|
22
|
-
};
|
|
23
|
-
//# sourceMappingURL=api.js.map
|
|
1
|
+
const s=()=>process.env.NEXT_PUBLIC_DASHNEX_API_DOMAIN||"https://api.dashnex.com",e=()=>process.env.DASHNEX_BUSINESS_API_URL||"https://api.business.dashnex.com",n=async(s,e={})=>{const n=await fetch(s,{...e,headers:{"Content-Type":"application/json",...e.headers}}),t=await n.json().catch(()=>({}));return{response:n,body:t}};export{n as apiFetch,s as getApiBase,e as getBusinessApiBase};
|