@@ -12,6 +12,7 @@ module.exports = {
12
12
let db_name = process . env . db ? process . env . db : 'dev-db' ;
13
13
let url = process . env . URL ? process . env . URL : 'http://localhost:8529' ;
14
14
let drop = process . env . DROP === 'true' ;
15
+ let diasableDiractivesChecking = process . env . DISABLE_DIRECTIVES_CHECKING === 'true' ;
15
16
disableEdgeValidation = process . env . DISABLE_EDGE_VALIDATION === 'true' ;
16
17
db = new arangojs . Database ( { url : url } ) ;
17
18
@@ -1158,94 +1159,96 @@ function addPossibleEdgeTypes(query, schema, type_name, field_name, use_aql = tr
1158
1159
* @param schema
1159
1160
*/
1160
1161
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
+ }
1249
1252
}
1250
1253
}
1251
1254
}
0 commit comments