moontraze 1.0.5 → 1.0.7
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/moontraze.js +16 -37
- package/lib/auth.js +84 -59
- package/lib/config.js +11 -89
- package/lib/deploy.js +11 -20
- package/package.json +17 -6
- package/bin/moon.js +0 -172
package/bin/moontraze.js
CHANGED
|
@@ -2,52 +2,37 @@
|
|
|
2
2
|
const { Command } = require('commander');
|
|
3
3
|
const chalk = require('chalk');
|
|
4
4
|
const { login } = require('../lib/auth');
|
|
5
|
-
const {
|
|
6
|
-
getConfig,
|
|
7
|
-
getPlatform,
|
|
8
|
-
getProject,
|
|
9
|
-
setProject,
|
|
10
|
-
setPlatformToken,
|
|
11
|
-
} = require('../lib/config');
|
|
5
|
+
const { getConfig, setConfig, getProject, setProject } = require('../lib/config');
|
|
12
6
|
const { deploy } = require('../lib/deploy');
|
|
13
7
|
|
|
14
8
|
const program = new Command();
|
|
15
9
|
|
|
16
|
-
//
|
|
17
|
-
const platformName = process.env.
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
const apiUrl = process.env.MOON_API || platform?.apiUrl || 'https://api.moontraze.com';
|
|
21
|
-
const domain = process.env.MOON_DOMAIN || platform?.domain || 'moontraze.com';
|
|
10
|
+
// Moon CLI se aata hai
|
|
11
|
+
const platformName = process.env.MOON_PLATFORM || 'moontraze';
|
|
12
|
+
const apiUrl = process.env.MOON_API || getConfig().apiUrl || 'https://api.moontraze.com';
|
|
13
|
+
const domain = process.env.MOON_DOMAIN || getConfig().domain || 'moontraze.com';
|
|
22
14
|
|
|
23
15
|
program
|
|
24
16
|
.name(platformName)
|
|
25
|
-
.description(`Deploy sites using ${
|
|
26
|
-
.version('1.0.
|
|
17
|
+
.description(`Deploy sites using ${platformName}`)
|
|
18
|
+
.version('1.0.5');
|
|
27
19
|
|
|
28
|
-
//
|
|
20
|
+
// login
|
|
29
21
|
program
|
|
30
22
|
.command('login')
|
|
31
23
|
.description('Log in with email/password or token')
|
|
32
|
-
.option('--token <jwt>', 'JWT token (
|
|
24
|
+
.option('--token <jwt>', 'JWT token (skip interactive login)')
|
|
33
25
|
.action(async (opts) => {
|
|
34
26
|
try {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// token us platform ke under save karo
|
|
39
|
-
if (token) {
|
|
40
|
-
setPlatformToken(platformName, token);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
console.log(chalk.green(`✓ Logged in to ${platform?.label || platformName}`));
|
|
27
|
+
await login(opts.token, { apiUrl });
|
|
28
|
+
console.log(chalk.green(`✓ Logged in to ${platformName}`));
|
|
44
29
|
} catch (e) {
|
|
45
30
|
console.error(chalk.red('Login failed:'), e.message);
|
|
46
31
|
process.exit(1);
|
|
47
32
|
}
|
|
48
33
|
});
|
|
49
34
|
|
|
50
|
-
//
|
|
35
|
+
// link
|
|
51
36
|
program
|
|
52
37
|
.command('link [name]')
|
|
53
38
|
.description('Link this folder to a hosting project name')
|
|
@@ -55,7 +40,6 @@ program
|
|
|
55
40
|
try {
|
|
56
41
|
const prompts = require('prompts');
|
|
57
42
|
let projectName = name;
|
|
58
|
-
|
|
59
43
|
if (!projectName) {
|
|
60
44
|
const a = await prompts({
|
|
61
45
|
type: 'text',
|
|
@@ -68,28 +52,24 @@ program
|
|
|
68
52
|
});
|
|
69
53
|
projectName = a.n;
|
|
70
54
|
}
|
|
71
|
-
|
|
72
55
|
if (!projectName) process.exit(1);
|
|
73
|
-
|
|
74
56
|
projectName = projectName.toLowerCase().replace(/[^a-z0-9-]/g, '');
|
|
75
|
-
setProject({ projectName
|
|
76
|
-
|
|
57
|
+
setProject({ projectName });
|
|
77
58
|
console.log(chalk.green(`Linked → ${projectName}.${domain}`));
|
|
78
|
-
console.log(chalk.gray('(saved .
|
|
59
|
+
console.log(chalk.gray('(saved .moontraze/project.json)'));
|
|
79
60
|
} catch (e) {
|
|
80
61
|
console.error(chalk.red(e.message));
|
|
81
62
|
process.exit(1);
|
|
82
63
|
}
|
|
83
64
|
});
|
|
84
65
|
|
|
85
|
-
//
|
|
66
|
+
// deploy
|
|
86
67
|
async function runDeploy(opts) {
|
|
87
68
|
try {
|
|
88
69
|
await deploy({
|
|
89
70
|
prod: !!(opts.prod || opts.production),
|
|
90
71
|
projectName: opts.project || opts.name,
|
|
91
|
-
apiUrl,
|
|
92
|
-
platformName,
|
|
72
|
+
apiUrl,
|
|
93
73
|
domain,
|
|
94
74
|
});
|
|
95
75
|
} catch (e) {
|
|
@@ -106,7 +86,6 @@ program
|
|
|
106
86
|
.option('-p, --project <name>', 'Project name (or use link)')
|
|
107
87
|
.action(runDeploy);
|
|
108
88
|
|
|
109
|
-
// Direct flags: moon moontraze --prod
|
|
110
89
|
program
|
|
111
90
|
.option('--prod', 'Deploy to production')
|
|
112
91
|
.option('--production', 'Deploy to production')
|
package/lib/auth.js
CHANGED
|
@@ -2,25 +2,24 @@ const prompts = require('prompts');
|
|
|
2
2
|
const chalk = require('chalk');
|
|
3
3
|
const http = require('http');
|
|
4
4
|
const { URL } = require('url');
|
|
5
|
-
const {
|
|
6
|
-
getConfig,
|
|
7
|
-
getPlatform,
|
|
8
|
-
setPlatformToken,
|
|
9
|
-
setConfig,
|
|
10
|
-
} = require('./config');
|
|
5
|
+
const { getConfig, setConfig } = require('./config');
|
|
11
6
|
|
|
12
7
|
async function login(tokenArg, options = {}) {
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
const apiUrl =
|
|
9
|
+
options.apiUrl ||
|
|
10
|
+
process.env.MOON_API ||
|
|
11
|
+
getConfig().apiUrl ||
|
|
12
|
+
'https://api.moontraze.com';
|
|
16
13
|
|
|
17
|
-
|
|
14
|
+
const label = process.env.MOON_LABEL || process.env.MOON_PLATFORM || 'Moontraze';
|
|
15
|
+
|
|
16
|
+
// --token (hidden power user)
|
|
18
17
|
if (tokenArg && String(tokenArg).trim()) {
|
|
19
|
-
return saveAndValidateToken(String(tokenArg).trim(), { apiUrl,
|
|
18
|
+
return saveAndValidateToken(String(tokenArg).trim(), { apiUrl, label });
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
console.log('');
|
|
23
|
-
console.log(chalk.cyan(`${
|
|
22
|
+
console.log(chalk.cyan(`${label} Login`));
|
|
24
23
|
console.log('');
|
|
25
24
|
|
|
26
25
|
const { method } = await prompts({
|
|
@@ -33,18 +32,16 @@ async function login(tokenArg, options = {}) {
|
|
|
33
32
|
],
|
|
34
33
|
});
|
|
35
34
|
|
|
36
|
-
if (!method)
|
|
37
|
-
throw new Error('Login cancelled');
|
|
38
|
-
}
|
|
35
|
+
if (!method) throw new Error('Login cancelled');
|
|
39
36
|
|
|
40
37
|
if (method === 'email') {
|
|
41
|
-
await loginWithEmail({ apiUrl,
|
|
38
|
+
await loginWithEmail({ apiUrl, label });
|
|
42
39
|
} else {
|
|
43
|
-
await loginWithMoonID({ apiUrl,
|
|
40
|
+
await loginWithMoonID({ apiUrl, label });
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
43
|
|
|
47
|
-
async function loginWithEmail({ apiUrl,
|
|
44
|
+
async function loginWithEmail({ apiUrl, label }) {
|
|
48
45
|
const answers = await prompts([
|
|
49
46
|
{
|
|
50
47
|
type: 'text',
|
|
@@ -76,65 +73,99 @@ async function loginWithEmail({ apiUrl, platformName, platform }) {
|
|
|
76
73
|
|
|
77
74
|
const data = await res.json().catch(() => ({}));
|
|
78
75
|
|
|
79
|
-
if (!res.ok)
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
if (!data.token) {
|
|
83
|
-
throw new Error('Login succeeded but no token returned');
|
|
84
|
-
}
|
|
76
|
+
if (!res.ok) throw new Error(data.error || 'Invalid email or password');
|
|
77
|
+
if (!data.token) throw new Error('Login succeeded but no token returned');
|
|
85
78
|
|
|
86
|
-
|
|
87
|
-
setPlatformToken(platformName, data.token);
|
|
79
|
+
setConfig({ token: data.token, apiUrl });
|
|
88
80
|
|
|
89
81
|
console.log('');
|
|
90
82
|
console.log(chalk.green('✓ Logged in'));
|
|
91
|
-
if (data.user?.email) {
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
console.log(chalk.gray(` Platform: ${platformName}`));
|
|
95
|
-
console.log(chalk.gray(` Config: ~/.moon/config.json`));
|
|
83
|
+
if (data.user?.email) console.log(chalk.gray(` ${data.user.email}`));
|
|
84
|
+
console.log(chalk.gray(` Config: ~/.moontraze/config.json`));
|
|
96
85
|
console.log('');
|
|
97
86
|
}
|
|
98
87
|
|
|
99
|
-
async function loginWithMoonID({ apiUrl,
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
|
|
88
|
+
async function loginWithMoonID({ apiUrl, label }) {
|
|
89
|
+
const fetch = require('node-fetch');
|
|
90
|
+
const nonce = Math.random().toString(36).substring(2, 12);
|
|
91
|
+
const state = `${nonce}.login`;
|
|
92
|
+
|
|
93
|
+
const startRes = await fetch(`${apiUrl}/api/platform/moonid/cli-start`, {
|
|
94
|
+
method: 'POST',
|
|
95
|
+
headers: { 'Content-Type': 'application/json' },
|
|
96
|
+
body: JSON.stringify({ state }),
|
|
97
|
+
});
|
|
98
|
+
const startData = await startRes.json().catch(() => ({}));
|
|
99
|
+
if (!startRes.ok) {
|
|
100
|
+
throw new Error(startData.error || 'Could not start MoonID CLI session');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const redirectUri =
|
|
104
|
+
startData.redirectUri ||
|
|
105
|
+
`${apiUrl}/api/platform/moonid/cli-callback`;
|
|
104
106
|
|
|
107
|
+
// App POST yahan karegi (web jaisa)
|
|
108
|
+
const notifyUrl = `${apiUrl}/api/platform/moonid/cli-complete`;
|
|
109
|
+
|
|
110
|
+
const appId = 'com.moonstorage.app';
|
|
105
111
|
const deepLink =
|
|
106
112
|
`moonid://auth` +
|
|
107
113
|
`?app_id=${encodeURIComponent(appId)}` +
|
|
108
114
|
`&action=login` +
|
|
109
115
|
`&redirect_uri=${encodeURIComponent(redirectUri)}` +
|
|
110
|
-
`&
|
|
116
|
+
`¬ify_url=${encodeURIComponent(notifyUrl)}` +
|
|
117
|
+
`&state=${encodeURIComponent(state)}` +
|
|
118
|
+
`&source=cli`;
|
|
111
119
|
|
|
112
120
|
const qrImageUrl = `https://api.qrserver.com/v1/create-qr-code/?size=220x220&data=${encodeURIComponent(
|
|
113
121
|
deepLink
|
|
114
122
|
)}`;
|
|
115
123
|
|
|
116
124
|
console.log('');
|
|
117
|
-
console.log(chalk.cyan(`${
|
|
125
|
+
console.log(chalk.cyan(`${label} — MoonID Login`));
|
|
118
126
|
console.log(chalk.gray('1. Open MoonID app on your phone'));
|
|
119
|
-
console.log(chalk.gray('2. Scan the QR code (open link below in browser)'));
|
|
127
|
+
console.log(chalk.gray('2. Scan the QR code (open the link below in a browser if needed)'));
|
|
120
128
|
console.log(chalk.gray('3. Approve login'));
|
|
121
129
|
console.log('');
|
|
122
130
|
console.log(chalk.yellow('QR code image:'));
|
|
123
131
|
console.log(chalk.underline(qrImageUrl));
|
|
124
132
|
console.log('');
|
|
125
|
-
console.log(chalk.gray('Deep link (if needed):'));
|
|
126
|
-
console.log(chalk.gray(deepLink));
|
|
127
|
-
console.log('');
|
|
128
133
|
console.log(chalk.gray('Waiting for approval... (Ctrl+C to cancel)'));
|
|
129
134
|
console.log('');
|
|
130
135
|
|
|
131
|
-
const token = await
|
|
136
|
+
const token = await pollCliStatus({ apiUrl, state, timeoutMs: 180000 });
|
|
137
|
+
if (!token) throw new Error('MoonID login timed out or denied');
|
|
132
138
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
139
|
+
await saveAndValidateToken(token, { apiUrl, label });
|
|
140
|
+
}
|
|
136
141
|
|
|
137
|
-
|
|
142
|
+
async function pollCliStatus({ apiUrl, state, timeoutMs }) {
|
|
143
|
+
const fetch = require('node-fetch');
|
|
144
|
+
const start = Date.now();
|
|
145
|
+
const interval = 2000;
|
|
146
|
+
|
|
147
|
+
while (Date.now() - start < timeoutMs) {
|
|
148
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
149
|
+
try {
|
|
150
|
+
const res = await fetch(
|
|
151
|
+
`${apiUrl}/api/platform/moonid/cli-status?state=${encodeURIComponent(state)}`
|
|
152
|
+
);
|
|
153
|
+
const data = await res.json().catch(() => ({}));
|
|
154
|
+
|
|
155
|
+
if (data.status === 'done' && data.token) {
|
|
156
|
+
return data.token;
|
|
157
|
+
}
|
|
158
|
+
if (data.status === 'denied' || data.status === 'error') {
|
|
159
|
+
throw new Error(data.error || 'MoonID login denied');
|
|
160
|
+
}
|
|
161
|
+
// pending / unknown → keep waiting
|
|
162
|
+
} catch (e) {
|
|
163
|
+
if (e.message && /denied|failed|not found|mismatch|expired/i.test(e.message)) {
|
|
164
|
+
throw e;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
138
169
|
}
|
|
139
170
|
|
|
140
171
|
function waitForMoonIDCallback({ port, state, timeoutMs }) {
|
|
@@ -142,7 +173,6 @@ function waitForMoonIDCallback({ port, state, timeoutMs }) {
|
|
|
142
173
|
const server = http.createServer((req, res) => {
|
|
143
174
|
try {
|
|
144
175
|
const u = new URL(req.url, `http://127.0.0.1:${port}`);
|
|
145
|
-
|
|
146
176
|
if (u.pathname !== '/callback') {
|
|
147
177
|
res.writeHead(404);
|
|
148
178
|
res.end('Not found');
|
|
@@ -175,39 +205,36 @@ function waitForMoonIDCallback({ port, state, timeoutMs }) {
|
|
|
175
205
|
if (!token) {
|
|
176
206
|
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
177
207
|
res.end(
|
|
178
|
-
'<html><body style="font-family:sans-serif;text-align:center;padding:40px"><h2>No token received</h2
|
|
208
|
+
'<html><body style="font-family:sans-serif;text-align:center;padding:40px"><h2>No token received</h2></body></html>'
|
|
179
209
|
);
|
|
180
210
|
return;
|
|
181
211
|
}
|
|
182
212
|
|
|
183
213
|
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
184
214
|
res.end(
|
|
185
|
-
'<html><body style="font-family:sans-serif;text-align:center;padding:40px"><h2>✓ Login successful</h2><p>You can close this tab
|
|
215
|
+
'<html><body style="font-family:sans-serif;text-align:center;padding:40px"><h2>✓ Login successful</h2><p>You can close this tab.</p></body></html>'
|
|
186
216
|
);
|
|
187
217
|
server.close();
|
|
188
218
|
resolve(token);
|
|
189
|
-
} catch
|
|
219
|
+
} catch {
|
|
190
220
|
res.writeHead(500);
|
|
191
221
|
res.end('Error');
|
|
192
222
|
}
|
|
193
223
|
});
|
|
194
224
|
|
|
195
225
|
server.listen(port, '127.0.0.1');
|
|
196
|
-
|
|
197
226
|
const timer = setTimeout(() => {
|
|
198
227
|
try {
|
|
199
228
|
server.close();
|
|
200
229
|
} catch (_) {}
|
|
201
230
|
resolve(null);
|
|
202
231
|
}, timeoutMs);
|
|
203
|
-
|
|
204
232
|
server.on('close', () => clearTimeout(timer));
|
|
205
233
|
});
|
|
206
234
|
}
|
|
207
235
|
|
|
208
|
-
async function saveAndValidateToken(token, { apiUrl,
|
|
236
|
+
async function saveAndValidateToken(token, { apiUrl, label }) {
|
|
209
237
|
const fetch = require('node-fetch');
|
|
210
|
-
|
|
211
238
|
const res = await fetch(`${apiUrl}/api/hosting/quota`, {
|
|
212
239
|
headers: { Authorization: `Bearer ${token}` },
|
|
213
240
|
});
|
|
@@ -216,13 +243,11 @@ async function saveAndValidateToken(token, { apiUrl, platformName }) {
|
|
|
216
243
|
throw new Error('Invalid or expired token');
|
|
217
244
|
}
|
|
218
245
|
|
|
219
|
-
|
|
220
|
-
setPlatformToken(platformName, token);
|
|
246
|
+
setConfig({ token, apiUrl });
|
|
221
247
|
|
|
222
248
|
console.log('');
|
|
223
249
|
console.log(chalk.green('✓ Logged in'));
|
|
224
|
-
console.log(chalk.gray(`
|
|
225
|
-
console.log(chalk.gray(` Config: ~/.moon/config.json`));
|
|
250
|
+
console.log(chalk.gray(` Config: ~/.moontraze/config.json`));
|
|
226
251
|
console.log('');
|
|
227
252
|
}
|
|
228
253
|
|
package/lib/config.js
CHANGED
|
@@ -2,9 +2,9 @@ const fs = require('fs');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const os = require('os');
|
|
4
4
|
|
|
5
|
-
const GLOBAL_DIR = path.join(os.homedir(), '.
|
|
5
|
+
const GLOBAL_DIR = path.join(os.homedir(), '.moontraze');
|
|
6
6
|
const GLOBAL_FILE = path.join(GLOBAL_DIR, 'config.json');
|
|
7
|
-
const LOCAL_DIR = path.join(process.cwd(), '.
|
|
7
|
+
const LOCAL_DIR = path.join(process.cwd(), '.moontraze');
|
|
8
8
|
const LOCAL_FILE = path.join(LOCAL_DIR, 'project.json');
|
|
9
9
|
|
|
10
10
|
function ensureDir(d) {
|
|
@@ -12,93 +12,27 @@ function ensureDir(d) {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
const DEFAULTS = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
label: 'Moontraze',
|
|
19
|
-
apiUrl: process.env.MOON_API || 'https://api.moontraze.com',
|
|
20
|
-
domain: process.env.MOON_DOMAIN || 'moontraze.com',
|
|
21
|
-
},
|
|
22
|
-
},
|
|
15
|
+
token: null,
|
|
16
|
+
apiUrl: process.env.MOON_API || 'https://api.moontraze.com',
|
|
17
|
+
domain: process.env.MOON_DOMAIN || 'moontraze.com',
|
|
23
18
|
};
|
|
24
19
|
|
|
25
|
-
function migrate(cfg) {
|
|
26
|
-
// old .moontraze → new structure support
|
|
27
|
-
if (cfg.apiUrl && !cfg.platforms) {
|
|
28
|
-
return {
|
|
29
|
-
defaultPlatform: 'moontraze',
|
|
30
|
-
platforms: {
|
|
31
|
-
moontraze: {
|
|
32
|
-
label: 'Moontraze',
|
|
33
|
-
apiUrl: cfg.apiUrl.includes('frelanceo')
|
|
34
|
-
? 'https://api.moontraze.com'
|
|
35
|
-
: cfg.apiUrl,
|
|
36
|
-
domain: cfg.domain?.includes('frelanceo')
|
|
37
|
-
? 'moontraze.com'
|
|
38
|
-
: cfg.domain || 'moontraze.com',
|
|
39
|
-
token: cfg.token || null,
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
return { ...DEFAULTS, ...cfg };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
20
|
function getConfig() {
|
|
48
21
|
try {
|
|
49
22
|
if (fs.existsSync(GLOBAL_FILE)) {
|
|
50
|
-
|
|
51
|
-
return migrate(saved);
|
|
23
|
+
return { ...DEFAULTS, ...JSON.parse(fs.readFileSync(GLOBAL_FILE, 'utf8')) };
|
|
52
24
|
}
|
|
53
25
|
} catch (_) {}
|
|
54
|
-
return
|
|
26
|
+
return { ...DEFAULTS };
|
|
55
27
|
}
|
|
56
28
|
|
|
57
29
|
function setConfig(partial) {
|
|
58
30
|
ensureDir(GLOBAL_DIR);
|
|
59
|
-
const
|
|
60
|
-
const next = { ...current, ...partial };
|
|
31
|
+
const next = { ...getConfig(), ...partial };
|
|
61
32
|
fs.writeFileSync(GLOBAL_FILE, JSON.stringify(next, null, 2));
|
|
62
33
|
return next;
|
|
63
34
|
}
|
|
64
35
|
|
|
65
|
-
function getPlatform(name) {
|
|
66
|
-
const cfg = getConfig();
|
|
67
|
-
const key = (name || cfg.defaultPlatform || 'moontraze').toLowerCase();
|
|
68
|
-
return cfg.platforms[key] || null;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function addPlatform(name, { apiUrl, label, domain }) {
|
|
72
|
-
if (!name || !apiUrl) throw new Error('name and apiUrl required');
|
|
73
|
-
const cfg = getConfig();
|
|
74
|
-
cfg.platforms[name.toLowerCase()] = {
|
|
75
|
-
label: label || name,
|
|
76
|
-
apiUrl,
|
|
77
|
-
domain: domain || null,
|
|
78
|
-
token: null,
|
|
79
|
-
};
|
|
80
|
-
setConfig(cfg);
|
|
81
|
-
return cfg.platforms[name.toLowerCase()];
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function removePlatform(name) {
|
|
85
|
-
const cfg = getConfig();
|
|
86
|
-
name = name.toLowerCase();
|
|
87
|
-
if (name === 'moontraze') throw new Error('Cannot remove default platform "moontraze"');
|
|
88
|
-
if (!cfg.platforms[name]) throw new Error(`Platform "${name}" not found`);
|
|
89
|
-
delete cfg.platforms[name];
|
|
90
|
-
if (cfg.defaultPlatform === name) cfg.defaultPlatform = 'moontraze';
|
|
91
|
-
setConfig(cfg);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function setPlatformToken(name, token) {
|
|
95
|
-
const cfg = getConfig();
|
|
96
|
-
name = (name || cfg.defaultPlatform).toLowerCase();
|
|
97
|
-
if (!cfg.platforms[name]) throw new Error(`Platform "${name}" not found`);
|
|
98
|
-
cfg.platforms[name].token = token;
|
|
99
|
-
setConfig(cfg);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
36
|
function getProject() {
|
|
103
37
|
try {
|
|
104
38
|
if (fs.existsSync(LOCAL_FILE)) {
|
|
@@ -111,26 +45,14 @@ function getProject() {
|
|
|
111
45
|
function setProject(data) {
|
|
112
46
|
ensureDir(LOCAL_DIR);
|
|
113
47
|
fs.writeFileSync(LOCAL_FILE, JSON.stringify(data, null, 2));
|
|
114
|
-
|
|
115
|
-
// auto .gitignore
|
|
116
48
|
const ignore = path.join(process.cwd(), '.gitignore');
|
|
117
49
|
try {
|
|
118
50
|
let g = fs.existsSync(ignore) ? fs.readFileSync(ignore, 'utf8') : '';
|
|
119
|
-
if (!g.includes('.
|
|
120
|
-
fs.appendFileSync(ignore, '\n.
|
|
51
|
+
if (!g.includes('.moontraze')) {
|
|
52
|
+
fs.appendFileSync(ignore, '\n.moontraze/\n');
|
|
121
53
|
}
|
|
122
54
|
} catch (_) {}
|
|
123
55
|
return data;
|
|
124
56
|
}
|
|
125
57
|
|
|
126
|
-
module.exports = {
|
|
127
|
-
getConfig,
|
|
128
|
-
setConfig,
|
|
129
|
-
getPlatform,
|
|
130
|
-
addPlatform,
|
|
131
|
-
removePlatform,
|
|
132
|
-
setPlatformToken,
|
|
133
|
-
getProject,
|
|
134
|
-
setProject,
|
|
135
|
-
GLOBAL_DIR,
|
|
136
|
-
};
|
|
58
|
+
module.exports = { getConfig, setConfig, getProject, setProject, GLOBAL_DIR };
|
package/lib/deploy.js
CHANGED
|
@@ -1,43 +1,37 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
2
|
const fetch = require('node-fetch');
|
|
4
3
|
const FormData = require('form-data');
|
|
5
4
|
const ora = require('ora');
|
|
6
5
|
const chalk = require('chalk');
|
|
7
|
-
const { getConfig,
|
|
6
|
+
const { getConfig, getProject } = require('./config');
|
|
8
7
|
const { zipCwd } = require('./zip');
|
|
9
8
|
|
|
10
9
|
async function deploy({
|
|
11
10
|
prod = true,
|
|
12
11
|
projectName,
|
|
13
12
|
apiUrl: apiUrlArg,
|
|
14
|
-
platformName: platformNameArg,
|
|
15
13
|
domain: domainArg,
|
|
16
14
|
} = {}) {
|
|
17
|
-
const
|
|
18
|
-
platformNameArg || process.env.MOON_CURRENT_PLATFORM || 'moontraze';
|
|
19
|
-
const platform = getPlatform(platformName);
|
|
15
|
+
const cfg = getConfig();
|
|
20
16
|
|
|
21
17
|
const api =
|
|
22
18
|
apiUrlArg ||
|
|
23
19
|
process.env.MOON_API ||
|
|
24
|
-
|
|
20
|
+
cfg.apiUrl ||
|
|
25
21
|
'https://api.moontraze.com';
|
|
26
22
|
|
|
27
23
|
const domain =
|
|
28
24
|
domainArg ||
|
|
29
25
|
process.env.MOON_DOMAIN ||
|
|
30
|
-
|
|
26
|
+
cfg.domain ||
|
|
31
27
|
'moontraze.com';
|
|
32
28
|
|
|
33
|
-
const token =
|
|
34
|
-
|
|
35
|
-
platform?.token ||
|
|
36
|
-
null;
|
|
29
|
+
const token = cfg.token || process.env.MOON_TOKEN || null;
|
|
30
|
+
const label = process.env.MOON_LABEL || process.env.MOON_PLATFORM || 'Moontraze';
|
|
37
31
|
|
|
38
32
|
if (!token) {
|
|
39
33
|
throw new Error(
|
|
40
|
-
|
|
34
|
+
'Not logged in. Run: moon moontraze login\n or: npx moontraze login'
|
|
41
35
|
);
|
|
42
36
|
}
|
|
43
37
|
|
|
@@ -48,12 +42,12 @@ async function deploy({
|
|
|
48
42
|
|
|
49
43
|
if (!name || name.length < 3) {
|
|
50
44
|
throw new Error(
|
|
51
|
-
|
|
45
|
+
'No project linked. Run: moon moontraze link my-site\n or: npx moontraze link my-site'
|
|
52
46
|
);
|
|
53
47
|
}
|
|
54
48
|
|
|
55
49
|
console.log('');
|
|
56
|
-
console.log(chalk.cyan(
|
|
50
|
+
console.log(chalk.cyan(label));
|
|
57
51
|
console.log(` API ${api}`);
|
|
58
52
|
console.log(` Project ${name}`);
|
|
59
53
|
console.log(` Target https://${name}.${domain}`);
|
|
@@ -90,13 +84,12 @@ async function deploy({
|
|
|
90
84
|
filename: `${name}.zip`,
|
|
91
85
|
contentType: 'application/zip',
|
|
92
86
|
});
|
|
87
|
+
form.append('redeploy', alreadyExists ? 'true' : 'false');
|
|
93
88
|
|
|
94
89
|
const endpoint = alreadyExists
|
|
95
90
|
? `${api}/api/hosting/redeploy`
|
|
96
91
|
: `${api}/api/hosting/deploy`;
|
|
97
92
|
|
|
98
|
-
form.append('redeploy', alreadyExists ? 'true' : 'false');
|
|
99
|
-
|
|
100
93
|
const res = await fetch(endpoint, {
|
|
101
94
|
method: 'POST',
|
|
102
95
|
headers: {
|
|
@@ -129,9 +122,7 @@ async function deploy({
|
|
|
129
122
|
if (data.deployment?.version) {
|
|
130
123
|
console.log(chalk.gray(` Version ${data.deployment.version}`));
|
|
131
124
|
}
|
|
132
|
-
console.log(
|
|
133
|
-
chalk.green(alreadyExists ? '✓ Redeployed' : '✓ Deployed')
|
|
134
|
-
);
|
|
125
|
+
console.log(chalk.green(alreadyExists ? '✓ Redeployed' : '✓ Deployed'));
|
|
135
126
|
console.log('');
|
|
136
127
|
} finally {
|
|
137
128
|
if (zipPath && fs.existsSync(zipPath)) {
|
package/package.json
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "moontraze",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "Deploy to Moontraze hosting — like vercel CLI",
|
|
5
5
|
"bin": {
|
|
6
|
-
"
|
|
7
|
-
"
|
|
6
|
+
"moon": "./bin/moon.js",
|
|
7
|
+
"moontraze": "./bin/moontraze.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"lib"
|
|
12
|
+
],
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=18"
|
|
8
15
|
},
|
|
9
|
-
"files": ["bin", "lib"],
|
|
10
|
-
"engines": { "node": ">=18" },
|
|
11
16
|
"dependencies": {
|
|
12
17
|
"archiver": "^7.0.1",
|
|
13
18
|
"commander": "^12.1.0",
|
|
@@ -17,6 +22,12 @@
|
|
|
17
22
|
"chalk": "^4.1.2",
|
|
18
23
|
"prompts": "^2.4.2"
|
|
19
24
|
},
|
|
20
|
-
"keywords": [
|
|
25
|
+
"keywords": [
|
|
26
|
+
"moontraze",
|
|
27
|
+
"deploy",
|
|
28
|
+
"hosting",
|
|
29
|
+
"moon",
|
|
30
|
+
"cli"
|
|
31
|
+
],
|
|
21
32
|
"license": "MIT"
|
|
22
33
|
}
|
package/bin/moon.js
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* moon <platform> <command>
|
|
4
|
-
* Example:
|
|
5
|
-
* moon moontraze login
|
|
6
|
-
* moon myproject deploy --prod
|
|
7
|
-
* moon platform add myproject --api https://api.myproject.com
|
|
8
|
-
*/
|
|
9
|
-
const chalk = require('chalk');
|
|
10
|
-
const path = require('path');
|
|
11
|
-
const {
|
|
12
|
-
getConfig,
|
|
13
|
-
getPlatform,
|
|
14
|
-
addPlatform,
|
|
15
|
-
removePlatform,
|
|
16
|
-
setConfig,
|
|
17
|
-
} = require('../lib/config');
|
|
18
|
-
|
|
19
|
-
function printRootHelp() {
|
|
20
|
-
const cfg = getConfig();
|
|
21
|
-
const platforms = Object.keys(cfg.platforms || {}).join(', ') || 'moontraze';
|
|
22
|
-
|
|
23
|
-
console.log(`
|
|
24
|
-
${chalk.bold('moon')} — multi-platform CLI
|
|
25
|
-
|
|
26
|
-
Usage:
|
|
27
|
-
moon <platform> <command>
|
|
28
|
-
moon platform <add|list|remove|use> ...
|
|
29
|
-
|
|
30
|
-
Platforms:
|
|
31
|
-
${platforms}
|
|
32
|
-
|
|
33
|
-
Examples:
|
|
34
|
-
moon moontraze login
|
|
35
|
-
moon moontraze deploy --prod
|
|
36
|
-
moon myproject login
|
|
37
|
-
moon myproject deploy
|
|
38
|
-
|
|
39
|
-
Platform management:
|
|
40
|
-
moon platform add <name> --api <url>
|
|
41
|
-
moon platform list
|
|
42
|
-
moon platform remove <name>
|
|
43
|
-
moon platform use <name> # set default
|
|
44
|
-
|
|
45
|
-
Same as:
|
|
46
|
-
npx moontraze login
|
|
47
|
-
`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const args = process.argv.slice(2);
|
|
51
|
-
const first = (args[0] || '').toLowerCase();
|
|
52
|
-
|
|
53
|
-
// Help
|
|
54
|
-
if (!first || first === '-h' || first === '--help' || first === 'help') {
|
|
55
|
-
printRootHelp();
|
|
56
|
-
process.exit(0);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Version
|
|
60
|
-
if (first === '-v' || first === '--version') {
|
|
61
|
-
try {
|
|
62
|
-
console.log(require('../package.json').version);
|
|
63
|
-
} catch {
|
|
64
|
-
console.log('1.0.0');
|
|
65
|
-
}
|
|
66
|
-
process.exit(0);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// ========== Platform management commands ==========
|
|
70
|
-
if (first === 'platform') {
|
|
71
|
-
const sub = (args[1] || '').toLowerCase();
|
|
72
|
-
|
|
73
|
-
if (sub === 'list') {
|
|
74
|
-
const cfg = getConfig();
|
|
75
|
-
console.log(chalk.bold('\nConfigured platforms:\n'));
|
|
76
|
-
for (const [name, p] of Object.entries(cfg.platforms || {})) {
|
|
77
|
-
const def = name === cfg.defaultPlatform ? chalk.green(' (default)') : '';
|
|
78
|
-
console.log(` ${chalk.cyan(name)}${def}`);
|
|
79
|
-
console.log(` API: ${p.apiUrl}`);
|
|
80
|
-
if (p.label) console.log(` Label: ${p.label}`);
|
|
81
|
-
console.log();
|
|
82
|
-
}
|
|
83
|
-
process.exit(0);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (sub === 'add') {
|
|
87
|
-
const name = args[2];
|
|
88
|
-
let apiUrl = null;
|
|
89
|
-
let label = null;
|
|
90
|
-
|
|
91
|
-
for (let i = 3; i < args.length; i++) {
|
|
92
|
-
if (args[i] === '--api' && args[i + 1]) apiUrl = args[++i];
|
|
93
|
-
if (args[i] === '--label' && args[i + 1]) label = args[++i];
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (!name || !apiUrl) {
|
|
97
|
-
console.error(chalk.red('Usage: moon platform add <name> --api <url> [--label <label>]'));
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
addPlatform(name, { apiUrl, label });
|
|
103
|
-
console.log(chalk.green(`✓ Platform "${name}" added`));
|
|
104
|
-
console.log(chalk.gray(` API: ${apiUrl}`));
|
|
105
|
-
console.log(chalk.gray(`\nNow you can run: moon ${name} login`));
|
|
106
|
-
} catch (err) {
|
|
107
|
-
console.error(chalk.red(err.message));
|
|
108
|
-
process.exit(1);
|
|
109
|
-
}
|
|
110
|
-
process.exit(0);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (sub === 'remove') {
|
|
114
|
-
const name = args[2];
|
|
115
|
-
if (!name) {
|
|
116
|
-
console.error(chalk.red('Usage: moon platform remove <name>'));
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
try {
|
|
120
|
-
removePlatform(name);
|
|
121
|
-
console.log(chalk.green(`✓ Platform "${name}" removed`));
|
|
122
|
-
} catch (err) {
|
|
123
|
-
console.error(chalk.red(err.message));
|
|
124
|
-
process.exit(1);
|
|
125
|
-
}
|
|
126
|
-
process.exit(0);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (sub === 'use') {
|
|
130
|
-
const name = args[2];
|
|
131
|
-
if (!name) {
|
|
132
|
-
console.error(chalk.red('Usage: moon platform use <name>'));
|
|
133
|
-
process.exit(1);
|
|
134
|
-
}
|
|
135
|
-
const p = getPlatform(name);
|
|
136
|
-
if (!p) {
|
|
137
|
-
console.error(chalk.red(`Platform "${name}" not found. Add it first.`));
|
|
138
|
-
process.exit(1);
|
|
139
|
-
}
|
|
140
|
-
setConfig({ defaultPlatform: name.toLowerCase() });
|
|
141
|
-
console.log(chalk.green(`✓ Default platform set to "${name}"`));
|
|
142
|
-
process.exit(0);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
console.error(chalk.red('Unknown platform command. Use: add | list | remove | use'));
|
|
146
|
-
process.exit(1);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// ========== Normal platform command ==========
|
|
150
|
-
const platformName = first;
|
|
151
|
-
const platform = getPlatform(platformName);
|
|
152
|
-
|
|
153
|
-
if (!platform) {
|
|
154
|
-
console.error(chalk.red(`Unknown platform: "${platformName}"`));
|
|
155
|
-
console.error(chalk.gray('Add it first: moon platform add ' + platformName + ' --api https://your-api.com'));
|
|
156
|
-
console.error(chalk.gray('Or see known platforms: moon platform list'));
|
|
157
|
-
process.exit(1);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Inject current platform info so moontraze.js (or generic runner) can use it
|
|
161
|
-
process.env.MOON_CURRENT_PLATFORM = platformName;
|
|
162
|
-
process.env.MOON_API = platform.apiUrl;
|
|
163
|
-
if (platform.domain) process.env.MOON_DOMAIN = platform.domain;
|
|
164
|
-
if (platform.token) process.env.MOON_TOKEN = platform.token;
|
|
165
|
-
|
|
166
|
-
// Forward to the actual platform runner
|
|
167
|
-
// Abhi ke liye sab platforms same runner use karenge (moontraze.js)
|
|
168
|
-
// Future mein alag runner bhi laga sakte ho
|
|
169
|
-
const runner = path.join(__dirname, 'moontraze.js');
|
|
170
|
-
|
|
171
|
-
process.argv = [process.argv[0], runner, ...args.slice(1)];
|
|
172
|
-
require(runner);
|