@instawp/cli 0.0.1-beta.4 → 0.0.1-beta.6
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/CHANGELOG.md +32 -0
- package/README.md +58 -10
- package/bin/win32/msys-2.0.dll +0 -0
- package/bin/win32/msys-crypto-3.dll +0 -0
- package/bin/win32/msys-iconv-2.dll +0 -0
- package/bin/win32/msys-intl-8.dll +0 -0
- package/bin/win32/msys-popt-0.dll +0 -0
- package/bin/win32/msys-xxhash-0.dll +0 -0
- package/bin/win32/msys-zstd-1.dll +0 -0
- package/bin/win32/rsync.exe +0 -0
- package/dist/commands/db.d.ts +2 -0
- package/dist/commands/db.js +331 -0
- package/dist/commands/db.js.map +1 -0
- package/dist/commands/exec.js +36 -3
- package/dist/commands/exec.js.map +1 -1
- package/dist/commands/logs.d.ts +2 -0
- package/dist/commands/logs.js +239 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/open.d.ts +2 -0
- package/dist/commands/open.js +114 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/sites.js +73 -0
- package/dist/commands/sites.js.map +1 -1
- package/dist/index.js +20 -8
- package/dist/index.js.map +1 -1
- package/dist/lib/output.js +14 -1
- package/dist/lib/output.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.0.1-beta.6 (2026-05-23)
|
|
4
|
+
|
|
5
|
+
### Bug Fixes (Windows)
|
|
6
|
+
- Bundled `rsync.exe` now actually loads. beta.4/beta.5 shipped with `msys-2.0.dll` from the legacy `msys2-runtime-3.3` fork, which is missing the `fallocate` symbol that rsync 3.4 needs — produced `Entry Point Not Found: fallocate` on launch and exit code `3221225785` (`STATUS_DLL_INIT_FAILED`) when invoked indirectly via `sync push/pull` or `local clone`.
|
|
7
|
+
- Rebuilt the Windows bundle against current MSYS2 packages: `msys2-runtime-3.6.9-1`, `libopenssl-3.6.2-1`, `libiconv-1.19-1`, `libxxhash-0.8.3-1`, `libzstd-1.5.7-1`, `popt-1.19-1`, `libintl-0.22.5-1`. Includes `msys-popt-0.dll` and `msys-intl-8.dll` which the newer rsync now requires.
|
|
8
|
+
- Upgraded bundled rsync from 3.4.0 → 3.4.2-2.
|
|
9
|
+
|
|
10
|
+
### Internals
|
|
11
|
+
- `scripts/fetch-windows-binaries.sh` now verifies DLL closure (every referenced `msys-*.dll` is present) and asserts `fallocate` is exported from `msys-2.0.dll` before declaring the bundle valid. Catches "wrong runtime fork" regressions at build time.
|
|
12
|
+
- Added `smoke-windows` job to the publish workflow — runs on `windows-latest` and actually executes the bundled `rsync.exe` and `busybox.exe` before npm publish. Publish is now gated on this passing.
|
|
13
|
+
|
|
14
|
+
## 0.0.1-beta.5 (2026-05-23)
|
|
15
|
+
|
|
16
|
+
### New Commands
|
|
17
|
+
- `db push <site> <file>` — Push a local SQL dump (`.sql` or `.sql.gz`) to the remote MySQL database. Always backs up the remote DB to `~/db-backup-{ISO}.sql.gz` first (skip with `--no-backup`). Confirmation prompt unless `--force`. Closes the #1 gap blocking full-site deploys from the CLI.
|
|
18
|
+
- `db pull <site>` — Stream the remote MySQL database to a local gzipped dump. `--output <path>` and `--no-compress` flags.
|
|
19
|
+
- `open <site>` — Open the site URL in the default browser. `--admin` opens `/wp-admin`, `--magic` opens the Magic Login URL, `--print` pipes the URL to stdout instead.
|
|
20
|
+
- `logs <site>` — Tail logs via SSH. `--wp` (default, debug.log), `--php` (PHP-FPM error log), `--nginx` (nginx error log), `--follow` / `-f`, `--lines <n>`. Multiple flags multi-tail. Probes HestiaCP path variations automatically.
|
|
21
|
+
- `sites creds <site>` — Re-fetch WP admin credentials + Magic Login URL for an existing site (previously only available in the `create` output).
|
|
22
|
+
|
|
23
|
+
### Improvements
|
|
24
|
+
- `wp <site>` is now positioned as the primary remote-access command; `exec` is documented as the escape hatch for non-WP shell commands.
|
|
25
|
+
- `wp` / `exec` accept POSIX `--` to forward raw args verbatim: `instawp wp my-site -- post list --post_type=page`.
|
|
26
|
+
- Spinners are suppressed in non-TTY contexts, CI environments (`CI` env var), `--json` mode, `NO_COLOR`, and `INSTAWP_QUIET` — fixes "Resolving site..." leaking into piped output.
|
|
27
|
+
|
|
28
|
+
### Bug Fixes
|
|
29
|
+
- `instawp wp <site> eval '...'` no longer breaks on parens, quotes, or other shell metacharacters. Each arg is now POSIX shell-quoted before being piped to the remote shell's stdin (previously `args.join(' ')` left metacharacters unescaped, causing remote `bash: syntax error near unexpected token '('`).
|
|
30
|
+
|
|
31
|
+
### Docs
|
|
32
|
+
- New `ROADMAP.md` capturing 15 forward-looking improvement areas (multi-site bulk ops, cost transparency, CI/CD deploy command, shell completion, `doctor`, config file, snapshot/migration CLI, self-update, etc.) ranked by ROI.
|
|
33
|
+
- README + CLAUDE.md updated with `wp`-primary positioning and examples for all new commands.
|
|
34
|
+
|
|
3
35
|
## 0.0.1-beta.4 (2026-05-22)
|
|
4
36
|
|
|
5
37
|
### Windows — Zero-Install Support
|
package/README.md
CHANGED
|
@@ -33,26 +33,42 @@ instawp sites list
|
|
|
33
33
|
instawp create --name my-site
|
|
34
34
|
instawp create --name my-site --php 8.3
|
|
35
35
|
|
|
36
|
+
# Re-fetch admin credentials + Magic Login URL
|
|
37
|
+
instawp sites creds <site>
|
|
38
|
+
|
|
39
|
+
# Open the site (or admin / magic login) in your browser
|
|
40
|
+
instawp open <site>
|
|
41
|
+
instawp open <site> --admin
|
|
42
|
+
instawp open <site> --magic
|
|
43
|
+
|
|
36
44
|
# Delete a site
|
|
37
45
|
instawp sites delete <site>
|
|
38
46
|
instawp sites delete <site> --force
|
|
39
47
|
```
|
|
40
48
|
|
|
41
|
-
### Run Commands
|
|
49
|
+
### Run Commands (WP-CLI + shell)
|
|
50
|
+
|
|
51
|
+
`wp` is the **primary** command for interacting with a remote site. `exec` is the escape hatch for non-WP shell commands.
|
|
42
52
|
|
|
43
53
|
```bash
|
|
44
|
-
#
|
|
54
|
+
# WP-CLI on a remote site
|
|
55
|
+
instawp wp <site> plugin list
|
|
56
|
+
instawp wp <site> option get siteurl
|
|
57
|
+
instawp wp <site> user list --api
|
|
58
|
+
|
|
59
|
+
# Pass raw args to WP-CLI with --
|
|
60
|
+
instawp wp <site> -- post list --post_type=page --format=json
|
|
61
|
+
|
|
62
|
+
# eval / PHP payloads — wrap in single quotes; args are shell-escaped for you
|
|
63
|
+
instawp wp <site> eval '\MyClass::init(["force" => true]);'
|
|
64
|
+
|
|
65
|
+
# Escape hatch for non-WP commands
|
|
45
66
|
instawp exec <site> ls -la
|
|
46
67
|
instawp exec <site> php -v
|
|
47
68
|
instawp exec <site> cat wp-config.php
|
|
48
69
|
|
|
49
|
-
#
|
|
50
|
-
instawp exec <site>
|
|
51
|
-
|
|
52
|
-
# WP-CLI shorthand (prepends `wp` automatically)
|
|
53
|
-
instawp wp <site> plugin list
|
|
54
|
-
instawp wp <site> option get siteurl
|
|
55
|
-
instawp wp <site> user list --api
|
|
70
|
+
# --api transport (no SSH setup required)
|
|
71
|
+
instawp exec <site> php -v --api
|
|
56
72
|
```
|
|
57
73
|
|
|
58
74
|
`<site>` can be a site **ID**, **name**, or **domain** — the CLI resolves it automatically.
|
|
@@ -79,6 +95,37 @@ instawp sync pull <site>
|
|
|
79
95
|
instawp sync push <site> --dry-run
|
|
80
96
|
```
|
|
81
97
|
|
|
98
|
+
### Database (mysqldump)
|
|
99
|
+
|
|
100
|
+
`db push` always backs up the remote database before overwriting (use `--no-backup` to skip).
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# Pull remote DB to a gzipped SQL dump
|
|
104
|
+
instawp db pull <site>
|
|
105
|
+
instawp db pull <site> --output ./backup.sql.gz
|
|
106
|
+
instawp db pull <site> --no-compress # write .sql instead of .sql.gz
|
|
107
|
+
|
|
108
|
+
# Push a local dump back (auto-backs up the remote first)
|
|
109
|
+
instawp db push <site> ./backup.sql.gz
|
|
110
|
+
instawp db push <site> ./backup.sql --force # skip confirmation
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Logs
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Tail the WP debug.log (default)
|
|
117
|
+
instawp logs <site>
|
|
118
|
+
instawp logs <site> --follow # tail -f
|
|
119
|
+
|
|
120
|
+
# Tail PHP-FPM or nginx error logs
|
|
121
|
+
instawp logs <site> --php
|
|
122
|
+
instawp logs <site> --nginx
|
|
123
|
+
instawp logs <site> --php --nginx -f # multi-tail
|
|
124
|
+
|
|
125
|
+
# Custom line count
|
|
126
|
+
instawp logs <site> --lines 500
|
|
127
|
+
```
|
|
128
|
+
|
|
82
129
|
### Teams
|
|
83
130
|
|
|
84
131
|
```bash
|
|
@@ -93,7 +140,8 @@ Add `--json` to any command for machine-readable output:
|
|
|
93
140
|
```bash
|
|
94
141
|
instawp sites list --json
|
|
95
142
|
instawp create --name test-site --json
|
|
96
|
-
instawp
|
|
143
|
+
instawp sites creds <site> --json
|
|
144
|
+
instawp wp <site> option get siteurl --json
|
|
97
145
|
```
|
|
98
146
|
|
|
99
147
|
## Environment Variables
|
package/bin/win32/msys-2.0.dll
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/bin/win32/rsync.exe
CHANGED
|
Binary file
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { join, dirname, basename } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { existsSync, mkdirSync, statSync, createReadStream, createWriteStream, unlinkSync } from 'node:fs';
|
|
5
|
+
import { createGunzip } from 'node:zlib';
|
|
6
|
+
import { pipeline } from 'node:stream/promises';
|
|
7
|
+
import { randomBytes } from 'node:crypto';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { requireAuth } from '../lib/api.js';
|
|
10
|
+
import { resolveSite } from '../lib/site-resolver.js';
|
|
11
|
+
import { ensureSshAccess } from '../lib/ssh-keys.js';
|
|
12
|
+
import { execViaSsh, execViaSshToFile } from '../lib/ssh-connection.js';
|
|
13
|
+
import { success, error, spinner, info, isJsonMode } from '../lib/output.js';
|
|
14
|
+
const KNOWN_HOSTS = join(homedir(), '.instawp', 'known_hosts');
|
|
15
|
+
/**
|
|
16
|
+
* Build scp args matching the ssh-connection.ts ssh args (key, known-hosts,
|
|
17
|
+
* StrictHostKeyChecking). Note `scp` uses uppercase `-P` for port.
|
|
18
|
+
*/
|
|
19
|
+
function scpArgs(conn) {
|
|
20
|
+
return [
|
|
21
|
+
'-i', conn.privateKeyPath,
|
|
22
|
+
'-P', String(conn.port),
|
|
23
|
+
'-o', 'StrictHostKeyChecking=accept-new',
|
|
24
|
+
'-o', `UserKnownHostsFile=${KNOWN_HOSTS}`,
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
function scpUpload(conn, localPath, remotePath) {
|
|
28
|
+
const target = `${conn.username}@${conn.host}:${remotePath}`;
|
|
29
|
+
const result = spawnSync('scp', [...scpArgs(conn), localPath, target], {
|
|
30
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
31
|
+
encoding: 'utf-8',
|
|
32
|
+
});
|
|
33
|
+
if ((result.status ?? 1) !== 0 && result.stderr) {
|
|
34
|
+
console.error(result.stderr);
|
|
35
|
+
}
|
|
36
|
+
return result.status ?? 1;
|
|
37
|
+
}
|
|
38
|
+
/** Timestamp like `2026-05-23T12-34-56` (filename-safe — `:` is illegal on Windows). */
|
|
39
|
+
function isoTimestamp() {
|
|
40
|
+
return new Date().toISOString().replace(/[:.]/g, '-').replace(/-\d{3}Z$/, '');
|
|
41
|
+
}
|
|
42
|
+
function sanitizeForFilename(s) {
|
|
43
|
+
return s.replace(/[^a-zA-Z0-9_.-]/g, '-');
|
|
44
|
+
}
|
|
45
|
+
function formatBytes(bytes) {
|
|
46
|
+
if (bytes < 1024)
|
|
47
|
+
return `${bytes} B`;
|
|
48
|
+
if (bytes < 1024 * 1024)
|
|
49
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
50
|
+
if (bytes < 1024 * 1024 * 1024)
|
|
51
|
+
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
52
|
+
return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
53
|
+
}
|
|
54
|
+
async function gunzipFile(src, dest) {
|
|
55
|
+
await pipeline(createReadStream(src), createGunzip(), createWriteStream(dest));
|
|
56
|
+
}
|
|
57
|
+
async function promptYesNo(question) {
|
|
58
|
+
const readline = await import('node:readline');
|
|
59
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
60
|
+
const answer = await new Promise((resolve) => {
|
|
61
|
+
rl.question(question, resolve);
|
|
62
|
+
});
|
|
63
|
+
rl.close();
|
|
64
|
+
return answer.trim().toLowerCase() === 'y' || answer.trim().toLowerCase() === 'yes';
|
|
65
|
+
}
|
|
66
|
+
export function registerDbCommand(program) {
|
|
67
|
+
const db = program
|
|
68
|
+
.command('db')
|
|
69
|
+
.description('Push/pull MySQL database dumps to/from a remote site');
|
|
70
|
+
// db pull <site>
|
|
71
|
+
db
|
|
72
|
+
.command('pull <site>')
|
|
73
|
+
.description('Pull remote MySQL database to a local SQL dump')
|
|
74
|
+
.option('--output <path>', 'Output file path (default: ./db-<site>-<timestamp>.sql.gz)')
|
|
75
|
+
.option('--no-compress', 'Write uncompressed .sql instead of .sql.gz')
|
|
76
|
+
.action(async (siteIdentifier, opts) => {
|
|
77
|
+
requireAuth();
|
|
78
|
+
const resolveSpin = spinner('Resolving site...');
|
|
79
|
+
resolveSpin.start();
|
|
80
|
+
let site;
|
|
81
|
+
try {
|
|
82
|
+
site = await resolveSite(siteIdentifier);
|
|
83
|
+
resolveSpin.succeed(`Site: ${site.name || site.sub_domain} (ID: ${site.id})`);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
resolveSpin.fail('Site resolution failed');
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
const conn = await ensureSshAccess(site.id);
|
|
90
|
+
const wpPath = `/home/${conn.username}/web/${conn.domain}/public_html`;
|
|
91
|
+
const compress = opts.compress !== false;
|
|
92
|
+
const siteLabel = sanitizeForFilename(site.name || site.sub_domain || `site-${site.id}`);
|
|
93
|
+
const ext = compress ? 'sql.gz' : 'sql';
|
|
94
|
+
const outputPath = opts.output || `./db-${siteLabel}-${isoTimestamp()}.${ext}`;
|
|
95
|
+
// Make sure the output directory exists
|
|
96
|
+
const outDir = dirname(outputPath);
|
|
97
|
+
if (outDir && outDir !== '.' && !existsSync(outDir)) {
|
|
98
|
+
mkdirSync(outDir, { recursive: true });
|
|
99
|
+
}
|
|
100
|
+
const dumpSpin = spinner(`Exporting database from ${conn.domain}...`);
|
|
101
|
+
dumpSpin.start();
|
|
102
|
+
// Stream `wp db export -` from remote. If --compress, pipe through gzip on
|
|
103
|
+
// the remote side so we never materialize the uncompressed dump locally.
|
|
104
|
+
const remoteCmd = compress
|
|
105
|
+
? `cd ${wpPath} && wp db export --single-transaction - | gzip`
|
|
106
|
+
: `cd ${wpPath} && wp db export --single-transaction -`;
|
|
107
|
+
try {
|
|
108
|
+
const { exitCode, stderr } = execViaSshToFile(conn, remoteCmd, outputPath);
|
|
109
|
+
if (exitCode !== 0) {
|
|
110
|
+
dumpSpin.fail('Database export failed');
|
|
111
|
+
if (stderr)
|
|
112
|
+
error(stderr.trim());
|
|
113
|
+
// Clean up empty/partial file
|
|
114
|
+
try {
|
|
115
|
+
if (existsSync(outputPath))
|
|
116
|
+
unlinkSync(outputPath);
|
|
117
|
+
}
|
|
118
|
+
catch { /* ignore */ }
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
const sizeBytes = statSync(outputPath).size;
|
|
122
|
+
if (sizeBytes === 0) {
|
|
123
|
+
dumpSpin.fail('Database export produced an empty file');
|
|
124
|
+
try {
|
|
125
|
+
unlinkSync(outputPath);
|
|
126
|
+
}
|
|
127
|
+
catch { /* ignore */ }
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
dumpSpin.succeed(`Database exported (${formatBytes(sizeBytes)})`);
|
|
131
|
+
success('Pull complete', {
|
|
132
|
+
file: outputPath,
|
|
133
|
+
size_bytes: sizeBytes,
|
|
134
|
+
site_id: site.id,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
dumpSpin.fail('Database export failed');
|
|
139
|
+
error(err.message || String(err));
|
|
140
|
+
try {
|
|
141
|
+
if (existsSync(outputPath))
|
|
142
|
+
unlinkSync(outputPath);
|
|
143
|
+
}
|
|
144
|
+
catch { /* ignore */ }
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
// db push <site> <file>
|
|
149
|
+
db
|
|
150
|
+
.command('push <site> <file>')
|
|
151
|
+
.description('Push local SQL dump to remote site database (creates a backup first)')
|
|
152
|
+
.option('--force', 'Skip confirmation prompt')
|
|
153
|
+
.option('--no-backup', 'Skip taking a remote backup before overwrite (DANGEROUS)')
|
|
154
|
+
.addHelpText('after', `
|
|
155
|
+
Notes:
|
|
156
|
+
- Always takes a remote backup first unless --no-backup is passed.
|
|
157
|
+
- After pushing to a site on a different domain, you may want to run:
|
|
158
|
+
instawp wp <site> search-replace <old-url> <new-url>
|
|
159
|
+
Auto-replacing site URLs is out of scope for this command.
|
|
160
|
+
`)
|
|
161
|
+
.action(async (siteIdentifier, file, opts) => {
|
|
162
|
+
requireAuth();
|
|
163
|
+
// Validate input file
|
|
164
|
+
if (!existsSync(file)) {
|
|
165
|
+
error(`File not found: ${file}`);
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
const localSize = statSync(file).size;
|
|
169
|
+
if (localSize === 0) {
|
|
170
|
+
error(`File is empty: ${file}`);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
// In JSON mode, can't prompt — require --force
|
|
174
|
+
if (isJsonMode() && !opts.force) {
|
|
175
|
+
error('--force is required when using --json (cannot prompt for confirmation)');
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
const resolveSpin = spinner('Resolving site...');
|
|
179
|
+
resolveSpin.start();
|
|
180
|
+
let site;
|
|
181
|
+
try {
|
|
182
|
+
site = await resolveSite(siteIdentifier);
|
|
183
|
+
resolveSpin.succeed(`Site: ${site.name || site.sub_domain} (ID: ${site.id})`);
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
resolveSpin.fail('Site resolution failed');
|
|
187
|
+
process.exit(1);
|
|
188
|
+
}
|
|
189
|
+
const conn = await ensureSshAccess(site.id);
|
|
190
|
+
const wpPath = `/home/${conn.username}/web/${conn.domain}/public_html`;
|
|
191
|
+
const remoteHome = `/home/${conn.username}`;
|
|
192
|
+
const timestamp = isoTimestamp();
|
|
193
|
+
const backupFilename = `db-backup-${timestamp}.sql.gz`;
|
|
194
|
+
const backupRemotePath = `${remoteHome}/${backupFilename}`;
|
|
195
|
+
const takeBackup = opts.backup !== false;
|
|
196
|
+
// Confirmation
|
|
197
|
+
if (!opts.force) {
|
|
198
|
+
const backupLine = takeBackup
|
|
199
|
+
? `A backup will be saved to ~/${backupFilename} on the remote.`
|
|
200
|
+
: chalk.red('NO BACKUP will be taken (--no-backup). This is irreversible.');
|
|
201
|
+
console.log(`\nThis will ${chalk.bold.red('OVERWRITE')} the database on ${chalk.bold(conn.domain)}.`);
|
|
202
|
+
console.log(backupLine);
|
|
203
|
+
const ok = await promptYesNo('Continue? (y/N) ');
|
|
204
|
+
if (!ok) {
|
|
205
|
+
info('Cancelled.');
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// Step 1: Backup
|
|
210
|
+
if (takeBackup) {
|
|
211
|
+
const backupSpin = spinner(`Backing up remote database to ~/${backupFilename}...`);
|
|
212
|
+
backupSpin.start();
|
|
213
|
+
const backupCmd = `cd ${wpPath} && wp db export --single-transaction - | gzip > ${backupRemotePath}`;
|
|
214
|
+
const backupResult = execViaSsh(conn, backupCmd);
|
|
215
|
+
if (backupResult.exitCode !== 0) {
|
|
216
|
+
backupSpin.fail('Backup failed — aborting push');
|
|
217
|
+
if (backupResult.stderr)
|
|
218
|
+
error(backupResult.stderr.trim());
|
|
219
|
+
process.exit(1);
|
|
220
|
+
}
|
|
221
|
+
backupSpin.succeed(`Backup saved: ~/${backupFilename}`);
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
info('Skipping backup (--no-backup)');
|
|
225
|
+
}
|
|
226
|
+
// Step 2: Prepare local SQL (gunzip if needed)
|
|
227
|
+
const isGzipped = file.endsWith('.gz') || file.endsWith('.gzip');
|
|
228
|
+
let uploadSource = file;
|
|
229
|
+
let tempLocalDecompressed = null;
|
|
230
|
+
if (isGzipped) {
|
|
231
|
+
const decompressSpin = spinner('Decompressing local dump...');
|
|
232
|
+
decompressSpin.start();
|
|
233
|
+
try {
|
|
234
|
+
const tmpName = `instawp-db-push-${randomBytes(6).toString('hex')}.sql`;
|
|
235
|
+
tempLocalDecompressed = join(process.env.TMPDIR || '/tmp', tmpName);
|
|
236
|
+
await gunzipFile(file, tempLocalDecompressed);
|
|
237
|
+
uploadSource = tempLocalDecompressed;
|
|
238
|
+
const decompressedSize = statSync(uploadSource).size;
|
|
239
|
+
decompressSpin.succeed(`Decompressed (${formatBytes(decompressedSize)})`);
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
decompressSpin.fail('Decompression failed');
|
|
243
|
+
error(err.message || String(err));
|
|
244
|
+
if (tempLocalDecompressed) {
|
|
245
|
+
try {
|
|
246
|
+
unlinkSync(tempLocalDecompressed);
|
|
247
|
+
}
|
|
248
|
+
catch { /* ignore */ }
|
|
249
|
+
}
|
|
250
|
+
if (takeBackup) {
|
|
251
|
+
info(`Remote backup preserved: ~/${backupFilename}`);
|
|
252
|
+
}
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// Step 3: Upload via scp to /tmp on remote
|
|
257
|
+
const remoteTempName = `db-import-${randomBytes(6).toString('hex')}.sql`;
|
|
258
|
+
const remoteTempPath = `/tmp/${remoteTempName}`;
|
|
259
|
+
const uploadSpin = spinner(`Uploading ${basename(uploadSource)} to remote...`);
|
|
260
|
+
uploadSpin.start();
|
|
261
|
+
const scpExit = scpUpload(conn, uploadSource, remoteTempPath);
|
|
262
|
+
if (scpExit !== 0) {
|
|
263
|
+
uploadSpin.fail(`Upload failed (scp exit ${scpExit})`);
|
|
264
|
+
if (tempLocalDecompressed) {
|
|
265
|
+
try {
|
|
266
|
+
unlinkSync(tempLocalDecompressed);
|
|
267
|
+
}
|
|
268
|
+
catch { /* ignore */ }
|
|
269
|
+
}
|
|
270
|
+
if (takeBackup) {
|
|
271
|
+
info(`Remote backup preserved: ~/${backupFilename}`);
|
|
272
|
+
}
|
|
273
|
+
process.exit(1);
|
|
274
|
+
}
|
|
275
|
+
uploadSpin.succeed('Upload complete');
|
|
276
|
+
// Clean up local temp file (we have it on remote now)
|
|
277
|
+
if (tempLocalDecompressed) {
|
|
278
|
+
try {
|
|
279
|
+
unlinkSync(tempLocalDecompressed);
|
|
280
|
+
}
|
|
281
|
+
catch { /* ignore */ }
|
|
282
|
+
}
|
|
283
|
+
// Step 4: Import on remote
|
|
284
|
+
const importSpin = spinner(`Importing database on ${conn.domain}...`);
|
|
285
|
+
importSpin.start();
|
|
286
|
+
const importResult = execViaSsh(conn, `cd ${wpPath} && wp db import ${remoteTempPath}`);
|
|
287
|
+
if (importResult.exitCode !== 0) {
|
|
288
|
+
importSpin.fail('Import failed');
|
|
289
|
+
if (importResult.stderr)
|
|
290
|
+
error(importResult.stderr.trim());
|
|
291
|
+
else if (importResult.stdout)
|
|
292
|
+
error(importResult.stdout.trim());
|
|
293
|
+
// Clean up temp file on remote even on failure (best effort)
|
|
294
|
+
execViaSsh(conn, `rm -f ${remoteTempPath}`);
|
|
295
|
+
if (takeBackup) {
|
|
296
|
+
console.log('');
|
|
297
|
+
info(`Remote backup preserved at: ~/${backupFilename}`);
|
|
298
|
+
info('To restore:');
|
|
299
|
+
console.log(` ssh ${conn.username}@${conn.host} 'cd ${wpPath} && gunzip -c ${backupRemotePath} | wp db import -'`);
|
|
300
|
+
console.log(` ${chalk.dim('# or pull the backup down and re-push:')}`);
|
|
301
|
+
console.log(` scp ${conn.username}@${conn.host}:${backupRemotePath} ./`);
|
|
302
|
+
console.log(` instawp db push ${siteIdentifier} ./${backupFilename}`);
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
error('No backup was taken — database state may be inconsistent.');
|
|
306
|
+
}
|
|
307
|
+
process.exit(1);
|
|
308
|
+
}
|
|
309
|
+
importSpin.succeed('Database imported');
|
|
310
|
+
// Step 5: Cleanup remote temp file
|
|
311
|
+
const cleanupSpin = spinner('Cleaning up...');
|
|
312
|
+
cleanupSpin.start();
|
|
313
|
+
const cleanupResult = execViaSsh(conn, `rm -f ${remoteTempPath}`);
|
|
314
|
+
if (cleanupResult.exitCode !== 0) {
|
|
315
|
+
cleanupSpin.fail(`Could not remove ${remoteTempPath} (non-fatal)`);
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
cleanupSpin.succeed('Cleanup complete');
|
|
319
|
+
}
|
|
320
|
+
success('Push complete', {
|
|
321
|
+
site_id: site.id,
|
|
322
|
+
backup_path: takeBackup ? backupRemotePath : null,
|
|
323
|
+
restored_from: file,
|
|
324
|
+
size_bytes: localSize,
|
|
325
|
+
});
|
|
326
|
+
if (!isJsonMode() && takeBackup) {
|
|
327
|
+
console.log(`\n ${chalk.dim('Backup:')} ~/${backupFilename} ${chalk.dim('(on remote)')}`);
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/commands/db.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC3G,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG7E,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;AAE/D;;;GAGG;AACH,SAAS,OAAO,CAAC,IAAmB;IAClC,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,cAAc;QACzB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;QACvB,IAAI,EAAE,kCAAkC;QACxC,IAAI,EAAE,sBAAsB,WAAW,EAAE;KAC1C,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,IAAmB,EAAE,SAAiB,EAAE,UAAkB;IAC3E,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,IAAI,UAAU,EAAE,CAAC;IAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE;QACrE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;QACjC,QAAQ,EAAE,OAAO;KAClB,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAChD,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,wFAAwF;AACxF,SAAS,YAAY;IACnB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,mBAAmB,CAAC,CAAS;IACpC,OAAO,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,IAAI,CAAC;IACtC,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAClE,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAChF,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AACzD,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,IAAY;IACjD,MAAM,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,YAAY,EAAE,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;AACjF,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,QAAgB;IACzC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;IAC/C,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtF,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;QACnD,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,MAAM,EAAE,GAAG,OAAO;SACf,OAAO,CAAC,IAAI,CAAC;SACb,WAAW,CAAC,sDAAsD,CAAC,CAAC;IAEvE,iBAAiB;IACjB,EAAE;SACC,OAAO,CAAC,aAAa,CAAC;SACtB,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CAAC,iBAAiB,EAAE,4DAA4D,CAAC;SACvF,MAAM,CAAC,eAAe,EAAE,4CAA4C,CAAC;SACrE,MAAM,CAAC,KAAK,EAAE,cAAsB,EAAE,IAAS,EAAE,EAAE;QAClD,WAAW,EAAE,CAAC;QAEd,MAAM,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;QACjD,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,IAAI,CAAC;QACT,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,WAAW,CAAC,cAAc,CAAC,CAAC;YACzC,WAAW,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,SAAS,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;QAChF,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;YAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,SAAS,IAAI,CAAC,QAAQ,QAAQ,IAAI,CAAC,MAAM,cAAc,CAAC;QAEvE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC;QACzC,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,IAAI,QAAQ,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACzF,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;QACxC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,IAAI,QAAQ,SAAS,IAAI,YAAY,EAAE,IAAI,GAAG,EAAE,CAAC;QAE/E,wCAAwC;QACxC,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QACnC,IAAI,MAAM,IAAI,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACpD,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,QAAQ,GAAG,OAAO,CAAC,2BAA2B,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC;QACtE,QAAQ,CAAC,KAAK,EAAE,CAAC;QAEjB,2EAA2E;QAC3E,yEAAyE;QACzE,MAAM,SAAS,GAAG,QAAQ;YACxB,CAAC,CAAC,MAAM,MAAM,gDAAgD;YAC9D,CAAC,CAAC,MAAM,MAAM,yCAAyC,CAAC;QAE1D,IAAI,CAAC;YACH,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YAC3E,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;gBACnB,QAAQ,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;gBACxC,IAAI,MAAM;oBAAE,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBACjC,8BAA8B;gBAC9B,IAAI,CAAC;oBAAC,IAAI,UAAU,CAAC,UAAU,CAAC;wBAAE,UAAU,CAAC,UAAU,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;gBAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,SAAS,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;YAC5C,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;gBACpB,QAAQ,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;gBACxD,IAAI,CAAC;oBAAC,UAAU,CAAC,UAAU,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;gBACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,QAAQ,CAAC,OAAO,CAAC,sBAAsB,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAElE,OAAO,CAAC,eAAe,EAAE;gBACvB,IAAI,EAAE,UAAU;gBAChB,UAAU,EAAE,SAAS;gBACrB,OAAO,EAAE,IAAI,CAAC,EAAE;aACjB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;YACxC,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAClC,IAAI,CAAC;gBAAC,IAAI,UAAU,CAAC,UAAU,CAAC;oBAAE,UAAU,CAAC,UAAU,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,wBAAwB;IACxB,EAAE;SACC,OAAO,CAAC,oBAAoB,CAAC;SAC7B,WAAW,CAAC,sEAAsE,CAAC;SACnF,MAAM,CAAC,SAAS,EAAE,0BAA0B,CAAC;SAC7C,MAAM,CAAC,aAAa,EAAE,0DAA0D,CAAC;SACjF,WAAW,CAAC,OAAO,EAAE;;;;;;CAMzB,CAAC;SACG,MAAM,CAAC,KAAK,EAAE,cAAsB,EAAE,IAAY,EAAE,IAAS,EAAE,EAAE;QAChE,WAAW,EAAE,CAAC;QAEd,sBAAsB;QACtB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;QACtC,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;YACpB,KAAK,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,+CAA+C;QAC/C,IAAI,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChC,KAAK,CAAC,wEAAwE,CAAC,CAAC;YAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;QACjD,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,IAAI,CAAC;QACT,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,WAAW,CAAC,cAAc,CAAC,CAAC;YACzC,WAAW,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,SAAS,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;QAChF,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;YAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,SAAS,IAAI,CAAC,QAAQ,QAAQ,IAAI,CAAC,MAAM,cAAc,CAAC;QACvE,MAAM,UAAU,GAAG,SAAS,IAAI,CAAC,QAAQ,EAAE,CAAC;QAE5C,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;QACjC,MAAM,cAAc,GAAG,aAAa,SAAS,SAAS,CAAC;QACvD,MAAM,gBAAgB,GAAG,GAAG,UAAU,IAAI,cAAc,EAAE,CAAC;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC;QAEzC,eAAe;QACf,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,UAAU,GAAG,UAAU;gBAC3B,CAAC,CAAC,+BAA+B,cAAc,iBAAiB;gBAChE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;YAC9E,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,oBAAoB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACtG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACxB,MAAM,EAAE,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC,CAAC;YACjD,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,IAAI,CAAC,YAAY,CAAC,CAAC;gBACnB,OAAO;YACT,CAAC;QACH,CAAC;QAED,iBAAiB;QACjB,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,UAAU,GAAG,OAAO,CAAC,mCAAmC,cAAc,KAAK,CAAC,CAAC;YACnF,UAAU,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,SAAS,GAAG,MAAM,MAAM,oDAAoD,gBAAgB,EAAE,CAAC;YACrG,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACjD,IAAI,YAAY,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAChC,UAAU,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;gBACjD,IAAI,YAAY,CAAC,MAAM;oBAAE,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,UAAU,CAAC,OAAO,CAAC,mBAAmB,cAAc,EAAE,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,+BAA+B,CAAC,CAAC;QACxC,CAAC;QAED,+CAA+C;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjE,IAAI,YAAY,GAAG,IAAI,CAAC;QACxB,IAAI,qBAAqB,GAAkB,IAAI,CAAC;QAEhD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,cAAc,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAAC;YAC9D,cAAc,CAAC,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,mBAAmB,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;gBACxE,qBAAqB,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,MAAM,EAAE,OAAO,CAAC,CAAC;gBACpE,MAAM,UAAU,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;gBAC9C,YAAY,GAAG,qBAAqB,CAAC;gBACrC,MAAM,gBAAgB,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC;gBACrD,cAAc,CAAC,OAAO,CAAC,iBAAiB,WAAW,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAC5E,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,cAAc,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;gBAC5C,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAClC,IAAI,qBAAqB,EAAE,CAAC;oBAC1B,IAAI,CAAC;wBAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC;oBAAC,CAAC;oBAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;gBACnE,CAAC;gBACD,IAAI,UAAU,EAAE,CAAC;oBACf,IAAI,CAAC,8BAA8B,cAAc,EAAE,CAAC,CAAC;gBACvD,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAED,2CAA2C;QAC3C,MAAM,cAAc,GAAG,aAAa,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;QACzE,MAAM,cAAc,GAAG,QAAQ,cAAc,EAAE,CAAC;QAEhD,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,QAAQ,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;QAC/E,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;QAC9D,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;YAClB,UAAU,CAAC,IAAI,CAAC,2BAA2B,OAAO,GAAG,CAAC,CAAC;YACvD,IAAI,qBAAqB,EAAE,CAAC;gBAC1B,IAAI,CAAC;oBAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YACnE,CAAC;YACD,IAAI,UAAU,EAAE,CAAC;gBACf,IAAI,CAAC,8BAA8B,cAAc,EAAE,CAAC,CAAC;YACvD,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAEtC,sDAAsD;QACtD,IAAI,qBAAqB,EAAE,CAAC;YAC1B,IAAI,CAAC;gBAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QACnE,CAAC;QAED,2BAA2B;QAC3B,MAAM,UAAU,GAAG,OAAO,CAAC,yBAAyB,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC;QACtE,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,YAAY,GAAG,UAAU,CAC7B,IAAI,EACJ,MAAM,MAAM,oBAAoB,cAAc,EAAE,CACjD,CAAC;QAEF,IAAI,YAAY,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAChC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACjC,IAAI,YAAY,CAAC,MAAM;gBAAE,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;iBACtD,IAAI,YAAY,CAAC,MAAM;gBAAE,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAEhE,6DAA6D;YAC7D,UAAU,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,CAAC,CAAC;YAE5C,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAChB,IAAI,CAAC,iCAAiC,cAAc,EAAE,CAAC,CAAC;gBACxD,IAAI,CAAC,aAAa,CAAC,CAAC;gBACpB,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,QAAQ,MAAM,iBAAiB,gBAAgB,oBAAoB,CAAC,CAAC;gBACpH,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,wCAAwC,CAAC,EAAE,CAAC,CAAC;gBACxE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,IAAI,gBAAgB,KAAK,CAAC,CAAC;gBAC1E,OAAO,CAAC,GAAG,CAAC,qBAAqB,cAAc,MAAM,cAAc,EAAE,CAAC,CAAC;YACzE,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,2DAA2D,CAAC,CAAC;YACrE,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAExC,mCAAmC;QACnC,MAAM,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC9C,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,CAAC,CAAC;QAClE,IAAI,aAAa,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YACjC,WAAW,CAAC,IAAI,CAAC,oBAAoB,cAAc,cAAc,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,CAAC,eAAe,EAAE;YACvB,OAAO,EAAE,IAAI,CAAC,EAAE;YAChB,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI;YACjD,aAAa,EAAE,IAAI;YACnB,UAAU,EAAE,SAAS;SACtB,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,EAAE,IAAI,UAAU,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,cAAc,IAAI,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/commands/exec.js
CHANGED
|
@@ -3,8 +3,26 @@ import { resolveSite } from '../lib/site-resolver.js';
|
|
|
3
3
|
import { ensureSshAccess } from '../lib/ssh-keys.js';
|
|
4
4
|
import { execViaSsh } from '../lib/ssh-connection.js';
|
|
5
5
|
import { error, spinner, isJsonMode } from '../lib/output.js';
|
|
6
|
+
// POSIX shell single-quote escape: 'safe' becomes 'safe' (passthrough for
|
|
7
|
+
// shell-safe chars), anything else wrapped in '...' with embedded ' → '\''.
|
|
8
|
+
// Required because the remote shell receives joined args via stdin and would
|
|
9
|
+
// otherwise interpret parens, quotes, semicolons, etc. (broke `wp eval '...'`).
|
|
10
|
+
function shellQuote(arg) {
|
|
11
|
+
if (arg === '')
|
|
12
|
+
return "''";
|
|
13
|
+
if (/^[a-zA-Z0-9_\-./=:@%+,]+$/.test(arg))
|
|
14
|
+
return arg;
|
|
15
|
+
return "'" + arg.replace(/'/g, "'\\''") + "'";
|
|
16
|
+
}
|
|
17
|
+
function joinForRemote(args) {
|
|
18
|
+
return args.map(shellQuote).join(' ');
|
|
19
|
+
}
|
|
6
20
|
async function execAction(siteIdentifier, args, opts) {
|
|
7
21
|
requireAuth();
|
|
22
|
+
// Drop POSIX `--` end-of-options marker so users can write
|
|
23
|
+
// instawp wp <site> -- post list --post_type=page
|
|
24
|
+
// and have everything after `--` reach WP-CLI verbatim.
|
|
25
|
+
args = args.filter(a => a !== '--');
|
|
8
26
|
if (args.length === 0) {
|
|
9
27
|
error('No command specified. Usage: instawp exec <site> <command...>');
|
|
10
28
|
process.exit(1);
|
|
@@ -20,7 +38,7 @@ async function execAction(siteIdentifier, args, opts) {
|
|
|
20
38
|
spin.fail('Site resolution failed');
|
|
21
39
|
process.exit(1);
|
|
22
40
|
}
|
|
23
|
-
const command = args
|
|
41
|
+
const command = joinForRemote(args);
|
|
24
42
|
if (opts.api) {
|
|
25
43
|
await execViaApi(site, command, opts);
|
|
26
44
|
}
|
|
@@ -102,11 +120,17 @@ async function execViaSshTransport(site, command) {
|
|
|
102
120
|
export function registerExecCommand(program) {
|
|
103
121
|
program
|
|
104
122
|
.command('exec <site> [args...]')
|
|
105
|
-
.description('
|
|
123
|
+
.description('Escape hatch: run arbitrary shell on a remote site (SSH default, or --api). For WP-CLI use `wp` instead.')
|
|
106
124
|
.passThroughOptions()
|
|
107
125
|
.allowUnknownOption()
|
|
108
126
|
.option('--api', 'Use API transport instead of SSH')
|
|
109
127
|
.option('--timeout <seconds>', 'Command timeout in seconds (API mode only)', '30')
|
|
128
|
+
.addHelpText('after', `
|
|
129
|
+
Examples:
|
|
130
|
+
$ instawp exec my-site ls -la
|
|
131
|
+
$ instawp exec my-site -- ps aux | grep php # use -- to forward raw args
|
|
132
|
+
$ instawp exec my-site php -v --api
|
|
133
|
+
`)
|
|
110
134
|
.action(async (siteIdentifier, args, opts) => {
|
|
111
135
|
// passThroughOptions may swallow --api/--timeout into args — extract them
|
|
112
136
|
const extractedApi = args.includes('--api');
|
|
@@ -127,11 +151,20 @@ export function registerExecCommand(program) {
|
|
|
127
151
|
export function registerWpCommand(program) {
|
|
128
152
|
program
|
|
129
153
|
.command('wp <site> [args...]')
|
|
130
|
-
.description('Run WP-CLI
|
|
154
|
+
.description('Run WP-CLI on a remote site (the primary remote-access command)')
|
|
131
155
|
.passThroughOptions()
|
|
132
156
|
.allowUnknownOption()
|
|
133
157
|
.option('--api', 'Use API transport instead of SSH')
|
|
134
158
|
.option('--timeout <seconds>', 'Command timeout in seconds (API mode only)', '30')
|
|
159
|
+
.addHelpText('after', `
|
|
160
|
+
Examples:
|
|
161
|
+
$ instawp wp my-site plugin list
|
|
162
|
+
$ instawp wp my-site theme activate twentytwentyfour
|
|
163
|
+
$ instawp wp my-site -- post list --post_type=page # use -- to pass raw WP-CLI args
|
|
164
|
+
$ instawp wp my-site eval '\\\\MyClass::init(["force" => true]);'
|
|
165
|
+
|
|
166
|
+
Tip: wrap PHP/eval payloads in single quotes — args are shell-escaped automatically before being sent to the remote shell.
|
|
167
|
+
`)
|
|
135
168
|
.action(async (siteIdentifier, args, opts) => {
|
|
136
169
|
// passThroughOptions may swallow --api/--timeout into args — extract them
|
|
137
170
|
const extractedApi = args.includes('--api');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/commands/exec.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9D,KAAK,UAAU,UAAU,CAAC,cAAsB,EAAE,IAAc,EAAE,IAAyC;IACzG,WAAW,EAAE,CAAC;IAEd,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;IAEb,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,WAAW,CAAC,cAAc,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/commands/exec.ts"],"names":[],"mappings":"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"}
|