@loopress/cli 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -28
- package/dist/commands/init.js +5 -5
- package/dist/commands/plugin/add.d.ts +0 -2
- package/dist/commands/plugin/add.js +6 -47
- package/dist/commands/plugin/pull.js +4 -6
- package/dist/commands/plugin/push.d.ts +1 -2
- package/dist/commands/plugin/push.js +18 -50
- package/dist/commands/status.js +6 -2
- package/dist/commands/telemetry/disable.d.ts +6 -0
- package/dist/commands/telemetry/disable.js +14 -0
- package/dist/commands/telemetry/enable.d.ts +6 -0
- package/dist/commands/telemetry/enable.js +14 -0
- package/dist/config/auth.manager.d.ts +4 -2
- package/dist/config/auth.manager.js +15 -5
- package/dist/config/project-config.manager.d.ts +7 -2
- package/dist/config/project-config.manager.js +35 -6
- package/dist/hooks/finally.js +11 -2
- package/dist/hooks/init.js +8 -16
- package/dist/lib/local-callback-server.d.ts +3 -3
- package/dist/lib/local-callback-server.js +14 -4
- package/dist/lib/open-browser.d.ts +1 -1
- package/dist/lib/open-browser.js +3 -10
- package/dist/lib/sentry.d.ts +0 -1
- package/dist/lib/sentry.js +6 -8
- package/dist/lib/wp-authorize-flow.d.ts +15 -3
- package/dist/lib/wp-authorize-flow.js +31 -24
- package/dist/lib/wp-client.d.ts +1 -1
- package/dist/lib/wp-client.js +1 -1
- package/dist/types/config.d.ts +1 -1
- package/dist/types/global-config.generated.d.ts +11 -1
- package/dist/types/plugin.d.ts +4 -5
- package/dist/types/project-config.generated.d.ts +1 -4
- package/dist/utils/plugins.d.ts +3 -7
- package/dist/utils/plugins.js +27 -13
- package/oclif.manifest.json +133 -90
- package/package.json +6 -2
- package/schemas/global-config.schema.json +17 -1
- package/schemas/project-config.schema.json +3 -4
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ $ npm install -g @loopress/cli
|
|
|
21
21
|
$ lps COMMAND
|
|
22
22
|
running command...
|
|
23
23
|
$ lps (--version)
|
|
24
|
-
@loopress/cli/0.
|
|
24
|
+
@loopress/cli/0.14.0 linux-x64 node-v24.18.0
|
|
25
25
|
$ lps --help [COMMAND]
|
|
26
26
|
USAGE
|
|
27
27
|
$ lps COMMAND
|
|
@@ -35,8 +35,9 @@ Loopress sends crash reports to our Sentry project so we can find and fix bugs.
|
|
|
35
35
|
|
|
36
36
|
To opt out, either:
|
|
37
37
|
|
|
38
|
-
-
|
|
39
|
-
-
|
|
38
|
+
- run `lps telemetry disable` (persists across all future commands), or
|
|
39
|
+
- set `LOOPRESS_TELEMETRY_DISABLED=1` (overrides the persisted preference for a single run,
|
|
40
|
+
useful in CI).
|
|
40
41
|
|
|
41
42
|
A crash report includes the command name, its flags/args as typed, your Node.js
|
|
42
43
|
version, and OS. WordPress credentials are configured via `lps project config`
|
|
@@ -52,7 +53,7 @@ report.
|
|
|
52
53
|
* [`lps init`](#lps-init)
|
|
53
54
|
* [`lps login`](#lps-login)
|
|
54
55
|
* [`lps logout`](#lps-logout)
|
|
55
|
-
* [`lps plugin add SLUG
|
|
56
|
+
* [`lps plugin add SLUG`](#lps-plugin-add-slug)
|
|
56
57
|
* [`lps plugin pull`](#lps-plugin-pull)
|
|
57
58
|
* [`lps plugin push`](#lps-plugin-push)
|
|
58
59
|
* [`lps project config`](#lps-project-config)
|
|
@@ -65,6 +66,8 @@ report.
|
|
|
65
66
|
* [`lps snippet pull [PATH]`](#lps-snippet-pull-path)
|
|
66
67
|
* [`lps snippet push [PATH]`](#lps-snippet-push-path)
|
|
67
68
|
* [`lps status`](#lps-status)
|
|
69
|
+
* [`lps telemetry disable`](#lps-telemetry-disable)
|
|
70
|
+
* [`lps telemetry enable`](#lps-telemetry-enable)
|
|
68
71
|
|
|
69
72
|
## `lps composer pull`
|
|
70
73
|
|
|
@@ -86,7 +89,7 @@ EXAMPLES
|
|
|
86
89
|
$ lps composer pull --dry-run
|
|
87
90
|
```
|
|
88
91
|
|
|
89
|
-
_See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.
|
|
92
|
+
_See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/composer/pull.ts)_
|
|
90
93
|
|
|
91
94
|
## `lps composer push`
|
|
92
95
|
|
|
@@ -108,7 +111,7 @@ EXAMPLES
|
|
|
108
111
|
$ lps composer push --dry-run
|
|
109
112
|
```
|
|
110
113
|
|
|
111
|
-
_See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.
|
|
114
|
+
_See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/composer/push.ts)_
|
|
112
115
|
|
|
113
116
|
## `lps help [COMMAND]`
|
|
114
117
|
|
|
@@ -145,7 +148,7 @@ EXAMPLES
|
|
|
145
148
|
$ lps init
|
|
146
149
|
```
|
|
147
150
|
|
|
148
|
-
_See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.
|
|
151
|
+
_See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/init.ts)_
|
|
149
152
|
|
|
150
153
|
## `lps login`
|
|
151
154
|
|
|
@@ -162,7 +165,7 @@ EXAMPLES
|
|
|
162
165
|
$ lps login
|
|
163
166
|
```
|
|
164
167
|
|
|
165
|
-
_See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.
|
|
168
|
+
_See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/login.ts)_
|
|
166
169
|
|
|
167
170
|
## `lps logout`
|
|
168
171
|
|
|
@@ -179,19 +182,18 @@ EXAMPLES
|
|
|
179
182
|
$ lps logout
|
|
180
183
|
```
|
|
181
184
|
|
|
182
|
-
_See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.
|
|
185
|
+
_See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/logout.ts)_
|
|
183
186
|
|
|
184
|
-
## `lps plugin add SLUG
|
|
187
|
+
## `lps plugin add SLUG`
|
|
185
188
|
|
|
186
189
|
Add a WordPress.org plugin to loopress.json
|
|
187
190
|
|
|
188
191
|
```
|
|
189
192
|
USAGE
|
|
190
|
-
$ lps plugin add SLUG [
|
|
193
|
+
$ lps plugin add SLUG [-d]
|
|
191
194
|
|
|
192
195
|
ARGUMENTS
|
|
193
|
-
SLUG
|
|
194
|
-
[VERSION] Version to pin (default: latest)
|
|
196
|
+
SLUG Plugin slug on WordPress.org
|
|
195
197
|
|
|
196
198
|
FLAGS
|
|
197
199
|
-d, --dry-run Show what would change without making changes
|
|
@@ -202,12 +204,10 @@ DESCRIPTION
|
|
|
202
204
|
EXAMPLES
|
|
203
205
|
$ lps plugin add woocommerce
|
|
204
206
|
|
|
205
|
-
$ lps plugin add woocommerce 8.9.1
|
|
206
|
-
|
|
207
207
|
$ lps plugin add contact-form-7 --dry-run
|
|
208
208
|
```
|
|
209
209
|
|
|
210
|
-
_See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.
|
|
210
|
+
_See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/plugin/add.ts)_
|
|
211
211
|
|
|
212
212
|
## `lps plugin pull`
|
|
213
213
|
|
|
@@ -229,7 +229,7 @@ EXAMPLES
|
|
|
229
229
|
$ lps plugin pull --dry-run
|
|
230
230
|
```
|
|
231
231
|
|
|
232
|
-
_See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.
|
|
232
|
+
_See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/plugin/pull.ts)_
|
|
233
233
|
|
|
234
234
|
## `lps plugin push`
|
|
235
235
|
|
|
@@ -251,7 +251,7 @@ EXAMPLES
|
|
|
251
251
|
$ lps plugin push --dry-run
|
|
252
252
|
```
|
|
253
253
|
|
|
254
|
-
_See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.
|
|
254
|
+
_See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/plugin/push.ts)_
|
|
255
255
|
|
|
256
256
|
## `lps project config`
|
|
257
257
|
|
|
@@ -269,7 +269,7 @@ EXAMPLES
|
|
|
269
269
|
$ lps project config
|
|
270
270
|
```
|
|
271
271
|
|
|
272
|
-
_See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.
|
|
272
|
+
_See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/config.ts)_
|
|
273
273
|
|
|
274
274
|
## `lps project list`
|
|
275
275
|
|
|
@@ -286,7 +286,7 @@ EXAMPLES
|
|
|
286
286
|
$ lps project list
|
|
287
287
|
```
|
|
288
288
|
|
|
289
|
-
_See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.
|
|
289
|
+
_See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/list.ts)_
|
|
290
290
|
|
|
291
291
|
## `lps project remove`
|
|
292
292
|
|
|
@@ -303,7 +303,7 @@ EXAMPLES
|
|
|
303
303
|
$ lps project remove
|
|
304
304
|
```
|
|
305
305
|
|
|
306
|
-
_See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.
|
|
306
|
+
_See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/remove.ts)_
|
|
307
307
|
|
|
308
308
|
## `lps project switch`
|
|
309
309
|
|
|
@@ -320,7 +320,7 @@ EXAMPLES
|
|
|
320
320
|
$ lps project switch
|
|
321
321
|
```
|
|
322
322
|
|
|
323
|
-
_See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.
|
|
323
|
+
_See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/switch.ts)_
|
|
324
324
|
|
|
325
325
|
## `lps project sync`
|
|
326
326
|
|
|
@@ -337,7 +337,7 @@ EXAMPLES
|
|
|
337
337
|
$ lps project sync
|
|
338
338
|
```
|
|
339
339
|
|
|
340
|
-
_See code: [src/commands/project/sync.ts](https://github.com/loopress/loopress/blob/v0.
|
|
340
|
+
_See code: [src/commands/project/sync.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/sync.ts)_
|
|
341
341
|
|
|
342
342
|
## `lps snippet list`
|
|
343
343
|
|
|
@@ -357,7 +357,7 @@ EXAMPLES
|
|
|
357
357
|
$ lps snippet list
|
|
358
358
|
```
|
|
359
359
|
|
|
360
|
-
_See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.
|
|
360
|
+
_See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/snippet/list.ts)_
|
|
361
361
|
|
|
362
362
|
## `lps snippet publish [PATH]`
|
|
363
363
|
|
|
@@ -380,7 +380,7 @@ EXAMPLES
|
|
|
380
380
|
$ lps snippet publish --path ./snippets
|
|
381
381
|
```
|
|
382
382
|
|
|
383
|
-
_See code: [src/commands/snippet/publish.ts](https://github.com/loopress/loopress/blob/v0.
|
|
383
|
+
_See code: [src/commands/snippet/publish.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/snippet/publish.ts)_
|
|
384
384
|
|
|
385
385
|
## `lps snippet pull [PATH]`
|
|
386
386
|
|
|
@@ -405,7 +405,7 @@ EXAMPLES
|
|
|
405
405
|
$ lps snippet pull --path ./snippets
|
|
406
406
|
```
|
|
407
407
|
|
|
408
|
-
_See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.
|
|
408
|
+
_See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/snippet/pull.ts)_
|
|
409
409
|
|
|
410
410
|
## `lps snippet push [PATH]`
|
|
411
411
|
|
|
@@ -431,7 +431,7 @@ EXAMPLES
|
|
|
431
431
|
$ lps snippet push --path ./snippets
|
|
432
432
|
```
|
|
433
433
|
|
|
434
|
-
_See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.
|
|
434
|
+
_See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/snippet/push.ts)_
|
|
435
435
|
|
|
436
436
|
## `lps status`
|
|
437
437
|
|
|
@@ -448,5 +448,39 @@ EXAMPLES
|
|
|
448
448
|
$ lps status
|
|
449
449
|
```
|
|
450
450
|
|
|
451
|
-
_See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.
|
|
451
|
+
_See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/status.ts)_
|
|
452
|
+
|
|
453
|
+
## `lps telemetry disable`
|
|
454
|
+
|
|
455
|
+
Disable error reporting to Sentry
|
|
456
|
+
|
|
457
|
+
```
|
|
458
|
+
USAGE
|
|
459
|
+
$ lps telemetry disable
|
|
460
|
+
|
|
461
|
+
DESCRIPTION
|
|
462
|
+
Disable error reporting to Sentry
|
|
463
|
+
|
|
464
|
+
EXAMPLES
|
|
465
|
+
$ lps telemetry disable
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
_See code: [src/commands/telemetry/disable.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/telemetry/disable.ts)_
|
|
469
|
+
|
|
470
|
+
## `lps telemetry enable`
|
|
471
|
+
|
|
472
|
+
Enable error reporting to Sentry
|
|
473
|
+
|
|
474
|
+
```
|
|
475
|
+
USAGE
|
|
476
|
+
$ lps telemetry enable
|
|
477
|
+
|
|
478
|
+
DESCRIPTION
|
|
479
|
+
Enable error reporting to Sentry
|
|
480
|
+
|
|
481
|
+
EXAMPLES
|
|
482
|
+
$ lps telemetry enable
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
_See code: [src/commands/telemetry/enable.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/telemetry/enable.ts)_
|
|
452
486
|
<!-- commandsstop -->
|
package/dist/commands/init.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Command } from '@oclif/core';
|
|
|
3
3
|
import { existsSync } from 'node:fs';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { configManager } from '../config/project-config.manager.js';
|
|
6
|
-
import {
|
|
6
|
+
import { writeLocalConfig } from '../utils/loopress-config.js';
|
|
7
7
|
// WordPress.org slugs for the two snippet plugins the Loopress WordPress plugin supports
|
|
8
8
|
// (see SnippetModule.php, which wires up both providers and auto-detects the active one).
|
|
9
9
|
const SNIPPET_PROVIDERS = [
|
|
@@ -76,11 +76,11 @@ export default class Init extends Command {
|
|
|
76
76
|
snippetsDir,
|
|
77
77
|
};
|
|
78
78
|
await writeLocalConfig(config);
|
|
79
|
-
let
|
|
79
|
+
let providerAdded = false;
|
|
80
80
|
if (providerChoice !== '__none__') {
|
|
81
81
|
try {
|
|
82
82
|
await this.config.runCommand('plugin:add', [providerChoice]);
|
|
83
|
-
|
|
83
|
+
providerAdded = true;
|
|
84
84
|
}
|
|
85
85
|
catch (error) {
|
|
86
86
|
this.warn(error.message);
|
|
@@ -89,8 +89,8 @@ export default class Init extends Command {
|
|
|
89
89
|
this.log(`\n✓ loopress.json created`);
|
|
90
90
|
this.log(` Project: ${projectLabel}`);
|
|
91
91
|
this.log(` Snippets: ${join(rootDir, snippetsDir)}`);
|
|
92
|
-
if (
|
|
93
|
-
this.log(` Plugin: ${providerChoice}
|
|
92
|
+
if (providerAdded) {
|
|
93
|
+
this.log(` Plugin: ${providerChoice}`);
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { LoopressCommand } from '../../lib/base.js';
|
|
2
|
-
export declare function resolvePluginVersion(slug: string, version: string): Promise<string>;
|
|
3
2
|
export default class Add extends LoopressCommand {
|
|
4
3
|
static args: {
|
|
5
4
|
slug: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
-
version: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
5
|
};
|
|
8
6
|
static description: string;
|
|
9
7
|
static examples: string[];
|
|
@@ -1,73 +1,32 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
|
-
import got from 'got';
|
|
3
2
|
import { LoopressCommand } from '../../lib/base.js';
|
|
4
3
|
import { writeLocalConfig } from '../../utils/loopress-config.js';
|
|
5
|
-
const WP_ORG_API = 'https://api.wordpress.org/plugins/info/1.2/';
|
|
6
|
-
const WP_ORG_TIMEOUT_MS = 10_000;
|
|
7
|
-
export async function resolvePluginVersion(slug, version) {
|
|
8
|
-
if (version !== 'latest')
|
|
9
|
-
return version;
|
|
10
|
-
let info;
|
|
11
|
-
try {
|
|
12
|
-
info = await got
|
|
13
|
-
.get(WP_ORG_API, {
|
|
14
|
-
searchParams: {
|
|
15
|
-
action: 'plugin_information',
|
|
16
|
-
'request[slug]': slug,
|
|
17
|
-
},
|
|
18
|
-
timeout: { request: WP_ORG_TIMEOUT_MS },
|
|
19
|
-
})
|
|
20
|
-
.json();
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
throw new Error(`Plugin "${slug}" not found on WordPress.org.`);
|
|
24
|
-
}
|
|
25
|
-
if (info.error)
|
|
26
|
-
throw new Error(`Plugin "${slug}" not found on WordPress.org.`);
|
|
27
|
-
return info.version;
|
|
28
|
-
}
|
|
29
4
|
export default class Add extends LoopressCommand {
|
|
30
5
|
static args = {
|
|
31
6
|
slug: Args.string({ description: 'Plugin slug on WordPress.org', required: true }),
|
|
32
|
-
version: Args.string({ description: 'Version to pin (default: latest)' }),
|
|
33
7
|
};
|
|
34
8
|
static description = 'Add a WordPress.org plugin to loopress.json';
|
|
35
|
-
static examples = [
|
|
36
|
-
'$ lps plugin add woocommerce',
|
|
37
|
-
'$ lps plugin add woocommerce 8.9.1',
|
|
38
|
-
'$ lps plugin add contact-form-7 --dry-run',
|
|
39
|
-
];
|
|
9
|
+
static examples = ['$ lps plugin add woocommerce', '$ lps plugin add contact-form-7 --dry-run'];
|
|
40
10
|
static flags = {
|
|
41
11
|
...LoopressCommand.dryRunFlag,
|
|
42
12
|
};
|
|
43
13
|
async run() {
|
|
44
14
|
const { args } = await this.parse(Add);
|
|
45
15
|
const { slug } = args;
|
|
46
|
-
const requestedVersion = args.version ?? 'latest';
|
|
47
|
-
this.log(`Resolving ${slug}@${requestedVersion}...`);
|
|
48
|
-
let resolvedVersion;
|
|
49
|
-
try {
|
|
50
|
-
resolvedVersion = await resolvePluginVersion(slug, requestedVersion);
|
|
51
|
-
}
|
|
52
|
-
catch (error) {
|
|
53
|
-
this.error(error.message);
|
|
54
|
-
}
|
|
55
|
-
this.log(`Resolved: ${slug}@${resolvedVersion}`);
|
|
56
16
|
const existing = this.localConfig.plugins ?? {};
|
|
57
|
-
if (existing[slug] ===
|
|
58
|
-
this.log(`${slug}
|
|
17
|
+
if (existing[slug] === 'latest') {
|
|
18
|
+
this.log(`${slug} is already in loopress.json, nothing to do.`);
|
|
59
19
|
return;
|
|
60
20
|
}
|
|
61
21
|
const updated = existing[slug] !== undefined;
|
|
62
|
-
const label = updated ? `${existing[slug]} → ${resolvedVersion}` : resolvedVersion;
|
|
63
22
|
if (this.dryRun) {
|
|
64
|
-
this.log(`[dry-run] Would ${updated ? 'update' : 'add'} ${slug}
|
|
23
|
+
this.log(`[dry-run] Would ${updated ? 'update' : 'add'} ${slug} in loopress.json`);
|
|
65
24
|
return;
|
|
66
25
|
}
|
|
67
26
|
await writeLocalConfig({
|
|
68
27
|
...this.localConfig,
|
|
69
|
-
plugins: { ...existing, [slug]:
|
|
28
|
+
plugins: { ...existing, [slug]: 'latest' },
|
|
70
29
|
});
|
|
71
|
-
this.log(`${updated ? 'Updated' : 'Added'} ${slug}
|
|
30
|
+
this.log(`${updated ? 'Updated' : 'Added'} ${slug}`);
|
|
72
31
|
}
|
|
73
32
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LoopressCommand } from '../../lib/base.js';
|
|
2
2
|
import { getComposerManagedSlugs, readComposerJson } from '../../utils/composer.js';
|
|
3
3
|
import { writeLocalConfig } from '../../utils/loopress-config.js';
|
|
4
|
-
import { mergePluginManifest } from '../../utils/plugins.js';
|
|
4
|
+
import { mergePluginManifest, parseInstalledPlugins } from '../../utils/plugins.js';
|
|
5
5
|
export default class Pull extends LoopressCommand {
|
|
6
6
|
static description = 'Pull installed plugins from WordPress into loopress.json';
|
|
7
7
|
static examples = ['$ lps plugin pull', '$ lps plugin pull --dry-run'];
|
|
@@ -11,10 +11,11 @@ export default class Pull extends LoopressCommand {
|
|
|
11
11
|
async run() {
|
|
12
12
|
const { url } = this.siteConfig;
|
|
13
13
|
this.log(`Pulling plugins from ${url}`);
|
|
14
|
-
const
|
|
14
|
+
const raw = await this.wp.get('wp/v2/plugins');
|
|
15
|
+
const installed = parseInstalledPlugins(raw);
|
|
15
16
|
const composerJson = await readComposerJson();
|
|
16
17
|
const composerSlugs = composerJson ? getComposerManagedSlugs(composerJson) : [];
|
|
17
|
-
const incoming = Object.fromEntries(installed.filter((p) => !composerSlugs.includes(p.slug)).map((p) => [p.slug,
|
|
18
|
+
const incoming = Object.fromEntries(installed.filter((p) => !composerSlugs.includes(p.slug)).map((p) => [p.slug, 'latest']));
|
|
18
19
|
if (composerSlugs.length > 0) {
|
|
19
20
|
const found = installed.filter((p) => composerSlugs.includes(p.slug)).map((p) => p.slug);
|
|
20
21
|
if (found.length > 0) {
|
|
@@ -38,8 +39,5 @@ export default class Pull extends LoopressCommand {
|
|
|
38
39
|
this.log(` + Added: ${added.join(', ')}`);
|
|
39
40
|
for (const u of updated)
|
|
40
41
|
this.log(` ~ Updated: ${u.slug} ${u.from} → ${u.to}`);
|
|
41
|
-
if (Object.keys(merged).length > 0) {
|
|
42
|
-
await this.wp.post('loopress/v1/plugins/auto-updates/disable', { slugs: Object.keys(merged) });
|
|
43
|
-
}
|
|
44
42
|
}
|
|
45
43
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { confirm } from '@inquirer/prompts';
|
|
2
1
|
import { Listr } from 'listr2';
|
|
3
2
|
import { PushCommand } from '../../lib/push-command.js';
|
|
4
3
|
import { getComposerManagedSlugs, readComposerJson } from '../../utils/composer.js';
|
|
5
|
-
import { diffPlugins } from '../../utils/plugins.js';
|
|
4
|
+
import { diffPlugins, parseInstalledPlugins } from '../../utils/plugins.js';
|
|
6
5
|
export default class Push extends PushCommand {
|
|
7
6
|
static description = 'Push plugins to WordPress to match loopress.json';
|
|
8
7
|
static examples = ['$ lps plugin push', '$ lps plugin push --dry-run'];
|
|
@@ -25,45 +24,39 @@ export default class Push extends PushCommand {
|
|
|
25
24
|
this.log('Run `lps composer push` to deploy them.');
|
|
26
25
|
}
|
|
27
26
|
this.log(`Pushing plugins to ${url}`);
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
27
|
+
const raw = await this.wp.get('wp/v2/plugins');
|
|
28
|
+
const installed = parseInstalledPlugins(raw);
|
|
29
|
+
const { toActivate, toInstall } = diffPlugins(filteredManifest, installed);
|
|
30
|
+
if (toInstall.length === 0 && toActivate.length === 0) {
|
|
31
31
|
this.log('Everything is already in sync.');
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
34
|
if (toInstall.length > 0) {
|
|
35
35
|
this.log(`\nTo install (${toInstall.length}):`);
|
|
36
36
|
for (const a of toInstall)
|
|
37
|
-
this.log(` + ${a.slug}
|
|
37
|
+
this.log(` + ${a.slug}`);
|
|
38
38
|
}
|
|
39
39
|
if (toActivate.length > 0) {
|
|
40
40
|
this.log(`\nTo activate (${toActivate.length}):`);
|
|
41
41
|
for (const a of toActivate)
|
|
42
42
|
this.log(` ↑ ${a.slug}`);
|
|
43
43
|
}
|
|
44
|
-
if (drifted.length > 0) {
|
|
45
|
-
this.log(`\nVersion mismatch (${drifted.length}):`);
|
|
46
|
-
for (const a of drifted) {
|
|
47
|
-
this.log(` ~ ${a.slug}: site has ${a.currentVersion}, manifest wants ${a.targetVersion}`);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
44
|
if (this.dryRun)
|
|
51
45
|
return;
|
|
52
|
-
//
|
|
46
|
+
// Installing with `status: active` activates in the same call, so installs never need a
|
|
47
|
+
// separate activation step the way the old custom endpoint's two-step flow did.
|
|
53
48
|
if (toInstall.length > 0) {
|
|
54
49
|
await new Listr(toInstall.map((action) => ({
|
|
55
|
-
task: async (_ctx, task) => this.
|
|
56
|
-
title: `Install ${action.slug}
|
|
50
|
+
task: async (_ctx, task) => this.installPlugin(action.slug, task),
|
|
51
|
+
title: `Install ${action.slug}`,
|
|
57
52
|
})), { concurrent: false, exitOnError: false }).run();
|
|
58
53
|
}
|
|
59
|
-
// Activate installed-but-inactive plugins without prompting.
|
|
60
54
|
if (toActivate.length > 0) {
|
|
61
55
|
await new Listr(toActivate.map((action) => ({
|
|
62
|
-
task: async (_ctx, task) => this.activatePlugin(action.slug, task),
|
|
56
|
+
task: async (_ctx, task) => this.activatePlugin(action.file, action.slug, task),
|
|
63
57
|
title: `Activate ${action.slug}`,
|
|
64
58
|
})), { concurrent: false, exitOnError: false }).run();
|
|
65
59
|
}
|
|
66
|
-
await this.syncDrifted(drifted);
|
|
67
60
|
if (this.failedCount > 0) {
|
|
68
61
|
this.error(`${this.failedCount} plugin${this.failedCount === 1 ? '' : 's'} failed to install or activate.`);
|
|
69
62
|
}
|
|
@@ -75,18 +68,16 @@ export default class Push extends PushCommand {
|
|
|
75
68
|
// it falls back to plain logging. Rethrowing on failure (rather than swallowing) is what lets Listr
|
|
76
69
|
// mark the task as failed (red cross) instead of completed, even though `exitOnError: false` stops
|
|
77
70
|
// that failure from aborting sibling tasks in the same list.
|
|
78
|
-
async activatePlugin(slug, task) {
|
|
79
|
-
await this.performPluginAction('activate',
|
|
71
|
+
async activatePlugin(file, slug, task) {
|
|
72
|
+
await this.performPluginAction('activate', slug, () => this.wp.put(`wp/v2/plugins/${file}`, { status: 'active' }), task);
|
|
80
73
|
}
|
|
81
|
-
async
|
|
82
|
-
await this.performPluginAction('install',
|
|
83
|
-
await this.activatePlugin(slug, task);
|
|
74
|
+
async installPlugin(slug, task) {
|
|
75
|
+
await this.performPluginAction('install', slug, () => this.wp.post('wp/v2/plugins', { slug, status: 'active' }), task);
|
|
84
76
|
}
|
|
85
|
-
async performPluginAction(verb, request, task) {
|
|
86
|
-
const { body, endpoint, slug } = request;
|
|
77
|
+
async performPluginAction(verb, slug, request, task) {
|
|
87
78
|
try {
|
|
88
|
-
|
|
89
|
-
const message = `✓ ${
|
|
79
|
+
await request();
|
|
80
|
+
const message = `✓ ${slug} ${verb === 'install' ? 'installed and activated' : 'activated'}`;
|
|
90
81
|
if (task)
|
|
91
82
|
task.output = message;
|
|
92
83
|
else
|
|
@@ -102,27 +93,4 @@ export default class Push extends PushCommand {
|
|
|
102
93
|
throw error;
|
|
103
94
|
}
|
|
104
95
|
}
|
|
105
|
-
// Prompt per drifted plugin before syncing. Prompts run sequentially on plain stdout,
|
|
106
|
-
// before the Listr renderer takes over the terminal for the confirmed subset.
|
|
107
|
-
async syncDrifted(drifted) {
|
|
108
|
-
const confirmedDrift = [];
|
|
109
|
-
for (const action of drifted) {
|
|
110
|
-
const proceed = await confirm({
|
|
111
|
-
default: false,
|
|
112
|
-
message: `${action.slug} is at ${action.currentVersion} on the site but manifest wants ${action.targetVersion}. Sync to ${action.targetVersion}?`,
|
|
113
|
-
});
|
|
114
|
-
if (proceed) {
|
|
115
|
-
confirmedDrift.push(action);
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
this.log(` Skipped ${action.slug}`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
if (confirmedDrift.length === 0)
|
|
122
|
-
return;
|
|
123
|
-
await new Listr(confirmedDrift.map((action) => ({
|
|
124
|
-
task: async (_ctx, task) => this.installAndActivate(action.slug, action.targetVersion, task),
|
|
125
|
-
title: `Sync ${action.slug} to ${action.targetVersion}`,
|
|
126
|
-
})), { concurrent: false, exitOnError: false }).run();
|
|
127
|
-
}
|
|
128
96
|
}
|
package/dist/commands/status.js
CHANGED
|
@@ -10,9 +10,13 @@ export default class Status extends Command {
|
|
|
10
10
|
const localConfig = await readLocalConfig();
|
|
11
11
|
if (localConfig.projectId) {
|
|
12
12
|
this.reportPinnedProject(localConfig.projectId);
|
|
13
|
-
return;
|
|
14
13
|
}
|
|
15
|
-
|
|
14
|
+
else {
|
|
15
|
+
this.reportActiveProject();
|
|
16
|
+
}
|
|
17
|
+
this.log('');
|
|
18
|
+
this.log(`Config dir: ${this.config.configDir}`);
|
|
19
|
+
this.log(`Data dir: ${this.config.dataDir}`);
|
|
16
20
|
}
|
|
17
21
|
reportActiveProject() {
|
|
18
22
|
const env = configManager.getCurrentEnv();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { configManager } from '../../config/project-config.manager.js';
|
|
3
|
+
export default class TelemetryDisable extends Command {
|
|
4
|
+
static description = 'Disable error reporting to Sentry';
|
|
5
|
+
static examples = ['$ lps telemetry disable'];
|
|
6
|
+
async run() {
|
|
7
|
+
if (configManager.isTelemetryDisabled()) {
|
|
8
|
+
this.log('Error reporting is already disabled.');
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
configManager.setTelemetryDisabled(true);
|
|
12
|
+
this.log('Error reporting disabled.');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { configManager } from '../../config/project-config.manager.js';
|
|
3
|
+
export default class TelemetryEnable extends Command {
|
|
4
|
+
static description = 'Enable error reporting to Sentry';
|
|
5
|
+
static examples = ['$ lps telemetry enable'];
|
|
6
|
+
async run() {
|
|
7
|
+
if (!configManager.isTelemetryDisabled()) {
|
|
8
|
+
this.log('Error reporting is already enabled.');
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
configManager.setTelemetryDisabled(false);
|
|
12
|
+
this.log('Error reporting enabled.');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -4,11 +4,13 @@ export interface ConsoleAuth {
|
|
|
4
4
|
token: string;
|
|
5
5
|
}
|
|
6
6
|
export declare class AuthManager {
|
|
7
|
-
private
|
|
8
|
-
constructor(
|
|
7
|
+
private dataDir?;
|
|
8
|
+
constructor(dataDir?: string | undefined);
|
|
9
9
|
clearAuth(): void;
|
|
10
10
|
getAuth(): ConsoleAuth | null;
|
|
11
11
|
getAuthFilePath(): string;
|
|
12
12
|
setAuth(auth: ConsoleAuth): void;
|
|
13
|
+
setDataDir(dataDir: string): void;
|
|
14
|
+
private requireDataDir;
|
|
13
15
|
}
|
|
14
16
|
export declare const authManager: AuthManager;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { existsSync, unlinkSync } from 'node:fs';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
2
|
import { join } from 'node:path';
|
|
4
3
|
import { readJsonFile, writeJsonFileAtomic } from './json-file.js';
|
|
5
4
|
export class AuthManager {
|
|
6
|
-
|
|
7
|
-
constructor(
|
|
8
|
-
this.
|
|
5
|
+
dataDir;
|
|
6
|
+
constructor(dataDir) {
|
|
7
|
+
this.dataDir = dataDir;
|
|
9
8
|
}
|
|
10
9
|
clearAuth() {
|
|
11
10
|
const filePath = this.getAuthFilePath();
|
|
@@ -16,10 +15,21 @@ export class AuthManager {
|
|
|
16
15
|
return readJsonFile(this.getAuthFilePath());
|
|
17
16
|
}
|
|
18
17
|
getAuthFilePath() {
|
|
19
|
-
return join(this.
|
|
18
|
+
return join(this.requireDataDir(), 'auth.json');
|
|
20
19
|
}
|
|
21
20
|
setAuth(auth) {
|
|
22
21
|
writeJsonFileAtomic(this.getAuthFilePath(), auth);
|
|
23
22
|
}
|
|
23
|
+
// Real CLI runs get this from the `init` hook (src/hooks/init.ts) before any command runs.
|
|
24
|
+
// Throwing when it's unset (rather than falling back to a hardcoded path) surfaces tests that
|
|
25
|
+
// forgot to configure the manager instead of silently touching some default location.
|
|
26
|
+
setDataDir(dataDir) {
|
|
27
|
+
this.dataDir = dataDir;
|
|
28
|
+
}
|
|
29
|
+
requireDataDir() {
|
|
30
|
+
if (!this.dataDir)
|
|
31
|
+
throw new Error('AuthManager used before setDataDir() was called');
|
|
32
|
+
return this.dataDir;
|
|
33
|
+
}
|
|
24
34
|
}
|
|
25
35
|
export const authManager = new AuthManager();
|