diff --git a/packages/bolt-connection/src/bolt/bolt-protocol-v6x0.transformer.js b/packages/bolt-connection/src/bolt/bolt-protocol-v6x0.transformer.js index c9ccd8578..600c24172 100644 --- a/packages/bolt-connection/src/bolt/bolt-protocol-v6x0.transformer.js +++ b/packages/bolt-connection/src/bolt/bolt-protocol-v6x0.transformer.js @@ -18,7 +18,7 @@ import v5x8 from './bolt-protocol-v5x8.transformer' import { TypeTransformer } from './transformer' import { structure } from '../packstream' -import { Vector, newError } from 'neo4j-driver-core' +import { Vector, isVector, newError } from 'neo4j-driver-core' const VECTOR = 0x56 const FLOAT_32 = 0xc6 const FLOAT_64 = 0xc1 @@ -39,7 +39,7 @@ const typeToTypeMarker = { function createVectorTransformer () { return new TypeTransformer({ signature: VECTOR, - isTypeInstance: object => object instanceof Vector, + isTypeInstance: object => isVector(object), toStructure: vector => { const typeMarker = typeToTypeMarker[vector.getType()] if (typeMarker === undefined) { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 83fc1400b..6e00ee095 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -102,7 +102,7 @@ import * as json from './json' import resultTransformers, { ResultTransformer } from './result-transformers' import ClientCertificate, { clientCertificateProviders, ClientCertificateProvider, ClientCertificateProviders, RotatingClientCertificateProvider, resolveCertificateProvider } from './client-certificate' import * as internal from './internal' // todo: removed afterwards -import Vector, { VectorType, vector } from './vector' +import Vector, { VectorType, vector, isVector } from './vector' /** * Object containing string constants representing predefined {@link Neo4jError} codes. @@ -189,7 +189,9 @@ const forExport = { notificationFilterDisabledClassification, notificationFilterMinimumSeverityLevel, clientCertificateProviders, - resolveCertificateProvider + resolveCertificateProvider, + isVector, + vector } export { @@ -268,6 +270,7 @@ export { notificationFilterMinimumSeverityLevel, clientCertificateProviders, resolveCertificateProvider, + isVector, Vector, vector } diff --git a/packages/core/src/vector.ts b/packages/core/src/vector.ts index aa95030d6..5f86a7d91 100644 --- a/packages/core/src/vector.ts +++ b/packages/core/src/vector.ts @@ -17,6 +17,8 @@ import { newError } from './error' +const VECTOR_IDENTIFIER_PROPERTY = '__isVector__' + type EnumRecord = { [key in T]: key } export type VectorType = 'INT8' | 'INT16' | 'INT32' | 'INT64' | 'FLOAT32' | 'FLOAT64' @@ -87,8 +89,38 @@ export default class Vector (typedArray: K): Vector { return new Vector(typedArray) } + +/** + * Test if given object is an instance of the {@link Vector} class. + * @param {Object} obj the object to test. + * @return {boolean} `true` if given object is a {@link Vector}, `false` otherwise. + */ +export function isVector (obj: any): obj is Vector { + return obj != null && obj[VECTOR_IDENTIFIER_PROPERTY] === true +} diff --git a/packages/core/test/vector-type.test.ts b/packages/core/test/vector-type.test.ts index 0a03c63fc..93ea84dbf 100644 --- a/packages/core/test/vector-type.test.ts +++ b/packages/core/test/vector-type.test.ts @@ -32,4 +32,20 @@ describe('Vector', () => { expect(vec.asTypedArray()).toEqual(typedArray) }) }) + describe('.toString()', () => { + it.each([ + ['Int8Array', Int8Array.from([1]), 'vector([1], 1, INTEGER8 NOT NULL)'], + ['Int16Array', Int16Array.from([1, 2, 3]), 'vector([1, 2, 3], 3, INTEGER16 NOT NULL)'], + ['Int32Array', Int32Array.from([3]), 'vector([3], 1, INTEGER32 NOT NULL)'], + ['BigInt64Array', BigInt64Array.from([BigInt(0)]), 'vector([0], 1, INTEGER NOT NULL)'], + ['Float32Array', Float32Array.from([0.5, 1.875]), 'vector([0.5, 1.875], 2, FLOAT32 NOT NULL)'], + ['Float32Array with special values', Float32Array.from([-Infinity, Infinity, NaN, -NaN, 1.401298464324817e-45, 3.4028235e38]), 'vector([-Infinity, Infinity, NaN, NaN, 1.401298464324817e-45, 3.4028234663852886e+38], 6, FLOAT32 NOT NULL)'], + ['Float64Array', Float64Array.from([2]), 'vector([2], 1, FLOAT NOT NULL)'], + ['Float64Array with special values', Float64Array.from([-Infinity, Infinity, NaN, -NaN, 2.2250738585072014e-308, 1.7976931348623157e308]), 'vector([-Infinity, Infinity, NaN, NaN, 2.2250738585072014e-308, 1.7976931348623157e+308], 6, FLOAT NOT NULL)'], + ['Float64Array of huge size', Float64Array.from([...Array(10000).keys()]), `vector([${[...Array(10000).keys()].join(', ')}], 10000, FLOAT NOT NULL)`] + ])('should correctly stringify (%s)', (_, typedArray, expectedString) => { + const vec = vector(typedArray) + expect(vec.toString()).toEqual(expectedString) + }) + }) }) diff --git a/packages/neo4j-driver-deno/lib/bolt-connection/bolt/bolt-protocol-v6x0.transformer.js b/packages/neo4j-driver-deno/lib/bolt-connection/bolt/bolt-protocol-v6x0.transformer.js index c0e0d16b2..a48e0c48a 100644 --- a/packages/neo4j-driver-deno/lib/bolt-connection/bolt/bolt-protocol-v6x0.transformer.js +++ b/packages/neo4j-driver-deno/lib/bolt-connection/bolt/bolt-protocol-v6x0.transformer.js @@ -18,7 +18,7 @@ import v5x8 from './bolt-protocol-v5x8.transformer.js' import { TypeTransformer } from './transformer.js' import { structure } from '../packstream/index.js' -import { Vector, newError } from '../../core/index.ts' +import { Vector, isVector, newError } from '../../core/index.ts' const VECTOR = 0x56 const FLOAT_32 = 0xc6 const FLOAT_64 = 0xc1 @@ -39,7 +39,7 @@ const typeToTypeMarker = { function createVectorTransformer () { return new TypeTransformer({ signature: VECTOR, - isTypeInstance: object => object instanceof Vector, + isTypeInstance: object => isVector(object), toStructure: vector => { const typeMarker = typeToTypeMarker[vector.getType()] if (typeMarker === undefined) { diff --git a/packages/neo4j-driver-deno/lib/core/index.ts b/packages/neo4j-driver-deno/lib/core/index.ts index b22a6600b..86214062b 100644 --- a/packages/neo4j-driver-deno/lib/core/index.ts +++ b/packages/neo4j-driver-deno/lib/core/index.ts @@ -102,7 +102,7 @@ import * as json from './json.ts' import resultTransformers, { ResultTransformer } from './result-transformers.ts' import ClientCertificate, { clientCertificateProviders, ClientCertificateProvider, ClientCertificateProviders, RotatingClientCertificateProvider, resolveCertificateProvider } from './client-certificate.ts' import * as internal from './internal/index.ts' -import Vector, { VectorType, vector } from './vector.ts' +import Vector, { VectorType, vector, isVector } from './vector.ts' /** * Object containing string constants representing predefined {@link Neo4jError} codes. @@ -189,7 +189,9 @@ const forExport = { notificationFilterDisabledClassification, notificationFilterMinimumSeverityLevel, clientCertificateProviders, - resolveCertificateProvider + resolveCertificateProvider, + isVector, + vector } export { @@ -268,6 +270,7 @@ export { notificationFilterMinimumSeverityLevel, clientCertificateProviders, resolveCertificateProvider, + isVector, Vector, vector } diff --git a/packages/neo4j-driver-deno/lib/core/vector.ts b/packages/neo4j-driver-deno/lib/core/vector.ts index 53ccccb01..d33c42922 100644 --- a/packages/neo4j-driver-deno/lib/core/vector.ts +++ b/packages/neo4j-driver-deno/lib/core/vector.ts @@ -17,6 +17,8 @@ import { newError } from './error.ts' +const VECTOR_IDENTIFIER_PROPERTY = '__isVector__' + type EnumRecord = { [key in T]: key } export type VectorType = 'INT8' | 'INT16' | 'INT32' | 'INT64' | 'FLOAT32' | 'FLOAT64' @@ -87,8 +89,38 @@ export default class Vector (typedArray: K): Vector { return new Vector(typedArray) } + +/** + * Test if given object is an instance of the {@link Vector} class. + * @param {Object} obj the object to test. + * @return {boolean} `true` if given object is a {@link Vector}, `false` otherwise. + */ +export function isVector (obj: any): obj is Vector { + return obj != null && obj[VECTOR_IDENTIFIER_PROPERTY] === true +} diff --git a/packages/neo4j-driver/src/index.js b/packages/neo4j-driver/src/index.js index bd767a000..84072bae1 100644 --- a/packages/neo4j-driver/src/index.js +++ b/packages/neo4j-driver/src/index.js @@ -80,6 +80,7 @@ import { staticAuthTokenManager, clientCertificateProviders, resolveCertificateProvider, + isVector, Vector, VectorType, vector @@ -410,6 +411,7 @@ const forExport = { notificationFilterDisabledCategory, notificationFilterMinimumSeverityLevel, clientCertificateProviders, + isVector, vector } @@ -484,6 +486,7 @@ export { notificationFilterDisabledClassification, notificationFilterMinimumSeverityLevel, clientCertificateProviders, + isVector, vector, Vector, VectorType diff --git a/packages/neo4j-driver/types/index.d.ts b/packages/neo4j-driver/types/index.d.ts index d41bf5783..5e582a5e3 100644 --- a/packages/neo4j-driver/types/index.d.ts +++ b/packages/neo4j-driver/types/index.d.ts @@ -98,7 +98,8 @@ import { ClientCertificateProviders, RotatingClientCertificateProvider, clientCertificateProviders, - types as coreTypes + types as coreTypes, + isVector } from 'neo4j-driver-core' import { AuthToken, @@ -299,6 +300,7 @@ declare const forExport: { notificationFilterMinimumSeverityLevel: typeof notificationFilterMinimumSeverityLevel logging: typeof logging clientCertificateProviders: typeof clientCertificateProviders + isVector: typeof isVector } export { @@ -379,7 +381,8 @@ export { notificationFilterDisabledClassification, notificationFilterMinimumSeverityLevel, logging, - clientCertificateProviders + clientCertificateProviders, + isVector } export type {