Skip to content

Commit 4232436

Browse files
amansingh63claude
andcommitted
merge: sync upstream bytebase/dbhub main (0.21.1)
Upstream changes: - Make @aws-sdk/rds-signer and @azure/identity optional (bytebase#298) - Fix PostgreSQL view comments in getTableComment() (bytebase#297) - Version bump 0.21.0 → 0.21.1 Conflicts resolved: README.md, package.json, server.json, tsup.config.ts (kept dbhub-analytics branding, merged upstream code changes) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c45c3ca commit 4232436

8 files changed

Lines changed: 69 additions & 10 deletions

File tree

frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@dbhub-analytics/frontend",
33
"private": true,
4-
"version": "0.21.0",
4+
"version": "0.21.1",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@
4040
"author": "amansingh63",
4141
"license": "MIT",
4242
"dependencies": {
43-
"@aws-sdk/rds-signer": "^3.1001.0",
44-
"@azure/identity": "^4.8.0",
4543
"@iarna/toml": "^2.2.5",
4644
"@modelcontextprotocol/sdk": "^1.25.1",
4745
"dotenv": "^16.4.7",
@@ -51,6 +49,8 @@
5149
"zod": "^3.24.2"
5250
},
5351
"optionalDependencies": {
52+
"@aws-sdk/rds-signer": "^3.1001.0",
53+
"@azure/identity": "^4.8.0",
5454
"@databricks/sql": "^1.13.0",
5555
"@google-cloud/bigquery": "^8.1.1",
5656
"better-sqlite3": "^11.9.0",

src/connectors/__tests__/postgres.integration.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ class PostgreSQLIntegrationTest extends IntegrationTestBase<PostgreSQLTestContai
167167
ON CONFLICT DO NOTHING
168168
`, {});
169169

170+
// Create a view with a comment (for view comment test)
171+
await connector.executeSQL(`
172+
CREATE OR REPLACE VIEW active_users AS SELECT id, name, email FROM users WHERE age >= 25
173+
`, {});
174+
await connector.executeSQL(`COMMENT ON VIEW active_users IS 'Users aged 25 or older'`, {});
175+
170176
// Create test stored procedures using SQL language to avoid dollar quoting
171177
await connector.executeSQL(`
172178
CREATE OR REPLACE FUNCTION get_user_count()
@@ -245,6 +251,11 @@ describe('PostgreSQL Connector Integration Tests', () => {
245251
expect(result.rows[0].array_val).toBeDefined();
246252
});
247253

254+
it('should return comment for views via getTableComment', async () => {
255+
const comment = await postgresTest.connector.getTableComment!('active_users');
256+
expect(comment).toBe('Users aged 25 or older');
257+
});
258+
248259
it('should handle PostgreSQL returning clause', async () => {
249260
const result = await postgresTest.connector.executeSQL(
250261
"INSERT INTO users (name, email, age) VALUES ('Returning Test', 'returning@example.com', 40) RETURNING id, name",

src/connectors/postgres/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ export class PostgresConnector implements Connector {
382382
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
383383
WHERE c.relname = $1
384384
AND n.nspname = $2
385-
AND c.relkind IN ('r','p','m','f')
385+
AND c.relkind IN ('r','p','m','f','v')
386386
`,
387387
[tableName, schemaToUse]
388388
);

src/connectors/sqlserver/index.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
ExecuteOptions,
1212
ConnectorConfig,
1313
} from "../interface.js";
14-
import { DefaultAzureCredential } from "@azure/identity";
14+
import { isDriverNotInstalled } from "../../utils/module-loader.js";
1515
import { SafeURL } from "../../utils/safe-url.js";
1616
import { obfuscateDSNPassword } from "../../utils/dsn-obfuscate.js";
1717
import { SQLRowLimiter } from "../../utils/sql-row-limiter.js";
@@ -94,6 +94,17 @@ export class SQLServerDSNParser implements DSNParser {
9494
// Handle authentication types
9595
switch (options.authentication) {
9696
case "azure-active-directory-access-token": {
97+
let DefaultAzureCredential: typeof import("@azure/identity")["DefaultAzureCredential"];
98+
try {
99+
({ DefaultAzureCredential } = await import("@azure/identity"));
100+
} catch (importError) {
101+
if (isDriverNotInstalled(importError, "@azure/identity")) {
102+
throw new Error(
103+
'Azure AD authentication requires the "@azure/identity" package. Install it with: pnpm add @azure/identity'
104+
);
105+
}
106+
throw importError;
107+
}
97108
try {
98109
const credential = new DefaultAzureCredential();
99110
const token = await credential.getToken("https://database.windows.net/");
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { isDriverNotInstalled } from '../module-loader.js';
3+
4+
describe('isDriverNotInstalled with scoped packages', () => {
5+
it('should match ERR_MODULE_NOT_FOUND for @aws-sdk/rds-signer', () => {
6+
const err = new Error(
7+
"Cannot find package '@aws-sdk/rds-signer' imported from /fake/path"
8+
);
9+
(err as NodeJS.ErrnoException).code = 'ERR_MODULE_NOT_FOUND';
10+
11+
expect(isDriverNotInstalled(err, '@aws-sdk/rds-signer')).toBe(true);
12+
});
13+
14+
it('should not match unrelated ERR_MODULE_NOT_FOUND errors', () => {
15+
const err = new Error(
16+
"Cannot find package 'some-other-pkg' imported from /fake/path"
17+
);
18+
(err as NodeJS.ErrnoException).code = 'ERR_MODULE_NOT_FOUND';
19+
20+
expect(isDriverNotInstalled(err, '@aws-sdk/rds-signer')).toBe(false);
21+
});
22+
});

src/utils/aws-rds-signer.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Signer } from "@aws-sdk/rds-signer";
1+
import { isDriverNotInstalled } from "./module-loader.js";
22

33
export interface RdsAuthTokenParams {
44
hostname: string;
@@ -13,6 +13,18 @@ export interface RdsAuthTokenParams {
1313
* (AWS CLI profile, env vars, instance role, etc.).
1414
*/
1515
export async function generateRdsAuthToken(params: RdsAuthTokenParams): Promise<string> {
16+
let Signer: typeof import("@aws-sdk/rds-signer")["Signer"];
17+
try {
18+
({ Signer } = await import("@aws-sdk/rds-signer"));
19+
} catch (error) {
20+
if (isDriverNotInstalled(error, "@aws-sdk/rds-signer")) {
21+
throw new Error(
22+
'AWS IAM authentication requires the "@aws-sdk/rds-signer" package. Install it with: pnpm add @aws-sdk/rds-signer'
23+
);
24+
}
25+
throw error;
26+
}
27+
1628
const signer = new Signer({
1729
hostname: params.hostname,
1830
port: params.port,

tsup.config.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ export default defineConfig({
88
dts: true,
99
clean: true,
1010
outDir: 'dist',
11-
// Database drivers are optionalDependencies loaded at runtime via dynamic
12-
// import(). They must be external so tsup does not bundle their CJS code
13-
// into ESM chunks (which causes "Dynamic require of X is not supported").
14-
external: ['pg', 'mysql2', 'mariadb', 'mssql', 'better-sqlite3', '@databricks/sql', '@google-cloud/bigquery'],
11+
// Optional runtime-loaded dependencies (database drivers and cloud auth
12+
// packages) are declared as optionalDependencies and loaded via dynamic
13+
// import(). Database drivers must be external so tsup does not bundle their
14+
// CJS code into ESM chunks (which causes "Dynamic require of X is not
15+
// supported"). Cloud auth packages are externalized to keep their large
16+
// dependency trees out of the bundle.
17+
external: ['pg', 'mysql2', 'mariadb', 'mssql', 'better-sqlite3', '@databricks/sql', '@google-cloud/bigquery', '@aws-sdk/rds-signer', '@azure/identity'],
1518
// Copy the employee-sqlite demo data to dist
1619
async onSuccess() {
1720
// Create target directory

0 commit comments

Comments
 (0)