@loopress/cli 0.8.0 → 0.10.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 +40 -71
- package/dist/commands/composer/pull.d.ts +0 -3
- package/dist/commands/composer/pull.js +0 -1
- package/dist/commands/composer/push.d.ts +0 -3
- package/dist/commands/composer/push.js +0 -1
- package/dist/commands/plugin/add.d.ts +0 -3
- package/dist/commands/plugin/add.js +0 -1
- package/dist/commands/plugin/pull.d.ts +0 -3
- package/dist/commands/plugin/pull.js +0 -1
- package/dist/commands/plugin/push.d.ts +3 -3
- package/dist/commands/plugin/push.js +63 -32
- package/dist/commands/sentry-test.d.ts +6 -0
- package/dist/commands/sentry-test.js +8 -0
- package/dist/commands/snippet/list.d.ts +0 -3
- package/dist/commands/snippet/list.js +1 -6
- package/dist/commands/snippet/pull.d.ts +0 -3
- package/dist/commands/snippet/pull.js +16 -23
- package/dist/commands/snippet/push.d.ts +1 -3
- package/dist/commands/snippet/push.js +25 -24
- 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 +0 -5
- package/dist/lib/base.js +1 -29
- package/dist/lib/sentry.d.ts +8 -0
- package/dist/lib/sentry.js +24 -0
- package/dist/types/config.d.ts +1 -19
- 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.generated.d.ts +46 -0
- package/dist/types/snippet.generated.js +2 -0
- package/dist/utils/loopress-config.d.ts +2 -7
- package/oclif.manifest.json +118 -292
- package/package.json +16 -3
- package/schemas/global-config.schema.json +83 -0
- package/schemas/project-config.schema.json +48 -0
- package/schemas/snippet.schema.json +61 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
|
+
import { Listr } from 'listr2';
|
|
2
3
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
3
4
|
import { join } from 'node:path';
|
|
4
5
|
import slugify from 'slugify';
|
|
@@ -43,14 +44,8 @@ export default class Pull extends LoopressCommand {
|
|
|
43
44
|
path: Args.string({ description: 'Path to snippets directory (overrides project config)' }),
|
|
44
45
|
};
|
|
45
46
|
static description = 'Pull snippets from WordPress';
|
|
46
|
-
static examples = [
|
|
47
|
-
'$ lps snippet pull',
|
|
48
|
-
'$ lps snippet pull --url http://example.com',
|
|
49
|
-
'$ lps snippet pull --path ./snippets',
|
|
50
|
-
'$ lps snippet pull --plugin wpcode',
|
|
51
|
-
];
|
|
47
|
+
static examples = ['$ lps snippet pull', '$ lps snippet pull --path ./snippets', '$ lps snippet pull --plugin wpcode'];
|
|
52
48
|
static flags = {
|
|
53
|
-
...LoopressCommand.baseFlags,
|
|
54
49
|
...LoopressCommand.dryRunFlag,
|
|
55
50
|
...snippetPluginFlag,
|
|
56
51
|
};
|
|
@@ -69,22 +64,20 @@ export default class Pull extends LoopressCommand {
|
|
|
69
64
|
return;
|
|
70
65
|
}
|
|
71
66
|
await mkdir(path, { recursive: true });
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
this.log(`Pulled ${count} snippet${count === 1 ? '' : 's'} to ${path}`);
|
|
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) {
|
|
71
|
+
const ext = EXTENSIONS[snippet.type];
|
|
72
|
+
const slug = slugify(snippet.name, { lower: true, strict: true });
|
|
73
|
+
const base = `${snippet.id}-${slug}`;
|
|
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}`);
|
|
88
81
|
if (skipped > 0) {
|
|
89
82
|
this.warn(`${skipped} snippet${skipped === 1 ? '' : 's'} skipped because they have no name`);
|
|
90
83
|
}
|
|
@@ -8,10 +8,8 @@ export default class Push extends PushCommand {
|
|
|
8
8
|
static flags: {
|
|
9
9
|
plugin: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
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>;
|
|
14
11
|
};
|
|
12
|
+
private failedCount;
|
|
15
13
|
run(): Promise<void>;
|
|
16
14
|
private ensureCanonicalFilename;
|
|
17
15
|
private loadSnippets;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
|
+
import { Listr } from 'listr2';
|
|
2
3
|
import { readdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
3
4
|
import { basename, dirname, extname, join } from 'node:path';
|
|
4
5
|
import slugify from 'slugify';
|
|
@@ -17,17 +18,12 @@ export default class Push extends PushCommand {
|
|
|
17
18
|
path: Args.string({ description: 'Path to snippets directory (overrides project config)' }),
|
|
18
19
|
};
|
|
19
20
|
static description = 'Push snippets to WordPress. Local snippet files created or updated remotely are renamed on disk to the `<id>-<slug>` convention.';
|
|
20
|
-
static examples = [
|
|
21
|
-
'$ lps snippet push',
|
|
22
|
-
'$ lps snippet push --url http://example.com',
|
|
23
|
-
'$ lps snippet push --path ./snippets',
|
|
24
|
-
'$ lps snippet push --plugin wpcode',
|
|
25
|
-
];
|
|
21
|
+
static examples = ['$ lps snippet push', '$ lps snippet push --path ./snippets', '$ lps snippet push --plugin wpcode'];
|
|
26
22
|
static flags = {
|
|
27
|
-
...PushCommand.baseFlags,
|
|
28
23
|
...PushCommand.dryRunFlag,
|
|
29
24
|
...snippetPluginFlag,
|
|
30
25
|
};
|
|
26
|
+
failedCount = 0;
|
|
31
27
|
async run() {
|
|
32
28
|
const { args, flags } = await this.parse(Push);
|
|
33
29
|
const { url } = this.siteConfig;
|
|
@@ -38,14 +34,12 @@ export default class Push extends PushCommand {
|
|
|
38
34
|
const snippets = await this.loadSnippets(path);
|
|
39
35
|
this.log(`Found ${snippets.length} snippet${snippets.length === 1 ? '' : 's'} to push`);
|
|
40
36
|
const adapter = getSnippetPlugin(resolvedPlugin);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (failed > 0) {
|
|
48
|
-
this.error(`${failed} snippet${failed === 1 ? '' : 's'} failed to push.`);
|
|
37
|
+
await new Listr(snippets.map((snippet) => ({
|
|
38
|
+
task: async (_ctx, task) => this.pushSnippet(snippet, adapter, task),
|
|
39
|
+
title: `Push ${snippet.name}`,
|
|
40
|
+
})), { concurrent: false, exitOnError: false }).run();
|
|
41
|
+
if (this.failedCount > 0) {
|
|
42
|
+
this.error(`${this.failedCount} snippet${this.failedCount === 1 ? '' : 's'} failed to push.`);
|
|
49
43
|
}
|
|
50
44
|
if (this.dryRun)
|
|
51
45
|
return;
|
|
@@ -85,7 +79,6 @@ export default class Push extends PushCommand {
|
|
|
85
79
|
await rename(snippet.path, newPath);
|
|
86
80
|
await writeFile(newMetaPath, JSON.stringify(meta, null, 2) + '\n');
|
|
87
81
|
await rm(oldMetaPath, { force: true });
|
|
88
|
-
this.log(` Renamed: ${snippet.path} → ${newPath}`);
|
|
89
82
|
}
|
|
90
83
|
async loadSnippets(path) {
|
|
91
84
|
const snippets = [];
|
|
@@ -145,30 +138,38 @@ export default class Push extends PushCommand {
|
|
|
145
138
|
}
|
|
146
139
|
return snippets;
|
|
147
140
|
}
|
|
148
|
-
|
|
141
|
+
// Throwing on failure (rather than returning a boolean) is what lets Listr mark the task as
|
|
142
|
+
// failed (red cross) instead of completed; `exitOnError: false` on the task list still lets
|
|
143
|
+
// sibling snippets push regardless.
|
|
144
|
+
async pushSnippet(snippet, adapter, task) {
|
|
149
145
|
if (this.dryRun) {
|
|
150
|
-
|
|
151
|
-
|
|
146
|
+
if (task)
|
|
147
|
+
task.output = `[dry-run] Would push: ${snippet.name}`;
|
|
148
|
+
return;
|
|
152
149
|
}
|
|
153
150
|
const endpointPath = adapter.endpointPath();
|
|
154
151
|
try {
|
|
155
152
|
const payload = adapter.toPayload(snippet);
|
|
156
153
|
if (snippet.id) {
|
|
157
154
|
await this.wp.put(`${endpointPath}/${snippet.id}`, payload);
|
|
158
|
-
this.log(` Updated: ${snippet.name} (id: ${snippet.id})`);
|
|
159
155
|
await this.ensureCanonicalFilename(snippet, snippet.id, snippet.name);
|
|
160
156
|
}
|
|
161
157
|
else {
|
|
162
158
|
const response = await this.wp.post(endpointPath, payload);
|
|
163
159
|
const created = adapter.fromRemote(response);
|
|
164
|
-
this.log(` Created: ${snippet.name} (id: ${created.id})`);
|
|
165
160
|
await this.ensureCanonicalFilename(snippet, created.id, created.name);
|
|
166
161
|
}
|
|
167
|
-
|
|
162
|
+
if (task)
|
|
163
|
+
task.output = `Pushed: ${snippet.name}`;
|
|
168
164
|
}
|
|
169
165
|
catch (error) {
|
|
170
|
-
|
|
171
|
-
|
|
166
|
+
const message = `Failed to push ${snippet.name}: ${error.message}`;
|
|
167
|
+
if (task)
|
|
168
|
+
task.output = message;
|
|
169
|
+
else
|
|
170
|
+
this.warn(` ${message}`);
|
|
171
|
+
this.failedCount++;
|
|
172
|
+
throw error;
|
|
172
173
|
}
|
|
173
174
|
}
|
|
174
175
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/node';
|
|
2
|
+
import { isTelemetryDisabled, runtimeContext } from '../lib/sentry.js';
|
|
3
|
+
// oclif has no `command_error` hook (checked @oclif/core@4.11.11's hooks.d.ts). `finally`
|
|
4
|
+
// is the closest equivalent: it always runs at the end of the CLI lifecycle and carries
|
|
5
|
+
// the error, if any, so it's where we report crashes before the process exits.
|
|
6
|
+
const hook = async function (options) {
|
|
7
|
+
if (!options.error || isTelemetryDisabled())
|
|
8
|
+
return;
|
|
9
|
+
try {
|
|
10
|
+
Sentry.captureException(options.error, {
|
|
11
|
+
contexts: { runtime: runtimeContext() },
|
|
12
|
+
extra: { argv: options.argv },
|
|
13
|
+
tags: { command: options.id },
|
|
14
|
+
});
|
|
15
|
+
await Sentry.flush(2000);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
this.debug('Failed to report error to Sentry: %O', error);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
export default hook;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/node';
|
|
2
|
+
import { consumeErrorReportingFlag, isTelemetryDisabled, resolveEnvironment, SENTRY_DSN } from '../lib/sentry.js';
|
|
3
|
+
const hook = async function (options) {
|
|
4
|
+
consumeErrorReportingFlag(options.argv);
|
|
5
|
+
if (isTelemetryDisabled())
|
|
6
|
+
return;
|
|
7
|
+
try {
|
|
8
|
+
Sentry.init({
|
|
9
|
+
dsn: SENTRY_DSN,
|
|
10
|
+
environment: resolveEnvironment(),
|
|
11
|
+
release: this.config.version,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
this.debug('Failed to initialize Sentry: %O', error);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
export default hook;
|
package/dist/lib/base.d.ts
CHANGED
|
@@ -3,11 +3,6 @@ import { EnvironmentConfig } from '../types/config.js';
|
|
|
3
3
|
import { LoopressLocalConfig } from '../utils/loopress-config.js';
|
|
4
4
|
import { WpClient } from './wp-client.js';
|
|
5
5
|
export declare abstract class LoopressCommand extends Command {
|
|
6
|
-
static baseFlags: {
|
|
7
|
-
password: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
-
url: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
-
user: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
};
|
|
11
6
|
static dryRunFlag: {
|
|
12
7
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
8
|
};
|
package/dist/lib/base.js
CHANGED
|
@@ -4,20 +4,6 @@ import { configManager } from '../config/project-config.manager.js';
|
|
|
4
4
|
import { readLocalConfig } from '../utils/loopress-config.js';
|
|
5
5
|
import { WpClient } from './wp-client.js';
|
|
6
6
|
export class LoopressCommand extends Command {
|
|
7
|
-
static baseFlags = {
|
|
8
|
-
password: Flags.string({
|
|
9
|
-
description: 'WordPress application password (overrides project config, requires --user)',
|
|
10
|
-
helpGroup: 'GLOBAL',
|
|
11
|
-
}),
|
|
12
|
-
url: Flags.string({
|
|
13
|
-
description: 'WordPress URL (overrides project config)',
|
|
14
|
-
helpGroup: 'GLOBAL',
|
|
15
|
-
}),
|
|
16
|
-
user: Flags.string({
|
|
17
|
-
description: 'WordPress username (overrides project config, requires --password)',
|
|
18
|
-
helpGroup: 'GLOBAL',
|
|
19
|
-
}),
|
|
20
|
-
};
|
|
21
7
|
static dryRunFlag = {
|
|
22
8
|
'dry-run': Flags.boolean({ char: 'd', description: 'Show what would change without making changes' }),
|
|
23
9
|
};
|
|
@@ -47,21 +33,7 @@ export class LoopressCommand extends Command {
|
|
|
47
33
|
}));
|
|
48
34
|
this.dryRun = Boolean(flags['dry-run']);
|
|
49
35
|
this.localConfig = await readLocalConfig();
|
|
50
|
-
|
|
51
|
-
this.error('--user and --password must be provided together.');
|
|
52
|
-
}
|
|
53
|
-
const flagToken = flags.user && flags.password ? `${flags.user}:${flags.password}` : undefined;
|
|
54
|
-
if (flags.url) {
|
|
55
|
-
this.siteConfig = {
|
|
56
|
-
addedAt: new Date().toISOString(),
|
|
57
|
-
name: 'cli-flags',
|
|
58
|
-
token: flagToken,
|
|
59
|
-
url: flags.url.replace(/\/+$/, ''),
|
|
60
|
-
};
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
const env = this.resolveEnvironment();
|
|
64
|
-
this.siteConfig = flagToken ? { ...env, token: flagToken } : env;
|
|
36
|
+
this.siteConfig = this.resolveEnvironment();
|
|
65
37
|
}
|
|
66
38
|
resolveSnippetPlugin(flag) {
|
|
67
39
|
if (flag)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const SENTRY_DSN = "https://a08dd56bfffc2a45d5b8f665e4cb8b7d@o4511586904309760.ingest.de.sentry.io/4511673275973712";
|
|
2
|
+
export declare function consumeErrorReportingFlag(argv: string[]): void;
|
|
3
|
+
export declare function isTelemetryDisabled(): boolean;
|
|
4
|
+
export declare function resolveEnvironment(): string;
|
|
5
|
+
export declare function runtimeContext(): {
|
|
6
|
+
node: string;
|
|
7
|
+
os: string;
|
|
8
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { platform, release } from 'node:os';
|
|
2
|
+
// DSNs are write-only and safe to embed in a distributed CLI, see https://docs.sentry.io/product/security/#can-i-make-my-sentry-dsn-private
|
|
3
|
+
export const SENTRY_DSN = 'https://a08dd56bfffc2a45d5b8f665e4cb8b7d@o4511586904309760.ingest.de.sentry.io/4511673275973712';
|
|
4
|
+
export function consumeErrorReportingFlag(argv) {
|
|
5
|
+
const index = argv.indexOf('--no-error-reporting');
|
|
6
|
+
if (index === -1)
|
|
7
|
+
return;
|
|
8
|
+
argv.splice(index, 1);
|
|
9
|
+
process.env.LOOPRESS_TELEMETRY_DISABLED = '1';
|
|
10
|
+
}
|
|
11
|
+
export function isTelemetryDisabled() {
|
|
12
|
+
return process.env.LOOPRESS_TELEMETRY_DISABLED === '1';
|
|
13
|
+
}
|
|
14
|
+
export function resolveEnvironment() {
|
|
15
|
+
if (process.env.SENTRY_ENVIRONMENT)
|
|
16
|
+
return process.env.SENTRY_ENVIRONMENT;
|
|
17
|
+
return process.env.NODE_ENV === 'development' ? 'development' : 'production';
|
|
18
|
+
}
|
|
19
|
+
export function runtimeContext() {
|
|
20
|
+
return {
|
|
21
|
+
node: process.version,
|
|
22
|
+
os: `${platform()} ${release()}`,
|
|
23
|
+
};
|
|
24
|
+
}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -1,19 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
addedAt: string;
|
|
3
|
-
name: string;
|
|
4
|
-
token?: string;
|
|
5
|
-
url: string;
|
|
6
|
-
}
|
|
7
|
-
export interface ProjectConfig {
|
|
8
|
-
addedAt: string;
|
|
9
|
-
environments: Record<string, EnvironmentConfig>;
|
|
10
|
-
name: string;
|
|
11
|
-
}
|
|
12
|
-
export interface CurrentProjectPointer {
|
|
13
|
-
env: string;
|
|
14
|
-
id: string;
|
|
15
|
-
}
|
|
16
|
-
export interface LoopressConfig {
|
|
17
|
-
currentProject: CurrentProjectPointer | null;
|
|
18
|
-
projects: Record<string, ProjectConfig>;
|
|
19
|
-
}
|
|
1
|
+
export type { CurrentProjectPointer, EnvironmentConfig, LoopressGlobalConfiguration as LoopressConfig, ProjectConfig, } from './global-config.generated.js';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global CLI state stored at ~/.loopress/config.json: known projects, their environments, and which one is currently active.
|
|
3
|
+
*/
|
|
4
|
+
export interface LoopressGlobalConfiguration {
|
|
5
|
+
/**
|
|
6
|
+
* Pointer to the currently active project and environment, or null if none is selected.
|
|
7
|
+
*/
|
|
8
|
+
currentProject: null | CurrentProjectPointer;
|
|
9
|
+
/**
|
|
10
|
+
* Known projects, keyed by project id.
|
|
11
|
+
*/
|
|
12
|
+
projects: {
|
|
13
|
+
[k: string]: ProjectConfig;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface CurrentProjectPointer {
|
|
17
|
+
/**
|
|
18
|
+
* Name of the currently active environment.
|
|
19
|
+
*/
|
|
20
|
+
env: string;
|
|
21
|
+
/**
|
|
22
|
+
* Id of the currently active project.
|
|
23
|
+
*/
|
|
24
|
+
id: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ProjectConfig {
|
|
27
|
+
/**
|
|
28
|
+
* ISO timestamp of when the project was added.
|
|
29
|
+
*/
|
|
30
|
+
addedAt: string;
|
|
31
|
+
/**
|
|
32
|
+
* Environments for this project, keyed by environment name.
|
|
33
|
+
*/
|
|
34
|
+
environments: {
|
|
35
|
+
[k: string]: EnvironmentConfig;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Human-readable project name.
|
|
39
|
+
*/
|
|
40
|
+
name: string;
|
|
41
|
+
}
|
|
42
|
+
export interface EnvironmentConfig {
|
|
43
|
+
/**
|
|
44
|
+
* ISO timestamp of when the environment was added.
|
|
45
|
+
*/
|
|
46
|
+
addedAt: string;
|
|
47
|
+
/**
|
|
48
|
+
* Environment name (e.g. "production", "staging").
|
|
49
|
+
*/
|
|
50
|
+
name: string;
|
|
51
|
+
/**
|
|
52
|
+
* API token used to authenticate against this environment.
|
|
53
|
+
*/
|
|
54
|
+
token?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Base URL of the WordPress site for this environment.
|
|
57
|
+
*/
|
|
58
|
+
url: string;
|
|
59
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-level config for the Loopress CLI (loopress.json).
|
|
3
|
+
*/
|
|
4
|
+
export interface LoopressProjectConfiguration {
|
|
5
|
+
$schema?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Base directory for all Loopress paths. All other path options are resolved relative to this directory.
|
|
8
|
+
*/
|
|
9
|
+
rootDir?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Directory where code snippets are read from and written to, relative to rootDir.
|
|
12
|
+
*/
|
|
13
|
+
snippetsDir?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Project identifier from the global Loopress config. When set, takes precedence over the currently active project in the global config.
|
|
16
|
+
*/
|
|
17
|
+
projectId?: string;
|
|
18
|
+
/**
|
|
19
|
+
* WordPress snippet plugin to use for pull and push commands.
|
|
20
|
+
*/
|
|
21
|
+
snippetPlugin?: 'wpcode' | 'code-snippets';
|
|
22
|
+
/**
|
|
23
|
+
* Pinned plugin versions. Keys are WordPress.org plugin slugs, values are version constraints.
|
|
24
|
+
*/
|
|
25
|
+
plugins?: {
|
|
26
|
+
/**
|
|
27
|
+
* Version to pin. Use an exact version (e.g. "8.9.1") or "latest".
|
|
28
|
+
*/
|
|
29
|
+
[k: string]: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sidecar .json file paired with a snippet's code file in the snippets directory (e.g. `123-my-snippet.php` + `123-my-snippet.json`).
|
|
3
|
+
*/
|
|
4
|
+
export interface LoopressSnippetMetadata {
|
|
5
|
+
$schema?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Remote snippet id. Omitted until the snippet has been pushed for the first time.
|
|
8
|
+
*/
|
|
9
|
+
id?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Snippet name/title. Defaults to the code file's name when omitted.
|
|
12
|
+
*/
|
|
13
|
+
name?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Snippet language. Defaults to the type inferred from the code file's extension when omitted.
|
|
16
|
+
*/
|
|
17
|
+
type?: 'css' | 'html' | 'js' | 'php' | 'text';
|
|
18
|
+
/**
|
|
19
|
+
* Whether the snippet is enabled.
|
|
20
|
+
*/
|
|
21
|
+
active?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Where the snippet runs. Supported values depend on the target plugin and snippet type.
|
|
24
|
+
*/
|
|
25
|
+
location?: 'admin' | 'body' | 'everywhere' | 'footer' | 'frontend' | 'header' | 'once';
|
|
26
|
+
/**
|
|
27
|
+
* Free-text note about the snippet.
|
|
28
|
+
*/
|
|
29
|
+
description?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Tags for organizing snippets.
|
|
32
|
+
*/
|
|
33
|
+
tags?: string[];
|
|
34
|
+
/**
|
|
35
|
+
* How the snippet is inserted into the page.
|
|
36
|
+
*/
|
|
37
|
+
insertMethod?: 'auto' | 'shortcode';
|
|
38
|
+
/**
|
|
39
|
+
* Execution priority. Lower runs earlier.
|
|
40
|
+
*/
|
|
41
|
+
priority?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Attribute names accepted by the snippet's shortcode, used when insertMethod is "shortcode".
|
|
44
|
+
*/
|
|
45
|
+
shortcodeAttributes?: string[];
|
|
46
|
+
}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
projectId?: string;
|
|
4
|
-
rootDir?: string;
|
|
5
|
-
snippetPlugin?: 'code-snippets' | 'wpcode';
|
|
6
|
-
snippetsDir?: string;
|
|
7
|
-
}
|
|
1
|
+
import { LoopressProjectConfiguration } from '../types/project-config.generated.js';
|
|
2
|
+
export type LoopressLocalConfig = LoopressProjectConfiguration;
|
|
8
3
|
export declare function readLocalConfig(): Promise<LoopressLocalConfig>;
|
|
9
4
|
export declare function writeLocalConfig(config: LoopressLocalConfig): Promise<void>;
|