@loopress/cli 0.12.0 → 0.14.0

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.
Files changed (49) hide show
  1. package/README.md +88 -29
  2. package/dist/commands/init.js +5 -5
  3. package/dist/commands/login.d.ts +0 -1
  4. package/dist/commands/login.js +21 -90
  5. package/dist/commands/plugin/add.d.ts +0 -2
  6. package/dist/commands/plugin/add.js +6 -47
  7. package/dist/commands/plugin/pull.js +4 -6
  8. package/dist/commands/plugin/push.d.ts +1 -2
  9. package/dist/commands/plugin/push.js +18 -50
  10. package/dist/commands/project/config.d.ts +2 -0
  11. package/dist/commands/project/config.js +45 -11
  12. package/dist/commands/snippet/publish.d.ts +10 -0
  13. package/dist/commands/snippet/publish.js +74 -0
  14. package/dist/commands/snippet/push.js +5 -70
  15. package/dist/commands/status.js +6 -2
  16. package/dist/commands/telemetry/disable.d.ts +6 -0
  17. package/dist/commands/telemetry/disable.js +14 -0
  18. package/dist/commands/telemetry/enable.d.ts +6 -0
  19. package/dist/commands/telemetry/enable.js +14 -0
  20. package/dist/config/auth.manager.d.ts +4 -2
  21. package/dist/config/auth.manager.js +15 -5
  22. package/dist/config/project-config.manager.d.ts +7 -2
  23. package/dist/config/project-config.manager.js +35 -6
  24. package/dist/hooks/finally.js +11 -2
  25. package/dist/hooks/init.js +8 -16
  26. package/dist/lib/load-snippets.d.ts +2 -0
  27. package/dist/lib/load-snippets.js +84 -0
  28. package/dist/lib/local-callback-server.d.ts +25 -0
  29. package/dist/lib/local-callback-server.js +103 -0
  30. package/dist/lib/open-browser.d.ts +2 -0
  31. package/dist/lib/open-browser.js +5 -0
  32. package/dist/lib/sentry.d.ts +0 -1
  33. package/dist/lib/sentry.js +6 -8
  34. package/dist/lib/wp-authorize-flow.d.ts +22 -0
  35. package/dist/lib/wp-authorize-flow.js +60 -0
  36. package/dist/lib/wp-client.d.ts +1 -1
  37. package/dist/lib/wp-client.js +1 -1
  38. package/dist/lib/wp-site-diagnostic.d.ts +13 -0
  39. package/dist/lib/wp-site-diagnostic.js +46 -0
  40. package/dist/types/config.d.ts +1 -1
  41. package/dist/types/global-config.generated.d.ts +11 -1
  42. package/dist/types/plugin.d.ts +4 -5
  43. package/dist/types/project-config.generated.d.ts +1 -4
  44. package/dist/utils/plugins.d.ts +3 -7
  45. package/dist/utils/plugins.js +27 -13
  46. package/oclif.manifest.json +163 -90
  47. package/package.json +7 -2
  48. package/schemas/global-config.schema.json +17 -1
  49. package/schemas/project-config.schema.json +3 -4
package/README.md CHANGED
@@ -21,7 +21,7 @@ $ npm install -g @loopress/cli
21
21
  $ lps COMMAND
22
22
  running command...
23
23
  $ lps (--version)
24
- @loopress/cli/0.12.0 linux-x64 node-v24.18.0
24
+ @loopress/cli/0.14.0 linux-x64 node-v24.18.0
25
25
  $ lps --help [COMMAND]
26
26
  USAGE
27
27
  $ lps COMMAND
@@ -35,8 +35,9 @@ Loopress sends crash reports to our Sentry project so we can find and fix bugs.
35
35
 
36
36
  To opt out, either:
37
37
 
38
- - set `LOOPRESS_TELEMETRY_DISABLED=1`, or
39
- - pass `--no-error-reporting` on the command.
38
+ - run `lps telemetry disable` (persists across all future commands), or
39
+ - set `LOOPRESS_TELEMETRY_DISABLED=1` (overrides the persisted preference for a single run,
40
+ useful in CI).
40
41
 
41
42
  A crash report includes the command name, its flags/args as typed, your Node.js
42
43
  version, and OS. WordPress credentials are configured via `lps project config`
@@ -52,7 +53,7 @@ report.
52
53
  * [`lps init`](#lps-init)
53
54
  * [`lps login`](#lps-login)
54
55
  * [`lps logout`](#lps-logout)
55
- * [`lps plugin add SLUG [VERSION]`](#lps-plugin-add-slug-version)
56
+ * [`lps plugin add SLUG`](#lps-plugin-add-slug)
56
57
  * [`lps plugin pull`](#lps-plugin-pull)
57
58
  * [`lps plugin push`](#lps-plugin-push)
58
59
  * [`lps project config`](#lps-project-config)
@@ -61,9 +62,12 @@ report.
61
62
  * [`lps project switch`](#lps-project-switch)
62
63
  * [`lps project sync`](#lps-project-sync)
63
64
  * [`lps snippet list`](#lps-snippet-list)
65
+ * [`lps snippet publish [PATH]`](#lps-snippet-publish-path)
64
66
  * [`lps snippet pull [PATH]`](#lps-snippet-pull-path)
65
67
  * [`lps snippet push [PATH]`](#lps-snippet-push-path)
66
68
  * [`lps status`](#lps-status)
69
+ * [`lps telemetry disable`](#lps-telemetry-disable)
70
+ * [`lps telemetry enable`](#lps-telemetry-enable)
67
71
 
68
72
  ## `lps composer pull`
69
73
 
@@ -85,7 +89,7 @@ EXAMPLES
85
89
  $ lps composer pull --dry-run
86
90
  ```
87
91
 
88
- _See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/composer/pull.ts)_
92
+ _See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/composer/pull.ts)_
89
93
 
90
94
  ## `lps composer push`
91
95
 
@@ -107,7 +111,7 @@ EXAMPLES
107
111
  $ lps composer push --dry-run
108
112
  ```
109
113
 
110
- _See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/composer/push.ts)_
114
+ _See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/composer/push.ts)_
111
115
 
112
116
  ## `lps help [COMMAND]`
113
117
 
@@ -144,7 +148,7 @@ EXAMPLES
144
148
  $ lps init
145
149
  ```
146
150
 
147
- _See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/init.ts)_
151
+ _See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/init.ts)_
148
152
 
149
153
  ## `lps login`
150
154
 
@@ -161,7 +165,7 @@ EXAMPLES
161
165
  $ lps login
162
166
  ```
163
167
 
164
- _See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/login.ts)_
168
+ _See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/login.ts)_
165
169
 
166
170
  ## `lps logout`
167
171
 
@@ -178,19 +182,18 @@ EXAMPLES
178
182
  $ lps logout
179
183
  ```
180
184
 
181
- _See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/logout.ts)_
185
+ _See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/logout.ts)_
182
186
 
183
- ## `lps plugin add SLUG [VERSION]`
187
+ ## `lps plugin add SLUG`
184
188
 
185
189
  Add a WordPress.org plugin to loopress.json
186
190
 
187
191
  ```
188
192
  USAGE
189
- $ lps plugin add SLUG [VERSION] [-d]
193
+ $ lps plugin add SLUG [-d]
190
194
 
191
195
  ARGUMENTS
192
- SLUG Plugin slug on WordPress.org
193
- [VERSION] Version to pin (default: latest)
196
+ SLUG Plugin slug on WordPress.org
194
197
 
195
198
  FLAGS
196
199
  -d, --dry-run Show what would change without making changes
@@ -201,12 +204,10 @@ DESCRIPTION
201
204
  EXAMPLES
202
205
  $ lps plugin add woocommerce
203
206
 
204
- $ lps plugin add woocommerce 8.9.1
205
-
206
207
  $ lps plugin add contact-form-7 --dry-run
207
208
  ```
208
209
 
209
- _See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/plugin/add.ts)_
210
+ _See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/plugin/add.ts)_
210
211
 
211
212
  ## `lps plugin pull`
212
213
 
@@ -228,7 +229,7 @@ EXAMPLES
228
229
  $ lps plugin pull --dry-run
229
230
  ```
230
231
 
231
- _See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/plugin/pull.ts)_
232
+ _See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/plugin/pull.ts)_
232
233
 
233
234
  ## `lps plugin push`
234
235
 
@@ -250,24 +251,25 @@ EXAMPLES
250
251
  $ lps plugin push --dry-run
251
252
  ```
252
253
 
253
- _See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/plugin/push.ts)_
254
+ _See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/plugin/push.ts)_
254
255
 
255
256
  ## `lps project config`
256
257
 
257
- Add or update a WordPress project environment
258
+ Add or update a WordPress project environment. By default, authorizes via WordPress in your browser; manual username/Application Password entry is available as a fallback.
258
259
 
259
260
  ```
260
261
  USAGE
261
262
  $ lps project config
262
263
 
263
264
  DESCRIPTION
264
- Add or update a WordPress project environment
265
+ Add or update a WordPress project environment. By default, authorizes via WordPress in your browser; manual
266
+ username/Application Password entry is available as a fallback.
265
267
 
266
268
  EXAMPLES
267
269
  $ lps project config
268
270
  ```
269
271
 
270
- _See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/project/config.ts)_
272
+ _See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/config.ts)_
271
273
 
272
274
  ## `lps project list`
273
275
 
@@ -284,7 +286,7 @@ EXAMPLES
284
286
  $ lps project list
285
287
  ```
286
288
 
287
- _See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/project/list.ts)_
289
+ _See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/list.ts)_
288
290
 
289
291
  ## `lps project remove`
290
292
 
@@ -301,7 +303,7 @@ EXAMPLES
301
303
  $ lps project remove
302
304
  ```
303
305
 
304
- _See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/project/remove.ts)_
306
+ _See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/remove.ts)_
305
307
 
306
308
  ## `lps project switch`
307
309
 
@@ -318,7 +320,7 @@ EXAMPLES
318
320
  $ lps project switch
319
321
  ```
320
322
 
321
- _See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/project/switch.ts)_
323
+ _See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/switch.ts)_
322
324
 
323
325
  ## `lps project sync`
324
326
 
@@ -335,7 +337,7 @@ EXAMPLES
335
337
  $ lps project sync
336
338
  ```
337
339
 
338
- _See code: [src/commands/project/sync.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/project/sync.ts)_
340
+ _See code: [src/commands/project/sync.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/sync.ts)_
339
341
 
340
342
  ## `lps snippet list`
341
343
 
@@ -355,7 +357,30 @@ EXAMPLES
355
357
  $ lps snippet list
356
358
  ```
357
359
 
358
- _See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/snippet/list.ts)_
360
+ _See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/snippet/list.ts)_
361
+
362
+ ## `lps snippet publish [PATH]`
363
+
364
+ Publish snippets to your Loopress account so they can be deployed to other projects. Does not touch any WordPress site.
365
+
366
+ ```
367
+ USAGE
368
+ $ lps snippet publish [PATH]
369
+
370
+ ARGUMENTS
371
+ [PATH] Path to snippets directory (overrides project config)
372
+
373
+ DESCRIPTION
374
+ Publish snippets to your Loopress account so they can be deployed to other projects. Does not touch any WordPress
375
+ site.
376
+
377
+ EXAMPLES
378
+ $ lps snippet publish
379
+
380
+ $ lps snippet publish --path ./snippets
381
+ ```
382
+
383
+ _See code: [src/commands/snippet/publish.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/snippet/publish.ts)_
359
384
 
360
385
  ## `lps snippet pull [PATH]`
361
386
 
@@ -380,7 +405,7 @@ EXAMPLES
380
405
  $ lps snippet pull --path ./snippets
381
406
  ```
382
407
 
383
- _See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/snippet/pull.ts)_
408
+ _See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/snippet/pull.ts)_
384
409
 
385
410
  ## `lps snippet push [PATH]`
386
411
 
@@ -406,7 +431,7 @@ EXAMPLES
406
431
  $ lps snippet push --path ./snippets
407
432
  ```
408
433
 
409
- _See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/snippet/push.ts)_
434
+ _See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/snippet/push.ts)_
410
435
 
411
436
  ## `lps status`
412
437
 
@@ -423,5 +448,39 @@ EXAMPLES
423
448
  $ lps status
424
449
  ```
425
450
 
426
- _See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.12.0/src/commands/status.ts)_
451
+ _See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/status.ts)_
452
+
453
+ ## `lps telemetry disable`
454
+
455
+ Disable error reporting to Sentry
456
+
457
+ ```
458
+ USAGE
459
+ $ lps telemetry disable
460
+
461
+ DESCRIPTION
462
+ Disable error reporting to Sentry
463
+
464
+ EXAMPLES
465
+ $ lps telemetry disable
466
+ ```
467
+
468
+ _See code: [src/commands/telemetry/disable.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/telemetry/disable.ts)_
469
+
470
+ ## `lps telemetry enable`
471
+
472
+ Enable error reporting to Sentry
473
+
474
+ ```
475
+ USAGE
476
+ $ lps telemetry enable
477
+
478
+ DESCRIPTION
479
+ Enable error reporting to Sentry
480
+
481
+ EXAMPLES
482
+ $ lps telemetry enable
483
+ ```
484
+
485
+ _See code: [src/commands/telemetry/enable.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/telemetry/enable.ts)_
427
486
  <!-- commandsstop -->
@@ -3,7 +3,7 @@ import { Command } from '@oclif/core';
3
3
  import { existsSync } from 'node:fs';
4
4
  import { join } from 'node:path';
5
5
  import { configManager } from '../config/project-config.manager.js';
6
- import { readLocalConfig, writeLocalConfig } from '../utils/loopress-config.js';
6
+ import { writeLocalConfig } from '../utils/loopress-config.js';
7
7
  // WordPress.org slugs for the two snippet plugins the Loopress WordPress plugin supports
8
8
  // (see SnippetModule.php, which wires up both providers and auto-detects the active one).
9
9
  const SNIPPET_PROVIDERS = [
@@ -76,11 +76,11 @@ export default class Init extends Command {
76
76
  snippetsDir,
77
77
  };
78
78
  await writeLocalConfig(config);
79
- let providerVersion;
79
+ let providerAdded = false;
80
80
  if (providerChoice !== '__none__') {
81
81
  try {
82
82
  await this.config.runCommand('plugin:add', [providerChoice]);
83
- providerVersion = (await readLocalConfig()).plugins?.[providerChoice];
83
+ providerAdded = true;
84
84
  }
85
85
  catch (error) {
86
86
  this.warn(error.message);
@@ -89,8 +89,8 @@ export default class Init extends Command {
89
89
  this.log(`\n✓ loopress.json created`);
90
90
  this.log(` Project: ${projectLabel}`);
91
91
  this.log(` Snippets: ${join(rootDir, snippetsDir)}`);
92
- if (providerChoice !== '__none__' && providerVersion) {
93
- this.log(` Plugin: ${providerChoice}@${providerVersion}`);
92
+ if (providerAdded) {
93
+ this.log(` Plugin: ${providerChoice}`);
94
94
  }
95
95
  }
96
96
  }
@@ -3,6 +3,5 @@ export default class Login extends Command {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  run(): Promise<void>;
6
- private openBrowser;
7
6
  private waitForCallback;
8
7
  }
@@ -1,9 +1,7 @@
1
1
  import { Command } from '@oclif/core';
2
- import { exec } from 'node:child_process';
3
- import { createServer } from 'node:http';
4
2
  import { authManager } from '../config/auth.manager.js';
3
+ import { renderResultPage, waitForLocalCallback } from '../lib/local-callback-server.js';
5
4
  const CONSOLE_URL = 'https://console.loopress.dev';
6
- const TIMEOUT_MS = 5 * 60 * 1000;
7
5
  export default class Login extends Command {
8
6
  static description = 'Log in to the Loopress console';
9
7
  static examples = ['$ lps login'];
@@ -12,95 +10,28 @@ export default class Login extends Command {
12
10
  authManager.setAuth({ email, savedAt: new Date().toISOString(), token });
13
11
  this.log(`\nLogged in${email ? ` as ${email}` : ''}. You're all set!`);
14
12
  }
15
- openBrowser(url) {
16
- const cmds = {
17
- darwin: `open "${url}"`,
18
- linux: `xdg-open "${url}"`,
19
- win32: `start "" "${url}"`,
20
- };
21
- const cmd = cmds[process.platform];
22
- if (cmd)
23
- exec(cmd);
24
- }
25
13
  waitForCallback() {
26
- return new Promise((resolve, reject) => {
27
- const server = createServer((req, res) => {
28
- try {
29
- const url = new URL(req.url ?? '/', 'http://localhost');
30
- const token = url.searchParams.get('token');
31
- const email = url.searchParams.get('email') ?? undefined;
32
- if (!token) {
33
- res.writeHead(400, { 'Content-Type': 'text/plain' });
34
- res.end('Missing token');
35
- return;
36
- }
37
- res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
38
- res.end(SUCCESS_PAGE);
39
- clearTimeout(timer);
40
- server.close();
41
- resolve({ email, token });
42
- }
43
- catch (error) {
44
- res.writeHead(500);
45
- res.end('Internal error');
46
- server.close();
47
- reject(error);
14
+ return waitForLocalCallback({
15
+ buildUrl: (callbackBaseUrl) => `${CONSOLE_URL}/cli-auth?callbackUrl=${encodeURIComponent(`${callbackBaseUrl}/callback`)}`,
16
+ handleRequest(url, { resolveWithPage, respondBadRequest }) {
17
+ const token = url.searchParams.get('token');
18
+ const email = url.searchParams.get('email') ?? undefined;
19
+ if (!token) {
20
+ respondBadRequest('Missing token');
21
+ return;
48
22
  }
49
- });
50
- server.on('error', (err) => {
51
- clearTimeout(timer);
52
- reject(err);
53
- });
54
- const timer = setTimeout(() => {
55
- server.close();
56
- reject(new Error('Login timed out after 5 minutes. Please try again.'));
57
- }, TIMEOUT_MS);
58
- server.listen(0, '127.0.0.1', () => {
59
- const { port } = server.address();
60
- const callbackUrl = `http://localhost:${port}/callback`;
61
- const loginUrl = `${CONSOLE_URL}/cli-auth?callbackUrl=${encodeURIComponent(callbackUrl)}`;
62
- this.log('Opening Loopress console in your browser...');
63
- this.log(`\nIf it doesn't open automatically, visit:\n${loginUrl}\n`);
64
- this.openBrowser(loginUrl);
65
- });
23
+ resolveWithPage(SUCCESS_PAGE, { email, token });
24
+ },
25
+ log: (message) => this.log(message),
26
+ openingMessage: 'Opening Loopress console in your browser...',
27
+ timeoutMessage: 'Login timed out after 5 minutes. Please try again.',
66
28
  });
67
29
  }
68
30
  }
69
- const SUCCESS_PAGE = `<!DOCTYPE html>
70
- <html lang="en">
71
- <head>
72
- <meta charset="UTF-8">
73
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
74
- <title>Loopress: Logged in</title>
75
- <style>
76
- *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
77
- body {
78
- font-family: system-ui, -apple-system, sans-serif;
79
- background: #f0fdf4;
80
- display: flex;
81
- align-items: center;
82
- justify-content: center;
83
- min-height: 100dvh;
84
- }
85
- .card {
86
- background: #fff;
87
- border-radius: 16px;
88
- padding: 2.5rem 3rem;
89
- text-align: center;
90
- box-shadow: 0 4px 32px rgba(0, 0, 0, .08);
91
- max-width: 420px;
92
- width: 90%;
93
- }
94
- .icon { font-size: 3rem; margin-bottom: 1rem; }
95
- h1 { color: #15803d; font-size: 1.5rem; margin-bottom: .5rem; }
96
- p { color: #6b7280; font-size: .95rem; line-height: 1.5; }
97
- </style>
98
- </head>
99
- <body>
100
- <div class="card">
101
- <div class="icon">✅</div>
102
- <h1>Login successful!</h1>
103
- <p>You can close this tab and return to your terminal.</p>
104
- </div>
105
- </body>
106
- </html>`;
31
+ const SUCCESS_PAGE = renderResultPage({
32
+ background: '#f0fdf4',
33
+ heading: 'Login successful!',
34
+ headingColor: '#15803d',
35
+ icon: '✅',
36
+ tabTitle: 'Logged in',
37
+ });
@@ -1,9 +1,7 @@
1
1
  import { LoopressCommand } from '../../lib/base.js';
2
- export declare function resolvePluginVersion(slug: string, version: string): Promise<string>;
3
2
  export default class Add extends LoopressCommand {
4
3
  static args: {
5
4
  slug: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
6
- version: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
5
  };
8
6
  static description: string;
9
7
  static examples: string[];
@@ -1,73 +1,32 @@
1
1
  import { Args } from '@oclif/core';
2
- import got from 'got';
3
2
  import { LoopressCommand } from '../../lib/base.js';
4
3
  import { writeLocalConfig } from '../../utils/loopress-config.js';
5
- const WP_ORG_API = 'https://api.wordpress.org/plugins/info/1.2/';
6
- const WP_ORG_TIMEOUT_MS = 10_000;
7
- export async function resolvePluginVersion(slug, version) {
8
- if (version !== 'latest')
9
- return version;
10
- let info;
11
- try {
12
- info = await got
13
- .get(WP_ORG_API, {
14
- searchParams: {
15
- action: 'plugin_information',
16
- 'request[slug]': slug,
17
- },
18
- timeout: { request: WP_ORG_TIMEOUT_MS },
19
- })
20
- .json();
21
- }
22
- catch {
23
- throw new Error(`Plugin "${slug}" not found on WordPress.org.`);
24
- }
25
- if (info.error)
26
- throw new Error(`Plugin "${slug}" not found on WordPress.org.`);
27
- return info.version;
28
- }
29
4
  export default class Add extends LoopressCommand {
30
5
  static args = {
31
6
  slug: Args.string({ description: 'Plugin slug on WordPress.org', required: true }),
32
- version: Args.string({ description: 'Version to pin (default: latest)' }),
33
7
  };
34
8
  static description = 'Add a WordPress.org plugin to loopress.json';
35
- static examples = [
36
- '$ lps plugin add woocommerce',
37
- '$ lps plugin add woocommerce 8.9.1',
38
- '$ lps plugin add contact-form-7 --dry-run',
39
- ];
9
+ static examples = ['$ lps plugin add woocommerce', '$ lps plugin add contact-form-7 --dry-run'];
40
10
  static flags = {
41
11
  ...LoopressCommand.dryRunFlag,
42
12
  };
43
13
  async run() {
44
14
  const { args } = await this.parse(Add);
45
15
  const { slug } = args;
46
- const requestedVersion = args.version ?? 'latest';
47
- this.log(`Resolving ${slug}@${requestedVersion}...`);
48
- let resolvedVersion;
49
- try {
50
- resolvedVersion = await resolvePluginVersion(slug, requestedVersion);
51
- }
52
- catch (error) {
53
- this.error(error.message);
54
- }
55
- this.log(`Resolved: ${slug}@${resolvedVersion}`);
56
16
  const existing = this.localConfig.plugins ?? {};
57
- if (existing[slug] === resolvedVersion) {
58
- this.log(`${slug}@${resolvedVersion} is already in loopress.json, nothing to do.`);
17
+ if (existing[slug] === 'latest') {
18
+ this.log(`${slug} is already in loopress.json, nothing to do.`);
59
19
  return;
60
20
  }
61
21
  const updated = existing[slug] !== undefined;
62
- const label = updated ? `${existing[slug]} → ${resolvedVersion}` : resolvedVersion;
63
22
  if (this.dryRun) {
64
- this.log(`[dry-run] Would ${updated ? 'update' : 'add'} ${slug}: ${label}`);
23
+ this.log(`[dry-run] Would ${updated ? 'update' : 'add'} ${slug} in loopress.json`);
65
24
  return;
66
25
  }
67
26
  await writeLocalConfig({
68
27
  ...this.localConfig,
69
- plugins: { ...existing, [slug]: resolvedVersion },
28
+ plugins: { ...existing, [slug]: 'latest' },
70
29
  });
71
- this.log(`${updated ? 'Updated' : 'Added'} ${slug}: ${label}`);
30
+ this.log(`${updated ? 'Updated' : 'Added'} ${slug}`);
72
31
  }
73
32
  }
@@ -1,7 +1,7 @@
1
1
  import { LoopressCommand } from '../../lib/base.js';
2
2
  import { getComposerManagedSlugs, readComposerJson } from '../../utils/composer.js';
3
3
  import { writeLocalConfig } from '../../utils/loopress-config.js';
4
- import { mergePluginManifest } from '../../utils/plugins.js';
4
+ import { mergePluginManifest, parseInstalledPlugins } from '../../utils/plugins.js';
5
5
  export default class Pull extends LoopressCommand {
6
6
  static description = 'Pull installed plugins from WordPress into loopress.json';
7
7
  static examples = ['$ lps plugin pull', '$ lps plugin pull --dry-run'];
@@ -11,10 +11,11 @@ export default class Pull extends LoopressCommand {
11
11
  async run() {
12
12
  const { url } = this.siteConfig;
13
13
  this.log(`Pulling plugins from ${url}`);
14
- const installed = await this.wp.get('loopress/v1/plugins');
14
+ const raw = await this.wp.get('wp/v2/plugins');
15
+ const installed = parseInstalledPlugins(raw);
15
16
  const composerJson = await readComposerJson();
16
17
  const composerSlugs = composerJson ? getComposerManagedSlugs(composerJson) : [];
17
- const incoming = Object.fromEntries(installed.filter((p) => !composerSlugs.includes(p.slug)).map((p) => [p.slug, p.version]));
18
+ const incoming = Object.fromEntries(installed.filter((p) => !composerSlugs.includes(p.slug)).map((p) => [p.slug, 'latest']));
18
19
  if (composerSlugs.length > 0) {
19
20
  const found = installed.filter((p) => composerSlugs.includes(p.slug)).map((p) => p.slug);
20
21
  if (found.length > 0) {
@@ -38,8 +39,5 @@ export default class Pull extends LoopressCommand {
38
39
  this.log(` + Added: ${added.join(', ')}`);
39
40
  for (const u of updated)
40
41
  this.log(` ~ Updated: ${u.slug} ${u.from} → ${u.to}`);
41
- if (Object.keys(merged).length > 0) {
42
- await this.wp.post('loopress/v1/plugins/auto-updates/disable', { slugs: Object.keys(merged) });
43
- }
44
42
  }
45
43
  }
@@ -8,7 +8,6 @@ export default class Push extends PushCommand {
8
8
  private failedCount;
9
9
  run(): Promise<void>;
10
10
  private activatePlugin;
11
- private installAndActivate;
11
+ private installPlugin;
12
12
  private performPluginAction;
13
- private syncDrifted;
14
13
  }