Skip to content

Commit 75e70fa

Browse files
committed
Remove circular dependency between json and util
Extracting `object-util` resolve this circular dependency issue.
1 parent 42e5855 commit 75e70fa

File tree

8 files changed

+163
-120
lines changed

8 files changed

+163
-120
lines changed

packages/bolt-connection/src/bolt/transformer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import { structure } from '../packstream'
2121
import { internal } from 'neo4j-driver-core'
2222

23-
const { util } = internal
23+
const { objectUtil } = internal
2424

2525
/**
2626
* Class responsible for applying the expected {@link TypeTransformer} to
@@ -53,7 +53,7 @@ export default class Transformer {
5353
}
5454
return struct
5555
} catch (error) {
56-
return util.createBrokenObject(error)
56+
return objectUtil.createBrokenObject(error)
5757
}
5858
}
5959

packages/core/src/internal/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import * as logger from './logger'
2929
import * as urlUtil from './url-util'
3030
import * as serverAddress from './server-address'
3131
import * as resolver from './resolver'
32+
import * as objectUtil from './object-util'
3233

3334
export {
3435
util,
@@ -42,5 +43,6 @@ export {
4243
logger,
4344
urlUtil,
4445
serverAddress,
45-
resolver
46+
resolver,
47+
objectUtil
4648
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
// eslint-disable-next-line @typescript-eslint/naming-convention
20+
const __isBrokenObject__ = '__isBrokenObject__'
21+
// eslint-disable-next-line @typescript-eslint/naming-convention
22+
const __reason__ = '__reason__'
23+
24+
/**
25+
* Creates a object which all method call will throw the given error
26+
*
27+
* @param {Error} error The error
28+
* @param {any} object The object. Default: {}
29+
* @returns {any} A broken object
30+
*/
31+
function createBrokenObject<T extends object> (error: Error, object: any = {}): T {
32+
const fail: <T>() => T = () => {
33+
throw error
34+
}
35+
36+
return new Proxy(object, {
37+
get: (_: T, p: string | Symbol): any => {
38+
if (p === __isBrokenObject__) {
39+
return true
40+
} else if (p === __reason__) {
41+
return error
42+
} else if (p === 'toJSON') {
43+
return undefined
44+
}
45+
fail()
46+
},
47+
set: fail,
48+
apply: fail,
49+
construct: fail,
50+
defineProperty: fail,
51+
deleteProperty: fail,
52+
getOwnPropertyDescriptor: fail,
53+
getPrototypeOf: fail,
54+
has: fail,
55+
isExtensible: fail,
56+
ownKeys: fail,
57+
preventExtensions: fail,
58+
setPrototypeOf: fail
59+
})
60+
}
61+
62+
/**
63+
* Verifies if it is a Broken Object
64+
* @param {any} object The object
65+
* @returns {boolean} If it was created with createBrokenObject
66+
*/
67+
function isBrokenObject (object: any): boolean {
68+
return object !== null && typeof object === 'object' && object[__isBrokenObject__] === true
69+
}
70+
71+
/**
72+
* Returns if the reason the object is broken.
73+
*
74+
* This method should only be called with instances create with {@link createBrokenObject}
75+
*
76+
* @param {any} object The object
77+
* @returns {Error} The reason the object is broken
78+
*/
79+
function getBrokenObjectReason (object: any): Error {
80+
return object[__reason__]
81+
}
82+
83+
export {
84+
createBrokenObject,
85+
isBrokenObject,
86+
getBrokenObjectReason
87+
}

packages/core/src/internal/util.ts

Lines changed: 1 addition & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ import { stringify } from '../json'
2424

2525
const ENCRYPTION_ON: EncryptionLevel = 'ENCRYPTION_ON'
2626
const ENCRYPTION_OFF: EncryptionLevel = 'ENCRYPTION_OFF'
27-
// eslint-disable-next-line @typescript-eslint/naming-convention
28-
const __isBrokenObject__ = '__isBrokenObject__'
29-
// eslint-disable-next-line @typescript-eslint/naming-convention
30-
const __reason__ = '__reason__'
3127
/**
3228
* Verifies if the object is null or empty
3329
* @param obj The subject object
@@ -227,65 +223,6 @@ function isString (str: any): str is string {
227223
return Object.prototype.toString.call(str) === '[object String]'
228224
}
229225

230-
/**
231-
* Creates a object which all method call will throw the given error
232-
*
233-
* @param {Error} error The error
234-
* @param {any} object The object. Default: {}
235-
* @returns {any} A broken object
236-
*/
237-
function createBrokenObject<T extends object> (error: Error, object: any = {}): T {
238-
const fail: <T>() => T = () => {
239-
throw error
240-
}
241-
242-
return new Proxy(object, {
243-
get: (_: T, p: string | Symbol): any => {
244-
if (p === __isBrokenObject__) {
245-
return true
246-
} else if (p === __reason__) {
247-
return error
248-
} else if (p === 'toJSON') {
249-
return undefined
250-
}
251-
fail()
252-
},
253-
set: fail,
254-
apply: fail,
255-
construct: fail,
256-
defineProperty: fail,
257-
deleteProperty: fail,
258-
getOwnPropertyDescriptor: fail,
259-
getPrototypeOf: fail,
260-
has: fail,
261-
isExtensible: fail,
262-
ownKeys: fail,
263-
preventExtensions: fail,
264-
setPrototypeOf: fail
265-
})
266-
}
267-
268-
/**
269-
* Verifies if it is a Broken Object
270-
* @param {any} object The object
271-
* @returns {boolean} If it was created with createBrokenObject
272-
*/
273-
function isBrokenObject (object: any): boolean {
274-
return object !== null && typeof object === 'object' && object[__isBrokenObject__] === true
275-
}
276-
277-
/**
278-
* Returns if the reason the object is broken.
279-
*
280-
* This method should only be called with instances create with {@link createBrokenObject}
281-
*
282-
* @param {any} object The object
283-
* @returns {Error} The reason the object is broken
284-
*/
285-
function getBrokenObjectReason (object: any): Error {
286-
return object[__reason__]
287-
}
288-
289226
export {
290227
isEmptyObjectOrNull,
291228
isObject,
@@ -297,8 +234,5 @@ export {
297234
assertValidDate,
298235
validateQueryAndParameters,
299236
ENCRYPTION_ON,
300-
ENCRYPTION_OFF,
301-
createBrokenObject,
302-
isBrokenObject,
303-
getBrokenObjectReason
237+
ENCRYPTION_OFF
304238
}

packages/core/src/json.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* limitations under the License.
1818
*/
1919

20-
import { isBrokenObject, getBrokenObjectReason } from './internal/util'
20+
import { isBrokenObject, getBrokenObjectReason } from './internal/object-util'
2121

2222
/**
2323
* Custom version on JSON.stringify that can handle values that normally don't support serialization, such as BigInt.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
import { newError } from '../../src'
20+
import {
21+
createBrokenObject,
22+
isBrokenObject,
23+
getBrokenObjectReason
24+
} from '../../src/internal/object-util'
25+
26+
describe('isBrokenObject', () => {
27+
it('should return true when object created with createBrokenObject', () => {
28+
const object = createBrokenObject(newError('error'), {})
29+
30+
expect(isBrokenObject(object)).toBe(true)
31+
})
32+
33+
it('should return false for regular objects', () => {
34+
const object = {}
35+
36+
expect(isBrokenObject(object)).toBe(false)
37+
})
38+
39+
it('should return false for non-objects', () => {
40+
expect(isBrokenObject(null)).toBe(false)
41+
expect(isBrokenObject(undefined)).toBe(false)
42+
expect(isBrokenObject(1)).toBe(false)
43+
expect(isBrokenObject(() => {})).toBe(false)
44+
expect(isBrokenObject('string')).toBe(false)
45+
})
46+
})
47+
48+
describe('getBrokenObjectReason', () => {
49+
it('should return the reason the object is broken', () => {
50+
const reason = newError('error')
51+
const object = createBrokenObject(reason, {})
52+
53+
expect(getBrokenObjectReason(object)).toBe(reason)
54+
})
55+
})
56+
57+
describe('createBrokenObject', () => {
58+
describe('toJSON', () => {
59+
it('should return undefined', () => {
60+
const reason = newError('error')
61+
const object = createBrokenObject(reason, {})
62+
63+
// @ts-expect-error
64+
expect(object.toJSON).toBeUndefined()
65+
})
66+
})
67+
})

packages/core/test/internal/util.test.ts

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
* See the License for the specific language governing permissions and
1717
* limitations under the License.
1818
*/
19-
import { newError } from '../../src'
2019
import Integer, { int } from '../../src/integer'
2120
import {
2221
isEmptyObjectOrNull,
@@ -29,10 +28,7 @@ import {
2928
assertValidDate,
3029
validateQueryAndParameters,
3130
ENCRYPTION_ON,
32-
ENCRYPTION_OFF,
33-
createBrokenObject,
34-
isBrokenObject,
35-
getBrokenObjectReason
31+
ENCRYPTION_OFF
3632
} from '../../src/internal/util'
3733

3834
/* eslint-disable no-new-wrappers */
@@ -254,47 +250,4 @@ describe('Util', () => {
254250
expect(ENCRYPTION_ON).toBe('ENCRYPTION_ON'))
255251
test('should ENCRYPTION_OFF toBe "ENCRYPTION_OFF"', () =>
256252
expect(ENCRYPTION_OFF).toBe('ENCRYPTION_OFF'))
257-
258-
describe('isBrokenObject', () => {
259-
it('should return true when object created with createBrokenObject', () => {
260-
const object = createBrokenObject(newError('error'), {})
261-
262-
expect(isBrokenObject(object)).toBe(true)
263-
})
264-
265-
it('should return false for regular objects', () => {
266-
const object = {}
267-
268-
expect(isBrokenObject(object)).toBe(false)
269-
})
270-
271-
it('should return false for non-objects', () => {
272-
expect(isBrokenObject(null)).toBe(false)
273-
expect(isBrokenObject(undefined)).toBe(false)
274-
expect(isBrokenObject(1)).toBe(false)
275-
expect(isBrokenObject(() => {})).toBe(false)
276-
expect(isBrokenObject('string')).toBe(false)
277-
})
278-
})
279-
280-
describe('getBrokenObjectReason', () => {
281-
it('should return the reason the object is broken', () => {
282-
const reason = newError('error')
283-
const object = createBrokenObject(reason, {})
284-
285-
expect(getBrokenObjectReason(object)).toBe(reason)
286-
})
287-
})
288-
289-
describe('createBrokenObject', () => {
290-
describe('toJSON', () => {
291-
it('should return undefined', () => {
292-
const reason = newError('error')
293-
const object = createBrokenObject(reason, {})
294-
295-
// @ts-expect-error
296-
expect(object.toJSON).toBeUndefined()
297-
})
298-
})
299-
})
300253
})

packages/core/test/json.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
import { json, newError } from '../src'
21-
import { createBrokenObject } from '../src/internal/util'
21+
import { createBrokenObject } from '../src/internal/object-util'
2222

2323
describe('json', () => {
2424
describe('.stringify', () => {

0 commit comments

Comments
 (0)