querymongo 1.0.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.
Files changed (50) hide show
  1. package/README.md +206 -0
  2. package/dist/application/MongoConverter.js +20 -0
  3. package/dist/application/MongoConverter.js.map +1 -0
  4. package/dist/application/MongoConverter.spec.js +59 -0
  5. package/dist/application/MongoConverter.spec.js.map +1 -0
  6. package/dist/cli/main.js +59 -0
  7. package/dist/cli/main.js.map +1 -0
  8. package/dist/domain/interfaces/Converter.js +2 -0
  9. package/dist/domain/interfaces/Converter.js.map +1 -0
  10. package/dist/index.js +6 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/infrastructure/converters/ConverterFactory.js +14 -0
  13. package/dist/infrastructure/converters/ConverterFactory.js.map +1 -0
  14. package/dist/infrastructure/converters/CreateConverter.js +27 -0
  15. package/dist/infrastructure/converters/CreateConverter.js.map +1 -0
  16. package/dist/infrastructure/converters/DeleteConverter.js +21 -0
  17. package/dist/infrastructure/converters/DeleteConverter.js.map +1 -0
  18. package/dist/infrastructure/converters/SelectConverter.js +24 -0
  19. package/dist/infrastructure/converters/SelectConverter.js.map +1 -0
  20. package/dist/infrastructure/converters/UpdateConverter.js +23 -0
  21. package/dist/infrastructure/converters/UpdateConverter.js.map +1 -0
  22. package/dist/infrastructure/parser/sqlParser.js +13 -0
  23. package/dist/infrastructure/parser/sqlParser.js.map +1 -0
  24. package/dist/infrastructure/utils/queryUtils.js +71 -0
  25. package/dist/infrastructure/utils/queryUtils.js.map +1 -0
  26. package/dist/types/application/MongoConverter.d.ts +5 -0
  27. package/dist/types/application/MongoConverter.d.ts.map +1 -0
  28. package/dist/types/application/MongoConverter.spec.d.ts +2 -0
  29. package/dist/types/application/MongoConverter.spec.d.ts.map +1 -0
  30. package/dist/types/cli/main.d.ts +3 -0
  31. package/dist/types/cli/main.d.ts.map +1 -0
  32. package/dist/types/domain/interfaces/Converter.d.ts +9 -0
  33. package/dist/types/domain/interfaces/Converter.d.ts.map +1 -0
  34. package/dist/types/index.d.ts +7 -0
  35. package/dist/types/index.d.ts.map +1 -0
  36. package/dist/types/infrastructure/converters/ConverterFactory.d.ts +8 -0
  37. package/dist/types/infrastructure/converters/ConverterFactory.d.ts.map +1 -0
  38. package/dist/types/infrastructure/converters/CreateConverter.d.ts +7 -0
  39. package/dist/types/infrastructure/converters/CreateConverter.d.ts.map +1 -0
  40. package/dist/types/infrastructure/converters/DeleteConverter.d.ts +7 -0
  41. package/dist/types/infrastructure/converters/DeleteConverter.d.ts.map +1 -0
  42. package/dist/types/infrastructure/converters/SelectConverter.d.ts +7 -0
  43. package/dist/types/infrastructure/converters/SelectConverter.d.ts.map +1 -0
  44. package/dist/types/infrastructure/converters/UpdateConverter.d.ts +7 -0
  45. package/dist/types/infrastructure/converters/UpdateConverter.d.ts.map +1 -0
  46. package/dist/types/infrastructure/parser/sqlParser.d.ts +11 -0
  47. package/dist/types/infrastructure/parser/sqlParser.d.ts.map +1 -0
  48. package/dist/types/infrastructure/utils/queryUtils.d.ts +9 -0
  49. package/dist/types/infrastructure/utils/queryUtils.d.ts.map +1 -0
  50. package/package.json +55 -0
package/README.md ADDED
@@ -0,0 +1,206 @@
1
+ # QueryMongo 🚀
2
+
3
+ SQL to MongoDB Query Converter CLI - Convierte queries SQL a MongoDB format de forma simple y poderosa.
4
+
5
+ ## 📋 Características
6
+
7
+ ✅ **Convertir SELECT queries** - Con proyecciones, filtros y límites
8
+ ✅ **Convertir INSERT queries** - Para inserción de documentos
9
+ ✅ **Convertir UPDATE queries** - Con filtros y actualizaciones
10
+ ✅ **Convertir DELETE queries** - Para eliminación de documentos
11
+ ✅ **CLI interactiva** - Modo interactivo para pruebas rápidas
12
+ ✅ **API TypeScript** - Para uso como librería en tus proyectos
13
+
14
+ ## 🏗️ Arquitectura
15
+
16
+ Proyecto implementado siguiendo **principios SOLID**, **Clean Code** y **DRY**:
17
+
18
+ ```
19
+ src/
20
+ ├── domain/
21
+ │ └── interfaces/
22
+ │ └── Converter.ts # Interface strategy para conversores
23
+ ├── infrastructure/
24
+ │ ├── parser/
25
+ │ │ └── sqlParser.ts # Wrapper sobre node-sql-parser
26
+ │ ├── converters/
27
+ │ │ ├── SelectConverter.ts # Estrategia SELECT
28
+ │ │ ├── CreateConverter.ts # Estrategia INSERT
29
+ │ │ ├── UpdateConverter.ts # Estrategia UPDATE
30
+ │ │ ├── DeleteConverter.ts # Estrategia DELETE
31
+ │ │ └── ConverterFactory.ts # Factory + Strategy Pattern
32
+ │ └── utils/
33
+ │ └── queryUtils.ts # Utilidades compartidas (DRY)
34
+ ├── application/
35
+ │ └── MongoConverter.ts # Orquestador principal
36
+ ├── cli/
37
+ │ └── main.ts # Interfaz CLI
38
+ └── index.ts # Exports públicos
39
+ ```
40
+
41
+ ### Patrones Aplicados
42
+
43
+ - **Strategy Pattern**: Cada tipo de query (SELECT, INSERT, etc) es una estrategia diferente
44
+ - **Factory Pattern**: `ConverterFactory` selecciona la estrategia correcta
45
+ - **Dependency Inversion**: Se depende de la interface `IConverter`, no de implementaciones
46
+ - **Single Responsibility**: Cada conversor tiene un propósito único
47
+
48
+ ## 🚀 Instalación
49
+
50
+ ```bash
51
+ npm install
52
+ npm run build
53
+ ```
54
+
55
+ ## 💻 Uso
56
+
57
+ ### Modo CLI - Interactivo
58
+
59
+ ```bash
60
+ npm run dev -- interactive
61
+ ```
62
+
63
+ Ingresa queries SQL y recibe instantáneamente el equivalente en MongoDB.
64
+
65
+ ### Usar como librería
66
+
67
+ ```typescript
68
+ import { mongoConverter } from "./src/application/MongoConverter.ts";
69
+
70
+ const result = mongoConverter.convert("SELECT name FROM users WHERE age > 18");
71
+ console.log(result);
72
+ ```
73
+
74
+ ## 📚 Ejemplos de Conversión
75
+
76
+ ### SELECT con proyección
77
+
78
+ ```sql
79
+ SELECT name, email FROM users
80
+ ```
81
+
82
+ **MongoDB:**
83
+
84
+ ```javascript
85
+ db.users.aggregate([{ $project: { name: 1, email: 1 } }]);
86
+ ```
87
+
88
+ ### SELECT con WHERE y LIMIT
89
+
90
+ ```sql
91
+ SELECT * FROM products WHERE price > 100 LIMIT 10
92
+ ```
93
+
94
+ **MongoDB:**
95
+
96
+ ```javascript
97
+ db.products.aggregate([{ $match: { price: { $gt: 100 } } }, { $limit: 10 }]);
98
+ ```
99
+
100
+ ### INSERT
101
+
102
+ ```sql
103
+ INSERT INTO users (name, email) VALUES ('John', 'john@example.com')
104
+ ```
105
+
106
+ **MongoDB:**
107
+
108
+ ```javascript
109
+ db.users.insertOne({ name: "John", email: "john@example.com" });
110
+ ```
111
+
112
+ ### UPDATE
113
+
114
+ ```sql
115
+ UPDATE users SET name = "Jane" WHERE id = 1
116
+ ```
117
+
118
+ **MongoDB:**
119
+
120
+ ```javascript
121
+ db.users.updateOne({ id: 1 }, { $set: { name: "Jane" } });
122
+ ```
123
+
124
+ ### DELETE
125
+
126
+ ```sql
127
+ DELETE FROM users WHERE id = 1
128
+ ```
129
+
130
+ **MongoDB:**
131
+
132
+ ```javascript
133
+ db.users.deleteOne({ id: 1 });
134
+ ```
135
+
136
+ ## 🧪 Testing
137
+
138
+ ```bash
139
+ npm test
140
+ ```
141
+
142
+ Cobertura: **100%** en líneas y funciones.
143
+
144
+ ## 📖 API Reference
145
+
146
+ ### `MongoConverter`
147
+
148
+ Clase principal para conversiones.
149
+
150
+ ```typescript
151
+ class MongoConverter {
152
+ convert(sql: string): Record<string, any>;
153
+ }
154
+ ```
155
+
156
+ **Parámetros:**
157
+
158
+ - `sql` (string): Query SQL a convertir
159
+
160
+ **Retorna:** Objeto con estructura MongoDB
161
+
162
+ **Lanza:** Error si el query SQL no es soportado
163
+
164
+ ### Exports Públicos
165
+
166
+ ```typescript
167
+ export {
168
+ MongoConverter,
169
+ mongoConverter,
170
+ } from "./src/application/MongoConverter.ts";
171
+ export type { IConverter } from "./src/domain/interfaces/Converter.ts";
172
+ ```
173
+
174
+ ## 🔧 Operadores Soportados
175
+
176
+ | SQL | MongoDB |
177
+ | ----------- | -------- |
178
+ | `=` | `$eq` |
179
+ | `!=` o `<>` | `$ne` |
180
+ | `<` | `$lt` |
181
+ | `>` | `$gt` |
182
+ | `<=` | `$lte` |
183
+ | `>=` | `$gte` |
184
+ | `LIKE` | `$regex` |
185
+ | `IN` | `$in` |
186
+ | `NOT IN` | `$nin` |
187
+
188
+ ## 📦 Dependencias
189
+
190
+ - **node-sql-parser**: Parseo de queries SQL
191
+ - **lodash**: Utilidades funcionales
192
+ - **chalk**: Colores en CLI
193
+ - **commander**: Interfaz CLI
194
+ - **typescript**: Compilador TypeScript
195
+
196
+ ## 🎯 Próximas Mejoras
197
+
198
+ - [ ] Soporte para JOIN
199
+ - [ ] Soporte para GROUP BY
200
+ - [ ] Soporte para ORDER BY
201
+ - [ ] Transacciones multi-documento
202
+ - [ ] Validación de esquema
203
+
204
+ ## 📄 Licencia
205
+
206
+ ISC
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Servicio principal de conversión
3
+ * Orquesta el parsing y la conversión a MongoDB
4
+ */
5
+ import { parseSqlQuery, normalizeQuery, } from "../infrastructure/parser/sqlParser.js";
6
+ import { getConverter } from "../infrastructure/converters/ConverterFactory.js";
7
+ export class MongoConverter {
8
+ convert(sql) {
9
+ const normalized = normalizeQuery(sql);
10
+ const parsed = parseSqlQuery(normalized);
11
+ const statement = Array.isArray(parsed) ? parsed[0] : parsed;
12
+ const converter = getConverter(normalized);
13
+ if (!converter) {
14
+ throw new Error(`Unsupported SQL statement: ${normalized.substring(0, 50)}...`);
15
+ }
16
+ return converter.convert(statement);
17
+ }
18
+ }
19
+ export const mongoConverter = new MongoConverter();
20
+ //# sourceMappingURL=MongoConverter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MongoConverter.js","sourceRoot":"","sources":["../../src/application/MongoConverter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,aAAa,EACb,cAAc,GACf,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,kDAAkD,CAAC;AAEhF,MAAM,OAAO,cAAc;IACzB,OAAO,CAAC,GAAW;QACjB,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QAEzC,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC7D,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;QAE3C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,8BAA8B,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAC/D,CAAC;QACJ,CAAC;QAED,OAAO,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Tests para verificar las conversiones SQL a MongoDB
3
+ */
4
+ import { test, describe } from "node:test";
5
+ import { equal, ok, throws } from "node:assert";
6
+ import { mongoConverter } from "../application/MongoConverter.js";
7
+ describe("MongoConverter", () => {
8
+ describe("SELECT queries", () => {
9
+ test("should convert simple SELECT query", () => {
10
+ const sql = "SELECT name, email FROM users";
11
+ const result = mongoConverter.convert(sql);
12
+ equal(result.collection, "users");
13
+ ok(result.pipeline.some((stage) => stage.$project));
14
+ });
15
+ test("should convert SELECT with WHERE clause", () => {
16
+ const sql = "SELECT * FROM users WHERE id = 1";
17
+ const result = mongoConverter.convert(sql);
18
+ equal(result.collection, "users");
19
+ ok(result.pipeline.some((stage) => stage.$match));
20
+ });
21
+ test("should convert SELECT with LIMIT", () => {
22
+ const sql = "SELECT name FROM products LIMIT 10";
23
+ const result = mongoConverter.convert(sql);
24
+ ok(result.pipeline.some((stage) => stage.$limit === 10));
25
+ });
26
+ });
27
+ describe("INSERT queries", () => {
28
+ test("should convert INSERT query", () => {
29
+ const sql = "INSERT INTO users (name, email) VALUES ('John', 'john@example.com')";
30
+ const result = mongoConverter.convert(sql);
31
+ equal(result.collection, "users");
32
+ equal(result.operation, "insertOne");
33
+ });
34
+ });
35
+ describe("UPDATE queries", () => {
36
+ test("should convert UPDATE query", () => {
37
+ const sql = 'UPDATE users SET name = "Jane" WHERE id = 1';
38
+ const result = mongoConverter.convert(sql);
39
+ equal(result.collection, "users");
40
+ equal(result.operation, "updateOne");
41
+ ok(result.update.$set);
42
+ });
43
+ });
44
+ describe("DELETE queries", () => {
45
+ test("should convert DELETE query", () => {
46
+ const sql = "DELETE FROM users WHERE id = 1";
47
+ const result = mongoConverter.convert(sql);
48
+ equal(result.collection, "users");
49
+ equal(result.operation, "deleteOne");
50
+ });
51
+ });
52
+ describe("Error handling", () => {
53
+ test("should throw on unsupported query type", () => {
54
+ const sql = "GRANT SELECT ON users TO john";
55
+ throws(() => mongoConverter.convert(sql), /Unsupported SQL statement/);
56
+ });
57
+ });
58
+ });
59
+ //# sourceMappingURL=MongoConverter.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MongoConverter.spec.js","sourceRoot":"","sources":["../../src/application/MongoConverter.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ /**
12
+ * CLI para convertir queries SQL a MongoDB
13
+ * Interfaz de línea de comandos usando Commander
14
+ */
15
+ import { Command } from "commander";
16
+ import chalk from "chalk";
17
+ import { mongoConverter } from "../application/MongoConverter.js";
18
+ const program = new Command();
19
+ program
20
+ .name("querymongo")
21
+ .description("Convert SQL queries to MongoDB format")
22
+ .version("1.0.0")
23
+ .usage("[command]");
24
+ program
25
+ .command("interactive")
26
+ .description("Start interactive mode")
27
+ .action(() => __awaiter(void 0, void 0, void 0, function* () {
28
+ const readline = yield import("readline");
29
+ const rl = readline.createInterface({
30
+ input: process.stdin,
31
+ output: process.stdout,
32
+ });
33
+ const question = (prompt) => {
34
+ return new Promise((resolve) => rl.question(prompt, resolve));
35
+ };
36
+ console.log(chalk.blue("\n📊 SQL to MongoDB Query Converter - Interactive Mode\n"));
37
+ console.log(chalk.gray('Type "exit" to quit\n'));
38
+ while (true) {
39
+ const sql = yield question(chalk.yellow("SQL Query > "));
40
+ if (sql.toLowerCase() === "exit") {
41
+ console.log(chalk.blue("Goodbye! 👋\n"));
42
+ rl.close();
43
+ break;
44
+ }
45
+ if (!sql.trim())
46
+ continue;
47
+ try {
48
+ const result = mongoConverter.convert(sql);
49
+ console.log(chalk.green("\n✓ MongoDB Query:\n"));
50
+ console.log(chalk.cyan(JSON.stringify(result, null, 2)) + "\n");
51
+ }
52
+ catch (error) {
53
+ console.error(chalk.red(`✗ Error: ${error instanceof Error ? error.message : "Unknown error"}\n`));
54
+ }
55
+ }
56
+ }))
57
+ .usage(" ");
58
+ program.parse(process.argv);
59
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";;;;;;;;;;AAEA;;;GAGG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAElE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,uCAAuC,CAAC;KACpD,OAAO,CAAC,OAAO,CAAC;KAChB,KAAK,CAAC,WAAW,CAAC,CAAC;AAEtB,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,wBAAwB,CAAC;KACrC,MAAM,CAAC,GAAS,EAAE;IACjB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;QAClC,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAmB,EAAE;QACnD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC;IAEF,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,0DAA0D,CAAC,CACvE,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAEjD,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;QAEzD,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;YACzC,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,MAAM;QACR,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;YAAE,SAAS;QAE1B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC;YACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAClE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CACP,YAAY,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,IAAI,CACzE,CACF,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC,CAAA,CAAC;KACD,KAAK,CAAC,GAAG,CAAC,CAAC;AAEd,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Converter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Converter.js","sourceRoot":"","sources":["../../../src/domain/interfaces/Converter.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * API pública del módulo
3
+ * Exporta las funcionalidades principales para uso como librería
4
+ */
5
+ export { MongoConverter, mongoConverter, } from "./application/MongoConverter.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,cAAc,EACd,cAAc,GACf,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { SelectConverter } from "./SelectConverter.js";
2
+ import { CreateConverter } from "./CreateConverter.js";
3
+ import { UpdateConverter } from "./UpdateConverter.js";
4
+ import { DeleteConverter } from "./DeleteConverter.js";
5
+ const CONVERTERS = [
6
+ SelectConverter,
7
+ CreateConverter,
8
+ UpdateConverter,
9
+ DeleteConverter,
10
+ ];
11
+ export const getConverter = (statement) => {
12
+ return CONVERTERS.find((converter) => converter.can(statement)) || null;
13
+ };
14
+ //# sourceMappingURL=ConverterFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConverterFactory.js","sourceRoot":"","sources":["../../../src/infrastructure/converters/ConverterFactory.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,UAAU,GAAiB;IAC/B,eAAe;IACf,eAAe;IACf,eAAe;IACf,eAAe;CAChB,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,SAAiB,EAAqB,EAAE;IACnE,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,IAAI,CAAC;AAC1E,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { removeUndefinedFields } from "../utils/queryUtils.js";
2
+ export const CreateConverter = {
3
+ can: (statement) => {
4
+ const lower = statement.toLowerCase();
5
+ return lower.startsWith("insert") || lower.startsWith("create");
6
+ },
7
+ convert: (query) => {
8
+ var _a;
9
+ const { ast } = query;
10
+ const { table, columns, values } = ast;
11
+ const collectionName = ((_a = table === null || table === void 0 ? void 0 : table[0]) === null || _a === void 0 ? void 0 : _a.table) || "collection";
12
+ const valuesList = values.values || [];
13
+ const docs = valuesList.map((v) => {
14
+ const row = v.value || v;
15
+ return Object.fromEntries(columns.map((col, idx) => { var _a; return [
16
+ col,
17
+ ((_a = row[idx]) === null || _a === void 0 ? void 0 : _a.value) || row[idx],
18
+ ]; }));
19
+ });
20
+ return removeUndefinedFields({
21
+ collection: collectionName,
22
+ operation: docs.length > 1 ? "insertMany" : "insertOne",
23
+ documents: docs.length === 1 ? docs[0] : docs,
24
+ });
25
+ },
26
+ };
27
+ //# sourceMappingURL=CreateConverter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreateConverter.js","sourceRoot":"","sources":["../../../src/infrastructure/converters/CreateConverter.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC,GAAG,EAAE,CAAC,SAAiB,EAAW,EAAE;QAClC,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,EAAE,CAAC,KAAU,EAAuB,EAAE;;QAC3C,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;QACtB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;QAEvC,MAAM,cAAc,GAAG,CAAA,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAG,CAAC,CAAC,0CAAE,KAAK,KAAI,YAAY,CAAC;QACzD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;QAEvC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE;YACrC,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;YACzB,OAAO,MAAM,CAAC,WAAW,CACvB,OAAO,CAAC,GAAG,CAAC,CAAC,GAAW,EAAE,GAAW,EAAE,EAAE,kBAAC;gBACxC,GAAG;gBACH,CAAA,MAAA,GAAG,CAAC,GAAG,CAAC,0CAAE,KAAK,KAAI,GAAG,CAAC,GAAG,CAAC;aAC5B,GAAA,CAAC,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,qBAAqB,CAAC;YAC3B,UAAU,EAAE,cAAc;YAC1B,SAAS,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW;YACvD,SAAS,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;SAC9C,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { buildFilter, determineOperation, removeUndefinedFields, } from "../utils/queryUtils.js";
2
+ export const DeleteConverter = {
3
+ can: (statement) => {
4
+ return statement.toLowerCase().startsWith("delete");
5
+ },
6
+ convert: (query) => {
7
+ var _a;
8
+ const { ast } = query;
9
+ const { from, where } = ast;
10
+ const collectionName = ((_a = from === null || from === void 0 ? void 0 : from[0]) === null || _a === void 0 ? void 0 : _a.table) || "collection";
11
+ return removeUndefinedFields({
12
+ collection: collectionName,
13
+ operation: determineOperation(where, {
14
+ one: "deleteOne",
15
+ many: "deleteMany",
16
+ }),
17
+ filter: where ? buildFilter(where) : {},
18
+ });
19
+ },
20
+ };
21
+ //# sourceMappingURL=DeleteConverter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeleteConverter.js","sourceRoot":"","sources":["../../../src/infrastructure/converters/DeleteConverter.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC,GAAG,EAAE,CAAC,SAAiB,EAAW,EAAE;QAClC,OAAO,SAAS,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,EAAE,CAAC,KAAU,EAAuB,EAAE;;QAC3C,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;QACtB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;QAE5B,MAAM,cAAc,GAAG,CAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAG,CAAC,CAAC,0CAAE,KAAK,KAAI,YAAY,CAAC;QAExD,OAAO,qBAAqB,CAAC;YAC3B,UAAU,EAAE,cAAc;YAC1B,SAAS,EAAE,kBAAkB,CAAC,KAAK,EAAE;gBACnC,GAAG,EAAE,WAAW;gBAChB,IAAI,EAAE,YAAY;aACnB,CAAC;YACF,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;SACxC,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { buildProjection, buildFilter, removeUndefinedFields, } from "../utils/queryUtils.js";
2
+ export const SelectConverter = {
3
+ can: (statement) => {
4
+ return statement.toLowerCase().startsWith("select");
5
+ },
6
+ convert: (query) => {
7
+ var _a, _b, _c, _d, _e;
8
+ const { ast } = query;
9
+ const { columns, from, where, limit } = ast;
10
+ const fields = columns && ((_b = (_a = columns[0]) === null || _a === void 0 ? void 0 : _a.expr) === null || _b === void 0 ? void 0 : _b.column) !== "*"
11
+ ? columns.map((col) => col.expr.column)
12
+ : "*";
13
+ const limitValue = ((_d = (_c = limit === null || limit === void 0 ? void 0 : limit.value) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.value) || (limit === null || limit === void 0 ? void 0 : limit.value) || limit;
14
+ return removeUndefinedFields({
15
+ collection: ((_e = from === null || from === void 0 ? void 0 : from[0]) === null || _e === void 0 ? void 0 : _e.table) || "collection",
16
+ pipeline: [
17
+ where && { $match: buildFilter(where) },
18
+ fields !== "*" && { $project: buildProjection(fields) },
19
+ limitValue && { $limit: limitValue },
20
+ ].filter(Boolean),
21
+ });
22
+ },
23
+ };
24
+ //# sourceMappingURL=SelectConverter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SelectConverter.js","sourceRoot":"","sources":["../../../src/infrastructure/converters/SelectConverter.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,eAAe,EACf,WAAW,EACX,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC,GAAG,EAAE,CAAC,SAAiB,EAAW,EAAE;QAClC,OAAO,SAAS,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,EAAE,CAAC,KAAU,EAAuB,EAAE;;QAC3C,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;QACtB,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;QAE5C,MAAM,MAAM,GACV,OAAO,IAAI,CAAA,MAAA,MAAA,OAAO,CAAC,CAAC,CAAC,0CAAE,IAAI,0CAAE,MAAM,MAAK,GAAG;YACzC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;YAC5C,CAAC,CAAC,GAAG,CAAC;QAEV,MAAM,UAAU,GAAG,CAAA,MAAA,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,KAAK,0CAAG,CAAC,CAAC,0CAAE,KAAK,MAAI,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,KAAK,CAAA,IAAI,KAAK,CAAC;QAErE,OAAO,qBAAqB,CAAC;YAC3B,UAAU,EAAE,CAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAG,CAAC,CAAC,0CAAE,KAAK,KAAI,YAAY;YAC5C,QAAQ,EAAE;gBACR,KAAK,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE;gBACvC,MAAM,KAAK,GAAG,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE;gBACvD,UAAU,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE;aACrC,CAAC,MAAM,CAAC,OAAO,CAAC;SAClB,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { buildFilter, determineOperation, removeUndefinedFields, } from "../utils/queryUtils.js";
2
+ export const UpdateConverter = {
3
+ can: (statement) => {
4
+ return statement.toLowerCase().startsWith("update");
5
+ },
6
+ convert: (query) => {
7
+ var _a;
8
+ const { ast } = query;
9
+ const { table, set, where } = ast;
10
+ const collectionName = ((_a = table === null || table === void 0 ? void 0 : table[0]) === null || _a === void 0 ? void 0 : _a.table) || "collection";
11
+ const updateData = Object.fromEntries(set.map((item) => { var _a; return [item.column, ((_a = item.value) === null || _a === void 0 ? void 0 : _a.value) || item.value]; }));
12
+ return removeUndefinedFields({
13
+ collection: collectionName,
14
+ operation: determineOperation(where, {
15
+ one: "updateOne",
16
+ many: "updateMany",
17
+ }),
18
+ filter: where ? buildFilter(where) : {},
19
+ update: { $set: updateData },
20
+ });
21
+ },
22
+ };
23
+ //# sourceMappingURL=UpdateConverter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UpdateConverter.js","sourceRoot":"","sources":["../../../src/infrastructure/converters/UpdateConverter.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC,GAAG,EAAE,CAAC,SAAiB,EAAW,EAAE;QAClC,OAAO,SAAS,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,EAAE,CAAC,KAAU,EAAuB,EAAE;;QAC3C,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;QACtB,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;QAElC,MAAM,cAAc,GAAG,CAAA,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAG,CAAC,CAAC,0CAAE,KAAK,KAAI,YAAY,CAAC;QACzD,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CACnC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,kBAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAA,MAAA,IAAI,CAAC,KAAK,0CAAE,KAAK,KAAI,IAAI,CAAC,KAAK,CAAC,GAAA,CAAC,CACvE,CAAC;QAEF,OAAO,qBAAqB,CAAC;YAC3B,UAAU,EAAE,cAAc;YAC1B,SAAS,EAAE,kBAAkB,CAAC,KAAK,EAAE;gBACnC,GAAG,EAAE,WAAW;gBAChB,IAAI,EAAE,YAAY;aACnB,CAAC;YACF,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;YACvC,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;SAC7B,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Parser SQL que encapsula node-sql-parser
3
+ * Abstrae la dependencia externa y proporciona una interfaz limpia
4
+ */
5
+ import sqlParser from "node-sql-parser";
6
+ const parser = new sqlParser.Parser();
7
+ export const parseSqlQuery = (sql) => {
8
+ return parser.parse(sql);
9
+ };
10
+ export const normalizeQuery = (query) => {
11
+ return query.trim().replace(/;$/, "").replace(/\s+/g, " ");
12
+ };
13
+ //# sourceMappingURL=sqlParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlParser.js","sourceRoot":"","sources":["../../../src/infrastructure/parser/sqlParser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,SAAS,MAAM,iBAAiB,CAAC;AAExC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;AAItC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAW,EAA+B,EAAE;IACxE,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAa,EAAU,EAAE;IACtD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC7D,CAAC,CAAC"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Utilidades para conversión de queries SQL a MongoDB
3
+ * Centraliza lógica reutilizable siguiendo principio DRY
4
+ */
5
+ import _ from "lodash";
6
+ export const removeUndefinedFields = (obj) => {
7
+ return _.omitBy(obj, _.isUndefined);
8
+ };
9
+ export const normalizeFieldName = (field) => {
10
+ return field.trim().replace(/`|"/g, "");
11
+ };
12
+ const normalizeFieldNames = (fields) => {
13
+ return fields.map(normalizeFieldName);
14
+ };
15
+ export const buildProjection = (fields) => {
16
+ if (fields === "*")
17
+ return {};
18
+ return Object.fromEntries(normalizeFieldNames(fields).map((f) => [f, 1]));
19
+ };
20
+ export const buildFilter = (condition) => {
21
+ if (!condition)
22
+ return {};
23
+ const { operator, left, right } = condition;
24
+ if (!operator)
25
+ return {};
26
+ if (operator.toUpperCase() === "AND") {
27
+ return {
28
+ $and: [buildFilter(left), buildFilter(right)],
29
+ };
30
+ }
31
+ if (operator.toUpperCase() === "OR") {
32
+ return {
33
+ $or: [buildFilter(left), buildFilter(right)],
34
+ };
35
+ }
36
+ const field = normalizeFieldName((left === null || left === void 0 ? void 0 : left.column) || (left === null || left === void 0 ? void 0 : left.value) || left || "");
37
+ const value = (right === null || right === void 0 ? void 0 : right.value) !== undefined ? right.value : right;
38
+ const operatorMap = {
39
+ "=": "$eq",
40
+ "!=": "$ne",
41
+ "<>": "$ne",
42
+ "<": "$lt",
43
+ ">": "$gt",
44
+ "<=": "$lte",
45
+ ">=": "$gte",
46
+ like: "$regex",
47
+ in: "$in",
48
+ "not in": "$nin",
49
+ };
50
+ const mongoOp = operatorMap[operator.toLowerCase()];
51
+ return mongoOp ? { [field]: { [mongoOp]: value } } : {};
52
+ };
53
+ export function determineOperation(where, operations) {
54
+ var _a;
55
+ const uniqueFields = ["id", "_id", "email", "username"];
56
+ const { operator, left } = where;
57
+ if (!where)
58
+ return operations.many;
59
+ if (["and", "or"].includes(operator === null || operator === void 0 ? void 0 : operator.toLowerCase())) {
60
+ return operations.many;
61
+ }
62
+ const field = (left === null || left === void 0 ? void 0 : left.column) || (left === null || left === void 0 ? void 0 : left.value) || left || "";
63
+ const isUniqueField = uniqueFields.includes((_a = field === null || field === void 0 ? void 0 : field.toLowerCase) === null || _a === void 0 ? void 0 : _a.call(field));
64
+ if (isUniqueField && operator === "=") {
65
+ return operations.one;
66
+ }
67
+ return [">", "<", ">=", "<=", "!=", "<>", "like", "in"].includes(operator === null || operator === void 0 ? void 0 : operator.toLowerCase())
68
+ ? operations.many
69
+ : operations.one;
70
+ }
71
+ //# sourceMappingURL=queryUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryUtils.js","sourceRoot":"","sources":["../../../src/infrastructure/utils/queryUtils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare class MongoConverter {
2
+ convert(sql: string): Record<string, any>;
3
+ }
4
+ export declare const mongoConverter: MongoConverter;
5
+ //# sourceMappingURL=MongoConverter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MongoConverter.d.ts","sourceRoot":"","sources":["../../../src/application/MongoConverter.ts"],"names":[],"mappings":"AAUA,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAcxC;CACF;AAED,eAAO,MAAM,cAAc,gBAAuB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=MongoConverter.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MongoConverter.spec.d.ts","sourceRoot":"","sources":["../../../src/application/MongoConverter.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/cli/main.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Interface para conversores de queries SQL a MongoDB
3
+ * Implementa Strategy Pattern para permitir diferentes estrategias de conversión
4
+ */
5
+ export interface IConverter {
6
+ can(statement: string): boolean;
7
+ convert(query: any): Record<string, any>;
8
+ }
9
+ //# sourceMappingURL=Converter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Converter.d.ts","sourceRoot":"","sources":["../../../../src/domain/interfaces/Converter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC1C"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * API pública del módulo
3
+ * Exporta las funcionalidades principales para uso como librería
4
+ */
5
+ export { MongoConverter, mongoConverter, } from "./application/MongoConverter.ts";
6
+ export type { IConverter } from "./domain/interfaces/Converter.ts";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,cAAc,EACd,cAAc,GACf,MAAM,iCAAiC,CAAC;AACzC,YAAY,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Factory que orquesta los conversores
3
+ * Implementa Strategy Pattern + Factory Pattern
4
+ * Centraliza la lógica de selección de conversor
5
+ */
6
+ import type { IConverter } from "../../domain/interfaces/Converter.ts";
7
+ export declare const getConverter: (statement: string) => IConverter | null;
8
+ //# sourceMappingURL=ConverterFactory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConverterFactory.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/converters/ConverterFactory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAavE,eAAO,MAAM,YAAY,cAAe,MAAM,KAAG,UAAU,GAAG,IAE7D,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Conversor para queries CREATE/INSERT
3
+ * Convierte CREATE/INSERT SQL a insertOne/insertMany de MongoDB
4
+ */
5
+ import type { IConverter } from "../../domain/interfaces/Converter.ts";
6
+ export declare const CreateConverter: IConverter;
7
+ //# sourceMappingURL=CreateConverter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreateConverter.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/converters/CreateConverter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAGvE,eAAO,MAAM,eAAe,EAAE,UA6B7B,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Conversor para queries DELETE
3
+ * Convierte DELETE SQL a deleteOne/deleteMany de MongoDB
4
+ */
5
+ import type { IConverter } from "../../domain/interfaces/Converter.ts";
6
+ export declare const DeleteConverter: IConverter;
7
+ //# sourceMappingURL=DeleteConverter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeleteConverter.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/converters/DeleteConverter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAOvE,eAAO,MAAM,eAAe,EAAE,UAoB7B,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Conversor para queries SELECT
3
+ * Convierte SELECT SQL a aggregation pipeline o find query de MongoDB
4
+ */
5
+ import type { IConverter } from "../../domain/interfaces/Converter.ts";
6
+ export declare const SelectConverter: IConverter;
7
+ //# sourceMappingURL=SelectConverter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SelectConverter.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/converters/SelectConverter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAOvE,eAAO,MAAM,eAAe,EAAE,UAyB7B,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Conversor para queries UPDATE
3
+ * Convierte UPDATE SQL a updateOne/updateMany de MongoDB
4
+ */
5
+ import type { IConverter } from "../../domain/interfaces/Converter.ts";
6
+ export declare const UpdateConverter: IConverter;
7
+ //# sourceMappingURL=UpdateConverter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UpdateConverter.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/converters/UpdateConverter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAOvE,eAAO,MAAM,eAAe,EAAE,UAwB7B,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Parser SQL que encapsula node-sql-parser
3
+ * Abstrae la dependencia externa y proporciona una interfaz limpia
4
+ */
5
+ import sqlParser from "node-sql-parser";
6
+ declare const parser: sqlParser.Parser;
7
+ export type ParsedQuery = ReturnType<typeof parser.parse>;
8
+ export declare const parseSqlQuery: (sql: string) => ParsedQuery | ParsedQuery[];
9
+ export declare const normalizeQuery: (query: string) => string;
10
+ export {};
11
+ //# sourceMappingURL=sqlParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlParser.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/parser/sqlParser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,SAAS,MAAM,iBAAiB,CAAC;AAExC,QAAA,MAAM,MAAM,kBAAyB,CAAC;AAEtC,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AAE1D,eAAO,MAAM,aAAa,QAAS,MAAM,KAAG,WAAW,GAAG,WAAW,EAEpE,CAAC;AAEF,eAAO,MAAM,cAAc,UAAW,MAAM,KAAG,MAE9C,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare const removeUndefinedFields: (obj: Record<string, any>) => Record<string, any>;
2
+ export declare const normalizeFieldName: (field: string) => string;
3
+ export declare const buildProjection: (fields: string[] | "*") => Record<string, 1 | 0>;
4
+ export declare const buildFilter: (condition: any) => Record<string, any>;
5
+ export declare function determineOperation(where: any, operations: {
6
+ one: string;
7
+ many: string;
8
+ }): string;
9
+ //# sourceMappingURL=queryUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryUtils.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/utils/queryUtils.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,qBAAqB,QAC3B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KACvB,MAAM,CAAC,MAAM,EAAE,GAAG,CAEpB,CAAC;AAEF,eAAO,MAAM,kBAAkB,UAAW,MAAM,KAAG,MAElD,CAAC;AAMF,eAAO,MAAM,eAAe,WAClB,MAAM,EAAE,GAAG,GAAG,KACrB,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAGtB,CAAC;AAEF,eAAO,MAAM,WAAW,cAAe,GAAG,KAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAsC9D,CAAC;AAEF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,GAAG,EACV,UAAU,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxC,MAAM,CAsBR"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "querymongo",
3
+ "type": "module",
4
+ "version": "1.0.0",
5
+ "description": "SQL to MongoDB Query Converter CLI",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "querymongo": "dist/cli/main.js"
9
+ },
10
+ "scripts": {
11
+ "clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",
12
+ "build": "npm run clean && tsc",
13
+ "start": "npm run build && node dist/cli/main.js",
14
+ "dev": "tsx src/cli/main.ts",
15
+ "test": "node --experimental-strip-types --experimental-test-coverage --test \"**/*.{spec,integration}.ts\"",
16
+ "format": "npx prettier --write ."
17
+ },
18
+ "keywords": [
19
+ "sql",
20
+ "mongodb",
21
+ "converter",
22
+ "query"
23
+ ],
24
+ "files": [
25
+ "dist",
26
+ "package.json"
27
+ ],
28
+ "repository": {
29
+ "url": "https://github.com/rubsuadav/querymongo",
30
+ "type": "git"
31
+ },
32
+ "homepage": "https://github.com/rubsuadav/querymongo",
33
+ "author": "rubsuadav",
34
+ "license": "ISC",
35
+ "engines": {
36
+ "node": "22.14.0",
37
+ "npm": "10.9.2"
38
+ },
39
+ "dependencies": {
40
+ "chalk": "^6.0.0",
41
+ "commander": "^15.0.0",
42
+ "lodash": "^4.18.1",
43
+ "node-sql-parser": "^5.4.0"
44
+ },
45
+ "devDependencies": {
46
+ "@semantic-release/changelog": "^6.0.3",
47
+ "@semantic-release/git": "^10.0.1",
48
+ "@semantic-release/github": "^12.0.9",
49
+ "@semantic-release/npm": "^13.1.5",
50
+ "@types/lodash": "^4.17.25",
51
+ "@types/node": "^26.6.2",
52
+ "tsx": "^4.23.15",
53
+ "typescript": "^7.0.2"
54
+ }
55
+ }