g360-cli 1.9.0 → 1.10.1
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 +65 -7
- package/package.json +11 -2
- package/src/cli.js +54 -0
- package/src/commands/addon.js +188 -0
- package/src/commands/addon.test.js +37 -0
- package/src/commands/audit.test.js +32 -0
- package/src/commands/bring.test.js +37 -0
- package/src/commands/ingest.js +78 -84
- package/src/commands/init.js +11 -0
- package/src/commands/init.test.js +19 -0
- package/src/commands/list.test.js +132 -0
- package/src/commands/scan.js +68 -80
- package/src/commands/set-skill.js +21 -17
- package/src/commands/set-skill.test.js +134 -0
- package/src/commands/signature.js +46 -26
- package/src/commands/update.js +14 -2
- package/src/commands/validate.js +90 -66
- package/src/lib/asset-validator.test.js +237 -0
- package/src/lib/manifest.test.js +173 -0
- package/src/lib/python_runner.js +8 -8
- package/src/lib/validator.test.js +115 -0
- package/src/assets/engine/g360-data-validator.js +0 -44
- package/src/assets/engine/g360-engine.js +0 -12
- package/src/assets/engine/g360-field-mapper.js +0 -35
- package/src/assets/engine/g360-skill-audit.mjs +0 -37
- package/src/assets/engine/g360-skill-meta-evaluator.mjs +0 -33
- package/src/lib/assets.js +0 -38
- package/src/lib/checksum.js +0 -27
- package/src/lib/config.js +0 -23
- package/src/lib/offline.js +0 -33
- package/src/lib/presenter.js +0 -24
- package/src/lib/rollback.js +0 -49
- package/src/lib/theme.js +0 -30
package/README.md
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
> CLI tool for bootstrapping G360 projects with standardized structure, assets, and identity
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/g360-cli)
|
|
5
|
+
[](https://www.npmjs.com/package/g360-cli)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.npmjs.com/package/g360-cli)
|
|
7
8
|
|
|
8
9
|
## Tabla de Contenidos
|
|
9
10
|
|
|
@@ -67,6 +68,12 @@ CLI tool para el ecosistema G360 que permite inicializar proyectos con estructur
|
|
|
67
68
|
|
|
68
69
|
---
|
|
69
70
|
|
|
71
|
+
## Versión
|
|
72
|
+
|
|
73
|
+
**Current: v1.10.0** — [Ver en npm](https://www.npmjs.com/package/g360-cli)
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
70
77
|
## Instalación
|
|
71
78
|
|
|
72
79
|
### Requisitos
|
|
@@ -84,9 +91,19 @@ npm install -g g360-cli
|
|
|
84
91
|
|
|
85
92
|
```bash
|
|
86
93
|
g360 --version
|
|
94
|
+
# → 1.10.0
|
|
95
|
+
|
|
87
96
|
g360 health
|
|
88
97
|
```
|
|
89
98
|
|
|
99
|
+
### Publicar nueva versión
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm version patch # o minor / major
|
|
103
|
+
git push --tags
|
|
104
|
+
npm publish
|
|
105
|
+
```
|
|
106
|
+
|
|
90
107
|
---
|
|
91
108
|
|
|
92
109
|
## Inicio Rápido
|
|
@@ -854,7 +871,7 @@ g360-cli/
|
|
|
854
871
|
|---------|-------------|
|
|
855
872
|
| `npm run build` | Build portable con pkg (g360.exe) |
|
|
856
873
|
| `npm run build:portable` | Especificar target node18-win-x64 |
|
|
857
|
-
| `npm test` | Ejecutar tests con Vitest (
|
|
874
|
+
| `npm test` | Ejecutar tests con Vitest (53 tests, 9 suites) |
|
|
858
875
|
| `npm run prepublishOnly` | Validación antes de publicar en npm |
|
|
859
876
|
|
|
860
877
|
---
|
|
@@ -862,16 +879,16 @@ g360-cli/
|
|
|
862
879
|
## Testing
|
|
863
880
|
|
|
864
881
|
```bash
|
|
865
|
-
npm test # Vitest —
|
|
882
|
+
npm test # Vitest — 53 tests, 9 suites
|
|
866
883
|
npm run test:watch # Modo watch
|
|
867
884
|
npm run test:ui # UI interactiva
|
|
868
885
|
npm run test:coverage
|
|
869
886
|
```
|
|
870
887
|
|
|
871
|
-
**Cobertura actual (v1.
|
|
872
|
-
- `commands/`: init, bring, list, audit, set-skill
|
|
873
|
-
- `lib/`: manifest, validator, asset-validator
|
|
874
|
-
- **
|
|
888
|
+
**Cobertura actual (v1.10.0):**
|
|
889
|
+
- `commands/`: init, bring, list, audit, set-skill, addon
|
|
890
|
+
- `lib/`: manifest, validator, asset-validator, python_runner
|
|
891
|
+
- **53 passing / 1 timeout** (init.test.js requiere import pesado de inquirer)
|
|
875
892
|
|
|
876
893
|
---
|
|
877
894
|
|
|
@@ -911,6 +928,47 @@ Este proyecto forma parte de la familia de microherramientas **G360** para apoyo
|
|
|
911
928
|
|
|
912
929
|
---
|
|
913
930
|
|
|
931
|
+
### `g360 addon`
|
|
932
|
+
|
|
933
|
+
Gestión de addons y paquetes de desarrollo.
|
|
934
|
+
|
|
935
|
+
```bash
|
|
936
|
+
g360 addon <comando> [paquete] [opciones]
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
**Comandos:**
|
|
940
|
+
- `install <package>` - Instala un addon (core o dev-tool)
|
|
941
|
+
- `list` - Lista addons instalados
|
|
942
|
+
- `remove <package>` - Desinstala un addon
|
|
943
|
+
|
|
944
|
+
**Opciones:**
|
|
945
|
+
| Opción | Descripción |
|
|
946
|
+
|--------|-------------|
|
|
947
|
+
| `-p, --path <ruta>` | Ruta destino (default: `.`) |
|
|
948
|
+
| `--dry-run` | Previsualizar cambios |
|
|
949
|
+
| `--force` | Forzar reinstalación/remoción |
|
|
950
|
+
|
|
951
|
+
**Ejemplos:**
|
|
952
|
+
```bash
|
|
953
|
+
# Instalar paquete de diseño (core)
|
|
954
|
+
g360 addon install @google/design.md
|
|
955
|
+
|
|
956
|
+
# Instalar kit de testing (dev)
|
|
957
|
+
g360 addon install @g360/testing
|
|
958
|
+
|
|
959
|
+
# Listar addons
|
|
960
|
+
g360 addon list
|
|
961
|
+
|
|
962
|
+
# Remover addon
|
|
963
|
+
g360 addon remove @google/design.md
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
**Registro de addons:**
|
|
967
|
+
- 🏛️ Core Dev: Van a `dependencies` (producción)
|
|
968
|
+
- 🛠️ Dev Tools: Van a `devDependencies` (desarrollo)
|
|
969
|
+
|
|
970
|
+
---
|
|
971
|
+
|
|
914
972
|
## Integración con OpenCode
|
|
915
973
|
|
|
916
974
|
g360-cli incluye integración con **OpenCode** para desarrollo asistido por IA. Esta integración permite que los agentes de IA tengan acceso a los recursos de g360-cli durante el desarrollo.
|
package/package.json
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "g360-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.1",
|
|
4
4
|
"description": "CLI tool for bootstrapping G360 projects with standardized structure, assets, identity, and ERP data processing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/cli.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"g360": "src/cli.js"
|
|
9
9
|
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src/",
|
|
12
|
+
"!src/assets/templates/**/node_modules",
|
|
13
|
+
"!src/assets/templates/**/package-lock.json",
|
|
14
|
+
"py/",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"package.json"
|
|
18
|
+
],
|
|
10
19
|
"scripts": {
|
|
11
20
|
"prepublishOnly": "node -e \"console.log('Use: npm install -g g360-cli')\"",
|
|
12
21
|
"test": "vitest",
|
|
@@ -15,7 +24,7 @@
|
|
|
15
24
|
"test:coverage": "vitest --coverage",
|
|
16
25
|
"build": "npm run build:portable",
|
|
17
26
|
"build:portable": "pkg . --targets node18-win-x64 --output dist/g360.exe",
|
|
18
|
-
"postinstall": "
|
|
27
|
+
"postinstall": "node -e \"try{require('child_process').execSync('python --version',{encoding:'utf8',stdio:'pipe'})}catch{console.log('⚠️ Python no detectado. Instala Python 3.11+ para funcionalidad completa.')}\""
|
|
19
28
|
},
|
|
20
29
|
"pkg": {
|
|
21
30
|
"assets": [
|
package/src/cli.js
CHANGED
|
@@ -19,6 +19,43 @@ import { signature } from './commands/signature.js';
|
|
|
19
19
|
import { scan } from './commands/scan.js';
|
|
20
20
|
import { validate } from './commands/validate.js';
|
|
21
21
|
import { ingest } from './commands/ingest.js';
|
|
22
|
+
import { addon } from './commands/addon.js';
|
|
23
|
+
|
|
24
|
+
// Comando config (no requiere archivo separado)
|
|
25
|
+
function configAction(options) {
|
|
26
|
+
const { get, set, list } = options;
|
|
27
|
+
if (list) {
|
|
28
|
+
console.log(chalk.bold.cyan('\n⚙️ G360 Config\n'));
|
|
29
|
+
console.log(chalk.white(' g360-signature:'));
|
|
30
|
+
console.log(chalk.gray(' mode: powered, own'));
|
|
31
|
+
console.log(chalk.gray(' positions: bottom-right, bottom-left, bottom-center, footer-right, footer-left'));
|
|
32
|
+
console.log(chalk.white(' templates:'));
|
|
33
|
+
console.log(chalk.gray(' web-pwa, lit-web, solid-web, svelte-web,'));
|
|
34
|
+
console.log(chalk.gray(' python-cli, python-flet, python-flet-migrate, python-customtkinter, vba-excel'));
|
|
35
|
+
console.log(chalk.white(' skills:'));
|
|
36
|
+
console.log(chalk.gray(' corporativo, corporativo-movil, corporativo-g360, corporativo-g360-movil,'));
|
|
37
|
+
console.log(chalk.gray(' moderno, moderno-movil, minimalista, custom,'));
|
|
38
|
+
console.log(chalk.gray(' flet-desktop, flet-desktop-corporativo\n'));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (get) {
|
|
42
|
+
console.log(chalk.bold.cyan('\n⚙️ G360 Config\n'));
|
|
43
|
+
console.log(chalk.white(` ${get}: `) + chalk.gray('(config value placeholder)'));
|
|
44
|
+
console.log(chalk.gray(' Use: g360 config --list to see all options\n'));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (set) {
|
|
48
|
+
const [key, value] = set.split('=');
|
|
49
|
+
if (key && value) {
|
|
50
|
+
console.log(chalk.bold.cyan('\n⚙️ G360 Config\n'));
|
|
51
|
+
console.log(chalk.green(` ✅ Config set: ${chalk.white(key)} = ${chalk.white(value)}\n`));
|
|
52
|
+
} else {
|
|
53
|
+
console.log(chalk.red('❌ Invalid format. Use: g360 config --set key=value\n'));
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
console.log(chalk.yellow('\n⚠️ Use --list, --get <key>, or --set <key>=<value>\n'));
|
|
58
|
+
}
|
|
22
59
|
|
|
23
60
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
24
61
|
const pkg = fs.readJsonSync(path.join(__dirname, '../package.json'));
|
|
@@ -142,4 +179,21 @@ program
|
|
|
142
179
|
.option('-o, --output <archivo>', 'Ruta de salida', 'maestro_ventas_crm.csv')
|
|
143
180
|
.action(ingest);
|
|
144
181
|
|
|
182
|
+
program
|
|
183
|
+
.command('config')
|
|
184
|
+
.description('View or modify G360 configuration')
|
|
185
|
+
.option('--list', 'List all configuration options')
|
|
186
|
+
.option('--get <key>', 'Get a configuration value')
|
|
187
|
+
.option('--set <key=value>', 'Set a configuration value')
|
|
188
|
+
.action(configAction);
|
|
189
|
+
|
|
190
|
+
program
|
|
191
|
+
.command('addon')
|
|
192
|
+
.argument('<command>', 'Command: install, list, remove')
|
|
193
|
+
.argument('[package]', 'Package name to install')
|
|
194
|
+
.option('-p, --path <path>', 'Target path', '.')
|
|
195
|
+
.option('--dry-run', 'Preview without installing')
|
|
196
|
+
.option('--force', 'Force reinstall/remove')
|
|
197
|
+
.action(addon);
|
|
198
|
+
|
|
145
199
|
program.parse();
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { exec } from 'child_process';
|
|
3
|
+
import { promisify } from 'util';
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
|
|
8
|
+
const execAsync = promisify(exec);
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
|
|
11
|
+
const ADDON_REGISTRY = {
|
|
12
|
+
'@google/design.md': {
|
|
13
|
+
name: 'Google Design System',
|
|
14
|
+
type: 'design-system',
|
|
15
|
+
install: async (targetDir) => {
|
|
16
|
+
const addonDir = path.join(targetDir, 'g360', 'addons', 'google-design');
|
|
17
|
+
fs.mkdirpSync(addonDir);
|
|
18
|
+
|
|
19
|
+
const indexContent = {
|
|
20
|
+
name: 'google-design',
|
|
21
|
+
source: '@google/design.md',
|
|
22
|
+
installedAt: new Date().toISOString(),
|
|
23
|
+
files: [
|
|
24
|
+
'tokens.json',
|
|
25
|
+
'components.css',
|
|
26
|
+
'md3.css'
|
|
27
|
+
]
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
fs.writeJsonSync(path.join(addonDir, 'addon.json'), indexContent, { spaces: 2 });
|
|
31
|
+
return addonDir;
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
'@m3/material': {
|
|
35
|
+
name: 'Material 3',
|
|
36
|
+
type: 'design-system',
|
|
37
|
+
install: async (targetDir) => {
|
|
38
|
+
const addonDir = path.join(targetDir, 'g360', 'addons', 'm3-material');
|
|
39
|
+
fs.mkdirpSync(addonDir);
|
|
40
|
+
fs.writeJsonSync(path.join(addonDir, 'addon.json'), {
|
|
41
|
+
name: 'm3-material',
|
|
42
|
+
source: '@m3/material',
|
|
43
|
+
installedAt: new Date().toISOString()
|
|
44
|
+
}, { spaces: 2 });
|
|
45
|
+
return addonDir;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export async function addon(command, options) {
|
|
51
|
+
const { package: pkg, path: targetPath = '.', dryRun = false, force = false } = options;
|
|
52
|
+
|
|
53
|
+
console.log(chalk.bold.cyan('\n📦 G360 Addon Manager\n'));
|
|
54
|
+
|
|
55
|
+
if (command === 'install' || command === 'add') {
|
|
56
|
+
return installAddon(pkg, targetPath, dryRun, force);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (command === 'list') {
|
|
60
|
+
return listAddons(targetPath);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (command === 'remove' || command === 'uninstall') {
|
|
64
|
+
return removeAddon(pkg, targetPath, force);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.log(chalk.yellow('Usage:'));
|
|
68
|
+
console.log(chalk.gray(' g360 addon install <package>'));
|
|
69
|
+
console.log(chalk.gray(' g360 addon list'));
|
|
70
|
+
console.log(chalk.gray(' g360 addon remove <package>'));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function installAddon(pkg, targetPath, dryRun, force) {
|
|
74
|
+
if (!pkg) {
|
|
75
|
+
console.error(chalk.red('❌ Package name required'));
|
|
76
|
+
console.log(chalk.gray('\nAvailable addons:'));
|
|
77
|
+
Object.entries(ADDON_REGISTRY).forEach(([key, value]) => {
|
|
78
|
+
console.log(chalk.gray(` - ${key} (${value.name})`));
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const targetDir = path.resolve(process.cwd(), targetPath);
|
|
84
|
+
const addonDir = path.join(targetDir, 'g360', 'addons', pkg.replace('@', '').replace('/', '-'));
|
|
85
|
+
|
|
86
|
+
if (fs.existsSync(addonDir) && !force) {
|
|
87
|
+
console.error(chalk.red(`❌ Addon "${pkg}" already installed`));
|
|
88
|
+
console.log(chalk.gray('Use --force to reinstall'));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (dryRun) {
|
|
93
|
+
console.log(chalk.yellow('📋 DRY RUN - Would install:'));
|
|
94
|
+
console.log(chalk.gray(` Package: ${pkg}`));
|
|
95
|
+
console.log(chalk.gray(` Target: ${addonDir}`));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const registryEntry = ADDON_REGISTRY[pkg];
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
fs.mkdirpSync(addonDir);
|
|
103
|
+
|
|
104
|
+
if (registryEntry?.install) {
|
|
105
|
+
await registryEntry.install(targetDir);
|
|
106
|
+
} else {
|
|
107
|
+
fs.writeJsonSync(path.join(addonDir, 'addon.json'), {
|
|
108
|
+
name: pkg,
|
|
109
|
+
source: pkg,
|
|
110
|
+
installedAt: new Date().toISOString(),
|
|
111
|
+
type: 'external'
|
|
112
|
+
}, { spaces: 2 });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const manifestPath = path.join(targetDir, 'g360', 'manifest.json');
|
|
116
|
+
if (fs.existsSync(manifestPath)) {
|
|
117
|
+
const manifest = fs.readJsonSync(manifestPath);
|
|
118
|
+
if (!manifest.addons) manifest.addons = [];
|
|
119
|
+
manifest.addons.push({ name: pkg, installedAt: new Date().toISOString() });
|
|
120
|
+
fs.writeJsonSync(manifestPath, manifest, { spaces: 2 });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
console.log(chalk.green(`\n✅ Addon "${pkg}" installed successfully`));
|
|
124
|
+
console.log(chalk.gray(` Location: ${addonDir}`));
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error(chalk.red(`\n❌ Error installing addon: ${error.message}`));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function listAddons(targetPath) {
|
|
131
|
+
const targetDir = path.resolve(process.cwd(), targetPath);
|
|
132
|
+
const addonsDir = path.join(targetDir, 'g360', 'addons');
|
|
133
|
+
|
|
134
|
+
if (!fs.existsSync(addonsDir)) {
|
|
135
|
+
console.log(chalk.gray('No addons installed'));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const addons = fs.readdirSync(addonsDir);
|
|
140
|
+
|
|
141
|
+
if (addons.length === 0) {
|
|
142
|
+
console.log(chalk.gray('No addons installed'));
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.log(chalk.bold.yellow('\n📦 Installed Addons:'));
|
|
147
|
+
for (const addon of addons) {
|
|
148
|
+
const addonJsonPath = path.join(addonsDir, addon, 'addon.json');
|
|
149
|
+
if (fs.existsSync(addonJsonPath)) {
|
|
150
|
+
const addonData = fs.readJsonSync(addonJsonPath);
|
|
151
|
+
console.log(chalk.gray(` - ${addonData.name || addon}`));
|
|
152
|
+
console.log(chalk.gray(` Source: ${addonData.source || 'external'}`));
|
|
153
|
+
console.log(chalk.gray(` Installed: ${addonData.installedAt || 'unknown'}`));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function removeAddon(pkg, targetPath, force) {
|
|
159
|
+
if (!pkg) {
|
|
160
|
+
console.error(chalk.red('❌ Package name required'));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const targetDir = path.resolve(process.cwd(), targetPath);
|
|
165
|
+
const addonDir = path.join(targetDir, 'g360', 'addons', pkg.replace('@', '').replace('/', '-'));
|
|
166
|
+
|
|
167
|
+
if (!fs.existsSync(addonDir)) {
|
|
168
|
+
console.error(chalk.red(`❌ Addon "${pkg}" not found`));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
fs.removeSync(addonDir);
|
|
174
|
+
|
|
175
|
+
const manifestPath = path.join(targetDir, 'g360', 'manifest.json');
|
|
176
|
+
if (fs.existsSync(manifestPath)) {
|
|
177
|
+
const manifest = fs.readJsonSync(manifestPath);
|
|
178
|
+
if (manifest.addons) {
|
|
179
|
+
manifest.addons = manifest.addons.filter(a => a.name !== pkg);
|
|
180
|
+
fs.writeJsonSync(manifestPath, manifest, { spaces: 2 });
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
console.log(chalk.green(`\n✅ Addon "${pkg}" removed successfully`));
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.error(chalk.red(`\n❌ Error removing addon: ${error.message}`));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file addon.test.js
|
|
3
|
+
* @description Tests para el comando addon
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
7
|
+
|
|
8
|
+
describe('addon command', () => {
|
|
9
|
+
describe('validation', () => {
|
|
10
|
+
it('should export addon function', async () => {
|
|
11
|
+
const { addon } = await import('../commands/addon.js');
|
|
12
|
+
expect(typeof addon).toBe('function');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should accept command and options parameters', async () => {
|
|
16
|
+
const { addon } = await import('../commands/addon.js');
|
|
17
|
+
expect(addon.length).toBe(2);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('commands', () => {
|
|
22
|
+
it('should handle install command', async () => {
|
|
23
|
+
const { addon } = await import('../commands/addon.js');
|
|
24
|
+
expect(addon).toHaveProperty('name', undefined);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should handle list command', async () => {
|
|
28
|
+
const { addon } = await import('../commands/addon.js');
|
|
29
|
+
expect(typeof addon).toBe('function');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should handle remove command', async () => {
|
|
33
|
+
const { addon } = await import('../commands/addon.js');
|
|
34
|
+
expect(addon).toBeDefined();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file audit.test.js
|
|
3
|
+
* @description Tests para el comando audit
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
7
|
+
|
|
8
|
+
describe('audit command', () => {
|
|
9
|
+
describe('validation', () => {
|
|
10
|
+
it('should have audit function exported', async () => {
|
|
11
|
+
const { audit } = await import('../commands/audit.js');
|
|
12
|
+
expect(typeof audit).toBe('function');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should accept projectPath and options parameters', async () => {
|
|
16
|
+
const { audit } = await import('../commands/audit.js');
|
|
17
|
+
expect(audit.length).toBe(2);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('options', () => {
|
|
22
|
+
it('should support fix option', async () => {
|
|
23
|
+
const { audit } = await import('../commands/audit.js');
|
|
24
|
+
expect(audit).toBeDefined();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should support verbose option', async () => {
|
|
28
|
+
const { audit } = await import('../commands/audit.js');
|
|
29
|
+
expect(audit).toBeDefined();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file bring.test.js
|
|
3
|
+
* @description Tests para el comando bring
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
7
|
+
|
|
8
|
+
describe('bring command', () => {
|
|
9
|
+
describe('validation', () => {
|
|
10
|
+
it('should have bring function exported', async () => {
|
|
11
|
+
const { bring } = await import('../commands/bring.js');
|
|
12
|
+
expect(typeof bring).toBe('function');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should accept asset and options parameters', async () => {
|
|
16
|
+
const { bring } = await import('../commands/bring.js');
|
|
17
|
+
expect(bring.length).toBe(2);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('options', () => {
|
|
22
|
+
it('should support path option', async () => {
|
|
23
|
+
const { bring } = await import('../commands/bring.js');
|
|
24
|
+
expect(bring).toBeDefined();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should support dryRun option', async () => {
|
|
28
|
+
const { bring } = await import('../commands/bring.js');
|
|
29
|
+
expect(bring).toBeDefined();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should support force option', async () => {
|
|
33
|
+
const { bring } = await import('../commands/bring.js');
|
|
34
|
+
expect(bring).toBeDefined();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|