@loopress/cli 0.15.0 → 0.17.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 +204 -24
- package/dist/commands/acf/list.d.ts +10 -0
- package/dist/commands/acf/list.js +36 -0
- package/dist/commands/acf/pull.d.ts +15 -0
- package/dist/commands/acf/pull.js +80 -0
- package/dist/commands/acf/push.d.ts +17 -0
- package/dist/commands/acf/push.js +108 -0
- package/dist/commands/composer/init.d.ts +9 -0
- package/dist/commands/composer/init.js +47 -0
- package/dist/commands/composer/pull.js +7 -4
- package/dist/commands/seo/list.d.ts +11 -0
- package/dist/commands/seo/list.js +60 -0
- package/dist/commands/seo/pull.d.ts +19 -0
- package/dist/commands/seo/pull.js +134 -0
- package/dist/commands/seo/push.d.ts +20 -0
- package/dist/commands/seo/push.js +171 -0
- package/dist/help.js +1 -1
- package/dist/lib/base.d.ts +2 -0
- package/dist/lib/base.js +10 -0
- package/dist/types/project-config.generated.d.ts +8 -0
- package/dist/utils/acf-format.d.ts +4 -0
- package/dist/utils/acf-format.js +12 -0
- package/dist/utils/composer.d.ts +8 -0
- package/dist/utils/plugins.js +5 -3
- package/dist/utils/seo-format.d.ts +20 -0
- package/dist/utils/seo-format.js +10 -0
- package/oclif.manifest.json +475 -134
- package/package.json +7 -1
- package/schemas/project-config.schema.json +10 -0
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.
|
|
24
|
+
@loopress/cli/0.17.0 linux-x64 node-v24.18.0
|
|
25
25
|
$ lps --help [COMMAND]
|
|
26
26
|
USAGE
|
|
27
27
|
$ lps COMMAND
|
|
@@ -47,6 +47,10 @@ report.
|
|
|
47
47
|
# Commands
|
|
48
48
|
|
|
49
49
|
<!-- commands -->
|
|
50
|
+
* [`lps acf list`](#lps-acf-list)
|
|
51
|
+
* [`lps acf pull [PATH]`](#lps-acf-pull-path)
|
|
52
|
+
* [`lps acf push [PATH]`](#lps-acf-push-path)
|
|
53
|
+
* [`lps composer init`](#lps-composer-init)
|
|
50
54
|
* [`lps composer pull`](#lps-composer-pull)
|
|
51
55
|
* [`lps composer push`](#lps-composer-push)
|
|
52
56
|
* [`lps help [COMMAND]`](#lps-help-command)
|
|
@@ -62,6 +66,9 @@ report.
|
|
|
62
66
|
* [`lps project push`](#lps-project-push)
|
|
63
67
|
* [`lps project remove`](#lps-project-remove)
|
|
64
68
|
* [`lps project switch`](#lps-project-switch)
|
|
69
|
+
* [`lps seo list`](#lps-seo-list)
|
|
70
|
+
* [`lps seo pull [PATH]`](#lps-seo-pull-path)
|
|
71
|
+
* [`lps seo push [PATH]`](#lps-seo-push-path)
|
|
65
72
|
* [`lps snippet list`](#lps-snippet-list)
|
|
66
73
|
* [`lps snippet publish [PATH]`](#lps-snippet-publish-path)
|
|
67
74
|
* [`lps snippet pull [PATH]`](#lps-snippet-pull-path)
|
|
@@ -70,9 +77,109 @@ report.
|
|
|
70
77
|
* [`lps telemetry disable`](#lps-telemetry-disable)
|
|
71
78
|
* [`lps telemetry enable`](#lps-telemetry-enable)
|
|
72
79
|
|
|
80
|
+
## `lps acf list`
|
|
81
|
+
|
|
82
|
+
List ACF field groups, post types, taxonomies, and options pages from WordPress
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
USAGE
|
|
86
|
+
$ lps acf list [-j] [--type field-groups|post-types|taxonomies|options-pages...]
|
|
87
|
+
|
|
88
|
+
FLAGS
|
|
89
|
+
-j, --json Output in JSON format
|
|
90
|
+
--type=<option>... Limit to specific ACF object types
|
|
91
|
+
<options: field-groups|post-types|taxonomies|options-pages>
|
|
92
|
+
|
|
93
|
+
DESCRIPTION
|
|
94
|
+
List ACF field groups, post types, taxonomies, and options pages from WordPress
|
|
95
|
+
|
|
96
|
+
EXAMPLES
|
|
97
|
+
$ lps acf list
|
|
98
|
+
|
|
99
|
+
$ lps acf list --type field-groups
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
_See code: [src/commands/acf/list.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/acf/list.ts)_
|
|
103
|
+
|
|
104
|
+
## `lps acf pull [PATH]`
|
|
105
|
+
|
|
106
|
+
Pull ACF field groups, post types, taxonomies, and options pages from WordPress
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
USAGE
|
|
110
|
+
$ lps acf pull [PATH] [-d] [--type field-groups|post-types|taxonomies|options-pages...]
|
|
111
|
+
|
|
112
|
+
ARGUMENTS
|
|
113
|
+
[PATH] Path to ACF directory (overrides project config)
|
|
114
|
+
|
|
115
|
+
FLAGS
|
|
116
|
+
-d, --dry-run Show what would change without making changes
|
|
117
|
+
--type=<option>... Limit to specific ACF object types
|
|
118
|
+
<options: field-groups|post-types|taxonomies|options-pages>
|
|
119
|
+
|
|
120
|
+
DESCRIPTION
|
|
121
|
+
Pull ACF field groups, post types, taxonomies, and options pages from WordPress
|
|
122
|
+
|
|
123
|
+
EXAMPLES
|
|
124
|
+
$ lps acf pull
|
|
125
|
+
|
|
126
|
+
$ lps acf pull --type field-groups
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
_See code: [src/commands/acf/pull.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/acf/pull.ts)_
|
|
130
|
+
|
|
131
|
+
## `lps acf push [PATH]`
|
|
132
|
+
|
|
133
|
+
Push ACF field groups, post types, taxonomies, and options pages to WordPress
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
USAGE
|
|
137
|
+
$ lps acf push [PATH] [-d] [--type field-groups|post-types|taxonomies|options-pages...]
|
|
138
|
+
|
|
139
|
+
ARGUMENTS
|
|
140
|
+
[PATH] Path to ACF directory (overrides project config)
|
|
141
|
+
|
|
142
|
+
FLAGS
|
|
143
|
+
-d, --dry-run Show what would change without making changes
|
|
144
|
+
--type=<option>... Limit to specific ACF object types
|
|
145
|
+
<options: field-groups|post-types|taxonomies|options-pages>
|
|
146
|
+
|
|
147
|
+
DESCRIPTION
|
|
148
|
+
Push ACF field groups, post types, taxonomies, and options pages to WordPress
|
|
149
|
+
|
|
150
|
+
EXAMPLES
|
|
151
|
+
$ lps acf push
|
|
152
|
+
|
|
153
|
+
$ lps acf push --type field-groups
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
_See code: [src/commands/acf/push.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/acf/push.ts)_
|
|
157
|
+
|
|
158
|
+
## `lps composer init`
|
|
159
|
+
|
|
160
|
+
Create a composer.json wired to WPackagist for installing WordPress.org plugins and themes
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
USAGE
|
|
164
|
+
$ lps composer init [-d]
|
|
165
|
+
|
|
166
|
+
FLAGS
|
|
167
|
+
-d, --dry-run Show what would change without making changes
|
|
168
|
+
|
|
169
|
+
DESCRIPTION
|
|
170
|
+
Create a composer.json wired to WPackagist for installing WordPress.org plugins and themes
|
|
171
|
+
|
|
172
|
+
EXAMPLES
|
|
173
|
+
$ lps composer init
|
|
174
|
+
|
|
175
|
+
$ lps composer init --dry-run
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
_See code: [src/commands/composer/init.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/composer/init.ts)_
|
|
179
|
+
|
|
73
180
|
## `lps composer pull`
|
|
74
181
|
|
|
75
|
-
Pull composer.lock from WordPress
|
|
182
|
+
Pull composer.json and composer.lock from WordPress
|
|
76
183
|
|
|
77
184
|
```
|
|
78
185
|
USAGE
|
|
@@ -82,7 +189,7 @@ FLAGS
|
|
|
82
189
|
-d, --dry-run Show what would change without making changes
|
|
83
190
|
|
|
84
191
|
DESCRIPTION
|
|
85
|
-
Pull composer.lock from WordPress
|
|
192
|
+
Pull composer.json and composer.lock from WordPress
|
|
86
193
|
|
|
87
194
|
EXAMPLES
|
|
88
195
|
$ lps composer pull
|
|
@@ -90,7 +197,7 @@ EXAMPLES
|
|
|
90
197
|
$ lps composer pull --dry-run
|
|
91
198
|
```
|
|
92
199
|
|
|
93
|
-
_See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.
|
|
200
|
+
_See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/composer/pull.ts)_
|
|
94
201
|
|
|
95
202
|
## `lps composer push`
|
|
96
203
|
|
|
@@ -112,7 +219,7 @@ EXAMPLES
|
|
|
112
219
|
$ lps composer push --dry-run
|
|
113
220
|
```
|
|
114
221
|
|
|
115
|
-
_See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.
|
|
222
|
+
_See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/composer/push.ts)_
|
|
116
223
|
|
|
117
224
|
## `lps help [COMMAND]`
|
|
118
225
|
|
|
@@ -149,7 +256,7 @@ EXAMPLES
|
|
|
149
256
|
$ lps init
|
|
150
257
|
```
|
|
151
258
|
|
|
152
|
-
_See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.
|
|
259
|
+
_See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/init.ts)_
|
|
153
260
|
|
|
154
261
|
## `lps login`
|
|
155
262
|
|
|
@@ -166,7 +273,7 @@ EXAMPLES
|
|
|
166
273
|
$ lps login
|
|
167
274
|
```
|
|
168
275
|
|
|
169
|
-
_See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.
|
|
276
|
+
_See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/login.ts)_
|
|
170
277
|
|
|
171
278
|
## `lps logout`
|
|
172
279
|
|
|
@@ -183,7 +290,7 @@ EXAMPLES
|
|
|
183
290
|
$ lps logout
|
|
184
291
|
```
|
|
185
292
|
|
|
186
|
-
_See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.
|
|
293
|
+
_See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/logout.ts)_
|
|
187
294
|
|
|
188
295
|
## `lps plugin add SLUG`
|
|
189
296
|
|
|
@@ -208,7 +315,7 @@ EXAMPLES
|
|
|
208
315
|
$ lps plugin add contact-form-7 --dry-run
|
|
209
316
|
```
|
|
210
317
|
|
|
211
|
-
_See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.
|
|
318
|
+
_See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/plugin/add.ts)_
|
|
212
319
|
|
|
213
320
|
## `lps plugin pull`
|
|
214
321
|
|
|
@@ -230,7 +337,7 @@ EXAMPLES
|
|
|
230
337
|
$ lps plugin pull --dry-run
|
|
231
338
|
```
|
|
232
339
|
|
|
233
|
-
_See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.
|
|
340
|
+
_See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/plugin/pull.ts)_
|
|
234
341
|
|
|
235
342
|
## `lps plugin push`
|
|
236
343
|
|
|
@@ -252,7 +359,7 @@ EXAMPLES
|
|
|
252
359
|
$ lps plugin push --dry-run
|
|
253
360
|
```
|
|
254
361
|
|
|
255
|
-
_See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.
|
|
362
|
+
_See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/plugin/push.ts)_
|
|
256
363
|
|
|
257
364
|
## `lps project config`
|
|
258
365
|
|
|
@@ -270,7 +377,7 @@ EXAMPLES
|
|
|
270
377
|
$ lps project config
|
|
271
378
|
```
|
|
272
379
|
|
|
273
|
-
_See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.
|
|
380
|
+
_See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/project/config.ts)_
|
|
274
381
|
|
|
275
382
|
## `lps project list`
|
|
276
383
|
|
|
@@ -287,7 +394,7 @@ EXAMPLES
|
|
|
287
394
|
$ lps project list
|
|
288
395
|
```
|
|
289
396
|
|
|
290
|
-
_See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.
|
|
397
|
+
_See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/project/list.ts)_
|
|
291
398
|
|
|
292
399
|
## `lps project pull`
|
|
293
400
|
|
|
@@ -304,7 +411,7 @@ EXAMPLES
|
|
|
304
411
|
$ lps project pull
|
|
305
412
|
```
|
|
306
413
|
|
|
307
|
-
_See code: [src/commands/project/pull.ts](https://github.com/loopress/loopress/blob/v0.
|
|
414
|
+
_See code: [src/commands/project/pull.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/project/pull.ts)_
|
|
308
415
|
|
|
309
416
|
## `lps project push`
|
|
310
417
|
|
|
@@ -321,7 +428,7 @@ EXAMPLES
|
|
|
321
428
|
$ lps project push
|
|
322
429
|
```
|
|
323
430
|
|
|
324
|
-
_See code: [src/commands/project/push.ts](https://github.com/loopress/loopress/blob/v0.
|
|
431
|
+
_See code: [src/commands/project/push.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/project/push.ts)_
|
|
325
432
|
|
|
326
433
|
## `lps project remove`
|
|
327
434
|
|
|
@@ -338,7 +445,7 @@ EXAMPLES
|
|
|
338
445
|
$ lps project remove
|
|
339
446
|
```
|
|
340
447
|
|
|
341
|
-
_See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.
|
|
448
|
+
_See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/project/remove.ts)_
|
|
342
449
|
|
|
343
450
|
## `lps project switch`
|
|
344
451
|
|
|
@@ -355,7 +462,80 @@ EXAMPLES
|
|
|
355
462
|
$ lps project switch
|
|
356
463
|
```
|
|
357
464
|
|
|
358
|
-
_See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.
|
|
465
|
+
_See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/project/switch.ts)_
|
|
466
|
+
|
|
467
|
+
## `lps seo list`
|
|
468
|
+
|
|
469
|
+
List posts with SEO meta, and redirects if supported by the active SEO plugin, on WordPress
|
|
470
|
+
|
|
471
|
+
```
|
|
472
|
+
USAGE
|
|
473
|
+
$ lps seo list [-j] [--post-type <value>...]
|
|
474
|
+
|
|
475
|
+
FLAGS
|
|
476
|
+
-j, --json Output in JSON format
|
|
477
|
+
--post-type=<value>... Limit to specific post types
|
|
478
|
+
|
|
479
|
+
DESCRIPTION
|
|
480
|
+
List posts with SEO meta, and redirects if supported by the active SEO plugin, on WordPress
|
|
481
|
+
|
|
482
|
+
EXAMPLES
|
|
483
|
+
$ lps seo list
|
|
484
|
+
|
|
485
|
+
$ lps seo list --post-type post
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
_See code: [src/commands/seo/list.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/seo/list.ts)_
|
|
489
|
+
|
|
490
|
+
## `lps seo pull [PATH]`
|
|
491
|
+
|
|
492
|
+
Pull SEO settings, post meta, and (if supported) redirects from WordPress
|
|
493
|
+
|
|
494
|
+
```
|
|
495
|
+
USAGE
|
|
496
|
+
$ lps seo pull [PATH] [-d] [--post-type <value>...]
|
|
497
|
+
|
|
498
|
+
ARGUMENTS
|
|
499
|
+
[PATH] Path to SEO directory (overrides project config)
|
|
500
|
+
|
|
501
|
+
FLAGS
|
|
502
|
+
-d, --dry-run Show what would change without making changes
|
|
503
|
+
--post-type=<value>... Limit post meta to specific post types
|
|
504
|
+
|
|
505
|
+
DESCRIPTION
|
|
506
|
+
Pull SEO settings, post meta, and (if supported) redirects from WordPress
|
|
507
|
+
|
|
508
|
+
EXAMPLES
|
|
509
|
+
$ lps seo pull
|
|
510
|
+
|
|
511
|
+
$ lps seo pull --post-type post --post-type page
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
_See code: [src/commands/seo/pull.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/seo/pull.ts)_
|
|
515
|
+
|
|
516
|
+
## `lps seo push [PATH]`
|
|
517
|
+
|
|
518
|
+
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.
|
|
519
|
+
|
|
520
|
+
```
|
|
521
|
+
USAGE
|
|
522
|
+
$ lps seo push [PATH] [-d]
|
|
523
|
+
|
|
524
|
+
ARGUMENTS
|
|
525
|
+
[PATH] Path to SEO directory (overrides project config)
|
|
526
|
+
|
|
527
|
+
FLAGS
|
|
528
|
+
-d, --dry-run Show what would change without making changes
|
|
529
|
+
|
|
530
|
+
DESCRIPTION
|
|
531
|
+
Push SEO settings, post meta, and redirects to WordPress. Local redirect files created remotely are renamed on disk to
|
|
532
|
+
the `<id>-<slug>` convention. Fails clearly per file if the active SEO plugin does not support redirects.
|
|
533
|
+
|
|
534
|
+
EXAMPLES
|
|
535
|
+
$ lps seo push
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
_See code: [src/commands/seo/push.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/seo/push.ts)_
|
|
359
539
|
|
|
360
540
|
## `lps snippet list`
|
|
361
541
|
|
|
@@ -375,7 +555,7 @@ EXAMPLES
|
|
|
375
555
|
$ lps snippet list
|
|
376
556
|
```
|
|
377
557
|
|
|
378
|
-
_See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.
|
|
558
|
+
_See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/snippet/list.ts)_
|
|
379
559
|
|
|
380
560
|
## `lps snippet publish [PATH]`
|
|
381
561
|
|
|
@@ -398,7 +578,7 @@ EXAMPLES
|
|
|
398
578
|
$ lps snippet publish --path ./snippets
|
|
399
579
|
```
|
|
400
580
|
|
|
401
|
-
_See code: [src/commands/snippet/publish.ts](https://github.com/loopress/loopress/blob/v0.
|
|
581
|
+
_See code: [src/commands/snippet/publish.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/snippet/publish.ts)_
|
|
402
582
|
|
|
403
583
|
## `lps snippet pull [PATH]`
|
|
404
584
|
|
|
@@ -423,7 +603,7 @@ EXAMPLES
|
|
|
423
603
|
$ lps snippet pull --path ./snippets
|
|
424
604
|
```
|
|
425
605
|
|
|
426
|
-
_See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.
|
|
606
|
+
_See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/snippet/pull.ts)_
|
|
427
607
|
|
|
428
608
|
## `lps snippet push [PATH]`
|
|
429
609
|
|
|
@@ -449,7 +629,7 @@ EXAMPLES
|
|
|
449
629
|
$ lps snippet push --path ./snippets
|
|
450
630
|
```
|
|
451
631
|
|
|
452
|
-
_See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.
|
|
632
|
+
_See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/snippet/push.ts)_
|
|
453
633
|
|
|
454
634
|
## `lps status`
|
|
455
635
|
|
|
@@ -466,7 +646,7 @@ EXAMPLES
|
|
|
466
646
|
$ lps status
|
|
467
647
|
```
|
|
468
648
|
|
|
469
|
-
_See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.
|
|
649
|
+
_See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/status.ts)_
|
|
470
650
|
|
|
471
651
|
## `lps telemetry disable`
|
|
472
652
|
|
|
@@ -483,7 +663,7 @@ EXAMPLES
|
|
|
483
663
|
$ lps telemetry disable
|
|
484
664
|
```
|
|
485
665
|
|
|
486
|
-
_See code: [src/commands/telemetry/disable.ts](https://github.com/loopress/loopress/blob/v0.
|
|
666
|
+
_See code: [src/commands/telemetry/disable.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/telemetry/disable.ts)_
|
|
487
667
|
|
|
488
668
|
## `lps telemetry enable`
|
|
489
669
|
|
|
@@ -500,5 +680,5 @@ EXAMPLES
|
|
|
500
680
|
$ lps telemetry enable
|
|
501
681
|
```
|
|
502
682
|
|
|
503
|
-
_See code: [src/commands/telemetry/enable.ts](https://github.com/loopress/loopress/blob/v0.
|
|
683
|
+
_See code: [src/commands/telemetry/enable.ts](https://github.com/loopress/loopress/blob/v0.17.0/src/commands/telemetry/enable.ts)_
|
|
504
684
|
<!-- commandsstop -->
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
type: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { LoopressCommand } from '../../lib/base.js';
|
|
3
|
+
import { ACF_OBJECT_TYPES, acfEndpoint, getAcfKey } from '../../utils/acf-format.js';
|
|
4
|
+
export default class List extends LoopressCommand {
|
|
5
|
+
static description = 'List ACF field groups, post types, taxonomies, and options pages from WordPress';
|
|
6
|
+
static examples = ['$ lps acf list', '$ lps acf list --type field-groups'];
|
|
7
|
+
static flags = {
|
|
8
|
+
json: Flags.boolean({ char: 'j', description: 'Output in JSON format' }),
|
|
9
|
+
type: Flags.string({ description: 'Limit to specific ACF object types', multiple: true, options: ACF_OBJECT_TYPES }),
|
|
10
|
+
};
|
|
11
|
+
async run() {
|
|
12
|
+
const { flags } = await this.parse(List);
|
|
13
|
+
const types = (flags.type && flags.type.length > 0 ? flags.type : ACF_OBJECT_TYPES);
|
|
14
|
+
const byType = {};
|
|
15
|
+
for (const type of types) {
|
|
16
|
+
byType[type] = await this.wp.get(acfEndpoint(type));
|
|
17
|
+
}
|
|
18
|
+
if (flags.json) {
|
|
19
|
+
this.log(JSON.stringify(byType, null, 2));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
for (const type of types) {
|
|
23
|
+
const objects = byType[type];
|
|
24
|
+
this.log(`${type} (${objects.length}):`);
|
|
25
|
+
if (objects.length === 0) {
|
|
26
|
+
this.log(' (none)');
|
|
27
|
+
this.log('');
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
for (const object of objects) {
|
|
31
|
+
this.log(` ${getAcfKey(object) ?? '(no key)'}. ${String(object.title ?? '(untitled)')}`);
|
|
32
|
+
}
|
|
33
|
+
this.log('');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
type: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
private findOrphanedFiles;
|
|
14
|
+
private pullType;
|
|
15
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { Listr } from 'listr2';
|
|
3
|
+
import { mkdir, readdir, rm, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { extname, join } from 'node:path';
|
|
5
|
+
import { LoopressCommand } from '../../lib/base.js';
|
|
6
|
+
import { ACF_OBJECT_TYPES, acfEndpoint, getAcfKey } from '../../utils/acf-format.js';
|
|
7
|
+
export default class Pull extends LoopressCommand {
|
|
8
|
+
static args = {
|
|
9
|
+
path: Args.string({ description: 'Path to ACF directory (overrides project config)' }),
|
|
10
|
+
};
|
|
11
|
+
static description = 'Pull ACF field groups, post types, taxonomies, and options pages from WordPress';
|
|
12
|
+
static examples = ['$ lps acf pull', '$ lps acf pull --type field-groups'];
|
|
13
|
+
static flags = {
|
|
14
|
+
...LoopressCommand.dryRunFlag,
|
|
15
|
+
type: Flags.string({ description: 'Limit to specific ACF object types', multiple: true, options: ACF_OBJECT_TYPES }),
|
|
16
|
+
};
|
|
17
|
+
async run() {
|
|
18
|
+
const { args, flags } = await this.parse(Pull);
|
|
19
|
+
const { url } = this.siteConfig;
|
|
20
|
+
const path = this.resolveAcfPath(args.path);
|
|
21
|
+
const types = (flags.type && flags.type.length > 0 ? flags.type : ACF_OBJECT_TYPES);
|
|
22
|
+
this.log(`Pulling ACF configuration from ${url}`);
|
|
23
|
+
this.log(`ACF path: ${path}`);
|
|
24
|
+
for (const type of types) {
|
|
25
|
+
await this.pullType(type, path);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Every file in a type's subdirectory is unambiguously `<key>.json` — unlike snippets, ACF
|
|
29
|
+
// objects have no numeric-id/slug filename convention. `key` is the stable identity ACF
|
|
30
|
+
// itself already uses for this (see its own Local JSON mechanism), so orphan detection is a
|
|
31
|
+
// plain set difference, no regex/extension juggling needed.
|
|
32
|
+
async findOrphanedFiles(dir, keepKeys) {
|
|
33
|
+
let files;
|
|
34
|
+
try {
|
|
35
|
+
files = await readdir(dir);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (error.code === 'ENOENT')
|
|
39
|
+
return [];
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
return files.filter((file) => extname(file) === '.json' && !keepKeys.has(file.slice(0, -'.json'.length)));
|
|
43
|
+
}
|
|
44
|
+
async pullType(type, basePath) {
|
|
45
|
+
const dir = join(basePath, type);
|
|
46
|
+
const remoteList = await this.wp.get(acfEndpoint(type));
|
|
47
|
+
const withKey = remoteList.filter((object) => getAcfKey(object) !== null);
|
|
48
|
+
const skipped = remoteList.length - withKey.length;
|
|
49
|
+
const orphans = await this.findOrphanedFiles(dir, new Set(withKey.map((object) => getAcfKey(object))));
|
|
50
|
+
if (this.dryRun) {
|
|
51
|
+
this.log(`[dry-run] Would pull ${withKey.length} ${type} to ${dir}`);
|
|
52
|
+
if (orphans.length > 0) {
|
|
53
|
+
this.log(`[dry-run] Would remove ${orphans.length} local file${orphans.length === 1 ? '' : 's'} in ${dir} no longer present on WordPress: ${orphans.join(', ')}`);
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (withKey.length > 0)
|
|
58
|
+
await mkdir(dir, { recursive: true });
|
|
59
|
+
await new Listr(withKey.map((object) => {
|
|
60
|
+
const key = getAcfKey(object);
|
|
61
|
+
return {
|
|
62
|
+
async task(_ctx, task) {
|
|
63
|
+
await writeFile(join(dir, `${key}.json`), JSON.stringify(object, null, 2) + '\n');
|
|
64
|
+
task.output = `Pulled: ${key}`;
|
|
65
|
+
},
|
|
66
|
+
title: `Pull ${key}`,
|
|
67
|
+
};
|
|
68
|
+
})).run();
|
|
69
|
+
for (const file of orphans) {
|
|
70
|
+
await rm(join(dir, file), { force: true });
|
|
71
|
+
}
|
|
72
|
+
if (orphans.length > 0) {
|
|
73
|
+
this.warn(`Removed ${orphans.length} local file${orphans.length === 1 ? '' : 's'} in ${dir} no longer present on WordPress: ${orphans.join(', ')}`);
|
|
74
|
+
}
|
|
75
|
+
this.log(`Pulled ${withKey.length} ${type} to ${dir}`);
|
|
76
|
+
if (skipped > 0) {
|
|
77
|
+
this.warn(`${skipped} ${type} skipped because they have no key`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
type: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
private failedCount;
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
private loadObjects;
|
|
15
|
+
private pushObject;
|
|
16
|
+
private pushType;
|
|
17
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Args, Flags } 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
|
+
import { ACF_OBJECT_TYPES, acfEndpoint, getAcfKey } from '../../utils/acf-format.js';
|
|
7
|
+
export default class Push extends PushCommand {
|
|
8
|
+
static args = {
|
|
9
|
+
path: Args.string({ description: 'Path to ACF directory (overrides project config)' }),
|
|
10
|
+
};
|
|
11
|
+
static description = 'Push ACF field groups, post types, taxonomies, and options pages to WordPress';
|
|
12
|
+
static examples = ['$ lps acf push', '$ lps acf push --type field-groups'];
|
|
13
|
+
static flags = {
|
|
14
|
+
...PushCommand.dryRunFlag,
|
|
15
|
+
type: Flags.string({ description: 'Limit to specific ACF object types', multiple: true, options: ACF_OBJECT_TYPES }),
|
|
16
|
+
};
|
|
17
|
+
failedCount = 0;
|
|
18
|
+
async run() {
|
|
19
|
+
const { args, flags } = await this.parse(Push);
|
|
20
|
+
const { url } = this.siteConfig;
|
|
21
|
+
const path = this.resolveAcfPath(args.path);
|
|
22
|
+
const types = (flags.type && flags.type.length > 0 ? flags.type : ACF_OBJECT_TYPES);
|
|
23
|
+
this.log(`Pushing ACF configuration to ${url}`);
|
|
24
|
+
this.log(`ACF path: ${path}`);
|
|
25
|
+
for (const type of types) {
|
|
26
|
+
await this.pushType(type, path);
|
|
27
|
+
}
|
|
28
|
+
if (this.failedCount > 0) {
|
|
29
|
+
this.error(`${this.failedCount} ACF object${this.failedCount === 1 ? '' : 's'} failed to push.`);
|
|
30
|
+
}
|
|
31
|
+
if (this.dryRun)
|
|
32
|
+
return;
|
|
33
|
+
await this.recordSuccess();
|
|
34
|
+
this.log('All ACF objects pushed.');
|
|
35
|
+
}
|
|
36
|
+
// One object's file is read in isolation: a corrupted or hand-broken JSON file (or one
|
|
37
|
+
// missing/emptying its "key") must only skip that object, not abort loading the rest of
|
|
38
|
+
// the type's directory — same principle as loadSnippets() for the snippet feature.
|
|
39
|
+
async loadObjects(dir) {
|
|
40
|
+
let files;
|
|
41
|
+
try {
|
|
42
|
+
files = await readdir(dir);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (error.code === 'ENOENT')
|
|
46
|
+
return [];
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
const objects = [];
|
|
50
|
+
for (const file of files) {
|
|
51
|
+
if (extname(file) !== '.json')
|
|
52
|
+
continue;
|
|
53
|
+
const filePath = join(dir, file);
|
|
54
|
+
let parsed;
|
|
55
|
+
try {
|
|
56
|
+
parsed = JSON.parse(await readFile(filePath, 'utf8'));
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
this.warn(`Skipping "${filePath}": ${error.message}`);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (typeof parsed !== 'object' || parsed === null || getAcfKey(parsed) === null) {
|
|
63
|
+
this.warn(`Skipping "${filePath}": missing or invalid "key"`);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
objects.push(parsed);
|
|
67
|
+
}
|
|
68
|
+
return objects;
|
|
69
|
+
}
|
|
70
|
+
// Throwing on failure (rather than returning a boolean) is what lets Listr mark the task as
|
|
71
|
+
// failed (red cross) instead of completed; `exitOnError: false` on the task list still lets
|
|
72
|
+
// sibling objects push regardless. POST alone covers create-or-update (the controller resolves
|
|
73
|
+
// that server-side via the object's `key`), unlike snippet push there's no numeric-id PUT/404
|
|
74
|
+
// fallback dance, and no rename-on-push step since `key` is permanently stable.
|
|
75
|
+
async pushObject(type, object, task) {
|
|
76
|
+
const key = getAcfKey(object) ?? '(unknown)';
|
|
77
|
+
if (this.dryRun) {
|
|
78
|
+
if (task)
|
|
79
|
+
task.output = `[dry-run] Would push: ${key}`;
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
await this.wp.post(acfEndpoint(type), object);
|
|
84
|
+
if (task)
|
|
85
|
+
task.output = `Pushed: ${key}`;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
const message = `Failed to push ${key}: ${error.message}`;
|
|
89
|
+
if (task)
|
|
90
|
+
task.output = message;
|
|
91
|
+
else
|
|
92
|
+
this.warn(` ${message}`);
|
|
93
|
+
this.failedCount++;
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async pushType(type, basePath) {
|
|
98
|
+
const dir = join(basePath, type);
|
|
99
|
+
const objects = await this.loadObjects(dir);
|
|
100
|
+
if (objects.length === 0)
|
|
101
|
+
return;
|
|
102
|
+
this.log(`Found ${objects.length} ${type} to push`);
|
|
103
|
+
await new Listr(objects.map((object) => ({
|
|
104
|
+
task: async (_ctx, task) => this.pushObject(type, object, task),
|
|
105
|
+
title: `Push ${getAcfKey(object) ?? '(unknown)'}`,
|
|
106
|
+
})), { concurrent: false, exitOnError: false }).run();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { LoopressCommand } from '../../lib/base.js';
|
|
2
|
+
export default class ComposerInit extends LoopressCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
};
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
}
|