yamchart 0.8.1 → 0.8.3
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/{advisor-57BOMUUF.js → advisor-JMWAAWJO.js} +10 -10
- package/dist/chunk-4W6IVOKO.js +362 -0
- package/dist/chunk-4W6IVOKO.js.map +1 -0
- package/dist/{chunk-JYQKDWLG.js → chunk-5N3FYFBV.js} +72 -1
- package/dist/chunk-5N3FYFBV.js.map +1 -0
- package/dist/{chunk-OTAUP5RC.js → chunk-7AVPKKYY.js} +5 -5
- package/dist/chunk-7AVPKKYY.js.map +1 -0
- package/dist/{chunk-X6LQGWUX.js → chunk-KP4CYPBL.js} +9 -2
- package/dist/chunk-KP4CYPBL.js.map +1 -0
- package/dist/{chunk-E2UZXDF6.js → chunk-N6PUISAQ.js} +4 -4
- package/dist/compare-ZN6RUOOQ.js +87 -0
- package/dist/compare-ZN6RUOOQ.js.map +1 -0
- package/dist/{connection-utils-FTSZU2VF.js → connection-utils-VEKXRCOM.js} +4 -4
- package/dist/describe-X55JPLES.js +29 -0
- package/dist/describe-X55JPLES.js.map +1 -0
- package/dist/{dev-MRZ76V74.js → dev-NZLS72PG.js} +9 -7
- package/dist/dev-NZLS72PG.js.map +1 -0
- package/dist/{dist-PVHFUYP2.js → dist-E2PVGIPT.js} +4 -2
- package/dist/{dist-WDTDQDTX.js → dist-GVNWQXFR.js} +2 -2
- package/dist/index.js +314 -32
- package/dist/index.js.map +1 -1
- package/dist/{lineage-XSITWW2O.js → lineage-T5NRHHZN.js} +32 -5
- package/dist/{lineage-XSITWW2O.js.map → lineage-T5NRHHZN.js.map} +1 -1
- package/dist/public/assets/{EventManagement-BlxJ2TFw.js → EventManagement-7MyQq5KD.js} +1 -1
- package/dist/public/assets/{LoginPage-BT8ikmPn.js → LoginPage-BypxvDY2.js} +1 -1
- package/dist/public/assets/{PublicViewer-B4uFxgbt.js → PublicViewer-CdDaYqTc.js} +1 -1
- package/dist/public/assets/{SetupWizard-njrOhCzw.js → SetupWizard-CEGLuSGr.js} +1 -1
- package/dist/public/assets/{ShareManagement-Bg16oJhW.js → ShareManagement-DcPZNRdx.js} +1 -1
- package/dist/public/assets/{UserManagement-tiCIT4UY.js → UserManagement-VZ9Qvds0.js} +1 -1
- package/dist/public/assets/{index-BZ25r23j.css → index-B_fusLA_.css} +1 -1
- package/dist/public/assets/index-Cxn1i3jV.js +187 -0
- package/dist/public/assets/{index.es-BuktD_R2.js → index.es-06ls9Fpg.js} +1 -1
- package/dist/public/assets/{jspdf.es.min-DFRl2hZQ.js → jspdf.es.min-DER4Hnpt.js} +3 -3
- package/dist/public/index.html +3 -3
- package/dist/{query-JRMMNXX6.js → query-3F5V5CZH.js} +4 -4
- package/dist/{sample-VGIY4U4J.js → sample-SWYXGWOM.js} +4 -4
- package/dist/search-ARIDL6DA.js +28 -0
- package/dist/search-ARIDL6DA.js.map +1 -0
- package/dist/source-resolver-UHKZVOOC.js +18 -0
- package/dist/source-resolver-UHKZVOOC.js.map +1 -0
- package/dist/{sync-warehouse-XHTBZH25.js → sync-warehouse-J4E2R2PW.js} +4 -4
- package/dist/tables-VAR2ZKUA.js +30 -0
- package/dist/tables-VAR2ZKUA.js.map +1 -0
- package/dist/templates/default/docs/yamchart-reference.md +23 -4
- package/dist/templates/default/yamchart.yaml +1 -1
- package/dist/templates/empty/yamchart.yaml +1 -1
- package/dist/{test-TXRZWNXK.js → test-SV5SLSLM.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-JYQKDWLG.js.map +0 -1
- package/dist/chunk-OTAUP5RC.js.map +0 -1
- package/dist/chunk-X6LQGWUX.js.map +0 -1
- package/dist/describe-TGIOBNJB.js +0 -44
- package/dist/describe-TGIOBNJB.js.map +0 -1
- package/dist/dev-MRZ76V74.js.map +0 -1
- package/dist/public/assets/index-B41yj3io.js +0 -187
- package/dist/search-QSYNG4SR.js +0 -39
- package/dist/search-QSYNG4SR.js.map +0 -1
- package/dist/tables-UOO342TA.js +0 -40
- package/dist/tables-UOO342TA.js.map +0 -1
- /package/dist/{advisor-57BOMUUF.js.map → advisor-JMWAAWJO.js.map} +0 -0
- /package/dist/{chunk-E2UZXDF6.js.map → chunk-N6PUISAQ.js.map} +0 -0
- /package/dist/{connection-utils-FTSZU2VF.js.map → connection-utils-VEKXRCOM.js.map} +0 -0
- /package/dist/{dist-PVHFUYP2.js.map → dist-E2PVGIPT.js.map} +0 -0
- /package/dist/{dist-WDTDQDTX.js.map → dist-GVNWQXFR.js.map} +0 -0
- /package/dist/{query-JRMMNXX6.js.map → query-3F5V5CZH.js.map} +0 -0
- /package/dist/{sample-VGIY4U4J.js.map → sample-SWYXGWOM.js.map} +0 -0
- /package/dist/{sync-warehouse-XHTBZH25.js.map → sync-warehouse-J4E2R2PW.js.map} +0 -0
- /package/dist/{test-TXRZWNXK.js.map → test-SV5SLSLM.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createConnector,
|
|
3
3
|
resolveConnection
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7AVPKKYY.js";
|
|
5
5
|
import {
|
|
6
6
|
detail,
|
|
7
7
|
error,
|
|
@@ -10,8 +10,8 @@ import {
|
|
|
10
10
|
success,
|
|
11
11
|
warning
|
|
12
12
|
} from "./chunk-HJVVHYVN.js";
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-KP4CYPBL.js";
|
|
14
|
+
import "./chunk-5N3FYFBV.js";
|
|
15
15
|
import "./chunk-UND73EOB.js";
|
|
16
16
|
import "./chunk-DGUM43GV.js";
|
|
17
17
|
|
|
@@ -44,7 +44,7 @@ async function getDbtProjectPath(projectDir, override) {
|
|
|
44
44
|
return null;
|
|
45
45
|
}
|
|
46
46
|
async function buildContext(projectDir, options) {
|
|
47
|
-
const { parseModelMetadata } = await import("./dist-
|
|
47
|
+
const { parseModelMetadata } = await import("./dist-E2PVGIPT.js");
|
|
48
48
|
const modelsDir = join(projectDir, "models");
|
|
49
49
|
const yamchartModels = [];
|
|
50
50
|
try {
|
|
@@ -140,7 +140,7 @@ async function buildContext(projectDir, options) {
|
|
|
140
140
|
};
|
|
141
141
|
if (dbtPath) {
|
|
142
142
|
try {
|
|
143
|
-
const { detectConventions, listDbtModels } = await import("./dist-
|
|
143
|
+
const { detectConventions, listDbtModels } = await import("./dist-GVNWQXFR.js");
|
|
144
144
|
const dbtProjectYml = await readFile(join(dbtPath, "dbt_project.yml"), "utf-8");
|
|
145
145
|
const dbtConfig = parseYaml(dbtProjectYml);
|
|
146
146
|
const conventions = await detectConventions(dbtPath);
|
|
@@ -236,7 +236,7 @@ async function runAdvisor(projectDir, questionOrMode, options) {
|
|
|
236
236
|
`warehouse: ${context.warehouse ? `connected (${context.warehouse.connectionType})` : "not connected"}`
|
|
237
237
|
);
|
|
238
238
|
console.log("");
|
|
239
|
-
const { AdvisorAgent, AnthropicProvider, buildModelPath } = await import("./dist-
|
|
239
|
+
const { AdvisorAgent, AnthropicProvider, buildModelPath } = await import("./dist-GVNWQXFR.js");
|
|
240
240
|
const provider = new AnthropicProvider(apiKey);
|
|
241
241
|
const agent = new AdvisorAgent(provider);
|
|
242
242
|
const isAudit = questionOrMode === "audit";
|
|
@@ -281,7 +281,7 @@ ${pc.bold(`[${i + 1}]`)} ${formatProposal(proposal, context.dbt.conventions, bui
|
|
|
281
281
|
spin2.stop();
|
|
282
282
|
console.log(result.response);
|
|
283
283
|
if (result.proposals.length > 0) {
|
|
284
|
-
const { buildModelPath: bmp } = await import("./dist-
|
|
284
|
+
const { buildModelPath: bmp } = await import("./dist-GVNWQXFR.js");
|
|
285
285
|
for (const proposal of result.proposals) {
|
|
286
286
|
console.log(
|
|
287
287
|
`
|
|
@@ -322,7 +322,7 @@ ${formatProposal(proposal, context.dbt.conventions, bmp)}`
|
|
|
322
322
|
conversationHistory.length = 0;
|
|
323
323
|
conversationHistory.push(...result.messages);
|
|
324
324
|
if (result.proposals.length > 0) {
|
|
325
|
-
const { buildModelPath: bmp } = await import("./dist-
|
|
325
|
+
const { buildModelPath: bmp } = await import("./dist-GVNWQXFR.js");
|
|
326
326
|
for (const proposal of result.proposals) {
|
|
327
327
|
console.log(
|
|
328
328
|
`
|
|
@@ -340,7 +340,7 @@ async function offerApply(context, proposals) {
|
|
|
340
340
|
return;
|
|
341
341
|
}
|
|
342
342
|
const { confirm } = await import("@inquirer/prompts");
|
|
343
|
-
const { writeDbtModel, buildModelPath, formatModelSql, updateSchemaYml } = await import("./dist-
|
|
343
|
+
const { writeDbtModel, buildModelPath, formatModelSql, updateSchemaYml } = await import("./dist-GVNWQXFR.js");
|
|
344
344
|
for (const proposal of proposals) {
|
|
345
345
|
console.log("");
|
|
346
346
|
const shouldApply = await confirm({
|
|
@@ -379,4 +379,4 @@ async function offerApply(context, proposals) {
|
|
|
379
379
|
export {
|
|
380
380
|
runAdvisor
|
|
381
381
|
};
|
|
382
|
-
//# sourceMappingURL=advisor-
|
|
382
|
+
//# sourceMappingURL=advisor-JMWAAWJO.js.map
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveTableName
|
|
3
|
+
} from "./chunk-VJC24RKT.js";
|
|
4
|
+
import {
|
|
5
|
+
getDescribeQuery,
|
|
6
|
+
getSearchQuery,
|
|
7
|
+
getTablesQuery
|
|
8
|
+
} from "./chunk-EHM6AMMA.js";
|
|
9
|
+
import {
|
|
10
|
+
createConnector,
|
|
11
|
+
resolveConnection
|
|
12
|
+
} from "./chunk-7AVPKKYY.js";
|
|
13
|
+
|
|
14
|
+
// src/commands/source-resolver.ts
|
|
15
|
+
import { readFile as readFile2, access as access2 } from "fs/promises";
|
|
16
|
+
import { join as join2 } from "path";
|
|
17
|
+
import { performance } from "perf_hooks";
|
|
18
|
+
|
|
19
|
+
// src/commands/model-parser.ts
|
|
20
|
+
import { readFile, readdir, access } from "fs/promises";
|
|
21
|
+
import { join, extname } from "path";
|
|
22
|
+
function parseModelReturns(sql) {
|
|
23
|
+
const nameMatch = sql.match(/--\s*@name:\s*(.+)/);
|
|
24
|
+
if (!nameMatch?.[1]) return null;
|
|
25
|
+
const name = nameMatch[1].trim();
|
|
26
|
+
const descMatch = sql.match(/--\s*@description:\s*(.+)/);
|
|
27
|
+
const description = descMatch?.[1]?.trim();
|
|
28
|
+
const columns = [];
|
|
29
|
+
const returnsMatch = sql.match(/--\s*@returns:\s*\n((?:\s*--\s+-\s+.+\n?)*)/);
|
|
30
|
+
if (returnsMatch?.[1]) {
|
|
31
|
+
const lines = returnsMatch[1].split("\n");
|
|
32
|
+
for (const line of lines) {
|
|
33
|
+
const colMatch = line.match(/--\s+-\s+(\w+)(?:\s*:\s*(\w+))?/);
|
|
34
|
+
if (colMatch?.[1]) {
|
|
35
|
+
columns.push({
|
|
36
|
+
name: colMatch[1],
|
|
37
|
+
type: colMatch[2] || "unknown",
|
|
38
|
+
nullable: "YES"
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { name, description, columns };
|
|
44
|
+
}
|
|
45
|
+
async function findSqlFiles(dir) {
|
|
46
|
+
const files = [];
|
|
47
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
const fullPath = join(dir, entry.name);
|
|
50
|
+
if (entry.isDirectory()) {
|
|
51
|
+
files.push(...await findSqlFiles(fullPath));
|
|
52
|
+
} else if (extname(entry.name) === ".sql") {
|
|
53
|
+
files.push(fullPath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return files;
|
|
57
|
+
}
|
|
58
|
+
async function scanModels(projectDir) {
|
|
59
|
+
const modelsDir = join(projectDir, "models");
|
|
60
|
+
try {
|
|
61
|
+
await access(modelsDir);
|
|
62
|
+
} catch {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
const sqlFiles = await findSqlFiles(modelsDir);
|
|
66
|
+
const models = [];
|
|
67
|
+
for (const filePath of sqlFiles) {
|
|
68
|
+
const content = await readFile(filePath, "utf-8");
|
|
69
|
+
const parsed = parseModelReturns(content);
|
|
70
|
+
if (parsed) {
|
|
71
|
+
models.push(parsed);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return models;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/commands/source-resolver.ts
|
|
78
|
+
async function loadCatalog(projectDir) {
|
|
79
|
+
try {
|
|
80
|
+
const catalogPath = join2(projectDir, ".yamchart", "catalog.json");
|
|
81
|
+
await access2(catalogPath);
|
|
82
|
+
const content = await readFile2(catalogPath, "utf-8");
|
|
83
|
+
return JSON.parse(content);
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function findCatalogModel(catalog, tableName) {
|
|
89
|
+
return catalog.models?.find(
|
|
90
|
+
(m) => m.name.toLowerCase() === tableName.toLowerCase()
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
function catalogColumnsToNormalized(columns) {
|
|
94
|
+
return columns.map((c) => ({
|
|
95
|
+
name: c.name,
|
|
96
|
+
type: c.data_type,
|
|
97
|
+
nullable: "YES"
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
async function describeFromCatalog(projectDir, table) {
|
|
101
|
+
const catalog = await loadCatalog(projectDir);
|
|
102
|
+
if (!catalog) return null;
|
|
103
|
+
const model = findCatalogModel(catalog, table);
|
|
104
|
+
if (!model?.columns?.length) return null;
|
|
105
|
+
return {
|
|
106
|
+
source: "catalog",
|
|
107
|
+
table: model.table || table,
|
|
108
|
+
columns: catalogColumnsToNormalized(model.columns),
|
|
109
|
+
durationMs: 0,
|
|
110
|
+
...model.table ? { resolvedFrom: table } : {}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
async function describeFromModel(projectDir, table) {
|
|
114
|
+
const models = await scanModels(projectDir);
|
|
115
|
+
const match = models.find(
|
|
116
|
+
(m) => m.name.toLowerCase() === table.toLowerCase()
|
|
117
|
+
);
|
|
118
|
+
if (!match || match.columns.length === 0) return null;
|
|
119
|
+
return {
|
|
120
|
+
source: "model",
|
|
121
|
+
table: match.name,
|
|
122
|
+
columns: match.columns,
|
|
123
|
+
durationMs: 0
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
async function describeFromDb(projectDir, table, connectionName) {
|
|
127
|
+
const resolved = await resolveTableName(projectDir, table);
|
|
128
|
+
const connection = await resolveConnection(projectDir, connectionName);
|
|
129
|
+
const connector = createConnector(connection, projectDir);
|
|
130
|
+
try {
|
|
131
|
+
await connector.connect();
|
|
132
|
+
const query = getDescribeQuery(connection.type, resolved.tableName);
|
|
133
|
+
const startTime = performance.now();
|
|
134
|
+
const result = await connector.execute(query.sql);
|
|
135
|
+
const durationMs = performance.now() - startTime;
|
|
136
|
+
const columns = query.normalize(result.rows);
|
|
137
|
+
return {
|
|
138
|
+
source: "db",
|
|
139
|
+
table: resolved.tableName,
|
|
140
|
+
columns,
|
|
141
|
+
connectionName: connection.name,
|
|
142
|
+
connectionType: connection.type,
|
|
143
|
+
durationMs,
|
|
144
|
+
...resolved.source === "catalog" ? { resolvedFrom: table } : {}
|
|
145
|
+
};
|
|
146
|
+
} finally {
|
|
147
|
+
await connector.disconnect();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async function resolveDescribeSource(projectDir, table, source, connectionName) {
|
|
151
|
+
switch (source) {
|
|
152
|
+
case "catalog": {
|
|
153
|
+
const catalog = await loadCatalog(projectDir);
|
|
154
|
+
if (!catalog) throw new Error("No catalog found. Run `yamchart sync-dbt` or `yamchart sync-warehouse` to populate it.");
|
|
155
|
+
const model = findCatalogModel(catalog, table);
|
|
156
|
+
if (!model) throw new Error(`Table "${table}" not found in catalog.`);
|
|
157
|
+
if (!model.columns?.length) throw new Error(`Catalog has no column metadata for "${table}". Run sync to populate.`);
|
|
158
|
+
return {
|
|
159
|
+
source: "catalog",
|
|
160
|
+
table: model.table || table,
|
|
161
|
+
columns: catalogColumnsToNormalized(model.columns),
|
|
162
|
+
durationMs: 0,
|
|
163
|
+
...model.table ? { resolvedFrom: table } : {}
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
case "model": {
|
|
167
|
+
const models = await scanModels(projectDir);
|
|
168
|
+
const match = models.find((m) => m.name.toLowerCase() === table.toLowerCase());
|
|
169
|
+
if (!match) throw new Error(`No model found matching "${table}". Check your models/ directory.`);
|
|
170
|
+
return {
|
|
171
|
+
source: "model",
|
|
172
|
+
table: match.name,
|
|
173
|
+
columns: match.columns,
|
|
174
|
+
durationMs: 0
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
case "db":
|
|
178
|
+
return describeFromDb(projectDir, table, connectionName);
|
|
179
|
+
case "auto": {
|
|
180
|
+
const catalogResult = await describeFromCatalog(projectDir, table);
|
|
181
|
+
if (catalogResult) return catalogResult;
|
|
182
|
+
const modelResult = await describeFromModel(projectDir, table);
|
|
183
|
+
if (modelResult) return modelResult;
|
|
184
|
+
return describeFromDb(projectDir, table, connectionName);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async function tablesFromCatalog(projectDir) {
|
|
189
|
+
const catalog = await loadCatalog(projectDir);
|
|
190
|
+
if (!catalog?.models?.length) return null;
|
|
191
|
+
const tables = catalog.models.map((m) => {
|
|
192
|
+
const parts = (m.table || m.name).split(".");
|
|
193
|
+
return {
|
|
194
|
+
schema: parts.length > 1 ? parts.slice(0, -1).join(".") : "",
|
|
195
|
+
name: parts[parts.length - 1],
|
|
196
|
+
type: m.source === "dbt-source" ? "SOURCE" : "TABLE"
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
return { source: "catalog", tables, durationMs: 0 };
|
|
200
|
+
}
|
|
201
|
+
async function tablesFromModel(projectDir) {
|
|
202
|
+
const models = await scanModels(projectDir);
|
|
203
|
+
if (models.length === 0) return null;
|
|
204
|
+
const tables = models.map((m) => ({
|
|
205
|
+
schema: "",
|
|
206
|
+
name: m.name,
|
|
207
|
+
type: "MODEL"
|
|
208
|
+
}));
|
|
209
|
+
return { source: "model", tables, durationMs: 0 };
|
|
210
|
+
}
|
|
211
|
+
async function tablesFromDb(projectDir, connectionName, options) {
|
|
212
|
+
const connection = await resolveConnection(projectDir, connectionName);
|
|
213
|
+
const connector = createConnector(connection, projectDir);
|
|
214
|
+
try {
|
|
215
|
+
await connector.connect();
|
|
216
|
+
const query = getTablesQuery(connection.type, options);
|
|
217
|
+
const start = performance.now();
|
|
218
|
+
const result = await connector.execute(query.sql);
|
|
219
|
+
const tables = query.normalize(result.rows);
|
|
220
|
+
const durationMs = Math.round((performance.now() - start) * 100) / 100;
|
|
221
|
+
return {
|
|
222
|
+
source: "db",
|
|
223
|
+
tables,
|
|
224
|
+
connectionName: connection.name,
|
|
225
|
+
connectionType: connection.type,
|
|
226
|
+
durationMs
|
|
227
|
+
};
|
|
228
|
+
} finally {
|
|
229
|
+
await connector.disconnect();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async function resolveTablesSource(projectDir, source, connectionName, options) {
|
|
233
|
+
switch (source) {
|
|
234
|
+
case "catalog": {
|
|
235
|
+
const catalog = await loadCatalog(projectDir);
|
|
236
|
+
if (!catalog) throw new Error("No catalog found. Run `yamchart sync-dbt` or `yamchart sync-warehouse` to populate it.");
|
|
237
|
+
const result = await tablesFromCatalog(projectDir);
|
|
238
|
+
return result || { source: "catalog", tables: [], durationMs: 0 };
|
|
239
|
+
}
|
|
240
|
+
case "model": {
|
|
241
|
+
const result = await tablesFromModel(projectDir);
|
|
242
|
+
return result || { source: "model", tables: [], durationMs: 0 };
|
|
243
|
+
}
|
|
244
|
+
case "db":
|
|
245
|
+
return tablesFromDb(projectDir, connectionName, options);
|
|
246
|
+
case "auto": {
|
|
247
|
+
const catalogResult = await tablesFromCatalog(projectDir);
|
|
248
|
+
if (catalogResult) return catalogResult;
|
|
249
|
+
const modelResult = await tablesFromModel(projectDir);
|
|
250
|
+
if (modelResult) return modelResult;
|
|
251
|
+
return tablesFromDb(projectDir, connectionName, options);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function searchCatalog(catalog, keyword) {
|
|
256
|
+
const results = [];
|
|
257
|
+
const lower = keyword.toLowerCase();
|
|
258
|
+
for (const model of catalog.models || []) {
|
|
259
|
+
const tableParts = (model.table || model.name).split(".");
|
|
260
|
+
const schema = tableParts.length > 1 ? tableParts.slice(0, -1).join(".") : "";
|
|
261
|
+
const tableName = tableParts[tableParts.length - 1];
|
|
262
|
+
if (model.name.toLowerCase().includes(lower) || tableName.toLowerCase().includes(lower)) {
|
|
263
|
+
results.push({ type: "table", schema, table: model.name });
|
|
264
|
+
}
|
|
265
|
+
for (const col of model.columns || []) {
|
|
266
|
+
if (col.name.toLowerCase().includes(lower)) {
|
|
267
|
+
results.push({
|
|
268
|
+
type: "column",
|
|
269
|
+
schema,
|
|
270
|
+
table: model.name,
|
|
271
|
+
column: col.name,
|
|
272
|
+
columnType: col.data_type
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return results;
|
|
278
|
+
}
|
|
279
|
+
async function searchFromDb(projectDir, keyword, connectionName) {
|
|
280
|
+
const connection = await resolveConnection(projectDir, connectionName);
|
|
281
|
+
const connector = createConnector(connection, projectDir);
|
|
282
|
+
try {
|
|
283
|
+
await connector.connect();
|
|
284
|
+
const query = getSearchQuery(connection.type, keyword);
|
|
285
|
+
const startTime = performance.now();
|
|
286
|
+
const result = await connector.execute(query.sql);
|
|
287
|
+
const durationMs = performance.now() - startTime;
|
|
288
|
+
const results = query.normalize(result.rows);
|
|
289
|
+
return {
|
|
290
|
+
source: "db",
|
|
291
|
+
keyword,
|
|
292
|
+
results,
|
|
293
|
+
connectionName: connection.name,
|
|
294
|
+
connectionType: connection.type,
|
|
295
|
+
durationMs
|
|
296
|
+
};
|
|
297
|
+
} finally {
|
|
298
|
+
await connector.disconnect();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
async function resolveSearchSource(projectDir, keyword, source, connectionName) {
|
|
302
|
+
switch (source) {
|
|
303
|
+
case "catalog": {
|
|
304
|
+
const catalog = await loadCatalog(projectDir);
|
|
305
|
+
if (!catalog) throw new Error("No catalog found. Run `yamchart sync-dbt` or `yamchart sync-warehouse` to populate it.");
|
|
306
|
+
return { source: "catalog", keyword, results: searchCatalog(catalog, keyword), durationMs: 0 };
|
|
307
|
+
}
|
|
308
|
+
case "model": {
|
|
309
|
+
const models = await scanModels(projectDir);
|
|
310
|
+
const lower = keyword.toLowerCase();
|
|
311
|
+
const results = [];
|
|
312
|
+
for (const model of models) {
|
|
313
|
+
if (model.name.toLowerCase().includes(lower)) {
|
|
314
|
+
results.push({ type: "table", schema: "", table: model.name });
|
|
315
|
+
}
|
|
316
|
+
for (const col of model.columns) {
|
|
317
|
+
if (col.name.toLowerCase().includes(lower)) {
|
|
318
|
+
results.push({ type: "column", schema: "", table: model.name, column: col.name, columnType: col.type });
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return { source: "model", keyword, results, durationMs: 0 };
|
|
323
|
+
}
|
|
324
|
+
case "db":
|
|
325
|
+
return searchFromDb(projectDir, keyword, connectionName);
|
|
326
|
+
case "auto": {
|
|
327
|
+
const catalog = await loadCatalog(projectDir);
|
|
328
|
+
if (catalog?.models?.length) {
|
|
329
|
+
const results = searchCatalog(catalog, keyword);
|
|
330
|
+
if (results.length > 0) {
|
|
331
|
+
return { source: "catalog", keyword, results, durationMs: 0 };
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
const models = await scanModels(projectDir);
|
|
335
|
+
if (models.length > 0) {
|
|
336
|
+
const lower = keyword.toLowerCase();
|
|
337
|
+
const results = [];
|
|
338
|
+
for (const model of models) {
|
|
339
|
+
if (model.name.toLowerCase().includes(lower)) {
|
|
340
|
+
results.push({ type: "table", schema: "", table: model.name });
|
|
341
|
+
}
|
|
342
|
+
for (const col of model.columns) {
|
|
343
|
+
if (col.name.toLowerCase().includes(lower)) {
|
|
344
|
+
results.push({ type: "column", schema: "", table: model.name, column: col.name, columnType: col.type });
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (results.length > 0) {
|
|
349
|
+
return { source: "model", keyword, results, durationMs: 0 };
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return searchFromDb(projectDir, keyword, connectionName);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export {
|
|
358
|
+
resolveDescribeSource,
|
|
359
|
+
resolveTablesSource,
|
|
360
|
+
resolveSearchSource
|
|
361
|
+
};
|
|
362
|
+
//# sourceMappingURL=chunk-4W6IVOKO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/source-resolver.ts","../src/commands/model-parser.ts"],"sourcesContent":["import { readFile, access } from 'fs/promises';\nimport { join } from 'path';\nimport { performance } from 'node:perf_hooks';\nimport type { NormalizedColumn, NormalizedTable, SearchResult } from './introspection.js';\nimport { getDescribeQuery, getTablesQuery, getSearchQuery } from './introspection.js';\nimport { resolveConnection, createConnector } from './connection-utils.js';\nimport { scanModels } from './model-parser.js';\nimport { resolveTableName } from './model-resolver.js';\n\nexport type SourceType = 'auto' | 'catalog' | 'model' | 'db';\n\ninterface CatalogColumn {\n name: string;\n data_type: string;\n description?: string;\n}\n\ninterface CatalogModel {\n name: string;\n table?: string;\n columns?: CatalogColumn[];\n source?: string;\n dependsOn?: string[];\n}\n\ninterface CatalogFile {\n models?: CatalogModel[];\n}\n\nexport interface DescribeSourceResult {\n source: 'catalog' | 'model' | 'db';\n table: string;\n columns: NormalizedColumn[];\n connectionName?: string;\n connectionType?: string;\n durationMs: number;\n resolvedFrom?: string;\n}\n\nexport interface TablesSourceResult {\n source: 'catalog' | 'model' | 'db';\n tables: NormalizedTable[];\n connectionName?: string;\n connectionType?: string;\n durationMs: number;\n}\n\nexport interface SearchSourceResult {\n source: 'catalog' | 'model' | 'db';\n keyword: string;\n results: SearchResult[];\n connectionName?: string;\n connectionType?: string;\n durationMs: number;\n}\n\nasync function loadCatalog(projectDir: string): Promise<CatalogFile | null> {\n try {\n const catalogPath = join(projectDir, '.yamchart', 'catalog.json');\n await access(catalogPath);\n const content = await readFile(catalogPath, 'utf-8');\n return JSON.parse(content) as CatalogFile;\n } catch {\n return null;\n }\n}\n\nfunction findCatalogModel(catalog: CatalogFile, tableName: string): CatalogModel | undefined {\n return catalog.models?.find(\n (m) => m.name.toLowerCase() === tableName.toLowerCase(),\n );\n}\n\nfunction catalogColumnsToNormalized(columns: CatalogColumn[]): NormalizedColumn[] {\n return columns.map((c) => ({\n name: c.name,\n type: c.data_type,\n nullable: 'YES',\n }));\n}\n\n// --- DESCRIBE ---\n\nasync function describeFromCatalog(\n projectDir: string,\n table: string,\n): Promise<DescribeSourceResult | null> {\n const catalog = await loadCatalog(projectDir);\n if (!catalog) return null;\n\n const model = findCatalogModel(catalog, table);\n if (!model?.columns?.length) return null;\n\n return {\n source: 'catalog',\n table: model.table || table,\n columns: catalogColumnsToNormalized(model.columns),\n durationMs: 0,\n ...(model.table ? { resolvedFrom: table } : {}),\n };\n}\n\nasync function describeFromModel(\n projectDir: string,\n table: string,\n): Promise<DescribeSourceResult | null> {\n const models = await scanModels(projectDir);\n const match = models.find(\n (m) => m.name.toLowerCase() === table.toLowerCase(),\n );\n if (!match || match.columns.length === 0) return null;\n\n return {\n source: 'model',\n table: match.name,\n columns: match.columns,\n durationMs: 0,\n };\n}\n\nasync function describeFromDb(\n projectDir: string,\n table: string,\n connectionName?: string,\n): Promise<DescribeSourceResult> {\n const resolved = await resolveTableName(projectDir, table);\n const connection = await resolveConnection(projectDir, connectionName);\n const connector = createConnector(connection, projectDir);\n\n try {\n await connector.connect();\n const query = getDescribeQuery(connection.type, resolved.tableName);\n const startTime = performance.now();\n const result = await connector.execute(query.sql);\n const durationMs = performance.now() - startTime;\n const columns = query.normalize(result.rows as Record<string, unknown>[]);\n\n return {\n source: 'db',\n table: resolved.tableName,\n columns,\n connectionName: connection.name,\n connectionType: connection.type,\n durationMs,\n ...(resolved.source === 'catalog' ? { resolvedFrom: table } : {}),\n };\n } finally {\n await connector.disconnect();\n }\n}\n\nexport async function resolveDescribeSource(\n projectDir: string,\n table: string,\n source: SourceType,\n connectionName?: string,\n): Promise<DescribeSourceResult> {\n switch (source) {\n case 'catalog': {\n const catalog = await loadCatalog(projectDir);\n if (!catalog) throw new Error('No catalog found. Run `yamchart sync-dbt` or `yamchart sync-warehouse` to populate it.');\n const model = findCatalogModel(catalog, table);\n if (!model) throw new Error(`Table \"${table}\" not found in catalog.`);\n if (!model.columns?.length) throw new Error(`Catalog has no column metadata for \"${table}\". Run sync to populate.`);\n return {\n source: 'catalog',\n table: model.table || table,\n columns: catalogColumnsToNormalized(model.columns),\n durationMs: 0,\n ...(model.table ? { resolvedFrom: table } : {}),\n };\n }\n\n case 'model': {\n const models = await scanModels(projectDir);\n const match = models.find((m) => m.name.toLowerCase() === table.toLowerCase());\n if (!match) throw new Error(`No model found matching \"${table}\". Check your models/ directory.`);\n return {\n source: 'model',\n table: match.name,\n columns: match.columns,\n durationMs: 0,\n };\n }\n\n case 'db':\n return describeFromDb(projectDir, table, connectionName);\n\n case 'auto': {\n const catalogResult = await describeFromCatalog(projectDir, table);\n if (catalogResult) return catalogResult;\n\n const modelResult = await describeFromModel(projectDir, table);\n if (modelResult) return modelResult;\n\n return describeFromDb(projectDir, table, connectionName);\n }\n }\n}\n\n// --- TABLES ---\n\nasync function tablesFromCatalog(projectDir: string): Promise<TablesSourceResult | null> {\n const catalog = await loadCatalog(projectDir);\n if (!catalog?.models?.length) return null;\n\n const tables: NormalizedTable[] = catalog.models.map((m) => {\n const parts = (m.table || m.name).split('.');\n return {\n schema: parts.length > 1 ? parts.slice(0, -1).join('.') : '',\n name: parts[parts.length - 1],\n type: m.source === 'dbt-source' ? 'SOURCE' : 'TABLE',\n };\n });\n\n return { source: 'catalog', tables, durationMs: 0 };\n}\n\nasync function tablesFromModel(projectDir: string): Promise<TablesSourceResult | null> {\n const models = await scanModels(projectDir);\n if (models.length === 0) return null;\n\n const tables: NormalizedTable[] = models.map((m) => ({\n schema: '',\n name: m.name,\n type: 'MODEL',\n }));\n\n return { source: 'model', tables, durationMs: 0 };\n}\n\nasync function tablesFromDb(\n projectDir: string,\n connectionName?: string,\n options?: { schema?: string; database?: string },\n): Promise<TablesSourceResult> {\n const connection = await resolveConnection(projectDir, connectionName);\n const connector = createConnector(connection, projectDir);\n\n try {\n await connector.connect();\n const query = getTablesQuery(connection.type, options);\n const start = performance.now();\n const result = await connector.execute(query.sql);\n const tables = query.normalize(result.rows);\n const durationMs = Math.round((performance.now() - start) * 100) / 100;\n\n return {\n source: 'db',\n tables,\n connectionName: connection.name,\n connectionType: connection.type,\n durationMs,\n };\n } finally {\n await connector.disconnect();\n }\n}\n\nexport async function resolveTablesSource(\n projectDir: string,\n source: SourceType,\n connectionName?: string,\n options?: { schema?: string; database?: string },\n): Promise<TablesSourceResult> {\n switch (source) {\n case 'catalog': {\n const catalog = await loadCatalog(projectDir);\n if (!catalog) throw new Error('No catalog found. Run `yamchart sync-dbt` or `yamchart sync-warehouse` to populate it.');\n const result = await tablesFromCatalog(projectDir);\n return result || { source: 'catalog', tables: [], durationMs: 0 };\n }\n\n case 'model': {\n const result = await tablesFromModel(projectDir);\n return result || { source: 'model', tables: [], durationMs: 0 };\n }\n\n case 'db':\n return tablesFromDb(projectDir, connectionName, options);\n\n case 'auto': {\n const catalogResult = await tablesFromCatalog(projectDir);\n if (catalogResult) return catalogResult;\n\n const modelResult = await tablesFromModel(projectDir);\n if (modelResult) return modelResult;\n\n return tablesFromDb(projectDir, connectionName, options);\n }\n }\n}\n\n// --- SEARCH ---\n\nfunction searchCatalog(catalog: CatalogFile, keyword: string): SearchResult[] {\n const results: SearchResult[] = [];\n const lower = keyword.toLowerCase();\n\n for (const model of catalog.models || []) {\n const tableParts = (model.table || model.name).split('.');\n const schema = tableParts.length > 1 ? tableParts.slice(0, -1).join('.') : '';\n const tableName = tableParts[tableParts.length - 1];\n\n if (model.name.toLowerCase().includes(lower) || tableName.toLowerCase().includes(lower)) {\n results.push({ type: 'table', schema, table: model.name });\n }\n\n for (const col of model.columns || []) {\n if (col.name.toLowerCase().includes(lower)) {\n results.push({\n type: 'column',\n schema,\n table: model.name,\n column: col.name,\n columnType: col.data_type,\n });\n }\n }\n }\n\n return results;\n}\n\nasync function searchFromDb(\n projectDir: string,\n keyword: string,\n connectionName?: string,\n): Promise<SearchSourceResult> {\n const connection = await resolveConnection(projectDir, connectionName);\n const connector = createConnector(connection, projectDir);\n\n try {\n await connector.connect();\n const query = getSearchQuery(connection.type, keyword);\n const startTime = performance.now();\n const result = await connector.execute(query.sql);\n const durationMs = performance.now() - startTime;\n const results = query.normalize(result.rows as Record<string, unknown>[]);\n\n return {\n source: 'db',\n keyword,\n results,\n connectionName: connection.name,\n connectionType: connection.type,\n durationMs,\n };\n } finally {\n await connector.disconnect();\n }\n}\n\nexport async function resolveSearchSource(\n projectDir: string,\n keyword: string,\n source: SourceType,\n connectionName?: string,\n): Promise<SearchSourceResult> {\n switch (source) {\n case 'catalog': {\n const catalog = await loadCatalog(projectDir);\n if (!catalog) throw new Error('No catalog found. Run `yamchart sync-dbt` or `yamchart sync-warehouse` to populate it.');\n return { source: 'catalog', keyword, results: searchCatalog(catalog, keyword), durationMs: 0 };\n }\n\n case 'model': {\n const models = await scanModels(projectDir);\n const lower = keyword.toLowerCase();\n const results: SearchResult[] = [];\n\n for (const model of models) {\n if (model.name.toLowerCase().includes(lower)) {\n results.push({ type: 'table', schema: '', table: model.name });\n }\n for (const col of model.columns) {\n if (col.name.toLowerCase().includes(lower)) {\n results.push({ type: 'column', schema: '', table: model.name, column: col.name, columnType: col.type });\n }\n }\n }\n\n return { source: 'model', keyword, results, durationMs: 0 };\n }\n\n case 'db':\n return searchFromDb(projectDir, keyword, connectionName);\n\n case 'auto': {\n const catalog = await loadCatalog(projectDir);\n if (catalog?.models?.length) {\n const results = searchCatalog(catalog, keyword);\n if (results.length > 0) {\n return { source: 'catalog', keyword, results, durationMs: 0 };\n }\n }\n\n const models = await scanModels(projectDir);\n if (models.length > 0) {\n const lower = keyword.toLowerCase();\n const results: SearchResult[] = [];\n for (const model of models) {\n if (model.name.toLowerCase().includes(lower)) {\n results.push({ type: 'table', schema: '', table: model.name });\n }\n for (const col of model.columns) {\n if (col.name.toLowerCase().includes(lower)) {\n results.push({ type: 'column', schema: '', table: model.name, column: col.name, columnType: col.type });\n }\n }\n }\n if (results.length > 0) {\n return { source: 'model', keyword, results, durationMs: 0 };\n }\n }\n\n return searchFromDb(projectDir, keyword, connectionName);\n }\n }\n}\n","import { readFile, readdir, access } from 'fs/promises';\nimport { join, extname } from 'path';\nimport type { NormalizedColumn } from './introspection.js';\n\nexport interface ParsedModel {\n name: string;\n description?: string;\n columns: NormalizedColumn[];\n}\n\n/**\n * Parse @name, @description, and @returns from a SQL model file's content.\n * Returns null if no @name annotation is found.\n */\nexport function parseModelReturns(sql: string): ParsedModel | null {\n const nameMatch = sql.match(/--\\s*@name:\\s*(.+)/);\n if (!nameMatch?.[1]) return null;\n\n const name = nameMatch[1].trim();\n\n const descMatch = sql.match(/--\\s*@description:\\s*(.+)/);\n const description = descMatch?.[1]?.trim();\n\n const columns: NormalizedColumn[] = [];\n\n // Find @returns: block and parse each -- - name: type line\n const returnsMatch = sql.match(/--\\s*@returns:\\s*\\n((?:\\s*--\\s+-\\s+.+\\n?)*)/);\n if (returnsMatch?.[1]) {\n const lines = returnsMatch[1].split('\\n');\n for (const line of lines) {\n const colMatch = line.match(/--\\s+-\\s+(\\w+)(?:\\s*:\\s*(\\w+))?/);\n if (colMatch?.[1]) {\n columns.push({\n name: colMatch[1],\n type: colMatch[2] || 'unknown',\n nullable: 'YES',\n });\n }\n }\n }\n\n return { name, description, columns };\n}\n\n/**\n * Recursively find all .sql files in a directory.\n */\nasync function findSqlFiles(dir: string): Promise<string[]> {\n const files: string[] = [];\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...await findSqlFiles(fullPath));\n } else if (extname(entry.name) === '.sql') {\n files.push(fullPath);\n }\n }\n\n return files;\n}\n\n/**\n * Scan models/ directory for SQL files, parse @name and @returns annotations.\n * Returns array of ParsedModel for files that have @name.\n */\nexport async function scanModels(projectDir: string): Promise<ParsedModel[]> {\n const modelsDir = join(projectDir, 'models');\n\n try {\n await access(modelsDir);\n } catch {\n return [];\n }\n\n const sqlFiles = await findSqlFiles(modelsDir);\n const models: ParsedModel[] = [];\n\n for (const filePath of sqlFiles) {\n const content = await readFile(filePath, 'utf-8');\n const parsed = parseModelReturns(content);\n if (parsed) {\n models.push(parsed);\n }\n }\n\n return models;\n}\n"],"mappings":"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","names":["readFile","access","join","join","access","readFile"]}
|
|
@@ -1329,6 +1329,76 @@ function resolveSnowflakeAuth(connection) {
|
|
|
1329
1329
|
throw new Error(`Auth type "${auth.type}" not yet implemented for Snowflake`);
|
|
1330
1330
|
}
|
|
1331
1331
|
|
|
1332
|
+
// ../../packages/query/dist/connectors/reconnecting.js
|
|
1333
|
+
var CONNECTION_ERROR_PATTERNS = [
|
|
1334
|
+
"terminated connection",
|
|
1335
|
+
"socket hang up",
|
|
1336
|
+
"connection reset",
|
|
1337
|
+
"ECONNRESET",
|
|
1338
|
+
"ECONNREFUSED",
|
|
1339
|
+
"ETIMEDOUT",
|
|
1340
|
+
"connection lost",
|
|
1341
|
+
"gone away",
|
|
1342
|
+
// MySQL: "server has gone away"
|
|
1343
|
+
"not connected"
|
|
1344
|
+
];
|
|
1345
|
+
function isConnectionError(error) {
|
|
1346
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1347
|
+
const lower = message.toLowerCase();
|
|
1348
|
+
return CONNECTION_ERROR_PATTERNS.some((pattern) => lower.includes(pattern.toLowerCase()));
|
|
1349
|
+
}
|
|
1350
|
+
var ReconnectingConnector = class {
|
|
1351
|
+
inner;
|
|
1352
|
+
constructor(inner) {
|
|
1353
|
+
this.inner = inner;
|
|
1354
|
+
}
|
|
1355
|
+
async connect() {
|
|
1356
|
+
return this.inner.connect();
|
|
1357
|
+
}
|
|
1358
|
+
async disconnect() {
|
|
1359
|
+
return this.inner.disconnect();
|
|
1360
|
+
}
|
|
1361
|
+
isConnected() {
|
|
1362
|
+
return this.inner.isConnected();
|
|
1363
|
+
}
|
|
1364
|
+
async execute(sql) {
|
|
1365
|
+
await this.ensureConnected();
|
|
1366
|
+
try {
|
|
1367
|
+
return await this.inner.execute(sql);
|
|
1368
|
+
} catch (err) {
|
|
1369
|
+
if (isConnectionError(err)) {
|
|
1370
|
+
await this.reconnect();
|
|
1371
|
+
return this.inner.execute(sql);
|
|
1372
|
+
}
|
|
1373
|
+
throw err;
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
async explain(sql) {
|
|
1377
|
+
await this.ensureConnected();
|
|
1378
|
+
try {
|
|
1379
|
+
return await this.inner.explain(sql);
|
|
1380
|
+
} catch (err) {
|
|
1381
|
+
if (isConnectionError(err)) {
|
|
1382
|
+
await this.reconnect();
|
|
1383
|
+
return this.inner.explain(sql);
|
|
1384
|
+
}
|
|
1385
|
+
throw err;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
async ensureConnected() {
|
|
1389
|
+
if (!this.inner.isConnected()) {
|
|
1390
|
+
await this.reconnect();
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
async reconnect() {
|
|
1394
|
+
try {
|
|
1395
|
+
await this.inner.disconnect();
|
|
1396
|
+
} catch {
|
|
1397
|
+
}
|
|
1398
|
+
await this.inner.connect();
|
|
1399
|
+
}
|
|
1400
|
+
};
|
|
1401
|
+
|
|
1332
1402
|
// ../../packages/query/dist/connectors/index.js
|
|
1333
1403
|
function serializeDateValue(value) {
|
|
1334
1404
|
if (value.getUTCHours() === 0 && value.getUTCMinutes() === 0 && value.getUTCSeconds() === 0 && value.getUTCMilliseconds() === 0) {
|
|
@@ -1516,6 +1586,7 @@ export {
|
|
|
1516
1586
|
resolvePostgresAuth,
|
|
1517
1587
|
resolveMySQLAuth,
|
|
1518
1588
|
resolveSnowflakeAuth,
|
|
1589
|
+
ReconnectingConnector,
|
|
1519
1590
|
serializeDateValue,
|
|
1520
1591
|
expandThis,
|
|
1521
1592
|
runAssertion,
|
|
@@ -1524,4 +1595,4 @@ export {
|
|
|
1524
1595
|
checkSchema,
|
|
1525
1596
|
VERSION
|
|
1526
1597
|
};
|
|
1527
|
-
//# sourceMappingURL=chunk-
|
|
1598
|
+
//# sourceMappingURL=chunk-5N3FYFBV.js.map
|