From 14d31a43582e463e057090b44590f741a0124be3 Mon Sep 17 00:00:00 2001 From: Shivam Raj <171748731+shivam2680@users.noreply.github.com> Date: Sat, 8 Feb 2025 01:14:10 +0530 Subject: [PATCH 1/5] updated py version for node14 testing (#278) Signed-off-by: Shivam Raj --- .github/workflows/main.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 64a5dfd0..e854e459 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -45,6 +45,11 @@ jobs: with: node-version: ${{ matrix.node-version }} - uses: actions/checkout@v3 + - name: Set up Python 3.10 for Node 14 + if: ${{ matrix.node-version == '14' }} + uses: actions/setup-python@v4 + with: + python-version: '3.10' - name: Cache node modules uses: actions/cache@v3 with: From 771fb3b2b34a90a5b8cb8f15c3c379692bc7e955 Mon Sep 17 00:00:00 2001 From: Shivam Raj <171748731+shivam2680@users.noreply.github.com> Date: Sat, 8 Feb 2025 01:26:47 +0530 Subject: [PATCH 2/5] removed clientId from userAgent string (#277) Signed-off-by: Shivam Raj --- lib/DBSQLClient.ts | 2 +- lib/utils/buildUserAgentString.ts | 4 ++-- tests/unit/utils/utils.test.ts | 34 ++++++++++++++----------------- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/lib/DBSQLClient.ts b/lib/DBSQLClient.ts index d3d9427c..923608ae 100644 --- a/lib/DBSQLClient.ts +++ b/lib/DBSQLClient.ts @@ -111,7 +111,7 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I socketTimeout: options.socketTimeout, proxy: options.proxy, headers: { - 'User-Agent': buildUserAgentString(options.clientId), + 'User-Agent': buildUserAgentString(), }, }; } diff --git a/lib/utils/buildUserAgentString.ts b/lib/utils/buildUserAgentString.ts index ce26fcfd..b6932f81 100644 --- a/lib/utils/buildUserAgentString.ts +++ b/lib/utils/buildUserAgentString.ts @@ -11,7 +11,7 @@ function getOperatingSystemVersion(): string { return `${os.type()} ${os.release()}`; } -export default function buildUserAgentString(clientId?: string): string { - const extra = [clientId, getNodeVersion(), getOperatingSystemVersion()].filter(Boolean); +export default function buildUserAgentString(): string { + const extra = [getNodeVersion(), getOperatingSystemVersion()].filter(Boolean); return `${productName}/${packageVersion} (${extra.join('; ')})`; } diff --git a/tests/unit/utils/utils.test.ts b/tests/unit/utils/utils.test.ts index f94e88c4..d76e480f 100644 --- a/tests/unit/utils/utils.test.ts +++ b/tests/unit/utils/utils.test.ts @@ -17,16 +17,16 @@ const progressUpdateResponseStub: TProgressUpdateResp = { describe('buildUserAgentString', () => { // It should follow https://www.rfc-editor.org/rfc/rfc7231#section-5.5.3 and // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent + // UserAgent ::= '/' '(' ')' + // where: + // is "NodejsDatabricksSqlConnector" + // is three period-separated digits (optionally with a suffix) + // is "Node.js ; " // - // UserAgent ::= '/' '(' ')' - // ProductName ::= 'NodejsDatabricksSqlConnector' - // ::= [ ';' ] 'Node.js' ';' - // - // Examples: - // - with provided: NodejsDatabricksSqlConnector/0.1.8-beta.1 (Client ID; Node.js 16.13.1; Darwin 21.5.0) - // - without provided: NodejsDatabricksSqlConnector/0.1.8-beta.1 (Node.js 16.13.1; Darwin 21.5.0) + // Example: + // - NodejsDatabricksSqlConnector/0.1.8-beta.1 (Node.js 16.13.1; Darwin 21.5.0) - function checkUserAgentString(ua: string, clientId?: string) { + function checkUserAgentString(ua: string) { // Prefix: 'NodejsDatabricksSqlConnector/' // Version: three period-separated digits and optional suffix const re = @@ -36,20 +36,16 @@ describe('buildUserAgentString', () => { const { comment } = match?.groups ?? {}; - expect(comment.split(';').length).to.be.gte(2); // at least Node and OS version should be there + const parts = comment.split(';').map((s) => s.trim()); + expect(parts.length).to.be.gte(2); // at least Node and OS version should be there - if (clientId) { - expect(comment.trim()).to.satisfy((s: string) => s.startsWith(`${clientId};`)); - } + // First part should start with "Node.js" followed by a version number. + expect(parts[0]).to.match(/^Node\.js\s+\d+\.\d+\.\d+/); + // Second part should represent the OS platform (a word) and OS version. + expect(parts[1]).to.match(/^\w+/); } - it('matches pattern with clientId', () => { - const clientId = 'Some Client ID'; - const ua = buildUserAgentString(clientId); - checkUserAgentString(ua, clientId); - }); - - it('matches pattern without clientId', () => { + it('matches pattern', () => { const ua = buildUserAgentString(); checkUserAgentString(ua); }); From 538bf7a84243a388e9e636964494c2010cc29fa5 Mon Sep 17 00:00:00 2001 From: Shivam Raj <171748731+shivam2680@users.noreply.github.com> Date: Thu, 20 Feb 2025 12:58:06 +0530 Subject: [PATCH 3/5] renamed clientId to userAgentHeader in connect args (#281) Signed-off-by: Shivam Raj --- examples/repl | 2 +- lib/DBSQLClient.ts | 2 +- lib/contracts/IDBSQLClient.ts | 2 +- lib/utils/buildUserAgentString.ts | 4 ++-- tests/unit/utils/utils.test.ts | 31 +++++++++++++++++++------------ 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/examples/repl b/examples/repl index d214549c..c546511b 100755 --- a/examples/repl +++ b/examples/repl @@ -15,7 +15,7 @@ async function initClient({ host, endpointId, token }) { host, path: `/sql/2.0/warehouses/${endpointId}`, token, - clientId: 'REPL', + userAgentEntry: 'REPL', }); } diff --git a/lib/DBSQLClient.ts b/lib/DBSQLClient.ts index 923608ae..ead39d9e 100644 --- a/lib/DBSQLClient.ts +++ b/lib/DBSQLClient.ts @@ -111,7 +111,7 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I socketTimeout: options.socketTimeout, proxy: options.proxy, headers: { - 'User-Agent': buildUserAgentString(), + 'User-Agent': buildUserAgentString(options.userAgentEntry), }, }; } diff --git a/lib/contracts/IDBSQLClient.ts b/lib/contracts/IDBSQLClient.ts index 0c0cee89..73fedde1 100644 --- a/lib/contracts/IDBSQLClient.ts +++ b/lib/contracts/IDBSQLClient.ts @@ -30,7 +30,7 @@ export type ConnectionOptions = { host: string; port?: number; path: string; - clientId?: string; + userAgentEntry?: string; socketTimeout?: number; proxy?: ProxyOptions; } & AuthOptions; diff --git a/lib/utils/buildUserAgentString.ts b/lib/utils/buildUserAgentString.ts index b6932f81..1cbbf177 100644 --- a/lib/utils/buildUserAgentString.ts +++ b/lib/utils/buildUserAgentString.ts @@ -11,7 +11,7 @@ function getOperatingSystemVersion(): string { return `${os.type()} ${os.release()}`; } -export default function buildUserAgentString(): string { - const extra = [getNodeVersion(), getOperatingSystemVersion()].filter(Boolean); +export default function buildUserAgentString(userAgentEntry?: string): string { + const extra = [userAgentEntry, getNodeVersion(), getOperatingSystemVersion()].filter(Boolean); return `${productName}/${packageVersion} (${extra.join('; ')})`; } diff --git a/tests/unit/utils/utils.test.ts b/tests/unit/utils/utils.test.ts index d76e480f..6f0369b2 100644 --- a/tests/unit/utils/utils.test.ts +++ b/tests/unit/utils/utils.test.ts @@ -17,16 +17,18 @@ const progressUpdateResponseStub: TProgressUpdateResp = { describe('buildUserAgentString', () => { // It should follow https://www.rfc-editor.org/rfc/rfc7231#section-5.5.3 and // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent - // UserAgent ::= '/' '(' ')' + // + // UserAgent ::= '/' '(' ')' // where: - // is "NodejsDatabricksSqlConnector" - // is three period-separated digits (optionally with a suffix) - // is "Node.js ; " + // ProductName ::= 'NodejsDatabricksSqlConnector' + // ProductVersion ::= three period-separated digits + // ::= [ ';' ] 'Node.js' ';' // - // Example: - // - NodejsDatabricksSqlConnector/0.1.8-beta.1 (Node.js 16.13.1; Darwin 21.5.0) + // Examples: + // - with provided: NodejsDatabricksSqlConnector/0.1.8-beta.1 (; Node.js 16.13.1; Darwin 21.5.0) + // - without provided: NodejsDatabricksSqlConnector/0.1.8-beta.1 (Node.js 16.13.1; Darwin 21.5.0) - function checkUserAgentString(ua: string) { + function checkUserAgentString(ua: string, userAgentEntry?: string) { // Prefix: 'NodejsDatabricksSqlConnector/' // Version: three period-separated digits and optional suffix const re = @@ -39,13 +41,18 @@ describe('buildUserAgentString', () => { const parts = comment.split(';').map((s) => s.trim()); expect(parts.length).to.be.gte(2); // at least Node and OS version should be there - // First part should start with "Node.js" followed by a version number. - expect(parts[0]).to.match(/^Node\.js\s+\d+\.\d+\.\d+/); - // Second part should represent the OS platform (a word) and OS version. - expect(parts[1]).to.match(/^\w+/); + if (userAgentEntry) { + expect(comment.trim()).to.satisfy((s: string) => s.startsWith(`${userAgentEntry};`)); + } } - it('matches pattern', () => { + it('matches pattern with userAgentEntry', () => { + const userAgentEntry = 'Some user agent'; + const ua = buildUserAgentString(userAgentEntry); + checkUserAgentString(ua, userAgentEntry); + }); + + it('matches pattern without userAgentEntry', () => { const ua = buildUserAgentString(); checkUserAgentString(ua); }); From cd43bcf710a6f1074a2f380c43e280e3e6e90018 Mon Sep 17 00:00:00 2001 From: Shivam Raj <171748731+shivam2680@users.noreply.github.com> Date: Wed, 12 Mar 2025 09:44:19 +0530 Subject: [PATCH 4/5] Give warning for deprecated clientId param (#282) * renamed clientId to userAgentHeader in connect args * add warning for deprecated clientId param * add backward compatibility --- lib/DBSQLClient.ts | 11 +++++++++++ lib/utils/buildUserAgentString.ts | 14 ++++++++++++++ tests/unit/DBSQLClient.test.ts | 19 +++++++++++++++++++ tests/unit/utils/utils.test.ts | 6 ++++++ 4 files changed, 50 insertions(+) diff --git a/lib/DBSQLClient.ts b/lib/DBSQLClient.ts index ead39d9e..85888d16 100644 --- a/lib/DBSQLClient.ts +++ b/lib/DBSQLClient.ts @@ -160,6 +160,17 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I * const session = client.connect({host, path, token}); */ public async connect(options: ConnectionOptions, authProvider?: IAuthentication): Promise { + const deprecatedClientId = (options as any).clientId; + if (deprecatedClientId !== undefined) { + this.logger.log( + LogLevel.warn, + 'Warning: The "clientId" option is deprecated. Please use "userAgentEntry" instead.', + ); + if (!options.userAgentEntry) { + options.userAgentEntry = deprecatedClientId; + } + } + this.authProvider = this.createAuthProvider(options, authProvider); this.connectionProvider = this.createConnectionProvider(options); diff --git a/lib/utils/buildUserAgentString.ts b/lib/utils/buildUserAgentString.ts index 1cbbf177..cd021e93 100644 --- a/lib/utils/buildUserAgentString.ts +++ b/lib/utils/buildUserAgentString.ts @@ -11,7 +11,21 @@ function getOperatingSystemVersion(): string { return `${os.type()} ${os.release()}`; } +function redactInternalToken(userAgentEntry: string): string { + const internalTokenPrefixes = ['dkea', 'dskea', 'dapi', 'dsapi', 'dose']; + for (const prefix of internalTokenPrefixes) { + if (userAgentEntry.startsWith(prefix)) { + return ''; + } + } + return userAgentEntry; +} + export default function buildUserAgentString(userAgentEntry?: string): string { + if (userAgentEntry) { + userAgentEntry = redactInternalToken(userAgentEntry); + } + const extra = [userAgentEntry, getNodeVersion(), getOperatingSystemVersion()].filter(Boolean); return `${productName}/${packageVersion} (${extra.join('; ')})`; } diff --git a/tests/unit/DBSQLClient.test.ts b/tests/unit/DBSQLClient.test.ts index 5caf8420..f4ac593f 100644 --- a/tests/unit/DBSQLClient.test.ts +++ b/tests/unit/DBSQLClient.test.ts @@ -79,6 +79,25 @@ describe('DBSQLClient.connect', () => { expect(thriftConnectionStub.on.called).to.be.true; }); + + it('should log a warning when deprecated clientId is passed', async () => { + const client = new DBSQLClient(); + const logSpy = sinon.spy((client as any).logger, 'log'); + + const optionsWithDeprecated = { + ...connectOptions, + clientId: 'clientId', + }; + + await client.connect(optionsWithDeprecated as any); + + const warningRegex = /Warning: The "clientId" option is deprecated\. Please use "userAgentEntry" instead\./; + const callFound = logSpy.getCalls().some((call) => warningRegex.test(call.args[1])); + + expect(callFound).to.be.true; + + logSpy.restore(); + }); }); describe('DBSQLClient.openSession', () => { diff --git a/tests/unit/utils/utils.test.ts b/tests/unit/utils/utils.test.ts index 6f0369b2..ed96326e 100644 --- a/tests/unit/utils/utils.test.ts +++ b/tests/unit/utils/utils.test.ts @@ -56,6 +56,12 @@ describe('buildUserAgentString', () => { const ua = buildUserAgentString(); checkUserAgentString(ua); }); + + it('should redact internal token in userAgentEntry', () => { + const userAgentEntry = 'dkea-internal-token'; + const userAgentString = buildUserAgentString(userAgentEntry); + expect(userAgentString).to.include(''); + }); }); describe('formatProgress', () => { From 6d6dd8b4c20aaccd5afb3359e1a4a68e1392a708 Mon Sep 17 00:00:00 2001 From: Shivam Raj <171748731+shivam2680@users.noreply.github.com> Date: Wed, 12 Mar 2025 22:09:47 +0530 Subject: [PATCH 5/5] prepare release 1.10.0 (#283) Signed-off-by: Shivam Raj --- CHANGELOG.md | 4 ++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b49dd8bd..0d13bf63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Release History +## 1.10.0 + +- Rename `clientId` parameter to `userAgentEntry` in connect call to standardize across sql drivers (databricks/databricks-sql-nodejs#281) + ## 1.9.0 - Support iterable interface for IOperation (databricks/databricks-sql-nodejs#252) diff --git a/package-lock.json b/package-lock.json index 36f6317d..ad6c2729 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@databricks/sql", - "version": "1.9.0", + "version": "1.10.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@databricks/sql", - "version": "1.9.0", + "version": "1.10.0", "license": "Apache 2.0", "dependencies": { "apache-arrow": "^13.0.0", diff --git a/package.json b/package.json index 74f608eb..25b875dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@databricks/sql", - "version": "1.9.0", + "version": "1.10.0", "description": "Driver for connection to Databricks SQL via Thrift API.", "main": "dist/index.js", "types": "dist/index.d.ts",