@patto/cli 0.1.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/LICENSE +661 -0
- package/README.md +323 -0
- package/dist/commands/core.d.ts +3 -0
- package/dist/commands/core.js +82 -0
- package/dist/commands/core.js.map +1 -0
- package/dist/commands/generate.d.ts +2 -0
- package/dist/commands/generate.js +231 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/core/resolve.d.ts +4 -0
- package/dist/core/resolve.js +62 -0
- package/dist/core/resolve.js.map +1 -0
- package/dist/core/run.d.ts +2 -0
- package/dist/core/run.js +53 -0
- package/dist/core/run.js.map +1 -0
- package/dist/core/stdin.d.ts +2 -0
- package/dist/core/stdin.js +30 -0
- package/dist/core/stdin.js.map +1 -0
- package/dist/core/types.d.ts +44 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/output/diagnostics.d.ts +8 -0
- package/dist/output/diagnostics.js +85 -0
- package/dist/output/diagnostics.js.map +1 -0
- package/dist/scaffold/names.d.ts +14 -0
- package/dist/scaffold/names.js +75 -0
- package/dist/scaffold/names.js.map +1 -0
- package/dist/scaffold/project.d.ts +13 -0
- package/dist/scaffold/project.js +41 -0
- package/dist/scaffold/project.js.map +1 -0
- package/dist/scaffold/templates.d.ts +34 -0
- package/dist/scaffold/templates.js +204 -0
- package/dist/scaffold/templates.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
7
|
+
const currentDir = path.dirname(currentFile);
|
|
8
|
+
export class CoreBinaryError extends Error {
|
|
9
|
+
code = 'patto_cli_core_unavailable';
|
|
10
|
+
}
|
|
11
|
+
export function resolveCoreBinary() {
|
|
12
|
+
const platformPackage = getPlatformPackage();
|
|
13
|
+
if (platformPackage === undefined) {
|
|
14
|
+
throw new CoreBinaryError(`Patto CLI aun no tiene binario compatible para ${process.platform}-${process.arch}. ` +
|
|
15
|
+
'Plataformas soportadas: linux-x64, linux-arm64 y win32-x64.');
|
|
16
|
+
}
|
|
17
|
+
const packageBinary = resolvePackageBinary(platformPackage);
|
|
18
|
+
if (packageBinary !== undefined) {
|
|
19
|
+
return packageBinary;
|
|
20
|
+
}
|
|
21
|
+
const workspaceBinary = path.resolve(currentDir, '..', '..', '..', platformPackage.workspaceDir, 'bin', platformPackage.binaryName);
|
|
22
|
+
if (existsSync(workspaceBinary)) {
|
|
23
|
+
return workspaceBinary;
|
|
24
|
+
}
|
|
25
|
+
throw new CoreBinaryError(`No encontre el binario nativo ${platformPackage.name}. ` +
|
|
26
|
+
'Ejecuta el build del core o reinstala @patto/cli para descargar la optionalDependency correcta.');
|
|
27
|
+
}
|
|
28
|
+
function resolvePackageBinary(platformPackage) {
|
|
29
|
+
try {
|
|
30
|
+
const packageJsonPath = require.resolve(`${platformPackage.name}/package.json`);
|
|
31
|
+
const binaryPath = path.join(path.dirname(packageJsonPath), 'bin', platformPackage.binaryName);
|
|
32
|
+
return existsSync(binaryPath) ? binaryPath : undefined;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function getPlatformPackage() {
|
|
39
|
+
if (process.platform === 'linux' && process.arch === 'x64') {
|
|
40
|
+
return {
|
|
41
|
+
name: '@patto/cli-core-linux-x64',
|
|
42
|
+
workspaceDir: 'cli-core-linux-x64',
|
|
43
|
+
binaryName: 'patto-core',
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (process.platform === 'linux' && process.arch === 'arm64') {
|
|
47
|
+
return {
|
|
48
|
+
name: '@patto/cli-core-linux-arm64',
|
|
49
|
+
workspaceDir: 'cli-core-linux-arm64',
|
|
50
|
+
binaryName: 'patto-core',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (process.platform === 'win32' && process.arch === 'x64') {
|
|
54
|
+
return {
|
|
55
|
+
name: '@patto/cli-core-win32-x64',
|
|
56
|
+
workspaceDir: 'cli-core-win32-x64',
|
|
57
|
+
binaryName: 'patto-core.exe',
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/core/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;AAQ7C,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC7B,IAAI,GAAG,4BAA4B,CAAC;CAChD;AAED,MAAM,UAAU,iBAAiB;IAC7B,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAC;IAE7C,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,IAAI,eAAe,CACrB,kDAAkD,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,IAAI;YAClF,6DAA6D,CACpE,CAAC;IACN,CAAC;IAED,MAAM,aAAa,GAAG,oBAAoB,CAAC,eAAe,CAAC,CAAC;IAE5D,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,aAAa,CAAC;IACzB,CAAC;IAED,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAChC,UAAU,EACV,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,eAAe,CAAC,YAAY,EAC5B,KAAK,EACL,eAAe,CAAC,UAAU,CAC7B,CAAC;IAEF,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAC9B,OAAO,eAAe,CAAC;IAC3B,CAAC;IAED,MAAM,IAAI,eAAe,CACrB,iCAAiC,eAAe,CAAC,IAAI,IAAI;QACrD,iGAAiG,CACxG,CAAC;AACN,CAAC;AAED,SAAS,oBAAoB,CAAC,eAAgC;IAC1D,IAAI,CAAC;QACD,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,eAAe,CAAC,IAAI,eAAe,CAAC,CAAC;QAChF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CACxB,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,EAC7B,KAAK,EACL,eAAe,CAAC,UAAU,CAC7B,CAAC;QAEF,OAAO,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,SAAS,CAAC;IACrB,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB;IACvB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QACzD,OAAO;YACH,IAAI,EAAE,2BAA2B;YACjC,YAAY,EAAE,oBAAoB;YAClC,UAAU,EAAE,YAAY;SAC3B,CAAC;IACN,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3D,OAAO;YACH,IAAI,EAAE,6BAA6B;YACnC,YAAY,EAAE,sBAAsB;YACpC,UAAU,EAAE,YAAY;SAC3B,CAAC;IACN,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QACzD,OAAO;YACH,IAAI,EAAE,2BAA2B;YACjC,YAAY,EAAE,oBAAoB;YAClC,UAAU,EAAE,gBAAgB;SAC/B,CAAC;IACN,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC"}
|
package/dist/core/run.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { resolveCoreBinary } from './resolve.js';
|
|
3
|
+
export async function runCore(options) {
|
|
4
|
+
const binary = resolveCoreBinary();
|
|
5
|
+
const args = [options.command, '--json'];
|
|
6
|
+
if (options.root !== undefined) {
|
|
7
|
+
args.push('--root', options.root);
|
|
8
|
+
}
|
|
9
|
+
if (options.lang !== undefined) {
|
|
10
|
+
args.push('--lang', options.lang);
|
|
11
|
+
}
|
|
12
|
+
const { exitCode, stdout, stderr } = await runProcess(binary, args);
|
|
13
|
+
return {
|
|
14
|
+
command: options.command,
|
|
15
|
+
exitCode,
|
|
16
|
+
stdout,
|
|
17
|
+
stderr,
|
|
18
|
+
output: parseCoreOutput(stdout),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function runProcess(binary, args) {
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
const child = spawn(binary, args, {
|
|
24
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
25
|
+
windowsHide: true,
|
|
26
|
+
});
|
|
27
|
+
const stdout = [];
|
|
28
|
+
const stderr = [];
|
|
29
|
+
child.stdout.on('data', (chunk) => stdout.push(chunk));
|
|
30
|
+
child.stderr.on('data', (chunk) => stderr.push(chunk));
|
|
31
|
+
child.on('error', reject);
|
|
32
|
+
child.on('close', (code) => {
|
|
33
|
+
resolve({
|
|
34
|
+
exitCode: code ?? 1,
|
|
35
|
+
stdout: Buffer.concat(stdout).toString('utf8'),
|
|
36
|
+
stderr: Buffer.concat(stderr).toString('utf8'),
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function parseCoreOutput(stdout) {
|
|
42
|
+
const trimmed = stdout.trim();
|
|
43
|
+
if (trimmed.length === 0) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
return JSON.parse(trimmed);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/core/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAuB;IACjD,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAEzC,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAEpE,OAAO;QACH,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,QAAQ;QACR,MAAM;QACN,MAAM;QACN,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC;KAClC,CAAC;AACN,CAAC;AAED,SAAS,UAAU,CACf,MAAc,EACd,IAAc;IAEd,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE;YAC9B,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;YACjC,WAAW,EAAE,IAAI;SACpB,CAAC,CAAC;QACH,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/D,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACvB,OAAO,CAAC;gBACJ,QAAQ,EAAE,IAAI,IAAI,CAAC;gBACnB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAC9C,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;aACjD,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,eAAe,CAAC,MAAc;IACnC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAE9B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { stdin } from 'node:process';
|
|
2
|
+
export async function readCoreRequest(defaultCommand) {
|
|
3
|
+
const raw = await readStdin();
|
|
4
|
+
const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
|
|
5
|
+
const command = parsed.command ?? defaultCommand;
|
|
6
|
+
if (command === undefined) {
|
|
7
|
+
throw new Error('El JSON de stdin debe incluir "command".');
|
|
8
|
+
}
|
|
9
|
+
if (!isCoreCommand(command)) {
|
|
10
|
+
throw new Error('El comando debe ser scan, lint, doctor o check.');
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
command,
|
|
14
|
+
root: parsed.root ?? process.cwd(),
|
|
15
|
+
lang: parsed.lang ?? 'auto',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function readStdin() {
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
const chunks = [];
|
|
21
|
+
stdin.on('data', (chunk) => chunks.push(chunk));
|
|
22
|
+
stdin.on('error', reject);
|
|
23
|
+
stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
|
24
|
+
stdin.resume();
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function isCoreCommand(value) {
|
|
28
|
+
return value === 'scan' || value === 'lint' || value === 'doctor' || value === 'check';
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=stdin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdin.js","sourceRoot":"","sources":["../../src/core/stdin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAGrC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,cAA4B;IAC9D,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiB,CAAC;IAC/E,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,cAAc,CAAC;IAEjD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACvE,CAAC;IAED,OAAO;QACH,OAAO;QACP,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE;QAClC,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,MAAM;KAC9B,CAAC;AACN,CAAC;AAED,SAAS,SAAS;IACd,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnC,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACxD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvE,KAAK,CAAC,MAAM,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAChC,OAAO,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,OAAO,CAAC;AAC3F,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export type CoreCommand = 'scan' | 'lint' | 'doctor' | 'check';
|
|
2
|
+
export type DiagnosticLevel = 'error' | 'warning' | 'info';
|
|
3
|
+
export interface CoreDiagnostic {
|
|
4
|
+
readonly level: DiagnosticLevel;
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly message: string;
|
|
7
|
+
readonly file?: string | null;
|
|
8
|
+
readonly line?: number | null;
|
|
9
|
+
readonly column?: number | null;
|
|
10
|
+
readonly hint?: string | null;
|
|
11
|
+
}
|
|
12
|
+
export interface CoreOutput {
|
|
13
|
+
readonly status?: string;
|
|
14
|
+
readonly command?: string;
|
|
15
|
+
readonly diagnostics?: CoreDiagnostic[];
|
|
16
|
+
readonly summary?: unknown;
|
|
17
|
+
readonly stats?: unknown;
|
|
18
|
+
readonly [key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
export interface CoreRequest {
|
|
21
|
+
readonly command?: CoreCommand;
|
|
22
|
+
readonly root?: string;
|
|
23
|
+
readonly lang?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface CoreRunOptions {
|
|
26
|
+
readonly command: CoreCommand;
|
|
27
|
+
readonly root?: string;
|
|
28
|
+
readonly lang?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface CoreRunResult {
|
|
31
|
+
readonly command: CoreCommand;
|
|
32
|
+
readonly exitCode: number;
|
|
33
|
+
readonly stdout: string;
|
|
34
|
+
readonly stderr: string;
|
|
35
|
+
readonly output: CoreOutput | null;
|
|
36
|
+
}
|
|
37
|
+
export interface CoreEnvelope {
|
|
38
|
+
readonly ok: boolean;
|
|
39
|
+
readonly command: CoreCommand;
|
|
40
|
+
readonly exitCode: number;
|
|
41
|
+
readonly stderr: string;
|
|
42
|
+
readonly output: CoreOutput | null;
|
|
43
|
+
readonly diagnostics: CoreDiagnostic[];
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":""}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { cac } from 'cac';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { registerCoreCommands, writeStructuredError } from './commands/core.js';
|
|
5
|
+
import { registerGenerateCommand } from './commands/generate.js';
|
|
6
|
+
const cli = cac('patto');
|
|
7
|
+
cli.version('0.1.0');
|
|
8
|
+
cli.help();
|
|
9
|
+
registerGenerateCommand(cli);
|
|
10
|
+
registerCoreCommands(cli);
|
|
11
|
+
try {
|
|
12
|
+
cli.parse(process.argv, { run: false });
|
|
13
|
+
if (cli.matchedCommand === undefined) {
|
|
14
|
+
cli.outputHelp();
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
await cli.runMatchedCommand();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
if (process.argv.includes('--stdin')) {
|
|
22
|
+
writeStructuredError(error);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
console.error(chalk.red(error instanceof Error ? error.message : String(error)));
|
|
26
|
+
}
|
|
27
|
+
process.exitCode = 1;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;AAEzB,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AACrB,GAAG,CAAC,IAAI,EAAE,CAAC;AAEX,uBAAuB,CAAC,GAAG,CAAC,CAAC;AAC7B,oBAAoB,CAAC,GAAG,CAAC,CAAC;AAE1B,IAAI,CAAC;IACD,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IAExC,IAAI,GAAG,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QACnC,GAAG,CAAC,UAAU,EAAE,CAAC;IACrB,CAAC;SAAM,CAAC;QACJ,MAAM,GAAG,CAAC,iBAAiB,EAAE,CAAC;IAClC,CAAC;AACL,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACb,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACnC,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACrF,CAAC;IAED,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CoreDiagnostic, CoreOutput } from '../core/types.js';
|
|
2
|
+
interface RenderOptions {
|
|
3
|
+
readonly root: string;
|
|
4
|
+
readonly command: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function printHumanOutput(output: CoreOutput | null, options: RenderOptions): void;
|
|
7
|
+
export declare function diagnosticsFromOutput(output: CoreOutput | null): CoreDiagnostic[];
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
export function printHumanOutput(output, options) {
|
|
5
|
+
const diagnostics = output?.diagnostics ?? [];
|
|
6
|
+
if (diagnostics.length === 0) {
|
|
7
|
+
console.log(chalk.green(`patto ${options.command}: sin diagnosticos.`));
|
|
8
|
+
printSummary(output);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
for (const diagnostic of diagnostics) {
|
|
12
|
+
printDiagnostic(diagnostic, options.root);
|
|
13
|
+
}
|
|
14
|
+
printSummary(output);
|
|
15
|
+
}
|
|
16
|
+
export function diagnosticsFromOutput(output) {
|
|
17
|
+
return output?.diagnostics ?? [];
|
|
18
|
+
}
|
|
19
|
+
function printDiagnostic(diagnostic, root) {
|
|
20
|
+
const color = colorForLevel(diagnostic.level);
|
|
21
|
+
const level = color(diagnostic.level.toUpperCase());
|
|
22
|
+
const location = formatLocation(diagnostic, root);
|
|
23
|
+
console.log(`${location} ${level} ${chalk.dim(diagnostic.code)}`);
|
|
24
|
+
console.log(` ${diagnostic.message}`);
|
|
25
|
+
if (diagnostic.file && diagnostic.line) {
|
|
26
|
+
printSourceFrame(root, diagnostic);
|
|
27
|
+
}
|
|
28
|
+
if (diagnostic.hint) {
|
|
29
|
+
console.log(chalk.dim(` hint: ${diagnostic.hint}`));
|
|
30
|
+
}
|
|
31
|
+
console.log('');
|
|
32
|
+
}
|
|
33
|
+
function printSourceFrame(root, diagnostic) {
|
|
34
|
+
const filePath = path.resolve(root, diagnostic.file ?? '');
|
|
35
|
+
if (!existsSync(filePath)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const lines = readFileSync(filePath, 'utf8').split(/\r?\n/);
|
|
39
|
+
const lineNumber = diagnostic.line ?? 1;
|
|
40
|
+
const sourceLine = lines[lineNumber - 1];
|
|
41
|
+
if (sourceLine === undefined) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const gutter = String(lineNumber).padStart(4, ' ');
|
|
45
|
+
const column = Math.max(1, diagnostic.column ?? 1);
|
|
46
|
+
const underlineStart = Math.max(0, column - 1);
|
|
47
|
+
const underlineWidth = inferUnderlineWidth(sourceLine, underlineStart);
|
|
48
|
+
const underline = `${' '.repeat(underlineStart)}${'^'.repeat(underlineWidth)}`;
|
|
49
|
+
console.log(chalk.dim(`${gutter} | `) + sourceLine);
|
|
50
|
+
console.log(chalk.dim(' | ') + colorForLevel(diagnostic.level)(underline));
|
|
51
|
+
}
|
|
52
|
+
function inferUnderlineWidth(sourceLine, start) {
|
|
53
|
+
const rest = sourceLine.slice(start);
|
|
54
|
+
const match = /^[A-Za-z0-9_@$.-]+/.exec(rest.trimStart());
|
|
55
|
+
const leadingSpaces = rest.length - rest.trimStart().length;
|
|
56
|
+
if (!match) {
|
|
57
|
+
return 1;
|
|
58
|
+
}
|
|
59
|
+
return Math.max(1, leadingSpaces + match[0].length);
|
|
60
|
+
}
|
|
61
|
+
function formatLocation(diagnostic, root) {
|
|
62
|
+
if (!diagnostic.file) {
|
|
63
|
+
return chalk.bold('<proyecto>');
|
|
64
|
+
}
|
|
65
|
+
const file = path.relative(process.cwd(), path.resolve(root, diagnostic.file));
|
|
66
|
+
const line = diagnostic.line ?? 1;
|
|
67
|
+
const column = diagnostic.column ?? 1;
|
|
68
|
+
return chalk.bold(`${file}:${line}:${column}`);
|
|
69
|
+
}
|
|
70
|
+
function printSummary(output) {
|
|
71
|
+
if (output?.summary === undefined) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
console.log(chalk.dim(`summary: ${JSON.stringify(output.summary)}`));
|
|
75
|
+
}
|
|
76
|
+
function colorForLevel(level) {
|
|
77
|
+
if (level === 'error') {
|
|
78
|
+
return chalk.red;
|
|
79
|
+
}
|
|
80
|
+
if (level === 'warning') {
|
|
81
|
+
return chalk.yellow;
|
|
82
|
+
}
|
|
83
|
+
return chalk.blue;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/output/diagnostics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ParsedName {
|
|
2
|
+
readonly input: string;
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly fileBase: string;
|
|
5
|
+
readonly classBase: string;
|
|
6
|
+
readonly dirs: string[];
|
|
7
|
+
readonly parts: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare function parseScaffoldName(input: string, label: string): ParsedName;
|
|
10
|
+
export declare function parseDiscordName(input: string, label: string): string;
|
|
11
|
+
export declare function parsePathSegments(input: string, label: string): string[];
|
|
12
|
+
export declare function toPascalCase(value: string): string;
|
|
13
|
+
export declare function commandClassNameFromPath(input: string): string;
|
|
14
|
+
export declare function commandImportPath(input: string): string;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const DISCORD_NAME_MAX_LENGTH = 32;
|
|
2
|
+
export function parseScaffoldName(input, label) {
|
|
3
|
+
const raw = input.trim();
|
|
4
|
+
if (raw.length === 0) {
|
|
5
|
+
throw new Error(`El nombre de ${label} no puede estar vacío.`);
|
|
6
|
+
}
|
|
7
|
+
if (raw.startsWith('/') || raw.includes('\\')) {
|
|
8
|
+
throw new Error(`El nombre de ${label} debe ser una ruta relativa con "/" si usa carpetas.`);
|
|
9
|
+
}
|
|
10
|
+
const rawParts = raw.split('/').filter(Boolean);
|
|
11
|
+
if (rawParts.length === 0) {
|
|
12
|
+
throw new Error(`El nombre de ${label} no puede estar vacío.`);
|
|
13
|
+
}
|
|
14
|
+
if (rawParts.some((part) => part === '.' || part === '..')) {
|
|
15
|
+
throw new Error(`El nombre de ${label} no puede contener "." ni "..".`);
|
|
16
|
+
}
|
|
17
|
+
const parts = rawParts.map((part) => normalizeSegment(part));
|
|
18
|
+
const invalidPart = parts.find((part) => part.length === 0);
|
|
19
|
+
if (invalidPart !== undefined) {
|
|
20
|
+
throw new Error(`El nombre de ${label} contiene un segmento inválido.`);
|
|
21
|
+
}
|
|
22
|
+
const name = parts[parts.length - 1];
|
|
23
|
+
validateDiscordName(name, label);
|
|
24
|
+
return {
|
|
25
|
+
input,
|
|
26
|
+
name,
|
|
27
|
+
fileBase: name,
|
|
28
|
+
classBase: toPascalCase(name),
|
|
29
|
+
dirs: parts.slice(0, -1),
|
|
30
|
+
parts,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function parseDiscordName(input, label) {
|
|
34
|
+
const name = normalizeSegment(input.trim());
|
|
35
|
+
validateDiscordName(name, label);
|
|
36
|
+
return name;
|
|
37
|
+
}
|
|
38
|
+
export function parsePathSegments(input, label) {
|
|
39
|
+
const parsed = parseScaffoldName(input, label);
|
|
40
|
+
return parsed.parts;
|
|
41
|
+
}
|
|
42
|
+
export function toPascalCase(value) {
|
|
43
|
+
return value
|
|
44
|
+
.split(/[-_]/g)
|
|
45
|
+
.filter(Boolean)
|
|
46
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
47
|
+
.join('');
|
|
48
|
+
}
|
|
49
|
+
export function commandClassNameFromPath(input) {
|
|
50
|
+
const parsed = parseScaffoldName(input, 'comando');
|
|
51
|
+
return `${parsed.classBase}Command`;
|
|
52
|
+
}
|
|
53
|
+
export function commandImportPath(input) {
|
|
54
|
+
const parsed = parseScaffoldName(input, 'comando');
|
|
55
|
+
return `@/commands/${[...parsed.dirs, `${parsed.fileBase}.command`].join('/')}`;
|
|
56
|
+
}
|
|
57
|
+
function normalizeSegment(value) {
|
|
58
|
+
return value
|
|
59
|
+
.normalize('NFD')
|
|
60
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
61
|
+
.toLowerCase()
|
|
62
|
+
.replace(/[_\s]+/g, '-')
|
|
63
|
+
.replace(/[^a-z0-9-]/g, '')
|
|
64
|
+
.replace(/-+/g, '-')
|
|
65
|
+
.replace(/^-|-$/g, '');
|
|
66
|
+
}
|
|
67
|
+
function validateDiscordName(name, label) {
|
|
68
|
+
if (!/^[a-z0-9]+(?:[-_][a-z0-9]+)*$/.test(name)) {
|
|
69
|
+
throw new Error(`El nombre de ${label} debe usar minúsculas, números, guiones o guion bajo.`);
|
|
70
|
+
}
|
|
71
|
+
if (name.length > DISCORD_NAME_MAX_LENGTH) {
|
|
72
|
+
throw new Error(`El nombre de ${label} no puede superar ${DISCORD_NAME_MAX_LENGTH} caracteres.`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=names.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"names.js","sourceRoot":"","sources":["../../src/scaffold/names.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ProjectContext {
|
|
2
|
+
readonly root: string;
|
|
3
|
+
}
|
|
4
|
+
export interface WriteResult {
|
|
5
|
+
readonly path: string;
|
|
6
|
+
readonly created: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function resolveProject(root?: string): ProjectContext;
|
|
9
|
+
export declare function projectPath(project: ProjectContext, ...segments: string[]): string;
|
|
10
|
+
export declare function writeFileOnce(filePath: string, content: string, force: boolean): WriteResult;
|
|
11
|
+
export declare function readTextFile(filePath: string): string;
|
|
12
|
+
export declare function writeTextFile(filePath: string, content: string): void;
|
|
13
|
+
export declare function fileExists(filePath: string): boolean;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export function resolveProject(root) {
|
|
4
|
+
const projectRoot = path.resolve(root ?? process.cwd());
|
|
5
|
+
const requiredFiles = [
|
|
6
|
+
path.join(projectRoot, 'src', 'core', 'structures', 'BaseCommand.ts'),
|
|
7
|
+
path.join(projectRoot, 'src', 'core', 'decorators', 'command.decorator.ts'),
|
|
8
|
+
];
|
|
9
|
+
const missingFile = requiredFiles.find((file) => !existsSync(file));
|
|
10
|
+
if (missingFile !== undefined) {
|
|
11
|
+
throw new Error(`No parece ser un proyecto Patto válido. No encontré ${path.relative(projectRoot, missingFile)}. Usa --root para indicar la raíz del bot.`);
|
|
12
|
+
}
|
|
13
|
+
return { root: projectRoot };
|
|
14
|
+
}
|
|
15
|
+
export function projectPath(project, ...segments) {
|
|
16
|
+
const target = path.resolve(project.root, ...segments);
|
|
17
|
+
const relative = path.relative(project.root, target);
|
|
18
|
+
if (relative.startsWith('..') || path.isAbsolute(relative)) {
|
|
19
|
+
throw new Error(`La ruta ${target} intenta salir de la raíz del proyecto.`);
|
|
20
|
+
}
|
|
21
|
+
return target;
|
|
22
|
+
}
|
|
23
|
+
export function writeFileOnce(filePath, content, force) {
|
|
24
|
+
if (existsSync(filePath) && !force) {
|
|
25
|
+
throw new Error(`El archivo ya existe: ${filePath}. Usa --force para reemplazarlo.`);
|
|
26
|
+
}
|
|
27
|
+
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
28
|
+
writeFileSync(filePath, content, 'utf8');
|
|
29
|
+
return { path: filePath, created: true };
|
|
30
|
+
}
|
|
31
|
+
export function readTextFile(filePath) {
|
|
32
|
+
return readFileSync(filePath, 'utf8');
|
|
33
|
+
}
|
|
34
|
+
export function writeTextFile(filePath, content) {
|
|
35
|
+
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
36
|
+
writeFileSync(filePath, content, 'utf8');
|
|
37
|
+
}
|
|
38
|
+
export function fileExists(filePath) {
|
|
39
|
+
return existsSync(filePath);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/scaffold/project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,IAAI,MAAM,WAAW,CAAC;AAW7B,MAAM,UAAU,cAAc,CAAC,IAAa;IACxC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACxD,MAAM,aAAa,GAAG;QAClB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,CAAC;QACrE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,sBAAsB,CAAC;KAC9E,CAAC;IAEF,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAEpE,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACX,uDAAuD,IAAI,CAAC,QAAQ,CAChE,WAAW,EACX,WAAW,CACd,4CAA4C,CAChD,CAAC;IACN,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAuB,EAAE,GAAG,QAAkB;IACtE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAErD,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,WAAW,MAAM,yCAAyC,CAAC,CAAC;IAChF,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,OAAe,EAAE,KAAc;IAC3E,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,kCAAkC,CAAC,CAAC;IACzF,CAAC;IAED,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAEzC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB;IACzC,OAAO,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,OAAe;IAC3D,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB;IACvC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ParsedName } from './names.js';
|
|
2
|
+
export type CommandKind = 'command' | 'subcommand' | 'subcommand-group';
|
|
3
|
+
export type PluginScopeName = 'specified' | 'folder' | 'deep-folder';
|
|
4
|
+
export interface CommandTemplateOptions {
|
|
5
|
+
readonly description?: string;
|
|
6
|
+
readonly category?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface SubcommandTemplateOptions extends CommandTemplateOptions {
|
|
9
|
+
readonly parent: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SubcommandGroupTemplateOptions extends CommandTemplateOptions {
|
|
12
|
+
readonly parent: string;
|
|
13
|
+
readonly group: string;
|
|
14
|
+
}
|
|
15
|
+
export interface PluginRegistrationOptions {
|
|
16
|
+
readonly classBase: string;
|
|
17
|
+
readonly importPath: string;
|
|
18
|
+
readonly scope: PluginScopeName;
|
|
19
|
+
readonly folder?: string;
|
|
20
|
+
readonly commands?: string[];
|
|
21
|
+
}
|
|
22
|
+
export declare function commandDefinitionTemplate(parsed: ParsedName, options: CommandTemplateOptions): string;
|
|
23
|
+
export declare function commandImplementationTemplate(parsed: ParsedName): string;
|
|
24
|
+
export declare function commandSingleFileTemplate(parsed: ParsedName, options: CommandTemplateOptions): string;
|
|
25
|
+
export declare function subcommandTemplate(parsed: ParsedName, options: SubcommandTemplateOptions): string;
|
|
26
|
+
export declare function subcommandGroupTemplate(parsed: ParsedName, options: SubcommandGroupTemplateOptions): string;
|
|
27
|
+
export declare function standaloneDefinitionTemplate(parsed: ParsedName, kind: CommandKind, options: CommandTemplateOptions & Partial<SubcommandTemplateOptions & SubcommandGroupTemplateOptions>): string;
|
|
28
|
+
export declare function pluginTemplate(classBase: string): string;
|
|
29
|
+
export declare function pluginImportStatement(classBase: string, importPath: string): string;
|
|
30
|
+
export declare function pluginCommandImportStatements(commands: string[] | undefined): string[];
|
|
31
|
+
export declare function pluginRegistrationTemplate(options: PluginRegistrationOptions): string;
|
|
32
|
+
export declare function pluginScopeEnum(scope: PluginScopeName): 'Specified' | 'Folder' | 'DeepFolder';
|
|
33
|
+
export declare function normalizePluginScope(scope: string | undefined, folder?: string): PluginScopeName;
|
|
34
|
+
export declare function normalizeCategory(category: string | undefined): string;
|