@bootmap/wpep-cli 1.1.1 → 1.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bootmap/wpep-cli",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "CLI tool for deploying Next.js static exports to WordPress via WP Elementor Publisher",
5
5
  "main": "bin/wpep.js",
6
6
  "type": "module",
@@ -20,8 +20,10 @@
20
20
  "author": "",
21
21
  "license": "ISC",
22
22
  "dependencies": {
23
+ "archiver": "^8.0.0",
23
24
  "chalk": "^5.3.0",
24
25
  "commander": "^11.1.0",
26
+ "form-data": "^4.0.6",
25
27
  "inquirer": "^9.2.12",
26
28
  "ora": "^7.0.1"
27
29
  }
@@ -5,6 +5,7 @@ import chalk from 'chalk';
5
5
  import ora from 'ora';
6
6
  import { execSync } from 'child_process';
7
7
  import inquirer from 'inquirer';
8
+ import archiver from 'archiver';
8
9
 
9
10
  function getFiles(dir, files = []) {
10
11
  if (!fs.existsSync(dir)) return files;
@@ -25,15 +26,18 @@ export default async function deployCommand(options) {
25
26
  let key = options.key;
26
27
 
27
28
  if (!url || !key) {
28
- const rcPath = path.join(process.cwd(), '.wpeprc.json');
29
- if (fs.existsSync(rcPath)) {
29
+ const rcPath = path.join(process.cwd(), '.wpep.config.json');
30
+ const oldRcPath = path.join(process.cwd(), '.wpeprc.json');
31
+ let configPath = fs.existsSync(rcPath) ? rcPath : (fs.existsSync(oldRcPath) ? oldRcPath : null);
32
+
33
+ if (configPath) {
30
34
  try {
31
- const config = JSON.parse(fs.readFileSync(rcPath, 'utf8'));
35
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
32
36
  url = url || config.url;
33
37
  key = key || config.key;
34
38
  options.dir = options.dir || config.dir;
35
39
  } catch (e) {
36
- throw new Error('Could not read .wpeprc.json. Run "wpep init" first.');
40
+ throw new Error('Could not read config file. Run "wpep init" first.');
37
41
  }
38
42
  }
39
43
  }
@@ -76,6 +80,15 @@ export default async function deployCommand(options) {
76
80
  );
77
81
  fs.writeFileSync(nextConfigPath, patched, 'utf8');
78
82
  }
83
+
84
+ // Check for next/image unoptimized
85
+ const hasNextImage = getFiles(process.cwd()).some(f => f.endsWith('.js') || f.endsWith('.tsx') || f.endsWith('.jsx'));
86
+ // A quick heuristic: if they have next.config.js but didn't set images: { unoptimized: true }
87
+ if (!originalContent.includes('unoptimized') && !originalContent.includes('unoptimized: true')) {
88
+ console.log(chalk.red.bold('\n⚠️ STATIC EXPORT WARNING'));
89
+ console.log(chalk.yellow('If you use next/image (<Image />), static exports will fail unless you configure unoptimized: true.'));
90
+ console.log(chalk.yellow('Add this to your next.config.js:\n images: { unoptimized: true }\n'));
91
+ }
79
92
  }
80
93
 
81
94
  if (options.build !== false) {
@@ -183,32 +196,57 @@ export default async function deployCommand(options) {
183
196
  if (skippedCount > 0) {
184
197
  console.log(chalk.green(`\n⚡ ${skippedCount} unchanged files will be copied server-side (not re-uploaded).`));
185
198
  }
186
- console.log(chalk.gray(`Uploading ${changedFiles.length} changed files...\n`));
199
+ console.log(chalk.gray(`Preparing ZIP archive for ${changedFiles.length} changed files...\n`));
200
+
201
+ const zipPath = path.join(process.cwd(), 'wpep-deploy.zip');
202
+ const outputZip = fs.createWriteStream(zipPath);
203
+ const archive = archiver('zip', { zlib: { level: 9 } });
204
+
205
+ const zipPromise = new Promise((resolve, reject) => {
206
+ outputZip.on('close', resolve);
207
+ archive.on('error', reject);
208
+ });
209
+
210
+ archive.pipe(outputZip);
187
211
 
188
- let uploaded = 0;
189
212
  for (const file of changedFiles) {
190
213
  const relativePath = path.relative(outDir, file);
191
- const data = fs.readFileSync(file);
192
- const base64Data = data.toString('base64');
193
- const hash = filesList[relativePath];
214
+ archive.file(file, { name: relativePath });
215
+ }
194
216
 
195
- const uploadSpinner = ora(`Uploading ${relativePath}...`).start();
217
+ await archive.finalize();
218
+ await zipPromise;
196
219
 
197
- try {
198
- const uploadRes = await fetch(`${url}/wp-json/wpep/v1/deployments/${deployId}/upload`, {
199
- method: 'POST',
200
- headers: { 'Content-Type': 'application/json', 'x-wpep-api-key': key },
201
- body: JSON.stringify({ path: relativePath, data: base64Data, hash })
202
- });
203
- if (!uploadRes.ok) {
204
- throw new Error(`Failed to upload ${relativePath}: ${uploadRes.statusText}`);
205
- }
206
- uploadSpinner.succeed(`Uploaded ${relativePath}`);
207
- uploaded++;
208
- } catch (e) {
209
- uploadSpinner.fail(`Failed to upload ${relativePath}`);
210
- throw e;
220
+ const uploadSpinner = ora('Uploading archive to WordPress...').start();
221
+ try {
222
+ const fileBuffer = fs.readFileSync(zipPath);
223
+ const blob = new Blob([fileBuffer], { type: 'application/zip' });
224
+
225
+ // We must use the native FormData (available in Node 18+)
226
+ const formData = new globalThis.FormData();
227
+ formData.append('archive', blob, 'wpep-deploy.zip');
228
+
229
+ const uploadRes = await fetch(`${url}/wp-json/wpep/v1/deployments/${deployId}/upload-archive`, {
230
+ method: 'POST',
231
+ headers: {
232
+ 'x-wpep-api-key': key
233
+ },
234
+ body: formData
235
+ });
236
+
237
+ if (!uploadRes.ok) {
238
+ const errorText = await uploadRes.text();
239
+ throw new Error(`Failed to upload archive: ${uploadRes.statusText} - ${errorText}`);
211
240
  }
241
+ uploadSpinner.succeed('Archive uploaded and extracted successfully.');
242
+
243
+ // Clean up zip
244
+ if (fs.existsSync(zipPath)) {
245
+ fs.unlinkSync(zipPath);
246
+ }
247
+ } catch (e) {
248
+ uploadSpinner.fail('Failed to upload archive.');
249
+ throw e;
212
250
  }
213
251
 
214
252
  const activateSpinner = ora('Activating deployment...').start();
@@ -6,7 +6,7 @@ import path from 'path';
6
6
  export default async function initCommand() {
7
7
  console.log(chalk.blue.bold('\nWelcome to WP Elementor Publisher (WPEP) CLI\n'));
8
8
 
9
- const rcPath = path.join(process.cwd(), '.wpeprc.json');
9
+ const rcPath = path.join(process.cwd(), '.wpep.config.json');
10
10
 
11
11
  let existingConfig = {};
12
12
  if (fs.existsSync(rcPath)) {
@@ -67,6 +67,6 @@ export default async function initCommand() {
67
67
 
68
68
  fs.writeFileSync(rcPath, JSON.stringify(config, null, 2));
69
69
 
70
- console.log(chalk.green(`\nSuccess! Saved configuration to ${chalk.bold('.wpeprc.json')}`));
70
+ console.log(chalk.green(`\n✅ Successfully initialized WPEP configuration in .wpep.config.json`));
71
71
  console.log(`You can now run ${chalk.cyan('wpep deploy')} to deploy your site.\n`);
72
72
  }