@loopress/cli 0.14.0 → 0.16.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 +161 -39
- 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/project/pull.d.ts +8 -0
- package/dist/commands/project/pull.js +69 -0
- package/dist/commands/project/{sync.d.ts → push.d.ts} +1 -2
- package/dist/commands/project/{sync.js → push.js} +8 -44
- package/dist/commands/snippet/publish.js +1 -1
- package/dist/config/project-config.manager.js +4 -4
- package/dist/help.js +1 -1
- package/dist/hooks/finally.js +7 -2
- package/dist/lib/base.d.ts +1 -0
- package/dist/lib/base.js +5 -0
- package/dist/lib/sentry.d.ts +1 -0
- package/dist/lib/sentry.js +11 -0
- package/dist/types/global-config.generated.d.ts +2 -2
- package/dist/types/project-config.generated.d.ts +4 -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/oclif.manifest.json +283 -55
- package/package.json +4 -1
- package/schemas/global-config.schema.json +2 -2
- package/schemas/project-config.schema.json +5 -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.16.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)
|
|
@@ -58,9 +62,10 @@ report.
|
|
|
58
62
|
* [`lps plugin push`](#lps-plugin-push)
|
|
59
63
|
* [`lps project config`](#lps-project-config)
|
|
60
64
|
* [`lps project list`](#lps-project-list)
|
|
65
|
+
* [`lps project pull`](#lps-project-pull)
|
|
66
|
+
* [`lps project push`](#lps-project-push)
|
|
61
67
|
* [`lps project remove`](#lps-project-remove)
|
|
62
68
|
* [`lps project switch`](#lps-project-switch)
|
|
63
|
-
* [`lps project sync`](#lps-project-sync)
|
|
64
69
|
* [`lps snippet list`](#lps-snippet-list)
|
|
65
70
|
* [`lps snippet publish [PATH]`](#lps-snippet-publish-path)
|
|
66
71
|
* [`lps snippet pull [PATH]`](#lps-snippet-pull-path)
|
|
@@ -69,9 +74,109 @@ report.
|
|
|
69
74
|
* [`lps telemetry disable`](#lps-telemetry-disable)
|
|
70
75
|
* [`lps telemetry enable`](#lps-telemetry-enable)
|
|
71
76
|
|
|
77
|
+
## `lps acf list`
|
|
78
|
+
|
|
79
|
+
List ACF field groups, post types, taxonomies, and options pages from WordPress
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
USAGE
|
|
83
|
+
$ lps acf list [-j] [--type field-groups|post-types|taxonomies|options-pages...]
|
|
84
|
+
|
|
85
|
+
FLAGS
|
|
86
|
+
-j, --json Output in JSON format
|
|
87
|
+
--type=<option>... Limit to specific ACF object types
|
|
88
|
+
<options: field-groups|post-types|taxonomies|options-pages>
|
|
89
|
+
|
|
90
|
+
DESCRIPTION
|
|
91
|
+
List ACF field groups, post types, taxonomies, and options pages from WordPress
|
|
92
|
+
|
|
93
|
+
EXAMPLES
|
|
94
|
+
$ lps acf list
|
|
95
|
+
|
|
96
|
+
$ lps acf list --type field-groups
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
_See code: [src/commands/acf/list.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/acf/list.ts)_
|
|
100
|
+
|
|
101
|
+
## `lps acf pull [PATH]`
|
|
102
|
+
|
|
103
|
+
Pull ACF field groups, post types, taxonomies, and options pages from WordPress
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
USAGE
|
|
107
|
+
$ lps acf pull [PATH] [-d] [--type field-groups|post-types|taxonomies|options-pages...]
|
|
108
|
+
|
|
109
|
+
ARGUMENTS
|
|
110
|
+
[PATH] Path to ACF directory (overrides project config)
|
|
111
|
+
|
|
112
|
+
FLAGS
|
|
113
|
+
-d, --dry-run Show what would change without making changes
|
|
114
|
+
--type=<option>... Limit to specific ACF object types
|
|
115
|
+
<options: field-groups|post-types|taxonomies|options-pages>
|
|
116
|
+
|
|
117
|
+
DESCRIPTION
|
|
118
|
+
Pull ACF field groups, post types, taxonomies, and options pages from WordPress
|
|
119
|
+
|
|
120
|
+
EXAMPLES
|
|
121
|
+
$ lps acf pull
|
|
122
|
+
|
|
123
|
+
$ lps acf pull --type field-groups
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
_See code: [src/commands/acf/pull.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/acf/pull.ts)_
|
|
127
|
+
|
|
128
|
+
## `lps acf push [PATH]`
|
|
129
|
+
|
|
130
|
+
Push ACF field groups, post types, taxonomies, and options pages to WordPress
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
USAGE
|
|
134
|
+
$ lps acf push [PATH] [-d] [--type field-groups|post-types|taxonomies|options-pages...]
|
|
135
|
+
|
|
136
|
+
ARGUMENTS
|
|
137
|
+
[PATH] Path to ACF directory (overrides project config)
|
|
138
|
+
|
|
139
|
+
FLAGS
|
|
140
|
+
-d, --dry-run Show what would change without making changes
|
|
141
|
+
--type=<option>... Limit to specific ACF object types
|
|
142
|
+
<options: field-groups|post-types|taxonomies|options-pages>
|
|
143
|
+
|
|
144
|
+
DESCRIPTION
|
|
145
|
+
Push ACF field groups, post types, taxonomies, and options pages to WordPress
|
|
146
|
+
|
|
147
|
+
EXAMPLES
|
|
148
|
+
$ lps acf push
|
|
149
|
+
|
|
150
|
+
$ lps acf push --type field-groups
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
_See code: [src/commands/acf/push.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/acf/push.ts)_
|
|
154
|
+
|
|
155
|
+
## `lps composer init`
|
|
156
|
+
|
|
157
|
+
Create a composer.json wired to WPackagist for installing WordPress.org plugins and themes
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
USAGE
|
|
161
|
+
$ lps composer init [-d]
|
|
162
|
+
|
|
163
|
+
FLAGS
|
|
164
|
+
-d, --dry-run Show what would change without making changes
|
|
165
|
+
|
|
166
|
+
DESCRIPTION
|
|
167
|
+
Create a composer.json wired to WPackagist for installing WordPress.org plugins and themes
|
|
168
|
+
|
|
169
|
+
EXAMPLES
|
|
170
|
+
$ lps composer init
|
|
171
|
+
|
|
172
|
+
$ lps composer init --dry-run
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
_See code: [src/commands/composer/init.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/composer/init.ts)_
|
|
176
|
+
|
|
72
177
|
## `lps composer pull`
|
|
73
178
|
|
|
74
|
-
Pull composer.lock from WordPress
|
|
179
|
+
Pull composer.json and composer.lock from WordPress
|
|
75
180
|
|
|
76
181
|
```
|
|
77
182
|
USAGE
|
|
@@ -81,7 +186,7 @@ FLAGS
|
|
|
81
186
|
-d, --dry-run Show what would change without making changes
|
|
82
187
|
|
|
83
188
|
DESCRIPTION
|
|
84
|
-
Pull composer.lock from WordPress
|
|
189
|
+
Pull composer.json and composer.lock from WordPress
|
|
85
190
|
|
|
86
191
|
EXAMPLES
|
|
87
192
|
$ lps composer pull
|
|
@@ -89,7 +194,7 @@ EXAMPLES
|
|
|
89
194
|
$ lps composer pull --dry-run
|
|
90
195
|
```
|
|
91
196
|
|
|
92
|
-
_See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.
|
|
197
|
+
_See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/composer/pull.ts)_
|
|
93
198
|
|
|
94
199
|
## `lps composer push`
|
|
95
200
|
|
|
@@ -111,7 +216,7 @@ EXAMPLES
|
|
|
111
216
|
$ lps composer push --dry-run
|
|
112
217
|
```
|
|
113
218
|
|
|
114
|
-
_See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.
|
|
219
|
+
_See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/composer/push.ts)_
|
|
115
220
|
|
|
116
221
|
## `lps help [COMMAND]`
|
|
117
222
|
|
|
@@ -148,7 +253,7 @@ EXAMPLES
|
|
|
148
253
|
$ lps init
|
|
149
254
|
```
|
|
150
255
|
|
|
151
|
-
_See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.
|
|
256
|
+
_See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/init.ts)_
|
|
152
257
|
|
|
153
258
|
## `lps login`
|
|
154
259
|
|
|
@@ -165,7 +270,7 @@ EXAMPLES
|
|
|
165
270
|
$ lps login
|
|
166
271
|
```
|
|
167
272
|
|
|
168
|
-
_See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.
|
|
273
|
+
_See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/login.ts)_
|
|
169
274
|
|
|
170
275
|
## `lps logout`
|
|
171
276
|
|
|
@@ -182,7 +287,7 @@ EXAMPLES
|
|
|
182
287
|
$ lps logout
|
|
183
288
|
```
|
|
184
289
|
|
|
185
|
-
_See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.
|
|
290
|
+
_See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/logout.ts)_
|
|
186
291
|
|
|
187
292
|
## `lps plugin add SLUG`
|
|
188
293
|
|
|
@@ -207,7 +312,7 @@ EXAMPLES
|
|
|
207
312
|
$ lps plugin add contact-form-7 --dry-run
|
|
208
313
|
```
|
|
209
314
|
|
|
210
|
-
_See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.
|
|
315
|
+
_See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/plugin/add.ts)_
|
|
211
316
|
|
|
212
317
|
## `lps plugin pull`
|
|
213
318
|
|
|
@@ -229,7 +334,7 @@ EXAMPLES
|
|
|
229
334
|
$ lps plugin pull --dry-run
|
|
230
335
|
```
|
|
231
336
|
|
|
232
|
-
_See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.
|
|
337
|
+
_See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/plugin/pull.ts)_
|
|
233
338
|
|
|
234
339
|
## `lps plugin push`
|
|
235
340
|
|
|
@@ -251,7 +356,7 @@ EXAMPLES
|
|
|
251
356
|
$ lps plugin push --dry-run
|
|
252
357
|
```
|
|
253
358
|
|
|
254
|
-
_See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.
|
|
359
|
+
_See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/plugin/push.ts)_
|
|
255
360
|
|
|
256
361
|
## `lps project config`
|
|
257
362
|
|
|
@@ -269,7 +374,7 @@ EXAMPLES
|
|
|
269
374
|
$ lps project config
|
|
270
375
|
```
|
|
271
376
|
|
|
272
|
-
_See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.
|
|
377
|
+
_See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/project/config.ts)_
|
|
273
378
|
|
|
274
379
|
## `lps project list`
|
|
275
380
|
|
|
@@ -286,58 +391,75 @@ EXAMPLES
|
|
|
286
391
|
$ lps project list
|
|
287
392
|
```
|
|
288
393
|
|
|
289
|
-
_See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.
|
|
394
|
+
_See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/project/list.ts)_
|
|
290
395
|
|
|
291
|
-
## `lps project
|
|
396
|
+
## `lps project pull`
|
|
292
397
|
|
|
293
|
-
|
|
398
|
+
Pull projects and environments from your Loopress account that are not configured locally yet
|
|
294
399
|
|
|
295
400
|
```
|
|
296
401
|
USAGE
|
|
297
|
-
$ lps project
|
|
402
|
+
$ lps project pull
|
|
298
403
|
|
|
299
404
|
DESCRIPTION
|
|
300
|
-
|
|
405
|
+
Pull projects and environments from your Loopress account that are not configured locally yet
|
|
301
406
|
|
|
302
407
|
EXAMPLES
|
|
303
|
-
$ lps project
|
|
408
|
+
$ lps project pull
|
|
304
409
|
```
|
|
305
410
|
|
|
306
|
-
_See code: [src/commands/project/
|
|
411
|
+
_See code: [src/commands/project/pull.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/project/pull.ts)_
|
|
307
412
|
|
|
308
|
-
## `lps project
|
|
413
|
+
## `lps project push`
|
|
309
414
|
|
|
310
|
-
|
|
415
|
+
Push locally configured projects, environments and credentials to your Loopress account
|
|
311
416
|
|
|
312
417
|
```
|
|
313
418
|
USAGE
|
|
314
|
-
$ lps project
|
|
419
|
+
$ lps project push
|
|
315
420
|
|
|
316
421
|
DESCRIPTION
|
|
317
|
-
|
|
422
|
+
Push locally configured projects, environments and credentials to your Loopress account
|
|
318
423
|
|
|
319
424
|
EXAMPLES
|
|
320
|
-
$ lps project
|
|
425
|
+
$ lps project push
|
|
321
426
|
```
|
|
322
427
|
|
|
323
|
-
_See code: [src/commands/project/
|
|
428
|
+
_See code: [src/commands/project/push.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/project/push.ts)_
|
|
324
429
|
|
|
325
|
-
## `lps project
|
|
430
|
+
## `lps project remove`
|
|
326
431
|
|
|
327
|
-
|
|
432
|
+
Remove one or more WordPress projects or environments
|
|
328
433
|
|
|
329
434
|
```
|
|
330
435
|
USAGE
|
|
331
|
-
$ lps project
|
|
436
|
+
$ lps project remove
|
|
332
437
|
|
|
333
438
|
DESCRIPTION
|
|
334
|
-
|
|
439
|
+
Remove one or more WordPress projects or environments
|
|
335
440
|
|
|
336
441
|
EXAMPLES
|
|
337
|
-
$ lps project
|
|
442
|
+
$ lps project remove
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
_See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/project/remove.ts)_
|
|
446
|
+
|
|
447
|
+
## `lps project switch`
|
|
448
|
+
|
|
449
|
+
Switch the active project and environment
|
|
450
|
+
|
|
451
|
+
```
|
|
452
|
+
USAGE
|
|
453
|
+
$ lps project switch
|
|
454
|
+
|
|
455
|
+
DESCRIPTION
|
|
456
|
+
Switch the active project and environment
|
|
457
|
+
|
|
458
|
+
EXAMPLES
|
|
459
|
+
$ lps project switch
|
|
338
460
|
```
|
|
339
461
|
|
|
340
|
-
_See code: [src/commands/project/
|
|
462
|
+
_See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/project/switch.ts)_
|
|
341
463
|
|
|
342
464
|
## `lps snippet list`
|
|
343
465
|
|
|
@@ -357,7 +479,7 @@ EXAMPLES
|
|
|
357
479
|
$ lps snippet list
|
|
358
480
|
```
|
|
359
481
|
|
|
360
|
-
_See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.
|
|
482
|
+
_See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/snippet/list.ts)_
|
|
361
483
|
|
|
362
484
|
## `lps snippet publish [PATH]`
|
|
363
485
|
|
|
@@ -380,7 +502,7 @@ EXAMPLES
|
|
|
380
502
|
$ lps snippet publish --path ./snippets
|
|
381
503
|
```
|
|
382
504
|
|
|
383
|
-
_See code: [src/commands/snippet/publish.ts](https://github.com/loopress/loopress/blob/v0.
|
|
505
|
+
_See code: [src/commands/snippet/publish.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/snippet/publish.ts)_
|
|
384
506
|
|
|
385
507
|
## `lps snippet pull [PATH]`
|
|
386
508
|
|
|
@@ -405,7 +527,7 @@ EXAMPLES
|
|
|
405
527
|
$ lps snippet pull --path ./snippets
|
|
406
528
|
```
|
|
407
529
|
|
|
408
|
-
_See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.
|
|
530
|
+
_See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/snippet/pull.ts)_
|
|
409
531
|
|
|
410
532
|
## `lps snippet push [PATH]`
|
|
411
533
|
|
|
@@ -431,7 +553,7 @@ EXAMPLES
|
|
|
431
553
|
$ lps snippet push --path ./snippets
|
|
432
554
|
```
|
|
433
555
|
|
|
434
|
-
_See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.
|
|
556
|
+
_See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/snippet/push.ts)_
|
|
435
557
|
|
|
436
558
|
## `lps status`
|
|
437
559
|
|
|
@@ -448,7 +570,7 @@ EXAMPLES
|
|
|
448
570
|
$ lps status
|
|
449
571
|
```
|
|
450
572
|
|
|
451
|
-
_See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.
|
|
573
|
+
_See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/status.ts)_
|
|
452
574
|
|
|
453
575
|
## `lps telemetry disable`
|
|
454
576
|
|
|
@@ -465,7 +587,7 @@ EXAMPLES
|
|
|
465
587
|
$ lps telemetry disable
|
|
466
588
|
```
|
|
467
589
|
|
|
468
|
-
_See code: [src/commands/telemetry/disable.ts](https://github.com/loopress/loopress/blob/v0.
|
|
590
|
+
_See code: [src/commands/telemetry/disable.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/telemetry/disable.ts)_
|
|
469
591
|
|
|
470
592
|
## `lps telemetry enable`
|
|
471
593
|
|
|
@@ -482,5 +604,5 @@ EXAMPLES
|
|
|
482
604
|
$ lps telemetry enable
|
|
483
605
|
```
|
|
484
606
|
|
|
485
|
-
_See code: [src/commands/telemetry/enable.ts](https://github.com/loopress/loopress/blob/v0.
|
|
607
|
+
_See code: [src/commands/telemetry/enable.ts](https://github.com/loopress/loopress/blob/v0.16.0/src/commands/telemetry/enable.ts)_
|
|
486
608
|
<!-- 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
|
+
}
|