diff --git a/packages/bolt-connection/src/bolt/request-message.js b/packages/bolt-connection/src/bolt/request-message.js index 4da2e2a5e..6ee13651d 100644 --- a/packages/bolt-connection/src/bolt/request-message.js +++ b/packages/bolt-connection/src/bolt/request-message.js @@ -200,12 +200,21 @@ export default class RequestMessage { * @return {RequestMessage} new HELLO message. */ static hello5x3 (userAgent, boltAgent, notificationFilter = null, routing = null) { - const metadata = { bolt_agent: boltAgent } + const metadata = { } if (userAgent) { metadata.user_agent = userAgent } + if (boltAgent) { + metadata.bolt_agent = { + product: boltAgent.product, + platform: boltAgent.platform, + language: boltAgent.language, + language_details: boltAgent.languageDetails + } + } + if (notificationFilter) { if (notificationFilter.minimumSeverityLevel) { metadata.notifications_minimum_severity = notificationFilter.minimumSeverityLevel diff --git a/packages/bolt-connection/test/bolt/bolt-protocol-v5x3.test.js b/packages/bolt-connection/test/bolt/bolt-protocol-v5x3.test.js index 4b70b5891..c4cd84ce6 100644 --- a/packages/bolt-connection/test/bolt/bolt-protocol-v5x3.test.js +++ b/packages/bolt-connection/test/bolt/bolt-protocol-v5x3.test.js @@ -268,7 +268,11 @@ describe('#unit BoltProtocolV5x3', () => { utils.spyProtocolWrite(protocol) const clientName = 'js-driver/1.2.3' - const boltAgent = 'js-driver/1.2.3 (bolt agent)' + const boltAgent = { + product: 'neo4j-javascript/5.6', + platform: 'netbsd 1.1.1; Some arch', + languageDetails: 'Node/16.0.1 (v8 1.7.0)' + } const authToken = { username: 'neo4j', password: 'secret' } const observer = protocol.initialize({ userAgent: clientName, boltAgent: boltAgent, authToken }) @@ -306,14 +310,18 @@ describe('#unit BoltProtocolV5x3', () => { const protocol = new BoltProtocolV5x3(recorder, null, false) utils.spyProtocolWrite(protocol) - const clientName = 'js-driver/1.2.3' + const boltAgent = { + product: 'neo4j-javascript/5.6', + platform: 'netbsd 1.1.1; Some arch', + languageDetails: 'Node/16.0.1 (v8 1.7.0)' + } const authToken = { username: 'neo4j', password: 'secret' } - const observer = protocol.initialize({ userAgent, boltAgent: clientName, authToken }) + const observer = protocol.initialize({ userAgent, boltAgent, authToken }) protocol.verifyMessageCount(2) expect(protocol.messages[0]).toBeMessage( - RequestMessage.hello5x3(userAgent, clientName) + RequestMessage.hello5x3(userAgent, boltAgent) ) expect(protocol.messages[1]).toBeMessage( RequestMessage.logon(authToken) diff --git a/packages/bolt-connection/test/bolt/request-message.test.js b/packages/bolt-connection/test/bolt/request-message.test.js index 7f86f9d09..53d14c511 100644 --- a/packages/bolt-connection/test/bolt/request-message.test.js +++ b/packages/bolt-connection/test/bolt/request-message.test.js @@ -531,22 +531,125 @@ describe('#unit RequestMessage', () => { ) }) }) + }) - function notificationFilterFixtures () { - return notificationFilterBehaviour.notificationFilterFixture() - .map(notificationFilter => { - const expectedNotificationFilter = {} - if (notificationFilter) { - if (notificationFilter.minimumSeverityLevel) { - expectedNotificationFilter.notifications_minimum_severity = notificationFilter.minimumSeverityLevel - } - - if (notificationFilter.disabledCategories) { - expectedNotificationFilter.notifications_disabled_categories = notificationFilter.disabledCategories - } - } - return [notificationFilter, expectedNotificationFilter] - }) - } + describe('Bolt5.3', () => { + it('should create HELLO with NodeJS Bolt Agent', () => { + const userAgent = 'my-driver/1.0.2' + const boltAgent = { + product: 'neo4j-javascript/5.6', + platform: 'netbsd 1.1.1; Some arch', + languageDetails: 'Node/16.0.1 (v8 1.7.0)' + } + + const expectedFields = { + user_agent: userAgent, + bolt_agent: { + product: 'neo4j-javascript/5.6', + platform: 'netbsd 1.1.1; Some arch', + language_details: 'Node/16.0.1 (v8 1.7.0)' + } + } + + const message = RequestMessage.hello5x3(userAgent, boltAgent) + + expect(message.signature).toEqual(0x01) + expect(message.fields).toEqual([ + expectedFields + ]) + expect(message.toString()).toEqual( + `HELLO ${json.stringify(expectedFields)}` + ) + }) + + it('should create HELLO with Browser Bolt Agent', () => { + const userAgent = 'my-driver/1.0.2' + + const boltAgent = { + product: 'neo4j-javascript/5.3', + platform: 'Macintosh; Intel Mac OS X 10_15_7' + } + + const expectedFields = { + user_agent: userAgent, + bolt_agent: { + product: 'neo4j-javascript/5.3', + platform: 'Macintosh; Intel Mac OS X 10_15_7' + } + } + + const message = RequestMessage.hello5x3(userAgent, boltAgent) + + expect(message.signature).toEqual(0x01) + expect(message.fields).toEqual([ + expectedFields + ]) + expect(message.toString()).toEqual( + `HELLO ${json.stringify(expectedFields)}` + ) + }) + + it('should create HELLO with Deno Bolt Agent', () => { + const userAgent = 'my-driver/1.0.2' + + const boltAgent = { + product: 'neo4j-javascript/5.3', + platform: 'macos 14.1; myArch', + languageDetails: 'Deno/1.19.1 (v8 8.1.39)' + } + + const expectedFields = { + user_agent: userAgent, + bolt_agent: { + product: 'neo4j-javascript/5.3', + platform: 'macos 14.1; myArch', + language_details: 'Deno/1.19.1 (v8 8.1.39)' + } + } + + const message = RequestMessage.hello5x3(userAgent, boltAgent) + + expect(message.signature).toEqual(0x01) + expect(message.fields).toEqual([ + expectedFields + ]) + expect(message.toString()).toEqual( + `HELLO ${json.stringify(expectedFields)}` + ) + }) + + it.each( + notificationFilterFixtures() + )('should create HELLO message where notificationFilters=%o', (notificationFilter, expectedNotificationFilter) => { + const userAgent = 'my-driver/1.0.2' + const message = RequestMessage.hello5x3(userAgent, undefined, notificationFilter) + + const expectedFields = { user_agent: userAgent, ...expectedNotificationFilter } + + expect(message.signature).toEqual(0x01) + expect(message.fields).toEqual([ + expectedFields + ]) + expect(message.toString()).toEqual( + `HELLO ${json.stringify(expectedFields)}` + ) + }) }) + + function notificationFilterFixtures () { + return notificationFilterBehaviour.notificationFilterFixture() + .map(notificationFilter => { + const expectedNotificationFilter = {} + if (notificationFilter) { + if (notificationFilter.minimumSeverityLevel) { + expectedNotificationFilter.notifications_minimum_severity = notificationFilter.minimumSeverityLevel + } + + if (notificationFilter.disabledCategories) { + expectedNotificationFilter.notifications_disabled_categories = notificationFilter.disabledCategories + } + } + return [notificationFilter, expectedNotificationFilter] + }) + } }) diff --git a/packages/core/src/internal/bolt-agent/browser/bolt-agent.ts b/packages/core/src/internal/bolt-agent/browser/bolt-agent.ts index 4e2c97390..69755f85f 100644 --- a/packages/core/src/internal/bolt-agent/browser/bolt-agent.ts +++ b/packages/core/src/internal/bolt-agent/browser/bolt-agent.ts @@ -17,14 +17,35 @@ * limitations under the License. */ /* eslint-disable */ -// @ts-ignore: browser code so must be skipped by ts -export function fromVersion (version: string, windowProvider = () => window): string { - // @ts-ignore: browser code so must be skipped by ts - const APP_VERSION = windowProvider().navigator.appVersion + +import { BoltAgent } from "../../../types"; + +interface SystemInfo { + appVersion: string +} + +/** + * Constructs a BoltAgent structure from a given product version. + * + * @param {string} version The product version + * @param {function():SystemInfo} getSystemInfo Parameter used of inject system information and mock calls to the APIs. + * @returns {BoltAgent} The bolt agent + */ +export function fromVersion ( + version: string, + getSystemInfo: () => SystemInfo = () => ({ + // @ts-ignore: browser code so must be skipped by ts + get appVersion(): window.navigator.appVersion + }) +): BoltAgent { + const systemInfo = getSystemInfo() //APP_VERSION looks like 5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 - const OS = APP_VERSION.split("(")[1].split(")")[0]; + const OS = systemInfo.appVersion.split("(")[1].split(")")[0]; - return `neo4j-javascript/${version} (${OS})` + return { + product: `neo4j-javascript/${version}`, + platform: OS + } } /* eslint-enable */ diff --git a/packages/core/src/internal/bolt-agent/deno/bolt-agent.ts b/packages/core/src/internal/bolt-agent/deno/bolt-agent.ts index d2c42b785..001d4776b 100644 --- a/packages/core/src/internal/bolt-agent/deno/bolt-agent.ts +++ b/packages/core/src/internal/bolt-agent/deno/bolt-agent.ts @@ -17,17 +17,49 @@ * limitations under the License. */ +import { BoltAgent } from '../../../types.ts' + +export interface SystemInfo { + hostArch: string + denoVersion: string + v8Version: string + osVersion: string + osRelease: string +} + +/** + * Constructs a BoltAgent structure from a given product version. + * + * @param {string} version The product version + * @param {function():SystemInfo} getSystemInfo Parameter used of inject system information and mock calls to the APIs. + * @returns {BoltAgent} The bolt agent + */ /* eslint-disable */ -export function fromVersion (version: string): string { - //@ts-ignore - const HOST_ARCH = Deno.build.arch - //@ts-ignore - const DENO_VERSION = `Deno/${Deno.version.deno}` - //@ts-ignore - const NODE_V8_VERSION = Deno.version.v8 - //@ts-ignore - const OS_NAME_VERSION = `${Deno.build.os} ${Deno.osRelease ? Deno.osRelease() : ''}`.trim() +export function fromVersion ( + version: string, + getSystemInfo: () => SystemInfo = () => ({ + //@ts-ignore + hostArch: Deno.build.arch, + //@ts-ignore + denoVersion: Deno.version.deno, + //@ts-ignore: + v8Version: Deno.version.v8, + //@ts-ignore + osVersion: Deno.build.os, + get osRelease() { + //@ts-ignore + return Deno.osRelease ? Deno.osRelease() : '' + } + }) +): BoltAgent { + const systemInfo = getSystemInfo() + const DENO_VERSION = `Deno/${systemInfo.denoVersion}` + const OS_NAME_VERSION = `${systemInfo.osVersion} ${systemInfo.osRelease}`.trim() - return `neo4j-javascript/${version} (${OS_NAME_VERSION}; ${HOST_ARCH}) ${DENO_VERSION} (v8 ${NODE_V8_VERSION})` + return { + product: `neo4j-javascript/${version}`, + platform: `${OS_NAME_VERSION}; ${systemInfo.hostArch}`, + languageDetails: `${DENO_VERSION} (v8 ${systemInfo.v8Version})` + } } /* eslint-enable */ diff --git a/packages/core/src/internal/bolt-agent/node/bolt-agent.ts b/packages/core/src/internal/bolt-agent/node/bolt-agent.ts index fe76a0a95..e59921d12 100644 --- a/packages/core/src/internal/bolt-agent/node/bolt-agent.ts +++ b/packages/core/src/internal/bolt-agent/node/bolt-agent.ts @@ -16,13 +16,49 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as os from 'os' +import { platform, release } from 'os' +import { BoltAgent } from '../../../types' -export function fromVersion (version: string): string { - const HOST_ARCH = process.config.variables.host_arch - const NODE_VERSION = 'Node/' + process.versions.node - const NODE_V8_VERSION = process.versions.v8 - const OS_NAME_VERSION = `${os.platform()} ${os.release()}` +interface SystemInfo { + hostArch: string + nodeVersion: string + v8Version: string + platform: NodeJS.Platform + release: string +} + +/** + * Constructs a BoltAgent structure from a given product version. + * + * @param {string} version The product version + * @param {function():SystemInfo} getSystemInfo Parameter used of inject system information and mock calls to the APIs. + * @returns {BoltAgent} The bolt agent + */ +export function fromVersion ( + version: string, + getSystemInfo: () => SystemInfo = () => ({ + hostArch: process.config.variables.host_arch, + nodeVersion: process.versions.node, + v8Version: process.versions.v8, + get platform () { + return platform() + }, + get release () { + return release() + } + }) +): BoltAgent { + const systemInfo = getSystemInfo() + const HOST_ARCH = systemInfo.hostArch + const NODE_VERSION = 'Node/' + systemInfo.nodeVersion + const NODE_V8_VERSION = systemInfo.v8Version + const OS_NAME_VERSION = `${systemInfo.platform} ${systemInfo.release}` - return `neo4j-javascript/${version} (${OS_NAME_VERSION}; ${HOST_ARCH}) ${NODE_VERSION} (v8 ${NODE_V8_VERSION})` + return { + product: `neo4j-javascript/${version}`, + platform: `${OS_NAME_VERSION}; ${HOST_ARCH}`, + languageDetails: `${NODE_VERSION} (v8 ${NODE_V8_VERSION})` + } } + +export type { SystemInfo } diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index c509145d3..b1c447e1e 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -49,6 +49,13 @@ export interface AuthToken { parameters?: Parameters } +export interface BoltAgent { + product?: string + platform?: string + language?: string + languageDetails?: string +} + export interface Config { encrypted?: boolean | EncryptionLevel trust?: TrustStrategy @@ -65,7 +72,7 @@ export interface Config { logging?: LoggingConfig resolver?: (address: string) => string[] | Promise userAgent?: string - boltAgent?: string + boltAgent?: BoltAgent } /** diff --git a/packages/core/test/deno/internal/bolt-agent/deno/bolt-agent.test.ts b/packages/core/test/deno/internal/bolt-agent/deno/bolt-agent.test.ts index 20929339a..9e457984f 100644 --- a/packages/core/test/deno/internal/bolt-agent/deno/bolt-agent.test.ts +++ b/packages/core/test/deno/internal/bolt-agent/deno/bolt-agent.test.ts @@ -18,16 +18,9 @@ */ /* eslint-disable */ //@ts-ignore -import { fromVersion } from '../../../../../src/internal/bolt-agent/deno/bolt-agent.ts' +import { fromVersion, SystemInfo } from '../../../../../src/internal/bolt-agent/deno/bolt-agent.ts' //@ts-ignore -import { assertMatch, assertEquals } from "https://deno.land/std@0.182.0/testing/asserts.ts"; - -//@ts-ignore -Deno.test('Test Contains deno and javascript', () => { - const boltAgent = fromVersion("5.3") - assertMatch(boltAgent, new RegExp("^neo4j-javascript/5.3")) - assertMatch(boltAgent, new RegExp("Deno/")) -}); +import { assertEquals } from "https://deno.land/std@0.182.0/testing/asserts.ts"; //@ts-ignore Deno.test('Test full bolt agent', () => { @@ -40,8 +33,30 @@ Deno.test('Test full bolt agent', () => { //@ts-ignore const OS_NAME_VERSION = `${Deno.build.os} ${Deno.osRelease ? Deno.osRelease() : ''}`.trim() - const boltAgentExpected = `neo4j-javascript/5.3 (${OS_NAME_VERSION}; ${HOST_ARCH}) ${DENO_VERSION} (v8 ${NODE_V8_VERSION})` + const boltAgent = fromVersion('5.3') + + assertEquals(boltAgent, { + product: 'neo4j-javascript/5.3', + platform: `${OS_NAME_VERSION}; ${HOST_ARCH}`, + languageDetails: `${DENO_VERSION} (v8 ${NODE_V8_VERSION})` + }) +}); + +// @ts-ignore +Deno.test('Test full bolt agent for mocked values', () => { + const systemInfo: SystemInfo = { + hostArch: 'myArch', + denoVersion: '1.19.1', + v8Version: '8.1.39', + osVersion: 'macos', + osRelease: '14.1' + } + const boltAgent = fromVersion('5.3', () => systemInfo) - assertEquals(fromVersion("5.3"), boltAgentExpected) + assertEquals(boltAgent, { + product: 'neo4j-javascript/5.3', + platform: 'macos 14.1; myArch', + languageDetails: `Deno/1.19.1 (v8 8.1.39)` + }) }); /* eslint-enable */ diff --git a/packages/core/test/internal/bolt-agent/browser/bolt-agent.test.ts b/packages/core/test/internal/bolt-agent/browser/bolt-agent.test.ts index 210ffac61..e78020574 100644 --- a/packages/core/test/internal/bolt-agent/browser/bolt-agent.test.ts +++ b/packages/core/test/internal/bolt-agent/browser/bolt-agent.test.ts @@ -22,17 +22,17 @@ describe('#unit boltAgent', () => { // This test is very fragile but the exact look of this string should not change without PM approval it('should return the correct bolt agent for specified version', () => { const version = '5.3' - const windowProvider = (): any => { + const getSystemInfo = (): any => { return { - navigator: { - appVersion: '5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36' - } + appVersion: '5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36' } } - const boltAgent = fromVersion(version, windowProvider) + const boltAgent = fromVersion(version, getSystemInfo) - expect(boltAgent.length === 0).toBeFalsy() - expect(boltAgent).toEqual(`neo4j-javascript/${version} (Macintosh; Intel Mac OS X 10_15_7)`) + expect(boltAgent).toEqual({ + product: 'neo4j-javascript/5.3', + platform: 'Macintosh; Intel Mac OS X 10_15_7' + }) }) }) diff --git a/packages/core/test/internal/bolt-agent/node/bolt-agent.test.ts b/packages/core/test/internal/bolt-agent/node/bolt-agent.test.ts index 5804202ad..2a85c8200 100644 --- a/packages/core/test/internal/bolt-agent/node/bolt-agent.test.ts +++ b/packages/core/test/internal/bolt-agent/node/bolt-agent.test.ts @@ -17,27 +17,42 @@ * limitations under the License. */ import { boltAgent as BoltAgent } from '../../../../src/internal' -import os from 'os' +import { SystemInfo } from '../../../../src/internal/bolt-agent' +import { platform, release } from 'os' describe('#unit boltAgent', () => { - // This test is very fragile but the exact look of this string should not change without PM approval + // This test is very fragile but the exact look of this struct should not change without PM approval it('should return the correct bolt agent for specified version', () => { const version = '5.3' - const boltAgent = BoltAgent.fromVersion(version) - const HOST_ARCH = process.config.variables.host_arch const NODE_VERSION = 'Node/' + process.versions.node const NODE_V8_VERSION = process.versions.v8 - const osName = os.platform() + const boltAgent = BoltAgent.fromVersion(version) + + expect(boltAgent).toEqual({ + product: `neo4j-javascript/${version}`, + platform: `${platform()} ${release()}; ${HOST_ARCH}`, + languageDetails: `${NODE_VERSION} (v8 ${NODE_V8_VERSION})` + }) + }) + + it('should return the correct bolt agent for mocked values', () => { + const version = '5.6' + const systemInfo: SystemInfo = { + hostArch: 'Some arch', + nodeVersion: '16.0.1', + v8Version: '1.7.0', + platform: 'netbsd', + release: '1.1.1' + } - expect(boltAgent.length === 0).toBeFalsy() - expect(boltAgent).toContain(`neo4j-javascript/${version}`) - expect(boltAgent).toContain(`${HOST_ARCH}`) - expect(boltAgent).toContain(`${NODE_VERSION}`) - expect(boltAgent).toContain(`${NODE_V8_VERSION}`) - expect(boltAgent).toContain(`${osName}`) + const boltAgent = BoltAgent.fromVersion(version, () => systemInfo) - expect(boltAgent).toEqual(`neo4j-javascript/${version} (${osName} ${os.release()}; ${HOST_ARCH}) ${NODE_VERSION} (v8 ${NODE_V8_VERSION})`) + expect(boltAgent).toEqual({ + product: 'neo4j-javascript/5.6', + platform: 'netbsd 1.1.1; Some arch', + languageDetails: 'Node/16.0.1 (v8 1.7.0)' + }) }) }) diff --git a/packages/neo4j-driver-deno/generate.ts b/packages/neo4j-driver-deno/generate.ts index 02d3c0565..ea523c2e4 100644 --- a/packages/neo4j-driver-deno/generate.ts +++ b/packages/neo4j-driver-deno/generate.ts @@ -24,6 +24,13 @@ const isDir = (path: string) => { } }; +const addExtIfNeeded = (path: string, ext: string): string => { + if (path.endsWith(ext)) { + return path; + } + return `${path}${ext}` +} + //////////////////////////////////////////////////////////////////////////////// // Parse arguments const parsedArgs = parse(Deno.args, { @@ -86,7 +93,7 @@ async function copyAndTransform(inDir: string, outDir: string) { (_x, origPath) => { const newPath = isDir(`${inDir}/${origPath}`) ? `${origPath}/index.ts` - : `${origPath}.ts`; + : addExtIfNeeded(origPath, '.ts'); return ` from '${newPath}'`; }, ); @@ -109,7 +116,7 @@ async function copyAndTransform(inDir: string, outDir: string) { (_x, origPath) => { const newPath = isDir(`${inDir}/${origPath}`) ? `${origPath}/index.js` - : `${origPath}.js`; + : addExtIfNeeded(origPath, '.js'); return ` from '${newPath}'`; }, ); diff --git a/packages/neo4j-driver-deno/lib/bolt-connection/bolt/request-message.js b/packages/neo4j-driver-deno/lib/bolt-connection/bolt/request-message.js index 6822f9c4f..f86c08ab7 100644 --- a/packages/neo4j-driver-deno/lib/bolt-connection/bolt/request-message.js +++ b/packages/neo4j-driver-deno/lib/bolt-connection/bolt/request-message.js @@ -200,12 +200,21 @@ export default class RequestMessage { * @return {RequestMessage} new HELLO message. */ static hello5x3 (userAgent, boltAgent, notificationFilter = null, routing = null) { - const metadata = { bolt_agent: boltAgent } + const metadata = { } if (userAgent) { metadata.user_agent = userAgent } + if (boltAgent) { + metadata.bolt_agent = { + product: boltAgent.product, + platform: boltAgent.platform, + language: boltAgent.language, + language_details: boltAgent.languageDetails + } + } + if (notificationFilter) { if (notificationFilter.minimumSeverityLevel) { metadata.notifications_minimum_severity = notificationFilter.minimumSeverityLevel diff --git a/packages/neo4j-driver-deno/lib/core/internal/bolt-agent/browser/bolt-agent.ts b/packages/neo4j-driver-deno/lib/core/internal/bolt-agent/browser/bolt-agent.ts index 4e2c97390..69755f85f 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/bolt-agent/browser/bolt-agent.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/bolt-agent/browser/bolt-agent.ts @@ -17,14 +17,35 @@ * limitations under the License. */ /* eslint-disable */ -// @ts-ignore: browser code so must be skipped by ts -export function fromVersion (version: string, windowProvider = () => window): string { - // @ts-ignore: browser code so must be skipped by ts - const APP_VERSION = windowProvider().navigator.appVersion + +import { BoltAgent } from "../../../types"; + +interface SystemInfo { + appVersion: string +} + +/** + * Constructs a BoltAgent structure from a given product version. + * + * @param {string} version The product version + * @param {function():SystemInfo} getSystemInfo Parameter used of inject system information and mock calls to the APIs. + * @returns {BoltAgent} The bolt agent + */ +export function fromVersion ( + version: string, + getSystemInfo: () => SystemInfo = () => ({ + // @ts-ignore: browser code so must be skipped by ts + get appVersion(): window.navigator.appVersion + }) +): BoltAgent { + const systemInfo = getSystemInfo() //APP_VERSION looks like 5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 - const OS = APP_VERSION.split("(")[1].split(")")[0]; + const OS = systemInfo.appVersion.split("(")[1].split(")")[0]; - return `neo4j-javascript/${version} (${OS})` + return { + product: `neo4j-javascript/${version}`, + platform: OS + } } /* eslint-enable */ diff --git a/packages/neo4j-driver-deno/lib/core/internal/bolt-agent/deno/bolt-agent.ts b/packages/neo4j-driver-deno/lib/core/internal/bolt-agent/deno/bolt-agent.ts index d2c42b785..001d4776b 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/bolt-agent/deno/bolt-agent.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/bolt-agent/deno/bolt-agent.ts @@ -17,17 +17,49 @@ * limitations under the License. */ +import { BoltAgent } from '../../../types.ts' + +export interface SystemInfo { + hostArch: string + denoVersion: string + v8Version: string + osVersion: string + osRelease: string +} + +/** + * Constructs a BoltAgent structure from a given product version. + * + * @param {string} version The product version + * @param {function():SystemInfo} getSystemInfo Parameter used of inject system information and mock calls to the APIs. + * @returns {BoltAgent} The bolt agent + */ /* eslint-disable */ -export function fromVersion (version: string): string { - //@ts-ignore - const HOST_ARCH = Deno.build.arch - //@ts-ignore - const DENO_VERSION = `Deno/${Deno.version.deno}` - //@ts-ignore - const NODE_V8_VERSION = Deno.version.v8 - //@ts-ignore - const OS_NAME_VERSION = `${Deno.build.os} ${Deno.osRelease ? Deno.osRelease() : ''}`.trim() +export function fromVersion ( + version: string, + getSystemInfo: () => SystemInfo = () => ({ + //@ts-ignore + hostArch: Deno.build.arch, + //@ts-ignore + denoVersion: Deno.version.deno, + //@ts-ignore: + v8Version: Deno.version.v8, + //@ts-ignore + osVersion: Deno.build.os, + get osRelease() { + //@ts-ignore + return Deno.osRelease ? Deno.osRelease() : '' + } + }) +): BoltAgent { + const systemInfo = getSystemInfo() + const DENO_VERSION = `Deno/${systemInfo.denoVersion}` + const OS_NAME_VERSION = `${systemInfo.osVersion} ${systemInfo.osRelease}`.trim() - return `neo4j-javascript/${version} (${OS_NAME_VERSION}; ${HOST_ARCH}) ${DENO_VERSION} (v8 ${NODE_V8_VERSION})` + return { + product: `neo4j-javascript/${version}`, + platform: `${OS_NAME_VERSION}; ${systemInfo.hostArch}`, + languageDetails: `${DENO_VERSION} (v8 ${systemInfo.v8Version})` + } } /* eslint-enable */ diff --git a/packages/neo4j-driver-deno/lib/core/internal/bolt-agent/node/bolt-agent.ts b/packages/neo4j-driver-deno/lib/core/internal/bolt-agent/node/bolt-agent.ts index fe76a0a95..28b605fdf 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/bolt-agent/node/bolt-agent.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/bolt-agent/node/bolt-agent.ts @@ -16,13 +16,49 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as os from 'os' +import { platform, release } from 'os' +import { BoltAgent } from '../../../types.ts' -export function fromVersion (version: string): string { - const HOST_ARCH = process.config.variables.host_arch - const NODE_VERSION = 'Node/' + process.versions.node - const NODE_V8_VERSION = process.versions.v8 - const OS_NAME_VERSION = `${os.platform()} ${os.release()}` +interface SystemInfo { + hostArch: string + nodeVersion: string + v8Version: string + platform: NodeJS.Platform + release: string +} + +/** + * Constructs a BoltAgent structure from a given product version. + * + * @param {string} version The product version + * @param {function():SystemInfo} getSystemInfo Parameter used of inject system information and mock calls to the APIs. + * @returns {BoltAgent} The bolt agent + */ +export function fromVersion ( + version: string, + getSystemInfo: () => SystemInfo = () => ({ + hostArch: process.config.variables.host_arch, + nodeVersion: process.versions.node, + v8Version: process.versions.v8, + get platform () { + return platform() + }, + get release () { + return release() + } + }) +): BoltAgent { + const systemInfo = getSystemInfo() + const HOST_ARCH = systemInfo.hostArch + const NODE_VERSION = 'Node/' + systemInfo.nodeVersion + const NODE_V8_VERSION = systemInfo.v8Version + const OS_NAME_VERSION = `${systemInfo.platform} ${systemInfo.release}` - return `neo4j-javascript/${version} (${OS_NAME_VERSION}; ${HOST_ARCH}) ${NODE_VERSION} (v8 ${NODE_V8_VERSION})` + return { + product: `neo4j-javascript/${version}`, + platform: `${OS_NAME_VERSION}; ${HOST_ARCH}`, + languageDetails: `${NODE_VERSION} (v8 ${NODE_V8_VERSION})` + } } + +export type { SystemInfo } diff --git a/packages/neo4j-driver-deno/lib/core/types.ts b/packages/neo4j-driver-deno/lib/core/types.ts index c509145d3..b1c447e1e 100644 --- a/packages/neo4j-driver-deno/lib/core/types.ts +++ b/packages/neo4j-driver-deno/lib/core/types.ts @@ -49,6 +49,13 @@ export interface AuthToken { parameters?: Parameters } +export interface BoltAgent { + product?: string + platform?: string + language?: string + languageDetails?: string +} + export interface Config { encrypted?: boolean | EncryptionLevel trust?: TrustStrategy @@ -65,7 +72,7 @@ export interface Config { logging?: LoggingConfig resolver?: (address: string) => string[] | Promise userAgent?: string - boltAgent?: string + boltAgent?: BoltAgent } /**