@loopress/cli 0.6.0 → 0.7.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 (35) hide show
  1. package/README.md +71 -90
  2. package/dist/commands/composer/pull.js +1 -1
  3. package/dist/commands/composer/push.js +1 -1
  4. package/dist/commands/init.js +15 -6
  5. package/dist/commands/login.js +1 -1
  6. package/dist/commands/logout.js +1 -1
  7. package/dist/commands/plugin/add.d.ts +0 -2
  8. package/dist/commands/plugin/add.js +2 -23
  9. package/dist/commands/plugin/pull.js +1 -1
  10. package/dist/commands/plugin/push.js +3 -3
  11. package/dist/commands/project/config.d.ts +1 -0
  12. package/dist/commands/project/config.js +36 -17
  13. package/dist/commands/project/list.js +4 -5
  14. package/dist/commands/project/remove.js +33 -14
  15. package/dist/commands/project/switch.d.ts +2 -0
  16. package/dist/commands/project/switch.js +28 -9
  17. package/dist/commands/snippet/list.js +3 -3
  18. package/dist/commands/snippet/pull.d.ts +1 -1
  19. package/dist/commands/snippet/pull.js +7 -6
  20. package/dist/commands/snippet/push.d.ts +2 -2
  21. package/dist/commands/snippet/push.js +47 -15
  22. package/dist/commands/{project/remove-env.d.ts → status.d.ts} +3 -1
  23. package/dist/commands/status.js +66 -0
  24. package/dist/config/project-config.manager.d.ts +17 -10
  25. package/dist/config/project-config.manager.js +91 -44
  26. package/dist/config/types.d.ts +5 -2
  27. package/dist/lib/base.js +13 -3
  28. package/dist/types/snippet.d.ts +2 -0
  29. package/dist/utils/snippet-plugin.d.ts +2 -1
  30. package/dist/utils/snippet-plugin.js +5 -4
  31. package/oclif.manifest.json +149 -175
  32. package/package.json +17 -2
  33. package/dist/commands/project/remove-env.js +0 -33
  34. package/dist/commands/project/switch-env.d.ts +0 -6
  35. package/dist/commands/project/switch-env.js +0 -33
package/README.md CHANGED
@@ -20,7 +20,7 @@ $ npm install -g @loopress/cli
20
20
  $ lps COMMAND
21
21
  running command...
22
22
  $ lps (--version)
23
- @loopress/cli/0.6.0 linux-x64 node-v24.17.0
23
+ @loopress/cli/0.7.0 linux-x64 node-v24.18.0
24
24
  $ lps --help [COMMAND]
25
25
  USAGE
26
26
  $ lps COMMAND
@@ -43,16 +43,15 @@ USAGE
43
43
  * [`lps project config`](#lps-project-config)
44
44
  * [`lps project list`](#lps-project-list)
45
45
  * [`lps project remove`](#lps-project-remove)
46
- * [`lps project remove-env`](#lps-project-remove-env)
47
46
  * [`lps project switch`](#lps-project-switch)
48
- * [`lps project switch-env`](#lps-project-switch-env)
49
47
  * [`lps snippet list`](#lps-snippet-list)
50
48
  * [`lps snippet pull [PATH]`](#lps-snippet-pull-path)
51
49
  * [`lps snippet push [PATH]`](#lps-snippet-push-path)
50
+ * [`lps status`](#lps-status)
52
51
 
53
52
  ## `lps composer pull`
54
53
 
55
- Pull composer.lock from the WordPress server
54
+ Pull composer.lock from WordPress
56
55
 
57
56
  ```
58
57
  USAGE
@@ -67,7 +66,7 @@ GLOBAL FLAGS
67
66
  --user=<value> WordPress username (fallback; prefer `lps project config`)
68
67
 
69
68
  DESCRIPTION
70
- Pull composer.lock from the WordPress server
69
+ Pull composer.lock from WordPress
71
70
 
72
71
  EXAMPLES
73
72
  $ lps composer pull
@@ -75,11 +74,11 @@ EXAMPLES
75
74
  $ lps composer pull --dry-run
76
75
  ```
77
76
 
78
- _See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/composer/pull.ts)_
77
+ _See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/composer/pull.ts)_
79
78
 
80
79
  ## `lps composer push`
81
80
 
82
- Upload composer.json and composer.lock to WordPress and run composer install
81
+ Push composer.json and composer.lock to WordPress and run composer install
83
82
 
84
83
  ```
85
84
  USAGE
@@ -94,7 +93,7 @@ GLOBAL FLAGS
94
93
  --user=<value> WordPress username (fallback; prefer `lps project config`)
95
94
 
96
95
  DESCRIPTION
97
- Upload composer.json and composer.lock to WordPress and run composer install
96
+ Push composer.json and composer.lock to WordPress and run composer install
98
97
 
99
98
  EXAMPLES
100
99
  $ lps composer push
@@ -102,7 +101,7 @@ EXAMPLES
102
101
  $ lps composer push --dry-run
103
102
  ```
104
103
 
105
- _See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/composer/push.ts)_
104
+ _See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/composer/push.ts)_
106
105
 
107
106
  ## `lps help [COMMAND]`
108
107
 
@@ -139,52 +138,52 @@ EXAMPLES
139
138
  $ lps init
140
139
  ```
141
140
 
142
- _See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/init.ts)_
141
+ _See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/init.ts)_
143
142
 
144
143
  ## `lps login`
145
144
 
146
- Log in to Loopress via the console
145
+ Log in to the Loopress console
147
146
 
148
147
  ```
149
148
  USAGE
150
149
  $ lps login
151
150
 
152
151
  DESCRIPTION
153
- Log in to Loopress via the console
152
+ Log in to the Loopress console
154
153
 
155
154
  EXAMPLES
156
155
  $ lps login
157
156
  ```
158
157
 
159
- _See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/login.ts)_
158
+ _See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/login.ts)_
160
159
 
161
160
  ## `lps logout`
162
161
 
163
- Log out from Loopress console
162
+ Log out from the Loopress console
164
163
 
165
164
  ```
166
165
  USAGE
167
166
  $ lps logout
168
167
 
169
168
  DESCRIPTION
170
- Log out from Loopress console
169
+ Log out from the Loopress console
171
170
 
172
171
  EXAMPLES
173
172
  $ lps logout
174
173
  ```
175
174
 
176
- _See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/logout.ts)_
175
+ _See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/logout.ts)_
177
176
 
178
177
  ## `lps plugin add SLUG [VERSION]`
179
178
 
180
- Add a plugin to loopress.json (WordPress.org) or run composer require (vendor/package)
179
+ Add a WordPress.org plugin to loopress.json
181
180
 
182
181
  ```
183
182
  USAGE
184
183
  $ lps plugin add SLUG [VERSION] [--password <value>] [--url <value>] [--user <value>] [-d]
185
184
 
186
185
  ARGUMENTS
187
- SLUG Plugin slug (WordPress.org) or Composer package (vendor/package)
186
+ SLUG Plugin slug on WordPress.org
188
187
  [VERSION] Version to pin (default: latest)
189
188
 
190
189
  FLAGS
@@ -196,19 +195,17 @@ GLOBAL FLAGS
196
195
  --user=<value> WordPress username (fallback; prefer `lps project config`)
197
196
 
198
197
  DESCRIPTION
199
- Add a plugin to loopress.json (WordPress.org) or run composer require (vendor/package)
198
+ Add a WordPress.org plugin to loopress.json
200
199
 
201
200
  EXAMPLES
202
201
  $ lps plugin add woocommerce
203
202
 
204
203
  $ lps plugin add woocommerce 8.9.1
205
204
 
206
- $ lps plugin add wpackagist-plugin/advanced-custom-fields
207
-
208
205
  $ lps plugin add contact-form-7 --dry-run
209
206
  ```
210
207
 
211
- _See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/plugin/add.ts)_
208
+ _See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/plugin/add.ts)_
212
209
 
213
210
  ## `lps plugin pull`
214
211
 
@@ -230,16 +227,16 @@ DESCRIPTION
230
227
  Pull installed plugins from WordPress into loopress.json
231
228
 
232
229
  EXAMPLES
233
- $ lps plugins pull
230
+ $ lps plugin pull
234
231
 
235
- $ lps plugins pull --dry-run
232
+ $ lps plugin pull --dry-run
236
233
  ```
237
234
 
238
- _See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/plugin/pull.ts)_
235
+ _See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/plugin/pull.ts)_
239
236
 
240
237
  ## `lps plugin push`
241
238
 
242
- Sync plugins on WordPress to match loopress.json
239
+ Push plugins to WordPress to match loopress.json
243
240
 
244
241
  ```
245
242
  USAGE
@@ -254,15 +251,15 @@ GLOBAL FLAGS
254
251
  --user=<value> WordPress username (fallback; prefer `lps project config`)
255
252
 
256
253
  DESCRIPTION
257
- Sync plugins on WordPress to match loopress.json
254
+ Push plugins to WordPress to match loopress.json
258
255
 
259
256
  EXAMPLES
260
- $ lps plugins push
257
+ $ lps plugin push
261
258
 
262
- $ lps plugins push --dry-run
259
+ $ lps plugin push --dry-run
263
260
  ```
264
261
 
265
- _See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/plugin/push.ts)_
262
+ _See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/plugin/push.ts)_
266
263
 
267
264
  ## `lps project config`
268
265
 
@@ -279,7 +276,7 @@ EXAMPLES
279
276
  $ lps project config
280
277
  ```
281
278
 
282
- _See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/project/config.ts)_
279
+ _See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/project/config.ts)_
283
280
 
284
281
  ## `lps project list`
285
282
 
@@ -296,75 +293,41 @@ EXAMPLES
296
293
  $ lps project list
297
294
  ```
298
295
 
299
- _See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/project/list.ts)_
296
+ _See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/project/list.ts)_
300
297
 
301
298
  ## `lps project remove`
302
299
 
303
- Remove one or more WordPress project configurations
300
+ Remove one or more WordPress projects or environments
304
301
 
305
302
  ```
306
303
  USAGE
307
304
  $ lps project remove
308
305
 
309
306
  DESCRIPTION
310
- Remove one or more WordPress project configurations
307
+ Remove one or more WordPress projects or environments
311
308
 
312
309
  EXAMPLES
313
310
  $ lps project remove
314
311
  ```
315
312
 
316
- _See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/project/remove.ts)_
317
-
318
- ## `lps project remove-env`
319
-
320
- Remove one or more environments from the current project
321
-
322
- ```
323
- USAGE
324
- $ lps project remove-env
325
-
326
- DESCRIPTION
327
- Remove one or more environments from the current project
328
-
329
- EXAMPLES
330
- $ lps project remove-env
331
- ```
332
-
333
- _See code: [src/commands/project/remove-env.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/project/remove-env.ts)_
313
+ _See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/project/remove.ts)_
334
314
 
335
315
  ## `lps project switch`
336
316
 
337
- Switch the active project
317
+ Switch the active project and environment
338
318
 
339
319
  ```
340
320
  USAGE
341
321
  $ lps project switch
342
322
 
343
323
  DESCRIPTION
344
- Switch the active project
324
+ Switch the active project and environment
345
325
 
346
326
  EXAMPLES
347
327
  $ lps project switch
348
328
  ```
349
329
 
350
- _See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/project/switch.ts)_
351
-
352
- ## `lps project switch-env`
353
-
354
- Switch the active environment within the current project
355
-
356
- ```
357
- USAGE
358
- $ lps project switch-env
359
-
360
- DESCRIPTION
361
- Switch the active environment within the current project
362
-
363
- EXAMPLES
364
- $ lps project switch-env
365
- ```
366
-
367
- _See code: [src/commands/project/switch-env.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/project/switch-env.ts)_
330
+ _See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/project/switch.ts)_
368
331
 
369
332
  ## `lps snippet list`
370
333
 
@@ -388,14 +351,14 @@ DESCRIPTION
388
351
  List snippets from WordPress
389
352
 
390
353
  EXAMPLES
391
- $ lps snippets list
354
+ $ lps snippet list
392
355
 
393
- $ lps snippets list --url http://example.com
356
+ $ lps snippet list --url http://example.com
394
357
 
395
- $ lps snippets list --plugin wpcode
358
+ $ lps snippet list --plugin wpcode
396
359
  ```
397
360
 
398
- _See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/snippet/list.ts)_
361
+ _See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/snippet/list.ts)_
399
362
 
400
363
  ## `lps snippet pull [PATH]`
401
364
 
@@ -409,7 +372,7 @@ ARGUMENTS
409
372
  [PATH] Path to snippets directory (overrides project config)
410
373
 
411
374
  FLAGS
412
- -d, --dryRun Dry run - show what would happen without making changes
375
+ -d, --dry-run Show what would be written without making changes
413
376
  -p, --plugin=<option> WordPress snippet plugin to target (overrides loopress.json)
414
377
  <options: code-snippets|wpcode>
415
378
 
@@ -422,20 +385,20 @@ DESCRIPTION
422
385
  Pull snippets from WordPress
423
386
 
424
387
  EXAMPLES
425
- $ lps snippets pull
388
+ $ lps snippet pull
426
389
 
427
- $ lps snippets pull --url http://example.com
390
+ $ lps snippet pull --url http://example.com
428
391
 
429
- $ lps snippets pull --path ./snippets
392
+ $ lps snippet pull --path ./snippets
430
393
 
431
- $ lps snippets pull --plugin wpcode
394
+ $ lps snippet pull --plugin wpcode
432
395
  ```
433
396
 
434
- _See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/snippet/pull.ts)_
397
+ _See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/snippet/pull.ts)_
435
398
 
436
399
  ## `lps snippet push [PATH]`
437
400
 
438
- Push snippets to WordPress
401
+ Push snippets to WordPress. Local snippet files created or updated remotely are renamed on disk to the `<id>-<slug>` convention.
439
402
 
440
403
  ```
441
404
  USAGE
@@ -445,7 +408,7 @@ ARGUMENTS
445
408
  [PATH] Path to snippets directory (overrides project config)
446
409
 
447
410
  FLAGS
448
- -d, --dryRun Dry run - show what would happen without making changes
411
+ -d, --dry-run Show what would change without making changes
449
412
  -p, --plugin=<option> WordPress snippet plugin to target (overrides loopress.json)
450
413
  <options: code-snippets|wpcode>
451
414
 
@@ -455,17 +418,35 @@ GLOBAL FLAGS
455
418
  --user=<value> WordPress username (fallback; prefer `lps project config`)
456
419
 
457
420
  DESCRIPTION
458
- Push snippets to WordPress
421
+ Push snippets to WordPress. Local snippet files created or updated remotely are renamed on disk to the `<id>-<slug>`
422
+ convention.
459
423
 
460
424
  EXAMPLES
461
- $ lps snippets push
425
+ $ lps snippet push
426
+
427
+ $ lps snippet push --url http://example.com
462
428
 
463
- $ lps snippets push --url http://example.com
429
+ $ lps snippet push --path ./snippets
430
+
431
+ $ lps snippet push --plugin wpcode
432
+ ```
464
433
 
465
- $ lps snippets push --path ./snippets
434
+ _See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/snippet/push.ts)_
466
435
 
467
- $ lps snippets push --plugin wpcode
436
+ ## `lps status`
437
+
438
+ Show which WordPress project and environment commands will target
439
+
440
+ ```
441
+ USAGE
442
+ $ lps status
443
+
444
+ DESCRIPTION
445
+ Show which WordPress project and environment commands will target
446
+
447
+ EXAMPLES
448
+ $ lps status
468
449
  ```
469
450
 
470
- _See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.6.0/src/commands/snippet/push.ts)_
451
+ _See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.7.0/src/commands/status.ts)_
471
452
  <!-- commandsstop -->
@@ -5,7 +5,7 @@ import { join } from 'node:path';
5
5
  import { LoopressCommand } from '../../lib/base.js';
6
6
  import { readLocalConfig } from '../../utils/loopress-config.js';
7
7
  export default class ComposerPull extends LoopressCommand {
8
- static description = 'Pull composer.lock from the WordPress server';
8
+ static description = 'Pull composer.lock from WordPress';
9
9
  static examples = ['$ lps composer pull', '$ lps composer pull --dry-run'];
10
10
  static flags = {
11
11
  ...LoopressCommand.baseFlags,
@@ -6,7 +6,7 @@ import { join } from 'node:path';
6
6
  import { PushCommand } from '../../lib/push-command.js';
7
7
  import { readLocalConfig } from '../../utils/loopress-config.js';
8
8
  export default class ComposerPush extends PushCommand {
9
- static description = 'Upload composer.json and composer.lock to WordPress and run composer install';
9
+ static description = 'Push composer.json and composer.lock to WordPress and run composer install';
10
10
  static examples = ['$ lps composer push', '$ lps composer push --dry-run'];
11
11
  static flags = {
12
12
  ...PushCommand.baseFlags,
@@ -22,19 +22,27 @@ export default class Init extends Command {
22
22
  }
23
23
  const projects = configManager.listProjects();
24
24
  let projectId;
25
+ let projectLabel;
25
26
  if (projects.length > 0) {
26
27
  const choices = [
27
- ...projects.map((p) => ({ name: p.name, value: p.name })),
28
+ ...projects.map((p) => ({ name: p.name, value: p.id })),
28
29
  { name: 'Enter a project ID manually', value: '__manual__' },
29
30
  ];
30
31
  const choice = await select({
31
32
  choices,
32
33
  message: 'WordPress project',
33
34
  });
34
- projectId = choice === '__manual__' ? (await input({
35
- message: 'Project ID',
36
- validate: (value) => (value.trim().length > 0 ? true : 'Project ID cannot be empty'),
37
- })) : choice;
35
+ if (choice === '__manual__') {
36
+ projectId = await input({
37
+ message: 'Project ID',
38
+ validate: (value) => (value.trim().length > 0 ? true : 'Project ID cannot be empty'),
39
+ });
40
+ projectLabel = projectId;
41
+ }
42
+ else {
43
+ projectId = choice;
44
+ projectLabel = projects.find((p) => p.id === choice).name;
45
+ }
38
46
  }
39
47
  else {
40
48
  this.log('No projects configured yet. Run `lps project config` to add one first.');
@@ -42,6 +50,7 @@ export default class Init extends Command {
42
50
  message: 'Project ID',
43
51
  validate: (value) => (value.trim().length > 0 ? true : 'Project ID cannot be empty'),
44
52
  });
53
+ projectLabel = projectId;
45
54
  }
46
55
  const snippetPlugin = await select({
47
56
  choices: [
@@ -66,7 +75,7 @@ export default class Init extends Command {
66
75
  };
67
76
  await writeLocalConfig(config);
68
77
  this.log(`\n✓ loopress.json created`);
69
- this.log(` Project: ${projectId}`);
78
+ this.log(` Project: ${projectLabel}`);
70
79
  this.log(` Plugin: ${snippetPlugin}`);
71
80
  this.log(` Snippets: ${join(rootDir, snippetsDir)}`);
72
81
  }
@@ -5,7 +5,7 @@ import { authManager } from '../config/auth.manager.js';
5
5
  const CONSOLE_URL = 'https://console.loopress.dev';
6
6
  const TIMEOUT_MS = 5 * 60 * 1000;
7
7
  export default class Login extends Command {
8
- static description = 'Log in to Loopress via the console';
8
+ static description = 'Log in to the Loopress console';
9
9
  static examples = ['$ lps login'];
10
10
  async run() {
11
11
  const { email, token } = await this.waitForCallback();
@@ -1,7 +1,7 @@
1
1
  import { Command } from '@oclif/core';
2
2
  import { authManager } from '../config/auth.manager.js';
3
3
  export default class Logout extends Command {
4
- static description = 'Log out from Loopress console';
4
+ static description = 'Log out from the Loopress console';
5
5
  static examples = ['$ lps logout'];
6
6
  async run() {
7
7
  const auth = authManager.getAuth();
@@ -14,6 +14,4 @@ export default class Add extends LoopressCommand {
14
14
  user: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
15
  };
16
16
  run(): Promise<void>;
17
- private requireComposerPackage;
18
- private requireWpOrgPlugin;
19
17
  }
@@ -1,6 +1,5 @@
1
1
  import { Args, Flags } from '@oclif/core';
2
2
  import got from 'got';
3
- import { spawnSync } from 'node:child_process';
4
3
  import { LoopressCommand } from '../../lib/base.js';
5
4
  import { readLocalConfig, writeLocalConfig } from '../../utils/loopress-config.js';
6
5
  const WP_ORG_API = 'https://api.wordpress.org/plugins/info/1.2/';
@@ -27,14 +26,13 @@ export async function resolvePluginVersion(slug, version) {
27
26
  }
28
27
  export default class Add extends LoopressCommand {
29
28
  static args = {
30
- slug: Args.string({ description: 'Plugin slug (WordPress.org) or Composer package (vendor/package)', required: true }),
29
+ slug: Args.string({ description: 'Plugin slug on WordPress.org', required: true }),
31
30
  version: Args.string({ description: 'Version to pin (default: latest)' }),
32
31
  };
33
- static description = 'Add a plugin to loopress.json (WordPress.org) or run composer require (vendor/package)';
32
+ static description = 'Add a WordPress.org plugin to loopress.json';
34
33
  static examples = [
35
34
  '$ lps plugin add woocommerce',
36
35
  '$ lps plugin add woocommerce 8.9.1',
37
- '$ lps plugin add wpackagist-plugin/advanced-custom-fields',
38
36
  '$ lps plugin add contact-form-7 --dry-run',
39
37
  ];
40
38
  static flags = {
@@ -46,25 +44,6 @@ export default class Add extends LoopressCommand {
46
44
  const dryRun = flags['dry-run'];
47
45
  const { slug } = args;
48
46
  const requestedVersion = args.version ?? 'latest';
49
- if (slug.includes('/')) {
50
- await this.requireComposerPackage(slug, requestedVersion, dryRun);
51
- return;
52
- }
53
- await this.requireWpOrgPlugin(slug, requestedVersion, dryRun);
54
- }
55
- async requireComposerPackage(pkg, version, dryRun) {
56
- const composerArg = version === 'latest' ? pkg : `${pkg}:${version}`;
57
- this.log(`Running: composer require ${composerArg}`);
58
- if (dryRun) {
59
- this.log(`[dry-run] Would run: composer require ${composerArg}`);
60
- return;
61
- }
62
- const result = spawnSync('composer', ['require', composerArg], { stdio: 'inherit' });
63
- if (result.status !== 0) {
64
- this.error('composer require failed. Make sure Composer is installed and accessible.');
65
- }
66
- }
67
- async requireWpOrgPlugin(slug, requestedVersion, dryRun) {
68
47
  this.log(`Resolving ${slug}@${requestedVersion}...`);
69
48
  let resolvedVersion;
70
49
  try {
@@ -6,7 +6,7 @@ import { readLocalConfig, writeLocalConfig } from '../../utils/loopress-config.j
6
6
  import { mergePluginManifest } from '../../utils/plugins.js';
7
7
  export default class Pull extends LoopressCommand {
8
8
  static description = 'Pull installed plugins from WordPress into loopress.json';
9
- static examples = ['$ lps plugins pull', '$ lps plugins pull --dry-run'];
9
+ static examples = ['$ lps plugin pull', '$ lps plugin pull --dry-run'];
10
10
  static flags = {
11
11
  ...LoopressCommand.baseFlags,
12
12
  'dry-run': Flags.boolean({ char: 'd', description: 'Show what would be written without making changes' }),
@@ -6,8 +6,8 @@ import { getComposerManagedSlugs, readComposerJson } from '../../utils/composer.
6
6
  import { readLocalConfig } from '../../utils/loopress-config.js';
7
7
  import { diffPlugins } from '../../utils/plugins.js';
8
8
  export default class Push extends PushCommand {
9
- static description = 'Sync plugins on WordPress to match loopress.json';
10
- static examples = ['$ lps plugins push', '$ lps plugins push --dry-run'];
9
+ static description = 'Push plugins to WordPress to match loopress.json';
10
+ static examples = ['$ lps plugin push', '$ lps plugin push --dry-run'];
11
11
  static flags = {
12
12
  ...PushCommand.baseFlags,
13
13
  'dry-run': Flags.boolean({ char: 'd', description: 'Show what would change without making changes' }),
@@ -20,7 +20,7 @@ export default class Push extends PushCommand {
20
20
  const localConfig = await readLocalConfig();
21
21
  const manifest = localConfig.plugins;
22
22
  if (!manifest || Object.keys(manifest).length === 0) {
23
- this.error('No plugins found in loopress.json. Run `lps plugins pull` first.');
23
+ this.error('No plugins found in loopress.json. Run `lps plugin pull` first.');
24
24
  }
25
25
  const composerJson = await readComposerJson();
26
26
  const composerSlugs = composerJson ? getComposerManagedSlugs(composerJson) : [];
@@ -3,4 +3,5 @@ export default class Config extends Command {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  run(): Promise<void>;
6
+ private resolveProject;
6
7
  }
@@ -1,20 +1,13 @@
1
1
  import { confirm, input, password as passwordPrompt, select } from '@inquirer/prompts';
2
2
  import { Command } from '@oclif/core';
3
3
  import { configManager } from '../../config/project-config.manager.js';
4
+ const NEW_PROJECT = '__new__';
4
5
  export default class Config extends Command {
5
6
  static description = 'Add or update a WordPress project environment';
6
7
  static examples = ['$ lps project config'];
7
8
  async run() {
8
9
  await this.parse(Config);
9
- const projectName = await input({
10
- message: 'Project name (identifier, no spaces)',
11
- validate(value) {
12
- if (!/^[a-z0-9_-]+$/.test(value)) {
13
- return 'Name must be lowercase with only letters, numbers, - and _';
14
- }
15
- return true;
16
- },
17
- });
10
+ const { projectId, projectName } = await this.resolveProject();
18
11
  const envChoice = await select({
19
12
  choices: [
20
13
  { name: 'local', value: 'local' },
@@ -30,8 +23,7 @@ export default class Config extends Command {
30
23
  validate: (value) => (value.trim().length > 0 ? true : 'Name cannot be empty'),
31
24
  })
32
25
  : envChoice;
33
- const existingProject = configManager.getProject(projectName);
34
- const existingEnv = existingProject?.environments[envName];
26
+ const existingEnv = configManager.getEnvironment(projectId, envName);
35
27
  if (existingEnv) {
36
28
  const overwrite = await confirm({
37
29
  default: false,
@@ -73,20 +65,47 @@ export default class Config extends Command {
73
65
  token,
74
66
  url,
75
67
  };
76
- if (existingProject) {
77
- configManager.setEnvironment(projectName, envName, env);
68
+ if (configManager.getProject(projectId)) {
69
+ configManager.setEnvironment(projectId, envName, env);
78
70
  }
79
71
  else {
80
72
  const project = {
81
73
  addedAt: new Date().toISOString(),
82
- currentEnv: envName,
83
74
  environments: { [envName]: env },
84
75
  name: projectName,
85
76
  };
86
- configManager.setProject(projectName, project);
77
+ configManager.setProject(projectId, project);
87
78
  }
88
79
  this.log(`✓ "${projectName}/${envName}" configured`);
89
- this.log('→ Run `lps project switch` to change active project');
90
- this.log('→ Run `lps project switch-env` to change active environment');
80
+ this.log('→ Run `lps project switch` to change the active project or environment');
81
+ }
82
+ async resolveProject() {
83
+ const projects = configManager.listProjects();
84
+ if (projects.length > 0) {
85
+ const choice = await select({
86
+ choices: [
87
+ ...projects.map((project) => ({ name: project.name, value: project.id })),
88
+ { name: 'Add a new project…', value: NEW_PROJECT },
89
+ ],
90
+ message: 'Project',
91
+ });
92
+ if (choice !== NEW_PROJECT) {
93
+ const project = projects.find((p) => p.id === choice);
94
+ return { projectId: project.id, projectName: project.name };
95
+ }
96
+ }
97
+ const existingNames = new Set(projects.map((project) => project.name.trim().toLowerCase()));
98
+ const projectName = await input({
99
+ message: 'Project name',
100
+ validate(value) {
101
+ const trimmed = value.trim();
102
+ if (trimmed.length === 0)
103
+ return 'Name cannot be empty';
104
+ if (existingNames.has(trimmed.toLowerCase()))
105
+ return `A project named "${trimmed}" already exists`;
106
+ return true;
107
+ },
108
+ });
109
+ return { projectId: configManager.createProjectId(), projectName: projectName.trim() };
91
110
  }
92
111
  }