@loopress/cli 0.7.0 → 0.9.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.
Files changed (59) hide show
  1. package/README.md +44 -75
  2. package/dist/commands/composer/pull.d.ts +0 -3
  3. package/dist/commands/composer/pull.js +4 -15
  4. package/dist/commands/composer/push.d.ts +0 -3
  5. package/dist/commands/composer/push.js +7 -17
  6. package/dist/commands/login.js +1 -1
  7. package/dist/commands/logout.js +1 -1
  8. package/dist/commands/plugin/add.d.ts +0 -3
  9. package/dist/commands/plugin/add.js +9 -10
  10. package/dist/commands/plugin/pull.d.ts +0 -3
  11. package/dist/commands/plugin/pull.js +7 -19
  12. package/dist/commands/plugin/push.d.ts +4 -3
  13. package/dist/commands/plugin/push.js +69 -63
  14. package/dist/commands/sentry-test.d.ts +6 -0
  15. package/dist/commands/sentry-test.js +8 -0
  16. package/dist/commands/snippet/list.d.ts +1 -4
  17. package/dist/commands/snippet/list.js +24 -44
  18. package/dist/commands/snippet/pull.d.ts +1 -4
  19. package/dist/commands/snippet/pull.js +40 -56
  20. package/dist/commands/snippet/push.d.ts +2 -4
  21. package/dist/commands/snippet/push.js +90 -77
  22. package/dist/config/auth.manager.d.ts +0 -2
  23. package/dist/config/auth.manager.js +5 -25
  24. package/dist/config/json-file.d.ts +2 -0
  25. package/dist/config/json-file.js +21 -0
  26. package/dist/config/project-config.manager.d.ts +1 -3
  27. package/dist/config/project-config.manager.js +7 -23
  28. package/dist/hooks/finally.d.ts +3 -0
  29. package/dist/hooks/finally.js +21 -0
  30. package/dist/hooks/init.d.ts +3 -0
  31. package/dist/hooks/init.js +18 -0
  32. package/dist/lib/base.d.ts +13 -8
  33. package/dist/lib/base.js +45 -43
  34. package/dist/lib/push-command.d.ts +0 -1
  35. package/dist/lib/push-command.js +0 -1
  36. package/dist/lib/sentry.d.ts +8 -0
  37. package/dist/lib/sentry.js +24 -0
  38. package/dist/lib/wp-client.d.ts +15 -0
  39. package/dist/lib/wp-client.js +53 -0
  40. package/dist/types/config.d.ts +1 -0
  41. package/dist/types/global-config.generated.d.ts +59 -0
  42. package/dist/types/global-config.generated.js +2 -0
  43. package/dist/types/project-config.generated.d.ts +31 -0
  44. package/dist/types/project-config.generated.js +2 -0
  45. package/dist/types/snippet.d.ts +7 -1
  46. package/dist/types/snippet.generated.d.ts +46 -0
  47. package/dist/types/snippet.generated.js +2 -0
  48. package/dist/utils/loopress-config.d.ts +2 -7
  49. package/dist/utils/loopress-config.js +5 -2
  50. package/dist/utils/snippet-plugin-flag.d.ts +3 -0
  51. package/dist/utils/snippet-plugin-flag.js +8 -0
  52. package/dist/utils/snippet-plugin.d.ts +23 -2
  53. package/dist/utils/snippet-plugin.js +168 -13
  54. package/oclif.manifest.json +66 -200
  55. package/package.json +19 -5
  56. package/dist/config/types.d.ts +0 -19
  57. package/dist/types/menu.d.ts +0 -7
  58. package/dist/types/menu.js +0 -1
  59. /package/dist/{config/types.js → types/config.js} +0 -0
@@ -1,24 +1,18 @@
1
1
  import { confirm } from '@inquirer/prompts';
2
- import { Flags } from '@oclif/core';
3
- import got from 'got';
2
+ import { Listr } from 'listr2';
4
3
  import { PushCommand } from '../../lib/push-command.js';
5
4
  import { getComposerManagedSlugs, readComposerJson } from '../../utils/composer.js';
6
- import { readLocalConfig } from '../../utils/loopress-config.js';
7
5
  import { diffPlugins } from '../../utils/plugins.js';
8
6
  export default class Push extends PushCommand {
9
7
  static description = 'Push plugins to WordPress to match loopress.json';
10
8
  static examples = ['$ lps plugin push', '$ lps plugin push --dry-run'];
11
9
  static flags = {
12
- ...PushCommand.baseFlags,
13
- 'dry-run': Flags.boolean({ char: 'd', description: 'Show what would change without making changes' }),
10
+ ...PushCommand.dryRunFlag,
14
11
  };
12
+ failedCount = 0;
15
13
  async run() {
16
- const { flags } = await this.parse(Push);
17
- const dryRun = flags['dry-run'];
18
- this.dryRun = dryRun;
19
14
  const { url } = this.siteConfig;
20
- const localConfig = await readLocalConfig();
21
- const manifest = localConfig.plugins;
15
+ const manifest = this.localConfig.plugins;
22
16
  if (!manifest || Object.keys(manifest).length === 0) {
23
17
  this.error('No plugins found in loopress.json. Run `lps plugin pull` first.');
24
18
  }
@@ -31,8 +25,7 @@ export default class Push extends PushCommand {
31
25
  this.log('Run `lps composer push` to deploy them.');
32
26
  }
33
27
  this.log(`Pushing plugins to ${url}`);
34
- const headers = await this.buildAuthHeaders();
35
- const installed = await got.get(`${url}/wp-json/loopress/v1/plugins`, { headers }).json();
28
+ const installed = await this.wp.get('loopress/v1/plugins');
36
29
  const { drifted, toActivate, toInstall } = diffPlugins(filteredManifest, installed);
37
30
  if (toInstall.length === 0 && toActivate.length === 0 && drifted.length === 0) {
38
31
  this.log('Everything is already in sync.');
@@ -54,69 +47,82 @@ export default class Push extends PushCommand {
54
47
  this.log(` ~ ${a.slug}: site has ${a.currentVersion}, manifest wants ${a.targetVersion}`);
55
48
  }
56
49
  }
57
- if (dryRun)
50
+ if (this.dryRun)
58
51
  return;
59
52
  // Install missing plugins and activate them.
60
- for (const action of toInstall) {
61
- this.log(`\nInstalling ${action.slug} @ ${action.targetVersion}...`);
62
- try {
63
- const result = await got
64
- .post(`${url}/wp-json/loopress/v1/plugins/install`, {
65
- headers,
66
- json: { slug: action.slug, version: action.targetVersion },
67
- })
68
- .json();
69
- this.log(` ✓ ${result.message}`);
70
- }
71
- catch (error) {
72
- this.warn(` Failed to install ${action.slug}: ${error.message}`);
73
- continue;
74
- }
75
- await this.activatePlugin(url, headers, action.slug);
53
+ if (toInstall.length > 0) {
54
+ await new Listr(toInstall.map((action) => ({
55
+ task: async (_ctx, task) => this.installAndActivate(action.slug, action.targetVersion, task),
56
+ title: `Install ${action.slug} @ ${action.targetVersion}`,
57
+ })), { concurrent: false, exitOnError: false }).run();
76
58
  }
77
59
  // Activate installed-but-inactive plugins without prompting.
78
- for (const action of toActivate) {
79
- this.log(`\nActivating ${action.slug}...`);
80
- await this.activatePlugin(url, headers, action.slug);
60
+ if (toActivate.length > 0) {
61
+ await new Listr(toActivate.map((action) => ({
62
+ task: async (_ctx, task) => this.activatePlugin(action.slug, task),
63
+ title: `Activate ${action.slug}`,
64
+ })), { concurrent: false, exitOnError: false }).run();
65
+ }
66
+ await this.syncDrifted(drifted);
67
+ if (this.failedCount > 0) {
68
+ this.error(`${this.failedCount} plugin${this.failedCount === 1 ? '' : 's'} failed to install or activate.`);
69
+ }
70
+ await this.recordSuccess();
71
+ }
72
+ // `task` is only passed when called from within a running Listr task list (see `run()`); it lets
73
+ // status lines go through `task.output` instead of `this.log`/`this.warn`, which would otherwise
74
+ // race with the renderer repainting the terminal. Called without `task` (e.g. directly in tests),
75
+ // it falls back to plain logging. Rethrowing on failure (rather than swallowing) is what lets Listr
76
+ // mark the task as failed (red cross) instead of completed, even though `exitOnError: false` stops
77
+ // that failure from aborting sibling tasks in the same list.
78
+ async activatePlugin(slug, task) {
79
+ await this.performPluginAction('activate', { body: { slug }, endpoint: 'loopress/v1/plugins/activate', slug }, task);
80
+ }
81
+ async installAndActivate(slug, version, task) {
82
+ await this.performPluginAction('install', { body: { slug, version }, endpoint: 'loopress/v1/plugins/install', slug }, task);
83
+ await this.activatePlugin(slug, task);
84
+ }
85
+ async performPluginAction(verb, request, task) {
86
+ const { body, endpoint, slug } = request;
87
+ try {
88
+ const result = await this.wp.post(endpoint, body);
89
+ const message = `✓ ${result.message}`;
90
+ if (task)
91
+ task.output = message;
92
+ else
93
+ this.log(` ${message}`);
94
+ }
95
+ catch (error) {
96
+ const message = `Failed to ${verb} ${slug}: ${error.message}`;
97
+ if (task)
98
+ task.output = message;
99
+ else
100
+ this.warn(` ${message}`);
101
+ this.failedCount++;
102
+ throw error;
81
103
  }
82
- // Prompt per drifted plugin before syncing.
104
+ }
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 = [];
83
109
  for (const action of drifted) {
84
- this.log('');
85
110
  const proceed = await confirm({
86
111
  default: false,
87
112
  message: `${action.slug} is at ${action.currentVersion} on the site but manifest wants ${action.targetVersion}. Sync to ${action.targetVersion}?`,
88
113
  });
89
- if (!proceed) {
90
- this.log(` Skipped ${action.slug}`);
91
- continue;
114
+ if (proceed) {
115
+ confirmedDrift.push(action);
92
116
  }
93
- this.log(` Syncing ${action.slug} to ${action.targetVersion}...`);
94
- try {
95
- const result = await got
96
- .post(`${url}/wp-json/loopress/v1/plugins/install`, {
97
- headers,
98
- json: { slug: action.slug, version: action.targetVersion },
99
- })
100
- .json();
101
- this.log(` ✓ ${result.message}`);
102
- }
103
- catch (error) {
104
- this.warn(` Failed to sync ${action.slug}: ${error.message}`);
105
- continue;
117
+ else {
118
+ this.log(` Skipped ${action.slug}`);
106
119
  }
107
- await this.activatePlugin(url, headers, action.slug);
108
- }
109
- await this.recordSuccess();
110
- }
111
- async activatePlugin(url, headers, slug) {
112
- try {
113
- const result = await got
114
- .post(`${url}/wp-json/loopress/v1/plugins/activate`, { headers, json: { slug } })
115
- .json();
116
- this.log(` ✓ ${result.message}`);
117
- }
118
- catch (error) {
119
- this.warn(` Failed to activate ${slug}: ${error.message}`);
120
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();
121
127
  }
122
128
  }
@@ -0,0 +1,6 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class SentryTest extends Command {
3
+ static description: string;
4
+ static hidden: boolean;
5
+ run(): Promise<void>;
6
+ }
@@ -0,0 +1,8 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class SentryTest extends Command {
3
+ static description = 'Throw a test error to verify Sentry error reporting is wired up correctly';
4
+ static hidden = true;
5
+ async run() {
6
+ throw new Error('Sentry test error from `lps sentry-test`');
7
+ }
8
+ }
@@ -3,11 +3,8 @@ export default class List extends LoopressCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static flags: {
6
- json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
6
  plugin: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
- password: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
- url: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
- user: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
8
  };
12
9
  run(): Promise<void>;
13
10
  }
@@ -1,59 +1,39 @@
1
1
  import { Flags } from '@oclif/core';
2
- import got from 'got';
3
2
  import { LoopressCommand } from '../../lib/base.js';
3
+ import { snippetPluginFlag } from '../../utils/snippet-plugin-flag.js';
4
4
  import { getSnippetPlugin } from '../../utils/snippet-plugin.js';
5
5
  export default class List extends LoopressCommand {
6
6
  static description = 'List snippets from WordPress';
7
- static examples = [
8
- '$ lps snippet list',
9
- '$ lps snippet list --url http://example.com',
10
- '$ lps snippet list --plugin wpcode',
11
- ];
7
+ static examples = ['$ lps snippet list', '$ lps snippet list --plugin wpcode'];
12
8
  static flags = {
13
- ...LoopressCommand.baseFlags,
14
9
  json: Flags.boolean({ char: 'j', description: 'Output in JSON format' }),
15
- plugin: Flags.string({
16
- char: 'p',
17
- description: 'WordPress snippet plugin to target (overrides loopress.json)',
18
- options: ['code-snippets', 'wpcode'],
19
- }),
10
+ ...snippetPluginFlag,
20
11
  };
21
12
  async run() {
22
13
  const { flags } = await this.parse(List);
23
- const { json, plugin } = flags;
24
- const { url } = this.siteConfig;
25
- const resolvedPlugin = await this.resolveSnippetPlugin(plugin);
26
- try {
27
- const adapter = getSnippetPlugin(resolvedPlugin);
28
- const endpoint = adapter.endpoint(url);
29
- const headers = await this.buildAuthHeaders();
30
- const remoteList = await got.get(endpoint, { headers }).json();
31
- const snippets = remoteList.map((r) => adapter.fromRemote(r));
32
- if (json) {
33
- this.log(JSON.stringify(snippets, null, 2));
14
+ const adapter = getSnippetPlugin(this.resolveSnippetPlugin(flags.plugin));
15
+ const remoteList = await this.wp.get(adapter.endpointPath());
16
+ const snippets = remoteList.map((r) => adapter.fromRemote(r));
17
+ if (flags.json) {
18
+ this.log(JSON.stringify(snippets, null, 2));
19
+ return;
20
+ }
21
+ if (snippets.length === 0) {
22
+ this.log('No snippets found');
23
+ return;
24
+ }
25
+ this.log(`Found ${snippets.length} snippet${snippets.length === 1 ? '' : 's'}:`);
26
+ this.log('');
27
+ for (const snippet of snippets) {
28
+ this.log(` ${snippet.id}. ${snippet.name}`);
29
+ this.log(` Active: ${snippet.active ? 'yes' : 'no'}`);
30
+ if (snippet.tags.length > 0) {
31
+ this.log(` Tags: ${snippet.tags.join(', ')}`);
34
32
  }
35
- else {
36
- if (snippets.length === 0) {
37
- this.log('No snippets found');
38
- return;
39
- }
40
- this.log(`Found ${snippets.length} snippet${snippets.length === 1 ? '' : 's'}:`);
41
- console.log('');
42
- for (const snippet of snippets) {
43
- this.log(` ${snippet.id}. ${snippet.name}`);
44
- this.log(` Active: ${snippet.active ? '✓' : '✗'}`);
45
- if (snippet.tags && snippet.tags.length > 0) {
46
- this.log(` Tags: ${snippet.tags.join(', ')}`);
47
- }
48
- if (snippet.description) {
49
- this.log(` Description: ${snippet.description}`);
50
- }
51
- console.log('');
52
- }
33
+ if (snippet.description) {
34
+ this.log(` Description: ${snippet.description}`);
53
35
  }
54
- }
55
- catch (error) {
56
- this.error(`❌ Error listing snippets: ${error.message}`);
36
+ this.log('');
57
37
  }
58
38
  }
59
39
  }
@@ -9,11 +9,8 @@ export default class Pull extends LoopressCommand {
9
9
  static description: string;
10
10
  static examples: string[];
11
11
  static flags: {
12
- 'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
12
  plugin: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
- password: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
- url: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
- user: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ 'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
14
  };
18
15
  run(): Promise<void>;
19
16
  }
@@ -1,7 +1,10 @@
1
- import { Args, Flags } from '@oclif/core';
2
- import got from 'got';
1
+ import { Args } from '@oclif/core';
2
+ import { Listr } from 'listr2';
3
+ import { mkdir, writeFile } from 'node:fs/promises';
4
+ import { join } from 'node:path';
3
5
  import slugify from 'slugify';
4
6
  import { LoopressCommand } from '../../lib/base.js';
7
+ import { snippetPluginFlag } from '../../utils/snippet-plugin-flag.js';
5
8
  import { getSnippetPlugin } from '../../utils/snippet-plugin.js';
6
9
  const EXTENSIONS = {
7
10
  css: 'css',
@@ -22,11 +25,18 @@ export function buildMetaFile(snippet) {
22
25
  name: snippet.name,
23
26
  type: snippet.type,
24
27
  active: snippet.active,
28
+ location: snippet.location,
25
29
  };
26
30
  if (snippet.description)
27
31
  meta.description = snippet.description;
28
32
  if (snippet.tags.length > 0)
29
33
  meta.tags = snippet.tags;
34
+ if (snippet.insertMethod === 'shortcode')
35
+ meta.insertMethod = snippet.insertMethod;
36
+ if (snippet.priority !== 10)
37
+ meta.priority = snippet.priority;
38
+ if (snippet.shortcodeAttributes.length > 0)
39
+ meta.shortcodeAttributes = snippet.shortcodeAttributes;
30
40
  return JSON.stringify(meta, null, 2) + '\n';
31
41
  }
32
42
  export default class Pull extends LoopressCommand {
@@ -34,68 +44,42 @@ export default class Pull extends LoopressCommand {
34
44
  path: Args.string({ description: 'Path to snippets directory (overrides project config)' }),
35
45
  };
36
46
  static description = 'Pull snippets from WordPress';
37
- static examples = [
38
- '$ lps snippet pull',
39
- '$ lps snippet pull --url http://example.com',
40
- '$ lps snippet pull --path ./snippets',
41
- '$ lps snippet pull --plugin wpcode',
42
- ];
47
+ static examples = ['$ lps snippet pull', '$ lps snippet pull --path ./snippets', '$ lps snippet pull --plugin wpcode'];
43
48
  static flags = {
44
- ...LoopressCommand.baseFlags,
45
- 'dry-run': Flags.boolean({ char: 'd', description: 'Show what would be written without making changes' }),
46
- plugin: Flags.string({
47
- char: 'p',
48
- description: 'WordPress snippet plugin to target (overrides loopress.json)',
49
- options: ['code-snippets', 'wpcode'],
50
- }),
49
+ ...LoopressCommand.dryRunFlag,
50
+ ...snippetPluginFlag,
51
51
  };
52
52
  async run() {
53
53
  const { args, flags } = await this.parse(Pull);
54
- const dryRun = flags['dry-run'];
55
- const { plugin } = flags;
56
54
  const { url } = this.siteConfig;
57
- const path = await this.resolveSnippetsPath(args.path);
58
- const resolvedPlugin = await this.resolveSnippetPlugin(plugin);
59
- this.log(`📥 Pulling snippets from ${url} via ${resolvedPlugin}`);
60
- this.log(`📂 From snippet path: ${path}`);
61
- this.log(`🔄 Dry run: ${dryRun ? 'yes' : 'no'}`);
62
- try {
63
- const adapter = getSnippetPlugin(resolvedPlugin);
64
- const endpoint = adapter.endpoint(url);
65
- const headers = await this.buildAuthHeaders();
66
- const remoteList = await got.get(endpoint, { headers }).json();
67
- const snippets = remoteList.map((r) => adapter.fromRemote(r));
68
- const fs = await import('node:fs/promises');
69
- await fs.mkdir(path, { recursive: true });
70
- if (dryRun) {
71
- this.log(`📝 [DRY RUN] Would pull ${snippets.length} snippets`);
72
- this.log(`🔍 Raw API sample:\n${JSON.stringify(remoteList[0], null, 2)}`);
73
- return;
74
- }
75
- let count = 0;
76
- let skipped = 0;
77
- for (const snippet of snippets) {
78
- if (!snippet.name.trim()) {
79
- skipped++;
80
- continue;
81
- }
55
+ const path = this.resolveSnippetsPath(args.path);
56
+ const resolvedPlugin = this.resolveSnippetPlugin(flags.plugin);
57
+ this.log(`Pulling snippets from ${url} via ${resolvedPlugin}`);
58
+ this.log(`Snippets path: ${path}`);
59
+ const adapter = getSnippetPlugin(resolvedPlugin);
60
+ const remoteList = await this.wp.get(adapter.endpointPath());
61
+ const snippets = remoteList.map((r) => adapter.fromRemote(r));
62
+ if (this.dryRun) {
63
+ this.log(`[dry-run] Would pull ${snippets.length} snippet${snippets.length === 1 ? '' : 's'} to ${path}`);
64
+ return;
65
+ }
66
+ await mkdir(path, { recursive: true });
67
+ const pullable = snippets.filter((snippet) => snippet.name.trim());
68
+ const skipped = snippets.length - pullable.length;
69
+ await new Listr(pullable.map((snippet) => ({
70
+ async task(_ctx, task) {
82
71
  const ext = EXTENSIONS[snippet.type];
83
72
  const slug = slugify(snippet.name, { lower: true, strict: true });
84
73
  const base = `${snippet.id}-${slug}`;
85
- const filePath = `${path}/${base}.${ext}`;
86
- const metaPath = `${path}/${base}.json`;
87
- await fs.writeFile(filePath, buildSnippetFile(snippet));
88
- await fs.writeFile(metaPath, buildMetaFile(snippet));
89
- count++;
90
- this.log(`✅ Pulled: ${snippet.name}`);
91
- }
92
- this.log(`🎉 Successfully pulled ${count} snippet${count === 1 ? '' : 's'} to ${path}`);
93
- if (skipped > 0) {
94
- this.warn(`${skipped} snippet${skipped === 1 ? '' : 's'} skipped because they have no name`);
95
- }
96
- }
97
- catch (error) {
98
- this.error(`❌ Error pulling snippets: ${error.message}`);
74
+ await writeFile(join(path, `${base}.${ext}`), buildSnippetFile(snippet));
75
+ await writeFile(join(path, `${base}.json`), buildMetaFile(snippet));
76
+ task.output = `Pulled: ${snippet.name}`;
77
+ },
78
+ title: `Pull ${snippet.name}`,
79
+ }))).run();
80
+ this.log(`Pulled ${pullable.length} snippet${pullable.length === 1 ? '' : 's'} to ${path}`);
81
+ if (skipped > 0) {
82
+ this.warn(`${skipped} snippet${skipped === 1 ? '' : 's'} skipped because they have no name`);
99
83
  }
100
84
  }
101
85
  }
@@ -6,12 +6,10 @@ export default class Push extends PushCommand {
6
6
  static description: string;
7
7
  static examples: string[];
8
8
  static flags: {
9
- 'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
9
  plugin: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
- password: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
- url: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
- user: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ 'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
11
  };
12
+ private failedCount;
15
13
  run(): Promise<void>;
16
14
  private ensureCanonicalFilename;
17
15
  private loadSnippets;