@dbml/connector 3.7.2

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.
@@ -0,0 +1,414 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchSchemaJson = void 0;
4
+ /* eslint-disable camelcase */
5
+ const pg_1 = require("pg");
6
+ const getValidatedClient = async (connection) => {
7
+ const client = new pg_1.Client(connection);
8
+ try {
9
+ // Connect to the PostgreSQL server
10
+ await client.connect();
11
+ // Validate if the connection is successful by making a simple query
12
+ await client.query('SELECT 1');
13
+ // If successful, return the client
14
+ return client;
15
+ }
16
+ catch (err) {
17
+ // Ensure to close the client in case of failure
18
+ await client.end();
19
+ if (err instanceof Error) {
20
+ throw new Error(`PostgreSQL connection error: ${err}`);
21
+ }
22
+ throw err; // Rethrow error if you want the calling code to handle it
23
+ }
24
+ };
25
+ const convertQueryBoolean = (val) => val === 'YES';
26
+ const getFieldType = (data_type, udt_name, character_maximum_length, numeric_precision, numeric_scale) => {
27
+ if (data_type === 'ARRAY') {
28
+ return `${udt_name.slice(1, udt_name.length)}[]`;
29
+ }
30
+ if (character_maximum_length) {
31
+ return `${udt_name}(${character_maximum_length})`;
32
+ }
33
+ if (numeric_precision && numeric_scale) {
34
+ return `${udt_name}(${numeric_precision},${numeric_scale})`;
35
+ }
36
+ return udt_name;
37
+ };
38
+ const getDbdefault = (data_type, column_default, default_type) => {
39
+ if (data_type === 'ARRAY') {
40
+ const values = column_default.slice(6, -1).split(',').map((value) => {
41
+ return value.split('::')[0];
42
+ });
43
+ return {
44
+ type: default_type,
45
+ value: `ARRAY[${values.join(', ')}]`,
46
+ };
47
+ }
48
+ if (default_type === 'string') {
49
+ const defaultValues = column_default.split('::')[0];
50
+ const isJson = data_type === 'json' || data_type === 'jsonb';
51
+ const type = isJson ? 'expression' : 'string';
52
+ return {
53
+ type,
54
+ value: defaultValues.slice(1, -1),
55
+ };
56
+ }
57
+ return {
58
+ type: default_type,
59
+ value: column_default,
60
+ };
61
+ };
62
+ const generateField = (row) => {
63
+ const { column_name, data_type, character_maximum_length, numeric_precision, numeric_scale, udt_schema, udt_name, identity_increment, is_nullable, column_default, default_type, column_comment, } = row;
64
+ const dbdefault = column_default && default_type !== 'increment' ? getDbdefault(data_type, column_default, default_type) : null;
65
+ const fieldType = data_type === 'USER-DEFINED' ? {
66
+ type_name: udt_name,
67
+ schemaName: udt_schema,
68
+ } : {
69
+ type_name: getFieldType(data_type, udt_name, character_maximum_length, numeric_precision, numeric_scale),
70
+ schemaName: null,
71
+ };
72
+ return {
73
+ name: column_name,
74
+ type: fieldType,
75
+ dbdefault,
76
+ not_null: !convertQueryBoolean(is_nullable),
77
+ increment: !!identity_increment || default_type === 'increment',
78
+ note: column_comment ? { value: column_comment } : { value: '' },
79
+ };
80
+ };
81
+ const generateTablesAndFields = async (client) => {
82
+ const fields = {};
83
+ const tablesAndFieldsSql = `
84
+ WITH comments AS (
85
+ SELECT
86
+ pc.relname AS table_name,
87
+ pn.nspname AS table_schema,
88
+ pa.attname AS column_name,
89
+ pd.description
90
+ FROM
91
+ pg_description pd
92
+ JOIN
93
+ pg_class pc ON pd.objoid = pc.oid
94
+ JOIN
95
+ pg_namespace pn ON pc.relnamespace = pn.oid
96
+ LEFT JOIN
97
+ pg_attribute pa ON pd.objoid = pa.attrelid AND pd.objsubid = pa.attnum
98
+ WHERE
99
+ pc.relkind = 'r'
100
+ AND pn.nspname NOT IN ('pg_catalog', 'information_schema')
101
+ )
102
+ SELECT
103
+ t.table_schema,
104
+ t.table_name,
105
+ c.column_name,
106
+ c.data_type,
107
+ c.character_maximum_length,
108
+ c.numeric_precision,
109
+ c.numeric_scale,
110
+ c.udt_schema,
111
+ c.udt_name,
112
+ c.identity_increment,
113
+ c.is_nullable,
114
+ c.column_default,
115
+ CASE
116
+ WHEN c.column_default IS NULL THEN NULL
117
+ WHEN c.column_default LIKE 'nextval(%' THEN 'increment'
118
+ WHEN c.column_default LIKE '''%' THEN 'string'
119
+ WHEN c.column_default = 'true' OR c.column_default = 'false' THEN 'boolean'
120
+ WHEN c.column_default ~ '^-?[0-9]+(.[0-9]+)?$' THEN 'number'
121
+ ELSE 'expression'
122
+ END AS default_type,
123
+ (SELECT description FROM comments WHERE table_name = t.table_name AND table_schema = t.table_schema AND column_name IS NULL) AS table_comment,
124
+ (SELECT description FROM comments WHERE table_name = t.table_name AND table_schema = t.table_schema AND column_name = c.column_name) AS column_comment
125
+ FROM
126
+ information_schema.columns c
127
+ JOIN
128
+ information_schema.tables t ON c.table_name = t.table_name AND c.table_schema = t.table_schema
129
+ WHERE
130
+ t.table_type = 'BASE TABLE'
131
+ AND t.table_schema NOT IN ('pg_catalog', 'information_schema')
132
+ ORDER BY
133
+ t.table_schema,
134
+ t.table_name,
135
+ c.ordinal_position
136
+ ;
137
+ `;
138
+ const tablesAndFieldsResult = await client.query(tablesAndFieldsSql);
139
+ const tables = tablesAndFieldsResult.rows.reduce((acc, row) => {
140
+ const { table_schema, table_name, table_comment } = row;
141
+ const key = `${table_schema}.${table_name}`;
142
+ if (!acc[key]) {
143
+ acc[key] = {
144
+ name: table_name,
145
+ schemaName: table_schema,
146
+ note: table_comment ? { value: table_comment } : { value: '' },
147
+ };
148
+ }
149
+ if (!fields[key])
150
+ fields[key] = [];
151
+ const field = generateField(row);
152
+ fields[key].push(field);
153
+ return acc;
154
+ }, {});
155
+ return {
156
+ tables: Object.values(tables),
157
+ fields,
158
+ };
159
+ };
160
+ const generateRawRefs = async (client) => {
161
+ const refs = [];
162
+ const refsListSql = `
163
+ SELECT
164
+ tc.table_schema,
165
+ tc.table_name,
166
+ tc.constraint_name as fk_constraint_name,
167
+ STRING_AGG(DISTINCT kcu.column_name, ',') AS column_names,
168
+ ccu.table_schema AS foreign_table_schema,
169
+ ccu.table_name AS foreign_table_name,
170
+ STRING_AGG(DISTINCT ccu.column_name, ',') AS foreign_column_names,
171
+ tc.constraint_type,
172
+ rc.delete_rule AS on_delete,
173
+ rc.update_rule AS on_update
174
+ FROM information_schema.table_constraints AS tc
175
+ JOIN information_schema.key_column_usage AS kcu
176
+ ON tc.constraint_name = kcu.constraint_name
177
+ AND tc.table_schema = kcu.table_schema
178
+ JOIN information_schema.constraint_column_usage AS ccu
179
+ ON ccu.constraint_name = tc.constraint_name
180
+ JOIN information_schema.referential_constraints AS rc
181
+ ON tc.constraint_name = rc.constraint_name
182
+ AND tc.table_schema = rc.constraint_schema
183
+ WHERE tc.constraint_type = 'FOREIGN KEY'
184
+ AND tc.table_schema NOT IN ('pg_catalog', 'information_schema')
185
+ GROUP BY
186
+ tc.table_schema,
187
+ tc.table_name,
188
+ tc.constraint_name,
189
+ ccu.table_schema,
190
+ ccu.table_name,
191
+ tc.constraint_type,
192
+ rc.delete_rule,
193
+ rc.update_rule
194
+ ORDER BY
195
+ tc.table_schema,
196
+ tc.table_name;
197
+ `;
198
+ const refsQueryResult = await client.query(refsListSql);
199
+ refsQueryResult.rows.forEach((refRow) => {
200
+ const { table_schema, fk_constraint_name, table_name, column_names, foreign_table_schema, foreign_table_name, foreign_column_names, on_delete, on_update, } = refRow;
201
+ const ep1 = {
202
+ tableName: table_name,
203
+ schemaName: table_schema,
204
+ fieldNames: column_names.split(','),
205
+ relation: '*',
206
+ };
207
+ const ep2 = {
208
+ tableName: foreign_table_name,
209
+ schemaName: foreign_table_schema,
210
+ fieldNames: foreign_column_names.split(','),
211
+ relation: '1',
212
+ };
213
+ refs.push({
214
+ name: fk_constraint_name,
215
+ endpoints: [ep1, ep2],
216
+ onDelete: on_delete === 'NO ACTION' ? null : on_delete,
217
+ onUpdate: on_update === 'NO ACTION' ? null : on_update,
218
+ });
219
+ });
220
+ return refs;
221
+ };
222
+ const generateIndexes = async (client) => {
223
+ // const tableConstraints = {};
224
+ const indexListSql = `
225
+ WITH user_tables AS (
226
+ SELECT
227
+ schemaname AS tableschema,
228
+ tablename
229
+ FROM pg_tables
230
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema') -- Exclude system schemas
231
+ AND tablename NOT LIKE 'pg_%' -- Exclude PostgreSQL system tables
232
+ AND tablename NOT LIKE 'sql_%' -- Exclude SQL standard tables
233
+ ),
234
+ index_info AS (
235
+ SELECT
236
+ t.relname AS table_name,
237
+ i.relname AS index_name,
238
+ ix.indisunique AS is_unique,
239
+ ix.indisprimary AS is_primary,
240
+ am.amname AS index_type,
241
+ array_to_string(array_agg(a.attname ORDER BY x.n), ', ') AS columns,
242
+ pg_get_expr(ix.indexprs, ix.indrelid) AS expressions,
243
+ CASE
244
+ WHEN ix.indisprimary THEN 'PRIMARY KEY'
245
+ WHEN ix.indisunique THEN 'UNIQUE'
246
+ ELSE NULL
247
+ END AS constraint_type
248
+ FROM
249
+ pg_class t
250
+ JOIN pg_index ix ON t.oid = ix.indrelid
251
+ JOIN pg_class i ON i.oid = ix.indexrelid
252
+ LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)
253
+ JOIN pg_am am ON i.relam = am.oid
254
+ LEFT JOIN generate_subscripts(ix.indkey, 1) AS x(n) ON a.attnum = ix.indkey[x.n]
255
+ WHERE
256
+ t.relkind = 'r'
257
+ AND t.relname NOT LIKE 'pg_%'
258
+ AND t.relname NOT LIKE 'sql_%'
259
+ GROUP BY
260
+ t.relname, i.relname, ix.indisunique, ix.indisprimary, am.amname, ix.indexprs, ix.indrelid
261
+ )
262
+ SELECT
263
+ ut.tableschema AS table_schema,
264
+ ut.tablename AS table_name,
265
+ ii.index_name,
266
+ ii.is_unique,
267
+ ii.is_primary,
268
+ ii.index_type,
269
+ ii.columns,
270
+ ii.expressions,
271
+ ii.constraint_type -- Added constraint type
272
+ FROM
273
+ user_tables ut
274
+ LEFT JOIN
275
+ index_info ii ON ut.tablename = ii.table_name
276
+ WHERE ii.columns IS NOT NULL
277
+ ORDER BY
278
+ ut.tablename,
279
+ ii.constraint_type,
280
+ ii.index_name
281
+ ;
282
+ `;
283
+ const indexListResult = await client.query(indexListSql);
284
+ const { outOfLineConstraints, inlineConstraints } = indexListResult.rows.reduce((acc, row) => {
285
+ const { constraint_type, columns } = row;
286
+ if (columns === 'null' || columns.trim() === '')
287
+ return acc;
288
+ const isSingleColumn = columns.split(',').length === 1;
289
+ const isInlineConstraint = isSingleColumn && (constraint_type === 'PRIMARY KEY' || constraint_type === 'UNIQUE');
290
+ if (isInlineConstraint) {
291
+ acc.inlineConstraints.push(row);
292
+ }
293
+ else {
294
+ acc.outOfLineConstraints.push(row);
295
+ }
296
+ return acc;
297
+ }, { outOfLineConstraints: [], inlineConstraints: [] });
298
+ const indexes = outOfLineConstraints.reduce((acc, indexRow) => {
299
+ const { table_schema, table_name, index_name, index_type, columns, expressions, } = indexRow;
300
+ const indexColumns = columns.split(',').map((column) => {
301
+ return {
302
+ type: 'column',
303
+ value: column.trim(),
304
+ };
305
+ });
306
+ const indexExpressions = expressions ? expressions.split(',').map((expression) => {
307
+ return {
308
+ type: 'expression',
309
+ value: expression,
310
+ };
311
+ }) : [];
312
+ const index = {
313
+ name: index_name,
314
+ type: index_type,
315
+ columns: [
316
+ ...indexColumns,
317
+ ...indexExpressions,
318
+ ],
319
+ };
320
+ const key = `${table_schema}.${table_name}`;
321
+ if (acc[key]) {
322
+ acc[key].push(index);
323
+ }
324
+ else {
325
+ acc[key] = [index];
326
+ }
327
+ return acc;
328
+ }, {});
329
+ const tableConstraints = inlineConstraints.reduce((acc, row) => {
330
+ const { table_schema, table_name, columns, constraint_type, } = row;
331
+ const key = `${table_schema}.${table_name}`;
332
+ if (!acc[key])
333
+ acc[key] = {};
334
+ const columnNames = columns.split(',').map((column) => column.trim());
335
+ columnNames.forEach((columnName) => {
336
+ if (!acc[key][columnName])
337
+ acc[key][columnName] = {};
338
+ if (constraint_type === 'PRIMARY KEY') {
339
+ acc[key][columnName].pk = true;
340
+ }
341
+ if (constraint_type === 'UNIQUE' && !acc[key][columnName].pk) {
342
+ acc[key][columnName].unique = true;
343
+ }
344
+ });
345
+ return acc;
346
+ }, {});
347
+ return {
348
+ indexes,
349
+ tableConstraints,
350
+ };
351
+ };
352
+ const generateRawEnums = async (client) => {
353
+ const enumListSql = `
354
+ SELECT
355
+ n.nspname AS schema_name,
356
+ t.typname AS enum_type,
357
+ e.enumlabel AS enum_value,
358
+ e.enumsortorder AS sort_order
359
+ FROM
360
+ pg_enum e
361
+ JOIN
362
+ pg_type t ON e.enumtypid = t.oid
363
+ JOIN
364
+ pg_namespace n ON t.typnamespace = n.oid
365
+ ORDER BY
366
+ schema_name,
367
+ enum_type,
368
+ sort_order;
369
+ ;
370
+ `;
371
+ const enumListResult = await client.query(enumListSql);
372
+ const enums = enumListResult.rows.reduce((acc, row) => {
373
+ const { schema_name, enum_type, enum_value } = row;
374
+ if (!acc[enum_type]) {
375
+ acc[enum_type] = {
376
+ name: enum_type,
377
+ schemaName: schema_name,
378
+ values: [],
379
+ };
380
+ }
381
+ acc[enum_type].values.push({
382
+ name: enum_value,
383
+ });
384
+ return acc;
385
+ }, {});
386
+ return Object.values(enums);
387
+ };
388
+ const fetchSchemaJson = async (connection) => {
389
+ const client = await getValidatedClient(connection);
390
+ const tablesAndFieldsRes = generateTablesAndFields(client);
391
+ const indexesRes = generateIndexes(client);
392
+ const refsRes = generateRawRefs(client);
393
+ const enumsRes = generateRawEnums(client);
394
+ const res = await Promise.all([
395
+ tablesAndFieldsRes,
396
+ indexesRes,
397
+ refsRes,
398
+ enumsRes,
399
+ ]);
400
+ client.end();
401
+ const { tables, fields } = res[0];
402
+ const { indexes, tableConstraints } = res[1];
403
+ const refs = res[2];
404
+ const enums = res[3];
405
+ return {
406
+ tables,
407
+ fields,
408
+ refs,
409
+ enums,
410
+ indexes,
411
+ tableConstraints,
412
+ };
413
+ };
414
+ exports.fetchSchemaJson = fetchSchemaJson;
@@ -0,0 +1,80 @@
1
+ interface NoteInfo {
2
+ value: string;
3
+ }
4
+ interface TypeInfo {
5
+ type_name: string;
6
+ schemaName: string | null;
7
+ }
8
+ type DefaultType = 'string' | 'number' | 'boolean' | 'expression';
9
+ interface DefaultInfo {
10
+ type: DefaultType;
11
+ value: string;
12
+ }
13
+ interface Field {
14
+ name: string;
15
+ type: TypeInfo;
16
+ dbdefault: DefaultInfo | null;
17
+ not_null: boolean;
18
+ increment: boolean;
19
+ note: NoteInfo;
20
+ }
21
+ interface Table {
22
+ name: string;
23
+ schemaName: string;
24
+ note: NoteInfo;
25
+ }
26
+ interface FieldsDictionary {
27
+ [key: string]: Field[];
28
+ }
29
+ interface TableConstraint {
30
+ [fieldName: string]: {
31
+ pk?: boolean;
32
+ unique?: boolean;
33
+ };
34
+ }
35
+ interface TableConstraintsDictionary {
36
+ [tableIdentifier: string]: TableConstraint;
37
+ }
38
+ interface RefEndpoint {
39
+ tableName: string;
40
+ schemaName: string;
41
+ fieldNames: string[];
42
+ relation: '*' | '1';
43
+ }
44
+ interface Ref {
45
+ name: string;
46
+ endpoints: RefEndpoint[];
47
+ onDelete: string | null;
48
+ onUpdate: string | null;
49
+ }
50
+ interface EnumValue {
51
+ name: string;
52
+ }
53
+ interface Enum {
54
+ name: string;
55
+ schemaName: string;
56
+ values: EnumValue[];
57
+ }
58
+ interface IndexColumn {
59
+ type: 'column' | 'expression';
60
+ value: string;
61
+ }
62
+ interface Index {
63
+ name: string;
64
+ type: string;
65
+ unique?: boolean;
66
+ pk?: boolean;
67
+ columns: IndexColumn[];
68
+ }
69
+ interface IndexesDictionary {
70
+ [tableIdentifier: string]: Index[];
71
+ }
72
+ interface DatabaseSchema {
73
+ tables: Table[];
74
+ fields: FieldsDictionary;
75
+ enums: Enum[];
76
+ tableConstraints: TableConstraintsDictionary;
77
+ refs: Ref[];
78
+ indexes: IndexesDictionary;
79
+ }
80
+ export { NoteInfo, TypeInfo, DefaultType, DefaultInfo, Field, Table, FieldsDictionary, TableConstraint, TableConstraintsDictionary, RefEndpoint, Ref, EnumValue, Enum, IndexColumn, Index, IndexesDictionary, DatabaseSchema, };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ import * as connector from "./connectors/connector";
2
+ export { connector, };
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.connector = void 0;
27
+ const connector = __importStar(require("./connectors/connector"));
28
+ exports.connector = connector;
package/jest.config.ts ADDED
@@ -0,0 +1,10 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'node',
4
+ transform: {
5
+ "^.+\\.[tj]sx?$": "babel-jest",
6
+ },
7
+ moduleNameMapper: {
8
+ "\\.(css|less|scss)$": "identity-obj-proxy",
9
+ },
10
+ };
package/jestHelpers.ts ADDED
@@ -0,0 +1,13 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ const scanDirNames = (dirname: string, subpath: string): string[] => {
5
+ const dirPath = path.join(dirname, subpath);
6
+ const sanitizedDirPath = path.normalize(dirPath);
7
+ const dirs = fs.readdirSync(sanitizedDirPath);
8
+ return dirs;
9
+ };
10
+
11
+ export {
12
+ scanDirNames,
13
+ };
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@dbml/connector",
3
+ "version": "3.7.2",
4
+ "description": "This package was created to fetch the schema JSON from many kind of databases.",
5
+ "author": "huy.phung.sw@gmail.com",
6
+ "license": "MIT",
7
+ "homepage": "https://dbml.dbdiagram.io",
8
+ "repository": "https://github.com/holistics/dbml/tree/master/packages/dbml-connector",
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "devDependencies": {
12
+ "@babel/core": "^7.21.4",
13
+ "@babel/node": "^7.20.7",
14
+ "@babel/plugin-transform-runtime": "^7.21.4",
15
+ "@babel/preset-env": "^7.21.4",
16
+ "@babel/preset-typescript": "^7.24.7",
17
+ "@babel/runtime": "^7.21.0",
18
+ "@types/jest": "^29.5.12",
19
+ "@types/mssql": "^9.1.5",
20
+ "@types/node": "^22.2.0",
21
+ "@types/pg": "^8.11.6",
22
+ "babel-jest": "^29.5.0",
23
+ "jest": "^29.7.0",
24
+ "ts-jest": "^29.2.4",
25
+ "ts-node": "^10.9.2",
26
+ "typescript": "^5.5.4"
27
+ },
28
+ "scripts": {
29
+ "build": "tsc",
30
+ "start": "node dist/index.js",
31
+ "test": "jest"
32
+ },
33
+ "dependencies": {
34
+ "mssql": "^11.0.1",
35
+ "mysql2": "^3.11.0",
36
+ "pg": "^8.12.0"
37
+ },
38
+ "engines": {
39
+ "node": ">=18"
40
+ },
41
+ "gitHead": "b616bcee47dbf0ffc924d10daa0b5836de002fc1"
42
+ }
@@ -0,0 +1,21 @@
1
+ import { DatabaseSchema } from './types';
2
+ import { fetchSchemaJson as fetchPostgresSchemaJson } from './postgresConnector';
3
+ import { fetchSchemaJson as fetchMssqlSchemaJson } from './mssqlConnector';
4
+ import { fetchSchemaJson as fetchMysqlSchemaJson } from './mysqlConnector';
5
+
6
+ const fetchSchemaJson = async (connection: string, format: string): Promise<DatabaseSchema> => {
7
+ switch (format) {
8
+ case 'postgres':
9
+ return fetchPostgresSchemaJson(connection);
10
+ case 'mssql':
11
+ return fetchMssqlSchemaJson(connection);
12
+ case 'mysql':
13
+ return fetchMysqlSchemaJson(connection);
14
+ default:
15
+ throw new Error(`Unsupported connection format: ${format}`);
16
+ }
17
+ };
18
+
19
+ export {
20
+ fetchSchemaJson,
21
+ };