@dbcube/cli 5.1.5 → 5.2.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 +59 -0
- package/package.json +23 -7
- package/src/commands/run/database/create/index.js +10 -12
- package/src/commands/run/pull.js +58 -1
- package/src/commands/run/seeder/add.js +4 -3
- package/src/commands/run/table/fresh.js +81 -35
- package/src/commands/run/table/refresh.js +4 -4
- package/src/commands/run/trigger/fresh.js +4 -3
- package/src/commands/version.js +66 -29
- package/src/index.js +162 -104
- package/src/utils/ConfigFileUtils.js +3 -2
- package/.npmignore +0 -58
- package/bun.lock +0 -192
- package/dbcube.config.js +0 -15
- package/pnpm-workspace.yaml +0 -3
- package/test-new-features.js +0 -129
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# @dbcube/cli
|
|
2
|
+
|
|
3
|
+
Command-line interface for [DBCube](https://www.npmjs.com/package/dbcube): schema management with `.cube` files, tracked migrations with rollback, seeders, triggers, TypeScript type generation and database introspection.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -D @dbcube/cli
|
|
9
|
+
npx dbcube init
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Commands
|
|
13
|
+
|
|
14
|
+
| Command | Description |
|
|
15
|
+
|---|---|
|
|
16
|
+
| `npx dbcube init` | Scaffold a new project (config + `dbcube/` + example schema) |
|
|
17
|
+
| `npx dbcube generate` | Generate TypeScript types from `.table.cube` files |
|
|
18
|
+
| `npx dbcube validate` | Validate every `.cube` file without executing (exit 1 on errors — CI-friendly) |
|
|
19
|
+
| `npx dbcube doctor` | Diagnose config, binaries and database connectivity |
|
|
20
|
+
| `npx dbcube dev` | Watch mode: saving a `.cube` file applies it automatically |
|
|
21
|
+
| `npx dbcube run database:create` | Interactive database setup (config + physical creation) |
|
|
22
|
+
| `npx dbcube run table:fresh` | Drop and recreate all tables (asks for written confirmation; `--force` for CI) |
|
|
23
|
+
| `npx dbcube run table:refresh` | Apply schema changes **without** dropping data |
|
|
24
|
+
| `npx dbcube run table:alter` | Apply pending `.alter.cube` migrations (`--dry-run`, `--all`) |
|
|
25
|
+
| `npx dbcube migrate:status` | Show applied / pending / modified migrations |
|
|
26
|
+
| `npx dbcube migrate:rollback` | Revert the last migration batch |
|
|
27
|
+
| `npx dbcube run pull [db]` | Generate `.table.cube` files FROM an existing database (MySQL, PostgreSQL, SQLite) |
|
|
28
|
+
| `npx dbcube run seeder:add` | Run `.seeder.cube` data seeders |
|
|
29
|
+
| `npx dbcube run trigger:fresh` | Recreate triggers from `.trigger.cube` files |
|
|
30
|
+
| `npx dbcube update` | Check and update the Rust engine binaries |
|
|
31
|
+
| `npx dbcube run download <engine> [ver]` | Download a specific engine binary |
|
|
32
|
+
| `npx dbcube -v` | Versions of CLI, packages, engines, Node and platform |
|
|
33
|
+
|
|
34
|
+
Run `npx dbcube help` for the full reference.
|
|
35
|
+
|
|
36
|
+
## Configuration
|
|
37
|
+
|
|
38
|
+
`dbcube.config.js` (created by `init`):
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
module.exports = function (config) {
|
|
42
|
+
config.set({
|
|
43
|
+
databases: {
|
|
44
|
+
myapp: {
|
|
45
|
+
type: "sqlite", // mysql | postgres | sqlite | mongodb
|
|
46
|
+
config: { DATABASE: "myapp" }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Documentation
|
|
54
|
+
|
|
55
|
+
https://dbcube.org
|
|
56
|
+
|
|
57
|
+
## License
|
|
58
|
+
|
|
59
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,22 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dbcube/cli",
|
|
3
|
-
"version": "5.1
|
|
4
|
-
"main": "index.js",
|
|
3
|
+
"version": "5.2.1",
|
|
4
|
+
"main": "src/index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dbcube": "node src/index.js"
|
|
7
7
|
},
|
|
8
8
|
"bin": {
|
|
9
9
|
"dbcube": "./src/index.js"
|
|
10
10
|
},
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"
|
|
11
|
+
"files": [
|
|
12
|
+
"src"
|
|
13
|
+
],
|
|
14
|
+
"keywords": [
|
|
15
|
+
"dbcube",
|
|
16
|
+
"cli",
|
|
17
|
+
"database",
|
|
18
|
+
"migrations",
|
|
19
|
+
"mysql",
|
|
20
|
+
"postgresql",
|
|
21
|
+
"sqlite",
|
|
22
|
+
"orm"
|
|
23
|
+
],
|
|
24
|
+
"author": "Albert Araya",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"description": "Command-line interface for DBCube: schema management (.cube files), migrations with rollback, seeders, triggers, TypeScript type generation and database introspection.",
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
15
30
|
"dependencies": {
|
|
16
|
-
"@dbcube/schema-builder": "^5.1
|
|
31
|
+
"@dbcube/schema-builder": "^5.2.1",
|
|
17
32
|
"@inquirer/prompts": "^8.5.2",
|
|
18
33
|
"alwait": "^1.0.0",
|
|
19
34
|
"chalk": "4.1.2",
|
|
35
|
+
"dbcube": "^5.2.1",
|
|
20
36
|
"dotenv": "^17.4.2",
|
|
21
37
|
"fs-extra": "^11.3.5",
|
|
22
38
|
"glob": "^13.0.6",
|
|
@@ -3,7 +3,7 @@ const alwait = require('alwait');
|
|
|
3
3
|
const ConfigFileUtils = require('../../../../utils/ConfigFileUtils');
|
|
4
4
|
const { select, input } = require('@inquirer/prompts');
|
|
5
5
|
const ora = require('ora');
|
|
6
|
-
const {
|
|
6
|
+
const { execFileSync } = require('child_process');
|
|
7
7
|
const path = require('path');
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -18,10 +18,9 @@ async function createNewDatabase() {
|
|
|
18
18
|
|
|
19
19
|
// Fase 1: Ejecutar addDatabaseConfig.js
|
|
20
20
|
console.log('🔧 Iniciando configuración de base de datos...');
|
|
21
|
-
const configCommand = `node "${path.join(__dirname, 'addDatabaseConfig.js')}"`;
|
|
22
21
|
|
|
23
22
|
try {
|
|
24
|
-
|
|
23
|
+
execFileSync(process.execPath, [path.join(__dirname, 'addDatabaseConfig.js')], {
|
|
25
24
|
stdio: 'inherit',
|
|
26
25
|
cwd: process.cwd()
|
|
27
26
|
});
|
|
@@ -37,20 +36,20 @@ async function createNewDatabase() {
|
|
|
37
36
|
|
|
38
37
|
try {
|
|
39
38
|
databaseName = fs.readFileSync(tempFile, 'utf8');
|
|
40
|
-
// Limpiar el archivo temporal
|
|
41
|
-
fs.unlinkSync(tempFile);
|
|
42
39
|
} catch (error) {
|
|
43
40
|
console.error('❌ Error: No se pudo obtener el nombre de la base de datos configurada');
|
|
44
41
|
process.exit(1);
|
|
42
|
+
} finally {
|
|
43
|
+
// Limpiar el archivo temporal pase lo que pase
|
|
44
|
+
try { fs.unlinkSync(tempFile); } catch { /* ya no existe */ }
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
console.log('\n🏗️ Iniciando creación física de la base de datos...');
|
|
48
48
|
|
|
49
|
-
// Fase 2: Ejecutar createDatabase.js
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
// Fase 2: Ejecutar createDatabase.js. execFileSync con array de
|
|
50
|
+
// argumentos: el nombre no pasa por el shell (sin inyección de comandos)
|
|
52
51
|
try {
|
|
53
|
-
|
|
52
|
+
execFileSync(process.execPath, [path.join(__dirname, 'createDatabase.js'), `--name=${databaseName}`], {
|
|
54
53
|
stdio: 'inherit',
|
|
55
54
|
cwd: process.cwd()
|
|
56
55
|
});
|
|
@@ -75,10 +74,9 @@ async function createNewDatabase() {
|
|
|
75
74
|
async function useExistingDatabase(databaseName) {
|
|
76
75
|
try {
|
|
77
76
|
// Ejecutar createDatabase.js con el nombre de la base de datos existente
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
// (execFileSync: el nombre no pasa por el shell, sin inyección de comandos)
|
|
80
78
|
try {
|
|
81
|
-
|
|
79
|
+
execFileSync(process.execPath, [path.join(__dirname, 'createDatabase.js'), `--name=${databaseName}`], {
|
|
82
80
|
stdio: 'inherit',
|
|
83
81
|
cwd: process.cwd()
|
|
84
82
|
});
|
package/src/commands/run/pull.js
CHANGED
|
@@ -101,13 +101,70 @@ async function introspect(engine, dbName, motor) {
|
|
|
101
101
|
if (!tables[fk.tn]) continue;
|
|
102
102
|
tables[fk.tn].fks[fk.cn] = { table: fk.rt, column: fk.rc };
|
|
103
103
|
}
|
|
104
|
+
} else if (motor === 'mongodb') {
|
|
105
|
+
// Introspección por muestreo: MongoDB no tiene esquema fijo, así que
|
|
106
|
+
// se infieren los tipos de los primeros 50 documentos por colección.
|
|
107
|
+
const listRes = await raw(engine, JSON.stringify({ listCollections: 1, nameOnly: true }));
|
|
108
|
+
const batch = listRes?.[0]?.cursor?.firstBatch ?? [];
|
|
109
|
+
const collections = batch
|
|
110
|
+
.map(c => c.name)
|
|
111
|
+
.filter(n => n && !n.startsWith('system.') && !n.startsWith('dbcube_'));
|
|
112
|
+
|
|
113
|
+
for (const coll of collections) {
|
|
114
|
+
const findRes = await raw(engine, JSON.stringify({ find: coll, limit: 50 }));
|
|
115
|
+
const docs = findRes?.[0]?.cursor?.firstBatch ?? [];
|
|
116
|
+
|
|
117
|
+
// campo -> { types: Set, seen: n, nullSeen: bool }
|
|
118
|
+
const fields = new Map();
|
|
119
|
+
for (const doc of docs) {
|
|
120
|
+
for (const [key, value] of Object.entries(doc)) {
|
|
121
|
+
if (key === '_id') continue; // gestionado por MongoDB
|
|
122
|
+
let f = fields.get(key);
|
|
123
|
+
if (!f) { f = { types: new Set(), seen: 0, nullSeen: false }; fields.set(key, f); }
|
|
124
|
+
f.seen++;
|
|
125
|
+
if (value === null) { f.nullSeen = true; continue; }
|
|
126
|
+
f.types.add(inferMongoCubeType(value));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
tables[coll] = {
|
|
131
|
+
columns: [...fields.entries()].map(([name, f]) => {
|
|
132
|
+
const types = [...f.types];
|
|
133
|
+
const dataType = types.length === 1 ? types[0] : 'json'; // tipos mixtos → json
|
|
134
|
+
return {
|
|
135
|
+
name,
|
|
136
|
+
dataType,
|
|
137
|
+
length: dataType === 'varchar' ? '255' : null,
|
|
138
|
+
nullable: f.nullSeen || f.seen < docs.length,
|
|
139
|
+
defaultValue: null,
|
|
140
|
+
isPk: false,
|
|
141
|
+
autoinc: false,
|
|
142
|
+
enumValues: null,
|
|
143
|
+
};
|
|
144
|
+
}),
|
|
145
|
+
fks: {},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
104
148
|
} else {
|
|
105
|
-
throw new Error(`pull is not supported yet for motor '${motor}' (mysql, postgresql, sqlite available)`);
|
|
149
|
+
throw new Error(`pull is not supported yet for motor '${motor}' (mysql, postgresql, sqlite, mongodb available)`);
|
|
106
150
|
}
|
|
107
151
|
|
|
108
152
|
return tables;
|
|
109
153
|
}
|
|
110
154
|
|
|
155
|
+
function inferMongoCubeType(value) {
|
|
156
|
+
if (typeof value === 'boolean') return 'boolean';
|
|
157
|
+
if (typeof value === 'number') return Number.isInteger(value) ? 'int' : 'double';
|
|
158
|
+
if (typeof value === 'string') {
|
|
159
|
+
if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(value)) return 'datetime';
|
|
160
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) return 'date';
|
|
161
|
+
return 'varchar';
|
|
162
|
+
}
|
|
163
|
+
// BSON dates llegan como {$date: ...} al serializar a JSON
|
|
164
|
+
if (value && typeof value === 'object' && '$date' in value) return 'datetime';
|
|
165
|
+
return 'json'; // objetos anidados y arrays
|
|
166
|
+
}
|
|
167
|
+
|
|
111
168
|
function renderCube(dbName, tableName, table) {
|
|
112
169
|
let out = `@database("${dbName}");\n\n`;
|
|
113
170
|
out += `@meta({\n name: "${tableName}";\n description: "Imported from existing database by dbcube pull";\n});\n\n`;
|
|
@@ -16,14 +16,15 @@ async function main() {
|
|
|
16
16
|
if (error.message.includes("reading 'init'")) {
|
|
17
17
|
console.error('❌ Configuracion de base de datos no encontrada\n');
|
|
18
18
|
console.error('Ejecute el comando para crear una nueva base de datos:');
|
|
19
|
-
console.error(`\
|
|
19
|
+
console.error(`\tnpx dbcube run database:create`);
|
|
20
20
|
console.error('\nO verifique que la base de datos este configurada en el archivo dbcube.config.js\n');
|
|
21
21
|
process.exit(1);
|
|
22
22
|
} else if (error.message.includes("reading 'getDatabase'")) {
|
|
23
23
|
console.error('- Se sugiere cambiar el linea o crear la base de datos a la que se hace referencia.');
|
|
24
24
|
} else {
|
|
25
|
-
console.error(
|
|
26
|
-
console.error(
|
|
25
|
+
console.error(`❌ ${error.message}`);
|
|
26
|
+
if (process.env.DEBUG) console.error(error);
|
|
27
|
+
process.exit(1);
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
}
|
|
@@ -1,35 +1,81 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
} else
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { Schema } = require('@dbcube/schema-builder');
|
|
3
|
+
const ConfigFileUtils = require('./../../../utils/ConfigFileUtils');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* dbcube run table:fresh [--seeder] [--force]
|
|
7
|
+
* DESTRUCTIVO: dropea y recrea todas las tablas desde los .table.cube.
|
|
8
|
+
* Pide confirmación ESCRITA (el nombre de la base de datos) salvo con --force.
|
|
9
|
+
*/
|
|
10
|
+
async function confirmDestruction(databases) {
|
|
11
|
+
const { input } = require('@inquirer/prompts');
|
|
12
|
+
|
|
13
|
+
console.log('');
|
|
14
|
+
console.log(` ${chalk.bgRed.white.bold(' ⚠ DESTRUCTIVE OPERATION ')}`);
|
|
15
|
+
console.log('');
|
|
16
|
+
console.log(` ${chalk.red('table:fresh will DROP and recreate ALL tables.')}`);
|
|
17
|
+
console.log(` ${chalk.red.bold('ALL DATA WILL BE PERMANENTLY LOST')} in:`);
|
|
18
|
+
for (const db of databases) {
|
|
19
|
+
console.log(` ${chalk.yellow('•')} ${chalk.bold(db.name)} ${chalk.gray(`(${db.type})`)}`);
|
|
20
|
+
}
|
|
21
|
+
console.log('');
|
|
22
|
+
console.log(` ${chalk.gray('To update schemas WITHOUT losing data use:')} ${chalk.white('npx dbcube run table:refresh')}`);
|
|
23
|
+
console.log('');
|
|
24
|
+
|
|
25
|
+
const expected = databases.length === 1 ? databases[0].name : 'all';
|
|
26
|
+
const answer = await input({
|
|
27
|
+
message: `Type ${chalk.bold(expected)} to confirm (anything else aborts):`,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return answer.trim() === expected;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function main() {
|
|
34
|
+
try {
|
|
35
|
+
const args = process.argv.slice(2);
|
|
36
|
+
const runSeeders = args.includes('--seeder');
|
|
37
|
+
const force = args.includes('--force') || args.includes('-y') || args.includes('--yes');
|
|
38
|
+
|
|
39
|
+
const configuredDatabases = await ConfigFileUtils.getConfiguredDatabases();
|
|
40
|
+
|
|
41
|
+
if (!force) {
|
|
42
|
+
if (!process.stdin.isTTY) {
|
|
43
|
+
console.error(`\n${chalk.red('❌ table:fresh is destructive and needs confirmation.')}`);
|
|
44
|
+
console.error(`${chalk.gray('Non-interactive environment detected — pass')} ${chalk.white('--force')} ${chalk.gray('to proceed (e.g. in CI).')}\n`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
const confirmed = await confirmDestruction(configuredDatabases);
|
|
48
|
+
if (!confirmed) {
|
|
49
|
+
console.log(`\n${chalk.yellow('Aborted.')} ${chalk.gray('No changes were made.')}\n`);
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
for (const config of configuredDatabases) {
|
|
55
|
+
const schema = new Schema(config.name);
|
|
56
|
+
await schema.freshTables();
|
|
57
|
+
if (runSeeders) {
|
|
58
|
+
await schema.executeSeeders();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (error.name === 'ExitPromptError') {
|
|
63
|
+
console.log(`\n${chalk.yellow('Aborted.')} ${chalk.gray('No changes were made.')}\n`);
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
if (error.message.includes("reading 'init'")) {
|
|
67
|
+
console.error('❌ Configuracion de base de datos no encontrada\n');
|
|
68
|
+
console.error('Ejecute el comando para crear una nueva base de datos:');
|
|
69
|
+
console.error(`\tdbcube run database:create`);
|
|
70
|
+
console.error('\nO verifique que la base de datos este configurada en el archivo dbcube.config.js\n');
|
|
71
|
+
process.exit(1);
|
|
72
|
+
} else if (error.message.includes("reading 'getDatabase'")) {
|
|
73
|
+
console.error('- Se sugiere cambiar el linea o crear la base de datos a la que se hace referencia.');
|
|
74
|
+
} else {
|
|
75
|
+
console.error('Error:', error.message);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
main().catch(console.error);
|
|
@@ -2,7 +2,6 @@ const { Schema } = require('@dbcube/schema-builder');
|
|
|
2
2
|
const ConfigFileUtils = require('./../../../utils/ConfigFileUtils');
|
|
3
3
|
|
|
4
4
|
async function main() {
|
|
5
|
-
console.clear();
|
|
6
5
|
try {
|
|
7
6
|
const configuredDatabases = await ConfigFileUtils.getConfiguredDatabases();
|
|
8
7
|
// Recorrer cada archivo y mostrar su contenido
|
|
@@ -14,14 +13,15 @@ async function main() {
|
|
|
14
13
|
if (error.message.includes("reading 'init'")) {
|
|
15
14
|
console.error('❌ Configuracion de base de datos no encontrada\n');
|
|
16
15
|
console.error('Ejecute el comando para crear una nueva base de datos:');
|
|
17
|
-
console.error(`\
|
|
16
|
+
console.error(`\tnpx dbcube run database:create`);
|
|
18
17
|
console.error('\nO verifique que la base de datos este configurada en el archivo dbcube.config.js\n');
|
|
19
18
|
process.exit(1);
|
|
20
19
|
} else if (error.message.includes("reading 'getDatabase'")) {
|
|
21
20
|
console.error('- Se sugiere cambiar el linea o crear la base de datos a la que se hace referencia.');
|
|
22
21
|
} else {
|
|
23
|
-
console.error(
|
|
24
|
-
console.error(
|
|
22
|
+
console.error(`❌ ${error.message}`);
|
|
23
|
+
if (process.env.DEBUG) console.error(error);
|
|
24
|
+
process.exit(1);
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -14,14 +14,15 @@ async function main() {
|
|
|
14
14
|
if (error.message.includes("reading 'init'")) {
|
|
15
15
|
console.error('❌ Configuracion de base de datos no encontrada\n');
|
|
16
16
|
console.error('Ejecute el comando para crear una nueva base de datos:');
|
|
17
|
-
console.error(`\
|
|
17
|
+
console.error(`\tnpx dbcube run database:create`);
|
|
18
18
|
console.error('\nO verifique que la base de datos este configurada en el archivo dbcube.config.js\n');
|
|
19
19
|
process.exit(1);
|
|
20
20
|
} else if (error.message.includes("reading 'getDatabase'")) {
|
|
21
21
|
console.error('- Se sugiere cambiar el linea o crear la base de datos a la que se hace referencia.');
|
|
22
22
|
} else {
|
|
23
|
-
console.error(
|
|
24
|
-
console.error(
|
|
23
|
+
console.error(`❌ ${error.message}`);
|
|
24
|
+
if (process.env.DEBUG) console.error(error);
|
|
25
|
+
process.exit(1);
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
console.log('\n');
|
package/src/commands/version.js
CHANGED
|
@@ -1,29 +1,66 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const chalk = require('chalk');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
try {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* dbcube version — CLI, packages, engine binaries, and environment info.
|
|
7
|
+
*/
|
|
8
|
+
function readVersion(pkgPath) {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(fs.readFileSync(pkgPath, 'utf8')).version;
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function findEngineVersions() {
|
|
17
|
+
const binDir = path.join(process.cwd(), '.dbcube', 'bin');
|
|
18
|
+
const engines = {};
|
|
19
|
+
try {
|
|
20
|
+
for (const f of fs.readdirSync(binDir)) {
|
|
21
|
+
const m = f.match(/^(query-engine|schema-engine|sqlite-engine)-v([\d.]+)-/);
|
|
22
|
+
if (m) engines[m[1]] = `v${m[2]}`;
|
|
23
|
+
}
|
|
24
|
+
} catch { /* no binaries downloaded yet */ }
|
|
25
|
+
return engines;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function showVersion() {
|
|
29
|
+
try {
|
|
30
|
+
const cliVersion = readVersion(path.join(__dirname, '../../package.json'));
|
|
31
|
+
const row = (label, value, dim = false) =>
|
|
32
|
+
console.log(` ${chalk.gray(label.padEnd(16))} ${dim ? chalk.gray(value) : chalk.white(value)}`);
|
|
33
|
+
|
|
34
|
+
console.log('');
|
|
35
|
+
console.log(` ${chalk.green.bold('▣ DBCube CLI')} ${chalk.bold('v' + cliVersion)}`);
|
|
36
|
+
console.log(` ${chalk.gray('─'.repeat(40))}`);
|
|
37
|
+
|
|
38
|
+
// Local package versions (when resolvable from the project)
|
|
39
|
+
const localPkgs = ['dbcube', '@dbcube/query-builder', '@dbcube/schema-builder', '@dbcube/core'];
|
|
40
|
+
for (const pkg of localPkgs) {
|
|
41
|
+
try {
|
|
42
|
+
const pkgJson = require.resolve(`${pkg}/package.json`, { paths: [process.cwd()] });
|
|
43
|
+
const v = readVersion(pkgJson);
|
|
44
|
+
if (v) row(pkg, 'v' + v);
|
|
45
|
+
} catch { /* not installed in this project */ }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const engines = findEngineVersions();
|
|
49
|
+
for (const [name, v] of Object.entries(engines)) {
|
|
50
|
+
row(name, `${v} ${chalk.gray('(rust)')}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log(` ${chalk.gray('─'.repeat(40))}`);
|
|
54
|
+
row('node', process.version, true);
|
|
55
|
+
row('platform', `${process.platform}-${process.arch}`, true);
|
|
56
|
+
console.log('');
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error('❌ Error al obtener la versión:', error.message);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
showVersion().catch(error => {
|
|
64
|
+
console.error('Error fatal:', error);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
});
|
package/src/index.js
CHANGED
|
@@ -1,104 +1,162 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
for (let i = 2; i < args.length; i++) {
|
|
17
|
-
commandArgs.push(args[i]);
|
|
18
|
-
}
|
|
19
|
-
} else if (args[0].includes('create:')) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
'run:table:
|
|
39
|
-
'run:table:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
'run:database:create': '../src/commands/run/database/create/
|
|
47
|
-
'run:database:create:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
'run:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
'
|
|
57
|
-
'
|
|
58
|
-
'
|
|
59
|
-
'
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
'migrate:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
'
|
|
68
|
-
|
|
69
|
-
'
|
|
70
|
-
|
|
71
|
-
'
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
|
|
5
|
+
// Obtener los argumentos pasados al comando
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
|
|
8
|
+
// Procesar los argumentos
|
|
9
|
+
let mainCommand = '';
|
|
10
|
+
const commandArgs = [];
|
|
11
|
+
|
|
12
|
+
if (args.length > 0) {
|
|
13
|
+
// Si el primer argumento es "run", combinamos con el segundo para formar el comando
|
|
14
|
+
if (args[0] === 'run' && args.length > 1) {
|
|
15
|
+
mainCommand = 'run:' + args[1];
|
|
16
|
+
for (let i = 2; i < args.length; i++) {
|
|
17
|
+
commandArgs.push(args[i]);
|
|
18
|
+
}
|
|
19
|
+
} else if (args[0].includes('create:')) {
|
|
20
|
+
mainCommand = args[0];
|
|
21
|
+
for (let i = 1; i < args.length; i++) {
|
|
22
|
+
commandArgs.push(args[i]);
|
|
23
|
+
}
|
|
24
|
+
} else {
|
|
25
|
+
mainCommand = args[0];
|
|
26
|
+
for (let i = 1; i < args.length; i++) {
|
|
27
|
+
commandArgs.push(args[i]);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
// Sin argumentos: mostrar ayuda en lugar de fallar
|
|
32
|
+
mainCommand = '--help';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Mapa de comandos para mapear nombres de comandos a rutas de archivo
|
|
36
|
+
const commandMap = {
|
|
37
|
+
'run:table:fresh': '../src/commands/run/table/fresh.js',
|
|
38
|
+
'run:table:refresh': '../src/commands/run/table/refresh.js',
|
|
39
|
+
'run:table:alter': '../src/commands/run/table/alter.js',
|
|
40
|
+
|
|
41
|
+
'run:trigger:fresh': '../src/commands/run/trigger/fresh.js',
|
|
42
|
+
|
|
43
|
+
'run:seeder:add': '../src/commands/run/seeder/add.js',
|
|
44
|
+
|
|
45
|
+
'run:database:create': '../src/commands/run/database/create/index.js',
|
|
46
|
+
'run:database:create:config': '../src/commands/run/database/create/addDatabaseConfig.js',
|
|
47
|
+
'run:database:create:physical': '../src/commands/run/database/create/createDatabase.js',
|
|
48
|
+
// Alias sin "run" (el help histórico lo documenta así)
|
|
49
|
+
'database:create': '../src/commands/run/database/create/index.js',
|
|
50
|
+
|
|
51
|
+
'run:pull': '../src/commands/run/pull.js',
|
|
52
|
+
|
|
53
|
+
'run:download': '../src/commands/run/download.js',
|
|
54
|
+
'run:update': '../src/commands/run/update.js',
|
|
55
|
+
|
|
56
|
+
'init': '../src/commands/init.js',
|
|
57
|
+
'generate': '../src/commands/generate.js',
|
|
58
|
+
'validate': '../src/commands/validate.js',
|
|
59
|
+
'doctor': '../src/commands/doctor.js',
|
|
60
|
+
'dev': '../src/commands/dev.js',
|
|
61
|
+
|
|
62
|
+
'migrate:status': '../src/commands/migrate/status.js',
|
|
63
|
+
'migrate:rollback': '../src/commands/migrate/rollback.js',
|
|
64
|
+
|
|
65
|
+
'update': '../src/commands/update.js',
|
|
66
|
+
|
|
67
|
+
'version': '../src/commands/version.js',
|
|
68
|
+
'--version': '../src/commands/version.js',
|
|
69
|
+
'-v': '../src/commands/version.js',
|
|
70
|
+
|
|
71
|
+
'help': '../src/commands/help.js',
|
|
72
|
+
'--help': '../src/commands/help.js',
|
|
73
|
+
'-h': '../src/commands/help.js',
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Distancia de Levenshtein para sugerencias "did you mean"
|
|
77
|
+
function levenshtein(a, b) {
|
|
78
|
+
const m = Array.from({ length: a.length + 1 }, (_, i) => [i, ...Array(b.length).fill(0)]);
|
|
79
|
+
for (let j = 0; j <= b.length; j++) m[0][j] = j;
|
|
80
|
+
for (let i = 1; i <= a.length; i++) {
|
|
81
|
+
for (let j = 1; j <= b.length; j++) {
|
|
82
|
+
m[i][j] = Math.min(
|
|
83
|
+
m[i - 1][j] + 1,
|
|
84
|
+
m[i][j - 1] + 1,
|
|
85
|
+
m[i - 1][j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return m[a.length][b.length];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function suggestCommand(input) {
|
|
93
|
+
// Candidatos: forma completa ("run table:fresh") y forma corta ("table:fresh"),
|
|
94
|
+
// ambos mostrando siempre la forma completa al usuario.
|
|
95
|
+
const candidates = [];
|
|
96
|
+
for (const c of Object.keys(commandMap)) {
|
|
97
|
+
if (c.startsWith('-')) continue;
|
|
98
|
+
if (c.startsWith('run:')) {
|
|
99
|
+
const display = 'run ' + c.slice(4);
|
|
100
|
+
candidates.push({ match: display, display });
|
|
101
|
+
candidates.push({ match: c.slice(4), display });
|
|
102
|
+
} else {
|
|
103
|
+
candidates.push({ match: c, display: c });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const scored = candidates
|
|
108
|
+
.map(({ match, display }) => ({ display, d: levenshtein(input.toLowerCase(), match.toLowerCase()) }))
|
|
109
|
+
.sort((x, y) => x.d - y.d);
|
|
110
|
+
|
|
111
|
+
if (scored.length === 0 || scored[0].d > Math.max(3, Math.floor(input.length / 2))) return [];
|
|
112
|
+
|
|
113
|
+
const seen = new Set();
|
|
114
|
+
return scored
|
|
115
|
+
.filter(s => s.d <= scored[0].d + 1)
|
|
116
|
+
.filter(s => !seen.has(s.display) && seen.add(s.display))
|
|
117
|
+
.slice(0, 3)
|
|
118
|
+
.map(s => s.display);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Función para ejecutar comandos basados en los argumentos
|
|
122
|
+
async function executeCommand(command, commandArgs) {
|
|
123
|
+
if (commandMap[command]) {
|
|
124
|
+
const examplePath = path.join(__dirname, commandMap[command]);
|
|
125
|
+
const originalArgv = process.argv;
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
process.argv = [process.argv[0], process.argv[1], ...commandArgs];
|
|
129
|
+
await require(examplePath);
|
|
130
|
+
} finally {
|
|
131
|
+
process.argv = originalArgv;
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
// Comando desconocido: error claro + sugerencias
|
|
135
|
+
const typed = [args[0], args[1]].filter(Boolean).join(' ');
|
|
136
|
+
console.log('');
|
|
137
|
+
console.log(` ${chalk.bgRed.white.bold(' ERROR ')} ${chalk.red(`Unknown command:`)} ${chalk.bold(typed)}`);
|
|
138
|
+
|
|
139
|
+
const suggestions = suggestCommand(typed);
|
|
140
|
+
if (suggestions.length > 0) {
|
|
141
|
+
console.log('');
|
|
142
|
+
console.log(` ${chalk.cyan('Did you mean:')}`);
|
|
143
|
+
for (const s of suggestions) {
|
|
144
|
+
console.log(` ${chalk.green('→')} ${chalk.white('npx dbcube ' + s)}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
console.log('');
|
|
149
|
+
console.log(` ${chalk.gray('Run')} ${chalk.yellow('npx dbcube help')} ${chalk.gray('to see all available commands.')}`);
|
|
150
|
+
console.log('');
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Ejecutar el comando correspondiente
|
|
156
|
+
executeCommand(mainCommand, commandArgs).catch(err => {
|
|
157
|
+
console.log('');
|
|
158
|
+
console.log(` ${chalk.bgRed.white.bold(' FATAL ')} ${chalk.red(err.message)}`);
|
|
159
|
+
console.log(` ${chalk.gray('Run')} ${chalk.yellow('npx dbcube doctor')} ${chalk.gray('to diagnose your setup.')}`);
|
|
160
|
+
console.log('');
|
|
161
|
+
process.exit(1);
|
|
162
|
+
});
|
|
@@ -78,8 +78,9 @@ class ConfigFileUtils {
|
|
|
78
78
|
}
|
|
79
79
|
return arrayDatabases;
|
|
80
80
|
} catch (error) {
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
// Fallar claro: devolver una DB inventada ocultaría el problema
|
|
82
|
+
// y haría que los comandos operen contra una base inexistente
|
|
83
|
+
throw new Error(`No se pudo cargar la configuración desde ${configPath}: ${error.message}`);
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
|
package/.npmignore
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# Directories
|
|
2
|
-
examples
|
|
3
|
-
|
|
4
|
-
# Ignorar dependencias y configuraciones de desarrollo
|
|
5
|
-
node_modules/
|
|
6
|
-
npm-debug.log*
|
|
7
|
-
yarn-debug.log*
|
|
8
|
-
yarn-error.log*
|
|
9
|
-
|
|
10
|
-
# Ignorar carpetas y archivos irrelevantes
|
|
11
|
-
.vscode/
|
|
12
|
-
.lh
|
|
13
|
-
.idea/
|
|
14
|
-
.DS_Store
|
|
15
|
-
Thumbs.db
|
|
16
|
-
*.log
|
|
17
|
-
|
|
18
|
-
# Ignorar configuraciones del proyecto
|
|
19
|
-
.env
|
|
20
|
-
.env.*.local
|
|
21
|
-
package-lock.json
|
|
22
|
-
|
|
23
|
-
# Ignorar archivos del sistema
|
|
24
|
-
*.swp
|
|
25
|
-
*.swo
|
|
26
|
-
*.tmp
|
|
27
|
-
*.temp
|
|
28
|
-
|
|
29
|
-
# Ignorar carpetas de trabajo
|
|
30
|
-
temp/
|
|
31
|
-
logs/
|
|
32
|
-
debug/
|
|
33
|
-
|
|
34
|
-
# Ignorar archivos de compilación
|
|
35
|
-
src/
|
|
36
|
-
tsconfig.json
|
|
37
|
-
tsconfig.tsbuildinfo
|
|
38
|
-
|
|
39
|
-
# Ignorar pruebas y configuraciones
|
|
40
|
-
tests/
|
|
41
|
-
__tests__/
|
|
42
|
-
__mocks__/
|
|
43
|
-
coverage/
|
|
44
|
-
jest.config.js
|
|
45
|
-
|
|
46
|
-
# Ignorar documentación o ejemplos no necesarios
|
|
47
|
-
docs/
|
|
48
|
-
examples/
|
|
49
|
-
|
|
50
|
-
# Asegurarse de incluir solo lo esencial
|
|
51
|
-
!.npmignore
|
|
52
|
-
tsconfig.json
|
|
53
|
-
tsup.config.ts
|
|
54
|
-
|
|
55
|
-
.dbcube
|
|
56
|
-
dbcube
|
|
57
|
-
.env
|
|
58
|
-
*.db
|
package/bun.lock
DELETED
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"lockfileVersion": 1,
|
|
3
|
-
"workspaces": {
|
|
4
|
-
"": {
|
|
5
|
-
"name": "@dbcube/cli",
|
|
6
|
-
"dependencies": {
|
|
7
|
-
"@dbcube/schema-builder": "^5.1.7",
|
|
8
|
-
"@inquirer/prompts": "^8.5.2",
|
|
9
|
-
"alwait": "^1.0.0",
|
|
10
|
-
"chalk": "4.1.2",
|
|
11
|
-
"dotenv": "^17.4.2",
|
|
12
|
-
"fs-extra": "^11.3.5",
|
|
13
|
-
"glob": "^13.0.6",
|
|
14
|
-
"ora": "5.4.1",
|
|
15
|
-
"unzipper": "^0.12.3",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
"overrides": {
|
|
20
|
-
"chalk": "4.1.2",
|
|
21
|
-
"ora": "5.4.1",
|
|
22
|
-
},
|
|
23
|
-
"packages": {
|
|
24
|
-
"@dbcube/core": ["@dbcube/core@5.1.15", "", { "dependencies": { "chalk": "4.1.2", "deasync": "^0.1.31", "follow-redirects": "^1.16.0", "ora": "5.4.1", "unzipper": "^0.12.3" }, "bin": { "dbcube-core": "dist/bin.cjs" } }, "sha512-/sA4Mya1pqb77Ki8LVm8mPnQVZb6OFsfxjR58rP8OeAOp/uWDWrBfL5GFdi8+a2+oZYJvz5d1DA/nEBB3jYjSA=="],
|
|
25
|
-
|
|
26
|
-
"@dbcube/schema-builder": ["@dbcube/schema-builder@5.1.7", "", { "dependencies": { "@dbcube/core": "^5.1.15", "chalk": "^5.6.2", "ora": "^9.4.0" } }, "sha512-oTea6R1EgKxwRjI7N1IkFnMZZms3pOMzPVATUaCZzHiUSol+IgHZ5rYQJvGIGXAs1s4lGndE1OokISHoc6o89g=="],
|
|
27
|
-
|
|
28
|
-
"@inquirer/ansi": ["@inquirer/ansi@2.0.7", "", {}, "sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q=="],
|
|
29
|
-
|
|
30
|
-
"@inquirer/checkbox": ["@inquirer/checkbox@5.2.1", "", { "dependencies": { "@inquirer/ansi": "^2.0.7", "@inquirer/core": "^11.2.1", "@inquirer/figures": "^2.0.7", "@inquirer/type": "^4.0.7" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-b6xmA/VlTe0ZgDQHDui+Nav470u7u49nRd8/iuhOcQPO9Ch7lGuogydhi2VOmNlZ+zXcM8IcPuNSwQcdJaF/kw=="],
|
|
31
|
-
|
|
32
|
-
"@inquirer/confirm": ["@inquirer/confirm@6.1.1", "", { "dependencies": { "@inquirer/core": "^11.2.1", "@inquirer/type": "^4.0.7" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ=="],
|
|
33
|
-
|
|
34
|
-
"@inquirer/core": ["@inquirer/core@11.2.1", "", { "dependencies": { "@inquirer/ansi": "^2.0.7", "@inquirer/figures": "^2.0.7", "@inquirer/type": "^4.0.7", "cli-width": "^4.1.0", "fast-wrap-ansi": "^0.2.0", "mute-stream": "^3.0.0", "signal-exit": "^4.1.0" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA=="],
|
|
35
|
-
|
|
36
|
-
"@inquirer/editor": ["@inquirer/editor@5.2.2", "", { "dependencies": { "@inquirer/core": "^11.2.1", "@inquirer/external-editor": "^3.0.3", "@inquirer/type": "^4.0.7" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-ZRVd/oD+sYsUd5zVm0NflqEzlqfYCyHNsqkHl2oWXEUHs12tCbcSFi+wVFEvD8+LGRaMUsVrE7qeo6lSG/S1Vg=="],
|
|
37
|
-
|
|
38
|
-
"@inquirer/expand": ["@inquirer/expand@5.1.1", "", { "dependencies": { "@inquirer/core": "^11.2.1", "@inquirer/type": "^4.0.7" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-YmQpenjbFSHAK3sOd44puHh3V1KXXr+JiNpUztoSQ4drLh2rTVzTap/YtlAVu/5xavifIlBfNEzJ/neZJ1a/1g=="],
|
|
39
|
-
|
|
40
|
-
"@inquirer/external-editor": ["@inquirer/external-editor@3.0.3", "", { "dependencies": { "chardet": "^2.1.1", "iconv-lite": "^0.7.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-6thf5I8q7lZwzGLAxPaaGEREEkZ3nyePPDQ1oyobblxmEE8mqTLguScP7pDjUTAibiyb4hfXl+qjUEJ+di/aNA=="],
|
|
41
|
-
|
|
42
|
-
"@inquirer/figures": ["@inquirer/figures@2.0.7", "", {}, "sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw=="],
|
|
43
|
-
|
|
44
|
-
"@inquirer/input": ["@inquirer/input@5.1.2", "", { "dependencies": { "@inquirer/core": "^11.2.1", "@inquirer/type": "^4.0.7" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-9K/DDBSQpOyZSkt6sOVP9Vo0TR7atX2kuILsUu0x3wVcVbe97lJwIJKMLdMw25tDYuXl/qp6erT0Xs1rfmcfZg=="],
|
|
45
|
-
|
|
46
|
-
"@inquirer/number": ["@inquirer/number@4.1.1", "", { "dependencies": { "@inquirer/core": "^11.2.1", "@inquirer/type": "^4.0.7" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-XF4IXAbPnGPgw0wsbC/i2tPcyfdZgDpUlhsqU0SfT4IRIGWha6Xm9VRgN5yYxJq+jnyXlfXI/nQ3ulfk0iEICA=="],
|
|
47
|
-
|
|
48
|
-
"@inquirer/password": ["@inquirer/password@5.1.1", "", { "dependencies": { "@inquirer/ansi": "^2.0.7", "@inquirer/core": "^11.2.1", "@inquirer/type": "^4.0.7" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-3XBfF7DAsp5qeDsvN5Rd1HmbNokVvEQoUM0QLrRcybC9nX96w3Pbmu7qUsb3IT3J3jBvs2+mTXaKHOUsgHMLzg=="],
|
|
49
|
-
|
|
50
|
-
"@inquirer/prompts": ["@inquirer/prompts@8.5.2", "", { "dependencies": { "@inquirer/checkbox": "^5.2.1", "@inquirer/confirm": "^6.1.1", "@inquirer/editor": "^5.2.2", "@inquirer/expand": "^5.1.1", "@inquirer/input": "^5.1.2", "@inquirer/number": "^4.1.1", "@inquirer/password": "^5.1.1", "@inquirer/rawlist": "^5.3.1", "@inquirer/search": "^4.2.1", "@inquirer/select": "^5.2.1" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-IYR/3C/paEVVQYQvdDlFZVjRCJVYHHON0XXMH91KO9GSxs0TdKYWlUdvfQl2EfAHDxUaN3IBffkE/BDTh5nJ6g=="],
|
|
51
|
-
|
|
52
|
-
"@inquirer/rawlist": ["@inquirer/rawlist@5.3.1", "", { "dependencies": { "@inquirer/core": "^11.2.1", "@inquirer/type": "^4.0.7" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-QqdTqQddL3qPX/PPrjobpsO25NZ4dWXgTLenrR445L2ptLEYE6Z+PD5c5CNDJNx4ugRgELAIpSIJxZaO2jJ2Og=="],
|
|
53
|
-
|
|
54
|
-
"@inquirer/search": ["@inquirer/search@4.2.1", "", { "dependencies": { "@inquirer/core": "^11.2.1", "@inquirer/figures": "^2.0.7", "@inquirer/type": "^4.0.7" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-xJj8QWKRSrfKoBIITLZK61dD3zwo0Rz11fgDImku30/Oe81zMdIdGgrLY2h6RkJ+KZ/GhNYIRMKnH/62qBTA5g=="],
|
|
55
|
-
|
|
56
|
-
"@inquirer/select": ["@inquirer/select@5.2.1", "", { "dependencies": { "@inquirer/ansi": "^2.0.7", "@inquirer/core": "^11.2.1", "@inquirer/figures": "^2.0.7", "@inquirer/type": "^4.0.7" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw=="],
|
|
57
|
-
|
|
58
|
-
"@inquirer/type": ["@inquirer/type@4.0.7", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g=="],
|
|
59
|
-
|
|
60
|
-
"alwait": ["alwait@1.0.0", "", {}, "sha512-o+jEoGVTJyvYDT5mOWkj2i4IsOC7SNCWGc/+o6rAfGx1x3jCBIeFsCwgW/3ZiNJ2dE3Hr1lzxC2a++6dLRLGqQ=="],
|
|
61
|
-
|
|
62
|
-
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
|
63
|
-
|
|
64
|
-
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
|
65
|
-
|
|
66
|
-
"balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
|
67
|
-
|
|
68
|
-
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
|
69
|
-
|
|
70
|
-
"bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
|
|
71
|
-
|
|
72
|
-
"bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
|
|
73
|
-
|
|
74
|
-
"bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="],
|
|
75
|
-
|
|
76
|
-
"brace-expansion": ["brace-expansion@5.0.3", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA=="],
|
|
77
|
-
|
|
78
|
-
"buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
|
|
79
|
-
|
|
80
|
-
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
|
81
|
-
|
|
82
|
-
"chardet": ["chardet@2.1.1", "", {}, "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ=="],
|
|
83
|
-
|
|
84
|
-
"cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
|
|
85
|
-
|
|
86
|
-
"cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
|
|
87
|
-
|
|
88
|
-
"cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="],
|
|
89
|
-
|
|
90
|
-
"clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="],
|
|
91
|
-
|
|
92
|
-
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
|
93
|
-
|
|
94
|
-
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
|
95
|
-
|
|
96
|
-
"core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
|
|
97
|
-
|
|
98
|
-
"deasync": ["deasync@0.1.31", "", { "dependencies": { "bindings": "^1.5.0", "node-addon-api": "^1.7.1" } }, "sha512-/6/cXqkw4LPqBVK6H0Y3L4zT7yI3pxykxPXErQ2tDCw0LJyThWL5VpBCpUOWX0vPq2OnF1pzcXvlNnvCiOQJuA=="],
|
|
99
|
-
|
|
100
|
-
"defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="],
|
|
101
|
-
|
|
102
|
-
"dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="],
|
|
103
|
-
|
|
104
|
-
"duplexer2": ["duplexer2@0.1.4", "", { "dependencies": { "readable-stream": "^2.0.2" } }, "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA=="],
|
|
105
|
-
|
|
106
|
-
"fast-string-truncated-width": ["fast-string-truncated-width@3.0.3", "", {}, "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g=="],
|
|
107
|
-
|
|
108
|
-
"fast-string-width": ["fast-string-width@3.0.2", "", { "dependencies": { "fast-string-truncated-width": "^3.0.2" } }, "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg=="],
|
|
109
|
-
|
|
110
|
-
"fast-wrap-ansi": ["fast-wrap-ansi@0.2.0", "", { "dependencies": { "fast-string-width": "^3.0.2" } }, "sha512-rLV8JHxTyhVmFYhBJuMujcrHqOT2cnO5Zxj37qROj23CP39GXubJRBUFF0z8KFK77Uc0SukZUf7JZhsVEQ6n8w=="],
|
|
111
|
-
|
|
112
|
-
"file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
|
|
113
|
-
|
|
114
|
-
"follow-redirects": ["follow-redirects@1.16.0", "", {}, "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw=="],
|
|
115
|
-
|
|
116
|
-
"fs-extra": ["fs-extra@11.3.5", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg=="],
|
|
117
|
-
|
|
118
|
-
"glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
|
|
119
|
-
|
|
120
|
-
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
|
121
|
-
|
|
122
|
-
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
|
123
|
-
|
|
124
|
-
"iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
|
|
125
|
-
|
|
126
|
-
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
|
127
|
-
|
|
128
|
-
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
|
129
|
-
|
|
130
|
-
"is-interactive": ["is-interactive@1.0.0", "", {}, "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="],
|
|
131
|
-
|
|
132
|
-
"is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="],
|
|
133
|
-
|
|
134
|
-
"isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
|
|
135
|
-
|
|
136
|
-
"jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="],
|
|
137
|
-
|
|
138
|
-
"log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="],
|
|
139
|
-
|
|
140
|
-
"lru-cache": ["lru-cache@11.2.1", "", {}, "sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ=="],
|
|
141
|
-
|
|
142
|
-
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
|
143
|
-
|
|
144
|
-
"minimatch": ["minimatch@10.2.2", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw=="],
|
|
145
|
-
|
|
146
|
-
"minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
|
147
|
-
|
|
148
|
-
"mute-stream": ["mute-stream@3.0.0", "", {}, "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw=="],
|
|
149
|
-
|
|
150
|
-
"node-addon-api": ["node-addon-api@1.7.2", "", {}, "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg=="],
|
|
151
|
-
|
|
152
|
-
"node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="],
|
|
153
|
-
|
|
154
|
-
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
|
|
155
|
-
|
|
156
|
-
"ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="],
|
|
157
|
-
|
|
158
|
-
"path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
|
159
|
-
|
|
160
|
-
"process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="],
|
|
161
|
-
|
|
162
|
-
"readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
|
163
|
-
|
|
164
|
-
"restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="],
|
|
165
|
-
|
|
166
|
-
"safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
|
167
|
-
|
|
168
|
-
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
|
169
|
-
|
|
170
|
-
"signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
|
171
|
-
|
|
172
|
-
"string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
|
|
173
|
-
|
|
174
|
-
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
|
175
|
-
|
|
176
|
-
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
|
177
|
-
|
|
178
|
-
"universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
|
|
179
|
-
|
|
180
|
-
"unzipper": ["unzipper@0.12.3", "", { "dependencies": { "bluebird": "~3.7.2", "duplexer2": "~0.1.4", "fs-extra": "^11.2.0", "graceful-fs": "^4.2.2", "node-int64": "^0.4.0" } }, "sha512-PZ8hTS+AqcGxsaQntl3IRBw65QrBI6lxzqDEL7IAo/XCEqRTKGfOX56Vea5TH9SZczRVxuzk1re04z/YjuYCJA=="],
|
|
181
|
-
|
|
182
|
-
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
|
183
|
-
|
|
184
|
-
"wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="],
|
|
185
|
-
|
|
186
|
-
"duplexer2/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
|
187
|
-
|
|
188
|
-
"restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
|
189
|
-
|
|
190
|
-
"unzipper/fs-extra": ["fs-extra@11.3.2", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A=="],
|
|
191
|
-
}
|
|
192
|
-
}
|
package/dbcube.config.js
DELETED
package/pnpm-workspace.yaml
DELETED
package/test-new-features.js
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* End-to-end test of the new query-builder features against the local
|
|
3
|
-
* SQLite test database (daemon mode + transactions + new methods).
|
|
4
|
-
* Run: node test-new-features.js
|
|
5
|
-
*/
|
|
6
|
-
const { Database } = require('@dbcube/query-builder');
|
|
7
|
-
|
|
8
|
-
const results = [];
|
|
9
|
-
function check(name, condition, detail = '') {
|
|
10
|
-
results.push({ name, ok: !!condition, detail });
|
|
11
|
-
console.log(`${condition ? '✅' : '❌'} ${name}${detail ? ` — ${detail}` : ''}`);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async function main() {
|
|
15
|
-
const db = new Database('test');
|
|
16
|
-
const t0 = Date.now();
|
|
17
|
-
|
|
18
|
-
// 0. Clean slate for the test table via raw()
|
|
19
|
-
await db.raw('DROP TABLE IF EXISTS qa_items');
|
|
20
|
-
await db.raw('CREATE TABLE qa_items (uuid TEXT, id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, qty INTEGER DEFAULT 0, price REAL)');
|
|
21
|
-
check('raw(): DDL ejecutado', true);
|
|
22
|
-
|
|
23
|
-
// 1. insert
|
|
24
|
-
const inserted = await db.table('qa_items').insert([
|
|
25
|
-
{ name: 'alpha', qty: 10, price: 5.5 },
|
|
26
|
-
{ name: 'beta', qty: 3, price: 2.0 },
|
|
27
|
-
{ name: 'gamma', qty: 0, price: 9.9 },
|
|
28
|
-
]);
|
|
29
|
-
check('insert(): 3 filas', Array.isArray(inserted));
|
|
30
|
-
|
|
31
|
-
// 2. raw with params
|
|
32
|
-
const rawRows = await db.raw('SELECT * FROM qa_items WHERE qty > ?', [1]);
|
|
33
|
-
check('raw() con parámetros', Array.isArray(rawRows) && rawRows.length === 2, `${rawRows.length} filas`);
|
|
34
|
-
|
|
35
|
-
// 3. exists / whereNotIn / offset
|
|
36
|
-
const hasAlpha = await db.table('qa_items').where('name', '=', 'alpha').exists();
|
|
37
|
-
const noDelta = await db.table('qa_items').where('name', '=', 'delta').exists();
|
|
38
|
-
check('exists()', hasAlpha === true && noDelta === false);
|
|
39
|
-
|
|
40
|
-
const notIn = await db.table('qa_items').whereNotIn('name', ['alpha']).get();
|
|
41
|
-
check('whereNotIn()', notIn.length === 2, `${notIn.length} filas`);
|
|
42
|
-
|
|
43
|
-
const offsetRows = await db.table('qa_items').orderBy('id', 'ASC').limit(10).offset(1).get();
|
|
44
|
-
check('offset()', offsetRows.length === 2 && offsetRows[0].name === 'beta');
|
|
45
|
-
|
|
46
|
-
// 4. paginate
|
|
47
|
-
const page = await db.table('qa_items').orderBy('id', 'ASC').paginate(1, 2);
|
|
48
|
-
check('paginate()', page.items.length === 2 && page.total === 3 && page.totalPages === 2 && page.hasNext === true,
|
|
49
|
-
JSON.stringify({ total: page.total, pages: page.totalPages }));
|
|
50
|
-
|
|
51
|
-
// 5. chunk
|
|
52
|
-
let chunkTotal = 0, chunkCalls = 0;
|
|
53
|
-
await db.table('qa_items').orderBy('id', 'ASC').chunk(2, rows => { chunkTotal += rows.length; chunkCalls++; });
|
|
54
|
-
check('chunk()', chunkTotal === 3 && chunkCalls === 2, `${chunkCalls} lotes, ${chunkTotal} filas`);
|
|
55
|
-
|
|
56
|
-
// 6. increment / decrement (atómico)
|
|
57
|
-
await db.table('qa_items').where('name', '=', 'beta').increment('qty', 5);
|
|
58
|
-
await db.table('qa_items').where('name', '=', 'alpha').decrement('qty', 4);
|
|
59
|
-
const beta = await db.table('qa_items').find('beta', 'name');
|
|
60
|
-
const alpha = await db.table('qa_items').find('alpha', 'name');
|
|
61
|
-
check('increment()/decrement()', beta.qty === 8 && alpha.qty === 6, `beta=${beta.qty} alpha=${alpha.qty}`);
|
|
62
|
-
|
|
63
|
-
// 7. upsert (SQLite necesita UNIQUE en la clave de conflicto)
|
|
64
|
-
await db.raw('CREATE UNIQUE INDEX IF NOT EXISTS qa_items_name ON qa_items(name)');
|
|
65
|
-
await db.table('qa_items').upsert([{ name: 'alpha', qty: 100, price: 1.0 }, { name: 'delta', qty: 7, price: 3.3 }], ['name']);
|
|
66
|
-
const alphaUp = await db.table('qa_items').find('alpha', 'name');
|
|
67
|
-
const delta = await db.table('qa_items').find('delta', 'name');
|
|
68
|
-
check('upsert()', alphaUp.qty === 100 && delta !== null, `alpha.qty=${alphaUp.qty}, delta insertado=${delta !== null}`);
|
|
69
|
-
|
|
70
|
-
// 8. having + selectRaw + groupBy
|
|
71
|
-
const grouped = await db.table('qa_items')
|
|
72
|
-
.selectRaw(['CASE WHEN qty > 5 THEN \'high\' ELSE \'low\' END AS bucket', 'COUNT(*) AS n'])
|
|
73
|
-
.groupBy('bucket')
|
|
74
|
-
.having('n', '>', 1)
|
|
75
|
-
.get();
|
|
76
|
-
check('selectRaw()+groupBy()+having()', Array.isArray(grouped) && grouped.length >= 1, JSON.stringify(grouped));
|
|
77
|
-
|
|
78
|
-
// 9. transaction commit
|
|
79
|
-
await db.transaction(async (trx) => {
|
|
80
|
-
await trx.table('qa_items').where('name', '=', 'beta').update({ price: 111 });
|
|
81
|
-
await trx.table('qa_items').insert([{ name: 'epsilon', qty: 1, price: 0.5 }]);
|
|
82
|
-
});
|
|
83
|
-
const betaTx = await db.table('qa_items').find('beta', 'name');
|
|
84
|
-
const eps = await db.table('qa_items').find('epsilon', 'name');
|
|
85
|
-
check('transaction() commit', betaTx.price === 111 && eps !== null);
|
|
86
|
-
|
|
87
|
-
// 10. transaction rollback
|
|
88
|
-
let rolledBack = false;
|
|
89
|
-
try {
|
|
90
|
-
await db.transaction(async (trx) => {
|
|
91
|
-
await trx.table('qa_items').where('name', '=', 'beta').update({ price: 999 });
|
|
92
|
-
throw new Error('forced failure');
|
|
93
|
-
});
|
|
94
|
-
} catch (e) {
|
|
95
|
-
rolledBack = e.message === 'forced failure';
|
|
96
|
-
}
|
|
97
|
-
const betaRb = await db.table('qa_items').find('beta', 'name');
|
|
98
|
-
check('transaction() rollback', rolledBack && betaRb.price === 111, `price=${betaRb.price} (esperado 111)`);
|
|
99
|
-
|
|
100
|
-
// 11. truncate
|
|
101
|
-
await db.raw('CREATE TABLE IF NOT EXISTS qa_tmp (uuid TEXT, id INTEGER PRIMARY KEY AUTOINCREMENT, v TEXT)');
|
|
102
|
-
await db.table('qa_tmp').insert([{ v: 'x' }, { v: 'y' }]);
|
|
103
|
-
await db.table('qa_tmp').truncate();
|
|
104
|
-
const tmpCount = await db.table('qa_tmp').count();
|
|
105
|
-
check('truncate()', Number(tmpCount) === 0);
|
|
106
|
-
|
|
107
|
-
// 12. Velocidad: 30 queries seguidas (daemon vs spawn)
|
|
108
|
-
const n = 30;
|
|
109
|
-
const t1 = Date.now();
|
|
110
|
-
for (let i = 0; i < n; i++) {
|
|
111
|
-
await db.table('qa_items').where('qty', '>', 0).limit(1).get();
|
|
112
|
-
}
|
|
113
|
-
const elapsed = Date.now() - t1;
|
|
114
|
-
const avg = (elapsed / n).toFixed(1);
|
|
115
|
-
check('velocidad: 30 queries seguidas', true, `${elapsed}ms total → ${avg}ms/query promedio`);
|
|
116
|
-
|
|
117
|
-
// Cleanup
|
|
118
|
-
await db.raw('DROP TABLE IF EXISTS qa_items');
|
|
119
|
-
await db.raw('DROP TABLE IF EXISTS qa_tmp');
|
|
120
|
-
|
|
121
|
-
const failed = results.filter(r => !r.ok);
|
|
122
|
-
console.log(`\n${failed.length === 0 ? '🎉 TODOS LOS TESTS PASARON' : `❌ ${failed.length} fallos`} (${results.length} checks, ${Date.now() - t0}ms)`);
|
|
123
|
-
process.exit(failed.length === 0 ? 0 : 1);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
main().catch(e => {
|
|
127
|
-
console.error('💥 Test crashed:', e.message);
|
|
128
|
-
process.exit(1);
|
|
129
|
-
});
|