Skip to content

Commit 580b40b

Browse files
committed
Fix plugin RE/FE apply
1 parent a4a8fc0 commit 580b40b

File tree

11 files changed

+128
-128
lines changed

11 files changed

+128
-128
lines changed

forward_engineering/api.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ module.exports = {
4141

4242
const containerResponse = await cosmosClient.database(containerProps.dbId).containers.createIfNotExists({
4343
id: graphName,
44-
partitionKey: getPartitionKey()(data.containerData),
44+
partitionKey: getPartitionKey(data.containerData),
4545
...applyToInstanceHelper().getContainerThroughputProps(containerProps),
4646
defaultTtl: applyToInstanceHelper().getTTL(containerProps),
4747
});

forward_engineering/applyToInstanceHelper.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,23 @@ const _ = require('lodash');
44

55
const applyToInstanceHelper = () => ({
66
setUpDocumentClient(connectionInfo) {
7-
const dbNameRegExp = /wss:\/\/(\S*).gremlin\.cosmos\./i;
8-
const dbName = dbNameRegExp.exec(connectionInfo.gremlinEndpoint);
9-
if (!dbName?.[1]) {
10-
throw new Error('Incorrect endpoint provided. Expected format: wss://<account name>.gremlin.cosmos.');
11-
}
12-
const endpoint = `https://${dbName[1]}.documents.azure.com:443/`;
7+
const dbName = connectionInfo.azureCosmosdbAccount;
8+
const endpoint = `https://${dbName}.documents.azure.com:443/`;
139
const key = connectionInfo.accountKey;
1410

1511
return new CosmosClient({ endpoint, key });
1612
},
1713

1814
async getGremlinClient(connectionInfo, databaseId, collection) {
15+
const gremlinEndpoint = `wss://${connectionInfo.azureCosmosdbAccount}.gremlin.cosmos.azure.com`;
1916
const traversalSource = 'g';
2017

2118
const authenticator = new gremlin.driver.auth.PlainTextSaslAuthenticator(
2219
`/dbs/${databaseId}/colls/${collection}`,
2320
connectionInfo.accountKey,
2421
);
2522

26-
const client = new gremlin.driver.Client(connectionInfo.gremlinEndpoint, {
23+
const client = new gremlin.driver.Client(gremlinEndpoint, {
2724
authenticator,
2825
traversalSource,
2926
rejectUnauthorized: true,

forward_engineering/generateContainerScript.js

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ const generateEdges = (collections, relationships, jsonData) => {
113113
return edges.join(';\n\n') + ';';
114114
};
115115

116-
const getGremlinScript = (_, data) => {
116+
const getGremlinScript = data => {
117117
let { collections, relationships, jsonData, containerData, options } = data;
118118
let resultScript = '';
119119
const traversalSource = _.get(containerData, [0, 'traversalSource'], 'g');
@@ -147,16 +147,23 @@ const getGremlinScript = (_, data) => {
147147
return resultScript;
148148
};
149149

150-
const getCosmosDbScript = (_, containerData) => {
151-
return JSON.stringify(
152-
{
153-
partitionKey: getPartitionKey(_)(containerData),
154-
indexingPolicy: getIndexPolicyScript(_)(containerData),
155-
...scriptHelper.addItems(_)(containerData),
156-
},
157-
null,
158-
2,
159-
);
150+
const getCosmosDbScript = containerData => {
151+
const partitionKey = getPartitionKey(containerData);
152+
153+
const getContainerConfig = () => {
154+
const baseConfig = {
155+
indexingPolicy: getIndexPolicyScript(containerData),
156+
...scriptHelper.addItems(containerData),
157+
};
158+
if (partitionKey) {
159+
return {
160+
partitionKey,
161+
...baseConfig,
162+
};
163+
}
164+
return baseConfig;
165+
};
166+
return JSON.stringify(getContainerConfig(), null, 2);
160167
};
161168

162169
const generateContainerScript = (data, logger, cb, app) => {
@@ -167,16 +174,16 @@ const generateContainerScript = (data, logger, cb, app) => {
167174
if (data.options.origin === 'ui') {
168175
cb(null, [
169176
{
170-
script: getGremlinScript(_, data),
177+
script: getGremlinScript(data),
171178
},
172179
{
173-
script: getCosmosDbScript(_, data.containerData),
180+
script: getCosmosDbScript(data.containerData),
174181
},
175182
]);
176183
} else if (scriptId === 'cosmosdb') {
177-
cb(null, getCosmosDbScript(_, data.containerData));
184+
cb(null, getCosmosDbScript(data.containerData));
178185
} else {
179-
cb(null, getGremlinScript(_, data));
186+
cb(null, getGremlinScript(data));
180187
}
181188
} catch (e) {
182189
logger.log('error', { message: e.message, stack: e.stack }, 'Forward-Engineering Error');

forward_engineering/getIndexPolicyScript.js

Lines changed: 52 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const _ = require('lodash');
2+
13
const add = (key, value) => obj => {
24
if (value === undefined || value === '' || (Array.isArray(value) && value.length === 0)) {
35
return obj;
@@ -61,73 +63,65 @@ const filterDeactivated = items => {
6163
});
6264
};
6365

64-
const getIncludedPath =
65-
_ =>
66-
(includedPaths = []) => {
67-
return filterDeactivated(includedPaths)
68-
.map(item => {
69-
return _.flow(add('path', getPath(item.indexIncludedPath)))({});
70-
})
71-
.filter(item => !_.isEmpty(item));
72-
};
66+
const getIncludedPath = (includedPaths = []) => {
67+
return filterDeactivated(includedPaths)
68+
.map(item => {
69+
return _.flow(add('path', getPath(item.indexIncludedPath)))({});
70+
})
71+
.filter(item => !_.isEmpty(item));
72+
};
7373

74-
const getExcludedPath =
75-
_ =>
76-
(excludedPaths = []) => {
77-
return filterDeactivated(excludedPaths)
78-
.map(item => {
79-
return _.flow(add('path', getPath(item.indexExcludedPath)))({});
80-
})
81-
.filter(item => !_.isEmpty(item));
82-
};
74+
const getExcludedPath = (excludedPaths = []) => {
75+
return filterDeactivated(excludedPaths)
76+
.map(item => {
77+
return _.flow(add('path', getPath(item.indexExcludedPath)))({});
78+
})
79+
.filter(item => !_.isEmpty(item));
80+
};
8381

84-
const getCompositeIndexes =
85-
_ =>
86-
(compositeIndexes = []) => {
87-
return filterDeactivated(compositeIndexes)
88-
.map(item => {
89-
if (!Array.isArray(item.compositeFieldPath)) {
90-
return;
91-
}
92-
93-
return _.uniqWith(
94-
item.compositeFieldPath.map(item => {
95-
const path = item.name.split('/');
96-
97-
return {
98-
path: ['', ...path.slice(1).map(prepareName)].join('/'),
99-
order: item.type || 'ascending',
100-
};
101-
}),
102-
(a, b) => a.path === b.path,
103-
).filter(item => !_.isEmpty(item));
104-
})
105-
.filter(item => !_.isEmpty(item));
106-
};
82+
const getCompositeIndexes = (compositeIndexes = []) => {
83+
return filterDeactivated(compositeIndexes)
84+
.map(item => {
85+
if (!Array.isArray(item.compositeFieldPath)) {
86+
return;
87+
}
10788

108-
const getSpatialIndexes =
109-
_ =>
110-
(spatialIndexes = []) => {
111-
return filterDeactivated(spatialIndexes)
112-
.map(item => {
113-
return _.flow(
114-
add('path', getPath(item.indexIncludedPath)),
115-
add('types', (item.dataTypes || []).map(dataType => dataType.spatialType).filter(Boolean)),
116-
)({});
117-
})
118-
.filter(item => !_.isEmpty(item) && item.path);
119-
};
89+
return _.uniqWith(
90+
item.compositeFieldPath.map(item => {
91+
const path = item.name.split('/');
92+
93+
return {
94+
path: ['', ...path.slice(1).map(prepareName)].join('/'),
95+
order: item.type || 'ascending',
96+
};
97+
}),
98+
(a, b) => a.path === b.path,
99+
).filter(item => !_.isEmpty(item));
100+
})
101+
.filter(item => !_.isEmpty(item));
102+
};
103+
104+
const getSpatialIndexes = (spatialIndexes = []) => {
105+
return filterDeactivated(spatialIndexes)
106+
.map(item => {
107+
return _.flow(
108+
add('path', getPath(item.indexIncludedPath)),
109+
add('types', (item.dataTypes || []).map(dataType => dataType.spatialType).filter(Boolean)),
110+
)({});
111+
})
112+
.filter(item => !_.isEmpty(item) && item.path);
113+
};
120114

121-
const getIndexPolicyScript = _ => containerData => {
115+
const getIndexPolicyScript = containerData => {
122116
const indexTab = containerData[1] || {};
123117

124118
return _.flow(
125119
add('automatic', indexTab.indexingAutomatic === 'true'),
126120
add('indexingMode', indexTab.indexingMode),
127-
add('includedPaths', getIncludedPath(_)(indexTab.includedPaths)),
128-
add('excludedPaths', getExcludedPath(_)(indexTab.excludedPaths)),
129-
add('spatialIndexes', getSpatialIndexes(_)(indexTab.spatialIndexes)),
130-
add('compositeIndexes', getCompositeIndexes(_)(indexTab.compositeIndexes)),
121+
add('includedPaths', getIncludedPath(indexTab.includedPaths)),
122+
add('excludedPaths', getExcludedPath(indexTab.excludedPaths)),
123+
add('spatialIndexes', getSpatialIndexes(indexTab.spatialIndexes)),
124+
add('compositeIndexes', getCompositeIndexes(indexTab.compositeIndexes)),
131125
)({});
132126
};
133127

forward_engineering/helpers/getPartitionKey.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
const getPartitionKey = _ => containerData => {
2-
return _.get(containerData, '[0].partitionKey[0].name', '').trim().replace(/\/$/, '');
1+
const _ = require('lodash');
2+
3+
const getPartitionKey = containerData => {
4+
return _.get(containerData, '[0].partitionKey[0].name', '').trim().replace(/\/$/, null);
35
};
46

57
module.exports = {

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"pre-push": "npx eslint ."
6161
},
6262
"scripts": {
63+
"install": "npx patch-package",
6364
"lint": "eslint . --max-warnings=0",
6465
"package": "node esbuild.package.js",
6566
"postinstall": "npx simple-git-hooks"

patches/gremlin+3.7.3.patch

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
diff --git a/node_modules/gremlin/lib/driver/connection.js b/node_modules/gremlin/lib/driver/connection.js
2-
index 38f6ee7..98e3749 100644
2+
index 38f6ee7..636c264 100644
33
--- a/node_modules/gremlin/lib/driver/connection.js
44
+++ b/node_modules/gremlin/lib/driver/connection.js
5-
@@ -124,7 +124,23 @@ class Connection extends EventEmitter {
5+
@@ -124,12 +124,19 @@ class Connection extends EventEmitter {
66
}
77
}
88

@@ -15,15 +15,21 @@ index 38f6ee7..98e3749 100644
1515
+ * the connections when they are done in a secured context (wss), e.g. websockets with tls.
1616
+ * When using Node 22's implementation the server is cutting the connection with non-101 response code.
1717
+ */
18-
+ const isNode = () => typeof process !== 'undefined' && !!process.versions && !!process.versions.node;
19-
+ const getWebsocketImplementation = async () => {
20-
+ if(isNode()){
21-
+ return (await import('ws')).default;
22-
+ }
23-
+ // In browser return the standard implementation
24-
+ return globalThis.WebSocket;
25-
+ }
26-
+ const WebSocket = await getWebsocketImplementation();
18+
+ const WebSocket = (await import('ws')).default;
2719

2820
this._ws = new WebSocket(
2921
this.url,
22+
- globalThis.WebSocket === undefined
23+
- ? {
24+
+ {
25+
headers: headers,
26+
ca: this.options.ca,
27+
cert: this.options.cert,
28+
@@ -138,7 +145,6 @@ class Connection extends EventEmitter {
29+
agent: this.options.agent,
30+
perMessageDeflate: this.options.enableCompression,
31+
}
32+
- : undefined,
33+
);
34+
35+
if ('binaryType' in this._ws) {

reverse_engineering/api.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ module.exports = {
166166
};
167167

168168
logger.log('info', { collection: collectionName }, 'Getting container nodes data', data.hiddenKeys);
169-
await gremlinHelper.connect({ collection: collectionName });
169+
await gremlinHelper.connect({ ...data, collection: collectionName });
170170
const nodesData = await getNodesData(collectionName, labels, logger, {
171171
recordSamplingSettings,
172172
fieldInference,
@@ -442,12 +442,8 @@ function createSchemaByPartitionKeyPath(path, documents = []) {
442442
}
443443

444444
const setUpDocumentClient = connectionInfo => {
445-
const dbNameRegExp = /(\S*).gremlin\.cosmos\.azure.com/i;
446-
const dbName = dbNameRegExp.exec(connectionInfo.gremlinEndpoint);
447-
if (!dbName?.[1]) {
448-
throw new Error('Incorrect endpoint provided. Expected format: <account name>.gremlin.cosmos.azurecom');
449-
}
450-
const endpoint = `https://${dbName[1]}.documents.azure.com/`;
445+
const dbName = connectionInfo.azureCosmosdbAccount;
446+
const endpoint = `https://${dbName}.documents.azure.com/`;
451447
const key = connectionInfo.accountKey;
452448

453449
return new CosmosClient({ endpoint, key });
@@ -590,9 +586,14 @@ async function getAdditionalAccountInfo(connectionInfo, logger) {
590586
logger.log('info', {}, 'Account additional info', connectionInfo.hiddenKeys);
591587

592588
try {
593-
const { clientId, appSecret, tenantId, subscriptionId, resourceGroupName, gremlinEndpoint } = connectionInfo;
594-
const accNameRegex = /wss:\/\/(.+)\.gremlin.+/i;
595-
const accountName = accNameRegex.test(gremlinEndpoint) ? accNameRegex.exec(gremlinEndpoint)[1] : '';
589+
const {
590+
clientId,
591+
appSecret,
592+
tenantId,
593+
subscriptionId,
594+
resourceGroupName,
595+
azureCosmosdbAccount: accountName,
596+
} = connectionInfo;
596597
const tokenBaseURl = `https://login.microsoftonline.com/${tenantId}/oauth2/token`;
597598
const { data: tokenData } = await axios({
598599
method: 'post',

reverse_engineering/config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
},
66
"excludeDocKind": ["id"],
77
"scenario": "getDatabases",
8-
"connectionList": ["name", "gremlinEndpoint"],
8+
"connectionList": ["name", "azureCosmosdbAccount"],
99
"widestColumn": "gremlinEndpoint",
1010
"helpUrl": "https://hackolade.com/help/Azureinstance2.html"
1111
}

reverse_engineering/connection_settings_modal/connectionSettingsModalConfig.json

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
}
1414
},
1515
{
16-
"inputLabel": "Gremlin endpoint",
17-
"inputKeyword": "gremlinEndpoint",
16+
"inputLabel": "Azure Cosmos DB Account",
17+
"inputKeyword": "azureCosmosdbAccount",
1818
"inputType": "text",
19-
"inputPlaceholder": "*.gremlin.cosmos.azure.com",
20-
"inputTooltip": "Paste Gremlin endpoint",
19+
"inputPlaceholder": "",
20+
"inputTooltip": "Paste the Azure Cosmos DB account",
2121
"defaultValue": "",
2222
"validation": [
2323
{
24-
"regex": "^.+\\.gremlin\\.cosmos\\.azure\\.com",
25-
"message": "Gremlin endpoint must satisfy the template:\n<account name>.gremlin.cosmos.azure.com"
24+
"regex": "^[a-z0-9]+(-[a-z0-9]+)*",
25+
"message": "CosmosDB account name can only contain lowercase letter, number and one - character"
2626
}
2727
]
2828
},
@@ -33,10 +33,7 @@
3333
"inputPlaceholder": "",
3434
"defaultValue": "",
3535
"inputTooltip": "Paste the account Primary or Secondary (Read-Only) Key",
36-
"isHiddenKey": true,
37-
"validation": {
38-
"regex": "([^\\s])"
39-
}
36+
"isHiddenKey": true
4037
}
4138
]
4239
},

0 commit comments

Comments
 (0)