shyp 0.1.0 → 0.1.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/README.md +46 -3
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +2 -3
- package/dist/commands/add.d.ts +0 -1
- package/dist/commands/add.js +140 -8
- package/dist/commands/deploy.d.ts +0 -1
- package/dist/commands/deploy.js +0 -1
- package/dist/commands/doctor.d.ts +0 -1
- package/dist/commands/doctor.js +0 -1
- package/dist/commands/index.d.ts +0 -1
- package/dist/commands/index.js +0 -1
- package/dist/commands/init.d.ts +0 -1
- package/dist/commands/init.js +0 -1
- package/dist/commands/logs.d.ts +0 -1
- package/dist/commands/logs.js +0 -1
- package/dist/commands/ports.d.ts +0 -1
- package/dist/commands/ports.js +0 -1
- package/dist/commands/start.d.ts +0 -1
- package/dist/commands/start.js +0 -1
- package/dist/commands/status.d.ts +0 -1
- package/dist/commands/status.js +38 -9
- package/dist/commands/sync.d.ts +0 -1
- package/dist/commands/sync.js +44 -3
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/lib/config.d.ts +0 -1
- package/dist/lib/config.js +0 -1
- package/dist/lib/deploy.d.ts +0 -1
- package/dist/lib/deploy.js +0 -1
- package/dist/lib/git.d.ts +0 -1
- package/dist/lib/git.js +0 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +1 -1
- package/dist/lib/nginx.d.ts +0 -1
- package/dist/lib/nginx.js +0 -1
- package/dist/lib/pm2.d.ts +0 -1
- package/dist/lib/pm2.js +0 -1
- package/dist/lib/ssl.d.ts +22 -0
- package/dist/lib/ssl.js +115 -0
- package/dist/lib/state.d.ts +0 -1
- package/dist/lib/state.js +0 -1
- package/dist/schemas/app.d.ts +0 -1
- package/dist/schemas/app.js +0 -1
- package/dist/schemas/config.d.ts +15 -16
- package/dist/schemas/config.js +1 -2
- package/dist/schemas/engine.d.ts +0 -1
- package/dist/schemas/engine.js +0 -1
- package/dist/schemas/index.d.ts +0 -1
- package/dist/schemas/index.js +0 -1
- package/dist/schemas/state.d.ts +0 -1
- package/dist/schemas/state.js +0 -1
- package/dist/server/index.d.ts +0 -1
- package/dist/server/index.js +0 -1
- package/dist/server/webhook.d.ts +0 -1
- package/dist/server/webhook.js +0 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
- package/dist/utils/logger.d.ts +0 -1
- package/dist/utils/logger.js +0 -1
- package/dist/utils/paths.d.ts +0 -1
- package/dist/utils/paths.js +0 -1
- package/dist/utils/spinner.d.ts +0 -1
- package/dist/utils/spinner.js +0 -1
- package/package.json +2 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/add.d.ts.map +0 -1
- package/dist/commands/add.js.map +0 -1
- package/dist/commands/deploy.d.ts.map +0 -1
- package/dist/commands/deploy.js.map +0 -1
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/index.d.ts.map +0 -1
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/logs.d.ts.map +0 -1
- package/dist/commands/logs.js.map +0 -1
- package/dist/commands/ports.d.ts.map +0 -1
- package/dist/commands/ports.js.map +0 -1
- package/dist/commands/start.d.ts.map +0 -1
- package/dist/commands/start.js.map +0 -1
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/sync.d.ts.map +0 -1
- package/dist/commands/sync.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/config.d.ts.map +0 -1
- package/dist/lib/config.js.map +0 -1
- package/dist/lib/deploy.d.ts.map +0 -1
- package/dist/lib/deploy.js.map +0 -1
- package/dist/lib/git.d.ts.map +0 -1
- package/dist/lib/git.js.map +0 -1
- package/dist/lib/index.d.ts.map +0 -1
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/nginx.d.ts.map +0 -1
- package/dist/lib/nginx.js.map +0 -1
- package/dist/lib/pm2.d.ts.map +0 -1
- package/dist/lib/pm2.js.map +0 -1
- package/dist/lib/state.d.ts.map +0 -1
- package/dist/lib/state.js.map +0 -1
- package/dist/schemas/app.d.ts.map +0 -1
- package/dist/schemas/app.js.map +0 -1
- package/dist/schemas/config.d.ts.map +0 -1
- package/dist/schemas/config.js.map +0 -1
- package/dist/schemas/engine.d.ts.map +0 -1
- package/dist/schemas/engine.js.map +0 -1
- package/dist/schemas/index.d.ts.map +0 -1
- package/dist/schemas/index.js.map +0 -1
- package/dist/schemas/state.d.ts.map +0 -1
- package/dist/schemas/state.js.map +0 -1
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js.map +0 -1
- package/dist/server/webhook.d.ts.map +0 -1
- package/dist/server/webhook.js.map +0 -1
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/paths.d.ts.map +0 -1
- package/dist/utils/paths.js.map +0 -1
- package/dist/utils/spinner.d.ts.map +0 -1
- package/dist/utils/spinner.js.map +0 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
12
|
From code to production. Shyp now.<br>
|
|
13
|
-
AI-native deployment for Node.js apps on Linux
|
|
13
|
+
AI-native deployment for Node.js apps on Linux.
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
16
|
<p align="center">
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
- Nginx (optional, for domains)
|
|
38
38
|
- Git
|
|
39
39
|
|
|
40
|
-
> ⚠️ **Windows is not supported.** Shyp is designed for Linux
|
|
40
|
+
> ⚠️ **Windows is not supported.** Shyp is designed for Linux deployment.
|
|
41
41
|
|
|
42
42
|
## Installation
|
|
43
43
|
|
|
@@ -45,6 +45,48 @@
|
|
|
45
45
|
npm install -g shyp
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
## Before You Deploy
|
|
49
|
+
|
|
50
|
+
Before adding your first app, complete this checklist:
|
|
51
|
+
|
|
52
|
+
### 1. DNS Configuration
|
|
53
|
+
Point your domain to your server:
|
|
54
|
+
- Create an **A record** pointing `yourdomain.com` → `your-server-ip`
|
|
55
|
+
- Optional: Add a **www** subdomain if needed
|
|
56
|
+
|
|
57
|
+
### 2. Email Forwarding
|
|
58
|
+
Set up email forwarding for SSL certificate notifications:
|
|
59
|
+
- Create `contact@yourdomain.com` forwarding to your real email
|
|
60
|
+
- This is used by Let's Encrypt for certificate expiry warnings
|
|
61
|
+
|
|
62
|
+
### 3. GitHub SSH Key
|
|
63
|
+
Ensure your server can pull from GitHub:
|
|
64
|
+
```bash
|
|
65
|
+
# Generate a deploy key (if you haven't already)
|
|
66
|
+
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_myapp -N ""
|
|
67
|
+
|
|
68
|
+
# Add the public key to your repo
|
|
69
|
+
cat ~/.ssh/id_ed25519_myapp.pub
|
|
70
|
+
# → GitHub repo → Settings → Deploy keys → Add deploy key
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 4. Webhook Secret (for auto-deploy)
|
|
74
|
+
Generate a shared secret for GitHub webhooks:
|
|
75
|
+
```bash
|
|
76
|
+
# Generate a random secret
|
|
77
|
+
openssl rand -hex 32
|
|
78
|
+
|
|
79
|
+
# Set it on your server
|
|
80
|
+
export SHYP_WEBHOOK_SECRET=your-generated-secret
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Then configure the webhook in GitHub:
|
|
84
|
+
1. Go to your repo → **Settings** → **Webhooks** → **Add webhook**
|
|
85
|
+
2. **Payload URL:** `http://your-server-ip:9000/`
|
|
86
|
+
3. **Content type:** `application/json`
|
|
87
|
+
4. **Secret:** Your `SHYP_WEBHOOK_SECRET`
|
|
88
|
+
5. **Events:** Just the push event
|
|
89
|
+
|
|
48
90
|
## Quick Start
|
|
49
91
|
|
|
50
92
|
```bash
|
|
@@ -93,7 +135,7 @@ landing-page ● online 3003 45MB 12d 3h example.com
|
|
|
93
135
|
| `shyp status` | Show status of all apps |
|
|
94
136
|
| `shyp deploy <name>` | Deploy an app |
|
|
95
137
|
| `shyp add <name>` | Add a new app configuration |
|
|
96
|
-
| `shyp sync` |
|
|
138
|
+
| `shyp sync` | Sync configs, provision SSL certs, reload Nginx |
|
|
97
139
|
| `shyp ports` | Show port allocations |
|
|
98
140
|
| `shyp logs <name>` | View deployment logs |
|
|
99
141
|
| `shyp doctor` | Check system health |
|
|
@@ -209,6 +251,7 @@ shyp deploy new-project
|
|
|
209
251
|
## Links
|
|
210
252
|
|
|
211
253
|
- **Website:** [shyp.now](https://shyp.now)
|
|
254
|
+
- **Documentation:** [shyp.now/docs](https://shyp.now/docs)
|
|
212
255
|
- **GitHub:** [github.com/shypd/shyp](https://github.com/shypd/shyp)
|
|
213
256
|
- **Issues:** [github.com/shypd/shyp/issues](https://github.com/shypd/shyp/issues)
|
|
214
257
|
- **npm:** [npmjs.com/package/shyp](https://www.npmjs.com/package/shyp)
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import { statusCommand, deployCommand, portsCommand, doctorCommand, initCommand,
|
|
|
4
4
|
program
|
|
5
5
|
.name('shyp')
|
|
6
6
|
.description('Zero friction deployment for Node.js apps')
|
|
7
|
-
.version('0.1.
|
|
7
|
+
.version('0.1.4');
|
|
8
8
|
// shyp status
|
|
9
9
|
program
|
|
10
10
|
.command('status')
|
|
@@ -40,7 +40,7 @@ program
|
|
|
40
40
|
// shyp sync
|
|
41
41
|
program
|
|
42
42
|
.command('sync')
|
|
43
|
-
.description('
|
|
43
|
+
.description('Sync configs, provision SSL certs, reload Nginx')
|
|
44
44
|
.option('-n, --dry-run', 'Show what would be done without making changes')
|
|
45
45
|
.action(syncCommand);
|
|
46
46
|
// shyp logs <name>
|
|
@@ -61,4 +61,3 @@ program
|
|
|
61
61
|
.action(addCommand);
|
|
62
62
|
// Parse arguments
|
|
63
63
|
program.parse();
|
|
64
|
-
//# sourceMappingURL=cli.js.map
|
package/dist/commands/add.d.ts
CHANGED
package/dist/commands/add.js
CHANGED
|
@@ -2,9 +2,124 @@ import { writeFile } from 'fs/promises';
|
|
|
2
2
|
import { existsSync } from 'fs';
|
|
3
3
|
import { stringify as yamlStringify } from 'yaml';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
|
+
import { input, select, confirm } from '@inquirer/prompts';
|
|
5
6
|
import { isInitialized, getAppConfigPath } from '../lib/config.js';
|
|
6
7
|
import { allocatePort } from '../lib/state.js';
|
|
7
8
|
import { log } from '../utils/logger.js';
|
|
9
|
+
function showPrerequisites() {
|
|
10
|
+
console.log();
|
|
11
|
+
console.log(chalk.bold.cyan('Before You Deploy'));
|
|
12
|
+
console.log(chalk.dim('─'.repeat(60)));
|
|
13
|
+
console.log();
|
|
14
|
+
console.log(chalk.yellow('Complete this checklist before adding your app:'));
|
|
15
|
+
console.log();
|
|
16
|
+
// 1. DNS
|
|
17
|
+
console.log(chalk.bold('1. DNS Configuration'));
|
|
18
|
+
console.log(chalk.dim(' Point your domain to your server\'s IP address:'));
|
|
19
|
+
console.log();
|
|
20
|
+
console.log(chalk.dim(' Go to your domain registrar (Namecheap, Cloudflare, etc.)'));
|
|
21
|
+
console.log(chalk.dim(' → DNS settings → Add record:'));
|
|
22
|
+
console.log(chalk.white(' Type: A'));
|
|
23
|
+
console.log(chalk.white(' Host: @ (or leave blank for root domain)'));
|
|
24
|
+
console.log(chalk.white(' Value: YOUR_SERVER_IP'));
|
|
25
|
+
console.log(chalk.white(' TTL: Automatic'));
|
|
26
|
+
console.log();
|
|
27
|
+
// 2. Email
|
|
28
|
+
console.log(chalk.bold('2. Email Forwarding (for SSL notifications)'));
|
|
29
|
+
console.log(chalk.dim(' Let\'s Encrypt sends certificate expiry warnings to contact@yourdomain.com'));
|
|
30
|
+
console.log();
|
|
31
|
+
console.log(chalk.dim(' Option A: Domain registrar email forwarding'));
|
|
32
|
+
console.log(chalk.dim(' → Email settings → Add forwarder:'));
|
|
33
|
+
console.log(chalk.white(' contact@yourdomain.com → your-real-email@gmail.com'));
|
|
34
|
+
console.log();
|
|
35
|
+
console.log(chalk.dim(' Option B: Use a different email in the wizard below'));
|
|
36
|
+
console.log();
|
|
37
|
+
// 3. SSH Key
|
|
38
|
+
console.log(chalk.bold('3. GitHub Deploy Key'));
|
|
39
|
+
console.log(chalk.dim(' Your server needs permission to pull from your GitHub repo.'));
|
|
40
|
+
console.log();
|
|
41
|
+
console.log(chalk.dim(' On your server, run:'));
|
|
42
|
+
console.log(chalk.white(' ssh-keygen -t ed25519 -f ~/.ssh/deploy_key -N ""'));
|
|
43
|
+
console.log(chalk.white(' cat ~/.ssh/deploy_key.pub'));
|
|
44
|
+
console.log();
|
|
45
|
+
console.log(chalk.dim(' Copy the public key, then in GitHub:'));
|
|
46
|
+
console.log(chalk.dim(' → Your repo → Settings → Deploy keys → Add deploy key'));
|
|
47
|
+
console.log(chalk.white(' Title: "My Server"'));
|
|
48
|
+
console.log(chalk.white(' Key: (paste the public key)'));
|
|
49
|
+
console.log(chalk.white(' Allow write access: No (leave unchecked)'));
|
|
50
|
+
console.log();
|
|
51
|
+
// 4. Webhook
|
|
52
|
+
console.log(chalk.bold('4. GitHub Webhook (optional - for auto-deploy on push)'));
|
|
53
|
+
console.log(chalk.dim(' Automatically deploy when you push to GitHub.'));
|
|
54
|
+
console.log();
|
|
55
|
+
console.log(chalk.dim(' First, generate a secret on your server:'));
|
|
56
|
+
console.log(chalk.white(' openssl rand -hex 32'));
|
|
57
|
+
console.log(chalk.dim(' Save this secret! Add it to your server environment:'));
|
|
58
|
+
console.log(chalk.white(' export SHYP_WEBHOOK_SECRET=your-generated-secret'));
|
|
59
|
+
console.log();
|
|
60
|
+
console.log(chalk.dim(' Then in GitHub:'));
|
|
61
|
+
console.log(chalk.dim(' → Your repo → Settings → Webhooks → Add webhook'));
|
|
62
|
+
console.log(chalk.white(' Payload URL: http://YOUR_SERVER_IP:9000/'));
|
|
63
|
+
console.log(chalk.white(' Content type: application/json'));
|
|
64
|
+
console.log(chalk.white(' Secret: (paste your SHYP_WEBHOOK_SECRET)'));
|
|
65
|
+
console.log(chalk.white(' Events: Just the push event'));
|
|
66
|
+
console.log(chalk.white(' Active: Yes'));
|
|
67
|
+
console.log();
|
|
68
|
+
console.log(chalk.dim(' After setup, run: shyp start'));
|
|
69
|
+
console.log();
|
|
70
|
+
}
|
|
71
|
+
async function runWizard(name) {
|
|
72
|
+
showPrerequisites();
|
|
73
|
+
const proceed = await confirm({
|
|
74
|
+
message: 'Have you completed the prerequisites above?',
|
|
75
|
+
default: true
|
|
76
|
+
});
|
|
77
|
+
if (!proceed) {
|
|
78
|
+
console.log();
|
|
79
|
+
log.info('Complete the prerequisites first, then run shyp add again');
|
|
80
|
+
process.exit(0);
|
|
81
|
+
}
|
|
82
|
+
console.log();
|
|
83
|
+
console.log(chalk.bold.cyan(`Adding new app: ${name}`));
|
|
84
|
+
console.log(chalk.dim('─'.repeat(50)));
|
|
85
|
+
console.log();
|
|
86
|
+
// Repository URL
|
|
87
|
+
const repo = await input({
|
|
88
|
+
message: 'GitHub repository URL:',
|
|
89
|
+
default: `git@github.com:YOUR_ORG/${name}.git`,
|
|
90
|
+
validate: (value) => {
|
|
91
|
+
if (!value.includes('github.com') && !value.startsWith('git@')) {
|
|
92
|
+
return 'Please enter a valid GitHub repository URL';
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
// Domain
|
|
98
|
+
const domain = await input({
|
|
99
|
+
message: 'Domain name (leave empty for no domain):',
|
|
100
|
+
default: ''
|
|
101
|
+
});
|
|
102
|
+
// Email for SSL (only if domain provided)
|
|
103
|
+
let email;
|
|
104
|
+
if (domain) {
|
|
105
|
+
email = await input({
|
|
106
|
+
message: 'Email for SSL certificates:',
|
|
107
|
+
default: `contact@${domain}`
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
// App type
|
|
111
|
+
const type = await select({
|
|
112
|
+
message: 'Application type:',
|
|
113
|
+
choices: [
|
|
114
|
+
{ name: 'Next.js', value: 'nextjs', description: 'Next.js application with npm start' },
|
|
115
|
+
{ name: 'Node.js', value: 'node', description: 'Standard Node.js application' },
|
|
116
|
+
{ name: 'Static', value: 'static', description: 'Static files served by Nginx' },
|
|
117
|
+
{ name: 'Script', value: 'script', description: 'Custom deploy script' }
|
|
118
|
+
],
|
|
119
|
+
default: 'nextjs'
|
|
120
|
+
});
|
|
121
|
+
return { repo, domain: domain || undefined, email, type };
|
|
122
|
+
}
|
|
8
123
|
export async function addCommand(name, options) {
|
|
9
124
|
log.banner();
|
|
10
125
|
if (!isInitialized()) {
|
|
@@ -17,20 +132,37 @@ export async function addCommand(name, options) {
|
|
|
17
132
|
log.dim(`Config: ${configPath}`);
|
|
18
133
|
process.exit(1);
|
|
19
134
|
}
|
|
135
|
+
// Check if we should run the wizard (no options provided)
|
|
136
|
+
const hasOptions = options.repo || options.domain || options.type || options.port;
|
|
137
|
+
let repo = options.repo;
|
|
138
|
+
let domain = options.domain;
|
|
139
|
+
let type = options.type || 'nextjs';
|
|
140
|
+
let email;
|
|
141
|
+
if (!hasOptions) {
|
|
142
|
+
// Run interactive wizard
|
|
143
|
+
const wizardResult = await runWizard(name);
|
|
144
|
+
repo = wizardResult.repo;
|
|
145
|
+
domain = wizardResult.domain;
|
|
146
|
+
type = wizardResult.type;
|
|
147
|
+
email = wizardResult.email;
|
|
148
|
+
}
|
|
20
149
|
// Allocate port if not specified
|
|
21
150
|
const port = options.port || await allocatePort(name, 'standard');
|
|
22
151
|
// Build config
|
|
23
152
|
const config = {
|
|
24
153
|
name,
|
|
25
154
|
description: `${name} application`,
|
|
26
|
-
repo:
|
|
155
|
+
repo: repo || `git@github.com:YOUR_ORG/${name}.git`,
|
|
27
156
|
branch: 'main',
|
|
28
157
|
path: `/var/www/${name}`,
|
|
29
|
-
type
|
|
158
|
+
type,
|
|
30
159
|
port,
|
|
31
160
|
};
|
|
32
|
-
if (
|
|
33
|
-
config.domain =
|
|
161
|
+
if (domain) {
|
|
162
|
+
config.domain = domain;
|
|
163
|
+
}
|
|
164
|
+
if (email) {
|
|
165
|
+
config.ssl = { email };
|
|
34
166
|
}
|
|
35
167
|
config.build = {
|
|
36
168
|
command: 'npm ci && npm run build',
|
|
@@ -52,6 +184,7 @@ export async function addCommand(name, options) {
|
|
|
52
184
|
// Write config file
|
|
53
185
|
const yaml = yamlStringify(config);
|
|
54
186
|
await writeFile(configPath, yaml);
|
|
187
|
+
console.log();
|
|
55
188
|
log.success(`Created app config: ${name}`);
|
|
56
189
|
console.log();
|
|
57
190
|
console.log(chalk.dim('Config file:'));
|
|
@@ -61,9 +194,8 @@ export async function addCommand(name, options) {
|
|
|
61
194
|
console.log(chalk.cyan(yaml));
|
|
62
195
|
console.log();
|
|
63
196
|
log.info('Next steps:');
|
|
64
|
-
console.log(chalk.dim(` 1.
|
|
65
|
-
console.log(chalk.dim(` 2. Apply changes:
|
|
66
|
-
console.log(chalk.dim(` 3. Deploy:
|
|
197
|
+
console.log(chalk.dim(` 1. Review the config: nano ${configPath}`));
|
|
198
|
+
console.log(chalk.dim(` 2. Apply changes: shyp sync`));
|
|
199
|
+
console.log(chalk.dim(` 3. Deploy: shyp deploy ${name}`));
|
|
67
200
|
console.log();
|
|
68
201
|
}
|
|
69
|
-
//# sourceMappingURL=add.js.map
|
package/dist/commands/deploy.js
CHANGED
package/dist/commands/doctor.js
CHANGED
package/dist/commands/index.d.ts
CHANGED
package/dist/commands/index.js
CHANGED
package/dist/commands/init.d.ts
CHANGED
package/dist/commands/init.js
CHANGED
package/dist/commands/logs.d.ts
CHANGED
package/dist/commands/logs.js
CHANGED
package/dist/commands/ports.d.ts
CHANGED
package/dist/commands/ports.js
CHANGED
package/dist/commands/start.d.ts
CHANGED
package/dist/commands/start.js
CHANGED
package/dist/commands/status.js
CHANGED
|
@@ -2,6 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { loadAppConfigs, loadEngineConfigs, isInitialized } from '../lib/config.js';
|
|
3
3
|
import { listProcesses, formatMemory, formatUptime } from '../lib/pm2.js';
|
|
4
4
|
import { loadPortAllocations, loadDeployments } from '../lib/state.js';
|
|
5
|
+
import { getCertInfo, formatCertStatus } from '../lib/ssl.js';
|
|
5
6
|
import { log } from '../utils/logger.js';
|
|
6
7
|
export async function statusCommand() {
|
|
7
8
|
log.banner();
|
|
@@ -22,11 +23,29 @@ export async function statusCommand() {
|
|
|
22
23
|
for (const p of processes) {
|
|
23
24
|
processMap.set(p.name, p);
|
|
24
25
|
}
|
|
26
|
+
// Collect all domains for cert checking
|
|
27
|
+
const domains = [];
|
|
28
|
+
for (const [, config] of apps) {
|
|
29
|
+
if (config.domain)
|
|
30
|
+
domains.push(config.domain);
|
|
31
|
+
}
|
|
32
|
+
for (const [, config] of engines) {
|
|
33
|
+
for (const [, mod] of Object.entries(config.modules)) {
|
|
34
|
+
if (mod.domain)
|
|
35
|
+
domains.push(mod.domain);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Get cert info for all domains
|
|
39
|
+
const certMap = new Map();
|
|
40
|
+
for (const domain of domains) {
|
|
41
|
+
const info = await getCertInfo(domain);
|
|
42
|
+
certMap.set(domain, info);
|
|
43
|
+
}
|
|
25
44
|
// Display apps
|
|
26
45
|
if (apps.size > 0) {
|
|
27
46
|
console.log(chalk.bold.white('\nApps'));
|
|
28
|
-
console.log(chalk.dim('─'.repeat(
|
|
29
|
-
console.log(chalk.dim('NAME'.padEnd(
|
|
47
|
+
console.log(chalk.dim('─'.repeat(80)));
|
|
48
|
+
console.log(chalk.dim('NAME'.padEnd(18)), chalk.dim('STATUS'.padEnd(12)), chalk.dim('PORT'.padEnd(6)), chalk.dim('MEM'.padEnd(8)), chalk.dim('UPTIME'.padEnd(10)), chalk.dim('SSL'.padEnd(6)), chalk.dim('DOMAIN'));
|
|
30
49
|
for (const [name, config] of apps) {
|
|
31
50
|
const pm2Name = config.pm2?.name || name;
|
|
32
51
|
const proc = processMap.get(pm2Name);
|
|
@@ -34,20 +53,26 @@ export async function statusCommand() {
|
|
|
34
53
|
const status = proc?.status || 'stopped';
|
|
35
54
|
const statusColor = status === 'online' ? chalk.green : chalk.red;
|
|
36
55
|
const statusIcon = status === 'online' ? '●' : '○';
|
|
37
|
-
|
|
56
|
+
// Get cert status
|
|
57
|
+
const certInfo = config.domain ? certMap.get(config.domain) : null;
|
|
58
|
+
const cert = certInfo ? formatCertStatus(certInfo) : { text: '-', color: 'dim' };
|
|
59
|
+
const certColor = cert.color === 'green' ? chalk.green :
|
|
60
|
+
cert.color === 'yellow' ? chalk.yellow :
|
|
61
|
+
cert.color === 'red' ? chalk.red : chalk.dim;
|
|
62
|
+
console.log(chalk.white(name.padEnd(18)), statusColor(`${statusIcon} ${status}`.padEnd(12)), chalk.cyan(String(port).padEnd(6)), chalk.dim((proc ? formatMemory(proc.memory) : '-').padEnd(8)), chalk.dim((proc ? formatUptime(proc.uptime) : '-').padEnd(10)), certColor(cert.text.padEnd(6)), chalk.yellow(config.domain || '-'));
|
|
38
63
|
}
|
|
39
64
|
}
|
|
40
65
|
// Display engines
|
|
41
66
|
if (engines.size > 0) {
|
|
42
67
|
console.log(chalk.bold.white('\nEngines'));
|
|
43
|
-
console.log(chalk.dim('─'.repeat(
|
|
68
|
+
console.log(chalk.dim('─'.repeat(80)));
|
|
44
69
|
for (const [name, config] of engines) {
|
|
45
70
|
const pm2Name = config.server.pm2?.name || name;
|
|
46
71
|
const proc = processMap.get(pm2Name);
|
|
47
72
|
const status = proc?.status || 'stopped';
|
|
48
73
|
const statusColor = status === 'online' ? chalk.green : chalk.red;
|
|
49
74
|
const statusIcon = status === 'online' ? '●' : '○';
|
|
50
|
-
console.log(chalk.white(name.padEnd(
|
|
75
|
+
console.log(chalk.white(name.padEnd(18)), statusColor(`${statusIcon} ${status}`.padEnd(12)), chalk.dim('Engine'), chalk.dim(proc ? formatMemory(proc.memory) : ''));
|
|
51
76
|
// Display modules
|
|
52
77
|
const modules = Object.entries(config.modules);
|
|
53
78
|
if (modules.length > 0) {
|
|
@@ -58,16 +83,20 @@ export async function statusCommand() {
|
|
|
58
83
|
const moduleStatus = moduleProc?.status || (status === 'online' ? 'managed' : 'stopped');
|
|
59
84
|
const moduleStatusColor = moduleStatus === 'online' || moduleStatus === 'managed' ? chalk.green : chalk.red;
|
|
60
85
|
const moduleIcon = moduleStatus === 'online' || moduleStatus === 'managed' ? '●' : '○';
|
|
61
|
-
|
|
86
|
+
// Get cert status for module
|
|
87
|
+
const modCertInfo = moduleConfig.domain ? certMap.get(moduleConfig.domain) : null;
|
|
88
|
+
const modCert = modCertInfo ? formatCertStatus(modCertInfo) : { text: '-', color: 'dim' };
|
|
89
|
+
const modCertColor = modCert.color === 'green' ? chalk.green :
|
|
90
|
+
modCert.color === 'yellow' ? chalk.yellow :
|
|
91
|
+
modCert.color === 'red' ? chalk.red : chalk.dim;
|
|
92
|
+
console.log(chalk.dim(' └─'), chalk.white(moduleName.padEnd(14)), moduleStatusColor(`${moduleIcon} ${moduleStatus}`.padEnd(12)), chalk.cyan(String(moduleConfig.port).padEnd(6)), modCertColor(modCert.text.padEnd(6)), chalk.yellow(moduleConfig.domain || '-'));
|
|
62
93
|
}
|
|
63
94
|
}
|
|
64
95
|
}
|
|
65
96
|
}
|
|
66
97
|
if (apps.size === 0 && engines.size === 0) {
|
|
67
98
|
log.dim('\nNo apps or engines configured.');
|
|
68
|
-
log.dim('Add an app:
|
|
69
|
-
log.dim('Import apps: shyp import');
|
|
99
|
+
log.dim('Add an app: shyp add <name>');
|
|
70
100
|
}
|
|
71
101
|
console.log();
|
|
72
102
|
}
|
|
73
|
-
//# sourceMappingURL=status.js.map
|
package/dist/commands/sync.d.ts
CHANGED
package/dist/commands/sync.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { loadAppConfigs, loadEngineConfigs, isInitialized } from '../lib/config.js';
|
|
1
|
+
import { loadAppConfigs, loadEngineConfigs, loadGlobalConfig, isInitialized } from '../lib/config.js';
|
|
2
2
|
import { allocatePort } from '../lib/state.js';
|
|
3
3
|
import { generateNginxConfig, generateModuleConfig, writeNginxConfig, enableNginxConfig, testNginxConfig, reloadNginx, } from '../lib/nginx.js';
|
|
4
|
+
import { getCertInfo, obtainCert, isCertbotAvailable } from '../lib/ssl.js';
|
|
4
5
|
import { log } from '../utils/logger.js';
|
|
5
6
|
import { createSpinner } from '../utils/spinner.js';
|
|
6
7
|
export async function syncCommand(options) {
|
|
@@ -14,12 +15,17 @@ export async function syncCommand(options) {
|
|
|
14
15
|
log.info('Dry run mode - no changes will be made');
|
|
15
16
|
console.log();
|
|
16
17
|
}
|
|
17
|
-
const [apps, engines] = await Promise.all([
|
|
18
|
+
const [apps, engines, globalConfig] = await Promise.all([
|
|
18
19
|
loadAppConfigs(),
|
|
19
20
|
loadEngineConfigs(),
|
|
21
|
+
loadGlobalConfig(),
|
|
20
22
|
]);
|
|
23
|
+
// Get SSL email from config (fallback to contact@domain per-domain)
|
|
24
|
+
const sslEmail = globalConfig?.server?.ssl?.email;
|
|
21
25
|
// Track what we're doing
|
|
22
26
|
const actions = [];
|
|
27
|
+
// Collect all domains for SSL
|
|
28
|
+
const domains = [];
|
|
23
29
|
// Allocate ports for apps that don't have them
|
|
24
30
|
log.info('Checking port allocations...');
|
|
25
31
|
for (const [name, config] of apps) {
|
|
@@ -28,6 +34,42 @@ export async function syncCommand(options) {
|
|
|
28
34
|
config.port = port;
|
|
29
35
|
actions.push(`Allocated port ${port} for ${name}`);
|
|
30
36
|
}
|
|
37
|
+
if (config.domain) {
|
|
38
|
+
domains.push(config.domain);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Collect engine module domains
|
|
42
|
+
for (const [, engine] of engines) {
|
|
43
|
+
for (const [, moduleConfig] of Object.entries(engine.modules)) {
|
|
44
|
+
if (moduleConfig.domain) {
|
|
45
|
+
domains.push(moduleConfig.domain);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Provision SSL certs for domains that need them
|
|
50
|
+
if (domains.length > 0 && !dryRun) {
|
|
51
|
+
log.info('Checking SSL certificates...');
|
|
52
|
+
const hasCertbot = await isCertbotAvailable();
|
|
53
|
+
if (hasCertbot) {
|
|
54
|
+
for (const domain of domains) {
|
|
55
|
+
const certInfo = await getCertInfo(domain);
|
|
56
|
+
if (!certInfo.exists) {
|
|
57
|
+
const spinner = createSpinner(`Obtaining cert for ${domain}...`).start();
|
|
58
|
+
const result = await obtainCert(domain, sslEmail);
|
|
59
|
+
if (result.success) {
|
|
60
|
+
spinner.succeed(`Obtained cert for ${domain}`);
|
|
61
|
+
actions.push(`Obtained SSL cert for ${domain}`);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
spinner.fail(`Failed to obtain cert for ${domain}`);
|
|
65
|
+
log.dim(` ${result.error}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
log.dim(' certbot not installed - skipping SSL provisioning');
|
|
72
|
+
}
|
|
31
73
|
}
|
|
32
74
|
// Generate nginx configs for apps with domains
|
|
33
75
|
log.info('Generating nginx configs...');
|
|
@@ -92,4 +134,3 @@ export async function syncCommand(options) {
|
|
|
92
134
|
console.log();
|
|
93
135
|
log.success(`Sync complete. Applied ${actions.length} changes.`);
|
|
94
136
|
}
|
|
95
|
-
//# sourceMappingURL=sync.js.map
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/lib/config.d.ts
CHANGED
|
@@ -7,4 +7,3 @@ export declare function loadEngineConfig(name: string): Promise<EngineConfig | n
|
|
|
7
7
|
export declare function isInitialized(): boolean;
|
|
8
8
|
export declare function getAppConfigPath(name: string): string;
|
|
9
9
|
export declare function getEngineConfigPath(name: string): string;
|
|
10
|
-
//# sourceMappingURL=config.d.ts.map
|
package/dist/lib/config.js
CHANGED
package/dist/lib/deploy.d.ts
CHANGED
|
@@ -9,4 +9,3 @@ export interface DeployResult {
|
|
|
9
9
|
export declare function deployApp(config: AppConfig): Promise<DeployResult>;
|
|
10
10
|
export declare function deployModule(engine: EngineConfig, moduleName: string, moduleConfig: ModuleConfig): Promise<DeployResult>;
|
|
11
11
|
export declare function deployEngine(engine: EngineConfig): Promise<DeployResult>;
|
|
12
|
-
//# sourceMappingURL=deploy.d.ts.map
|
package/dist/lib/deploy.js
CHANGED
package/dist/lib/git.d.ts
CHANGED
package/dist/lib/git.js
CHANGED
package/dist/lib/index.d.ts
CHANGED
package/dist/lib/index.js
CHANGED
package/dist/lib/nginx.d.ts
CHANGED
package/dist/lib/nginx.js
CHANGED
package/dist/lib/pm2.d.ts
CHANGED
|
@@ -22,4 +22,3 @@ export declare function saveProcessList(): Promise<void>;
|
|
|
22
22
|
export declare function isPM2Available(): Promise<boolean>;
|
|
23
23
|
export declare function formatMemory(bytes: number): string;
|
|
24
24
|
export declare function formatUptime(startTime: number): string;
|
|
25
|
-
//# sourceMappingURL=pm2.d.ts.map
|