@loopress/cli 0.16.0 → 0.18.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.
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Loopress
2
2
 
3
- A new CLI generated with oclif
3
+ CLI to interact with the Loopress ecosystem
4
4
 
5
5
  [![oclif](https://img.shields.io/badge/cli-oclif-brightgreen.svg)](https://oclif.io)
6
- [![Version](https://img.shields.io/npm/v/mynewcli.svg)](https://npmjs.org/package/mynewcli)
7
- [![Downloads/week](https://img.shields.io/npm/dw/mynewcli.svg)](https://npmjs.org/package/mynewcli)
6
+ [![Version](https://img.shields.io/npm/v/@loopress/cli.svg)](https://www.npmjs.com/package/@loopress/cli)
7
+ [![Downloads/week](https://img.shields.io/npm/dw/@loopress/cli.svg)](https://npmjs.org/package/@loopress/cli)
8
8
 
9
9
  <!-- toc -->
10
10
  * [Loopress](#loopress)
@@ -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.16.0 linux-x64 node-v24.18.0
24
+ @loopress/cli/0.18.0 linux-x64 node-v24.18.0
25
25
  $ lps --help [COMMAND]
26
26
  USAGE
27
27
  $ lps COMMAND
@@ -50,9 +50,15 @@ report.
50
50
  * [`lps acf list`](#lps-acf-list)
51
51
  * [`lps acf pull [PATH]`](#lps-acf-pull-path)
52
52
  * [`lps acf push [PATH]`](#lps-acf-push-path)
53
+ * [`lps api list`](#lps-api-list)
54
+ * [`lps api pull [PATH]`](#lps-api-pull-path)
55
+ * [`lps api push [PATH]`](#lps-api-push-path)
53
56
  * [`lps composer init`](#lps-composer-init)
54
57
  * [`lps composer pull`](#lps-composer-pull)
55
58
  * [`lps composer push`](#lps-composer-push)
59
+ * [`lps form list`](#lps-form-list)
60
+ * [`lps form pull [PATH]`](#lps-form-pull-path)
61
+ * [`lps form push [PATH]`](#lps-form-push-path)
56
62
  * [`lps help [COMMAND]`](#lps-help-command)
57
63
  * [`lps init`](#lps-init)
58
64
  * [`lps login`](#lps-login)
@@ -66,6 +72,9 @@ report.
66
72
  * [`lps project push`](#lps-project-push)
67
73
  * [`lps project remove`](#lps-project-remove)
68
74
  * [`lps project switch`](#lps-project-switch)
75
+ * [`lps seo list`](#lps-seo-list)
76
+ * [`lps seo pull [PATH]`](#lps-seo-pull-path)
77
+ * [`lps seo push [PATH]`](#lps-seo-push-path)
69
78
  * [`lps snippet list`](#lps-snippet-list)
70
79
  * [`lps snippet publish [PATH]`](#lps-snippet-publish-path)
71
80
  * [`lps snippet pull [PATH]`](#lps-snippet-pull-path)
@@ -96,7 +105,7 @@ EXAMPLES
96
105
  $ lps acf list --type field-groups
97
106
  ```
98
107
 
99
- _See code: [src/commands/acf/list.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/acf/list.ts)_
108
+ _See code: [src/commands/acf/list.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/acf/list.ts)_
100
109
 
101
110
  ## `lps acf pull [PATH]`
102
111
 
@@ -123,7 +132,7 @@ EXAMPLES
123
132
  $ lps acf pull --type field-groups
124
133
  ```
125
134
 
126
- _See code: [src/commands/acf/pull.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/acf/pull.ts)_
135
+ _See code: [src/commands/acf/pull.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/acf/pull.ts)_
127
136
 
128
137
  ## `lps acf push [PATH]`
129
138
 
@@ -150,7 +159,77 @@ EXAMPLES
150
159
  $ lps acf push --type field-groups
151
160
  ```
152
161
 
153
- _See code: [src/commands/acf/push.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/acf/push.ts)_
162
+ _See code: [src/commands/acf/push.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/acf/push.ts)_
163
+
164
+ ## `lps api list`
165
+
166
+ List custom API route files from WordPress
167
+
168
+ ```
169
+ USAGE
170
+ $ lps api list [-j]
171
+
172
+ FLAGS
173
+ -j, --json Output in JSON format
174
+
175
+ DESCRIPTION
176
+ List custom API route files from WordPress
177
+
178
+ EXAMPLES
179
+ $ lps api list
180
+ ```
181
+
182
+ _See code: [src/commands/api/list.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/api/list.ts)_
183
+
184
+ ## `lps api pull [PATH]`
185
+
186
+ Pull custom API route files from WordPress
187
+
188
+ ```
189
+ USAGE
190
+ $ lps api pull [PATH] [-d]
191
+
192
+ ARGUMENTS
193
+ [PATH] Path to api directory (overrides project config)
194
+
195
+ FLAGS
196
+ -d, --dry-run Show what would change without making changes
197
+
198
+ DESCRIPTION
199
+ Pull custom API route files from WordPress
200
+
201
+ EXAMPLES
202
+ $ lps api pull
203
+
204
+ $ lps api pull --path ./api
205
+ ```
206
+
207
+ _See code: [src/commands/api/pull.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/api/pull.ts)_
208
+
209
+ ## `lps api push [PATH]`
210
+
211
+ Push custom API route files to WordPress
212
+
213
+ ```
214
+ USAGE
215
+ $ lps api push [PATH] [-d]
216
+
217
+ ARGUMENTS
218
+ [PATH] Path to api directory (overrides project config)
219
+
220
+ FLAGS
221
+ -d, --dry-run Show what would change without making changes
222
+
223
+ DESCRIPTION
224
+ Push custom API route files to WordPress
225
+
226
+ EXAMPLES
227
+ $ lps api push
228
+
229
+ $ lps api push --path ./api
230
+ ```
231
+
232
+ _See code: [src/commands/api/push.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/api/push.ts)_
154
233
 
155
234
  ## `lps composer init`
156
235
 
@@ -172,7 +251,7 @@ EXAMPLES
172
251
  $ lps composer init --dry-run
173
252
  ```
174
253
 
175
- _See code: [src/commands/composer/init.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/composer/init.ts)_
254
+ _See code: [src/commands/composer/init.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/composer/init.ts)_
176
255
 
177
256
  ## `lps composer pull`
178
257
 
@@ -194,7 +273,7 @@ EXAMPLES
194
273
  $ lps composer pull --dry-run
195
274
  ```
196
275
 
197
- _See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/composer/pull.ts)_
276
+ _See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/composer/pull.ts)_
198
277
 
199
278
  ## `lps composer push`
200
279
 
@@ -216,7 +295,74 @@ EXAMPLES
216
295
  $ lps composer push --dry-run
217
296
  ```
218
297
 
219
- _See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/composer/push.ts)_
298
+ _See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/composer/push.ts)_
299
+
300
+ ## `lps form list`
301
+
302
+ List forms from WordPress
303
+
304
+ ```
305
+ USAGE
306
+ $ lps form list [-j]
307
+
308
+ FLAGS
309
+ -j, --json Output in JSON format
310
+
311
+ DESCRIPTION
312
+ List forms from WordPress
313
+
314
+ EXAMPLES
315
+ $ lps form list
316
+ ```
317
+
318
+ _See code: [src/commands/form/list.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/form/list.ts)_
319
+
320
+ ## `lps form pull [PATH]`
321
+
322
+ Pull forms from WordPress
323
+
324
+ ```
325
+ USAGE
326
+ $ lps form pull [PATH] [-d]
327
+
328
+ ARGUMENTS
329
+ [PATH] Path to forms directory (overrides project config)
330
+
331
+ FLAGS
332
+ -d, --dry-run Show what would change without making changes
333
+
334
+ DESCRIPTION
335
+ Pull forms from WordPress
336
+
337
+ EXAMPLES
338
+ $ lps form pull
339
+ ```
340
+
341
+ _See code: [src/commands/form/pull.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/form/pull.ts)_
342
+
343
+ ## `lps form push [PATH]`
344
+
345
+ Push forms to WordPress. Local files created or updated remotely are renamed on disk to the `<id>-<slug>.json` convention.
346
+
347
+ ```
348
+ USAGE
349
+ $ lps form push [PATH] [-d]
350
+
351
+ ARGUMENTS
352
+ [PATH] Path to forms directory (overrides project config)
353
+
354
+ FLAGS
355
+ -d, --dry-run Show what would change without making changes
356
+
357
+ DESCRIPTION
358
+ Push forms to WordPress. Local files created or updated remotely are renamed on disk to the `<id>-<slug>.json`
359
+ convention.
360
+
361
+ EXAMPLES
362
+ $ lps form push
363
+ ```
364
+
365
+ _See code: [src/commands/form/push.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/form/push.ts)_
220
366
 
221
367
  ## `lps help [COMMAND]`
222
368
 
@@ -253,7 +399,7 @@ EXAMPLES
253
399
  $ lps init
254
400
  ```
255
401
 
256
- _See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/init.ts)_
402
+ _See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/init.ts)_
257
403
 
258
404
  ## `lps login`
259
405
 
@@ -270,7 +416,7 @@ EXAMPLES
270
416
  $ lps login
271
417
  ```
272
418
 
273
- _See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/login.ts)_
419
+ _See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/login.ts)_
274
420
 
275
421
  ## `lps logout`
276
422
 
@@ -287,7 +433,7 @@ EXAMPLES
287
433
  $ lps logout
288
434
  ```
289
435
 
290
- _See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/logout.ts)_
436
+ _See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/logout.ts)_
291
437
 
292
438
  ## `lps plugin add SLUG`
293
439
 
@@ -312,7 +458,7 @@ EXAMPLES
312
458
  $ lps plugin add contact-form-7 --dry-run
313
459
  ```
314
460
 
315
- _See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/plugin/add.ts)_
461
+ _See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/plugin/add.ts)_
316
462
 
317
463
  ## `lps plugin pull`
318
464
 
@@ -334,7 +480,7 @@ EXAMPLES
334
480
  $ lps plugin pull --dry-run
335
481
  ```
336
482
 
337
- _See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/plugin/pull.ts)_
483
+ _See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/plugin/pull.ts)_
338
484
 
339
485
  ## `lps plugin push`
340
486
 
@@ -356,7 +502,7 @@ EXAMPLES
356
502
  $ lps plugin push --dry-run
357
503
  ```
358
504
 
359
- _See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/plugin/push.ts)_
505
+ _See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/plugin/push.ts)_
360
506
 
361
507
  ## `lps project config`
362
508
 
@@ -374,7 +520,7 @@ EXAMPLES
374
520
  $ lps project config
375
521
  ```
376
522
 
377
- _See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/project/config.ts)_
523
+ _See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/project/config.ts)_
378
524
 
379
525
  ## `lps project list`
380
526
 
@@ -391,7 +537,7 @@ EXAMPLES
391
537
  $ lps project list
392
538
  ```
393
539
 
394
- _See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/project/list.ts)_
540
+ _See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/project/list.ts)_
395
541
 
396
542
  ## `lps project pull`
397
543
 
@@ -408,7 +554,7 @@ EXAMPLES
408
554
  $ lps project pull
409
555
  ```
410
556
 
411
- _See code: [src/commands/project/pull.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/project/pull.ts)_
557
+ _See code: [src/commands/project/pull.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/project/pull.ts)_
412
558
 
413
559
  ## `lps project push`
414
560
 
@@ -425,7 +571,7 @@ EXAMPLES
425
571
  $ lps project push
426
572
  ```
427
573
 
428
- _See code: [src/commands/project/push.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/project/push.ts)_
574
+ _See code: [src/commands/project/push.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/project/push.ts)_
429
575
 
430
576
  ## `lps project remove`
431
577
 
@@ -442,7 +588,7 @@ EXAMPLES
442
588
  $ lps project remove
443
589
  ```
444
590
 
445
- _See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/project/remove.ts)_
591
+ _See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/project/remove.ts)_
446
592
 
447
593
  ## `lps project switch`
448
594
 
@@ -459,7 +605,80 @@ EXAMPLES
459
605
  $ lps project switch
460
606
  ```
461
607
 
462
- _See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/project/switch.ts)_
608
+ _See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/project/switch.ts)_
609
+
610
+ ## `lps seo list`
611
+
612
+ List posts with SEO meta, and redirects if supported by the active SEO plugin, on WordPress
613
+
614
+ ```
615
+ USAGE
616
+ $ lps seo list [-j] [--post-type <value>...]
617
+
618
+ FLAGS
619
+ -j, --json Output in JSON format
620
+ --post-type=<value>... Limit to specific post types
621
+
622
+ DESCRIPTION
623
+ List posts with SEO meta, and redirects if supported by the active SEO plugin, on WordPress
624
+
625
+ EXAMPLES
626
+ $ lps seo list
627
+
628
+ $ lps seo list --post-type post
629
+ ```
630
+
631
+ _See code: [src/commands/seo/list.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/seo/list.ts)_
632
+
633
+ ## `lps seo pull [PATH]`
634
+
635
+ Pull SEO settings, post meta, and (if supported) redirects from WordPress
636
+
637
+ ```
638
+ USAGE
639
+ $ lps seo pull [PATH] [-d] [--post-type <value>...]
640
+
641
+ ARGUMENTS
642
+ [PATH] Path to SEO directory (overrides project config)
643
+
644
+ FLAGS
645
+ -d, --dry-run Show what would change without making changes
646
+ --post-type=<value>... Limit post meta to specific post types
647
+
648
+ DESCRIPTION
649
+ Pull SEO settings, post meta, and (if supported) redirects from WordPress
650
+
651
+ EXAMPLES
652
+ $ lps seo pull
653
+
654
+ $ lps seo pull --post-type post --post-type page
655
+ ```
656
+
657
+ _See code: [src/commands/seo/pull.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/seo/pull.ts)_
658
+
659
+ ## `lps seo push [PATH]`
660
+
661
+ Push SEO settings, post meta, and redirects to WordPress. Local redirect files created remotely are renamed on disk to the `<id>-<slug>` convention. Fails clearly per file if the active SEO plugin does not support redirects.
662
+
663
+ ```
664
+ USAGE
665
+ $ lps seo push [PATH] [-d]
666
+
667
+ ARGUMENTS
668
+ [PATH] Path to SEO directory (overrides project config)
669
+
670
+ FLAGS
671
+ -d, --dry-run Show what would change without making changes
672
+
673
+ DESCRIPTION
674
+ Push SEO settings, post meta, and redirects to WordPress. Local redirect files created remotely are renamed on disk to
675
+ the `<id>-<slug>` convention. Fails clearly per file if the active SEO plugin does not support redirects.
676
+
677
+ EXAMPLES
678
+ $ lps seo push
679
+ ```
680
+
681
+ _See code: [src/commands/seo/push.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/seo/push.ts)_
463
682
 
464
683
  ## `lps snippet list`
465
684
 
@@ -479,7 +698,7 @@ EXAMPLES
479
698
  $ lps snippet list
480
699
  ```
481
700
 
482
- _See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/snippet/list.ts)_
701
+ _See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/snippet/list.ts)_
483
702
 
484
703
  ## `lps snippet publish [PATH]`
485
704
 
@@ -502,7 +721,7 @@ EXAMPLES
502
721
  $ lps snippet publish --path ./snippets
503
722
  ```
504
723
 
505
- _See code: [src/commands/snippet/publish.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/snippet/publish.ts)_
724
+ _See code: [src/commands/snippet/publish.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/snippet/publish.ts)_
506
725
 
507
726
  ## `lps snippet pull [PATH]`
508
727
 
@@ -527,7 +746,7 @@ EXAMPLES
527
746
  $ lps snippet pull --path ./snippets
528
747
  ```
529
748
 
530
- _See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/snippet/pull.ts)_
749
+ _See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/snippet/pull.ts)_
531
750
 
532
751
  ## `lps snippet push [PATH]`
533
752
 
@@ -553,7 +772,7 @@ EXAMPLES
553
772
  $ lps snippet push --path ./snippets
554
773
  ```
555
774
 
556
- _See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/snippet/push.ts)_
775
+ _See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/snippet/push.ts)_
557
776
 
558
777
  ## `lps status`
559
778
 
@@ -570,7 +789,7 @@ EXAMPLES
570
789
  $ lps status
571
790
  ```
572
791
 
573
- _See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/status.ts)_
792
+ _See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/status.ts)_
574
793
 
575
794
  ## `lps telemetry disable`
576
795
 
@@ -587,7 +806,7 @@ EXAMPLES
587
806
  $ lps telemetry disable
588
807
  ```
589
808
 
590
- _See code: [src/commands/telemetry/disable.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/telemetry/disable.ts)_
809
+ _See code: [src/commands/telemetry/disable.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/telemetry/disable.ts)_
591
810
 
592
811
  ## `lps telemetry enable`
593
812
 
@@ -604,5 +823,5 @@ EXAMPLES
604
823
  $ lps telemetry enable
605
824
  ```
606
825
 
607
- _See code: [src/commands/telemetry/enable.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/telemetry/enable.ts)_
826
+ _See code: [src/commands/telemetry/enable.ts](https://github.com/loopress/loopress/blob/v0.18.0/src/commands/telemetry/enable.ts)_
608
827
  <!-- commandsstop -->
@@ -0,0 +1,9 @@
1
+ import { LoopressCommand } from '../../lib/base.js';
2
+ export default class List extends LoopressCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,26 @@
1
+ import { Flags } from '@oclif/core';
2
+ import { LoopressCommand } from '../../lib/base.js';
3
+ export default class List extends LoopressCommand {
4
+ static description = 'List custom API route files from WordPress';
5
+ static examples = ['$ lps api list'];
6
+ static flags = {
7
+ json: Flags.boolean({ char: 'j', description: 'Output in JSON format' }),
8
+ };
9
+ async run() {
10
+ const { flags } = await this.parse(List);
11
+ const files = await this.wp.get('loopress/v1/api-files');
12
+ if (flags.json) {
13
+ this.log(JSON.stringify(files, null, 2));
14
+ return;
15
+ }
16
+ if (files.length === 0) {
17
+ this.log('No API route files found');
18
+ return;
19
+ }
20
+ this.log(`Found ${files.length} route file${files.length === 1 ? '' : 's'}:`);
21
+ this.log('');
22
+ for (const file of files) {
23
+ this.log(` ${file.filename}`);
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,13 @@
1
+ import { LoopressCommand } from '../../lib/base.js';
2
+ export default class Pull extends LoopressCommand {
3
+ static args: {
4
+ path: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ 'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ private findOrphanedFiles;
13
+ }
@@ -0,0 +1,64 @@
1
+ import { Args } from '@oclif/core';
2
+ import { Listr } from 'listr2';
3
+ import { mkdir, readdir, rm, writeFile } from 'node:fs/promises';
4
+ import { join } from 'node:path';
5
+ import { LoopressCommand } from '../../lib/base.js';
6
+ export default class Pull extends LoopressCommand {
7
+ static args = {
8
+ path: Args.string({ description: 'Path to api directory (overrides project config)' }),
9
+ };
10
+ static description = 'Pull custom API route files from WordPress';
11
+ static examples = ['$ lps api pull', '$ lps api pull --path ./api'];
12
+ static flags = {
13
+ ...LoopressCommand.dryRunFlag,
14
+ };
15
+ async run() {
16
+ const { args } = await this.parse(Pull);
17
+ const { url } = this.siteConfig;
18
+ const path = this.resolveApiPath(args.path);
19
+ this.log(`Pulling API routes from ${url}`);
20
+ this.log(`API path: ${path}`);
21
+ const files = await this.wp.get('loopress/v1/api-files');
22
+ // Files following the `<filename>.php` convention no longer present remotely belong to
23
+ // a route deleted on WordPress. Left on disk, they'd silently come back to life the next
24
+ // time `api push` runs (see obsidian/Product/Push Deletion Rules.md: push itself stays
25
+ // additive-only, but pull already cleans up locally, same as `snippet pull`).
26
+ const orphans = await this.findOrphanedFiles(path, new Set(files.map((file) => file.filename)));
27
+ if (this.dryRun) {
28
+ this.log(`[dry-run] Would pull ${files.length} route file${files.length === 1 ? '' : 's'} to ${path}`);
29
+ if (orphans.length > 0) {
30
+ this.log(`[dry-run] Would remove ${orphans.length} local file${orphans.length === 1 ? '' : 's'} whose route no longer exists on WordPress: ${orphans.join(', ')}`);
31
+ }
32
+ return;
33
+ }
34
+ await mkdir(path, { recursive: true });
35
+ await new Listr(files.map((file) => ({
36
+ async task(_ctx, task) {
37
+ await writeFile(join(path, `${file.filename}.php`), file.content);
38
+ task.output = `Pulled: ${file.filename}`;
39
+ },
40
+ title: `Pull ${file.filename}`,
41
+ }))).run();
42
+ for (const file of orphans)
43
+ await rm(join(path, file), { force: true });
44
+ if (orphans.length > 0) {
45
+ this.warn(`Removed ${orphans.length} local file${orphans.length === 1 ? '' : 's'} whose route no longer exists on WordPress: ${orphans.join(', ')}`);
46
+ }
47
+ this.log(`Pulled ${files.length} route file${files.length === 1 ? '' : 's'} to ${path}`);
48
+ }
49
+ // Only ever matches `.php` files already following the flat `<filename>.php` convention
50
+ // that `api pull`/`push` themselves produce, so a hand-created non-.php file is never at
51
+ // risk of being picked up here.
52
+ async findOrphanedFiles(path, keepFilenames) {
53
+ let entries;
54
+ try {
55
+ entries = await readdir(path);
56
+ }
57
+ catch (error) {
58
+ if (error.code === 'ENOENT')
59
+ return [];
60
+ throw error;
61
+ }
62
+ return entries.filter((entry) => entry.endsWith('.php') && !keepFilenames.has(entry.slice(0, -4)));
63
+ }
64
+ }
@@ -0,0 +1,15 @@
1
+ import { PushCommand } from '../../lib/push-command.js';
2
+ export default class Push extends PushCommand {
3
+ static args: {
4
+ path: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ 'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ private failedCount;
12
+ run(): Promise<void>;
13
+ private loadFiles;
14
+ private pushFile;
15
+ }
@@ -0,0 +1,76 @@
1
+ import { Args } from '@oclif/core';
2
+ import { Listr } from 'listr2';
3
+ import { readdir, readFile } from 'node:fs/promises';
4
+ import { extname, join } from 'node:path';
5
+ import { PushCommand } from '../../lib/push-command.js';
6
+ export default class Push extends PushCommand {
7
+ static args = {
8
+ path: Args.string({ description: 'Path to api directory (overrides project config)' }),
9
+ };
10
+ static description = 'Push custom API route files to WordPress';
11
+ static examples = ['$ lps api push', '$ lps api push --path ./api'];
12
+ static flags = {
13
+ ...PushCommand.dryRunFlag,
14
+ };
15
+ failedCount = 0;
16
+ async run() {
17
+ const { args } = await this.parse(Push);
18
+ const { url } = this.siteConfig;
19
+ const path = this.resolveApiPath(args.path);
20
+ this.log(`Pushing API routes to ${url}`);
21
+ this.log(`API path: ${path}`);
22
+ const files = await this.loadFiles(path);
23
+ this.log(`Found ${files.length} route file${files.length === 1 ? '' : 's'} to push`);
24
+ await new Listr(files.map((file) => ({
25
+ task: async (_ctx, task) => this.pushFile(file, task),
26
+ title: `Push ${file.filename}`,
27
+ })), { concurrent: false, exitOnError: false }).run();
28
+ if (this.failedCount > 0) {
29
+ this.error(`${this.failedCount} route file${this.failedCount === 1 ? '' : 's'} failed to push.`);
30
+ }
31
+ if (this.dryRun)
32
+ return;
33
+ await this.recordSuccess();
34
+ this.log('All API routes pushed.');
35
+ }
36
+ async loadFiles(path) {
37
+ let entries;
38
+ try {
39
+ entries = await readdir(path);
40
+ }
41
+ catch (error) {
42
+ if (error.code === 'ENOENT')
43
+ return [];
44
+ throw error;
45
+ }
46
+ const files = [];
47
+ for (const entry of entries) {
48
+ if (extname(entry) !== '.php')
49
+ continue;
50
+ const content = await readFile(join(path, entry), 'utf8');
51
+ files.push({ content, filename: entry.slice(0, -4) });
52
+ }
53
+ return files;
54
+ }
55
+ async pushFile(file, task) {
56
+ if (this.dryRun) {
57
+ if (task)
58
+ task.output = `[dry-run] Would push: ${file.filename}`;
59
+ return;
60
+ }
61
+ try {
62
+ await this.wp.put(`loopress/v1/api-files/${file.filename}`, { content: file.content });
63
+ if (task)
64
+ task.output = `Pushed: ${file.filename}`;
65
+ }
66
+ catch (error) {
67
+ const message = `Failed to push ${file.filename}: ${error.message}`;
68
+ if (task)
69
+ task.output = message;
70
+ else
71
+ this.warn(` ${message}`);
72
+ this.failedCount++;
73
+ throw error;
74
+ }
75
+ }
76
+ }