nexusapp-cli 3.0.0 → 3.1.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/dist/client.d.ts +6 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +63 -0
- package/dist/client.js.map +1 -0
- package/dist/commands/auth.d.ts +3 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +178 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/bucket.d.ts +3 -0
- package/dist/commands/bucket.d.ts.map +1 -0
- package/dist/commands/bucket.js +354 -0
- package/dist/commands/bucket.js.map +1 -0
- package/dist/commands/database.d.ts +3 -0
- package/dist/commands/database.d.ts.map +1 -0
- package/dist/commands/database.js +350 -0
- package/dist/commands/database.js.map +1 -0
- package/dist/commands/deploy.d.ts +3 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +1009 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/domain.d.ts +3 -0
- package/dist/commands/domain.d.ts.map +1 -0
- package/dist/commands/domain.js +174 -0
- package/dist/commands/domain.js.map +1 -0
- package/dist/commands/exec.d.ts +3 -0
- package/dist/commands/exec.d.ts.map +1 -0
- package/dist/commands/exec.js +176 -0
- package/dist/commands/exec.js.map +1 -0
- package/dist/commands/managedDb.d.ts +3 -0
- package/dist/commands/managedDb.d.ts.map +1 -0
- package/dist/commands/managedDb.js +227 -0
- package/dist/commands/managedDb.js.map +1 -0
- package/dist/commands/member.d.ts +3 -0
- package/dist/commands/member.d.ts.map +1 -0
- package/dist/commands/member.js +175 -0
- package/dist/commands/member.js.map +1 -0
- package/dist/commands/project.d.ts +3 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +92 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/secret.d.ts +3 -0
- package/dist/commands/secret.d.ts.map +1 -0
- package/dist/commands/secret.js +121 -0
- package/dist/commands/secret.js.map +1 -0
- package/dist/commands/token.d.ts +3 -0
- package/dist/commands/token.d.ts.map +1 -0
- package/dist/commands/token.js +179 -0
- package/dist/commands/token.js.map +1 -0
- package/dist/commands/volume.d.ts +3 -0
- package/dist/commands/volume.d.ts.map +1 -0
- package/dist/commands/volume.js +149 -0
- package/dist/commands/volume.js.map +1 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +53 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/output.d.ts +9 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +71 -0
- package/dist/output.js.map +1 -0
- package/package.json +6 -2
- package/src/client.ts +0 -68
- package/src/commands/auth.ts +0 -186
- package/src/commands/bucket.ts +0 -261
- package/src/commands/database.ts +0 -305
- package/src/commands/deploy.ts +0 -904
- package/src/commands/domain.ts +0 -167
- package/src/commands/exec.ts +0 -154
- package/src/commands/managedDb.ts +0 -170
- package/src/commands/member.ts +0 -168
- package/src/commands/project.ts +0 -81
- package/src/commands/secret.ts +0 -117
- package/src/commands/token.ts +0 -173
- package/src/commands/volume.ts +0 -113
- package/src/config.ts +0 -56
- package/src/index.ts +0 -39
- package/src/output.ts +0 -65
- package/tsconfig.json +0 -19
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
export declare const client: AxiosInstance;
|
|
3
|
+
/** Unwrap { success, data } envelope if present, otherwise return as-is. */
|
|
4
|
+
export declare function unwrap(responseData: any): any;
|
|
5
|
+
export declare function apiError(error: unknown): string;
|
|
6
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,aAAa,EAAc,MAAM,OAAO,CAAC;AAkDzD,eAAO,MAAM,MAAM,eAAiB,CAAC;AAErC,4EAA4E;AAC5E,wBAAgB,MAAM,CAAC,YAAY,EAAE,GAAG,GAAG,GAAG,CAK7C;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAO/C"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.client = void 0;
|
|
7
|
+
exports.unwrap = unwrap;
|
|
8
|
+
exports.apiError = apiError;
|
|
9
|
+
const axios_1 = __importDefault(require("axios"));
|
|
10
|
+
const config_js_1 = require("./config.js");
|
|
11
|
+
function createClient() {
|
|
12
|
+
const config = (0, config_js_1.getConfig)();
|
|
13
|
+
const baseURL = config.apiUrl || 'https://nexusai.run';
|
|
14
|
+
const instance = axios_1.default.create({
|
|
15
|
+
baseURL,
|
|
16
|
+
timeout: 30000,
|
|
17
|
+
});
|
|
18
|
+
instance.interceptors.request.use((req) => {
|
|
19
|
+
const cfg = (0, config_js_1.getConfig)();
|
|
20
|
+
if (cfg.token) {
|
|
21
|
+
req.headers = req.headers || {};
|
|
22
|
+
req.headers['Authorization'] = `Bearer ${cfg.token}`;
|
|
23
|
+
}
|
|
24
|
+
return req;
|
|
25
|
+
});
|
|
26
|
+
instance.interceptors.response.use((res) => res, (error) => {
|
|
27
|
+
if (!error.response) {
|
|
28
|
+
const url = baseURL;
|
|
29
|
+
console.error(`Cannot reach NEXUS AI API at ${url}.`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
const status = error.response.status;
|
|
33
|
+
const data = error.response.data;
|
|
34
|
+
if (status === 401) {
|
|
35
|
+
console.error("Session expired. Run 'nexus auth login'");
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
if (status === 403) {
|
|
39
|
+
console.error(data?.message || data?.error || 'Access denied.');
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
return Promise.reject(error);
|
|
43
|
+
});
|
|
44
|
+
return instance;
|
|
45
|
+
}
|
|
46
|
+
exports.client = createClient();
|
|
47
|
+
/** Unwrap { success, data } envelope if present, otherwise return as-is. */
|
|
48
|
+
function unwrap(responseData) {
|
|
49
|
+
if (responseData && typeof responseData === 'object' && 'data' in responseData) {
|
|
50
|
+
return responseData.data;
|
|
51
|
+
}
|
|
52
|
+
return responseData;
|
|
53
|
+
}
|
|
54
|
+
function apiError(error) {
|
|
55
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
56
|
+
const data = error.response?.data;
|
|
57
|
+
return data?.message || data?.error || error.message;
|
|
58
|
+
}
|
|
59
|
+
if (error instanceof Error)
|
|
60
|
+
return error.message;
|
|
61
|
+
return String(error);
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;;;;AAqDA,wBAKC;AAED,4BAOC;AAnED,kDAAyD;AACzD,2CAAwC;AAExC,SAAS,YAAY;IACnB,MAAM,MAAM,GAAG,IAAA,qBAAS,GAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,IAAI,qBAAqB,CAAC;IAEvD,MAAM,QAAQ,GAAG,eAAK,CAAC,MAAM,CAAC;QAC5B,OAAO;QACP,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;IAEH,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACxC,MAAM,GAAG,GAAG,IAAA,qBAAS,GAAE,CAAC;QACxB,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;YAChC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,GAAG,CAAC,KAAK,EAAE,CAAC;QACvD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAChC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EACZ,CAAC,KAAiB,EAAE,EAAE;QACpB,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,OAAO,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,gCAAgC,GAAG,GAAG,CAAC,CAAC;YACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAW,CAAC;QAExC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;YACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,IAAI,IAAI,EAAE,KAAK,IAAI,gBAAgB,CAAC,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC,CACF,CAAC;IAEF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAEY,QAAA,MAAM,GAAG,YAAY,EAAE,CAAC;AAErC,4EAA4E;AAC5E,SAAgB,MAAM,CAAC,YAAiB;IACtC,IAAI,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,MAAM,IAAI,YAAY,EAAE,CAAC;QAC/E,OAAO,YAAY,CAAC,IAAI,CAAC;IAC3B,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,SAAgB,QAAQ,CAAC,KAAc;IACrC,IAAI,eAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAW,CAAC;QACzC,OAAO,IAAI,EAAE,OAAO,IAAI,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC;IACvD,CAAC;IACD,IAAI,KAAK,YAAY,KAAK;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IACjD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyEpC,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgHnD"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerAuth = registerAuth;
|
|
7
|
+
const http_1 = __importDefault(require("http"));
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const axios_1 = __importDefault(require("axios"));
|
|
10
|
+
const config_js_1 = require("../config.js");
|
|
11
|
+
const client_js_1 = require("../client.js");
|
|
12
|
+
const output_js_1 = require("../output.js");
|
|
13
|
+
function openBrowser(url) {
|
|
14
|
+
const platform = process.platform;
|
|
15
|
+
if (platform === 'darwin') {
|
|
16
|
+
(0, child_process_1.execFile)('open', [url], () => { });
|
|
17
|
+
}
|
|
18
|
+
else if (platform === 'win32') {
|
|
19
|
+
(0, child_process_1.execFile)('cmd', ['/c', 'start', '', url], () => { });
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
(0, child_process_1.execFile)('xdg-open', [url], () => { });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function successHtml(webUrl) {
|
|
26
|
+
return `<!DOCTYPE html><html><head><meta charset="utf-8"><title>NEXUS AI CLI</title>
|
|
27
|
+
<style>
|
|
28
|
+
*{box-sizing:border-box;margin:0;padding:0}
|
|
29
|
+
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;background:#0b0c12;color:#e5e7eb}
|
|
30
|
+
.box{text-align:center;padding:2.5rem 3rem;background:#ffffff08;border:1px solid #ffffff14;border-radius:1.25rem;max-width:360px;width:90%}
|
|
31
|
+
.logo{display:flex;align-items:center;justify-content:center;gap:.65rem;margin-bottom:2rem}
|
|
32
|
+
.logo img{height:2.25rem;width:2.25rem}
|
|
33
|
+
.logo-name{font-size:1rem;font-weight:600;color:#fff;letter-spacing:-.01em}
|
|
34
|
+
.check{width:2.75rem;height:2.75rem;background:#0ea5e920;border-radius:50%;display:flex;align-items:center;justify-content:center;margin:0 auto 1.25rem}
|
|
35
|
+
.check svg{width:1.25rem;height:1.25rem;stroke:#38bdf8;fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round}
|
|
36
|
+
.title{font-size:1.2rem;font-weight:700;color:#fff;margin-bottom:.4rem}
|
|
37
|
+
.sub{color:#6b7280;font-size:.85rem;line-height:1.5}
|
|
38
|
+
</style></head>
|
|
39
|
+
<body><div class="box">
|
|
40
|
+
<div class="logo">
|
|
41
|
+
<img src="${webUrl}/logo.svg" alt="NEXUS AI" onerror="this.style.display='none'">
|
|
42
|
+
<span class="logo-name">NEXUS AI</span>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="check"><svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg></div>
|
|
45
|
+
<div class="title">Authorization successful</div>
|
|
46
|
+
<div class="sub">You can close this tab and return to your terminal.</div>
|
|
47
|
+
</div></body></html>`;
|
|
48
|
+
}
|
|
49
|
+
function waitForCallback(server, webUrl) {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
const timeout = setTimeout(() => {
|
|
52
|
+
server.close();
|
|
53
|
+
reject(new Error('Timed out waiting for browser authorization (2 minutes).'));
|
|
54
|
+
}, 120000);
|
|
55
|
+
server.on('request', (req, res) => {
|
|
56
|
+
const url = new URL(req.url, `http://localhost`);
|
|
57
|
+
const token = url.searchParams.get('token');
|
|
58
|
+
const tokenId = url.searchParams.get('tokenId') || '';
|
|
59
|
+
const email = url.searchParams.get('email') || '';
|
|
60
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
61
|
+
res.end(successHtml(webUrl));
|
|
62
|
+
clearTimeout(timeout);
|
|
63
|
+
server.close();
|
|
64
|
+
if (!token) {
|
|
65
|
+
reject(new Error('No token received from browser.'));
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
resolve({ token, tokenId, email });
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function registerAuth(program) {
|
|
74
|
+
const auth = program.command('auth').description('Authentication commands');
|
|
75
|
+
// login
|
|
76
|
+
auth
|
|
77
|
+
.command('login')
|
|
78
|
+
.description('Log in to NEXUS AI via browser')
|
|
79
|
+
.option('--api-url <url>', 'Backend API base URL (e.g. http://localhost:3001)')
|
|
80
|
+
.option('--web-url <url>', 'Frontend URL (e.g. http://localhost:3002)')
|
|
81
|
+
.option('--token <token>', 'Use an existing nxk_* access token directly')
|
|
82
|
+
.action(async (opts) => {
|
|
83
|
+
const apiUrl = opts.apiUrl || process.env.NEXUSAI_API_URL || 'https://nexusai.run';
|
|
84
|
+
const webUrl = opts.webUrl || process.env.NEXUSAI_WEB_URL
|
|
85
|
+
|| apiUrl.replace(':3001', ':3002').replace('api.nexusai.run', 'nexusai.run');
|
|
86
|
+
// --token shortcut: skip browser
|
|
87
|
+
if (opts.token) {
|
|
88
|
+
try {
|
|
89
|
+
const res = await axios_1.default.get(`${apiUrl}/api/auth/verify`, {
|
|
90
|
+
headers: { Authorization: `Bearer ${opts.token}` },
|
|
91
|
+
});
|
|
92
|
+
const user = res.data;
|
|
93
|
+
(0, config_js_1.saveConfig)({ apiUrl, token: opts.token, tokenId: '' });
|
|
94
|
+
(0, output_js_1.success)(`Logged in as ${user.email || user.user?.email}`);
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
(0, output_js_1.errorMsg)('Token verification failed: ' + (0, client_js_1.apiError)(err));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// Start local callback server on a random port
|
|
103
|
+
const server = http_1.default.createServer();
|
|
104
|
+
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
|
|
105
|
+
const port = server.address().port;
|
|
106
|
+
const callbackUrl = `http://localhost:${port}`;
|
|
107
|
+
const authUrl = `${webUrl}/cli-auth?callback=${encodeURIComponent(callbackUrl)}`;
|
|
108
|
+
console.log('');
|
|
109
|
+
console.log('Opening your browser to complete login...');
|
|
110
|
+
console.log('');
|
|
111
|
+
console.log(` ${authUrl}`);
|
|
112
|
+
console.log('');
|
|
113
|
+
console.log('If the browser did not open, copy the URL above into your browser.');
|
|
114
|
+
console.log('');
|
|
115
|
+
openBrowser(authUrl);
|
|
116
|
+
const spin = (0, output_js_1.spinner)('Waiting for browser authorization...');
|
|
117
|
+
try {
|
|
118
|
+
const { token, tokenId, email } = await waitForCallback(server, webUrl);
|
|
119
|
+
(0, config_js_1.saveConfig)({ apiUrl, token, tokenId });
|
|
120
|
+
spin.stop();
|
|
121
|
+
(0, output_js_1.success)(`Logged in as ${email}`);
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
spin.fail(err instanceof Error ? err.message : String(err));
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
// logout
|
|
129
|
+
auth
|
|
130
|
+
.command('logout')
|
|
131
|
+
.description('Log out and revoke access token')
|
|
132
|
+
.action(async () => {
|
|
133
|
+
const config = (0, config_js_1.getConfig)();
|
|
134
|
+
if (!config.token) {
|
|
135
|
+
console.log('Not logged in.');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (config.tokenId) {
|
|
139
|
+
try {
|
|
140
|
+
await client_js_1.client.post(`/api/tokens/${config.tokenId}/revoke`);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// best-effort revocation
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
(0, config_js_1.clearConfig)();
|
|
147
|
+
(0, output_js_1.success)('Logged out.');
|
|
148
|
+
});
|
|
149
|
+
// whoami
|
|
150
|
+
auth
|
|
151
|
+
.command('whoami')
|
|
152
|
+
.description('Show current authenticated user')
|
|
153
|
+
.option('--json', 'Output raw JSON')
|
|
154
|
+
.action(async (opts) => {
|
|
155
|
+
try {
|
|
156
|
+
const res = await client_js_1.client.get('/api/auth/verify');
|
|
157
|
+
const user = (0, client_js_1.unwrap)(res.data);
|
|
158
|
+
if (opts.json) {
|
|
159
|
+
(0, output_js_1.printJson)(user);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const u = user.user || user;
|
|
163
|
+
const email = u.email || 'unknown';
|
|
164
|
+
const org = u.organization?.name || u.organizationId || '—';
|
|
165
|
+
const role = u.role || '—';
|
|
166
|
+
(0, output_js_1.printTable)(['Field', 'Value'], [
|
|
167
|
+
['Email', email],
|
|
168
|
+
['Organization', org],
|
|
169
|
+
['Role', role],
|
|
170
|
+
]);
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bucket.d.ts","sourceRoot":"","sources":["../../src/commands/bucket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqPrD"}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.registerBucket = registerBucket;
|
|
40
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const client_js_1 = require("../client.js");
|
|
44
|
+
const output_js_1 = require("../output.js");
|
|
45
|
+
function formatBytes(bytes) {
|
|
46
|
+
const n = typeof bytes === 'bigint' ? Number(bytes) : bytes;
|
|
47
|
+
if (n < 1024)
|
|
48
|
+
return `${n} B`;
|
|
49
|
+
if (n < 1024 * 1024)
|
|
50
|
+
return `${(n / 1024).toFixed(1)} KB`;
|
|
51
|
+
if (n < 1024 * 1024 * 1024)
|
|
52
|
+
return `${(n / (1024 * 1024)).toFixed(1)} MB`;
|
|
53
|
+
return `${(n / (1024 * 1024 * 1024)).toFixed(2)} GB`;
|
|
54
|
+
}
|
|
55
|
+
function registerBucket(program) {
|
|
56
|
+
const bk = program
|
|
57
|
+
.command('bucket')
|
|
58
|
+
.description('Object storage buckets (S3-compatible MinIO buckets)');
|
|
59
|
+
bk
|
|
60
|
+
.command('list')
|
|
61
|
+
.description('List buckets')
|
|
62
|
+
.option('--json', 'Output raw JSON')
|
|
63
|
+
.action(async (opts) => {
|
|
64
|
+
try {
|
|
65
|
+
const res = await client_js_1.client.get('/api/buckets');
|
|
66
|
+
const buckets = (0, client_js_1.unwrap)(res.data) || [];
|
|
67
|
+
if (opts.json) {
|
|
68
|
+
(0, output_js_1.printJson)(buckets);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (!buckets.length) {
|
|
72
|
+
console.log('No buckets found.');
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
(0, output_js_1.printTable)(['ID', 'NAME', 'SIZE', 'OBJECTS', 'ATTACHED TO', 'CREATED'], buckets.map((b) => [
|
|
76
|
+
b.id,
|
|
77
|
+
b.displayName ? `${b.name} (${b.displayName})` : b.name,
|
|
78
|
+
formatBytes(b.sizeBytes),
|
|
79
|
+
String(b.objectCount),
|
|
80
|
+
b.attachments?.length ? b.attachments.map((a) => a.deploymentName).join(', ') : '—',
|
|
81
|
+
b.createdAt ? (0, output_js_1.timeAgo)(b.createdAt) : '—',
|
|
82
|
+
]));
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
bk
|
|
90
|
+
.command('create <name>')
|
|
91
|
+
.description('Create a new bucket (org-scoped)')
|
|
92
|
+
.option('--display-name <name>', 'Friendly display name')
|
|
93
|
+
.option('--region <region>', 'Region', 'us-east-1')
|
|
94
|
+
.option('--json', 'Output raw JSON')
|
|
95
|
+
.action(async (name, opts) => {
|
|
96
|
+
try {
|
|
97
|
+
const res = await client_js_1.client.post('/api/buckets', {
|
|
98
|
+
name,
|
|
99
|
+
displayName: opts.displayName,
|
|
100
|
+
region: opts.region,
|
|
101
|
+
});
|
|
102
|
+
const b = (0, client_js_1.unwrap)(res.data);
|
|
103
|
+
if (opts.json) {
|
|
104
|
+
(0, output_js_1.printJson)(b);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
(0, output_js_1.success)(`Bucket created: ${b.id} (${b.name})`);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
bk
|
|
115
|
+
.command('delete <id>')
|
|
116
|
+
.description('Delete a bucket (must be detached first; deletes all objects)')
|
|
117
|
+
.option('--yes', 'Skip confirmation prompt')
|
|
118
|
+
.action(async (id, opts) => {
|
|
119
|
+
if (!opts.yes) {
|
|
120
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
121
|
+
{ type: 'confirm', name: 'confirm', message: `Delete bucket "${id}" and ALL its objects?`, default: false },
|
|
122
|
+
]);
|
|
123
|
+
if (!confirm) {
|
|
124
|
+
console.log('Cancelled.');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
await client_js_1.client.delete(`/api/buckets/${id}`);
|
|
130
|
+
(0, output_js_1.success)(`Bucket ${id} deleted.`);
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
bk
|
|
138
|
+
.command('attach <id> <deployment-id>')
|
|
139
|
+
.description('Attach a bucket to a deployment (injects S3_* env vars on next deploy)')
|
|
140
|
+
.action(async (id, deploymentId) => {
|
|
141
|
+
try {
|
|
142
|
+
await client_js_1.client.post(`/api/buckets/${id}/attach`, { deploymentId });
|
|
143
|
+
(0, output_js_1.success)(`Attached bucket ${id} to deployment ${deploymentId}.`);
|
|
144
|
+
console.log(" Run 'nexus deploy redeploy <id>' for env vars to take effect.");
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
bk
|
|
152
|
+
.command('detach <id> <deployment-id>')
|
|
153
|
+
.description('Detach a bucket from a deployment')
|
|
154
|
+
.action(async (id, deploymentId) => {
|
|
155
|
+
try {
|
|
156
|
+
await client_js_1.client.post(`/api/buckets/${id}/detach`, { deploymentId });
|
|
157
|
+
(0, output_js_1.success)(`Bucket ${id} detached from ${deploymentId}.`);
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
bk
|
|
165
|
+
.command('credentials <id>')
|
|
166
|
+
.description('Reveal the S3-compatible credentials for an external client (audit-logged)')
|
|
167
|
+
.option('--json', 'Output raw JSON')
|
|
168
|
+
.action(async (id, opts) => {
|
|
169
|
+
try {
|
|
170
|
+
const res = await client_js_1.client.get(`/api/buckets/${id}/credentials`);
|
|
171
|
+
const c = (0, client_js_1.unwrap)(res.data);
|
|
172
|
+
if (opts.json) {
|
|
173
|
+
(0, output_js_1.printJson)(c);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
console.log(`Endpoint: ${c.endpoint}`);
|
|
177
|
+
console.log(`Region: ${c.region}`);
|
|
178
|
+
console.log(`Bucket: ${c.bucket}`);
|
|
179
|
+
console.log(`Access key: ${c.accessKey}`);
|
|
180
|
+
console.log(`Secret key: ${c.secretKey}`);
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
bk
|
|
188
|
+
.command('rotate-credentials <id>')
|
|
189
|
+
.description('Rotate the per-bucket S3 access key (use to migrate legacy buckets to scoped IAM)')
|
|
190
|
+
.option('--yes', 'Skip confirmation prompt')
|
|
191
|
+
.action(async (id, opts) => {
|
|
192
|
+
if (!opts.yes) {
|
|
193
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
194
|
+
{
|
|
195
|
+
type: 'confirm',
|
|
196
|
+
name: 'confirm',
|
|
197
|
+
message: 'Rotate credentials? Attached deployments must be redeployed to pick up new S3_* env vars.',
|
|
198
|
+
default: false,
|
|
199
|
+
},
|
|
200
|
+
]);
|
|
201
|
+
if (!confirm) {
|
|
202
|
+
console.log('Cancelled.');
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
await client_js_1.client.post(`/api/buckets/${id}/rotate-credentials`);
|
|
208
|
+
(0, output_js_1.success)(`Credentials rotated. Redeploy any attached deployments.`);
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
bk
|
|
216
|
+
.command('refresh-usage <id>')
|
|
217
|
+
.description('Refresh size and object count for a bucket')
|
|
218
|
+
.option('--json', 'Output raw JSON')
|
|
219
|
+
.action(async (id, opts) => {
|
|
220
|
+
try {
|
|
221
|
+
const res = await client_js_1.client.post(`/api/buckets/${id}/refresh-usage`);
|
|
222
|
+
const b = (0, client_js_1.unwrap)(res.data);
|
|
223
|
+
if (opts.json) {
|
|
224
|
+
(0, output_js_1.printJson)(b);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
(0, output_js_1.success)(`${b.name}: ${formatBytes(b.sizeBytes)} across ${b.objectCount} object(s)`);
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
// ---- file ops ------------------------------------------------------------
|
|
235
|
+
bk
|
|
236
|
+
.command('files <id>')
|
|
237
|
+
.description('List files in a bucket')
|
|
238
|
+
.option('--prefix <prefix>', 'Filter by key prefix')
|
|
239
|
+
.option('--limit <n>', 'Max keys to return (default 1000)', '1000')
|
|
240
|
+
.option('--json', 'Output raw JSON')
|
|
241
|
+
.action(async (id, opts) => {
|
|
242
|
+
try {
|
|
243
|
+
const params = { limit: opts.limit };
|
|
244
|
+
if (opts.prefix)
|
|
245
|
+
params.prefix = opts.prefix;
|
|
246
|
+
const res = await client_js_1.client.get(`/api/buckets/${id}/files`, { params });
|
|
247
|
+
const data = (0, client_js_1.unwrap)(res.data);
|
|
248
|
+
if (opts.json) {
|
|
249
|
+
(0, output_js_1.printJson)(data);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (!data.objects?.length) {
|
|
253
|
+
console.log('Empty.');
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
(0, output_js_1.printTable)(['KEY', 'SIZE', 'MODIFIED'], data.objects.map((o) => [
|
|
257
|
+
o.key,
|
|
258
|
+
formatBytes(o.sizeBytes),
|
|
259
|
+
o.lastModified ? (0, output_js_1.timeAgo)(o.lastModified) : '—',
|
|
260
|
+
]));
|
|
261
|
+
if (data.truncated)
|
|
262
|
+
console.log(`(truncated — pass --limit to see more)`);
|
|
263
|
+
}
|
|
264
|
+
catch (err) {
|
|
265
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
bk
|
|
270
|
+
.command('upload <id> <local-file>')
|
|
271
|
+
.description('Upload a local file into the bucket')
|
|
272
|
+
.option('--key <key>', 'Object key (default: filename of local file)')
|
|
273
|
+
.action(async (id, localFile, opts) => {
|
|
274
|
+
try {
|
|
275
|
+
if (!fs.existsSync(localFile)) {
|
|
276
|
+
(0, output_js_1.errorMsg)(`File not found: ${localFile}`);
|
|
277
|
+
process.exit(1);
|
|
278
|
+
}
|
|
279
|
+
const key = opts.key || path.basename(localFile);
|
|
280
|
+
const stat = fs.statSync(localFile);
|
|
281
|
+
const stream = fs.createReadStream(localFile);
|
|
282
|
+
await client_js_1.client.put(`/api/buckets/${id}/files/${encodeURIComponent(key)}`, stream, { headers: { 'Content-Type': 'application/octet-stream', 'Content-Length': String(stat.size) } });
|
|
283
|
+
(0, output_js_1.success)(`Uploaded ${formatBytes(stat.size)} → ${key}`);
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
287
|
+
process.exit(1);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
bk
|
|
291
|
+
.command('download <id> <key>')
|
|
292
|
+
.description('Download a file from the bucket')
|
|
293
|
+
.option('--out <path>', 'Local output path (default: key basename)')
|
|
294
|
+
.option('--share', 'Print a short-lived signed URL instead of downloading')
|
|
295
|
+
.option('--ttl <seconds>', 'Lifetime for --share URL in seconds (30-3600, default 300)', '300')
|
|
296
|
+
.option('--json', 'Output raw JSON (only with --share)')
|
|
297
|
+
.action(async (id, key, opts) => {
|
|
298
|
+
try {
|
|
299
|
+
if (opts.share) {
|
|
300
|
+
const res = await client_js_1.client.post(`/api/buckets/${id}/files/${encodeURIComponent(key)}/download-url`, { ttlSeconds: parseInt(opts.ttl, 10) || 300 });
|
|
301
|
+
const data = (0, client_js_1.unwrap)(res.data);
|
|
302
|
+
if (opts.json) {
|
|
303
|
+
(0, output_js_1.printJson)(data);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
console.log(`URL: ${data.url}`);
|
|
307
|
+
console.log(`Key: ${data.key}`);
|
|
308
|
+
console.log(`Expires at: ${data.expiresAt}`);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const res = await client_js_1.client.get(`/api/buckets/${id}/files/${encodeURIComponent(key)}/download`, { responseType: 'stream' });
|
|
312
|
+
const outPath = path.resolve(opts.out || path.basename(key));
|
|
313
|
+
const dir = path.dirname(outPath);
|
|
314
|
+
if (!fs.existsSync(dir))
|
|
315
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
316
|
+
await new Promise((resolve, reject) => {
|
|
317
|
+
const writer = fs.createWriteStream(outPath);
|
|
318
|
+
res.data.pipe(writer);
|
|
319
|
+
writer.on('finish', () => resolve());
|
|
320
|
+
writer.on('error', reject);
|
|
321
|
+
res.data.on('error', reject);
|
|
322
|
+
});
|
|
323
|
+
(0, output_js_1.success)(`Downloaded → ${outPath}`);
|
|
324
|
+
}
|
|
325
|
+
catch (err) {
|
|
326
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
327
|
+
process.exit(1);
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
bk
|
|
331
|
+
.command('rm <id> <key>')
|
|
332
|
+
.description('Delete a file from the bucket')
|
|
333
|
+
.option('--yes', 'Skip confirmation prompt')
|
|
334
|
+
.action(async (id, key, opts) => {
|
|
335
|
+
if (!opts.yes) {
|
|
336
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
337
|
+
{ type: 'confirm', name: 'confirm', message: `Delete "${key}"?`, default: false },
|
|
338
|
+
]);
|
|
339
|
+
if (!confirm) {
|
|
340
|
+
console.log('Cancelled.');
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
try {
|
|
345
|
+
await client_js_1.client.delete(`/api/buckets/${id}/files/${encodeURIComponent(key)}`);
|
|
346
|
+
(0, output_js_1.success)(`Deleted ${key}`);
|
|
347
|
+
}
|
|
348
|
+
catch (err) {
|
|
349
|
+
(0, output_js_1.errorMsg)((0, client_js_1.apiError)(err));
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
//# sourceMappingURL=bucket.js.map
|