@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.
- package/README.md +44 -75
- package/dist/commands/composer/pull.d.ts +0 -3
- package/dist/commands/composer/pull.js +4 -15
- package/dist/commands/composer/push.d.ts +0 -3
- package/dist/commands/composer/push.js +7 -17
- package/dist/commands/login.js +1 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/plugin/add.d.ts +0 -3
- package/dist/commands/plugin/add.js +9 -10
- package/dist/commands/plugin/pull.d.ts +0 -3
- package/dist/commands/plugin/pull.js +7 -19
- package/dist/commands/plugin/push.d.ts +4 -3
- package/dist/commands/plugin/push.js +69 -63
- package/dist/commands/sentry-test.d.ts +6 -0
- package/dist/commands/sentry-test.js +8 -0
- package/dist/commands/snippet/list.d.ts +1 -4
- package/dist/commands/snippet/list.js +24 -44
- package/dist/commands/snippet/pull.d.ts +1 -4
- package/dist/commands/snippet/pull.js +40 -56
- package/dist/commands/snippet/push.d.ts +2 -4
- package/dist/commands/snippet/push.js +90 -77
- package/dist/config/auth.manager.d.ts +0 -2
- package/dist/config/auth.manager.js +5 -25
- package/dist/config/json-file.d.ts +2 -0
- package/dist/config/json-file.js +21 -0
- package/dist/config/project-config.manager.d.ts +1 -3
- package/dist/config/project-config.manager.js +7 -23
- package/dist/hooks/finally.d.ts +3 -0
- package/dist/hooks/finally.js +21 -0
- package/dist/hooks/init.d.ts +3 -0
- package/dist/hooks/init.js +18 -0
- package/dist/lib/base.d.ts +13 -8
- package/dist/lib/base.js +45 -43
- package/dist/lib/push-command.d.ts +0 -1
- package/dist/lib/push-command.js +0 -1
- package/dist/lib/sentry.d.ts +8 -0
- package/dist/lib/sentry.js +24 -0
- package/dist/lib/wp-client.d.ts +15 -0
- package/dist/lib/wp-client.js +53 -0
- package/dist/types/config.d.ts +1 -0
- package/dist/types/global-config.generated.d.ts +59 -0
- package/dist/types/global-config.generated.js +2 -0
- package/dist/types/project-config.generated.d.ts +31 -0
- package/dist/types/project-config.generated.js +2 -0
- package/dist/types/snippet.d.ts +7 -1
- package/dist/types/snippet.generated.d.ts +46 -0
- package/dist/types/snippet.generated.js +2 -0
- package/dist/utils/loopress-config.d.ts +2 -7
- package/dist/utils/loopress-config.js +5 -2
- package/dist/utils/snippet-plugin-flag.d.ts +3 -0
- package/dist/utils/snippet-plugin-flag.js +8 -0
- package/dist/utils/snippet-plugin.d.ts +23 -2
- package/dist/utils/snippet-plugin.js +168 -13
- package/oclif.manifest.json +66 -200
- package/package.json +19 -5
- package/dist/config/types.d.ts +0 -19
- package/dist/types/menu.d.ts +0 -7
- package/dist/types/menu.js +0 -1
- /package/dist/{config/types.js → types/config.js} +0 -0
|
@@ -1,24 +1,18 @@
|
|
|
1
1
|
import { confirm } from '@inquirer/prompts';
|
|
2
|
-
import {
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
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 (
|
|
90
|
-
|
|
91
|
-
continue;
|
|
114
|
+
if (proceed) {
|
|
115
|
+
confirmedDrift.push(action);
|
|
92
116
|
}
|
|
93
|
-
|
|
94
|
-
|
|
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,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
|
-
|
|
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
|
-
|
|
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
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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
|
|
2
|
-
import
|
|
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.
|
|
45
|
-
|
|
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 =
|
|
58
|
-
const resolvedPlugin =
|
|
59
|
-
this.log(
|
|
60
|
-
this.log(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
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;
|