@gzl10/osx-cli 4.0.6 → 4.0.9

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.
@@ -47,14 +47,47 @@ var OracleService = class {
47
47
  connection = null;
48
48
  /**
49
49
  * Conecta a Oracle usando TNS
50
+ * Maneja errores ORA-XXXXX con mensajes descriptivos
50
51
  */
51
52
  async connect(config) {
53
+ if (!process.env.NLS_LANG) {
54
+ process.env.NLS_LANG = "SPANISH_SPAIN.AL32UTF8";
55
+ }
52
56
  initThickMode();
53
- this.connection = await oracledb.getConnection({
54
- user: config.user,
55
- password: config.password,
56
- connectString: config.tns
57
- });
57
+ try {
58
+ this.connection = await oracledb.getConnection({
59
+ user: config.user,
60
+ password: config.password,
61
+ connectString: config.tns
62
+ });
63
+ } catch (err) {
64
+ const oraError = err;
65
+ const code = oraError.errorNum;
66
+ switch (code) {
67
+ case 12154:
68
+ throw new Error(
69
+ `TNS inv\xE1lido: No se pudo resolver '${config.tns}'. Verifica tnsnames.ora o usa formato host:puerto/servicio`
70
+ );
71
+ case 1017:
72
+ throw new Error(`Credenciales inv\xE1lidas para usuario '${config.user}'`);
73
+ case 12170:
74
+ throw new Error(
75
+ `Timeout de conexi\xF3n a '${config.tns}'. Verifica red/firewall`
76
+ );
77
+ case 28040:
78
+ throw new Error(
79
+ `Protocolo de autenticaci\xF3n incompatible. Verifica versi\xF3n de Oracle Instant Client`
80
+ );
81
+ case 12541:
82
+ throw new Error(
83
+ `No hay listener en '${config.tns}'. Verifica que el servicio Oracle est\xE9 activo`
84
+ );
85
+ default:
86
+ throw new Error(
87
+ `Error de conexi\xF3n Oracle: ${oraError.message || String(err)}`
88
+ );
89
+ }
90
+ }
58
91
  }
59
92
  /**
60
93
  * Ejecuta una query con parámetros nombrados
@@ -116,16 +149,56 @@ var TABLE_COLUMNS = `
116
149
  ORDER BY COLS.COLUMN_ID
117
150
  `;
118
151
  var TABLE_CHILDREN = `
119
- SELECT DISTINCT ac_child.table_name AS "child_table"
120
- FROM ALL_CONSTRAINTS ac_parent
121
- JOIN ALL_CONSTRAINTS ac_child
122
- ON ac_parent.constraint_name = ac_child.r_constraint_name
123
- AND ac_parent.owner = ac_child.r_owner
124
- WHERE ac_parent.owner = :schema
125
- AND ac_parent.table_name = :tableName
126
- AND ac_parent.constraint_type = 'P'
127
- AND ac_child.constraint_type = 'R'
128
- AND ac_child.status = 'ENABLED'
152
+ WITH FK_RELATIONS AS (
153
+ SELECT
154
+ ac_child.owner AS child_owner,
155
+ ac_child.table_name AS child_table,
156
+ acc_child.column_name AS child_column,
157
+ acc_parent.column_name AS parent_column,
158
+ acc_child.position
159
+ FROM ALL_CONSTRAINTS ac_parent
160
+ JOIN ALL_CONSTRAINTS ac_child
161
+ ON ac_parent.constraint_name = ac_child.r_constraint_name
162
+ AND ac_parent.owner = ac_child.r_owner
163
+ JOIN ALL_CONS_COLUMNS acc_child
164
+ ON ac_child.constraint_name = acc_child.constraint_name
165
+ AND ac_child.owner = acc_child.owner
166
+ JOIN ALL_CONS_COLUMNS acc_parent
167
+ ON ac_parent.constraint_name = acc_parent.constraint_name
168
+ AND ac_parent.owner = acc_parent.owner
169
+ AND acc_child.position = acc_parent.position
170
+ WHERE ac_parent.owner = :schema
171
+ AND ac_parent.table_name = :tableName
172
+ AND ac_parent.constraint_type = 'P'
173
+ AND ac_child.constraint_type = 'R'
174
+ AND ac_child.status = 'ENABLED'
175
+ ),
176
+ UNIQUE_COLS AS (
177
+ SELECT DISTINCT
178
+ uc.owner,
179
+ uc.table_name,
180
+ ucc.column_name
181
+ FROM ALL_CONSTRAINTS uc
182
+ JOIN ALL_CONS_COLUMNS ucc
183
+ ON uc.constraint_name = ucc.constraint_name
184
+ AND uc.owner = ucc.owner
185
+ WHERE uc.constraint_type IN ('P', 'U')
186
+ AND (uc.owner, uc.table_name) IN (
187
+ SELECT DISTINCT child_owner, child_table FROM FK_RELATIONS
188
+ )
189
+ )
190
+ SELECT
191
+ fk.child_table AS "child_table",
192
+ fk.child_column AS "child_column",
193
+ fk.parent_column AS "parent_column",
194
+ fk.position AS "position",
195
+ CASE WHEN uc.column_name IS NOT NULL THEN '1:1' ELSE '1:N' END AS "cardinality"
196
+ FROM FK_RELATIONS fk
197
+ LEFT JOIN UNIQUE_COLS uc
198
+ ON uc.owner = fk.child_owner
199
+ AND uc.table_name = fk.child_table
200
+ AND uc.column_name = fk.child_column
201
+ ORDER BY fk.child_table, fk.position
129
202
  `;
130
203
  var TABLE_STATS = `
131
204
  SELECT NUM_ROWS as "count", LAST_ANALYZED as "last_update"
@@ -185,6 +258,23 @@ var SchemaExtractor = class {
185
258
  schema,
186
259
  tableName
187
260
  });
261
+ const childrenMap = /* @__PURE__ */ new Map();
262
+ for (const row of childrenRows) {
263
+ let relation = childrenMap.get(row.child_table);
264
+ if (!relation) {
265
+ relation = {
266
+ table: row.child_table,
267
+ cardinality: row.cardinality,
268
+ columns: []
269
+ };
270
+ childrenMap.set(row.child_table, relation);
271
+ }
272
+ relation.columns.push({
273
+ child: row.child_column,
274
+ parent: row.parent_column
275
+ });
276
+ }
277
+ const children = Array.from(childrenMap.values());
188
278
  const [statsRow] = await this.oracle.query(TABLE_STATS, {
189
279
  schema,
190
280
  tableName
@@ -197,7 +287,7 @@ var SchemaExtractor = class {
197
287
  name: tableName,
198
288
  comment: commentRow?.COMMENTS || "",
199
289
  columns,
200
- children: childrenRows.map((r) => r.child_table),
290
+ children,
201
291
  count: statsRow?.count ?? 0,
202
292
  lastUpdate: statsRow?.last_update?.toISOString() ?? null,
203
293
  examples
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  OracleService,
4
4
  SchemaExtractor
5
- } from "./chunk-XHMPD7KT.js";
5
+ } from "./chunk-7QQUO4HK.js";
6
6
 
7
7
  // src/cli.ts
8
8
  import { readFileSync as readFileSync2 } from "fs";
package/dist/index.d.ts CHANGED
@@ -10,6 +10,17 @@ interface OracleColumn {
10
10
  nullable: 'Y' | 'N';
11
11
  is_pk: 'Y' | 'N';
12
12
  }
13
+ /**
14
+ * Representa una relación FK con una tabla hija
15
+ */
16
+ interface ChildRelation {
17
+ table: string;
18
+ cardinality: '1:1' | '1:N';
19
+ columns: Array<{
20
+ child: string;
21
+ parent: string;
22
+ }>;
23
+ }
13
24
  /**
14
25
  * Esquema de tabla compatible con Atlas OriginType=BBDD
15
26
  */
@@ -19,7 +30,7 @@ interface TableSchema {
19
30
  name: string;
20
31
  comment: string;
21
32
  columns: OracleColumn[];
22
- children: string[];
33
+ children: ChildRelation[];
23
34
  count: number;
24
35
  lastUpdate: string | null;
25
36
  examples: Record<string, unknown>[];
@@ -52,6 +63,7 @@ declare class OracleService {
52
63
  private connection;
53
64
  /**
54
65
  * Conecta a Oracle usando TNS
66
+ * Maneja errores ORA-XXXXX con mensajes descriptivos
55
67
  */
56
68
  connect(config: OracleConfig): Promise<void>;
57
69
  /**
@@ -97,7 +109,10 @@ declare const TABLE_COMMENT = "\n SELECT comments\n FROM ALL_TAB_COMMENTS\n W
97
109
  declare const TABLE_COLUMNS = "\n WITH PK_COLUMNS AS (\n SELECT acc.COLUMN_NAME\n FROM ALL_CONSTRAINTS ac\n JOIN ALL_CONS_COLUMNS acc\n ON ac.CONSTRAINT_NAME = acc.CONSTRAINT_NAME\n AND ac.OWNER = acc.OWNER\n WHERE ac.CONSTRAINT_TYPE = 'P'\n AND ac.OWNER = :schema\n AND ac.TABLE_NAME = :tableName\n )\n SELECT\n COLS.COLUMN_NAME as \"column_name\",\n DESCRIP.COMMENTS as \"comment\",\n COLS.DATA_TYPE as \"data_type\",\n COLS.DATA_LENGTH as \"data_length\",\n COLS.DATA_PRECISION as \"data_precision\",\n COLS.NULLABLE as \"nullable\",\n CASE WHEN PK.COLUMN_NAME IS NOT NULL THEN 'Y' ELSE 'N' END AS \"is_pk\"\n FROM ALL_TAB_COLUMNS COLS\n JOIN ALL_COL_COMMENTS DESCRIP\n ON DESCRIP.OWNER = COLS.OWNER\n AND DESCRIP.TABLE_NAME = COLS.TABLE_NAME\n AND DESCRIP.COLUMN_NAME = COLS.COLUMN_NAME\n LEFT JOIN PK_COLUMNS PK ON PK.COLUMN_NAME = COLS.COLUMN_NAME\n WHERE COLS.OWNER = :schema AND COLS.TABLE_NAME = :tableName\n ORDER BY COLS.COLUMN_ID\n";
98
110
  /**
99
111
  * Query para obtener las tablas hijas (que tienen FK hacia esta tabla)
112
+ * Incluye: columnas de la relación y cardinalidad inferida (1:1 si FK tiene UNIQUE/PK)
113
+ *
114
+ * Usa CTEs para evaluar UNIQUE_COLS una sola vez (evita EXISTS anidado por fila)
100
115
  */
101
- declare const TABLE_CHILDREN = "\n SELECT DISTINCT ac_child.table_name AS \"child_table\"\n FROM ALL_CONSTRAINTS ac_parent\n JOIN ALL_CONSTRAINTS ac_child\n ON ac_parent.constraint_name = ac_child.r_constraint_name\n AND ac_parent.owner = ac_child.r_owner\n WHERE ac_parent.owner = :schema\n AND ac_parent.table_name = :tableName\n AND ac_parent.constraint_type = 'P'\n AND ac_child.constraint_type = 'R'\n AND ac_child.status = 'ENABLED'\n";
116
+ declare const TABLE_CHILDREN = "\n WITH FK_RELATIONS AS (\n SELECT\n ac_child.owner AS child_owner,\n ac_child.table_name AS child_table,\n acc_child.column_name AS child_column,\n acc_parent.column_name AS parent_column,\n acc_child.position\n FROM ALL_CONSTRAINTS ac_parent\n JOIN ALL_CONSTRAINTS ac_child\n ON ac_parent.constraint_name = ac_child.r_constraint_name\n AND ac_parent.owner = ac_child.r_owner\n JOIN ALL_CONS_COLUMNS acc_child\n ON ac_child.constraint_name = acc_child.constraint_name\n AND ac_child.owner = acc_child.owner\n JOIN ALL_CONS_COLUMNS acc_parent\n ON ac_parent.constraint_name = acc_parent.constraint_name\n AND ac_parent.owner = acc_parent.owner\n AND acc_child.position = acc_parent.position\n WHERE ac_parent.owner = :schema\n AND ac_parent.table_name = :tableName\n AND ac_parent.constraint_type = 'P'\n AND ac_child.constraint_type = 'R'\n AND ac_child.status = 'ENABLED'\n ),\n UNIQUE_COLS AS (\n SELECT DISTINCT\n uc.owner,\n uc.table_name,\n ucc.column_name\n FROM ALL_CONSTRAINTS uc\n JOIN ALL_CONS_COLUMNS ucc\n ON uc.constraint_name = ucc.constraint_name\n AND uc.owner = ucc.owner\n WHERE uc.constraint_type IN ('P', 'U')\n AND (uc.owner, uc.table_name) IN (\n SELECT DISTINCT child_owner, child_table FROM FK_RELATIONS\n )\n )\n SELECT\n fk.child_table AS \"child_table\",\n fk.child_column AS \"child_column\",\n fk.parent_column AS \"parent_column\",\n fk.position AS \"position\",\n CASE WHEN uc.column_name IS NOT NULL THEN '1:1' ELSE '1:N' END AS \"cardinality\"\n FROM FK_RELATIONS fk\n LEFT JOIN UNIQUE_COLS uc\n ON uc.owner = fk.child_owner\n AND uc.table_name = fk.child_table\n AND uc.column_name = fk.child_column\n ORDER BY fk.child_table, fk.position\n";
102
117
 
103
118
  export { type ExtractOptions, type OracleColumn, type OracleConfig, OracleService, SchemaExtractor, TABLE_CHILDREN, TABLE_COLUMNS, TABLE_COMMENT, type TableSchema };
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  TABLE_CHILDREN,
5
5
  TABLE_COLUMNS,
6
6
  TABLE_COMMENT
7
- } from "./chunk-XHMPD7KT.js";
7
+ } from "./chunk-7QQUO4HK.js";
8
8
  export {
9
9
  OracleService,
10
10
  SchemaExtractor,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gzl10/osx-cli",
3
- "version": "4.0.6",
3
+ "version": "4.0.9",
4
4
  "description": "Oracle Schema Extractor CLI - Genera JSON compatible con Atlas OriginType=BBDD",
5
5
  "type": "module",
6
6
  "bin": {