Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Special Characters in Schema #7

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/NeptuneSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ const schema = {
};

function sanitize(text) {
// TODO implement sanitization logic
// placeholder for sanitization of query text that cannot be parameterized
return text;
return `\`${text}\``;
}

/**
Expand Down Expand Up @@ -446,7 +444,7 @@ async function getNeptuneSchema() {
await getEdgesDirections();

await getEdgesDirectionsCardinality();

return JSON.stringify(schema, null, 2);
}

Expand Down
161 changes: 108 additions & 53 deletions src/graphdb.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function checkForDuplicateNames(schema) {
}


// Write a function that takes an input a string and return the string lowercase except the first charachter uppercase
// Write a function that takes an input a string and return the string lowercase except the first character uppercase
function toPascalCase (str) {
let r = '';
if (changeCase) {
Expand All @@ -52,6 +52,25 @@ function toPascalCase (str) {
return r.trim();
}

// Changes every instance of invalid characters in the given label with the following abbreviations
function cleanseLabel(label) {
return label
.replaceAll("!", "_ex_")
.replaceAll("$", "_dol_")
.replaceAll("&", "_amp_")
.replaceAll("(", "_op_")
.replaceAll(")", "_cp_")
.replaceAll(".", "_dot_")
.replaceAll(":", "_cn_")
.replaceAll("=", "_eq_")
.replaceAll("@", "_at_")
.replaceAll("[", "_os_")
.replaceAll("]", "_cs_")
.replaceAll("{", "_oc_")
.replaceAll("|", "_vb_")
.replaceAll("}", "_cc_")
.replaceAll("-", "_hy_");
}

function graphDBInferenceSchema (graphbSchema, addMutations) {
sophiadt marked this conversation as resolved.
Show resolved Hide resolved
let r = '';
Expand All @@ -61,65 +80,77 @@ function graphDBInferenceSchema (graphbSchema, addMutations) {

gdbs.nodeStructures.forEach(node => {
// node type
let nodeCase = node.label;
let nodeCase = cleanseLabel(node.label);
if (changeCase) {
nodeCase = toPascalCase(node.label);
nodeCase = toPascalCase(nodeCase);
}

if (node.label !== nodeCase) {
r += `type ${nodeCase} @alias(property:"${node.label}") {\n`;
} else {
}
else {
r += `type ${nodeCase} {\n`;
}

r += '\t_id: ID! @id\n';

node.properties.forEach(property => {
if (property.name == 'id')
if (property.name === 'id') {
r+= `\tid: ID\n`;
else
r+= `\t${property.name}: ${property.type}\n`;
}
else {
let propertyCase = cleanseLabel(property.name);
let alias = '';
if (property.name !== propertyCase) {
alias = ` @alias(property: "${property.name}")`;
}
r+= `\t${propertyCase}: ${property.type}${alias}\n`;
}
});

let edgeTypes = [];
gdbs.edgeStructures.forEach(edge => {
edge.directions.forEach(direction => {
let fromCase = toPascalCase(direction.from);
let toCase = toPascalCase(direction.to);
let edgeCase = toPascalCase(edge.label);
if (direction.from == node.label && direction.to == node.label){
if (direction.relationship == 'MANY-MANY') {
let fromCase = toPascalCase(cleanseLabel(direction.from));
let toCase = toPascalCase(cleanseLabel(direction.to));
let edgeCase = toPascalCase(cleanseLabel(edge.label));

if (direction.from === node.label && direction.to === node.label){
if (direction.relationship === 'MANY-MANY') {
r += `\t${nodeCase.toLocaleLowerCase() + edgeCase}sOut(filter: ${nodeCase}Input, options: Options): [${nodeCase}] @relationship(edgeType:"${edge.label}", direction:OUT)\n`;
r += `\t${nodeCase.toLocaleLowerCase() + edgeCase}sIn(filter: ${nodeCase}Input, options: Options): [${nodeCase}] @relationship(edgeType:"${edge.label}", direction:IN)\n`;
r += `\t${nodeCase.toLocaleLowerCase() + edgeCase}sIn(filter: ${nodeCase}Input, options: Options): [${nodeCase}] @relationship(edgeType:"${edge.label}", direction:IN)\n`;
kmcginnes marked this conversation as resolved.
Show resolved Hide resolved
}
if (direction.relationship == 'ONE-ONE') {
if (direction.relationship === 'ONE-ONE') {
r += `\t${nodeCase.toLocaleLowerCase() + edgeCase}Out: ${nodeCase} @relationship(edgeType:"${edge.label}", direction:OUT)\n`;
r += `\t${nodeCase.toLocaleLowerCase() + edgeCase}In: ${nodeCase} @relationship(edgeType:"${edge.label}", direction:IN)\n`;
}
if (!edgeTypes.includes(edge.label))
edgeTypes.push(edge.label);
}

if (direction.from == node.label && direction.to != node.label){
if (direction.relationship == 'MANY-MANY') {
r += `\t${toCase.toLocaleLowerCase() + edgeCase}sOut(filter: ${toCase}Input, options: Options): [${toCase}] @relationship(edgeType:"${edge.label}", direction:OUT)\n`
if (direction.from === node.label && direction.to !== node.label){
if (direction.relationship === 'MANY-MANY') {
r += `\t${toCase.toLocaleLowerCase() + edgeCase}sOut(filter: ${toCase}Input, options: Options): [${toCase}] @relationship(edgeType:"${edge.label}", direction:OUT)\n`;
}
if (direction.relationship == 'ONE-MANY') {
r += `\t${toCase.toLocaleLowerCase() + edgeCase}sOut(filter: ${toCase}Input, options: Options): [${toCase}] @relationship(edgeType:"${edge.label}", direction:OUT)\n`
if (direction.relationship === 'ONE-MANY') {
r += `\t${toCase.toLocaleLowerCase() + edgeCase}sOut(filter: ${toCase}Input, options: Options): [${toCase}] @relationship(edgeType:"${edge.label}", direction:OUT)\n`;
}
if (direction.relationship == 'MANY-ONE') {
r += `\t${toCase.toLocaleLowerCase() + edgeCase}Out: ${toCase} @relationship(edgeType:"${edge.label}", direction:OUT)\n`
if (direction.relationship === 'MANY-ONE') {
r += `\t${toCase.toLocaleLowerCase() + edgeCase}Out: ${toCase} @relationship(edgeType:"${edge.label}", direction:OUT)\n`;
}
if (!edgeTypes.includes(edge.label))
edgeTypes.push(edge.label);
}

if (direction.from != node.label && direction.to == node.label){
if (direction.relationship == 'MANY-MANY') {
if (direction.from !== node.label && direction.to === node.label){
if (direction.relationship === 'MANY-MANY') {
r += `\t${fromCase.toLocaleLowerCase() + edgeCase}sIn(filter: ${fromCase}Input, options: Options): [${fromCase}] @relationship(edgeType:"${edge.label}", direction:IN)\n`
}
if (direction.relationship == 'ONE-MANY') {
r += `\t${fromCase.toLocaleLowerCase() + edgeCase}In: ${fromCase} @relationship(edgeType:"${edge.label}", direction:IN)\n`
if (direction.relationship === 'ONE-MANY') {
r += `\t${fromCase.toLocaleLowerCase() + edgeCase}In: ${fromCase} @relationship(edgeType:"${edge.label}", direction:IN)\n`;
}
if (direction.relationship == 'MANY-ONE') {
r += `\t${fromCase.toLocaleLowerCase() + edgeCase}sIn(filter: ${fromCase}Input, options: Options): [${fromCase}] @relationship(edgeType:"${edge.label}", direction:IN)\n`
if (direction.relationship === 'MANY-ONE') {
r += `\t${fromCase.toLocaleLowerCase() + edgeCase}sIn(filter: ${fromCase}Input, options: Options): [${fromCase}] @relationship(edgeType:"${edge.label}", direction:IN)\n`;
}
if (!edgeTypes.includes(edge.label))
edgeTypes.push(edge.label);
Expand All @@ -141,7 +172,7 @@ function graphDBInferenceSchema (graphbSchema, addMutations) {
? toPascalCase(edgeType)
: edgeType;

r += `\t${aliasedEdgeType}:${caseAdjustedEdgeType}`;
r += `\t${cleanseLabel(aliasedEdgeType)}:${cleanseLabel(caseAdjustedEdgeType)}\n`;
});

r += '}\n\n';
Expand All @@ -150,36 +181,59 @@ function graphDBInferenceSchema (graphbSchema, addMutations) {
r += `input ${nodeCase}Input {\n`;
r += '\t_id: ID @id\n';
node.properties.forEach(property => {
r+= `\t${property.name}: ${property.type}\n`;
let propertyCase = cleanseLabel(property.name);
if (property.name !== propertyCase) {
r+= `\t${propertyCase}: ${property.type} @alias(property: "${property.name}")\n`;
}
else {
r+= `\t${property.name}: ${property.type}\n`;
}
});
r += '}\n\n';
})

// edge types
gdbs.edgeStructures.forEach(edge => {
// edge type
let edgeCase = edge.label;
let edgeCase = cleanseLabel(edge.label);
if (changeCase) {
edgeCase = toPascalCase(edge.label);
r += `type ${edgeCase} @alias(property:"${edge.label}") {\n`;
} else {
edgeCase = toPascalCase(edgeCase);
}
if (edge.label !== edgeCase) {
r += `type ${edgeCase} @alias(property:"${edge.label}") {\n`;
}
else {
r += `type ${edgeCase} {\n`;
}
r += '\t_id: ID! @id\n';

edge.properties.forEach(property => {
if (property.name == 'id')
r+= `\tid: ID\n`;
else
r+= `\t${property.name}: ${property.type}\n`;
if (property.name === 'id') {
r += `\tid: ID\n`;
}
else {
let propertyCase = cleanseLabel(property.name);
let alias = '';
if (property.name !== propertyCase) {
alias = ` @alias(property: "${property.name}")`;
}
r+= `\t${propertyCase}: ${property.type}${alias}\n`;
}
});
r += '}\n\n';

// input for the edge type
if (edge.properties.length > 0) {
r += `input ${edgeCase}Input {\n`;
if (edge.properties.length > 0) {
r += `input ${edgeCase}Input {\n`;

edge.properties.forEach(property => {
r+= `\t${property.name}: ${property.type}\n`;
let propertyCase = cleanseLabel(property.name);
if (property.name !== propertyCase) {
r += `\t${propertyCase}: ${property.type} @alias(property: "${property.name}")\n`;
}
else {
r+= `\t${property.name}: ${property.type}\n`;
}
});
r += '}\n\n';
}
Expand All @@ -193,34 +247,35 @@ function graphDBInferenceSchema (graphbSchema, addMutations) {
// query
r += `type Query {\n`;
gdbs.nodeStructures.forEach(node => {
let nodeCase = toPascalCase(node.label);
let nodeCase = toPascalCase(cleanseLabel(node.label));
r += `\tgetNode${nodeCase}(filter: ${nodeCase}Input): ${nodeCase}\n`;
r += `\tgetNode${nodeCase}s(filter: ${nodeCase}Input, options: Options): [${nodeCase}]\n`;
});
r += '}\n\n';

// mutation
if (addMutations) {
if (addMutations) {
r += `type Mutation {\n`;
gdbs.nodeStructures.forEach(node => {
let nodeCase = toPascalCase(node.label);
let nodeCase = toPascalCase(cleanseLabel(node.label));
r += `\tcreateNode${nodeCase}(input: ${nodeCase}Input!): ${nodeCase}\n`;
r += `\tupdateNode${nodeCase}(input: ${nodeCase}Input!): ${nodeCase}\n`;
r += `\tdeleteNode${nodeCase}(_id: ID!): Boolean\n`;
});

gdbs.edgeStructures.forEach(edge => {
edge.directions.forEach(direction => {
let edgeCase = toPascalCase(edge.label);
let fromCase = toPascalCase(direction.from);
let toCase = toPascalCase(direction.to);
if (edge.properties.length > 0) {
r += `\tconnectNode${fromCase}ToNode${toCase}Edge${edgeCase}(from_id: ID!, to_id: ID!, edge: ${edgeCase}Input!): ${edgeCase}\n`;
r += `\tupdateEdge${edgeCase}From${fromCase}To${toCase}(from_id: ID!, to_id: ID!, edge: ${edgeCase}Input!): ${edgeCase}\n`;
} else {
r += `\tconnectNode${fromCase}ToNode${toCase}Edge${edgeCase}(from_id: ID!, to_id: ID!): ${edgeCase}\n`;
}
r += `\tdeleteEdge${edgeCase}From${fromCase}To${toCase}(from_id: ID!, to_id: ID!): Boolean\n`;
let fromCase = toPascalCase(cleanseLabel(direction.from));
let toCase = toPascalCase(cleanseLabel(direction.to));
let edgeCase = toPascalCase(cleanseLabel(edge.label));

if (edge.properties.length > 0) {
r += `\tconnectNode${fromCase}ToNode${toCase}Edge${edgeCase}(from_id: ID!, to_id: ID!, edge: ${edgeCase}Input!): ${edgeCase}\n`;
r += `\tupdateEdge${edgeCase}From${fromCase}To${toCase}(from_id: ID!, to_id: ID!, edge: ${edgeCase}Input!): ${edgeCase}\n`;
} else {
r += `\tconnectNode${fromCase}ToNode${toCase}Edge${edgeCase}(from_id: ID!, to_id: ID!): ${edgeCase}\n`;
}
r += `\tdeleteEdge${edgeCase}From${fromCase}To${toCase}(from_id: ID!, to_id: ID!): Boolean\n`;
});
});
r += '}\n\n';
Expand Down
Loading