@neo4j-cypher/query-tools 2.0.0-next.36 → 2.0.0-next.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/cjs/index.cjs +1848 -0
- package/dist/cjs/index.cjs.map +7 -0
- package/dist/esm/package.json +9 -8
- package/dist/esm/src/connectionErrorHandler.d.ts +1 -2
- package/dist/esm/src/connectionErrorHandler.js +1 -1
- package/dist/esm/src/connectionErrorHandler.js.map +1 -1
- package/dist/esm/src/cypher-execution/extract-unique-nodes-and-relationships.d.ts +1 -1
- package/dist/esm/src/cypher-execution/extract-unique-nodes-and-relationships.test.js +0 -4
- package/dist/esm/src/cypher-execution/extract-unique-nodes-and-relationships.test.js.map +1 -1
- package/dist/esm/src/cypher-execution/query-result.js +2 -9
- package/dist/esm/src/cypher-execution/query-result.js.map +1 -1
- package/dist/esm/src/data-transforms/record-to-string.js +1 -2
- package/dist/esm/src/data-transforms/record-to-string.js.map +1 -1
- package/dist/esm/src/integration-tests/pollingIntegrationTests.test.js.map +1 -1
- package/dist/esm/src/integration-tests/setupTestContainer.d.ts +1 -1
- package/dist/esm/src/integration-tests/setupTestContainer.js +1 -1
- package/dist/esm/src/integration-tests/setupTestContainer.js.map +1 -1
- package/dist/esm/src/metadataPoller.d.ts +4 -4
- package/dist/esm/src/metadataPoller.js +1 -1
- package/dist/esm/src/metadataPoller.js.map +1 -1
- package/dist/esm/src/neo4jConnection.d.ts +4 -4
- package/dist/esm/src/neo4jConnection.js +2 -2
- package/dist/esm/src/neo4jConnection.js.map +1 -1
- package/dist/esm/src/queries/dataSummary.d.ts +1 -1
- package/dist/esm/src/queries/dataSummary.js.map +1 -1
- package/dist/esm/src/queries/databases.d.ts +3 -13
- package/dist/esm/src/queries/databases.js +2 -5
- package/dist/esm/src/queries/databases.js.map +1 -1
- package/dist/esm/src/queries/functions.d.ts +1 -3
- package/dist/esm/src/queries/functions.js +2 -3
- package/dist/esm/src/queries/functions.js.map +1 -1
- package/dist/esm/src/queries/graphSchema.d.ts +2 -2
- package/dist/esm/src/queries/graphSchema.js +1 -1
- package/dist/esm/src/queries/graphSchema.js.map +1 -1
- package/dist/esm/src/queries/procedures.d.ts +1 -3
- package/dist/esm/src/queries/procedures.js +2 -3
- package/dist/esm/src/queries/procedures.js.map +1 -1
- package/dist/esm/src/queries/version.d.ts +1 -1
- package/dist/esm/src/result-transformers/graph-result-transformer.d.ts +4 -3
- package/dist/esm/src/result-transformers/graph-result-transformer.js +2 -2
- package/dist/esm/src/result-transformers/graph-result-transformer.js.map +1 -1
- package/dist/esm/src/schemaPoller.d.ts +3 -3
- package/dist/esm/src/schemaPoller.js.map +1 -1
- package/dist/esm/src/types/sdkTypes.d.ts +1 -6
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/types/src/connectionErrorHandler.d.ts +1 -2
- package/dist/types/src/cypher-execution/extract-unique-nodes-and-relationships.d.ts +1 -1
- package/dist/types/src/integration-tests/setupTestContainer.d.ts +1 -1
- package/dist/types/src/metadataPoller.d.ts +4 -4
- package/dist/types/src/neo4jConnection.d.ts +4 -4
- package/dist/types/src/queries/dataSummary.d.ts +1 -1
- package/dist/types/src/queries/databases.d.ts +3 -13
- package/dist/types/src/queries/functions.d.ts +1 -3
- package/dist/types/src/queries/graphSchema.d.ts +2 -2
- package/dist/types/src/queries/procedures.d.ts +1 -3
- package/dist/types/src/queries/version.d.ts +1 -1
- package/dist/types/src/result-transformers/graph-result-transformer.d.ts +4 -3
- package/dist/types/src/schemaPoller.d.ts +3 -3
- package/dist/types/src/types/sdkTypes.d.ts +1 -6
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -9
- package/src/connectionErrorHandler.ts +6 -3
- package/src/cypher-execution/extract-unique-nodes-and-relationships.test.ts +0 -4
- package/src/cypher-execution/extract-unique-nodes-and-relationships.ts +1 -1
- package/src/cypher-execution/query-result.ts +1 -13
- package/src/data-transforms/record-to-string.ts +2 -3
- package/src/integration-tests/pollingIntegrationTests.test.ts +6 -5
- package/src/integration-tests/setupTestContainer.ts +3 -2
- package/src/metadataPoller.ts +14 -10
- package/src/neo4jConnection.ts +6 -6
- package/src/queries/dataSummary.ts +4 -4
- package/src/queries/databases.ts +5 -7
- package/src/queries/functions.ts +7 -4
- package/src/queries/graphSchema.ts +8 -7
- package/src/queries/procedures.ts +7 -4
- package/src/queries/version.ts +1 -1
- package/src/result-transformers/graph-result-transformer.ts +5 -11
- package/src/schemaPoller.ts +4 -3
- package/src/types/sdkTypes.ts +1 -7
- package/tsconfig.json +4 -4
- package/tsconfig.node.json +1 -2
- package/dist/cjs/package.json +0 -46
- package/dist/cjs/src/connectionErrorHandler.d.ts +0 -12
- package/dist/cjs/src/connectionErrorHandler.js +0 -41
- package/dist/cjs/src/connectionErrorHandler.js.map +0 -1
- package/dist/cjs/src/cypher-execution/extract-unique-nodes-and-relationships.d.ts +0 -33
- package/dist/cjs/src/cypher-execution/extract-unique-nodes-and-relationships.js +0 -93
- package/dist/cjs/src/cypher-execution/extract-unique-nodes-and-relationships.js.map +0 -1
- package/dist/cjs/src/cypher-execution/extract-unique-nodes-and-relationships.test.d.ts +0 -1
- package/dist/cjs/src/cypher-execution/extract-unique-nodes-and-relationships.test.js +0 -129
- package/dist/cjs/src/cypher-execution/extract-unique-nodes-and-relationships.test.js.map +0 -1
- package/dist/cjs/src/cypher-execution/query-result.d.ts +0 -11
- package/dist/cjs/src/cypher-execution/query-result.js +0 -239
- package/dist/cjs/src/cypher-execution/query-result.js.map +0 -1
- package/dist/cjs/src/data-transforms/clean-type.d.ts +0 -6
- package/dist/cjs/src/data-transforms/clean-type.js +0 -16
- package/dist/cjs/src/data-transforms/clean-type.js.map +0 -1
- package/dist/cjs/src/data-transforms/cypher-type-names.d.ts +0 -6
- package/dist/cjs/src/data-transforms/cypher-type-names.js +0 -91
- package/dist/cjs/src/data-transforms/cypher-type-names.js.map +0 -1
- package/dist/cjs/src/data-transforms/format-float.d.ts +0 -1
- package/dist/cjs/src/data-transforms/format-float.js +0 -14
- package/dist/cjs/src/data-transforms/format-float.js.map +0 -1
- package/dist/cjs/src/data-transforms/record-to-string.d.ts +0 -8
- package/dist/cjs/src/data-transforms/record-to-string.js +0 -185
- package/dist/cjs/src/data-transforms/record-to-string.js.map +0 -1
- package/dist/cjs/src/index.d.ts +0 -17
- package/dist/cjs/src/index.js +0 -33
- package/dist/cjs/src/index.js.map +0 -1
- package/dist/cjs/src/integration-tests/pollingIntegrationTests.test.d.ts +0 -1
- package/dist/cjs/src/integration-tests/pollingIntegrationTests.test.js +0 -42
- package/dist/cjs/src/integration-tests/pollingIntegrationTests.test.js.map +0 -1
- package/dist/cjs/src/integration-tests/setupTestContainer.d.ts +0 -10
- package/dist/cjs/src/integration-tests/setupTestContainer.js +0 -23
- package/dist/cjs/src/integration-tests/setupTestContainer.js.map +0 -1
- package/dist/cjs/src/metadataPoller.d.ts +0 -34
- package/dist/cjs/src/metadataPoller.js +0 -214
- package/dist/cjs/src/metadataPoller.js.map +0 -1
- package/dist/cjs/src/neo4jConnection.d.ts +0 -36
- package/dist/cjs/src/neo4jConnection.js +0 -128
- package/dist/cjs/src/neo4jConnection.js.map +0 -1
- package/dist/cjs/src/queries/dataSummary.d.ts +0 -7
- package/dist/cjs/src/queries/dataSummary.js +0 -33
- package/dist/cjs/src/queries/dataSummary.js.map +0 -1
- package/dist/cjs/src/queries/databases.d.ts +0 -38
- package/dist/cjs/src/queries/databases.js +0 -114
- package/dist/cjs/src/queries/databases.js.map +0 -1
- package/dist/cjs/src/queries/functions.d.ts +0 -16
- package/dist/cjs/src/queries/functions.js +0 -88
- package/dist/cjs/src/queries/functions.js.map +0 -1
- package/dist/cjs/src/queries/graphSchema.d.ts +0 -28
- package/dist/cjs/src/queries/graphSchema.js +0 -88
- package/dist/cjs/src/queries/graphSchema.js.map +0 -1
- package/dist/cjs/src/queries/procedures.d.ts +0 -16
- package/dist/cjs/src/queries/procedures.js +0 -106
- package/dist/cjs/src/queries/procedures.js.map +0 -1
- package/dist/cjs/src/queries/roles.d.ts +0 -11
- package/dist/cjs/src/queries/roles.js +0 -24
- package/dist/cjs/src/queries/roles.js.map +0 -1
- package/dist/cjs/src/queries/users.d.ts +0 -15
- package/dist/cjs/src/queries/users.js +0 -24
- package/dist/cjs/src/queries/users.js.map +0 -1
- package/dist/cjs/src/queries/version.d.ts +0 -7
- package/dist/cjs/src/queries/version.js +0 -32
- package/dist/cjs/src/queries/version.js.map +0 -1
- package/dist/cjs/src/result-transformers/graph-result-transformer.d.ts +0 -36
- package/dist/cjs/src/result-transformers/graph-result-transformer.js +0 -37
- package/dist/cjs/src/result-transformers/graph-result-transformer.js.map +0 -1
- package/dist/cjs/src/schemaPoller.d.ts +0 -45
- package/dist/cjs/src/schemaPoller.js +0 -199
- package/dist/cjs/src/schemaPoller.js.map +0 -1
- package/dist/cjs/src/types/cypher-data-types.d.ts +0 -41
- package/dist/cjs/src/types/cypher-data-types.js +0 -47
- package/dist/cjs/src/types/cypher-data-types.js.map +0 -1
- package/dist/cjs/src/types/sdkTypes.d.ts +0 -23
- package/dist/cjs/src/types/sdkTypes.js +0 -11
- package/dist/cjs/src/types/sdkTypes.js.map +0 -1
- package/dist/cjs/tsconfig.tsbuildinfo +0 -1
- package/dist/cjs/vitest.config.d.mts +0 -2
- package/dist/cjs/vitest.config.mjs +0 -10
- package/dist/cjs/vitest.config.mjs.map +0 -1
|
@@ -0,0 +1,1848 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
ESCAPE_CHAR: () => ESCAPE_CHAR,
|
|
34
|
+
FRIENDLY_ERROR_MESSAGES: () => FRIENDLY_ERROR_MESSAGES,
|
|
35
|
+
Neo4jSchemaPoller: () => Neo4jSchemaPoller,
|
|
36
|
+
RESERVED_TYPE_PROPERTY_NAME: () => RESERVED_TYPE_PROPERTY_NAME,
|
|
37
|
+
addAnnotationProp: () => addAnnotationProp,
|
|
38
|
+
cypherDataToCypherCSVString: () => cypherDataToCypherCSVString,
|
|
39
|
+
cypherDataToString: () => cypherDataToString,
|
|
40
|
+
deleteAnnotationProp: () => deleteAnnotationProp,
|
|
41
|
+
deserializeTypeAnnotations: () => deserializeTypeAnnotations,
|
|
42
|
+
extractUniqueNodesAndRels: () => extractUniqueNodesAndRels,
|
|
43
|
+
getCypherTypeName: () => getCypherTypeName,
|
|
44
|
+
getPropertyTypeDisplayName: () => getPropertyTypeDisplayName,
|
|
45
|
+
getVersion: () => getVersion,
|
|
46
|
+
graphResultTransformer: () => graphResultTransformer,
|
|
47
|
+
isCypherBasicPropertyType: () => isCypherBasicPropertyType,
|
|
48
|
+
isCypherPropertyType: () => isCypherPropertyType,
|
|
49
|
+
isCypherTemporalType: () => isCypherTemporalType,
|
|
50
|
+
isInt8Array: () => isInt8Array,
|
|
51
|
+
propertyToString: () => propertyToString,
|
|
52
|
+
serializeTypeAnnotations: () => serializeTypeAnnotations,
|
|
53
|
+
spacialFormat: () => spacialFormat
|
|
54
|
+
});
|
|
55
|
+
module.exports = __toCommonJS(index_exports);
|
|
56
|
+
|
|
57
|
+
// src/connectionErrorHandler.ts
|
|
58
|
+
var FRIENDLY_ERROR_MESSAGES = {
|
|
59
|
+
"Neo.ClientError.Security.AuthenticationRateLimit": "Double check your username and password",
|
|
60
|
+
"Neo.ClientError.Security.CredentialsExpired": "Double check your username and password",
|
|
61
|
+
"Neo.ClientError.Security.Unauthorized": "Double check your username and password",
|
|
62
|
+
"Neo.ClientError.Security.TokenExpired": "Double check your username and password",
|
|
63
|
+
"Neo.ClientError.Database.DatabaseNotFound": "Double check that the database exists",
|
|
64
|
+
ServiceUnavailable: "Double check the scheme, host and port are correct, make sure Neo4j is running and that you have a network connection if needed",
|
|
65
|
+
Default: "An error occurred while connecting to Neo4j"
|
|
66
|
+
};
|
|
67
|
+
function isRetriableNeo4jError(error) {
|
|
68
|
+
return isNeo4jError(error) ? error.retriable : true;
|
|
69
|
+
}
|
|
70
|
+
function isNeo4jError(error) {
|
|
71
|
+
return error instanceof Error && error.code !== void 0 && error.message !== void 0;
|
|
72
|
+
}
|
|
73
|
+
function getConnectionError(error) {
|
|
74
|
+
if (isNeo4jError(error)) {
|
|
75
|
+
return {
|
|
76
|
+
message: stripTrailingPeriod(error.message),
|
|
77
|
+
code: error.code,
|
|
78
|
+
friendlyMessage: FRIENDLY_ERROR_MESSAGES[error.code] ?? FRIENDLY_ERROR_MESSAGES.Default
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
message: "",
|
|
83
|
+
code: "",
|
|
84
|
+
friendlyMessage: FRIENDLY_ERROR_MESSAGES.Default
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function stripTrailingPeriod(message) {
|
|
88
|
+
return message.endsWith(".") ? message.slice(0, -1) : message;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/cypher-execution/extract-unique-nodes-and-relationships.ts
|
|
92
|
+
var import_neo4j_driver = require("neo4j-driver");
|
|
93
|
+
var extractUniqueNodesAndRels = (records, {
|
|
94
|
+
nodeLimit,
|
|
95
|
+
keepDanglingRels = false
|
|
96
|
+
} = {}) => {
|
|
97
|
+
let limitHit = false;
|
|
98
|
+
const items = /* @__PURE__ */ new Set();
|
|
99
|
+
for (const record of records) {
|
|
100
|
+
for (const key of record.keys) {
|
|
101
|
+
items.add(record.get(key));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const paths = [];
|
|
105
|
+
const nodeMap = /* @__PURE__ */ new Map();
|
|
106
|
+
function addNode(n) {
|
|
107
|
+
if (!limitHit) {
|
|
108
|
+
const id = n.elementId.toString();
|
|
109
|
+
if (!nodeMap.has(id)) {
|
|
110
|
+
nodeMap.set(id, n);
|
|
111
|
+
}
|
|
112
|
+
if (typeof nodeLimit === "number" && nodeMap.size === nodeLimit) {
|
|
113
|
+
limitHit = true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const relMap = /* @__PURE__ */ new Map();
|
|
118
|
+
function addRel(r) {
|
|
119
|
+
const id = r.elementId.toString();
|
|
120
|
+
if (!relMap.has(id)) {
|
|
121
|
+
relMap.set(id, r);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const findAllEntities = (item) => {
|
|
125
|
+
if (typeof item !== "object" || !item) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if ((0, import_neo4j_driver.isRelationship)(item)) {
|
|
129
|
+
addRel(item);
|
|
130
|
+
} else if ((0, import_neo4j_driver.isNode)(item)) {
|
|
131
|
+
addNode(item);
|
|
132
|
+
} else if ((0, import_neo4j_driver.isPath)(item)) {
|
|
133
|
+
paths.push(item);
|
|
134
|
+
} else if (Array.isArray(item)) {
|
|
135
|
+
item.forEach(findAllEntities);
|
|
136
|
+
} else {
|
|
137
|
+
Object.values(item).forEach(findAllEntities);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
findAllEntities(Array.from(items));
|
|
141
|
+
for (const path of paths) {
|
|
142
|
+
addNode(path.start);
|
|
143
|
+
addNode(path.end);
|
|
144
|
+
for (const segment of path.segments) {
|
|
145
|
+
addNode(segment.start);
|
|
146
|
+
addNode(segment.end);
|
|
147
|
+
addRel(segment.relationship);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const nodes = Array.from(nodeMap.values());
|
|
151
|
+
const relationships = Array.from(relMap.values()).filter((item) => {
|
|
152
|
+
if (keepDanglingRels) {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
const start = item.startNodeElementId.toString();
|
|
156
|
+
const end = item.endNodeElementId.toString();
|
|
157
|
+
return nodeMap.has(start) && nodeMap.has(end);
|
|
158
|
+
});
|
|
159
|
+
return { nodes, relationships, limitHit };
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
// src/cypher-execution/query-result.ts
|
|
163
|
+
var import_neo4j_driver2 = require("neo4j-driver");
|
|
164
|
+
var RESERVED_TYPE_PROPERTY_NAME = "transport-class";
|
|
165
|
+
var ESCAPE_CHAR = "_";
|
|
166
|
+
function addAnnotationProp(obj, type, prop = RESERVED_TYPE_PROPERTY_NAME) {
|
|
167
|
+
let objShallowCopy = Object.entries(obj).reduce(
|
|
168
|
+
(newObj, [key, value]) => {
|
|
169
|
+
newObj[key] = value;
|
|
170
|
+
return newObj;
|
|
171
|
+
},
|
|
172
|
+
{}
|
|
173
|
+
);
|
|
174
|
+
if (Object.prototype.hasOwnProperty.call(objShallowCopy, prop)) {
|
|
175
|
+
objShallowCopy = addAnnotationProp(
|
|
176
|
+
objShallowCopy,
|
|
177
|
+
objShallowCopy[prop],
|
|
178
|
+
ESCAPE_CHAR + prop
|
|
179
|
+
);
|
|
180
|
+
delete objShallowCopy[prop];
|
|
181
|
+
}
|
|
182
|
+
objShallowCopy[prop] = type;
|
|
183
|
+
return objShallowCopy;
|
|
184
|
+
}
|
|
185
|
+
function deleteAnnotationProp(obj) {
|
|
186
|
+
let escapedProp = RESERVED_TYPE_PROPERTY_NAME;
|
|
187
|
+
while (Object.prototype.hasOwnProperty.call(obj, escapedProp)) {
|
|
188
|
+
obj[escapedProp.replace(ESCAPE_CHAR, "")] = obj[escapedProp];
|
|
189
|
+
delete obj[escapedProp];
|
|
190
|
+
escapedProp = ESCAPE_CHAR + escapedProp;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function copyAndAnnotate(obj) {
|
|
194
|
+
return Object.keys(obj).reduce((newObj, key) => {
|
|
195
|
+
const value = obj[key];
|
|
196
|
+
newObj[key] = serializeTypeAnnotations(value);
|
|
197
|
+
return newObj;
|
|
198
|
+
}, {});
|
|
199
|
+
}
|
|
200
|
+
function serializeTypeAnnotations(item) {
|
|
201
|
+
if (Array.isArray(item)) {
|
|
202
|
+
return item.map((i) => serializeTypeAnnotations(i));
|
|
203
|
+
}
|
|
204
|
+
if (item === null || item === void 0) {
|
|
205
|
+
return item;
|
|
206
|
+
}
|
|
207
|
+
if (item instanceof import_neo4j_driver2.types.Record) {
|
|
208
|
+
const tmp = copyAndAnnotate(item);
|
|
209
|
+
return addAnnotationProp(tmp, "Record");
|
|
210
|
+
}
|
|
211
|
+
if (item instanceof import_neo4j_driver2.types.ResultSummary) {
|
|
212
|
+
const tmp = copyAndAnnotate(item);
|
|
213
|
+
return addAnnotationProp(tmp, "ResultSummary");
|
|
214
|
+
}
|
|
215
|
+
if (item instanceof import_neo4j_driver2.types.Node) {
|
|
216
|
+
const tmp = copyAndAnnotate(item);
|
|
217
|
+
return addAnnotationProp(tmp, "Node");
|
|
218
|
+
}
|
|
219
|
+
if (item instanceof import_neo4j_driver2.types.PathSegment) {
|
|
220
|
+
const tmp = copyAndAnnotate(item);
|
|
221
|
+
return addAnnotationProp(tmp, "PathSegment");
|
|
222
|
+
}
|
|
223
|
+
if (item instanceof import_neo4j_driver2.types.Path) {
|
|
224
|
+
const tmp = copyAndAnnotate(item);
|
|
225
|
+
return addAnnotationProp(tmp, "Path");
|
|
226
|
+
}
|
|
227
|
+
if (item instanceof import_neo4j_driver2.types.Relationship) {
|
|
228
|
+
const tmp = copyAndAnnotate(item);
|
|
229
|
+
return addAnnotationProp(tmp, "Relationship");
|
|
230
|
+
}
|
|
231
|
+
if (item instanceof import_neo4j_driver2.types.Point) {
|
|
232
|
+
const tmp = copyAndAnnotate(item);
|
|
233
|
+
return addAnnotationProp(tmp, "Point");
|
|
234
|
+
}
|
|
235
|
+
if (item instanceof import_neo4j_driver2.types.Date) {
|
|
236
|
+
const tmp = copyAndAnnotate(item);
|
|
237
|
+
return addAnnotationProp(tmp, "Date");
|
|
238
|
+
}
|
|
239
|
+
if (item instanceof import_neo4j_driver2.types.DateTime) {
|
|
240
|
+
const tmp = copyAndAnnotate(item);
|
|
241
|
+
return addAnnotationProp(tmp, "DateTime");
|
|
242
|
+
}
|
|
243
|
+
if (item instanceof import_neo4j_driver2.types.Duration) {
|
|
244
|
+
const tmp = copyAndAnnotate(item);
|
|
245
|
+
return addAnnotationProp(tmp, "Duration");
|
|
246
|
+
}
|
|
247
|
+
if (item instanceof import_neo4j_driver2.types.LocalDateTime) {
|
|
248
|
+
const tmp = copyAndAnnotate(item);
|
|
249
|
+
return addAnnotationProp(tmp, "LocalDateTime");
|
|
250
|
+
}
|
|
251
|
+
if (item instanceof import_neo4j_driver2.types.LocalTime) {
|
|
252
|
+
const tmp = copyAndAnnotate(item);
|
|
253
|
+
return addAnnotationProp(tmp, "LocalTime");
|
|
254
|
+
}
|
|
255
|
+
if (item instanceof import_neo4j_driver2.types.Time) {
|
|
256
|
+
const tmp = copyAndAnnotate(item);
|
|
257
|
+
return addAnnotationProp(tmp, "Time");
|
|
258
|
+
}
|
|
259
|
+
if ((0, import_neo4j_driver2.isInt)(item)) {
|
|
260
|
+
const tmp = { ...item };
|
|
261
|
+
return addAnnotationProp(tmp, "Integer");
|
|
262
|
+
}
|
|
263
|
+
if ((0, import_neo4j_driver2.isVector)(item)) {
|
|
264
|
+
const typedArray = item.asTypedArray();
|
|
265
|
+
const values = typedArray instanceof BigInt64Array ? Array.from(typedArray, (v) => v.toString()) : Array.from(typedArray);
|
|
266
|
+
return addAnnotationProp(
|
|
267
|
+
{
|
|
268
|
+
_type: item.getType(),
|
|
269
|
+
_values: values
|
|
270
|
+
},
|
|
271
|
+
"Vector"
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
if (typeof item === "object") {
|
|
275
|
+
const tmp = copyAndAnnotate(item);
|
|
276
|
+
return addAnnotationProp(tmp, "Object");
|
|
277
|
+
}
|
|
278
|
+
return item;
|
|
279
|
+
}
|
|
280
|
+
function deserializeTypeAnnotations(rawItem) {
|
|
281
|
+
if (Array.isArray(rawItem)) {
|
|
282
|
+
const mapped = rawItem.map((i) => deserializeTypeAnnotations(i));
|
|
283
|
+
return mapped;
|
|
284
|
+
}
|
|
285
|
+
if (rawItem === null || rawItem === void 0 || typeof rawItem === "boolean" || typeof rawItem === "string" || !Object.prototype.hasOwnProperty.call(rawItem, RESERVED_TYPE_PROPERTY_NAME)) {
|
|
286
|
+
return rawItem;
|
|
287
|
+
}
|
|
288
|
+
const item = { ...rawItem };
|
|
289
|
+
const className = item[RESERVED_TYPE_PROPERTY_NAME];
|
|
290
|
+
deleteAnnotationProp(item);
|
|
291
|
+
switch (className) {
|
|
292
|
+
case "Record":
|
|
293
|
+
return new import_neo4j_driver2.types.Record(
|
|
294
|
+
deserializeTypeAnnotations(item.keys),
|
|
295
|
+
deserializeTypeAnnotations(item._fields),
|
|
296
|
+
deserializeTypeAnnotations(item._fieldLookup)
|
|
297
|
+
);
|
|
298
|
+
case "ResultSummary": {
|
|
299
|
+
const metadata = {
|
|
300
|
+
...item,
|
|
301
|
+
type: item.queryType,
|
|
302
|
+
db: item.database.name,
|
|
303
|
+
result_available_after: deserializeTypeAnnotations(
|
|
304
|
+
item.resultAvailableAfter
|
|
305
|
+
),
|
|
306
|
+
result_consumed_after: deserializeTypeAnnotations(
|
|
307
|
+
item.resultConsumedAfter
|
|
308
|
+
),
|
|
309
|
+
profile: item.profile === false ? null : item.profile,
|
|
310
|
+
plan: item.plan === false ? null : item.plan,
|
|
311
|
+
stream_summary: { have_records_streamed: true },
|
|
312
|
+
server: {
|
|
313
|
+
...item.server,
|
|
314
|
+
version: item.server.agent
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
return new import_neo4j_driver2.types.ResultSummary(
|
|
318
|
+
deserializeTypeAnnotations(item.query.text),
|
|
319
|
+
deserializeTypeAnnotations(item.query.parameters),
|
|
320
|
+
deserializeTypeAnnotations(metadata),
|
|
321
|
+
deserializeTypeAnnotations(item.server.protocolVersion)
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
case "Node":
|
|
325
|
+
return new import_neo4j_driver2.types.Node(
|
|
326
|
+
deserializeTypeAnnotations(item.identity),
|
|
327
|
+
item.labels,
|
|
328
|
+
deserializeTypeAnnotations(item.properties),
|
|
329
|
+
item.elementId
|
|
330
|
+
);
|
|
331
|
+
case "Relationship":
|
|
332
|
+
return new import_neo4j_driver2.types.Relationship(
|
|
333
|
+
deserializeTypeAnnotations(item.identity),
|
|
334
|
+
deserializeTypeAnnotations(item.start),
|
|
335
|
+
deserializeTypeAnnotations(item.end),
|
|
336
|
+
item.type,
|
|
337
|
+
deserializeTypeAnnotations(item.properties),
|
|
338
|
+
item.elementId,
|
|
339
|
+
item.startNodeElementId,
|
|
340
|
+
item.endNodeElementId
|
|
341
|
+
);
|
|
342
|
+
case "PathSegment":
|
|
343
|
+
return new import_neo4j_driver2.types.PathSegment(
|
|
344
|
+
deserializeTypeAnnotations(item.start),
|
|
345
|
+
deserializeTypeAnnotations(item.relationship),
|
|
346
|
+
deserializeTypeAnnotations(item.end)
|
|
347
|
+
);
|
|
348
|
+
case "Path": {
|
|
349
|
+
const { segments } = item;
|
|
350
|
+
return new import_neo4j_driver2.types.Path(
|
|
351
|
+
deserializeTypeAnnotations(item.start),
|
|
352
|
+
deserializeTypeAnnotations(item.end),
|
|
353
|
+
(Array.isArray(segments) ? segments : []).map(
|
|
354
|
+
(x) => deserializeTypeAnnotations(x)
|
|
355
|
+
)
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
case "Point":
|
|
359
|
+
return new import_neo4j_driver2.types.Point(
|
|
360
|
+
deserializeTypeAnnotations(item.srid),
|
|
361
|
+
deserializeTypeAnnotations(item.x),
|
|
362
|
+
deserializeTypeAnnotations(item.y),
|
|
363
|
+
deserializeTypeAnnotations(item.z)
|
|
364
|
+
);
|
|
365
|
+
case "Date":
|
|
366
|
+
return new import_neo4j_driver2.types.Date(
|
|
367
|
+
deserializeTypeAnnotations(item.year),
|
|
368
|
+
deserializeTypeAnnotations(item.month),
|
|
369
|
+
deserializeTypeAnnotations(item.day)
|
|
370
|
+
);
|
|
371
|
+
case "DateTime":
|
|
372
|
+
return new import_neo4j_driver2.types.DateTime(
|
|
373
|
+
deserializeTypeAnnotations(item.year),
|
|
374
|
+
deserializeTypeAnnotations(item.month),
|
|
375
|
+
deserializeTypeAnnotations(item.day),
|
|
376
|
+
deserializeTypeAnnotations(item.hour),
|
|
377
|
+
deserializeTypeAnnotations(item.minute),
|
|
378
|
+
deserializeTypeAnnotations(item.second),
|
|
379
|
+
deserializeTypeAnnotations(item.nanosecond),
|
|
380
|
+
deserializeTypeAnnotations(item.timeZoneOffsetSeconds),
|
|
381
|
+
deserializeTypeAnnotations(item.timeZoneId)
|
|
382
|
+
);
|
|
383
|
+
case "Duration":
|
|
384
|
+
return new import_neo4j_driver2.types.Duration(
|
|
385
|
+
deserializeTypeAnnotations(item.months),
|
|
386
|
+
deserializeTypeAnnotations(item.days),
|
|
387
|
+
deserializeTypeAnnotations(item.seconds),
|
|
388
|
+
deserializeTypeAnnotations(item.nanoseconds)
|
|
389
|
+
);
|
|
390
|
+
case "LocalDateTime":
|
|
391
|
+
return new import_neo4j_driver2.types.LocalDateTime(
|
|
392
|
+
deserializeTypeAnnotations(item.year),
|
|
393
|
+
deserializeTypeAnnotations(item.month),
|
|
394
|
+
deserializeTypeAnnotations(item.day),
|
|
395
|
+
deserializeTypeAnnotations(item.hour),
|
|
396
|
+
deserializeTypeAnnotations(item.minute),
|
|
397
|
+
deserializeTypeAnnotations(item.second),
|
|
398
|
+
deserializeTypeAnnotations(item.nanosecond)
|
|
399
|
+
);
|
|
400
|
+
case "LocalTime":
|
|
401
|
+
return new import_neo4j_driver2.types.LocalTime(
|
|
402
|
+
deserializeTypeAnnotations(item.hour),
|
|
403
|
+
deserializeTypeAnnotations(item.minute),
|
|
404
|
+
deserializeTypeAnnotations(item.second),
|
|
405
|
+
deserializeTypeAnnotations(item.nanosecond)
|
|
406
|
+
);
|
|
407
|
+
case "Time":
|
|
408
|
+
return new import_neo4j_driver2.types.Time(
|
|
409
|
+
deserializeTypeAnnotations(item.hour),
|
|
410
|
+
deserializeTypeAnnotations(item.minute),
|
|
411
|
+
deserializeTypeAnnotations(item.second),
|
|
412
|
+
deserializeTypeAnnotations(item.nanosecond),
|
|
413
|
+
deserializeTypeAnnotations(item.timeZoneOffsetSeconds)
|
|
414
|
+
);
|
|
415
|
+
case "Integer":
|
|
416
|
+
return (0, import_neo4j_driver2.int)(item);
|
|
417
|
+
case "Vector": {
|
|
418
|
+
const type = item._type;
|
|
419
|
+
const values = item._values;
|
|
420
|
+
let typedArray;
|
|
421
|
+
switch (type) {
|
|
422
|
+
case "INT8":
|
|
423
|
+
typedArray = new Int8Array(values);
|
|
424
|
+
break;
|
|
425
|
+
case "INT16":
|
|
426
|
+
typedArray = new Int16Array(values);
|
|
427
|
+
break;
|
|
428
|
+
case "INT32":
|
|
429
|
+
typedArray = new Int32Array(values);
|
|
430
|
+
break;
|
|
431
|
+
case "INT64":
|
|
432
|
+
typedArray = new BigInt64Array(values.map((v) => BigInt(v)));
|
|
433
|
+
break;
|
|
434
|
+
case "FLOAT32":
|
|
435
|
+
typedArray = new Float32Array(values);
|
|
436
|
+
break;
|
|
437
|
+
case "FLOAT64":
|
|
438
|
+
typedArray = new Float64Array(values);
|
|
439
|
+
break;
|
|
440
|
+
default:
|
|
441
|
+
return item;
|
|
442
|
+
}
|
|
443
|
+
return new import_neo4j_driver2.Vector(typedArray);
|
|
444
|
+
}
|
|
445
|
+
case "Object":
|
|
446
|
+
return Object.keys(item).reduce(
|
|
447
|
+
(newObj, key) => {
|
|
448
|
+
newObj[key] = deserializeTypeAnnotations(item[key]);
|
|
449
|
+
return newObj;
|
|
450
|
+
},
|
|
451
|
+
{}
|
|
452
|
+
);
|
|
453
|
+
default:
|
|
454
|
+
return item;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// src/data-transforms/cypher-type-names.ts
|
|
459
|
+
var import_neo4j_driver4 = require("neo4j-driver");
|
|
460
|
+
|
|
461
|
+
// src/types/cypher-data-types.ts
|
|
462
|
+
var import_neo4j_driver3 = require("neo4j-driver");
|
|
463
|
+
var isCypherTemporalType = (anything) => {
|
|
464
|
+
if (typeof anything === "object" && anything !== null) {
|
|
465
|
+
return [
|
|
466
|
+
import_neo4j_driver3.isDate,
|
|
467
|
+
import_neo4j_driver3.isTime,
|
|
468
|
+
import_neo4j_driver3.isDateTime,
|
|
469
|
+
import_neo4j_driver3.isLocalTime,
|
|
470
|
+
import_neo4j_driver3.isLocalDateTime,
|
|
471
|
+
import_neo4j_driver3.isDuration
|
|
472
|
+
].some((tester) => tester(anything));
|
|
473
|
+
}
|
|
474
|
+
return false;
|
|
475
|
+
};
|
|
476
|
+
var isCypherBasicPropertyType = (value) => {
|
|
477
|
+
const valType = typeof value;
|
|
478
|
+
return value === null || valType === "boolean" || valType === "string" || valType === "number" || valType === "bigint" || value?.constructor === Int8Array || (0, import_neo4j_driver3.isInt)(value) || isCypherTemporalType(value) || (0, import_neo4j_driver3.isPoint)(value) || (0, import_neo4j_driver3.isVector)(value);
|
|
479
|
+
};
|
|
480
|
+
var isCypherPropertyType = (value) => {
|
|
481
|
+
if (Array.isArray(value)) {
|
|
482
|
+
if (value.length === 0) {
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
return isCypherBasicPropertyType(value[0]);
|
|
486
|
+
}
|
|
487
|
+
return isCypherBasicPropertyType(value);
|
|
488
|
+
};
|
|
489
|
+
function isInt8Array(val) {
|
|
490
|
+
return typeof val === "object" && val !== null && val.constructor === Int8Array;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// src/data-transforms/cypher-type-names.ts
|
|
494
|
+
var capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
495
|
+
var getPropertyTypeDisplayName = (val) => {
|
|
496
|
+
const jsType = typeof val;
|
|
497
|
+
if (jsType === "number") {
|
|
498
|
+
return "Float";
|
|
499
|
+
}
|
|
500
|
+
if (val === null || val === void 0) {
|
|
501
|
+
return "null";
|
|
502
|
+
}
|
|
503
|
+
if (typeof val !== "object") {
|
|
504
|
+
const capitalized = capitalize(jsType);
|
|
505
|
+
switch (capitalized) {
|
|
506
|
+
case "String":
|
|
507
|
+
case "Bigint":
|
|
508
|
+
case "Boolean":
|
|
509
|
+
return capitalized;
|
|
510
|
+
default:
|
|
511
|
+
return "Unknown";
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
if (val instanceof Array) {
|
|
515
|
+
const [firstVal] = val;
|
|
516
|
+
if (firstVal !== void 0) {
|
|
517
|
+
return `List<${getPropertyTypeDisplayName(firstVal)}>(${val.length})`;
|
|
518
|
+
}
|
|
519
|
+
return `List(${val.length})`;
|
|
520
|
+
}
|
|
521
|
+
if ((0, import_neo4j_driver4.isLocalTime)(val)) {
|
|
522
|
+
return "LocalTime";
|
|
523
|
+
}
|
|
524
|
+
if ((0, import_neo4j_driver4.isTime)(val)) {
|
|
525
|
+
return "Time";
|
|
526
|
+
}
|
|
527
|
+
if ((0, import_neo4j_driver4.isDate)(val)) {
|
|
528
|
+
return "Date";
|
|
529
|
+
}
|
|
530
|
+
if ((0, import_neo4j_driver4.isLocalDateTime)(val)) {
|
|
531
|
+
return "LocalDateTime";
|
|
532
|
+
}
|
|
533
|
+
if ((0, import_neo4j_driver4.isDateTime)(val)) {
|
|
534
|
+
return "DateTime";
|
|
535
|
+
}
|
|
536
|
+
if ((0, import_neo4j_driver4.isInt)(val)) {
|
|
537
|
+
return "Integer";
|
|
538
|
+
}
|
|
539
|
+
if ((0, import_neo4j_driver4.isDuration)(val)) {
|
|
540
|
+
return "Duration";
|
|
541
|
+
}
|
|
542
|
+
if ((0, import_neo4j_driver4.isPoint)(val)) {
|
|
543
|
+
return "Point";
|
|
544
|
+
}
|
|
545
|
+
if (isInt8Array(val)) {
|
|
546
|
+
return "ByteArray";
|
|
547
|
+
}
|
|
548
|
+
if ((0, import_neo4j_driver4.isVector)(val)) {
|
|
549
|
+
return "Vector";
|
|
550
|
+
}
|
|
551
|
+
return "Unknown";
|
|
552
|
+
};
|
|
553
|
+
function getCypherTypeName(val) {
|
|
554
|
+
if (Array.isArray(val)) {
|
|
555
|
+
return "List";
|
|
556
|
+
}
|
|
557
|
+
if (isCypherBasicPropertyType(val)) {
|
|
558
|
+
return getPropertyTypeDisplayName(val);
|
|
559
|
+
}
|
|
560
|
+
if ((0, import_neo4j_driver4.isNode)(val)) {
|
|
561
|
+
return "Node";
|
|
562
|
+
}
|
|
563
|
+
if ((0, import_neo4j_driver4.isRelationship)(val)) {
|
|
564
|
+
return "Relationship";
|
|
565
|
+
}
|
|
566
|
+
if ((0, import_neo4j_driver4.isPath)(val)) {
|
|
567
|
+
return "Path";
|
|
568
|
+
}
|
|
569
|
+
if ((0, import_neo4j_driver4.isVector)(val)) {
|
|
570
|
+
return "Vector";
|
|
571
|
+
}
|
|
572
|
+
return "Map";
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// src/data-transforms/record-to-string.ts
|
|
576
|
+
var import_neo4j_driver5 = require("neo4j-driver");
|
|
577
|
+
|
|
578
|
+
// src/data-transforms/format-float.ts
|
|
579
|
+
var formatFloat = (anything) => {
|
|
580
|
+
if ([Infinity, -Infinity, NaN].includes(anything)) {
|
|
581
|
+
return `${anything}`;
|
|
582
|
+
}
|
|
583
|
+
if (Math.floor(anything) === anything) {
|
|
584
|
+
return `${anything}.0`;
|
|
585
|
+
}
|
|
586
|
+
return anything.toString();
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
// src/data-transforms/record-to-string.ts
|
|
590
|
+
var spacialFormat = (p) => {
|
|
591
|
+
const zString = p.z !== void 0 ? `, z:${formatFloat(p.z)}` : "";
|
|
592
|
+
return `point({srid:${p.srid.toString()}, x:${formatFloat(
|
|
593
|
+
p.x
|
|
594
|
+
)}, y:${formatFloat(p.y)}${zString}})`;
|
|
595
|
+
};
|
|
596
|
+
function propertyToString(property, quoteStrings = true, localeFormattedDates = false) {
|
|
597
|
+
if (Array.isArray(property)) {
|
|
598
|
+
return `[${property.map((p) => propertyToString(p, quoteStrings)).join(", ")}]`;
|
|
599
|
+
}
|
|
600
|
+
if (property === null) {
|
|
601
|
+
return "null";
|
|
602
|
+
}
|
|
603
|
+
if (isCypherTemporalType(property)) {
|
|
604
|
+
if ((0, import_neo4j_driver5.isDate)(property) && localeFormattedDates) {
|
|
605
|
+
return property.toStandardDate().toLocaleDateString();
|
|
606
|
+
}
|
|
607
|
+
if ((0, import_neo4j_driver5.isLocalDateTime)(property) && localeFormattedDates) {
|
|
608
|
+
return property.toStandardDate().toLocaleString();
|
|
609
|
+
}
|
|
610
|
+
return property.toString();
|
|
611
|
+
}
|
|
612
|
+
if (typeof property === "boolean" || (0, import_neo4j_driver5.isInt)(property) || typeof property === "bigint" || (0, import_neo4j_driver5.isVector)(property)) {
|
|
613
|
+
return property.toString();
|
|
614
|
+
}
|
|
615
|
+
if ((0, import_neo4j_driver5.isPoint)(property)) {
|
|
616
|
+
return spacialFormat(property);
|
|
617
|
+
}
|
|
618
|
+
if (typeof property === "number") {
|
|
619
|
+
return formatFloat(property);
|
|
620
|
+
}
|
|
621
|
+
if (typeof property === "string") {
|
|
622
|
+
if (quoteStrings) {
|
|
623
|
+
return `"${property}"`;
|
|
624
|
+
}
|
|
625
|
+
return property;
|
|
626
|
+
}
|
|
627
|
+
if (isInt8Array(property)) {
|
|
628
|
+
return "ByteArray";
|
|
629
|
+
}
|
|
630
|
+
return String(property);
|
|
631
|
+
}
|
|
632
|
+
var cypherShellStyleStringify = (value, {
|
|
633
|
+
stringStyle,
|
|
634
|
+
quoteStrings
|
|
635
|
+
}) => {
|
|
636
|
+
const includeIds = stringStyle === "cypher-with-ids";
|
|
637
|
+
if ((0, import_neo4j_driver5.isNode)(value)) {
|
|
638
|
+
const labels = value.labels.length > 0 ? `:${value.labels.join(":")}` : "";
|
|
639
|
+
const properties = Object.entries(value.properties).map(([key, val]) => {
|
|
640
|
+
return `${key}: ${propertyToString(val, quoteStrings)}`;
|
|
641
|
+
}).concat(
|
|
642
|
+
includeIds ? [
|
|
643
|
+
`<elementId>: "${value.elementId.toString()}", <id>: ${value.identity.toString()}`
|
|
644
|
+
] : []
|
|
645
|
+
).join(", ");
|
|
646
|
+
const propertiesString = properties.length > 0 ? `{${properties}}` : "";
|
|
647
|
+
const space = labels.length > 0 && propertiesString.length > 0 ? " " : "";
|
|
648
|
+
return `(${labels}${space}${propertiesString})`;
|
|
649
|
+
} else if ((0, import_neo4j_driver5.isRelationship)(value)) {
|
|
650
|
+
const type = value.type ? `:${value.type}` : "";
|
|
651
|
+
const properties = Object.entries(value.properties).map(([key, val]) => {
|
|
652
|
+
return `${key}: ${propertyToString(val, quoteStrings)}`;
|
|
653
|
+
}).concat(
|
|
654
|
+
includeIds ? [
|
|
655
|
+
`<elementId>: ${quoteStrings ? `"${value.elementId.toString()}"` : value.elementId.toString()}, <id>: ${value.identity.toString()}`
|
|
656
|
+
] : []
|
|
657
|
+
).join(", ");
|
|
658
|
+
const propertiesString = properties.length > 0 ? ` {${properties}}` : "";
|
|
659
|
+
return `[${type}${propertiesString}]`;
|
|
660
|
+
} else if ((0, import_neo4j_driver5.isPath)(value)) {
|
|
661
|
+
if (value.segments.length === 0) {
|
|
662
|
+
return cypherShellStyleStringify(value.start, {
|
|
663
|
+
stringStyle,
|
|
664
|
+
quoteStrings
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
return value.segments.map((segment, index) => {
|
|
668
|
+
const result = [];
|
|
669
|
+
if (index === 0) {
|
|
670
|
+
result.push(
|
|
671
|
+
cypherShellStyleStringify(segment.start, {
|
|
672
|
+
stringStyle,
|
|
673
|
+
quoteStrings
|
|
674
|
+
})
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
if (segment.start.elementId === segment.relationship.startNodeElementId) {
|
|
678
|
+
result.push("-");
|
|
679
|
+
result.push(
|
|
680
|
+
cypherShellStyleStringify(segment.relationship, {
|
|
681
|
+
stringStyle,
|
|
682
|
+
quoteStrings
|
|
683
|
+
})
|
|
684
|
+
);
|
|
685
|
+
result.push("->");
|
|
686
|
+
result.push(
|
|
687
|
+
cypherShellStyleStringify(segment.end, {
|
|
688
|
+
stringStyle,
|
|
689
|
+
quoteStrings
|
|
690
|
+
})
|
|
691
|
+
);
|
|
692
|
+
} else {
|
|
693
|
+
result.push("<-");
|
|
694
|
+
result.push(
|
|
695
|
+
cypherShellStyleStringify(segment.relationship, {
|
|
696
|
+
stringStyle,
|
|
697
|
+
quoteStrings
|
|
698
|
+
})
|
|
699
|
+
);
|
|
700
|
+
result.push("-");
|
|
701
|
+
result.push(
|
|
702
|
+
cypherShellStyleStringify(segment.end, {
|
|
703
|
+
stringStyle,
|
|
704
|
+
quoteStrings
|
|
705
|
+
})
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
return result.join("");
|
|
709
|
+
}).join("");
|
|
710
|
+
}
|
|
711
|
+
return "";
|
|
712
|
+
};
|
|
713
|
+
var recursiveStringify = (value, {
|
|
714
|
+
indentationLevel = 0,
|
|
715
|
+
quoteStrings = true,
|
|
716
|
+
stringStyle = "json"
|
|
717
|
+
} = {}) => {
|
|
718
|
+
if (value === void 0) {
|
|
719
|
+
return "";
|
|
720
|
+
}
|
|
721
|
+
const indentation = " ".repeat(indentationLevel);
|
|
722
|
+
const nextIndentationLevel = indentationLevel + 1;
|
|
723
|
+
const nextIdentation = " ".repeat(nextIndentationLevel);
|
|
724
|
+
if (isCypherPropertyType(value)) {
|
|
725
|
+
return propertyToString(value, quoteStrings);
|
|
726
|
+
}
|
|
727
|
+
if (Array.isArray(value)) {
|
|
728
|
+
return `[
|
|
729
|
+
${value.map(
|
|
730
|
+
(v) => `${nextIdentation}${recursiveStringify(v, {
|
|
731
|
+
indentationLevel: nextIndentationLevel,
|
|
732
|
+
quoteStrings
|
|
733
|
+
})}`
|
|
734
|
+
).join(",\n")}
|
|
735
|
+
${indentation}]`;
|
|
736
|
+
}
|
|
737
|
+
if (stringStyle !== "json" && ((0, import_neo4j_driver5.isNode)(value) || (0, import_neo4j_driver5.isRelationship)(value) || (0, import_neo4j_driver5.isPath)(value))) {
|
|
738
|
+
return cypherShellStyleStringify(value, { stringStyle, quoteStrings });
|
|
739
|
+
}
|
|
740
|
+
const entries = Object.entries(value);
|
|
741
|
+
if (entries.length === 0) {
|
|
742
|
+
return "{}";
|
|
743
|
+
}
|
|
744
|
+
return `{
|
|
745
|
+
${entries.map(([key, val]) => {
|
|
746
|
+
return `${nextIdentation}${key}: ${recursiveStringify(val, {
|
|
747
|
+
indentationLevel: nextIndentationLevel,
|
|
748
|
+
quoteStrings
|
|
749
|
+
})}`;
|
|
750
|
+
}).join(",\n")}
|
|
751
|
+
${indentation}}`;
|
|
752
|
+
};
|
|
753
|
+
var cypherDataToString = (map, stringStyle = "json", quoteStrings = true) => {
|
|
754
|
+
return recursiveStringify(map, { quoteStrings, stringStyle });
|
|
755
|
+
};
|
|
756
|
+
var cypherDataToCypherCSVString = (map, stringStyle) => {
|
|
757
|
+
return recursiveStringify(map, { quoteStrings: false, stringStyle });
|
|
758
|
+
};
|
|
759
|
+
|
|
760
|
+
// src/result-transformers/graph-result-transformer.ts
|
|
761
|
+
var import_neo4j_driver6 = require("neo4j-driver");
|
|
762
|
+
var graphResultTransformer = import_neo4j_driver6.resultTransformers.mapped({
|
|
763
|
+
map(record) {
|
|
764
|
+
return record;
|
|
765
|
+
},
|
|
766
|
+
collect(records, summary) {
|
|
767
|
+
const { nodes, relationships, limitHit } = extractUniqueNodesAndRels(records);
|
|
768
|
+
return { nodes, relationships, limitHit, records, summary };
|
|
769
|
+
}
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
// src/schemaPoller.ts
|
|
773
|
+
var import_events = require("events");
|
|
774
|
+
var import_neo4j_driver15 = __toESM(require("neo4j-driver"), 1);
|
|
775
|
+
|
|
776
|
+
// src/metadataPoller.ts
|
|
777
|
+
var import_language_support = require("@neo4j-cypher/language-support");
|
|
778
|
+
|
|
779
|
+
// src/queries/databases.ts
|
|
780
|
+
var import_neo4j_driver7 = require("neo4j-driver");
|
|
781
|
+
|
|
782
|
+
// src/types/sdkTypes.ts
|
|
783
|
+
var DbType = {
|
|
784
|
+
SYSTEM: "system",
|
|
785
|
+
STANDARD: "standard",
|
|
786
|
+
COMPOSITE: "composite",
|
|
787
|
+
GRAPH_SHARD: "graph shard",
|
|
788
|
+
PROPERTY_SHARD: "property shard"
|
|
789
|
+
};
|
|
790
|
+
|
|
791
|
+
// src/queries/databases.ts
|
|
792
|
+
var findComposite = (databases, alias) => {
|
|
793
|
+
const compositeDatabases = databases.filter((db) => db.type === "composite");
|
|
794
|
+
return compositeDatabases.find((db) => db.constituents?.includes(alias));
|
|
795
|
+
};
|
|
796
|
+
var isCompositeAlias = (databases, alias) => findComposite(databases, alias) !== void 0;
|
|
797
|
+
var removeCompositeAliases = (databases) => {
|
|
798
|
+
return databases.map(({ aliases, ...db }) => ({
|
|
799
|
+
...db,
|
|
800
|
+
aliases: aliases?.filter((alias) => !isCompositeAlias(databases, alias))
|
|
801
|
+
}));
|
|
802
|
+
};
|
|
803
|
+
var removeSPDShards = (databases) => {
|
|
804
|
+
return databases.filter((db) => {
|
|
805
|
+
return !(db.type !== void 0 && (db.type === DbType.GRAPH_SHARD || db.type === DbType.PROPERTY_SHARD));
|
|
806
|
+
});
|
|
807
|
+
};
|
|
808
|
+
function listDatabases() {
|
|
809
|
+
const query = "SHOW DATABASES YIELD *";
|
|
810
|
+
const resultTransformer = import_neo4j_driver7.resultTransformers.mapped({
|
|
811
|
+
map(record) {
|
|
812
|
+
const obj = record.toObject();
|
|
813
|
+
if (obj.defaultLanguage) {
|
|
814
|
+
obj.defaultLanguage = obj.defaultLanguage.toUpperCase();
|
|
815
|
+
}
|
|
816
|
+
return obj;
|
|
817
|
+
},
|
|
818
|
+
collect(databases, summary) {
|
|
819
|
+
const instancesRecord = databases.reduce((acc, db) => {
|
|
820
|
+
const instanceId = `${db.name}@${db.address}`;
|
|
821
|
+
acc[instanceId] = db;
|
|
822
|
+
return acc;
|
|
823
|
+
}, {});
|
|
824
|
+
const logicalDatabases = getLogicalDatabases(instancesRecord);
|
|
825
|
+
const uiDatabases = removeSPDShards(
|
|
826
|
+
removeCompositeAliases(Object.values(logicalDatabases))
|
|
827
|
+
);
|
|
828
|
+
return {
|
|
829
|
+
databases: sortDatabases(uiDatabases),
|
|
830
|
+
summary
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
});
|
|
834
|
+
return {
|
|
835
|
+
query,
|
|
836
|
+
queryConfig: { resultTransformer, routing: "READ", database: "system" }
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
function getLogicalDatabases(instances) {
|
|
840
|
+
const mergeDatabases = (db1, db2) => {
|
|
841
|
+
let mergedDatabase = { ...db1 };
|
|
842
|
+
if (db2.role === "leader" || db2.writer === true) {
|
|
843
|
+
mergedDatabase = { ...db2 };
|
|
844
|
+
}
|
|
845
|
+
return mergedDatabase;
|
|
846
|
+
};
|
|
847
|
+
return Object.values(instances).reduce(
|
|
848
|
+
(databases, instance) => {
|
|
849
|
+
const key = instance.name;
|
|
850
|
+
const existingDatabase = databases[key];
|
|
851
|
+
const mergedDatabase = existingDatabase ? mergeDatabases(existingDatabase, instance) : instance;
|
|
852
|
+
return {
|
|
853
|
+
...databases,
|
|
854
|
+
[key]: mergedDatabase
|
|
855
|
+
};
|
|
856
|
+
},
|
|
857
|
+
{}
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
function sortDatabases(databases) {
|
|
861
|
+
function databaseComparator(a, b) {
|
|
862
|
+
if (a.default && b.home) return 1;
|
|
863
|
+
if (a.default) return -1;
|
|
864
|
+
if (b.default) return 1;
|
|
865
|
+
if (a.name === "system") return 1;
|
|
866
|
+
if (b.name === "system") return -1;
|
|
867
|
+
return a.name.localeCompare(b.name);
|
|
868
|
+
}
|
|
869
|
+
return databases.sort(databaseComparator);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
// src/queries/dataSummary.ts
|
|
873
|
+
var import_neo4j_driver8 = require("neo4j-driver");
|
|
874
|
+
var ITEM_LIMIT = 1e3;
|
|
875
|
+
function getDataSummary(database) {
|
|
876
|
+
const query = `CALL db.labels() YIELD label
|
|
877
|
+
RETURN COLLECT(label)[..${ITEM_LIMIT}] AS result
|
|
878
|
+
UNION ALL
|
|
879
|
+
CALL db.relationshipTypes() YIELD relationshipType
|
|
880
|
+
RETURN COLLECT(relationshipType)[..${ITEM_LIMIT}] AS result
|
|
881
|
+
UNION ALL
|
|
882
|
+
CALL db.propertyKeys() YIELD propertyKey
|
|
883
|
+
RETURN COLLECT(propertyKey)[..${ITEM_LIMIT}] AS result`;
|
|
884
|
+
const resultTransformer = import_neo4j_driver8.resultTransformers.mapped({
|
|
885
|
+
map(record) {
|
|
886
|
+
return record.toObject().result;
|
|
887
|
+
},
|
|
888
|
+
collect(results, summary) {
|
|
889
|
+
return {
|
|
890
|
+
labels: results[0],
|
|
891
|
+
relationshipTypes: results[1],
|
|
892
|
+
propertyKeys: results[2],
|
|
893
|
+
summary
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
});
|
|
897
|
+
return {
|
|
898
|
+
query,
|
|
899
|
+
queryConfig: { resultTransformer, routing: "READ", database }
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
// src/queries/functions.ts
|
|
904
|
+
var import_ajv = require("ajv");
|
|
905
|
+
var import_neo4j_driver9 = require("neo4j-driver");
|
|
906
|
+
|
|
907
|
+
// src/data-transforms/clean-type.ts
|
|
908
|
+
function cleanType(type) {
|
|
909
|
+
let resultType = type;
|
|
910
|
+
if (resultType.startsWith("LIST? OF ")) {
|
|
911
|
+
resultType = resultType.replace("LIST? OF ", "LIST<");
|
|
912
|
+
resultType += ">";
|
|
913
|
+
}
|
|
914
|
+
return resultType.replace(/\?/g, "");
|
|
915
|
+
}
|
|
916
|
+
function cleanTypeDescription(arg) {
|
|
917
|
+
return { ...arg, type: cleanType(arg.type) };
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// src/queries/functions.ts
|
|
921
|
+
function cleanTypes(result) {
|
|
922
|
+
return {
|
|
923
|
+
...result,
|
|
924
|
+
argumentDescription: result.argumentDescription.map(cleanTypeDescription),
|
|
925
|
+
returnDescription: cleanType(result.returnDescription)
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
var functionSchema = {
|
|
929
|
+
type: "object",
|
|
930
|
+
properties: {
|
|
931
|
+
aggregating: { type: "boolean" },
|
|
932
|
+
argumentDescription: {
|
|
933
|
+
type: "array",
|
|
934
|
+
items: {
|
|
935
|
+
type: "object",
|
|
936
|
+
properties: {
|
|
937
|
+
name: { type: "string" },
|
|
938
|
+
description: { type: "string" },
|
|
939
|
+
type: { type: "string" },
|
|
940
|
+
default: { type: "string", nullable: true },
|
|
941
|
+
isDeprecated: { type: "boolean", default: false }
|
|
942
|
+
},
|
|
943
|
+
required: ["name", "description", "type", "isDeprecated"]
|
|
944
|
+
}
|
|
945
|
+
},
|
|
946
|
+
category: { type: "string" },
|
|
947
|
+
description: { type: "string" },
|
|
948
|
+
isBuiltIn: { type: "boolean" },
|
|
949
|
+
name: { type: "string" },
|
|
950
|
+
returnDescription: { type: "string" },
|
|
951
|
+
signature: { type: "string" },
|
|
952
|
+
isDeprecated: { type: "boolean", default: false },
|
|
953
|
+
deprecatedBy: { type: "string", nullable: true }
|
|
954
|
+
},
|
|
955
|
+
required: [
|
|
956
|
+
"aggregating",
|
|
957
|
+
"argumentDescription",
|
|
958
|
+
"category",
|
|
959
|
+
"description",
|
|
960
|
+
"isBuiltIn",
|
|
961
|
+
"isDeprecated",
|
|
962
|
+
"name",
|
|
963
|
+
"returnDescription",
|
|
964
|
+
"signature"
|
|
965
|
+
],
|
|
966
|
+
additionalProperties: true
|
|
967
|
+
};
|
|
968
|
+
var validateFunction = new import_ajv.Ajv({ useDefaults: true }).compile(functionSchema);
|
|
969
|
+
function listFunctions({ executableByMe, cypherVersion } = {
|
|
970
|
+
executableByMe: false,
|
|
971
|
+
cypherVersion: void 0
|
|
972
|
+
}) {
|
|
973
|
+
const query = `${cypherVersion ? cypherVersion + " " : ""}
|
|
974
|
+
SHOW FUNCTIONS
|
|
975
|
+
${executableByMe ? "EXECUTABLE BY CURRENT USER" : ""}
|
|
976
|
+
YIELD *`;
|
|
977
|
+
const resultTransformer = import_neo4j_driver9.resultTransformers.mapped({
|
|
978
|
+
map(record) {
|
|
979
|
+
const objResult = record.toObject();
|
|
980
|
+
validateFunction(objResult);
|
|
981
|
+
const result = cleanTypes(objResult);
|
|
982
|
+
return result;
|
|
983
|
+
},
|
|
984
|
+
collect(functions, summary) {
|
|
985
|
+
return { functions, summary };
|
|
986
|
+
}
|
|
987
|
+
});
|
|
988
|
+
return {
|
|
989
|
+
query,
|
|
990
|
+
queryConfig: { resultTransformer, routing: "READ", database: "system" }
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
// src/queries/procedures.ts
|
|
995
|
+
var import_ajv2 = require("ajv");
|
|
996
|
+
var import_neo4j_driver10 = require("neo4j-driver");
|
|
997
|
+
var procedureSchema = {
|
|
998
|
+
type: "object",
|
|
999
|
+
properties: {
|
|
1000
|
+
admin: { type: "boolean" },
|
|
1001
|
+
argumentDescription: {
|
|
1002
|
+
type: "array",
|
|
1003
|
+
items: {
|
|
1004
|
+
type: "object",
|
|
1005
|
+
properties: {
|
|
1006
|
+
name: { type: "string" },
|
|
1007
|
+
description: { type: "string" },
|
|
1008
|
+
type: { type: "string" },
|
|
1009
|
+
default: { type: "string", nullable: true },
|
|
1010
|
+
isDeprecated: { type: "boolean", default: false }
|
|
1011
|
+
},
|
|
1012
|
+
required: ["name", "description", "type", "isDeprecated"]
|
|
1013
|
+
}
|
|
1014
|
+
},
|
|
1015
|
+
description: { type: "string" },
|
|
1016
|
+
mode: { type: "string" },
|
|
1017
|
+
name: { type: "string" },
|
|
1018
|
+
option: { type: "object" },
|
|
1019
|
+
returnDescription: {
|
|
1020
|
+
type: "array",
|
|
1021
|
+
items: {
|
|
1022
|
+
type: "object",
|
|
1023
|
+
properties: {
|
|
1024
|
+
name: { type: "string" },
|
|
1025
|
+
description: { type: "string" },
|
|
1026
|
+
type: { type: "string" },
|
|
1027
|
+
isDeprecated: { type: "boolean", default: false }
|
|
1028
|
+
},
|
|
1029
|
+
required: ["name", "description", "type", "isDeprecated"]
|
|
1030
|
+
}
|
|
1031
|
+
},
|
|
1032
|
+
signature: { type: "string" },
|
|
1033
|
+
worksOnSystem: { type: "boolean" },
|
|
1034
|
+
deprecatedBy: { type: "string", nullable: true }
|
|
1035
|
+
},
|
|
1036
|
+
required: [
|
|
1037
|
+
"admin",
|
|
1038
|
+
"argumentDescription",
|
|
1039
|
+
"description",
|
|
1040
|
+
"mode",
|
|
1041
|
+
"name",
|
|
1042
|
+
"option",
|
|
1043
|
+
"returnDescription",
|
|
1044
|
+
"signature",
|
|
1045
|
+
"worksOnSystem"
|
|
1046
|
+
],
|
|
1047
|
+
additionalProperties: true
|
|
1048
|
+
};
|
|
1049
|
+
var validateProcedure = new import_ajv2.Ajv({ useDefaults: true }).compile(
|
|
1050
|
+
procedureSchema
|
|
1051
|
+
);
|
|
1052
|
+
function cleanTypes2(result) {
|
|
1053
|
+
return {
|
|
1054
|
+
...result,
|
|
1055
|
+
argumentDescription: result.argumentDescription.map(cleanTypeDescription),
|
|
1056
|
+
returnDescription: result.returnDescription.map(cleanTypeDescription)
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
function listProcedures({ executableByMe, cypherVersion } = {
|
|
1060
|
+
executableByMe: false,
|
|
1061
|
+
cypherVersion: void 0
|
|
1062
|
+
}) {
|
|
1063
|
+
const query = `${cypherVersion ? cypherVersion + " " : ""}
|
|
1064
|
+
SHOW PROCEDURES
|
|
1065
|
+
${executableByMe ? "EXECUTABLE BY CURRENT USER" : ""}
|
|
1066
|
+
YIELD *`;
|
|
1067
|
+
const resultTransformer = import_neo4j_driver10.resultTransformers.mapped({
|
|
1068
|
+
map(record) {
|
|
1069
|
+
const objResult = record.toObject();
|
|
1070
|
+
validateProcedure(objResult);
|
|
1071
|
+
const result = cleanTypes2(objResult);
|
|
1072
|
+
return result;
|
|
1073
|
+
},
|
|
1074
|
+
collect(procedures, summary) {
|
|
1075
|
+
return { procedures, summary };
|
|
1076
|
+
}
|
|
1077
|
+
});
|
|
1078
|
+
return {
|
|
1079
|
+
query,
|
|
1080
|
+
queryConfig: {
|
|
1081
|
+
routing: "READ",
|
|
1082
|
+
database: "system",
|
|
1083
|
+
resultTransformer
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
// src/queries/roles.ts
|
|
1089
|
+
var import_neo4j_driver11 = require("neo4j-driver");
|
|
1090
|
+
function listRoles() {
|
|
1091
|
+
const query = `SHOW ROLES`;
|
|
1092
|
+
const resultTransformer = import_neo4j_driver11.resultTransformers.mapped({
|
|
1093
|
+
map(record) {
|
|
1094
|
+
return record.toObject();
|
|
1095
|
+
},
|
|
1096
|
+
collect(roles, summary) {
|
|
1097
|
+
return { roles, summary };
|
|
1098
|
+
}
|
|
1099
|
+
});
|
|
1100
|
+
return {
|
|
1101
|
+
query,
|
|
1102
|
+
queryConfig: { resultTransformer, routing: "READ", database: "system" }
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
// src/queries/users.ts
|
|
1107
|
+
var import_neo4j_driver12 = require("neo4j-driver");
|
|
1108
|
+
function listUsers() {
|
|
1109
|
+
const query = `SHOW USERS`;
|
|
1110
|
+
const resultTransformer = import_neo4j_driver12.resultTransformers.mapped({
|
|
1111
|
+
map(record) {
|
|
1112
|
+
return record.toObject();
|
|
1113
|
+
},
|
|
1114
|
+
collect(users, summary) {
|
|
1115
|
+
return { users, summary };
|
|
1116
|
+
}
|
|
1117
|
+
});
|
|
1118
|
+
return {
|
|
1119
|
+
query,
|
|
1120
|
+
queryConfig: { resultTransformer, routing: "READ", database: "system" }
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
// src/queries/graphSchema.ts
|
|
1125
|
+
var import_neo4j_driver13 = require("neo4j-driver");
|
|
1126
|
+
var import_ajv3 = require("ajv");
|
|
1127
|
+
var graphSchemaSchema = {
|
|
1128
|
+
type: "object",
|
|
1129
|
+
properties: {
|
|
1130
|
+
nodes: {
|
|
1131
|
+
type: "array",
|
|
1132
|
+
items: {
|
|
1133
|
+
type: "object",
|
|
1134
|
+
properties: {
|
|
1135
|
+
labels: {
|
|
1136
|
+
type: "array",
|
|
1137
|
+
items: { type: "string" }
|
|
1138
|
+
},
|
|
1139
|
+
elementId: { type: "string" }
|
|
1140
|
+
},
|
|
1141
|
+
required: ["labels", "elementId"],
|
|
1142
|
+
additionalProperties: true
|
|
1143
|
+
}
|
|
1144
|
+
},
|
|
1145
|
+
relationships: {
|
|
1146
|
+
type: "array",
|
|
1147
|
+
items: {
|
|
1148
|
+
type: "object",
|
|
1149
|
+
properties: {
|
|
1150
|
+
type: { type: "string" },
|
|
1151
|
+
endNodeElementId: { type: "string" },
|
|
1152
|
+
startNodeElementId: { type: "string" }
|
|
1153
|
+
},
|
|
1154
|
+
required: ["type", "endNodeElementId", "startNodeElementId"],
|
|
1155
|
+
additionalProperties: true
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
},
|
|
1159
|
+
required: ["nodes", "relationships"],
|
|
1160
|
+
additionalProperties: true
|
|
1161
|
+
};
|
|
1162
|
+
var validateGraphSchema = new import_ajv3.Ajv({ useDefaults: true }).compile(
|
|
1163
|
+
graphSchemaSchema
|
|
1164
|
+
);
|
|
1165
|
+
function listGraphSchema(database) {
|
|
1166
|
+
const query = `CALL db.schema.visualization() YIELD *`;
|
|
1167
|
+
const resultTransformer = import_neo4j_driver13.resultTransformers.mapped({
|
|
1168
|
+
map(record) {
|
|
1169
|
+
const objResult = record.toObject();
|
|
1170
|
+
validateGraphSchema(objResult);
|
|
1171
|
+
return objResult;
|
|
1172
|
+
},
|
|
1173
|
+
collect(records, summary) {
|
|
1174
|
+
return {
|
|
1175
|
+
summary,
|
|
1176
|
+
graphSchema: extractRelationshipsWithNamedNodes(records)
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
});
|
|
1180
|
+
return {
|
|
1181
|
+
query,
|
|
1182
|
+
queryConfig: { resultTransformer, routing: "READ", database }
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
function extractRelationshipsWithNamedNodes(graphSchemas) {
|
|
1186
|
+
const items = [];
|
|
1187
|
+
if (graphSchemas.length !== 1) {
|
|
1188
|
+
return items;
|
|
1189
|
+
}
|
|
1190
|
+
const graphSchema = graphSchemas[0];
|
|
1191
|
+
const nodes = {};
|
|
1192
|
+
for (const node of graphSchema.nodes) {
|
|
1193
|
+
nodes[node.elementId] = node.labels[0];
|
|
1194
|
+
}
|
|
1195
|
+
for (const rel of graphSchema.relationships) {
|
|
1196
|
+
const from = nodes[rel.startNodeElementId];
|
|
1197
|
+
const to = nodes[rel.endNodeElementId];
|
|
1198
|
+
const relType = rel.type;
|
|
1199
|
+
items.push({ from, to, relType });
|
|
1200
|
+
}
|
|
1201
|
+
return items;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// src/metadataPoller.ts
|
|
1205
|
+
var QueryPoller = class {
|
|
1206
|
+
status = "not-started";
|
|
1207
|
+
data;
|
|
1208
|
+
lastFetchStart;
|
|
1209
|
+
errorMessage;
|
|
1210
|
+
connection;
|
|
1211
|
+
onRefetchDone;
|
|
1212
|
+
queryArgs;
|
|
1213
|
+
constructor({
|
|
1214
|
+
prefetchedData,
|
|
1215
|
+
queryArgs,
|
|
1216
|
+
connection,
|
|
1217
|
+
onRefetchDone
|
|
1218
|
+
}) {
|
|
1219
|
+
this.connection = connection;
|
|
1220
|
+
this.queryArgs = queryArgs;
|
|
1221
|
+
this.onRefetchDone = onRefetchDone;
|
|
1222
|
+
if (prefetchedData) {
|
|
1223
|
+
this.data = prefetchedData;
|
|
1224
|
+
this.lastFetchStart = Date.now();
|
|
1225
|
+
this.status = "fetched";
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
async refetch() {
|
|
1229
|
+
if (this.status === "fetching") return;
|
|
1230
|
+
this.status = "fetching";
|
|
1231
|
+
this.lastFetchStart = Date.now();
|
|
1232
|
+
delete this.errorMessage;
|
|
1233
|
+
try {
|
|
1234
|
+
const data = await this.connection.runSdkQuery(this.queryArgs, {
|
|
1235
|
+
queryType: "system"
|
|
1236
|
+
});
|
|
1237
|
+
this.data = data;
|
|
1238
|
+
this.status = "fetched";
|
|
1239
|
+
this.onRefetchDone?.({ success: true, data });
|
|
1240
|
+
} catch (e) {
|
|
1241
|
+
const errorMessage = String(e);
|
|
1242
|
+
this.errorMessage = errorMessage;
|
|
1243
|
+
this.status = "error";
|
|
1244
|
+
console.error(e);
|
|
1245
|
+
this.onRefetchDone?.({ success: false, errorMessage });
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
var MetadataPoller = class {
|
|
1250
|
+
dbSchema = {};
|
|
1251
|
+
};
|
|
1252
|
+
var DisconnectedMetadataPoller = class extends MetadataPoller {
|
|
1253
|
+
dbSchema = {};
|
|
1254
|
+
constructor(parameters) {
|
|
1255
|
+
super();
|
|
1256
|
+
this.dbSchema.parameters = parameters;
|
|
1257
|
+
}
|
|
1258
|
+
stopBackgroundPolling() {
|
|
1259
|
+
}
|
|
1260
|
+
startBackgroundPolling() {
|
|
1261
|
+
}
|
|
1262
|
+
fetchDbSchema() {
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1265
|
+
var ConnectedMetadataPoller = class extends MetadataPoller {
|
|
1266
|
+
constructor(databases, parameters, serverCypherVersions, connection, events) {
|
|
1267
|
+
super();
|
|
1268
|
+
this.connection = connection;
|
|
1269
|
+
this.events = events;
|
|
1270
|
+
this.dbSchema.parameters = parameters;
|
|
1271
|
+
this.databases = new QueryPoller({
|
|
1272
|
+
connection,
|
|
1273
|
+
queryArgs: listDatabases(),
|
|
1274
|
+
prefetchedData: { databases },
|
|
1275
|
+
onRefetchDone: (result) => {
|
|
1276
|
+
if (result.success) {
|
|
1277
|
+
this.dbSchema.databaseNames = result.data.databases.flatMap(
|
|
1278
|
+
(db) => db.name
|
|
1279
|
+
);
|
|
1280
|
+
this.dbSchema.aliasNames = result.data.databases.flatMap(
|
|
1281
|
+
(db) => db.aliases ?? []
|
|
1282
|
+
);
|
|
1283
|
+
const dbs = result.data.databases;
|
|
1284
|
+
const currentDb = dbs.find(
|
|
1285
|
+
(db) => db.name === this.connection.currentDb
|
|
1286
|
+
);
|
|
1287
|
+
if (currentDb) {
|
|
1288
|
+
this.dbSchema.defaultLanguage = currentDb.defaultLanguage;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
});
|
|
1293
|
+
this.users = new QueryPoller({
|
|
1294
|
+
connection,
|
|
1295
|
+
queryArgs: listUsers(),
|
|
1296
|
+
onRefetchDone: (result) => {
|
|
1297
|
+
if (result.success) {
|
|
1298
|
+
this.dbSchema.userNames = result.data.users.map((user) => user.user);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
});
|
|
1302
|
+
this.roles = new QueryPoller({
|
|
1303
|
+
connection,
|
|
1304
|
+
queryArgs: listRoles(),
|
|
1305
|
+
onRefetchDone: (result) => {
|
|
1306
|
+
if (result.success) {
|
|
1307
|
+
this.dbSchema.roleNames = result.data.roles.map((role) => role.role);
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
});
|
|
1311
|
+
this.graphSchema = new QueryPoller({
|
|
1312
|
+
connection,
|
|
1313
|
+
queryArgs: listGraphSchema(connection.currentDb),
|
|
1314
|
+
onRefetchDone: (result) => {
|
|
1315
|
+
if (result.success) {
|
|
1316
|
+
const { graphSchema } = result.data;
|
|
1317
|
+
this.dbSchema.graphSchema = graphSchema;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
this.dataSummary = new QueryPoller({
|
|
1322
|
+
connection,
|
|
1323
|
+
queryArgs: getDataSummary(connection.currentDb),
|
|
1324
|
+
onRefetchDone: (result) => {
|
|
1325
|
+
if (result.success) {
|
|
1326
|
+
const { labels, propertyKeys, relationshipTypes } = result.data;
|
|
1327
|
+
this.dbSchema.labels = labels;
|
|
1328
|
+
this.dbSchema.propertyKeys = propertyKeys;
|
|
1329
|
+
this.dbSchema.relationshipTypes = relationshipTypes;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
});
|
|
1333
|
+
const versions = serverCypherVersions?.includes("25") ? import_language_support.allCypherVersions : [void 0];
|
|
1334
|
+
versions.forEach((cypherVersion) => {
|
|
1335
|
+
const effectiveCypherVersion = cypherVersion ?? "CYPHER 5";
|
|
1336
|
+
this.procedures[effectiveCypherVersion] = new QueryPoller({
|
|
1337
|
+
connection,
|
|
1338
|
+
queryArgs: listProcedures({
|
|
1339
|
+
executableByMe: true,
|
|
1340
|
+
cypherVersion
|
|
1341
|
+
}),
|
|
1342
|
+
onRefetchDone: (result) => {
|
|
1343
|
+
if (result.success) {
|
|
1344
|
+
const procedures = result.data.procedures.reduce((acc, curr) => {
|
|
1345
|
+
const { name } = curr;
|
|
1346
|
+
acc[name] = curr;
|
|
1347
|
+
return acc;
|
|
1348
|
+
}, {});
|
|
1349
|
+
if (!this.dbSchema.procedures) {
|
|
1350
|
+
this.dbSchema.procedures = {};
|
|
1351
|
+
}
|
|
1352
|
+
this.dbSchema.procedures[effectiveCypherVersion] = procedures;
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
});
|
|
1356
|
+
this.functions[effectiveCypherVersion] = new QueryPoller({
|
|
1357
|
+
connection,
|
|
1358
|
+
queryArgs: listFunctions({
|
|
1359
|
+
executableByMe: true,
|
|
1360
|
+
cypherVersion
|
|
1361
|
+
}),
|
|
1362
|
+
onRefetchDone: (result) => {
|
|
1363
|
+
if (result.success) {
|
|
1364
|
+
const functions = result.data.functions.reduce((acc, curr) => {
|
|
1365
|
+
const { name } = curr;
|
|
1366
|
+
acc[name] = curr;
|
|
1367
|
+
return acc;
|
|
1368
|
+
}, {});
|
|
1369
|
+
if (!this.dbSchema.functions) {
|
|
1370
|
+
this.dbSchema.functions = {};
|
|
1371
|
+
}
|
|
1372
|
+
this.dbSchema.functions[effectiveCypherVersion] = functions;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
1376
|
+
});
|
|
1377
|
+
}
|
|
1378
|
+
databases;
|
|
1379
|
+
dataSummary;
|
|
1380
|
+
functions = {};
|
|
1381
|
+
procedures = {};
|
|
1382
|
+
users;
|
|
1383
|
+
roles;
|
|
1384
|
+
graphSchema;
|
|
1385
|
+
dbPollingInterval;
|
|
1386
|
+
dbSchema = {};
|
|
1387
|
+
async fetchDbSchema() {
|
|
1388
|
+
await Promise.allSettled([
|
|
1389
|
+
this.databases.refetch(),
|
|
1390
|
+
this.dataSummary.refetch(),
|
|
1391
|
+
...Object.values(this.procedures).map((version) => version?.refetch()),
|
|
1392
|
+
...Object.values(this.functions).map((version) => version?.refetch())
|
|
1393
|
+
]);
|
|
1394
|
+
if (this.dbSchema.labels && this.dbSchema.relationshipTypes && this.dbSchema.labels.length + this.dbSchema.relationshipTypes.length < 200) {
|
|
1395
|
+
await this.graphSchema.refetch();
|
|
1396
|
+
} else {
|
|
1397
|
+
this.dbSchema.graphSchema = void 0;
|
|
1398
|
+
}
|
|
1399
|
+
this.events.emit("schemaFetched");
|
|
1400
|
+
}
|
|
1401
|
+
stopBackgroundPolling() {
|
|
1402
|
+
clearInterval(this.dbPollingInterval);
|
|
1403
|
+
this.dbPollingInterval = void 0;
|
|
1404
|
+
}
|
|
1405
|
+
startBackgroundPolling(intervalSeconds = 30) {
|
|
1406
|
+
this.stopBackgroundPolling();
|
|
1407
|
+
void this.fetchDbSchema();
|
|
1408
|
+
this.dbPollingInterval = setInterval(
|
|
1409
|
+
() => void this.fetchDbSchema(),
|
|
1410
|
+
intervalSeconds * 1e3
|
|
1411
|
+
);
|
|
1412
|
+
}
|
|
1413
|
+
};
|
|
1414
|
+
|
|
1415
|
+
// package.json
|
|
1416
|
+
var package_default = {
|
|
1417
|
+
name: "@neo4j-cypher/query-tools",
|
|
1418
|
+
version: "2.0.0-next.38",
|
|
1419
|
+
description: "",
|
|
1420
|
+
bugs: {
|
|
1421
|
+
url: "https://github.com/neo4j/cypher-language-support/issues"
|
|
1422
|
+
},
|
|
1423
|
+
license: "Apache-2.0",
|
|
1424
|
+
author: "Neo4j Inc.",
|
|
1425
|
+
repository: {
|
|
1426
|
+
type: "git",
|
|
1427
|
+
url: "git://github.com/neo4j/cypher-language-support.git"
|
|
1428
|
+
},
|
|
1429
|
+
type: "module",
|
|
1430
|
+
main: "./dist/cjs/index.cjs",
|
|
1431
|
+
module: "./dist/esm/src/index.js",
|
|
1432
|
+
types: "./dist/types/src/index.d.ts",
|
|
1433
|
+
exports: {
|
|
1434
|
+
".": {
|
|
1435
|
+
types: "./dist/types/src/index.d.ts",
|
|
1436
|
+
require: "./dist/cjs/index.cjs",
|
|
1437
|
+
import: "./dist/esm/src/index.js",
|
|
1438
|
+
default: "./dist/cjs/index.cjs"
|
|
1439
|
+
}
|
|
1440
|
+
},
|
|
1441
|
+
scripts: {
|
|
1442
|
+
build: "concurrently 'npm:build-esm' 'npm:build-commonjs' 'npm:build-types'",
|
|
1443
|
+
"build-esm": "tsc --outDir dist/esm",
|
|
1444
|
+
"build-commonjs": "esbuild ./src/index.ts --bundle --format=cjs --sourcemap --packages=external --outfile=dist/cjs/index.cjs",
|
|
1445
|
+
"build-types": "tsc --emitDeclarationOnly --outDir dist/types",
|
|
1446
|
+
dev: "concurrently 'npm:build-esm -- --watch' 'npm:build-commonjs -- --watch'",
|
|
1447
|
+
clean: "rm -rf dist tsconfig*.tsbuildinfo",
|
|
1448
|
+
test: "vitest run extract-unique-nodes-and-relationships",
|
|
1449
|
+
"test:polling": "vitest run pollingIntegrationTests"
|
|
1450
|
+
},
|
|
1451
|
+
dependencies: {
|
|
1452
|
+
"@neo4j-cypher/language-support": "workspace:*",
|
|
1453
|
+
ajv: "^8.12.0",
|
|
1454
|
+
"neo4j-driver": "catalog:"
|
|
1455
|
+
},
|
|
1456
|
+
devDependencies: {
|
|
1457
|
+
"@testcontainers/neo4j": "^11.5.1"
|
|
1458
|
+
},
|
|
1459
|
+
engines: {
|
|
1460
|
+
node: ">=24.11.1"
|
|
1461
|
+
}
|
|
1462
|
+
};
|
|
1463
|
+
|
|
1464
|
+
// src/neo4jConnection.ts
|
|
1465
|
+
var METADATA_BASE = {
|
|
1466
|
+
app: "neo4j-sdk",
|
|
1467
|
+
version: package_default.version
|
|
1468
|
+
};
|
|
1469
|
+
var RECORD_LIMIT = 5e3;
|
|
1470
|
+
function resolveInitialDatabase(databases, database) {
|
|
1471
|
+
if (database) {
|
|
1472
|
+
return databases.find(
|
|
1473
|
+
(d) => d.name === database || d?.aliases?.includes(database)
|
|
1474
|
+
)?.name;
|
|
1475
|
+
}
|
|
1476
|
+
const home = databases.find((d) => d.home);
|
|
1477
|
+
const def = databases.find((d) => d.default);
|
|
1478
|
+
const system = databases.find((d) => d.name === "system");
|
|
1479
|
+
return home?.name ?? def?.name ?? system?.name ?? databases[0]?.name;
|
|
1480
|
+
}
|
|
1481
|
+
var Neo4jConnection = class {
|
|
1482
|
+
constructor(connectedUser, protocolVersion, databases, driver, database) {
|
|
1483
|
+
this.connectedUser = connectedUser;
|
|
1484
|
+
this.protocolVersion = protocolVersion;
|
|
1485
|
+
this.databases = databases;
|
|
1486
|
+
this.driver = driver;
|
|
1487
|
+
this.currentDb = resolveInitialDatabase(databases, database);
|
|
1488
|
+
this.serverVersion = void 0;
|
|
1489
|
+
}
|
|
1490
|
+
currentDb;
|
|
1491
|
+
serverVersion;
|
|
1492
|
+
async evalQuery(session, query, parameters, metadata, tx) {
|
|
1493
|
+
let result;
|
|
1494
|
+
if (!tx) {
|
|
1495
|
+
result = session.run(query, parameters, {
|
|
1496
|
+
metadata
|
|
1497
|
+
});
|
|
1498
|
+
} else {
|
|
1499
|
+
result = tx.run(query, parameters);
|
|
1500
|
+
}
|
|
1501
|
+
const records = [];
|
|
1502
|
+
let recordLimitHit = false;
|
|
1503
|
+
for await (const record of result) {
|
|
1504
|
+
if (records.length < RECORD_LIMIT) {
|
|
1505
|
+
records.push(record);
|
|
1506
|
+
} else {
|
|
1507
|
+
recordLimitHit = true;
|
|
1508
|
+
break;
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
const summary = await result.summary();
|
|
1512
|
+
return { records, summary, recordLimitHit };
|
|
1513
|
+
}
|
|
1514
|
+
async runCypherQuery({
|
|
1515
|
+
query,
|
|
1516
|
+
parameters,
|
|
1517
|
+
database,
|
|
1518
|
+
abortSignal,
|
|
1519
|
+
implicitTransaction = false
|
|
1520
|
+
}) {
|
|
1521
|
+
const session = this.driver.session({
|
|
1522
|
+
database: database ?? this.currentDb
|
|
1523
|
+
});
|
|
1524
|
+
if (abortSignal !== void 0) {
|
|
1525
|
+
abortSignal.addEventListener("abort", () => {
|
|
1526
|
+
void session.close();
|
|
1527
|
+
});
|
|
1528
|
+
}
|
|
1529
|
+
const metadata = {
|
|
1530
|
+
...METADATA_BASE,
|
|
1531
|
+
type: "user-direct"
|
|
1532
|
+
};
|
|
1533
|
+
try {
|
|
1534
|
+
let result;
|
|
1535
|
+
if (implicitTransaction) {
|
|
1536
|
+
result = this.evalQuery(session, query, parameters, metadata);
|
|
1537
|
+
} else {
|
|
1538
|
+
result = session.executeWrite(
|
|
1539
|
+
async (tx) => {
|
|
1540
|
+
const result2 = this.evalQuery(
|
|
1541
|
+
session,
|
|
1542
|
+
query,
|
|
1543
|
+
parameters,
|
|
1544
|
+
metadata,
|
|
1545
|
+
tx
|
|
1546
|
+
);
|
|
1547
|
+
return result2;
|
|
1548
|
+
},
|
|
1549
|
+
{
|
|
1550
|
+
metadata
|
|
1551
|
+
}
|
|
1552
|
+
);
|
|
1553
|
+
}
|
|
1554
|
+
return await result;
|
|
1555
|
+
} finally {
|
|
1556
|
+
await session.close();
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
async runSdkQuery({ query, queryConfig }, { queryType, abortSignal }) {
|
|
1560
|
+
const session = this.driver.session({
|
|
1561
|
+
database: queryConfig?.database ?? this.currentDb
|
|
1562
|
+
});
|
|
1563
|
+
if (abortSignal !== void 0) {
|
|
1564
|
+
abortSignal.addEventListener("abort", () => {
|
|
1565
|
+
void session.close();
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
try {
|
|
1569
|
+
const executeInTransaction = queryConfig.routing === "READ" ? session.executeRead.bind(session) : session.executeWrite.bind(session);
|
|
1570
|
+
return await executeInTransaction(
|
|
1571
|
+
async (tx) => {
|
|
1572
|
+
const result = tx.run(query, {});
|
|
1573
|
+
return await queryConfig.resultTransformer(result);
|
|
1574
|
+
},
|
|
1575
|
+
{ timeout: 500, metadata: { ...METADATA_BASE, type: queryType } }
|
|
1576
|
+
);
|
|
1577
|
+
} finally {
|
|
1578
|
+
await session.close();
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
async healthcheck() {
|
|
1582
|
+
try {
|
|
1583
|
+
await this.driver.verifyConnectivity({ database: this.currentDb });
|
|
1584
|
+
return true;
|
|
1585
|
+
} catch {
|
|
1586
|
+
return false;
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
dispose() {
|
|
1590
|
+
void this.driver?.close();
|
|
1591
|
+
}
|
|
1592
|
+
};
|
|
1593
|
+
|
|
1594
|
+
// src/queries/version.ts
|
|
1595
|
+
var import_neo4j_driver14 = require("neo4j-driver");
|
|
1596
|
+
function getVersion() {
|
|
1597
|
+
const query = "CALL dbms.components() YIELD name, versions";
|
|
1598
|
+
const resultTransformer = import_neo4j_driver14.resultTransformers.mapped({
|
|
1599
|
+
map(record) {
|
|
1600
|
+
const obj = record.toObject();
|
|
1601
|
+
const name = obj.name;
|
|
1602
|
+
const versions = obj.versions;
|
|
1603
|
+
return { name, versions };
|
|
1604
|
+
},
|
|
1605
|
+
collect(rows, summary) {
|
|
1606
|
+
for (const row of rows) {
|
|
1607
|
+
if (row.name === "Neo4j Kernel") {
|
|
1608
|
+
return { serverVersion: row.versions[0], summary };
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
return { serverVersion: void 0, summary };
|
|
1612
|
+
}
|
|
1613
|
+
});
|
|
1614
|
+
return {
|
|
1615
|
+
query,
|
|
1616
|
+
queryConfig: { resultTransformer, routing: "READ", database: "system" }
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
// src/schemaPoller.ts
|
|
1621
|
+
var MAX_RETRY_ATTEMPTS = 5;
|
|
1622
|
+
var RETRY_INTERVAL_MS = 3e4;
|
|
1623
|
+
var Neo4jSchemaPoller = class {
|
|
1624
|
+
connection;
|
|
1625
|
+
metadata;
|
|
1626
|
+
events = new import_events.EventEmitter();
|
|
1627
|
+
driver;
|
|
1628
|
+
reconnectionTimeout;
|
|
1629
|
+
retries = MAX_RETRY_ATTEMPTS;
|
|
1630
|
+
lastError;
|
|
1631
|
+
parameters = {};
|
|
1632
|
+
setParameters(parameters) {
|
|
1633
|
+
this.parameters = parameters;
|
|
1634
|
+
if (this.metadata) {
|
|
1635
|
+
this.metadata.dbSchema.parameters = parameters;
|
|
1636
|
+
} else {
|
|
1637
|
+
this.metadata = new DisconnectedMetadataPoller(parameters);
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
async connect(url, credentials, config, database) {
|
|
1641
|
+
try {
|
|
1642
|
+
this.driver = await this.initializeDriver(
|
|
1643
|
+
url,
|
|
1644
|
+
credentials,
|
|
1645
|
+
config,
|
|
1646
|
+
database
|
|
1647
|
+
);
|
|
1648
|
+
} catch (error) {
|
|
1649
|
+
console.error("Error connecting to Neo4j.", error);
|
|
1650
|
+
return {
|
|
1651
|
+
success: false,
|
|
1652
|
+
retriable: isRetriableNeo4jError(error),
|
|
1653
|
+
error: getConnectionError(error)
|
|
1654
|
+
};
|
|
1655
|
+
}
|
|
1656
|
+
return { success: true };
|
|
1657
|
+
}
|
|
1658
|
+
async persistentConnect(url, credentials, config, database) {
|
|
1659
|
+
const shouldHaveConnection = this.connection !== void 0;
|
|
1660
|
+
const connectionAlive = await this.connection?.healthcheck();
|
|
1661
|
+
const shouldUpdateConnection = this.connection && database && this.connection?.currentDb !== database;
|
|
1662
|
+
if (!connectionAlive || shouldUpdateConnection) {
|
|
1663
|
+
if (shouldHaveConnection && !shouldUpdateConnection) {
|
|
1664
|
+
console.error("Connection to Neo4j dropped");
|
|
1665
|
+
this.disconnect();
|
|
1666
|
+
} else if (shouldUpdateConnection) {
|
|
1667
|
+
this.disconnect();
|
|
1668
|
+
}
|
|
1669
|
+
try {
|
|
1670
|
+
await this.connectAndStartMetadataPoller(
|
|
1671
|
+
url,
|
|
1672
|
+
credentials,
|
|
1673
|
+
config,
|
|
1674
|
+
database
|
|
1675
|
+
);
|
|
1676
|
+
this.reconnectionTimeout = this.setReconnectionTimeout(
|
|
1677
|
+
url,
|
|
1678
|
+
credentials,
|
|
1679
|
+
config,
|
|
1680
|
+
database
|
|
1681
|
+
);
|
|
1682
|
+
return this.handleSuccessfulConnection();
|
|
1683
|
+
} catch (error) {
|
|
1684
|
+
console.error("Error connecting to Neo4j.", error);
|
|
1685
|
+
this.retries -= 1;
|
|
1686
|
+
this.lastError = getConnectionError(error);
|
|
1687
|
+
if (!isRetriableNeo4jError(error)) {
|
|
1688
|
+
return this.handlePermanentlyFailingConnection();
|
|
1689
|
+
}
|
|
1690
|
+
if (this.retries > 0) {
|
|
1691
|
+
this.reconnectionTimeout = this.setReconnectionTimeout(
|
|
1692
|
+
url,
|
|
1693
|
+
credentials,
|
|
1694
|
+
config,
|
|
1695
|
+
database
|
|
1696
|
+
);
|
|
1697
|
+
return this.handleNonSuccessfulConnection();
|
|
1698
|
+
}
|
|
1699
|
+
return this.handlePermanentlyFailingConnection();
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
this.reconnectionTimeout = this.setReconnectionTimeout(
|
|
1703
|
+
url,
|
|
1704
|
+
credentials,
|
|
1705
|
+
config,
|
|
1706
|
+
database
|
|
1707
|
+
);
|
|
1708
|
+
return { success: true };
|
|
1709
|
+
}
|
|
1710
|
+
disconnect() {
|
|
1711
|
+
if (this.connection) {
|
|
1712
|
+
console.log("Disconnected from Neo4j");
|
|
1713
|
+
}
|
|
1714
|
+
this.connection?.dispose();
|
|
1715
|
+
this.metadata?.stopBackgroundPolling();
|
|
1716
|
+
this.connection = void 0;
|
|
1717
|
+
const parameters = this.metadata?.dbSchema?.parameters ?? {};
|
|
1718
|
+
this.metadata = new DisconnectedMetadataPoller(parameters);
|
|
1719
|
+
this.driver = void 0;
|
|
1720
|
+
clearTimeout(this.reconnectionTimeout);
|
|
1721
|
+
}
|
|
1722
|
+
async getAvailableCypherVersions() {
|
|
1723
|
+
const { query: cypherVersionQuery, queryConfig: cypherVersionQueryConfig } = getVersion();
|
|
1724
|
+
try {
|
|
1725
|
+
if (this.driver) {
|
|
1726
|
+
await this.driver.executeQuery(
|
|
1727
|
+
"CYPHER 25 " + cypherVersionQuery,
|
|
1728
|
+
{},
|
|
1729
|
+
cypherVersionQueryConfig
|
|
1730
|
+
);
|
|
1731
|
+
return ["5", "25"];
|
|
1732
|
+
}
|
|
1733
|
+
} catch {
|
|
1734
|
+
return ["5"];
|
|
1735
|
+
}
|
|
1736
|
+
return ["5"];
|
|
1737
|
+
}
|
|
1738
|
+
async connectAndStartMetadataPoller(url, credentials, config, database) {
|
|
1739
|
+
this.driver = this.driver ?? await this.initializeDriver(url, credentials, config, database);
|
|
1740
|
+
const { query: dbQuery, queryConfig: dbQueryConfig } = listDatabases();
|
|
1741
|
+
const { databases, summary } = await this.driver.executeQuery(
|
|
1742
|
+
dbQuery,
|
|
1743
|
+
{},
|
|
1744
|
+
dbQueryConfig
|
|
1745
|
+
);
|
|
1746
|
+
const protocolVersion = summary.server.protocolVersion?.toString() ?? "unknown";
|
|
1747
|
+
this.connection = new Neo4jConnection(
|
|
1748
|
+
credentials.username,
|
|
1749
|
+
protocolVersion,
|
|
1750
|
+
databases,
|
|
1751
|
+
this.driver,
|
|
1752
|
+
database
|
|
1753
|
+
);
|
|
1754
|
+
const serverCypherVersions = await this.getAvailableCypherVersions();
|
|
1755
|
+
const { query: serverVersionQuery, queryConfig: serverVersionQueryConfig } = getVersion();
|
|
1756
|
+
let { serverVersion } = await this.driver.executeQuery(
|
|
1757
|
+
serverVersionQuery,
|
|
1758
|
+
{},
|
|
1759
|
+
serverVersionQueryConfig
|
|
1760
|
+
);
|
|
1761
|
+
if (serverVersion?.startsWith("5.27.0")) {
|
|
1762
|
+
const agent = summary.server.agent;
|
|
1763
|
+
if (agent) {
|
|
1764
|
+
const matchedVersion = agent.match(/\d+\.\d+\.\d+/);
|
|
1765
|
+
if (matchedVersion) {
|
|
1766
|
+
serverVersion = matchedVersion[0];
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
this.connection.serverVersion = serverVersion;
|
|
1771
|
+
this.metadata = new ConnectedMetadataPoller(
|
|
1772
|
+
databases,
|
|
1773
|
+
this.parameters,
|
|
1774
|
+
serverCypherVersions,
|
|
1775
|
+
this.connection,
|
|
1776
|
+
this.events
|
|
1777
|
+
);
|
|
1778
|
+
this.metadata.startBackgroundPolling();
|
|
1779
|
+
}
|
|
1780
|
+
async initializeDriver(url, credentials, config, database) {
|
|
1781
|
+
const driver = import_neo4j_driver15.default.driver(
|
|
1782
|
+
url,
|
|
1783
|
+
import_neo4j_driver15.default.auth.basic(credentials.username, credentials.password),
|
|
1784
|
+
{
|
|
1785
|
+
userAgent: config.appName,
|
|
1786
|
+
...config.driverConfig
|
|
1787
|
+
}
|
|
1788
|
+
);
|
|
1789
|
+
await driver.verifyConnectivity({ database });
|
|
1790
|
+
if (await driver.supportsSessionAuth()) {
|
|
1791
|
+
if (!await driver.verifyAuthentication()) {
|
|
1792
|
+
throw new Error("Invalid credentials");
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
return driver;
|
|
1796
|
+
}
|
|
1797
|
+
setReconnectionTimeout(url, credentials, config, database) {
|
|
1798
|
+
return setTimeout(() => {
|
|
1799
|
+
void this.persistentConnect(url, credentials, config, database);
|
|
1800
|
+
}, RETRY_INTERVAL_MS);
|
|
1801
|
+
}
|
|
1802
|
+
handleSuccessfulConnection() {
|
|
1803
|
+
this.resetRetries();
|
|
1804
|
+
console.log("Established connection to Neo4j");
|
|
1805
|
+
this.events.emit("connectionConnected");
|
|
1806
|
+
return { success: true };
|
|
1807
|
+
}
|
|
1808
|
+
handleNonSuccessfulConnection() {
|
|
1809
|
+
const connectionError = this.formatConnectionErrorFriendlyMessage(
|
|
1810
|
+
this.lastError,
|
|
1811
|
+
true
|
|
1812
|
+
);
|
|
1813
|
+
this.events.emit("connectionErrored", connectionError);
|
|
1814
|
+
return {
|
|
1815
|
+
success: false,
|
|
1816
|
+
retriable: true,
|
|
1817
|
+
error: connectionError
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
handlePermanentlyFailingConnection() {
|
|
1821
|
+
this.resetRetries();
|
|
1822
|
+
const connectionError = this.formatConnectionErrorFriendlyMessage(
|
|
1823
|
+
this.lastError,
|
|
1824
|
+
false
|
|
1825
|
+
);
|
|
1826
|
+
this.events.emit("connectionFailed", connectionError);
|
|
1827
|
+
return {
|
|
1828
|
+
success: false,
|
|
1829
|
+
retriable: false,
|
|
1830
|
+
error: connectionError
|
|
1831
|
+
};
|
|
1832
|
+
}
|
|
1833
|
+
formatConnectionErrorFriendlyMessage(connectionError = {
|
|
1834
|
+
message: "",
|
|
1835
|
+
friendlyMessage: FRIENDLY_ERROR_MESSAGES.Default,
|
|
1836
|
+
code: ""
|
|
1837
|
+
}, retriable) {
|
|
1838
|
+
const friendlyMessage = retriable ? `${connectionError.friendlyMessage}. Retrying in ${RETRY_INTERVAL_MS / 1e3} seconds` : connectionError.friendlyMessage;
|
|
1839
|
+
return {
|
|
1840
|
+
...connectionError,
|
|
1841
|
+
friendlyMessage
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
resetRetries() {
|
|
1845
|
+
this.retries = MAX_RETRY_ATTEMPTS;
|
|
1846
|
+
}
|
|
1847
|
+
};
|
|
1848
|
+
//# sourceMappingURL=index.cjs.map
|