@loopress/cli 0.14.0 → 0.15.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
@@ -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.14.0 linux-x64 node-v24.18.0
24
+ @loopress/cli/0.15.0 linux-x64 node-v24.18.0
25
25
  $ lps --help [COMMAND]
26
26
  USAGE
27
27
  $ lps COMMAND
@@ -58,9 +58,10 @@ report.
58
58
  * [`lps plugin push`](#lps-plugin-push)
59
59
  * [`lps project config`](#lps-project-config)
60
60
  * [`lps project list`](#lps-project-list)
61
+ * [`lps project pull`](#lps-project-pull)
62
+ * [`lps project push`](#lps-project-push)
61
63
  * [`lps project remove`](#lps-project-remove)
62
64
  * [`lps project switch`](#lps-project-switch)
63
- * [`lps project sync`](#lps-project-sync)
64
65
  * [`lps snippet list`](#lps-snippet-list)
65
66
  * [`lps snippet publish [PATH]`](#lps-snippet-publish-path)
66
67
  * [`lps snippet pull [PATH]`](#lps-snippet-pull-path)
@@ -89,7 +90,7 @@ EXAMPLES
89
90
  $ lps composer pull --dry-run
90
91
  ```
91
92
 
92
- _See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/composer/pull.ts)_
93
+ _See code: [src/commands/composer/pull.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/composer/pull.ts)_
93
94
 
94
95
  ## `lps composer push`
95
96
 
@@ -111,7 +112,7 @@ EXAMPLES
111
112
  $ lps composer push --dry-run
112
113
  ```
113
114
 
114
- _See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/composer/push.ts)_
115
+ _See code: [src/commands/composer/push.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/composer/push.ts)_
115
116
 
116
117
  ## `lps help [COMMAND]`
117
118
 
@@ -148,7 +149,7 @@ EXAMPLES
148
149
  $ lps init
149
150
  ```
150
151
 
151
- _See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/init.ts)_
152
+ _See code: [src/commands/init.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/init.ts)_
152
153
 
153
154
  ## `lps login`
154
155
 
@@ -165,7 +166,7 @@ EXAMPLES
165
166
  $ lps login
166
167
  ```
167
168
 
168
- _See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/login.ts)_
169
+ _See code: [src/commands/login.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/login.ts)_
169
170
 
170
171
  ## `lps logout`
171
172
 
@@ -182,7 +183,7 @@ EXAMPLES
182
183
  $ lps logout
183
184
  ```
184
185
 
185
- _See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/logout.ts)_
186
+ _See code: [src/commands/logout.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/logout.ts)_
186
187
 
187
188
  ## `lps plugin add SLUG`
188
189
 
@@ -207,7 +208,7 @@ EXAMPLES
207
208
  $ lps plugin add contact-form-7 --dry-run
208
209
  ```
209
210
 
210
- _See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/plugin/add.ts)_
211
+ _See code: [src/commands/plugin/add.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/plugin/add.ts)_
211
212
 
212
213
  ## `lps plugin pull`
213
214
 
@@ -229,7 +230,7 @@ EXAMPLES
229
230
  $ lps plugin pull --dry-run
230
231
  ```
231
232
 
232
- _See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/plugin/pull.ts)_
233
+ _See code: [src/commands/plugin/pull.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/plugin/pull.ts)_
233
234
 
234
235
  ## `lps plugin push`
235
236
 
@@ -251,7 +252,7 @@ EXAMPLES
251
252
  $ lps plugin push --dry-run
252
253
  ```
253
254
 
254
- _See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/plugin/push.ts)_
255
+ _See code: [src/commands/plugin/push.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/plugin/push.ts)_
255
256
 
256
257
  ## `lps project config`
257
258
 
@@ -269,7 +270,7 @@ EXAMPLES
269
270
  $ lps project config
270
271
  ```
271
272
 
272
- _See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/config.ts)_
273
+ _See code: [src/commands/project/config.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/project/config.ts)_
273
274
 
274
275
  ## `lps project list`
275
276
 
@@ -286,58 +287,75 @@ EXAMPLES
286
287
  $ lps project list
287
288
  ```
288
289
 
289
- _See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/list.ts)_
290
+ _See code: [src/commands/project/list.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/project/list.ts)_
290
291
 
291
- ## `lps project remove`
292
+ ## `lps project pull`
292
293
 
293
- Remove one or more WordPress projects or environments
294
+ Pull projects and environments from your Loopress account that are not configured locally yet
294
295
 
295
296
  ```
296
297
  USAGE
297
- $ lps project remove
298
+ $ lps project pull
298
299
 
299
300
  DESCRIPTION
300
- Remove one or more WordPress projects or environments
301
+ Pull projects and environments from your Loopress account that are not configured locally yet
301
302
 
302
303
  EXAMPLES
303
- $ lps project remove
304
+ $ lps project pull
304
305
  ```
305
306
 
306
- _See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/remove.ts)_
307
+ _See code: [src/commands/project/pull.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/project/pull.ts)_
307
308
 
308
- ## `lps project switch`
309
+ ## `lps project push`
309
310
 
310
- Switch the active project and environment
311
+ Push locally configured projects, environments and credentials to your Loopress account
311
312
 
312
313
  ```
313
314
  USAGE
314
- $ lps project switch
315
+ $ lps project push
315
316
 
316
317
  DESCRIPTION
317
- Switch the active project and environment
318
+ Push locally configured projects, environments and credentials to your Loopress account
318
319
 
319
320
  EXAMPLES
320
- $ lps project switch
321
+ $ lps project push
321
322
  ```
322
323
 
323
- _See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/switch.ts)_
324
+ _See code: [src/commands/project/push.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/project/push.ts)_
324
325
 
325
- ## `lps project sync`
326
+ ## `lps project remove`
326
327
 
327
- Sync locally configured projects and environments with your Loopress account
328
+ Remove one or more WordPress projects or environments
328
329
 
329
330
  ```
330
331
  USAGE
331
- $ lps project sync
332
+ $ lps project remove
332
333
 
333
334
  DESCRIPTION
334
- Sync locally configured projects and environments with your Loopress account
335
+ Remove one or more WordPress projects or environments
335
336
 
336
337
  EXAMPLES
337
- $ lps project sync
338
+ $ lps project remove
339
+ ```
340
+
341
+ _See code: [src/commands/project/remove.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/project/remove.ts)_
342
+
343
+ ## `lps project switch`
344
+
345
+ Switch the active project and environment
346
+
347
+ ```
348
+ USAGE
349
+ $ lps project switch
350
+
351
+ DESCRIPTION
352
+ Switch the active project and environment
353
+
354
+ EXAMPLES
355
+ $ lps project switch
338
356
  ```
339
357
 
340
- _See code: [src/commands/project/sync.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/project/sync.ts)_
358
+ _See code: [src/commands/project/switch.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/project/switch.ts)_
341
359
 
342
360
  ## `lps snippet list`
343
361
 
@@ -357,7 +375,7 @@ EXAMPLES
357
375
  $ lps snippet list
358
376
  ```
359
377
 
360
- _See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/snippet/list.ts)_
378
+ _See code: [src/commands/snippet/list.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/snippet/list.ts)_
361
379
 
362
380
  ## `lps snippet publish [PATH]`
363
381
 
@@ -380,7 +398,7 @@ EXAMPLES
380
398
  $ lps snippet publish --path ./snippets
381
399
  ```
382
400
 
383
- _See code: [src/commands/snippet/publish.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/snippet/publish.ts)_
401
+ _See code: [src/commands/snippet/publish.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/snippet/publish.ts)_
384
402
 
385
403
  ## `lps snippet pull [PATH]`
386
404
 
@@ -405,7 +423,7 @@ EXAMPLES
405
423
  $ lps snippet pull --path ./snippets
406
424
  ```
407
425
 
408
- _See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/snippet/pull.ts)_
426
+ _See code: [src/commands/snippet/pull.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/snippet/pull.ts)_
409
427
 
410
428
  ## `lps snippet push [PATH]`
411
429
 
@@ -431,7 +449,7 @@ EXAMPLES
431
449
  $ lps snippet push --path ./snippets
432
450
  ```
433
451
 
434
- _See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/snippet/push.ts)_
452
+ _See code: [src/commands/snippet/push.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/snippet/push.ts)_
435
453
 
436
454
  ## `lps status`
437
455
 
@@ -448,7 +466,7 @@ EXAMPLES
448
466
  $ lps status
449
467
  ```
450
468
 
451
- _See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/status.ts)_
469
+ _See code: [src/commands/status.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/status.ts)_
452
470
 
453
471
  ## `lps telemetry disable`
454
472
 
@@ -465,7 +483,7 @@ EXAMPLES
465
483
  $ lps telemetry disable
466
484
  ```
467
485
 
468
- _See code: [src/commands/telemetry/disable.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/telemetry/disable.ts)_
486
+ _See code: [src/commands/telemetry/disable.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/telemetry/disable.ts)_
469
487
 
470
488
  ## `lps telemetry enable`
471
489
 
@@ -482,5 +500,5 @@ EXAMPLES
482
500
  $ lps telemetry enable
483
501
  ```
484
502
 
485
- _See code: [src/commands/telemetry/enable.ts](https://github.com/loopress/loopress/blob/v0.14.0/src/commands/telemetry/enable.ts)_
503
+ _See code: [src/commands/telemetry/enable.ts](https://github.com/loopress/loopress/blob/v0.15.0/src/commands/telemetry/enable.ts)_
486
504
  <!-- commandsstop -->
@@ -0,0 +1,8 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class Pull extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ run(): Promise<void>;
6
+ private fetchApiProjects;
7
+ private pullProject;
8
+ }
@@ -0,0 +1,69 @@
1
+ import { Command } from '@oclif/core';
2
+ import { Listr } from 'listr2';
3
+ import { authManager } from '../../config/auth.manager.js';
4
+ import { configManager } from '../../config/project-config.manager.js';
5
+ import { ApiClient } from '../../lib/api-client.js';
6
+ export default class Pull extends Command {
7
+ static description = 'Pull projects and environments from your Loopress account that are not configured locally yet';
8
+ static examples = ['$ lps project pull'];
9
+ async run() {
10
+ await this.parse(Pull);
11
+ const token = authManager.getAuth()?.token;
12
+ if (!token) {
13
+ this.error('Not logged in. Run `lps login` first.');
14
+ }
15
+ const api = new ApiClient(token);
16
+ const apiProjects = await this.fetchApiProjects(api);
17
+ const linkedApiProjectIds = new Set(configManager
18
+ .listProjects()
19
+ .map((project) => project.apiProjectId)
20
+ .filter((id) => id !== undefined));
21
+ const newApiProjects = apiProjects.filter((apiProject) => !linkedApiProjectIds.has(apiProject.id));
22
+ let projectCount = 0;
23
+ let environmentCount = 0;
24
+ if (newApiProjects.length > 0) {
25
+ await new Listr(newApiProjects.map((apiProject) => ({
26
+ task: (_ctx, task) => {
27
+ this.pullProject(apiProject, task);
28
+ projectCount++;
29
+ environmentCount += apiProject.environments.length;
30
+ },
31
+ title: `Pull project "${apiProject.name}" from the API`,
32
+ })), { concurrent: false, exitOnError: false }).run();
33
+ }
34
+ this.log(`\n✓ Pulled ${projectCount} project${projectCount === 1 ? '' : 's'}, ${environmentCount} environment${environmentCount === 1 ? '' : 's'} from your Loopress account`);
35
+ }
36
+ async fetchApiProjects(api) {
37
+ try {
38
+ return await api.get('projects');
39
+ }
40
+ catch (error) {
41
+ this.error(`Could not fetch projects from the API: ${error.message}`);
42
+ }
43
+ }
44
+ // Reuse a local project already linked to this API project instead of always minting a new
45
+ // one: otherwise every pull that can't "claim" an existing link (e.g. after the local config
46
+ // was reset or desynced from the API) creates yet another duplicate entry.
47
+ pullProject(apiProject, task) {
48
+ const existing = configManager.findProjectByApiId(apiProject.id);
49
+ const environments = { ...existing?.environments };
50
+ for (const env of apiProject.environments) {
51
+ environments[env.name] = {
52
+ ...environments[env.name],
53
+ addedAt: environments[env.name]?.addedAt ?? env.createdAt,
54
+ apiEnvironmentId: env.id,
55
+ name: env.name,
56
+ url: env.url,
57
+ };
58
+ }
59
+ configManager.setProject(existing?.id ?? configManager.createProjectId(apiProject.name), {
60
+ addedAt: existing?.addedAt ?? apiProject.createdAt,
61
+ apiProjectId: apiProject.id,
62
+ environments,
63
+ name: apiProject.name,
64
+ });
65
+ const envCount = apiProject.environments.length;
66
+ if (task)
67
+ task.output = `Pulled with ${envCount} environment${envCount === 1 ? '' : 's'}`;
68
+ }
69
+ }
@@ -1,5 +1,5 @@
1
1
  import { Command } from '@oclif/core';
2
- export default class Sync extends Command {
2
+ export default class Push extends Command {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  run(): Promise<void>;
@@ -8,6 +8,5 @@ export default class Sync extends Command {
8
8
  private fetchApiProjects;
9
9
  private planEnvironment;
10
10
  private planProject;
11
- private pullProject;
12
11
  private pushCredentials;
13
12
  }
@@ -5,11 +5,11 @@ import slugify from 'slugify';
5
5
  import { authManager } from '../../config/auth.manager.js';
6
6
  import { configManager } from '../../config/project-config.manager.js';
7
7
  import { ApiClient } from '../../lib/api-client.js';
8
- export default class Sync extends Command {
9
- static description = 'Sync locally configured projects and environments with your Loopress account';
10
- static examples = ['$ lps project sync'];
8
+ export default class Push extends Command {
9
+ static description = 'Push locally configured projects, environments and credentials to your Loopress account';
10
+ static examples = ['$ lps project push'];
11
11
  async run() {
12
- await this.parse(Sync);
12
+ await this.parse(Push);
13
13
  const token = authManager.getAuth()?.token;
14
14
  if (!token) {
15
15
  this.error('Not logged in. Run `lps login` first.');
@@ -77,22 +77,11 @@ export default class Sync extends Command {
77
77
  await this.pushCredentials(api, plan.apiProjectId, envPlan.apiEnvironmentId, envPlan.env);
78
78
  }
79
79
  catch (error) {
80
- this.warn(`Failed to sync "${plan.project.name}/${envPlan.env.name}": ${error.message}`);
80
+ this.warn(`Failed to push "${plan.project.name}/${envPlan.env.name}": ${error.message}`);
81
81
  }
82
82
  }
83
83
  }
84
- const newApiProjects = apiProjects.filter((candidate) => !claimedProjectIds.has(candidate.id));
85
- if (newApiProjects.length > 0) {
86
- await new Listr(newApiProjects.map((apiProject) => ({
87
- task: async (_ctx, task) => {
88
- this.pullProject(apiProject, task);
89
- projectCount++;
90
- environmentCount += apiProject.environments.length;
91
- },
92
- title: `Pull project "${apiProject.name}" from the API`,
93
- })), { concurrent: false, exitOnError: false }).run();
94
- }
95
- this.log(`\n✓ Synced ${projectCount} project${projectCount === 1 ? '' : 's'}, ${environmentCount} environment${environmentCount === 1 ? '' : 's'} with your Loopress account`);
84
+ this.log(`\n✓ Pushed ${projectCount} project${projectCount === 1 ? '' : 's'}, ${environmentCount} environment${environmentCount === 1 ? '' : 's'} to your Loopress account`);
96
85
  }
97
86
  async applyEnvironment(api, apiProjectId, envPlan, task) {
98
87
  try {
@@ -111,7 +100,7 @@ export default class Sync extends Command {
111
100
  task.output = envPlan.action === 'create' ? 'Created on the API' : 'Linked to the API';
112
101
  }
113
102
  catch (error) {
114
- const message = `Failed to sync "${envPlan.env.name}": ${error.message}`;
103
+ const message = `Failed to push "${envPlan.env.name}": ${error.message}`;
115
104
  if (task)
116
105
  task.output = message;
117
106
  throw error;
@@ -131,7 +120,7 @@ export default class Sync extends Command {
131
120
  task.output = plan.action === 'create' ? 'Created on the API' : 'Linked to the API';
132
121
  }
133
122
  catch (error) {
134
- const message = `Failed to sync project "${plan.project.name}": ${error.message}`;
123
+ const message = `Failed to push project "${plan.project.name}": ${error.message}`;
135
124
  if (task)
136
125
  task.output = message;
137
126
  throw error;
@@ -183,31 +172,6 @@ export default class Sync extends Command {
183
172
  }
184
173
  return { action: 'create', project };
185
174
  }
186
- pullProject(apiProject, task) {
187
- // Reuse a local project already linked to this API project instead of always minting a
188
- // new one: otherwise every sync run that can't "claim" an existing link (e.g. after the
189
- // local config was reset or desynced from the API) creates yet another duplicate entry.
190
- const existing = configManager.findProjectByApiId(apiProject.id);
191
- const environments = { ...existing?.environments };
192
- for (const env of apiProject.environments) {
193
- environments[env.name] = {
194
- ...environments[env.name],
195
- addedAt: environments[env.name]?.addedAt ?? env.createdAt,
196
- apiEnvironmentId: env.id,
197
- name: env.name,
198
- url: env.url,
199
- };
200
- }
201
- configManager.setProject(existing?.id ?? configManager.createProjectId(apiProject.name), {
202
- addedAt: existing?.addedAt ?? apiProject.createdAt,
203
- apiProjectId: apiProject.id,
204
- environments,
205
- name: apiProject.name,
206
- });
207
- const envCount = apiProject.environments.length;
208
- if (task)
209
- task.output = `Pulled with ${envCount} environment${envCount === 1 ? '' : 's'}`;
210
- }
211
175
  async pushCredentials(api, apiProjectId, apiEnvironmentId, env) {
212
176
  if (!env.token)
213
177
  return;
@@ -32,7 +32,7 @@ export default class Publish extends Command {
32
32
  this.error(`Project "${projectId}" (from loopress.json) not found. Run \`lps project config\` to configure it.`);
33
33
  }
34
34
  if (!project.apiProjectId) {
35
- this.error(`Project "${project.name}" is not linked to your Loopress account yet. Run \`lps project sync\` first.`);
35
+ this.error(`Project "${project.name}" is not linked to your Loopress account yet. Run \`lps project push\` first.`);
36
36
  }
37
37
  const path = args.path ?? join(localConfig.rootDir ?? '.', localConfig.snippetsDir ?? 'snippets');
38
38
  this.log(`Publishing snippets from ${path}`);
@@ -24,10 +24,10 @@ export class ProjectConfigManager {
24
24
  mkdirSync(dir, { recursive: true });
25
25
  }
26
26
  }
27
- // Looks up a local project already linked to a given API project, regardless of whether
28
- // it was "claimed" in the current sync run. Used by `project sync` to avoid minting a new
29
- // local project every time it pulls an API project whose local link was lost (e.g. after
30
- // a reset or partial config corruption), which otherwise accumulates duplicate entries.
27
+ // Looks up a local project already linked to a given API project. Used by `project pull` to
28
+ // avoid minting a new local project every time it pulls an API project whose local link was
29
+ // lost (e.g. after a reset or partial config corruption), which otherwise accumulates
30
+ // duplicate entries.
31
31
  findProjectByApiId(apiProjectId) {
32
32
  const config = this.readConfig();
33
33
  for (const [id, project] of Object.entries(config.projects)) {
@@ -1,4 +1,4 @@
1
- import { isTelemetryDisabled, resolveEnvironment, runtimeContext, SENTRY_DSN } from '../lib/sentry.js';
1
+ import { isTelemetryDisabled, redactArgv, resolveEnvironment, runtimeContext, SENTRY_DSN, } from '../lib/sentry.js';
2
2
  // oclif has no `command_error` hook (checked @oclif/core@4.11.11's hooks.d.ts). `finally`
3
3
  // is the closest equivalent: it always runs at the end of the CLI lifecycle and carries
4
4
  // the error, if any, so it's where we report crashes before the process exits.
@@ -15,10 +15,15 @@ const hook = async function (options) {
15
15
  dsn: SENTRY_DSN,
16
16
  environment: resolveEnvironment(),
17
17
  release: this.config.version,
18
+ // Node defaults `server_name` to os.hostname(), which is often the user's real name
19
+ // (e.g. "jane-doe-macbook-pro"). sendDefaultPii covers IP addresses and similar, off by
20
+ // default but set explicitly since this reports from users' own machines.
21
+ sendDefaultPii: false,
22
+ serverName: 'loopress',
18
23
  });
19
24
  Sentry.captureException(options.error, {
20
25
  contexts: { runtime: runtimeContext() },
21
- extra: { argv: options.argv },
26
+ extra: { argv: redactArgv(options.argv) },
22
27
  tags: { command: options.id },
23
28
  });
24
29
  await Sentry.flush(2000);
@@ -5,3 +5,4 @@ export declare function runtimeContext(): {
5
5
  node: string;
6
6
  os: string;
7
7
  };
8
+ export declare function redactArgv(argv: string[]): string[];
@@ -20,3 +20,14 @@ export function runtimeContext() {
20
20
  os: `${platform()} ${release()}`,
21
21
  };
22
22
  }
23
+ // Positional args and flag values can carry WordPress URLs, usernames, application passwords,
24
+ // or tokens (e.g. `lps login --token xxx`, `lps project config <url>`). Only flag names are
25
+ // safe to report, they help tell which code path crashed without leaking what was passed to it.
26
+ export function redactArgv(argv) {
27
+ return argv.map((arg) => {
28
+ if (!arg.startsWith('-'))
29
+ return '[REDACTED]';
30
+ const eqIndex = arg.indexOf('=');
31
+ return eqIndex === -1 ? arg : arg.slice(0, eqIndex);
32
+ });
33
+ }
@@ -30,7 +30,7 @@ export interface ProjectConfig {
30
30
  */
31
31
  addedAt: string;
32
32
  /**
33
- * Id of the matching project on the Loopress API, once synced via `lps project sync`.
33
+ * Id of the matching project on the Loopress API, once pushed via `lps project push`.
34
34
  */
35
35
  apiProjectId?: string;
36
36
  /**
@@ -50,7 +50,7 @@ export interface EnvironmentConfig {
50
50
  */
51
51
  addedAt: string;
52
52
  /**
53
- * Id of the matching environment on the Loopress API, once synced via `lps project sync`.
53
+ * Id of the matching environment on the Loopress API, once pushed via `lps project push`.
54
54
  */
55
55
  apiEnvironmentId?: string;
56
56
  /**
@@ -113,26 +113,25 @@
113
113
  "status.js"
114
114
  ]
115
115
  },
116
- "composer:pull": {
116
+ "snippet:list": {
117
117
  "aliases": [],
118
118
  "args": {},
119
- "description": "Pull composer.lock from WordPress",
119
+ "description": "List snippets from WordPress",
120
120
  "examples": [
121
- "$ lps composer pull",
122
- "$ lps composer pull --dry-run"
121
+ "$ lps snippet list"
123
122
  ],
124
123
  "flags": {
125
- "dry-run": {
126
- "char": "d",
127
- "description": "Show what would change without making changes",
128
- "name": "dry-run",
124
+ "json": {
125
+ "char": "j",
126
+ "description": "Output in JSON format",
127
+ "name": "json",
129
128
  "allowNo": false,
130
129
  "type": "boolean"
131
130
  }
132
131
  },
133
132
  "hasDynamicHelp": false,
134
133
  "hiddenAliases": [],
135
- "id": "composer:pull",
134
+ "id": "snippet:list",
136
135
  "pluginAlias": "@loopress/cli",
137
136
  "pluginName": "@loopress/cli",
138
137
  "pluginType": "core",
@@ -150,96 +149,52 @@
150
149
  "relativePath": [
151
150
  "dist",
152
151
  "commands",
153
- "composer",
154
- "pull.js"
155
- ]
156
- },
157
- "composer:push": {
158
- "aliases": [],
159
- "args": {},
160
- "description": "Push composer.json and composer.lock to WordPress and run composer install",
161
- "examples": [
162
- "$ lps composer push",
163
- "$ lps composer push --dry-run"
164
- ],
165
- "flags": {
166
- "dry-run": {
167
- "char": "d",
168
- "description": "Show what would change without making changes",
169
- "name": "dry-run",
170
- "allowNo": false,
171
- "type": "boolean"
172
- }
173
- },
174
- "hasDynamicHelp": false,
175
- "hiddenAliases": [],
176
- "id": "composer:push",
177
- "pluginAlias": "@loopress/cli",
178
- "pluginName": "@loopress/cli",
179
- "pluginType": "core",
180
- "strict": true,
181
- "isESM": true,
182
- "relativePath": [
183
- "dist",
184
- "commands",
185
- "composer",
186
- "push.js"
152
+ "snippet",
153
+ "list.js"
187
154
  ]
188
155
  },
189
- "plugin:add": {
156
+ "snippet:publish": {
190
157
  "aliases": [],
191
158
  "args": {
192
- "slug": {
193
- "description": "Plugin slug on WordPress.org",
194
- "name": "slug",
195
- "required": true
159
+ "path": {
160
+ "description": "Path to snippets directory (overrides project config)",
161
+ "name": "path"
196
162
  }
197
163
  },
198
- "description": "Add a WordPress.org plugin to loopress.json",
164
+ "description": "Publish snippets to your Loopress account so they can be deployed to other projects. Does not touch any WordPress site.",
199
165
  "examples": [
200
- "$ lps plugin add woocommerce",
201
- "$ lps plugin add contact-form-7 --dry-run"
166
+ "$ lps snippet publish",
167
+ "$ lps snippet publish --path ./snippets"
202
168
  ],
203
- "flags": {
204
- "dry-run": {
205
- "char": "d",
206
- "description": "Show what would change without making changes",
207
- "name": "dry-run",
208
- "allowNo": false,
209
- "type": "boolean"
210
- }
211
- },
169
+ "flags": {},
212
170
  "hasDynamicHelp": false,
213
171
  "hiddenAliases": [],
214
- "id": "plugin:add",
172
+ "id": "snippet:publish",
215
173
  "pluginAlias": "@loopress/cli",
216
174
  "pluginName": "@loopress/cli",
217
175
  "pluginType": "core",
218
176
  "strict": true,
219
177
  "enableJsonFlag": false,
220
- "dryRunFlag": {
221
- "dry-run": {
222
- "char": "d",
223
- "description": "Show what would change without making changes",
224
- "allowNo": false,
225
- "type": "boolean"
226
- }
227
- },
228
178
  "isESM": true,
229
179
  "relativePath": [
230
180
  "dist",
231
181
  "commands",
232
- "plugin",
233
- "add.js"
182
+ "snippet",
183
+ "publish.js"
234
184
  ]
235
185
  },
236
- "plugin:pull": {
186
+ "snippet:pull": {
237
187
  "aliases": [],
238
- "args": {},
239
- "description": "Pull installed plugins from WordPress into loopress.json",
188
+ "args": {
189
+ "path": {
190
+ "description": "Path to snippets directory (overrides project config)",
191
+ "name": "path"
192
+ }
193
+ },
194
+ "description": "Pull snippets from WordPress",
240
195
  "examples": [
241
- "$ lps plugin pull",
242
- "$ lps plugin pull --dry-run"
196
+ "$ lps snippet pull",
197
+ "$ lps snippet pull --path ./snippets"
243
198
  ],
244
199
  "flags": {
245
200
  "dry-run": {
@@ -252,7 +207,7 @@
252
207
  },
253
208
  "hasDynamicHelp": false,
254
209
  "hiddenAliases": [],
255
- "id": "plugin:pull",
210
+ "id": "snippet:pull",
256
211
  "pluginAlias": "@loopress/cli",
257
212
  "pluginName": "@loopress/cli",
258
213
  "pluginType": "core",
@@ -270,17 +225,22 @@
270
225
  "relativePath": [
271
226
  "dist",
272
227
  "commands",
273
- "plugin",
228
+ "snippet",
274
229
  "pull.js"
275
230
  ]
276
231
  },
277
- "plugin:push": {
232
+ "snippet:push": {
278
233
  "aliases": [],
279
- "args": {},
280
- "description": "Push plugins to WordPress to match loopress.json",
234
+ "args": {
235
+ "path": {
236
+ "description": "Path to snippets directory (overrides project config)",
237
+ "name": "path"
238
+ }
239
+ },
240
+ "description": "Push snippets to WordPress. Local snippet files created or updated remotely are renamed on disk to the `<id>-<slug>` convention.",
281
241
  "examples": [
282
- "$ lps plugin push",
283
- "$ lps plugin push --dry-run"
242
+ "$ lps snippet push",
243
+ "$ lps snippet push --path ./snippets"
284
244
  ],
285
245
  "flags": {
286
246
  "dry-run": {
@@ -293,7 +253,7 @@
293
253
  },
294
254
  "hasDynamicHelp": false,
295
255
  "hiddenAliases": [],
296
- "id": "plugin:push",
256
+ "id": "snippet:push",
297
257
  "pluginAlias": "@loopress/cli",
298
258
  "pluginName": "@loopress/cli",
299
259
  "pluginType": "core",
@@ -302,7 +262,7 @@
302
262
  "relativePath": [
303
263
  "dist",
304
264
  "commands",
305
- "plugin",
265
+ "snippet",
306
266
  "push.js"
307
267
  ]
308
268
  },
@@ -354,17 +314,17 @@
354
314
  "list.js"
355
315
  ]
356
316
  },
357
- "project:remove": {
317
+ "project:pull": {
358
318
  "aliases": [],
359
319
  "args": {},
360
- "description": "Remove one or more WordPress projects or environments",
320
+ "description": "Pull projects and environments from your Loopress account that are not configured locally yet",
361
321
  "examples": [
362
- "$ lps project remove"
322
+ "$ lps project pull"
363
323
  ],
364
324
  "flags": {},
365
325
  "hasDynamicHelp": false,
366
326
  "hiddenAliases": [],
367
- "id": "project:remove",
327
+ "id": "project:pull",
368
328
  "pluginAlias": "@loopress/cli",
369
329
  "pluginName": "@loopress/cli",
370
330
  "pluginType": "core",
@@ -375,20 +335,20 @@
375
335
  "dist",
376
336
  "commands",
377
337
  "project",
378
- "remove.js"
338
+ "pull.js"
379
339
  ]
380
340
  },
381
- "project:switch": {
341
+ "project:push": {
382
342
  "aliases": [],
383
343
  "args": {},
384
- "description": "Switch the active project and environment",
344
+ "description": "Push locally configured projects, environments and credentials to your Loopress account",
385
345
  "examples": [
386
- "$ lps project switch"
346
+ "$ lps project push"
387
347
  ],
388
348
  "flags": {},
389
349
  "hasDynamicHelp": false,
390
350
  "hiddenAliases": [],
391
- "id": "project:switch",
351
+ "id": "project:push",
392
352
  "pluginAlias": "@loopress/cli",
393
353
  "pluginName": "@loopress/cli",
394
354
  "pluginType": "core",
@@ -399,20 +359,20 @@
399
359
  "dist",
400
360
  "commands",
401
361
  "project",
402
- "switch.js"
362
+ "push.js"
403
363
  ]
404
364
  },
405
- "project:sync": {
365
+ "project:remove": {
406
366
  "aliases": [],
407
367
  "args": {},
408
- "description": "Sync locally configured projects and environments with your Loopress account",
368
+ "description": "Remove one or more WordPress projects or environments",
409
369
  "examples": [
410
- "$ lps project sync"
370
+ "$ lps project remove"
411
371
  ],
412
372
  "flags": {},
413
373
  "hasDynamicHelp": false,
414
374
  "hiddenAliases": [],
415
- "id": "project:sync",
375
+ "id": "project:remove",
416
376
  "pluginAlias": "@loopress/cli",
417
377
  "pluginName": "@loopress/cli",
418
378
  "pluginType": "core",
@@ -423,91 +383,87 @@
423
383
  "dist",
424
384
  "commands",
425
385
  "project",
426
- "sync.js"
386
+ "remove.js"
427
387
  ]
428
388
  },
429
- "snippet:list": {
389
+ "project:switch": {
430
390
  "aliases": [],
431
391
  "args": {},
432
- "description": "List snippets from WordPress",
392
+ "description": "Switch the active project and environment",
433
393
  "examples": [
434
- "$ lps snippet list"
394
+ "$ lps project switch"
435
395
  ],
436
- "flags": {
437
- "json": {
438
- "char": "j",
439
- "description": "Output in JSON format",
440
- "name": "json",
441
- "allowNo": false,
442
- "type": "boolean"
443
- }
444
- },
396
+ "flags": {},
445
397
  "hasDynamicHelp": false,
446
398
  "hiddenAliases": [],
447
- "id": "snippet:list",
399
+ "id": "project:switch",
448
400
  "pluginAlias": "@loopress/cli",
449
401
  "pluginName": "@loopress/cli",
450
402
  "pluginType": "core",
451
403
  "strict": true,
452
404
  "enableJsonFlag": false,
453
- "dryRunFlag": {
454
- "dry-run": {
455
- "char": "d",
456
- "description": "Show what would change without making changes",
457
- "allowNo": false,
458
- "type": "boolean"
459
- }
460
- },
461
405
  "isESM": true,
462
406
  "relativePath": [
463
407
  "dist",
464
408
  "commands",
465
- "snippet",
466
- "list.js"
409
+ "project",
410
+ "switch.js"
467
411
  ]
468
412
  },
469
- "snippet:publish": {
413
+ "plugin:add": {
470
414
  "aliases": [],
471
415
  "args": {
472
- "path": {
473
- "description": "Path to snippets directory (overrides project config)",
474
- "name": "path"
416
+ "slug": {
417
+ "description": "Plugin slug on WordPress.org",
418
+ "name": "slug",
419
+ "required": true
475
420
  }
476
421
  },
477
- "description": "Publish snippets to your Loopress account so they can be deployed to other projects. Does not touch any WordPress site.",
422
+ "description": "Add a WordPress.org plugin to loopress.json",
478
423
  "examples": [
479
- "$ lps snippet publish",
480
- "$ lps snippet publish --path ./snippets"
424
+ "$ lps plugin add woocommerce",
425
+ "$ lps plugin add contact-form-7 --dry-run"
481
426
  ],
482
- "flags": {},
427
+ "flags": {
428
+ "dry-run": {
429
+ "char": "d",
430
+ "description": "Show what would change without making changes",
431
+ "name": "dry-run",
432
+ "allowNo": false,
433
+ "type": "boolean"
434
+ }
435
+ },
483
436
  "hasDynamicHelp": false,
484
437
  "hiddenAliases": [],
485
- "id": "snippet:publish",
438
+ "id": "plugin:add",
486
439
  "pluginAlias": "@loopress/cli",
487
440
  "pluginName": "@loopress/cli",
488
441
  "pluginType": "core",
489
442
  "strict": true,
490
443
  "enableJsonFlag": false,
444
+ "dryRunFlag": {
445
+ "dry-run": {
446
+ "char": "d",
447
+ "description": "Show what would change without making changes",
448
+ "allowNo": false,
449
+ "type": "boolean"
450
+ }
451
+ },
491
452
  "isESM": true,
492
453
  "relativePath": [
493
454
  "dist",
494
455
  "commands",
495
- "snippet",
496
- "publish.js"
456
+ "plugin",
457
+ "add.js"
497
458
  ]
498
459
  },
499
- "snippet:pull": {
460
+ "plugin:pull": {
500
461
  "aliases": [],
501
- "args": {
502
- "path": {
503
- "description": "Path to snippets directory (overrides project config)",
504
- "name": "path"
505
- }
506
- },
507
- "description": "Pull snippets from WordPress",
462
+ "args": {},
463
+ "description": "Pull installed plugins from WordPress into loopress.json",
508
464
  "examples": [
509
- "$ lps snippet pull",
510
- "$ lps snippet pull --path ./snippets"
465
+ "$ lps plugin pull",
466
+ "$ lps plugin pull --dry-run"
511
467
  ],
512
468
  "flags": {
513
469
  "dry-run": {
@@ -520,7 +476,7 @@
520
476
  },
521
477
  "hasDynamicHelp": false,
522
478
  "hiddenAliases": [],
523
- "id": "snippet:pull",
479
+ "id": "plugin:pull",
524
480
  "pluginAlias": "@loopress/cli",
525
481
  "pluginName": "@loopress/cli",
526
482
  "pluginType": "core",
@@ -538,22 +494,17 @@
538
494
  "relativePath": [
539
495
  "dist",
540
496
  "commands",
541
- "snippet",
497
+ "plugin",
542
498
  "pull.js"
543
499
  ]
544
500
  },
545
- "snippet:push": {
501
+ "plugin:push": {
546
502
  "aliases": [],
547
- "args": {
548
- "path": {
549
- "description": "Path to snippets directory (overrides project config)",
550
- "name": "path"
551
- }
552
- },
553
- "description": "Push snippets to WordPress. Local snippet files created or updated remotely are renamed on disk to the `<id>-<slug>` convention.",
503
+ "args": {},
504
+ "description": "Push plugins to WordPress to match loopress.json",
554
505
  "examples": [
555
- "$ lps snippet push",
556
- "$ lps snippet push --path ./snippets"
506
+ "$ lps plugin push",
507
+ "$ lps plugin push --dry-run"
557
508
  ],
558
509
  "flags": {
559
510
  "dry-run": {
@@ -566,7 +517,7 @@
566
517
  },
567
518
  "hasDynamicHelp": false,
568
519
  "hiddenAliases": [],
569
- "id": "snippet:push",
520
+ "id": "plugin:push",
570
521
  "pluginAlias": "@loopress/cli",
571
522
  "pluginName": "@loopress/cli",
572
523
  "pluginType": "core",
@@ -575,7 +526,7 @@
575
526
  "relativePath": [
576
527
  "dist",
577
528
  "commands",
578
- "snippet",
529
+ "plugin",
579
530
  "push.js"
580
531
  ]
581
532
  },
@@ -626,7 +577,80 @@
626
577
  "telemetry",
627
578
  "enable.js"
628
579
  ]
580
+ },
581
+ "composer:pull": {
582
+ "aliases": [],
583
+ "args": {},
584
+ "description": "Pull composer.lock from WordPress",
585
+ "examples": [
586
+ "$ lps composer pull",
587
+ "$ lps composer pull --dry-run"
588
+ ],
589
+ "flags": {
590
+ "dry-run": {
591
+ "char": "d",
592
+ "description": "Show what would change without making changes",
593
+ "name": "dry-run",
594
+ "allowNo": false,
595
+ "type": "boolean"
596
+ }
597
+ },
598
+ "hasDynamicHelp": false,
599
+ "hiddenAliases": [],
600
+ "id": "composer:pull",
601
+ "pluginAlias": "@loopress/cli",
602
+ "pluginName": "@loopress/cli",
603
+ "pluginType": "core",
604
+ "strict": true,
605
+ "enableJsonFlag": false,
606
+ "dryRunFlag": {
607
+ "dry-run": {
608
+ "char": "d",
609
+ "description": "Show what would change without making changes",
610
+ "allowNo": false,
611
+ "type": "boolean"
612
+ }
613
+ },
614
+ "isESM": true,
615
+ "relativePath": [
616
+ "dist",
617
+ "commands",
618
+ "composer",
619
+ "pull.js"
620
+ ]
621
+ },
622
+ "composer:push": {
623
+ "aliases": [],
624
+ "args": {},
625
+ "description": "Push composer.json and composer.lock to WordPress and run composer install",
626
+ "examples": [
627
+ "$ lps composer push",
628
+ "$ lps composer push --dry-run"
629
+ ],
630
+ "flags": {
631
+ "dry-run": {
632
+ "char": "d",
633
+ "description": "Show what would change without making changes",
634
+ "name": "dry-run",
635
+ "allowNo": false,
636
+ "type": "boolean"
637
+ }
638
+ },
639
+ "hasDynamicHelp": false,
640
+ "hiddenAliases": [],
641
+ "id": "composer:push",
642
+ "pluginAlias": "@loopress/cli",
643
+ "pluginName": "@loopress/cli",
644
+ "pluginType": "core",
645
+ "strict": true,
646
+ "isESM": true,
647
+ "relativePath": [
648
+ "dist",
649
+ "commands",
650
+ "composer",
651
+ "push.js"
652
+ ]
629
653
  }
630
654
  },
631
- "version": "0.14.0"
655
+ "version": "0.15.0"
632
656
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loopress/cli",
3
3
  "description": "CLI tool for syncing WordPress code snippets, plugins, and Composer dependencies via the REST API",
4
- "version": "0.14.0",
4
+ "version": "0.15.0",
5
5
  "author": "jean-smaug",
6
6
  "bin": {
7
7
  "loopress": "bin/run.js",
@@ -50,7 +50,7 @@
50
50
  },
51
51
  "apiProjectId": {
52
52
  "type": "string",
53
- "description": "Id of the matching project on the Loopress API, once synced via `lps project sync`."
53
+ "description": "Id of the matching project on the Loopress API, once pushed via `lps project push`."
54
54
  },
55
55
  "environments": {
56
56
  "type": "object",
@@ -87,7 +87,7 @@
87
87
  },
88
88
  "apiEnvironmentId": {
89
89
  "type": "string",
90
- "description": "Id of the matching environment on the Loopress API, once synced via `lps project sync`."
90
+ "description": "Id of the matching environment on the Loopress API, once pushed via `lps project push`."
91
91
  },
92
92
  "name": {
93
93
  "type": "string",