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); });