Skip to content

Commit 7c5414a

Browse files
committed
Small changes before pulling master
1 parent da5f223 commit 7c5414a

File tree

2 files changed

+92
-88
lines changed

2 files changed

+92
-88
lines changed

graphql-api-generator/utils/utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,7 @@ def printSchemaWithDirectives(schema):
920920
output+= _location._name_ + ' | '
921921

922922
output = output[:-3] + '\n\n'
923+
print(_dir.name)
923924

924925
# Two special directives that should not exists in the db schema
925926
output += 'directive @_requiredForTarget_AccordingToInterface(interface: String!) on FIELD_DEFINITION\n\n'

graphql-server/drivers/arangodb/driver.js

Lines changed: 91 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module.exports = {
1212
let db_name = process.env.db ? process.env.db : 'dev-db';
1313
let url = process.env.URL ? process.env.URL : 'http://localhost:8529';
1414
let drop = process.env.DROP === 'true';
15+
let diasableDiractivesChecking = process.env.DISABLE_DIRECTIVES_CHECKING === 'true';
1516
disableEdgeValidation = process.env.DISABLE_EDGE_VALIDATION === 'true';
1617
db = new arangojs.Database({ url: url });
1718

@@ -1158,94 +1159,96 @@ function addPossibleEdgeTypes(query, schema, type_name, field_name, use_aql = tr
11581159
* @param schema
11591160
*/
11601161
function addfinalDirectiveChecksForType(ctxt, type, id, schema) {
1161-
for (let f in type.getFields()) {
1162-
let field = type.getFields()[f];
1163-
for (dir of field.astNode.directives) {
1164-
if (dir.name.value == 'noloops') {
1165-
let collection = asAQLVar(`db.${getEdgeCollectionName(type.name, field.name)}`);
1166-
ctxt.trans.finalConstraintChecks.push(`if(db._query(aql\`FOR v IN 1..1 OUTBOUND ${id} ${collection} FILTER ${id} == v._id RETURN v\`).next()){`);
1167-
ctxt.trans.finalConstraintChecks.push(` throw "Field ${f} in ${type.name} is breaking a @noloops directive!";`);
1168-
ctxt.trans.finalConstraintChecks.push(`}`);
1169-
}
1170-
else if (dir.name.value == 'distinct') {
1171-
let collection = asAQLVar(`db.${getEdgeCollectionName(type.name, field.name)}`);
1172-
ctxt.trans.finalConstraintChecks.push(`if(db._query(aql\`FOR v, e IN 1..1 OUTBOUND ${id} ${collection} FOR v2, e2 IN 1..1 OUTBOUND ${id} ${collection} FILTER v._id == v2._id AND e._id != e2._id RETURN v\`).next()){`);
1173-
ctxt.trans.finalConstraintChecks.push(` throw "Field ${f} in ${type.name} is breaking a @distinct directive!";`);
1174-
ctxt.trans.finalConstraintChecks.push(`}`);
1175-
}
1176-
else if (dir.name.value == 'uniqueForTarget') {
1177-
// The direct variant of @uniqueForTarget
1178-
// edge is named after current type etc.
1179-
let collection = asAQLVar(`db.${getEdgeCollectionName(type.name, field.name)}`);
1180-
ctxt.trans.finalConstraintChecks.push(`if(db._query(aql\`FOR v, e IN 1..1 OUTBOUND ${id} ${collection} FOR v2, e2 IN 1..1 INBOUND v._id ${collection} FILTER e._id != e2._id RETURN v\`).next()){`);
1181-
ctxt.trans.finalConstraintChecks.push(` throw "Field ${f} in ${type.name} is breaking a @uniqueForTarget directive!";`);
1182-
ctxt.trans.finalConstraintChecks.push(`}`);
1183-
}
1184-
else if (dir.name.value == '_uniqueForTarget_AccordingToInterface') {
1185-
// The inherited/implemented variant of @uniqueForTarget
1186-
// The target does not only require at most one edge of this type, but at most one of any type implementing the interface
1187-
// Thankfully we got the name of the interface as a mandatory argument and can hence use this to get all types implementing it
1188-
1189-
let interfaceName = dir.arguments[0].value.value; // If we add more arguments to the directive this will fail horrible.
1190-
// But that should not happen (and it is quite easy to fix)
1191-
1192-
ctxt.trans.finalConstraintChecks.push(`if(db._query(aql\`FOR v, e IN 1..1 OUTBOUND ${id}`);
1193-
addPossibleEdgeTypes(ctxt.trans.finalConstraintChecks, schema, interfaceName, field.name, false);
1194-
ctxt.trans.finalConstraintChecks.push(`FOR v2, e2 IN 1..1 INBOUND v._id`);
1195-
addPossibleEdgeTypes(ctxt.trans.finalConstraintChecks, schema, interfaceName, field.name, false);
1196-
ctxt.trans.finalConstraintChecks.push(`FILTER e._id != e2._id RETURN v\`).next()){`);
1197-
ctxt.trans.finalConstraintChecks.push(` throw "Field ${f} in ${type.name} is breaking a @_uniqueForTarget_AccordingToInterface directive!";`);
1198-
ctxt.trans.finalConstraintChecks.push(`}`);
1199-
}
1200-
else if (dir.name.value == 'requiredForTarget') {
1201-
// The direct variant of @requiredForTarget
1202-
// edge is named after current type etc.
1203-
let edgeCollection = asAQLVar(`db.${getEdgeCollectionName(type.name, field.name)}`);
1204-
1205-
// The target type might be an interface, giving us slightly more to keep track of
1206-
// First, find the right collections to check
1207-
ctxt.trans.finalConstraintChecks.push(`if(db._query(aql\`FOR x IN FLATTEN(FOR i IN [`);
1208-
addPossibleTypes(ctxt.trans.finalConstraintChecks, schema, graphql.getNamedType(field.type), false);
1209-
// Second, count all edges ending at objects in these collections
1210-
ctxt.trans.finalConstraintChecks.push(`] RETURN i) LET endpoints = ( FOR v IN 1..1 INBOUND x ${edgeCollection} RETURN v)`);
1211-
// If the count returns 0, we have an object breaking the directive
1212-
ctxt.trans.finalConstraintChecks.push(`FILTER LENGTH(endpoints) == 0 RETURN x\`).next()){`);
1213-
ctxt.trans.finalConstraintChecks.push(` throw "There are object(s) breaking the @requiredForTarget directive of Field ${f} in ${type.name}!";`);
1214-
ctxt.trans.finalConstraintChecks.push(`}`);
1215-
}
1216-
else if (dir.name.value == '_requiredForTarget_AccordingToInterface') {
1217-
// The inherited/implemented variant of @requiredForTarget
1218-
// The target does not directly require an edge of this type, but at least one of any type implementing the interface
1219-
// Thankfully we got the name of the interface as a mandatory argument and can hence use this to get all types implementing it
1220-
1221-
let interfaceName = dir.arguments[0].value.value; // If we add more arguments to the directive this will fail horrible.
1222-
// But that should not happen (and it is quite easy to fix)
1223-
1224-
// The target type might be an interface, giving us slightly more to keep track of
1225-
// First, find the right collections to check
1226-
ctxt.trans.finalConstraintChecks.push(`if(db._query(aql\`FOR x IN FLATTEN(FOR i IN [`);
1227-
addPossibleTypes(ctxt.trans.finalConstraintChecks, schema, graphql.getNamedType(field.type), false);
1228-
// Second, count all edges ending at objects in these collections
1229-
ctxt.trans.finalConstraintChecks.push(`] RETURN i) LET endpoints = ( FOR v IN 1..1 INBOUND x `);
1230-
addPossibleEdgeTypes(ctxt.trans.finalConstraintChecks, schema, interfaceName, field.name, false);
1231-
ctxt.trans.finalConstraintChecks.push(` RETURN v)`);
1232-
// If the count returns 0, we have an object breaking the directive
1233-
ctxt.trans.finalConstraintChecks.push(`FILTER LENGTH(endpoints) == 0 RETURN x\`).next()){`);
1234-
ctxt.trans.finalConstraintChecks.push(` throw "There are object(s) breaking the inherited @_requiredForTarget_AccordingToInterface directive of Field ${f} in ${type.name}!";`);
1235-
ctxt.trans.finalConstraintChecks.push(`}`);
1236-
}
1237-
else if (dir.name.value == 'required' && field.name[0] == '_') {
1238-
// This is actually the reverse edge of a @requiredForTarget directive
1239-
1240-
let pattern_string = `^_(.+?)From${type.name}$`; // get the non-reversed edge name
1241-
let re = new RegExp(pattern_string);
1242-
let field_name = re.exec(field.name)[1];
1243-
1244-
ctxt.trans.finalConstraintChecks.push(`if(!db._query(aql\`FOR v IN 1..1 INBOUND ${id}`);
1245-
addPossibleEdgeTypes(ctxt.trans.finalConstraintChecks, schema, graphql.getNamedType(field.type), field_name, false);
1246-
ctxt.trans.finalConstraintChecks.push(`RETURN x\`).next()){`);
1247-
ctxt.trans.finalConstraintChecks.push(` throw "Field ${f} in ${type.name} is breaking a @requiredForTarget directive (in reverse)!";`);
1248-
ctxt.trans.finalConstraintChecks.push(`}`);
1162+
if (!diasableDiractivesChecking) {
1163+
for (let f in type.getFields()) {
1164+
let field = type.getFields()[f];
1165+
for (dir of field.astNode.directives) {
1166+
if (dir.name.value == 'noloops') {
1167+
let collection = asAQLVar(`db.${getEdgeCollectionName(type.name, field.name)}`);
1168+
ctxt.trans.finalConstraintChecks.push(`if(db._query(aql\`FOR v IN 1..1 OUTBOUND ${id} ${collection} FILTER ${id} == v._id RETURN v\`).next()){`);
1169+
ctxt.trans.finalConstraintChecks.push(` throw "Field ${f} in ${type.name} is breaking a @noloops directive!";`);
1170+
ctxt.trans.finalConstraintChecks.push(`}`);
1171+
}
1172+
else if (dir.name.value == 'distinct') {
1173+
let collection = asAQLVar(`db.${getEdgeCollectionName(type.name, field.name)}`);
1174+
ctxt.trans.finalConstraintChecks.push(`if(db._query(aql\`FOR v, e IN 1..1 OUTBOUND ${id} ${collection} FOR v2, e2 IN 1..1 OUTBOUND ${id} ${collection} FILTER v._id == v2._id AND e._id != e2._id RETURN v\`).next()){`);
1175+
ctxt.trans.finalConstraintChecks.push(` throw "Field ${f} in ${type.name} is breaking a @distinct directive!";`);
1176+
ctxt.trans.finalConstraintChecks.push(`}`);
1177+
}
1178+
else if (dir.name.value == 'uniqueForTarget') {
1179+
// The direct variant of @uniqueForTarget
1180+
// edge is named after current type etc.
1181+
let collection = asAQLVar(`db.${getEdgeCollectionName(type.name, field.name)}`);
1182+
ctxt.trans.finalConstraintChecks.push(`if(db._query(aql\`FOR v, e IN 1..1 OUTBOUND ${id} ${collection} FOR v2, e2 IN 1..1 INBOUND v._id ${collection} FILTER e._id != e2._id RETURN v\`).next()){`);
1183+
ctxt.trans.finalConstraintChecks.push(` throw "Field ${f} in ${type.name} is breaking a @uniqueForTarget directive!";`);
1184+
ctxt.trans.finalConstraintChecks.push(`}`);
1185+
}
1186+
else if (dir.name.value == '_uniqueForTarget_AccordingToInterface') {
1187+
// The inherited/implemented variant of @uniqueForTarget
1188+
// The target does not only require at most one edge of this type, but at most one of any type implementing the interface
1189+
// Thankfully we got the name of the interface as a mandatory argument and can hence use this to get all types implementing it
1190+
1191+
let interfaceName = dir.arguments[0].value.value; // If we add more arguments to the directive this will fail horrible.
1192+
// But that should not happen (and it is quite easy to fix)
1193+
1194+
ctxt.trans.finalConstraintChecks.push(`if(db._query(aql\`FOR v, e IN 1..1 OUTBOUND ${id}`);
1195+
addPossibleEdgeTypes(ctxt.trans.finalConstraintChecks, schema, interfaceName, field.name, false);
1196+
ctxt.trans.finalConstraintChecks.push(`FOR v2, e2 IN 1..1 INBOUND v._id`);
1197+
addPossibleEdgeTypes(ctxt.trans.finalConstraintChecks, schema, interfaceName, field.name, false);
1198+
ctxt.trans.finalConstraintChecks.push(`FILTER e._id != e2._id RETURN v\`).next()){`);
1199+
ctxt.trans.finalConstraintChecks.push(` throw "Field ${f} in ${type.name} is breaking a @_uniqueForTarget_AccordingToInterface directive!";`);
1200+
ctxt.trans.finalConstraintChecks.push(`}`);
1201+
}
1202+
else if (dir.name.value == 'requiredForTarget') {
1203+
// The direct variant of @requiredForTarget
1204+
// edge is named after current type etc.
1205+
let edgeCollection = asAQLVar(`db.${getEdgeCollectionName(type.name, field.name)}`);
1206+
1207+
// The target type might be an interface, giving us slightly more to keep track of
1208+
// First, find the right collections to check
1209+
ctxt.trans.finalConstraintChecks.push(`if(db._query(aql\`FOR x IN FLATTEN(FOR i IN [`);
1210+
addPossibleTypes(ctxt.trans.finalConstraintChecks, schema, graphql.getNamedType(field.type), false);
1211+
// Second, count all edges ending at objects in these collections
1212+
ctxt.trans.finalConstraintChecks.push(`] RETURN i) LET endpoints = ( FOR v IN 1..1 INBOUND x ${edgeCollection} RETURN v)`);
1213+
// If the count returns 0, we have an object breaking the directive
1214+
ctxt.trans.finalConstraintChecks.push(`FILTER LENGTH(endpoints) == 0 RETURN x\`).next()){`);
1215+
ctxt.trans.finalConstraintChecks.push(` throw "There are object(s) breaking the @requiredForTarget directive of Field ${f} in ${type.name}!";`);
1216+
ctxt.trans.finalConstraintChecks.push(`}`);
1217+
}
1218+
else if (dir.name.value == '_requiredForTarget_AccordingToInterface') {
1219+
// The inherited/implemented variant of @requiredForTarget
1220+
// The target does not directly require an edge of this type, but at least one of any type implementing the interface
1221+
// Thankfully we got the name of the interface as a mandatory argument and can hence use this to get all types implementing it
1222+
1223+
let interfaceName = dir.arguments[0].value.value; // If we add more arguments to the directive this will fail horrible.
1224+
// But that should not happen (and it is quite easy to fix)
1225+
1226+
// The target type might be an interface, giving us slightly more to keep track of
1227+
// First, find the right collections to check
1228+
ctxt.trans.finalConstraintChecks.push(`if(db._query(aql\`FOR x IN FLATTEN(FOR i IN [`);
1229+
addPossibleTypes(ctxt.trans.finalConstraintChecks, schema, graphql.getNamedType(field.type), false);
1230+
// Second, count all edges ending at objects in these collections
1231+
ctxt.trans.finalConstraintChecks.push(`] RETURN i) LET endpoints = ( FOR v IN 1..1 INBOUND x `);
1232+
addPossibleEdgeTypes(ctxt.trans.finalConstraintChecks, schema, interfaceName, field.name, false);
1233+
ctxt.trans.finalConstraintChecks.push(` RETURN v)`);
1234+
// If the count returns 0, we have an object breaking the directive
1235+
ctxt.trans.finalConstraintChecks.push(`FILTER LENGTH(endpoints) == 0 RETURN x\`).next()){`);
1236+
ctxt.trans.finalConstraintChecks.push(` throw "There are object(s) breaking the inherited @_requiredForTarget_AccordingToInterface directive of Field ${f} in ${type.name}!";`);
1237+
ctxt.trans.finalConstraintChecks.push(`}`);
1238+
}
1239+
else if (dir.name.value == 'required' && field.name[0] == '_') {
1240+
// This is actually the reverse edge of a @requiredForTarget directive
1241+
1242+
let pattern_string = `^_(.+?)From${type.name}$`; // get the non-reversed edge name
1243+
let re = new RegExp(pattern_string);
1244+
let field_name = re.exec(field.name)[1];
1245+
1246+
ctxt.trans.finalConstraintChecks.push(`if(!db._query(aql\`FOR v IN 1..1 INBOUND ${id}`);
1247+
addPossibleEdgeTypes(ctxt.trans.finalConstraintChecks, schema, graphql.getNamedType(field.type), field_name, false);
1248+
ctxt.trans.finalConstraintChecks.push(`RETURN x\`).next()){`);
1249+
ctxt.trans.finalConstraintChecks.push(` throw "Field ${f} in ${type.name} is breaking a @requiredForTarget directive (in reverse)!";`);
1250+
ctxt.trans.finalConstraintChecks.push(`}`);
1251+
}
12491252
}
12501253
}
12511254
}

0 commit comments

Comments
 (0)