moontraze 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/moon.js +131 -27
- package/bin/moontraze.js +43 -21
- package/lib/auth.js +35 -27
- package/lib/config.js +83 -18
- package/lib/deploy.js +40 -19
- package/lib/zip.js +11 -4
- package/package.json +1 -1
package/bin/moon.js
CHANGED
|
@@ -1,68 +1,172 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* moon <platform> <command>
|
|
4
|
-
* Example:
|
|
5
|
-
*
|
|
4
|
+
* Example:
|
|
5
|
+
* moon moontraze login
|
|
6
|
+
* moon myproject deploy --prod
|
|
7
|
+
* moon platform add myproject --api https://api.myproject.com
|
|
6
8
|
*/
|
|
7
9
|
const chalk = require('chalk');
|
|
8
10
|
const path = require('path');
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
// otherapp: { label: 'Other', runner: path.join(__dirname, 'other.js') },
|
|
17
|
-
};
|
|
11
|
+
const {
|
|
12
|
+
getConfig,
|
|
13
|
+
getPlatform,
|
|
14
|
+
addPlatform,
|
|
15
|
+
removePlatform,
|
|
16
|
+
setConfig,
|
|
17
|
+
} = require('../lib/config');
|
|
18
18
|
|
|
19
19
|
function printRootHelp() {
|
|
20
|
+
const cfg = getConfig();
|
|
21
|
+
const platforms = Object.keys(cfg.platforms || {}).join(', ') || 'moontraze';
|
|
22
|
+
|
|
20
23
|
console.log(`
|
|
21
24
|
${chalk.bold('moon')} — multi-platform CLI
|
|
22
25
|
|
|
23
26
|
Usage:
|
|
24
27
|
moon <platform> <command>
|
|
28
|
+
moon platform <add|list|remove|use> ...
|
|
25
29
|
|
|
26
30
|
Platforms:
|
|
27
|
-
|
|
31
|
+
${platforms}
|
|
28
32
|
|
|
29
33
|
Examples:
|
|
30
34
|
moon moontraze login
|
|
31
|
-
moon moontraze link my-site
|
|
32
35
|
moon moontraze deploy --prod
|
|
33
|
-
moon
|
|
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
|
|
34
44
|
|
|
35
45
|
Same as:
|
|
36
46
|
npx moontraze login
|
|
37
|
-
npx moontraze deploy --prod
|
|
38
47
|
`);
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
const args = process.argv.slice(2);
|
|
42
|
-
const
|
|
51
|
+
const first = (args[0] || '').toLowerCase();
|
|
43
52
|
|
|
44
|
-
|
|
53
|
+
// Help
|
|
54
|
+
if (!first || first === '-h' || first === '--help' || first === 'help') {
|
|
45
55
|
printRootHelp();
|
|
46
56
|
process.exit(0);
|
|
47
57
|
}
|
|
48
58
|
|
|
49
|
-
|
|
59
|
+
// Version
|
|
60
|
+
if (first === '-v' || first === '--version') {
|
|
50
61
|
try {
|
|
51
62
|
console.log(require('../package.json').version);
|
|
52
63
|
} catch {
|
|
53
|
-
console.log('
|
|
64
|
+
console.log('1.0.0');
|
|
54
65
|
}
|
|
55
66
|
process.exit(0);
|
|
56
67
|
}
|
|
57
68
|
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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'));
|
|
63
157
|
process.exit(1);
|
|
64
158
|
}
|
|
65
159
|
|
|
66
|
-
//
|
|
67
|
-
process.
|
|
68
|
-
|
|
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);
|
package/bin/moontraze.js
CHANGED
|
@@ -2,31 +2,52 @@
|
|
|
2
2
|
const { Command } = require('commander');
|
|
3
3
|
const chalk = require('chalk');
|
|
4
4
|
const { login } = require('../lib/auth');
|
|
5
|
-
const {
|
|
5
|
+
const {
|
|
6
|
+
getConfig,
|
|
7
|
+
getPlatform,
|
|
8
|
+
getProject,
|
|
9
|
+
setProject,
|
|
10
|
+
setPlatformToken,
|
|
11
|
+
} = require('../lib/config');
|
|
6
12
|
const { deploy } = require('../lib/deploy');
|
|
7
13
|
|
|
8
14
|
const program = new Command();
|
|
9
15
|
|
|
16
|
+
// Current platform (moon.js se inject hota hai)
|
|
17
|
+
const platformName = process.env.MOON_CURRENT_PLATFORM || 'moontraze';
|
|
18
|
+
const platform = getPlatform(platformName) || getConfig().platforms?.moontraze;
|
|
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';
|
|
22
|
+
|
|
10
23
|
program
|
|
11
|
-
.name(
|
|
12
|
-
.description(
|
|
13
|
-
.version('1.0.
|
|
24
|
+
.name(platformName)
|
|
25
|
+
.description(`Deploy sites using ${platform?.label || platformName}`)
|
|
26
|
+
.version('1.0.4');
|
|
14
27
|
|
|
15
|
-
//
|
|
28
|
+
// ========== login ==========
|
|
16
29
|
program
|
|
17
30
|
.command('login')
|
|
18
31
|
.description('Log in with email/password or token')
|
|
19
32
|
.option('--token <jwt>', 'JWT token (advanced, skip interactive login)')
|
|
20
33
|
.action(async (opts) => {
|
|
21
34
|
try {
|
|
22
|
-
|
|
35
|
+
// login function ko current apiUrl dena zaroori hai
|
|
36
|
+
const token = await login(opts.token, { apiUrl, platformName });
|
|
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}`));
|
|
23
44
|
} catch (e) {
|
|
24
45
|
console.error(chalk.red('Login failed:'), e.message);
|
|
25
46
|
process.exit(1);
|
|
26
47
|
}
|
|
27
48
|
});
|
|
28
49
|
|
|
29
|
-
//
|
|
50
|
+
// ========== link ==========
|
|
30
51
|
program
|
|
31
52
|
.command('link [name]')
|
|
32
53
|
.description('Link this folder to a hosting project name')
|
|
@@ -34,6 +55,7 @@ program
|
|
|
34
55
|
try {
|
|
35
56
|
const prompts = require('prompts');
|
|
36
57
|
let projectName = name;
|
|
58
|
+
|
|
37
59
|
if (!projectName) {
|
|
38
60
|
const a = await prompts({
|
|
39
61
|
type: 'text',
|
|
@@ -46,25 +68,29 @@ program
|
|
|
46
68
|
});
|
|
47
69
|
projectName = a.n;
|
|
48
70
|
}
|
|
71
|
+
|
|
49
72
|
if (!projectName) process.exit(1);
|
|
73
|
+
|
|
50
74
|
projectName = projectName.toLowerCase().replace(/[^a-z0-9-]/g, '');
|
|
51
|
-
setProject({ projectName });
|
|
52
|
-
|
|
75
|
+
setProject({ projectName, platform: platformName });
|
|
76
|
+
|
|
53
77
|
console.log(chalk.green(`Linked → ${projectName}.${domain}`));
|
|
54
|
-
console.log(
|
|
55
|
-
chalk.gray('(saved .moontraze/project.json — same as .vercel)')
|
|
56
|
-
);
|
|
78
|
+
console.log(chalk.gray('(saved .moon/project.json)'));
|
|
57
79
|
} catch (e) {
|
|
58
80
|
console.error(chalk.red(e.message));
|
|
59
81
|
process.exit(1);
|
|
60
82
|
}
|
|
61
83
|
});
|
|
62
84
|
|
|
85
|
+
// ========== deploy ==========
|
|
63
86
|
async function runDeploy(opts) {
|
|
64
87
|
try {
|
|
65
88
|
await deploy({
|
|
66
89
|
prod: !!(opts.prod || opts.production),
|
|
67
90
|
projectName: opts.project || opts.name,
|
|
91
|
+
apiUrl, // ← important
|
|
92
|
+
platformName,
|
|
93
|
+
domain,
|
|
68
94
|
});
|
|
69
95
|
} catch (e) {
|
|
70
96
|
console.error(chalk.red('\nDeploy failed:'), e.message);
|
|
@@ -80,7 +106,7 @@ program
|
|
|
80
106
|
.option('-p, --project <name>', 'Project name (or use link)')
|
|
81
107
|
.action(runDeploy);
|
|
82
108
|
|
|
83
|
-
// moon moontraze --prod
|
|
109
|
+
// Direct flags: moon moontraze --prod
|
|
84
110
|
program
|
|
85
111
|
.option('--prod', 'Deploy to production')
|
|
86
112
|
.option('--production', 'Deploy to production')
|
|
@@ -98,14 +124,10 @@ program.addHelpText(
|
|
|
98
124
|
'after',
|
|
99
125
|
`
|
|
100
126
|
Examples:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
moon moontraze login
|
|
106
|
-
moon moontraze link my-site
|
|
107
|
-
moon moontraze deploy --prod
|
|
108
|
-
moon moontraze --prod
|
|
127
|
+
moon ${platformName} login
|
|
128
|
+
moon ${platformName} link my-site
|
|
129
|
+
moon ${platformName} deploy --prod
|
|
130
|
+
moon ${platformName} --prod
|
|
109
131
|
`
|
|
110
132
|
);
|
|
111
133
|
|
package/lib/auth.js
CHANGED
|
@@ -2,16 +2,25 @@ const prompts = require('prompts');
|
|
|
2
2
|
const chalk = require('chalk');
|
|
3
3
|
const http = require('http');
|
|
4
4
|
const { URL } = require('url');
|
|
5
|
-
const {
|
|
5
|
+
const {
|
|
6
|
+
getConfig,
|
|
7
|
+
getPlatform,
|
|
8
|
+
setPlatformToken,
|
|
9
|
+
setConfig,
|
|
10
|
+
} = require('./config');
|
|
11
|
+
|
|
12
|
+
async function login(tokenArg, options = {}) {
|
|
13
|
+
const platformName = options.platformName || process.env.MOON_CURRENT_PLATFORM || 'moontraze';
|
|
14
|
+
const platform = getPlatform(platformName);
|
|
15
|
+
const apiUrl = options.apiUrl || process.env.MOON_API || platform?.apiUrl || 'https://api.moontraze.com';
|
|
6
16
|
|
|
7
|
-
async function login(tokenArg) {
|
|
8
17
|
// Power user: --token still works (hidden)
|
|
9
18
|
if (tokenArg && String(tokenArg).trim()) {
|
|
10
|
-
return saveAndValidateToken(String(tokenArg).trim());
|
|
19
|
+
return saveAndValidateToken(String(tokenArg).trim(), { apiUrl, platformName });
|
|
11
20
|
}
|
|
12
21
|
|
|
13
22
|
console.log('');
|
|
14
|
-
console.log(chalk.cyan(
|
|
23
|
+
console.log(chalk.cyan(`${platform?.label || platformName} Login`));
|
|
15
24
|
console.log('');
|
|
16
25
|
|
|
17
26
|
const { method } = await prompts({
|
|
@@ -29,20 +38,19 @@ async function login(tokenArg) {
|
|
|
29
38
|
}
|
|
30
39
|
|
|
31
40
|
if (method === 'email') {
|
|
32
|
-
await loginWithEmail();
|
|
41
|
+
await loginWithEmail({ apiUrl, platformName, platform });
|
|
33
42
|
} else {
|
|
34
|
-
await loginWithMoonID();
|
|
43
|
+
await loginWithMoonID({ apiUrl, platformName, platform });
|
|
35
44
|
}
|
|
36
45
|
}
|
|
37
46
|
|
|
38
|
-
async function loginWithEmail() {
|
|
47
|
+
async function loginWithEmail({ apiUrl, platformName, platform }) {
|
|
39
48
|
const answers = await prompts([
|
|
40
49
|
{
|
|
41
50
|
type: 'text',
|
|
42
51
|
name: 'email',
|
|
43
52
|
message: 'Email',
|
|
44
|
-
validate: (v) =>
|
|
45
|
-
v && v.includes('@') ? true : 'Enter a valid email',
|
|
53
|
+
validate: (v) => (v && v.includes('@') ? true : 'Enter a valid email'),
|
|
46
54
|
},
|
|
47
55
|
{
|
|
48
56
|
type: 'password',
|
|
@@ -56,10 +64,8 @@ async function loginWithEmail() {
|
|
|
56
64
|
throw new Error('Login cancelled');
|
|
57
65
|
}
|
|
58
66
|
|
|
59
|
-
const cfg = getConfig();
|
|
60
67
|
const fetch = require('node-fetch');
|
|
61
|
-
|
|
62
|
-
const res = await fetch(`${cfg.apiUrl}/api/platform/login`, {
|
|
68
|
+
const res = await fetch(`${apiUrl}/api/platform/login`, {
|
|
63
69
|
method: 'POST',
|
|
64
70
|
headers: { 'Content-Type': 'application/json' },
|
|
65
71
|
body: JSON.stringify({
|
|
@@ -73,28 +79,29 @@ async function loginWithEmail() {
|
|
|
73
79
|
if (!res.ok) {
|
|
74
80
|
throw new Error(data.error || 'Invalid email or password');
|
|
75
81
|
}
|
|
76
|
-
|
|
77
82
|
if (!data.token) {
|
|
78
83
|
throw new Error('Login succeeded but no token returned');
|
|
79
84
|
}
|
|
80
85
|
|
|
81
|
-
|
|
86
|
+
// Token us platform ke under save hoga
|
|
87
|
+
setPlatformToken(platformName, data.token);
|
|
88
|
+
|
|
82
89
|
console.log('');
|
|
83
90
|
console.log(chalk.green('✓ Logged in'));
|
|
84
91
|
if (data.user?.email) {
|
|
85
92
|
console.log(chalk.gray(` ${data.user.email}`));
|
|
86
93
|
}
|
|
87
|
-
console.log(chalk.gray(`
|
|
94
|
+
console.log(chalk.gray(` Platform: ${platformName}`));
|
|
95
|
+
console.log(chalk.gray(` Config: ~/.moon/config.json`));
|
|
88
96
|
console.log('');
|
|
89
97
|
}
|
|
90
98
|
|
|
91
|
-
async function loginWithMoonID() {
|
|
92
|
-
const cfg = getConfig();
|
|
99
|
+
async function loginWithMoonID({ apiUrl, platformName, platform }) {
|
|
93
100
|
const state = Math.random().toString(36).substring(2, 12);
|
|
94
101
|
const port = 17321 + Math.floor(Math.random() * 100);
|
|
95
102
|
const redirectUri = `http://127.0.0.1:${port}/callback`;
|
|
96
|
-
|
|
97
103
|
const appId = 'com.moonstorage.app';
|
|
104
|
+
|
|
98
105
|
const deepLink =
|
|
99
106
|
`moonid://auth` +
|
|
100
107
|
`?app_id=${encodeURIComponent(appId)}` +
|
|
@@ -107,7 +114,7 @@ async function loginWithMoonID() {
|
|
|
107
114
|
)}`;
|
|
108
115
|
|
|
109
116
|
console.log('');
|
|
110
|
-
console.log(chalk.cyan(
|
|
117
|
+
console.log(chalk.cyan(`${platform?.label || platformName} — MoonID Login`));
|
|
111
118
|
console.log(chalk.gray('1. Open MoonID app on your phone'));
|
|
112
119
|
console.log(chalk.gray('2. Scan the QR code (open link below in browser)'));
|
|
113
120
|
console.log(chalk.gray('3. Approve login'));
|
|
@@ -121,18 +128,17 @@ async function loginWithMoonID() {
|
|
|
121
128
|
console.log(chalk.gray('Waiting for approval... (Ctrl+C to cancel)'));
|
|
122
129
|
console.log('');
|
|
123
130
|
|
|
124
|
-
// Local server — MoonID redirect yahan aayega
|
|
125
131
|
const token = await waitForMoonIDCallback({ port, state, timeoutMs: 120000 });
|
|
126
132
|
|
|
127
133
|
if (!token) {
|
|
128
134
|
throw new Error('MoonID login timed out or denied');
|
|
129
135
|
}
|
|
130
136
|
|
|
131
|
-
await saveAndValidateToken(token);
|
|
137
|
+
await saveAndValidateToken(token, { apiUrl, platformName });
|
|
132
138
|
}
|
|
133
139
|
|
|
134
140
|
function waitForMoonIDCallback({ port, state, timeoutMs }) {
|
|
135
|
-
return new Promise((resolve
|
|
141
|
+
return new Promise((resolve) => {
|
|
136
142
|
const server = http.createServer((req, res) => {
|
|
137
143
|
try {
|
|
138
144
|
const u = new URL(req.url, `http://127.0.0.1:${port}`);
|
|
@@ -199,11 +205,10 @@ function waitForMoonIDCallback({ port, state, timeoutMs }) {
|
|
|
199
205
|
});
|
|
200
206
|
}
|
|
201
207
|
|
|
202
|
-
async function saveAndValidateToken(token) {
|
|
203
|
-
const cfg = getConfig();
|
|
208
|
+
async function saveAndValidateToken(token, { apiUrl, platformName }) {
|
|
204
209
|
const fetch = require('node-fetch');
|
|
205
210
|
|
|
206
|
-
const res = await fetch(`${
|
|
211
|
+
const res = await fetch(`${apiUrl}/api/hosting/quota`, {
|
|
207
212
|
headers: { Authorization: `Bearer ${token}` },
|
|
208
213
|
});
|
|
209
214
|
|
|
@@ -211,10 +216,13 @@ async function saveAndValidateToken(token) {
|
|
|
211
216
|
throw new Error('Invalid or expired token');
|
|
212
217
|
}
|
|
213
218
|
|
|
214
|
-
|
|
219
|
+
// Token specific platform ke under save hoga
|
|
220
|
+
setPlatformToken(platformName, token);
|
|
221
|
+
|
|
215
222
|
console.log('');
|
|
216
223
|
console.log(chalk.green('✓ Logged in'));
|
|
217
|
-
console.log(chalk.gray(`
|
|
224
|
+
console.log(chalk.gray(` Platform: ${platformName}`));
|
|
225
|
+
console.log(chalk.gray(` Config: ~/.moon/config.json`));
|
|
218
226
|
console.log('');
|
|
219
227
|
}
|
|
220
228
|
|
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(), '.moon');
|
|
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(), '.moon');
|
|
8
8
|
const LOCAL_FILE = path.join(LOCAL_DIR, 'project.json');
|
|
9
9
|
|
|
10
10
|
function ensureDir(d) {
|
|
@@ -12,21 +12,36 @@ function ensureDir(d) {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
const DEFAULTS = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
defaultPlatform: 'moontraze',
|
|
16
|
+
platforms: {
|
|
17
|
+
moontraze: {
|
|
18
|
+
label: 'Moontraze',
|
|
19
|
+
apiUrl: process.env.MOON_API || 'https://api.moontraze.com',
|
|
20
|
+
domain: process.env.MOON_DOMAIN || 'moontraze.com',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
18
23
|
};
|
|
19
24
|
|
|
20
25
|
function migrate(cfg) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
+
};
|
|
25
43
|
}
|
|
26
|
-
|
|
27
|
-
next.domain = DEFAULTS.domain;
|
|
28
|
-
}
|
|
29
|
-
return next;
|
|
44
|
+
return { ...DEFAULTS, ...cfg };
|
|
30
45
|
}
|
|
31
46
|
|
|
32
47
|
function getConfig() {
|
|
@@ -36,16 +51,54 @@ function getConfig() {
|
|
|
36
51
|
return migrate(saved);
|
|
37
52
|
}
|
|
38
53
|
} catch (_) {}
|
|
39
|
-
return
|
|
54
|
+
return JSON.parse(JSON.stringify(DEFAULTS)); // deep copy
|
|
40
55
|
}
|
|
41
56
|
|
|
42
57
|
function setConfig(partial) {
|
|
43
58
|
ensureDir(GLOBAL_DIR);
|
|
44
|
-
const
|
|
59
|
+
const current = getConfig();
|
|
60
|
+
const next = { ...current, ...partial };
|
|
45
61
|
fs.writeFileSync(GLOBAL_FILE, JSON.stringify(next, null, 2));
|
|
46
62
|
return next;
|
|
47
63
|
}
|
|
48
64
|
|
|
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
|
+
|
|
49
102
|
function getProject() {
|
|
50
103
|
try {
|
|
51
104
|
if (fs.existsSync(LOCAL_FILE)) {
|
|
@@ -58,14 +111,26 @@ function getProject() {
|
|
|
58
111
|
function setProject(data) {
|
|
59
112
|
ensureDir(LOCAL_DIR);
|
|
60
113
|
fs.writeFileSync(LOCAL_FILE, JSON.stringify(data, null, 2));
|
|
114
|
+
|
|
115
|
+
// auto .gitignore
|
|
61
116
|
const ignore = path.join(process.cwd(), '.gitignore');
|
|
62
117
|
try {
|
|
63
118
|
let g = fs.existsSync(ignore) ? fs.readFileSync(ignore, 'utf8') : '';
|
|
64
|
-
if (!g.includes('.
|
|
65
|
-
fs.appendFileSync(ignore, '\n.
|
|
119
|
+
if (!g.includes('.moon')) {
|
|
120
|
+
fs.appendFileSync(ignore, '\n.moon/\n');
|
|
66
121
|
}
|
|
67
122
|
} catch (_) {}
|
|
68
123
|
return data;
|
|
69
124
|
}
|
|
70
125
|
|
|
71
|
-
module.exports = {
|
|
126
|
+
module.exports = {
|
|
127
|
+
getConfig,
|
|
128
|
+
setConfig,
|
|
129
|
+
getPlatform,
|
|
130
|
+
addPlatform,
|
|
131
|
+
removePlatform,
|
|
132
|
+
setPlatformToken,
|
|
133
|
+
getProject,
|
|
134
|
+
setProject,
|
|
135
|
+
GLOBAL_DIR,
|
|
136
|
+
};
|
package/lib/deploy.js
CHANGED
|
@@ -4,14 +4,40 @@ const fetch = require('node-fetch');
|
|
|
4
4
|
const FormData = require('form-data');
|
|
5
5
|
const ora = require('ora');
|
|
6
6
|
const chalk = require('chalk');
|
|
7
|
-
const { getConfig, getProject } = require('./config');
|
|
7
|
+
const { getConfig, getPlatform, getProject } = require('./config');
|
|
8
8
|
const { zipCwd } = require('./zip');
|
|
9
9
|
|
|
10
|
-
async function deploy({
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
async function deploy({
|
|
11
|
+
prod = true,
|
|
12
|
+
projectName,
|
|
13
|
+
apiUrl: apiUrlArg,
|
|
14
|
+
platformName: platformNameArg,
|
|
15
|
+
domain: domainArg,
|
|
16
|
+
} = {}) {
|
|
17
|
+
const platformName =
|
|
18
|
+
platformNameArg || process.env.MOON_CURRENT_PLATFORM || 'moontraze';
|
|
19
|
+
const platform = getPlatform(platformName);
|
|
20
|
+
|
|
21
|
+
const api =
|
|
22
|
+
apiUrlArg ||
|
|
23
|
+
process.env.MOON_API ||
|
|
24
|
+
platform?.apiUrl ||
|
|
25
|
+
'https://api.moontraze.com';
|
|
26
|
+
|
|
27
|
+
const domain =
|
|
28
|
+
domainArg ||
|
|
29
|
+
process.env.MOON_DOMAIN ||
|
|
30
|
+
platform?.domain ||
|
|
31
|
+
'moontraze.com';
|
|
32
|
+
|
|
33
|
+
const token =
|
|
34
|
+
process.env.MOON_TOKEN ||
|
|
35
|
+
platform?.token ||
|
|
36
|
+
null;
|
|
37
|
+
|
|
38
|
+
if (!token) {
|
|
13
39
|
throw new Error(
|
|
14
|
-
|
|
40
|
+
`Not logged in. Run: moon ${platformName} login`
|
|
15
41
|
);
|
|
16
42
|
}
|
|
17
43
|
|
|
@@ -19,18 +45,16 @@ async function deploy({ prod = true, projectName } = {}) {
|
|
|
19
45
|
const name = (projectName || linked?.projectName || '')
|
|
20
46
|
.toLowerCase()
|
|
21
47
|
.replace(/[^a-z0-9-]/g, '');
|
|
48
|
+
|
|
22
49
|
if (!name || name.length < 3) {
|
|
23
50
|
throw new Error(
|
|
24
|
-
|
|
51
|
+
`No project linked. Run: moon ${platformName} link my-site`
|
|
25
52
|
);
|
|
26
53
|
}
|
|
27
54
|
|
|
28
|
-
const domain = cfg.domain || 'moontraze.com';
|
|
29
|
-
const api = cfg.apiUrl || 'https://api.moontraze.com';
|
|
30
|
-
|
|
31
55
|
console.log('');
|
|
32
|
-
console.log(chalk.cyan(
|
|
33
|
-
console.log(`
|
|
56
|
+
console.log(chalk.cyan(platform?.label || platformName));
|
|
57
|
+
console.log(` API ${api}`);
|
|
34
58
|
console.log(` Project ${name}`);
|
|
35
59
|
console.log(` Target https://${name}.${domain}`);
|
|
36
60
|
console.log('');
|
|
@@ -45,9 +69,10 @@ async function deploy({ prod = true, projectName } = {}) {
|
|
|
45
69
|
|
|
46
70
|
spinner.text = 'Checking project...';
|
|
47
71
|
let alreadyExists = false;
|
|
72
|
+
|
|
48
73
|
try {
|
|
49
74
|
const statusRes = await fetch(`${api}/api/hosting/status/${name}`, {
|
|
50
|
-
headers: { Authorization: `Bearer ${
|
|
75
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
51
76
|
});
|
|
52
77
|
if (statusRes.ok) {
|
|
53
78
|
const statusData = await statusRes.json();
|
|
@@ -66,21 +91,16 @@ async function deploy({ prod = true, projectName } = {}) {
|
|
|
66
91
|
contentType: 'application/zip',
|
|
67
92
|
});
|
|
68
93
|
|
|
69
|
-
// existing → redeploy; new → deploy
|
|
70
94
|
const endpoint = alreadyExists
|
|
71
95
|
? `${api}/api/hosting/redeploy`
|
|
72
96
|
: `${api}/api/hosting/deploy`;
|
|
73
97
|
|
|
74
|
-
|
|
75
|
-
form.append('redeploy', 'true');
|
|
76
|
-
} else {
|
|
77
|
-
form.append('redeploy', 'false');
|
|
78
|
-
}
|
|
98
|
+
form.append('redeploy', alreadyExists ? 'true' : 'false');
|
|
79
99
|
|
|
80
100
|
const res = await fetch(endpoint, {
|
|
81
101
|
method: 'POST',
|
|
82
102
|
headers: {
|
|
83
|
-
Authorization: `Bearer ${
|
|
103
|
+
Authorization: `Bearer ${token}`,
|
|
84
104
|
...form.getHeaders(),
|
|
85
105
|
},
|
|
86
106
|
body: form,
|
|
@@ -102,6 +122,7 @@ async function deploy({ prod = true, projectName } = {}) {
|
|
|
102
122
|
}
|
|
103
123
|
|
|
104
124
|
spinner.succeed(`Ready in ${sec}s`);
|
|
125
|
+
|
|
105
126
|
const url = data.url || `https://${name}.${domain}`;
|
|
106
127
|
console.log('');
|
|
107
128
|
console.log(chalk.green(` Production ${url}`));
|
package/lib/zip.js
CHANGED
|
@@ -11,7 +11,8 @@ const SKIP = new Set([
|
|
|
11
11
|
'build',
|
|
12
12
|
'out',
|
|
13
13
|
'.vercel',
|
|
14
|
-
'.
|
|
14
|
+
'.moon',
|
|
15
|
+
'.moontraze', // purana bhi skip
|
|
15
16
|
'.netlify',
|
|
16
17
|
'coverage',
|
|
17
18
|
]);
|
|
@@ -25,8 +26,9 @@ function zipCwd() {
|
|
|
25
26
|
return new Promise((resolve, reject) => {
|
|
26
27
|
const outPath = path.join(
|
|
27
28
|
os.tmpdir(),
|
|
28
|
-
`
|
|
29
|
+
`moon-${Date.now()}.zip`
|
|
29
30
|
);
|
|
31
|
+
|
|
30
32
|
const output = fs.createWriteStream(outPath);
|
|
31
33
|
const archive = archiver('zip', { zlib: { level: 9 } });
|
|
32
34
|
|
|
@@ -38,10 +40,15 @@ function zipCwd() {
|
|
|
38
40
|
for (const name of fs.readdirSync(dir)) {
|
|
39
41
|
const full = path.join(dir, name);
|
|
40
42
|
const rel = base ? path.join(base, name) : name;
|
|
43
|
+
|
|
41
44
|
if (shouldSkip(rel)) continue;
|
|
45
|
+
|
|
42
46
|
const st = fs.statSync(full);
|
|
43
|
-
if (st.isDirectory())
|
|
44
|
-
|
|
47
|
+
if (st.isDirectory()) {
|
|
48
|
+
walk(full, rel);
|
|
49
|
+
} else {
|
|
50
|
+
archive.file(full, { name: rel.replace(/\\/g, '/') });
|
|
51
|
+
}
|
|
45
52
|
}
|
|
46
53
|
};
|
|
47
54
|
|