dbtour-source-mssql 0.0.0-stage → 0.2.4
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/dist/index.d.ts +4 -0
- package/dist/index.js +23 -0
- package/dist/map.d.ts +85 -0
- package/dist/map.js +134 -0
- package/dist/query.sql +108 -0
- package/package.json +39 -4
- package/README.md +0 -3
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// The SQL Server source. `connection` is anything the mssql package accepts: an ADO string
|
|
2
|
+
// (Server=host,1433;Database=Shop;User Id=reader;Password=…;TrustServerCertificate=True) or an
|
|
3
|
+
// mssql:// URL. It is read from the environment variable dbtour.yaml names, never from the file.
|
|
4
|
+
import { readFileSync } from 'node:fs';
|
|
5
|
+
import sql from 'mssql';
|
|
6
|
+
import { mapRecordsets, toRecordsets } from "./map.js";
|
|
7
|
+
export { mapRecordsets, toRecordsets, formatType } from "./map.js";
|
|
8
|
+
export const query = readFileSync(new URL('./query.sql', import.meta.url), 'utf8');
|
|
9
|
+
export async function extract(config) {
|
|
10
|
+
if (!config.connection) {
|
|
11
|
+
throw new Error(`Source ${config.name} has no connection: add "connection: \${DBTOUR_MSSQL}" to it in dbtour.yaml and set that variable`);
|
|
12
|
+
}
|
|
13
|
+
const pool = new sql.ConnectionPool(config.connection);
|
|
14
|
+
await pool.connect();
|
|
15
|
+
try {
|
|
16
|
+
const result = await pool.request().query(query);
|
|
17
|
+
const exclude = Array.isArray(config.exclude) ? config.exclude.map(String) : undefined;
|
|
18
|
+
return mapRecordsets(toRecordsets(result.recordsets), { name: config.name, exclude });
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
await pool.close();
|
|
22
|
+
}
|
|
23
|
+
}
|
package/dist/map.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { Database } from 'dbtour';
|
|
2
|
+
export interface InfoRow {
|
|
3
|
+
name: string;
|
|
4
|
+
version: string | null;
|
|
5
|
+
description: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface TableRow {
|
|
8
|
+
schema: string;
|
|
9
|
+
name: string;
|
|
10
|
+
kind: 'table' | 'view';
|
|
11
|
+
description: string | null;
|
|
12
|
+
definition: string | null;
|
|
13
|
+
}
|
|
14
|
+
export interface ColumnRow {
|
|
15
|
+
schema: string;
|
|
16
|
+
table: string;
|
|
17
|
+
name: string;
|
|
18
|
+
position: number;
|
|
19
|
+
type: string;
|
|
20
|
+
maxLength: number;
|
|
21
|
+
precision: number;
|
|
22
|
+
scale: number;
|
|
23
|
+
nullable: boolean;
|
|
24
|
+
identity: boolean;
|
|
25
|
+
default: string | null;
|
|
26
|
+
computed: string | null;
|
|
27
|
+
description: string | null;
|
|
28
|
+
}
|
|
29
|
+
export interface KeyRow {
|
|
30
|
+
schema: string;
|
|
31
|
+
table: string;
|
|
32
|
+
name: string;
|
|
33
|
+
kind: 'PK' | 'UQ';
|
|
34
|
+
column: string;
|
|
35
|
+
ordinal: number;
|
|
36
|
+
}
|
|
37
|
+
export interface ForeignKeyRow {
|
|
38
|
+
name: string;
|
|
39
|
+
schema: string;
|
|
40
|
+
table: string;
|
|
41
|
+
column: string;
|
|
42
|
+
toSchema: string;
|
|
43
|
+
toTable: string;
|
|
44
|
+
toColumn: string;
|
|
45
|
+
ordinal: number;
|
|
46
|
+
onDelete: string;
|
|
47
|
+
onUpdate: string;
|
|
48
|
+
}
|
|
49
|
+
export interface IndexRow {
|
|
50
|
+
schema: string;
|
|
51
|
+
table: string;
|
|
52
|
+
name: string;
|
|
53
|
+
unique: boolean;
|
|
54
|
+
primary: boolean;
|
|
55
|
+
column: string;
|
|
56
|
+
ordinal: number;
|
|
57
|
+
included: boolean;
|
|
58
|
+
}
|
|
59
|
+
export interface CheckRow {
|
|
60
|
+
schema: string;
|
|
61
|
+
table: string;
|
|
62
|
+
name: string;
|
|
63
|
+
definition: string;
|
|
64
|
+
column: string | null;
|
|
65
|
+
}
|
|
66
|
+
export interface Recordsets {
|
|
67
|
+
info: InfoRow[];
|
|
68
|
+
tables: TableRow[];
|
|
69
|
+
columns: ColumnRow[];
|
|
70
|
+
keys: KeyRow[];
|
|
71
|
+
foreignKeys: ForeignKeyRow[];
|
|
72
|
+
indexes: IndexRow[];
|
|
73
|
+
checks: CheckRow[];
|
|
74
|
+
}
|
|
75
|
+
export interface MapOptions {
|
|
76
|
+
/** The name the docs call the database; the server's own name when not given. */
|
|
77
|
+
name?: string;
|
|
78
|
+
/** Tables to leave out, as schema.table with * for any run of characters: `dbo.sys*`, `*.webpages_*`. */
|
|
79
|
+
exclude?: string[];
|
|
80
|
+
}
|
|
81
|
+
/** The result sets in the order query.sql returns them. */
|
|
82
|
+
export declare function toRecordsets(sets: unknown[][]): Recordsets;
|
|
83
|
+
export declare function mapRecordsets(sets: Recordsets, options?: MapOptions): Database;
|
|
84
|
+
/** The type as SQL Server would spell it in a CREATE TABLE: nvarchar(320), varchar(max), decimal(18,2), datetime2(7). */
|
|
85
|
+
export declare function formatType(row: Pick<ColumnRow, 'type' | 'maxLength' | 'precision' | 'scale'>): string;
|
package/dist/map.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/** The result sets in the order query.sql returns them. */
|
|
2
|
+
export function toRecordsets(sets) {
|
|
3
|
+
if (sets.length !== 7)
|
|
4
|
+
throw new Error(`query.sql returns 7 result sets, got ${sets.length}: the query and map.ts disagree`);
|
|
5
|
+
const [info, tables, columns, keys, foreignKeys, indexes, checks] = sets;
|
|
6
|
+
return { info, tables, columns, keys, foreignKeys, indexes, checks };
|
|
7
|
+
}
|
|
8
|
+
export function mapRecordsets(sets, options = {}) {
|
|
9
|
+
const info = sets.info[0];
|
|
10
|
+
const excluded = (options.exclude ?? []).map(pattern);
|
|
11
|
+
const keep = (schema, table) => !excluded.some((p) => p.test(`${schema}.${table}`));
|
|
12
|
+
const tables = new Map();
|
|
13
|
+
const schemas = [];
|
|
14
|
+
for (const row of sets.tables) {
|
|
15
|
+
if (!keep(row.schema, row.name))
|
|
16
|
+
continue;
|
|
17
|
+
let schema = schemas.find((s) => s.name === row.schema);
|
|
18
|
+
if (!schema)
|
|
19
|
+
schemas.push((schema = { name: row.schema, tables: [] }));
|
|
20
|
+
const table = { name: row.name, kind: row.kind, columns: [], indexes: [], constraints: [] };
|
|
21
|
+
if (row.description)
|
|
22
|
+
table.description = row.description;
|
|
23
|
+
if (row.kind === 'view' && row.definition)
|
|
24
|
+
table.definition = row.definition;
|
|
25
|
+
schema.tables.push(table);
|
|
26
|
+
tables.set(`${row.schema}.${row.name}`, table);
|
|
27
|
+
}
|
|
28
|
+
for (const row of sets.columns) {
|
|
29
|
+
const table = tables.get(`${row.schema}.${row.table}`);
|
|
30
|
+
if (!table)
|
|
31
|
+
continue;
|
|
32
|
+
const column = { name: row.name, type: formatType(row), nullable: Boolean(row.nullable) };
|
|
33
|
+
if (row.default !== null)
|
|
34
|
+
column.default = row.default;
|
|
35
|
+
if (row.computed !== null)
|
|
36
|
+
column.computed = row.computed;
|
|
37
|
+
if (row.identity)
|
|
38
|
+
column.identity = true;
|
|
39
|
+
if (row.description)
|
|
40
|
+
column.description = row.description;
|
|
41
|
+
table.columns.push(column);
|
|
42
|
+
}
|
|
43
|
+
for (const [key, rows] of groupBy(sets.keys, (r) => `${r.schema}.${r.table}|${r.name}`)) {
|
|
44
|
+
const table = tables.get(key.split('|')[0]);
|
|
45
|
+
if (!table)
|
|
46
|
+
continue;
|
|
47
|
+
const columns = rows.sort((a, b) => a.ordinal - b.ordinal).map((r) => r.column);
|
|
48
|
+
if (rows[0].kind === 'PK')
|
|
49
|
+
table.primaryKey = columns;
|
|
50
|
+
table.constraints.push({ name: rows[0].name, kind: rows[0].kind === 'PK' ? 'primary' : 'unique', columns });
|
|
51
|
+
}
|
|
52
|
+
const relations = [];
|
|
53
|
+
for (const [, rows] of groupBy(sets.foreignKeys, (r) => r.name)) {
|
|
54
|
+
const ordered = rows.sort((a, b) => a.ordinal - b.ordinal);
|
|
55
|
+
const first = ordered[0];
|
|
56
|
+
const from = `${first.schema}.${first.table}`;
|
|
57
|
+
const to = `${first.toSchema}.${first.toTable}`;
|
|
58
|
+
if (!tables.has(from) || !tables.has(to))
|
|
59
|
+
continue;
|
|
60
|
+
const relation = { name: first.name, from: { table: from, columns: ordered.map((r) => r.column) }, to: { table: to, columns: ordered.map((r) => r.toColumn) } };
|
|
61
|
+
if (first.onDelete && first.onDelete !== 'NO_ACTION')
|
|
62
|
+
relation.onDelete = first.onDelete;
|
|
63
|
+
if (first.onUpdate && first.onUpdate !== 'NO_ACTION')
|
|
64
|
+
relation.onUpdate = first.onUpdate;
|
|
65
|
+
relations.push(relation);
|
|
66
|
+
tables.get(from).constraints.push({ name: first.name, kind: 'foreign', columns: relation.from.columns, definition: `${to} (${relation.to.columns.join(', ')})` });
|
|
67
|
+
}
|
|
68
|
+
for (const [key, rows] of groupBy(sets.indexes, (r) => `${r.schema}.${r.table}|${r.name}`)) {
|
|
69
|
+
const table = tables.get(key.split('|')[0]);
|
|
70
|
+
if (!table || rows[0].primary)
|
|
71
|
+
continue;
|
|
72
|
+
const index = {
|
|
73
|
+
name: rows[0].name,
|
|
74
|
+
columns: rows.filter((r) => !r.included).sort((a, b) => a.ordinal - b.ordinal).map((r) => r.column),
|
|
75
|
+
unique: Boolean(rows[0].unique),
|
|
76
|
+
};
|
|
77
|
+
const included = rows.filter((r) => r.included).map((r) => r.column);
|
|
78
|
+
if (included.length > 0)
|
|
79
|
+
index.included = included;
|
|
80
|
+
table.indexes.push(index);
|
|
81
|
+
}
|
|
82
|
+
for (const row of sets.checks) {
|
|
83
|
+
const table = tables.get(`${row.schema}.${row.table}`);
|
|
84
|
+
if (!table)
|
|
85
|
+
continue;
|
|
86
|
+
const constraint = { name: row.name, kind: 'check', columns: row.column ? [row.column] : [], definition: row.definition };
|
|
87
|
+
table.constraints.push(constraint);
|
|
88
|
+
}
|
|
89
|
+
const database = { name: options.name ?? info.name, driver: 'mssql', schemas, relations };
|
|
90
|
+
if (info.version)
|
|
91
|
+
database.version = info.version;
|
|
92
|
+
if (info.description)
|
|
93
|
+
database.description = info.description;
|
|
94
|
+
return database;
|
|
95
|
+
}
|
|
96
|
+
/** The type as SQL Server would spell it in a CREATE TABLE: nvarchar(320), varchar(max), decimal(18,2), datetime2(7). */
|
|
97
|
+
export function formatType(row) {
|
|
98
|
+
const t = row.type.toLowerCase();
|
|
99
|
+
switch (t) {
|
|
100
|
+
case 'char':
|
|
101
|
+
case 'varchar':
|
|
102
|
+
case 'binary':
|
|
103
|
+
case 'varbinary':
|
|
104
|
+
return `${t}(${row.maxLength === -1 ? 'max' : row.maxLength})`;
|
|
105
|
+
case 'nchar':
|
|
106
|
+
case 'nvarchar':
|
|
107
|
+
// max_length counts bytes; these types hold two per character.
|
|
108
|
+
return `${t}(${row.maxLength === -1 ? 'max' : row.maxLength / 2})`;
|
|
109
|
+
case 'decimal':
|
|
110
|
+
case 'numeric':
|
|
111
|
+
return `${t}(${row.precision},${row.scale})`;
|
|
112
|
+
case 'datetime2':
|
|
113
|
+
case 'datetimeoffset':
|
|
114
|
+
case 'time':
|
|
115
|
+
return `${t}(${row.scale})`;
|
|
116
|
+
default:
|
|
117
|
+
return t;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function groupBy(rows, key) {
|
|
121
|
+
const groups = new Map();
|
|
122
|
+
for (const row of rows) {
|
|
123
|
+
const k = key(row);
|
|
124
|
+
const group = groups.get(k);
|
|
125
|
+
if (group)
|
|
126
|
+
group.push(row);
|
|
127
|
+
else
|
|
128
|
+
groups.set(k, [row]);
|
|
129
|
+
}
|
|
130
|
+
return groups;
|
|
131
|
+
}
|
|
132
|
+
function pattern(text) {
|
|
133
|
+
return new RegExp('^' + text.split('*').map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('.*') + '$', 'i');
|
|
134
|
+
}
|
package/dist/query.sql
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
-- Everything dbtour needs from SQL Server, in one batch of seven result sets, read in this order by map.ts.
|
|
2
|
+
-- Reads the catalogue views only: a login with VIEW DEFINITION on the database is enough.
|
|
3
|
+
SET NOCOUNT ON;
|
|
4
|
+
|
|
5
|
+
-- 1. The database
|
|
6
|
+
SELECT DB_NAME() AS [name],
|
|
7
|
+
CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(50)) AS [version],
|
|
8
|
+
(SELECT TOP (1) CAST([value] AS nvarchar(max)) FROM sys.extended_properties WHERE class = 0 AND [name] = 'MS_Description') AS [description];
|
|
9
|
+
|
|
10
|
+
-- 2. Tables and views
|
|
11
|
+
SELECT s.[name] AS [schema],
|
|
12
|
+
o.[name] AS [name],
|
|
13
|
+
CASE o.[type] WHEN 'V' THEN 'view' ELSE 'table' END AS [kind],
|
|
14
|
+
CAST(ep.[value] AS nvarchar(max)) AS [description],
|
|
15
|
+
m.[definition] AS [definition]
|
|
16
|
+
FROM sys.objects o
|
|
17
|
+
JOIN sys.schemas s ON s.schema_id = o.schema_id
|
|
18
|
+
LEFT JOIN sys.extended_properties ep ON ep.class = 1 AND ep.major_id = o.object_id AND ep.minor_id = 0 AND ep.[name] = 'MS_Description'
|
|
19
|
+
LEFT JOIN sys.sql_modules m ON m.object_id = o.object_id
|
|
20
|
+
WHERE o.[type] IN ('U', 'V') AND o.is_ms_shipped = 0
|
|
21
|
+
ORDER BY s.[name], o.[name];
|
|
22
|
+
|
|
23
|
+
-- 3. Columns
|
|
24
|
+
SELECT s.[name] AS [schema],
|
|
25
|
+
o.[name] AS [table],
|
|
26
|
+
c.[name] AS [name],
|
|
27
|
+
c.column_id AS [position],
|
|
28
|
+
t.[name] AS [type],
|
|
29
|
+
c.max_length AS [maxLength],
|
|
30
|
+
c.[precision] AS [precision],
|
|
31
|
+
c.scale AS [scale],
|
|
32
|
+
c.is_nullable AS [nullable],
|
|
33
|
+
c.is_identity AS [identity],
|
|
34
|
+
d.[definition] AS [default],
|
|
35
|
+
cc.[definition] AS [computed],
|
|
36
|
+
CAST(ep.[value] AS nvarchar(max)) AS [description]
|
|
37
|
+
FROM sys.columns c
|
|
38
|
+
JOIN sys.objects o ON o.object_id = c.object_id AND o.[type] IN ('U', 'V') AND o.is_ms_shipped = 0
|
|
39
|
+
JOIN sys.schemas s ON s.schema_id = o.schema_id
|
|
40
|
+
JOIN sys.types t ON t.user_type_id = c.user_type_id
|
|
41
|
+
LEFT JOIN sys.default_constraints d ON d.object_id = c.default_object_id
|
|
42
|
+
LEFT JOIN sys.computed_columns cc ON cc.object_id = c.object_id AND cc.column_id = c.column_id
|
|
43
|
+
LEFT JOIN sys.extended_properties ep ON ep.class = 1 AND ep.major_id = c.object_id AND ep.minor_id = c.column_id AND ep.[name] = 'MS_Description'
|
|
44
|
+
ORDER BY s.[name], o.[name], c.column_id;
|
|
45
|
+
|
|
46
|
+
-- 4. Primary keys and unique constraints, one row per column
|
|
47
|
+
SELECT s.[name] AS [schema],
|
|
48
|
+
o.[name] AS [table],
|
|
49
|
+
kc.[name] AS [name],
|
|
50
|
+
kc.[type] AS [kind],
|
|
51
|
+
c.[name] AS [column],
|
|
52
|
+
ic.key_ordinal AS [ordinal]
|
|
53
|
+
FROM sys.key_constraints kc
|
|
54
|
+
JOIN sys.objects o ON o.object_id = kc.parent_object_id AND o.is_ms_shipped = 0
|
|
55
|
+
JOIN sys.schemas s ON s.schema_id = o.schema_id
|
|
56
|
+
JOIN sys.index_columns ic ON ic.object_id = kc.parent_object_id AND ic.index_id = kc.unique_index_id AND ic.key_ordinal > 0
|
|
57
|
+
JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
|
|
58
|
+
ORDER BY s.[name], o.[name], kc.[name], ic.key_ordinal;
|
|
59
|
+
|
|
60
|
+
-- 5. Foreign keys, one row per column pair
|
|
61
|
+
SELECT fk.[name] AS [name],
|
|
62
|
+
ps.[name] AS [schema],
|
|
63
|
+
po.[name] AS [table],
|
|
64
|
+
pc.[name] AS [column],
|
|
65
|
+
rs.[name] AS [toSchema],
|
|
66
|
+
ro.[name] AS [toTable],
|
|
67
|
+
rc.[name] AS [toColumn],
|
|
68
|
+
fkc.constraint_column_id AS [ordinal],
|
|
69
|
+
fk.delete_referential_action_desc AS [onDelete],
|
|
70
|
+
fk.update_referential_action_desc AS [onUpdate]
|
|
71
|
+
FROM sys.foreign_keys fk
|
|
72
|
+
JOIN sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
|
|
73
|
+
JOIN sys.objects po ON po.object_id = fk.parent_object_id
|
|
74
|
+
JOIN sys.schemas ps ON ps.schema_id = po.schema_id
|
|
75
|
+
JOIN sys.columns pc ON pc.object_id = fkc.parent_object_id AND pc.column_id = fkc.parent_column_id
|
|
76
|
+
JOIN sys.objects ro ON ro.object_id = fk.referenced_object_id
|
|
77
|
+
JOIN sys.schemas rs ON rs.schema_id = ro.schema_id
|
|
78
|
+
JOIN sys.columns rc ON rc.object_id = fkc.referenced_object_id AND rc.column_id = fkc.referenced_column_id
|
|
79
|
+
ORDER BY fk.[name], fkc.constraint_column_id;
|
|
80
|
+
|
|
81
|
+
-- 6. Indexes, one row per column, key columns then included ones
|
|
82
|
+
SELECT s.[name] AS [schema],
|
|
83
|
+
o.[name] AS [table],
|
|
84
|
+
i.[name] AS [name],
|
|
85
|
+
i.is_unique AS [unique],
|
|
86
|
+
i.is_primary_key AS [primary],
|
|
87
|
+
c.[name] AS [column],
|
|
88
|
+
ic.key_ordinal AS [ordinal],
|
|
89
|
+
ic.is_included_column AS [included]
|
|
90
|
+
FROM sys.indexes i
|
|
91
|
+
JOIN sys.objects o ON o.object_id = i.object_id AND o.[type] IN ('U', 'V') AND o.is_ms_shipped = 0
|
|
92
|
+
JOIN sys.schemas s ON s.schema_id = o.schema_id
|
|
93
|
+
JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
|
|
94
|
+
JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
|
|
95
|
+
WHERE i.[name] IS NOT NULL AND i.[type] > 0
|
|
96
|
+
ORDER BY s.[name], o.[name], i.[name], ic.is_included_column, ic.key_ordinal, ic.index_column_id;
|
|
97
|
+
|
|
98
|
+
-- 7. Check constraints
|
|
99
|
+
SELECT s.[name] AS [schema],
|
|
100
|
+
o.[name] AS [table],
|
|
101
|
+
ck.[name] AS [name],
|
|
102
|
+
ck.[definition] AS [definition],
|
|
103
|
+
c.[name] AS [column]
|
|
104
|
+
FROM sys.check_constraints ck
|
|
105
|
+
JOIN sys.objects o ON o.object_id = ck.parent_object_id AND o.is_ms_shipped = 0
|
|
106
|
+
JOIN sys.schemas s ON s.schema_id = o.schema_id
|
|
107
|
+
LEFT JOIN sys.columns c ON c.object_id = ck.parent_object_id AND c.column_id = ck.parent_column_id
|
|
108
|
+
ORDER BY s.[name], o.[name], ck.[name];
|
package/package.json
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dbtour-source-mssql",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.4",
|
|
4
|
+
"description": "SQL Server source for dbtour: tables, views, columns, keys, relations, indexes, descriptions.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Victor Saly",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/victorsaly/dbtour.git",
|
|
11
|
+
"directory": "packages/source-mssql"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=22.18"
|
|
15
|
+
},
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"prepack": "node ../../scripts/build.mjs"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"dbtour",
|
|
30
|
+
"mssql",
|
|
31
|
+
"sql-server",
|
|
32
|
+
"schema"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"mssql": "^12.7.13"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/mssql": "^9.1.8",
|
|
39
|
+
"dbtour": "0.2.4"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/README.md
DELETED