UNPKG

ibm-graphql-query-generator

Version:

Randomly generate a GraphQL query using a GraphQL schema

843 lines 34.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const graphql_1 = require("graphql"); const seedrandom = require("seedrandom"); const merge_1 = require("merge"); const provide_variables_1 = require("./provide-variables"); const DEFAULT_CONFIG = { depthProbability: 0.5, breadthProbability: 0.5, maxDepth: 5, ignoreOptionalArguments: true, argumentsToIgnore: [], argumentsToConsider: [], considerInterfaces: false, considerUnions: false, pickNestedQueryField: false, providePlaceholders: false, providerMap: {} }; // Default location const loc = { start: 0, end: 0, startToken: null, endToken: null, source: null }; function getDocumentDefinition(definitions) { return { kind: graphql_1.Kind.DOCUMENT, definitions, loc }; } function getTypeNameMetaFieldDef() { return { name: { kind: 'Name', value: '__typename' }, kind: 'FieldDefinition', type: { kind: 'NonNullType', type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } } }; } function getQueryOperationDefinition(schema, config) { const node = schema.getQueryType().astNode; const { selectionSet, variableDefinitionsMap, variableValues } = getSelectionSetAndVars(schema, node, config); // Throw error if query would be empty if (selectionSet.selections.length === 0) { throw new Error(`Could not create query - no selection was possible at the root level`); } return { queryDocument: { kind: graphql_1.Kind.OPERATION_DEFINITION, operation: 'query', selectionSet, variableDefinitions: Object.values(variableDefinitionsMap), loc, name: getName('RandomQuery') }, variableValues }; } function getMutationOperationDefinition(schema, config) { const node = schema.getMutationType().astNode; const { selectionSet, variableDefinitionsMap, variableValues } = getSelectionSetAndVars(schema, node, config); // Throw error if mutation would be empty if (selectionSet.selections.length === 0) { throw new Error(`Could not create mutation - no selection was possible at the root level`); } return { mutationDocument: { kind: graphql_1.Kind.OPERATION_DEFINITION, operation: 'mutation', selectionSet, variableDefinitions: Object.values(variableDefinitionsMap), loc, name: getName('RandomMutation') }, variableValues }; } function getTypeName(type) { if (type.kind === graphql_1.Kind.NAMED_TYPE) { return type.name.value; } else if (type.kind === graphql_1.Kind.LIST_TYPE) { return getTypeName(type.type); } else if (type.kind === graphql_1.Kind.NON_NULL_TYPE) { return getTypeName(type.type); } else { throw new Error(`Cannot get name of type: ${type}`); } } exports.getTypeName = getTypeName; function isMandatoryType(type) { return type.kind === graphql_1.Kind.NON_NULL_TYPE; } function getName(name) { return { kind: graphql_1.Kind.NAME, value: name }; } function isObjectField(field, schema) { const ast = schema.getType(getTypeName(field.type)).astNode; return typeof ast !== 'undefined' && ast.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION; } function isInterfaceField(field, schema) { const ast = schema.getType(getTypeName(field.type)).astNode; return (typeof ast !== 'undefined' && ast.kind === graphql_1.Kind.INTERFACE_TYPE_DEFINITION); } function isUnionField(field, schema) { const ast = schema.getType(getTypeName(field.type)).astNode; return typeof ast !== 'undefined' && ast.kind === graphql_1.Kind.UNION_TYPE_DEFINITION; } function considerArgument(arg, config) { const isArgumentToIgnore = config.argumentsToIgnore.includes(arg.name.value); const isArgumentToConsider = config.argumentsToConsider.includes(arg.name.value); const isMand = isMandatoryType(arg.type); const isOptional = !isMand; // Check for consistency if (isMand && isArgumentToIgnore) { throw new Error(`Cannot ignore non-null argument "${arg.name.value}"`); } if (isArgumentToIgnore && isArgumentToConsider) { throw new Error(`Cannot ignore AND consider argument "${arg.name.value}"`); } // Return value based on options if (isMand) { return true; } if (isArgumentToConsider) { return true; } if (isArgumentToIgnore) { return false; } if (isOptional && config.ignoreOptionalArguments) { return false; } return true; } exports.considerArgument = considerArgument; function fieldHasLeafs(field, schema) { const ast = schema.getType(getTypeName(field.type)).astNode; if (ast.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION || ast.kind === graphql_1.Kind.INTERFACE_TYPE_DEFINITION) { return ast.fields.some((child) => { const childAst = schema.getType(getTypeName(child.type)).astNode; return (typeof childAst === 'undefined' || childAst.kind === graphql_1.Kind.SCALAR_TYPE_DEFINITION); }); } else if (ast.kind === graphql_1.Kind.UNION_TYPE_DEFINITION) { return ast.types.some((child) => { let unionNamedTypes = schema.getType(child.name.value).astNode.fields; return unionNamedTypes.some((child) => { const childAst = schema.getType(getTypeName(child.type)).astNode; return (typeof childAst === 'undefined' || childAst.kind === graphql_1.Kind.SCALAR_TYPE_DEFINITION); }); }); } return false; } function getRandomFields(fields, config, schema, depth) { const results = []; // Create lists of nested and flat fields to pick from let nested; let flat; if (config.considerInterfaces && config.considerUnions) { nested = fields.filter((field) => { return (isObjectField(field, schema) || isInterfaceField(field, schema) || isUnionField(field, schema)); }); flat = fields.filter((field) => { return !(isObjectField(field, schema) || isInterfaceField(field, schema) || isUnionField(field, schema)); }); } else if (config.considerInterfaces && config.considerUnions) { fields = fields.filter((field) => { return !isInterfaceField(field, schema); }); nested = fields.filter((field) => { return isObjectField(field, schema) || isUnionField(field, schema); }); flat = fields.filter((field) => { return !(isObjectField(field, schema) || isUnionField(field, schema)); }); } else if (config.considerInterfaces && config.considerUnions) { fields = fields.filter((field) => { return !isUnionField(field, schema); }); nested = fields.filter((field) => { return isObjectField(field, schema) || isInterfaceField(field, schema); }); flat = fields.filter((field) => { return !(isObjectField(field, schema) || isInterfaceField(field, schema)); }); } else { fields = fields.filter((field) => { return !(isInterfaceField(field, schema) || isUnionField(field, schema)); }); nested = fields.filter((field) => { return isObjectField(field, schema); }); flat = fields.filter((field) => { return !isObjectField(field, schema); }); } // Filter out fields that only have nested subfields if (depth + 2 === config.maxDepth) { nested = nested.filter((field) => fieldHasLeafs(field, schema)); } const nextIsLeaf = depth + 1 === config.maxDepth; const pickNested = typeof config.depthProbability === 'number' ? random(config) <= config.depthProbability : random(config) <= config.depthProbability(depth); // If we decide to pick nested, choose one nested field (if one exists)... if ((pickNested && nested.length > 0 && !nextIsLeaf) || (depth === 0 && config.pickNestedQueryField)) { let nestedIndex = Math.floor(random(config) * nested.length); results.push(nested[nestedIndex]); nested.splice(nestedIndex, 1); // ...and possibly choose more nested.forEach((field) => { const pickNested = typeof config.breadthProbability === 'number' ? random(config) <= config.breadthProbability : random(config) <= config.breadthProbability(depth); if (pickNested) { results.push(field); } }); } // Pick flat fields based on the breadth probability flat.forEach((field) => { const pickFlat = typeof config.breadthProbability === 'number' ? random(config) <= config.breadthProbability : random(config) <= config.breadthProbability(depth); if (pickFlat) { results.push(field); } }); // Ensure to pick at least one field if (results.length === 0) { // If the next level is not the last, we can choose ANY field if (!nextIsLeaf) { const forcedIndex = Math.floor(random(config) * fields.length); results.push(fields[forcedIndex]); // ...otherwise, we HAVE TO choose a flat field: } else if (flat.length > 0) { const forcedFlatIndex = Math.floor(random(config) * flat.length); results.push(flat[forcedFlatIndex]); } else { // default to selecting __typename meta field: results.push(getTypeNameMetaFieldDef()); } } return results; } function getVariableDefinition(name, type) { return { kind: graphql_1.Kind.VARIABLE_DEFINITION, type: type, variable: { kind: graphql_1.Kind.VARIABLE, name: getName(name) } }; } function getVariable(argName, varName) { return { kind: graphql_1.Kind.ARGUMENT, loc, name: getName(argName), value: { kind: graphql_1.Kind.VARIABLE, name: getName(varName) } }; } function getNextNodefactor(variableValues) { if (typeof variableValues['first'] === 'number') { variableValues['first']; } return 1; } /** * Returns the first slicing argument defined in the field's @listSize * directive, if: * - The @listSize directive is indeed present, and defines slicing arguments * - The requiredArguments do not already include any of the defined slicing * arguments * - The @listSize directive doesn't also set requireOneSlicingArgument to * false * * TODO: add link to specification / documentation of @listSize directive */ function getMissingSlicingArg(requiredArguments, field, schema) { // Return null if there is no @listSize directive: const listSizeDirective = getListSizeDirective(field); if (!listSizeDirective) return null; // Return null if @listSize directive defines no slicing arguments: const slicingArgumentsArg = getSlicingArguments(listSizeDirective); if (!slicingArgumentsArg) return null; // Return null if requireOneSlicingArgument is set to false: const requireOneSlicingArg = getRequireOneSlicingArgument(listSizeDirective); if (requireOneSlicingArg && requireOneSlicingArg.value.value === false // already checked requireOneSlicingArg is a boolean ) return null; // Return null if a slicing argument is already used: const slicingArguments = slicingArgumentsArg.value.values // already checked slicingArgumentsArg is a list .filter((value) => value.kind === 'StringValue') .map((value) => value.value); const usesSlicingArg = slicingArguments.some((slicingArg) => requiredArguments .map((existing) => existing.name.value) .includes(slicingArg)); if (usesSlicingArg) return null; // Returns the first slicing argument if slicing argument can be split on '.' // then we just need to check the first level match return field.arguments.find((arg) => { return slicingArguments.find((slicingArgument) => { const tokenizedPath = slicingArgument.split('.'); if (tokenizedPath.length < 1) return false; return arg.name.value === tokenizedPath[0]; }); }); } function getArgsAndVars(field, nodeName, config, schema, providedValues) { const fieldName = field.name.value; const allArgs = field.arguments; const args = []; const variableDefinitionsMap = {}; const requiredArguments = allArgs.filter((arg) => considerArgument(arg, config)); /** * Check for slicing arguments defined in a @listSize directive that should * be present: */ const missingSlicingArg = getMissingSlicingArg(requiredArguments, field, schema); /** * Check if missingSlicingArg is already in requiredArguments * * Because slicing arguments may be deeply nested (input object types), there * isn't a simple way to check for conflicts */ if (missingSlicingArg && !requiredArguments.find((arg) => { return arg.name.value === missingSlicingArg.name.value; })) { requiredArguments.push(missingSlicingArg); } requiredArguments.forEach((arg) => { const varName = `${nodeName}__${fieldName}__${arg.name.value}`; args.push(getVariable(arg.name.value, varName)); variableDefinitionsMap[varName] = getVariableDefinition(varName, arg.type); }); const variableValues = {}; // First, check for providers based on type__field query // (Note: such a provider must return a value which is an object) const { providerFound, value } = provide_variables_1.getProviderValue(`${nodeName}__${fieldName}`, config, providedValues); if (providerFound && typeof value === 'object') { Object.entries(value).forEach(([argName, value]) => { const varName = `${nodeName}__${fieldName}__${argName}`; // Only consider required arguments (provider can provide more than necessary) if (Object.keys(variableDefinitionsMap).includes(varName)) { variableValues[varName] = value; } }); } // Second, check for providers based on type__field__argument query // (Note: they overwrite possibly already provided values) requiredArguments.forEach((arg) => { const varName = `${nodeName}__${fieldName}__${arg.name.value}`; const argType = schema.getType(getTypeName(arg.type)); const { providerFound, value } = provide_variables_1.getProviderValue(varName, config, Object.assign(Object.assign({}, variableValues), providedValues), // pass already used variable values argType); if (providerFound) { variableValues[varName] = value; } }); // Third, populate all so-far neglected require variables with defaults or null requiredArguments.forEach((arg) => { const varName = `${nodeName}__${fieldName}__${arg.name.value}`; const argType = schema.getType(getTypeName(arg.type)); if (typeof variableValues[varName] === 'undefined') { if (provide_variables_1.isEnumType(argType)) { // Enum values can be randomly selected variableValues[varName] = provide_variables_1.getRandomEnum(argType); } else if (config.providePlaceholders) { variableValues[varName] = provide_variables_1.getDefaultArgValue(schema, config, arg.type); // Add default values for unfulfilled listSize directive if applicable const listSizeDirective = getListSizeDirective(field); if (listSizeDirective) { const value = getListSizeDirectiveDefaultValue(listSizeDirective, arg.type, config, schema); if (value !== undefined) { if (typeof value !== 'object') { variableValues[varName] = value; } else { variableValues[varName] = merge_1.default.recursive(value, variableValues[varName]); } } } } else if (arg.type.kind === 'NonNullType') { throw new Error(`Missing provider for non-null variable "${varName}" of type "${graphql_1.print(arg.type)}". ` + `Either add a provider (e.g., using a wildcard "*__*" or "*__*__*"), ` + `or set providePlaceholders configuration option to true.`); } else { variableValues[varName] = null; } } }); return { args, variableDefinitionsMap, variableValues }; } /** * Given a field node, return the listSize directive, if it exists */ function getListSizeDirective(field) { return field === null || field === void 0 ? void 0 : field.directives.find((dir) => dir.name.value === 'listSize'); } /** * Given a listSize directive, get the slicingArguments argument */ function getSlicingArguments(listSizeDirective) { if (!listSizeDirective) return undefined; const slicingArgumentsArg = listSizeDirective.arguments.find((arg) => arg.name.value === 'slicingArguments'); if (!slicingArgumentsArg || slicingArgumentsArg.value.kind !== 'ListValue') return undefined; return slicingArgumentsArg; } /** * Given a listSize directive, get the requireOneSlicingArgument argument */ function getRequireOneSlicingArgument(listSizeDirective) { if (!listSizeDirective) return undefined; const requireOneSlicingArg = listSizeDirective.arguments.find((arg) => arg.name.value === 'requireOneSlicingArgument'); if (!requireOneSlicingArg || requireOneSlicingArg.value.kind !== 'BooleanValue') return undefined; return requireOneSlicingArg; } /** * For a given listSize directive, return a default value for it */ function getListSizeDirectiveDefaultValue(listSizeDirective, typeNode, config, schema) { // if requiredOneSlicingArg is false then we do not add anything because none of the slicingArguments are required const requireOneSlicingArg = getRequireOneSlicingArgument(listSizeDirective); if (requireOneSlicingArg && requireOneSlicingArg.value.value === false) { return undefined; } const slicingArgumentsArg = getSlicingArguments(listSizeDirective); if (!slicingArgumentsArg) return undefined; /** * Already checked slicingArgumentsArguments is a list * * Extract paths from slicingArgumentsArguments */ const slicingArgumentsPaths = slicingArgumentsArg.value.values.map((value) => { if (value.kind === 'StringValue') return value.value; }); if (slicingArgumentsPaths.length > 0) { const slicingArgumentsTokenizedPath = slicingArgumentsPaths[0].split('.'); return getListSizeDirectiveDefaultValueHelper(slicingArgumentsTokenizedPath, typeNode, config, schema); } } function getListSizeDirectiveDefaultValueHelper(tokenizedPath, typeNode, config, schema) { var _a; if (tokenizedPath.length === 0) { return undefined; } if (tokenizedPath.length === 1) { return provide_variables_1.getDefaultArgValue(schema, config, typeNode); } const result = {}; const namedType = unwrapType(typeNode); if (namedType.kind === 'NamedType') { const type = schema.getType(namedType.name.value); if (((_a = type.astNode) === null || _a === void 0 ? void 0 : _a.kind) === 'InputObjectTypeDefinition') { const nextType = type.astNode.fields.find((field) => { return field.name.value === tokenizedPath[1]; }); const value = getListSizeDirectiveDefaultValueHelper(tokenizedPath.slice(1), nextType.type, config, schema); // Add value depending if it is a list or not if (!isListType(typeNode)) { result[tokenizedPath[1]] = value; } else { result[tokenizedPath[1]] = [value]; } } } return result; } /** * Given a type node, return the named type node */ function unwrapType(type) { if (type.kind === 'ListType' || type.kind === 'NonNullType') { return unwrapType(type.type); } else { return type; } } /** * Given a type node, determine if it is some kind of list node, whether it be * non-null list or nested list, or any combination of which */ function isListType(type) { if (type.kind === 'NamedType') { return false; } else { if (type.kind === 'ListType') { return true; } else { return isListType(type.type); } } } function getSelectionSetAndVars(schema, node, config, depth = 0) { let selections = []; let variableDefinitionsMap = {}; let variableValues = {}; // Abort at leaf nodes: if (depth === config.maxDepth) { return { selectionSet: undefined, variableDefinitionsMap, variableValues }; } if (node.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION) { let fields = getRandomFields(node.fields, config, schema, depth); fields.forEach((field) => { // Recurse, if field has children: const nextNode = schema.getType(getTypeName(field.type)).astNode; let selectionSet = undefined; if (typeof nextNode !== 'undefined') { const res = getSelectionSetAndVars(schema, nextNode, config, depth + 1); // Update counts and nodeFactor: config.resolveCount += config.nodeFactor; config.nodeFactor *= getNextNodefactor(res.variableValues); config.typeCount += config.nodeFactor; selectionSet = res.selectionSet; variableDefinitionsMap = Object.assign(Object.assign({}, variableDefinitionsMap), res.variableDefinitionsMap); variableValues = Object.assign(Object.assign({}, variableValues), res.variableValues); } const avs = getArgsAndVars(field, node.name.value, config, schema, variableValues); variableDefinitionsMap = Object.assign(Object.assign({}, variableDefinitionsMap), avs.variableDefinitionsMap); variableValues = Object.assign(Object.assign({}, variableValues), avs.variableValues); selections.push({ kind: graphql_1.Kind.FIELD, name: getName(field.name.value), selectionSet, arguments: avs.args }); }); } else if (node.kind === graphql_1.Kind.INTERFACE_TYPE_DEFINITION) { let fields = getRandomFields(node.fields, config, schema, depth); fields.forEach((field) => { // Recurse, if field has children: const nextNode = schema.getType(getTypeName(field.type)).astNode; let selectionSet = undefined; if (typeof nextNode !== 'undefined') { const res = getSelectionSetAndVars(schema, nextNode, config, depth + 1); // Update counts and nodeFactor: config.resolveCount += config.nodeFactor; config.nodeFactor *= getNextNodefactor(res.variableValues); config.typeCount += config.nodeFactor; selectionSet = res.selectionSet; variableDefinitionsMap = Object.assign(Object.assign({}, variableDefinitionsMap), res.variableDefinitionsMap); variableValues = Object.assign(Object.assign({}, variableValues), res.variableValues); } const avs = getArgsAndVars(field, node.name.value, config, schema, variableValues); variableDefinitionsMap = Object.assign(Object.assign({}, variableDefinitionsMap), avs.variableDefinitionsMap); variableValues = Object.assign(Object.assign({}, variableValues), avs.variableValues); selections.push({ kind: graphql_1.Kind.FIELD, name: getName(field.name.value), selectionSet, arguments: avs.args }); }); // Get all objects that implement an interface let objectsImplementingInterface = Object.values(schema.getTypeMap()).filter((namedType) => { if (namedType.astNode && namedType.astNode.kind === 'ObjectTypeDefinition') { let interfaceNames = namedType.astNode.interfaces.map((interfaceNamedType) => { return interfaceNamedType.name.value; }); if (interfaceNames.includes(node.name.value)) { return true; } } return false; }); // Randomly select named types from the union let pickObjectsImplementingInterface = objectsImplementingInterface.filter(() => { if (typeof config.breadthProbability === 'number') { return random(config) <= config.breadthProbability; } else { return random(config) <= config.breadthProbability(depth); } }); // If no named types are selected, select any one if (pickObjectsImplementingInterface.length === 0) { const forcedCleanIndex = Math.floor(random(config) * objectsImplementingInterface.length); pickObjectsImplementingInterface.push(objectsImplementingInterface[forcedCleanIndex]); } pickObjectsImplementingInterface.forEach((namedType) => { if (namedType.astNode) { let type = namedType.astNode; // Unions can only contain objects if (type.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION) { // Get selections let selectionSet = undefined; const res = getSelectionSetAndVars(schema, type, config, depth); selectionSet = res.selectionSet; variableDefinitionsMap = Object.assign(Object.assign({}, variableDefinitionsMap), res.variableDefinitionsMap); variableValues = Object.assign(Object.assign({}, variableValues), res.variableValues); let fragment = { kind: graphql_1.Kind.INLINE_FRAGMENT, typeCondition: { kind: graphql_1.Kind.NAMED_TYPE, name: { kind: graphql_1.Kind.NAME, value: type.name.value } }, selectionSet: selectionSet }; selections.push(fragment); } else { throw Error(`There should only be object types ` + `in the selectionSet but found: ` + `"${JSON.stringify(type, null, 2)}"`); } } else { selections.push({ kind: graphql_1.Kind.FIELD, name: { kind: graphql_1.Kind.NAME, value: namedType.name } }); } }); } else if (node.kind === graphql_1.Kind.UNION_TYPE_DEFINITION) { // Get the named types in the union let unionNamedTypes = node.types.map((namedTypeNode) => { return schema.getType(namedTypeNode.name.value); }); // Randomly select named types from the union let pickUnionNamedTypes = unionNamedTypes.filter(() => { if (typeof config.breadthProbability === 'number') { return random(config) <= config.breadthProbability; } else { return random(config) <= config.breadthProbability(depth); } }); // If no named types are selected, select any one if (pickUnionNamedTypes.length === 0) { const forcedCleanIndex = Math.floor(random(config) * unionNamedTypes.length); pickUnionNamedTypes.push(unionNamedTypes[forcedCleanIndex]); } pickUnionNamedTypes.forEach((namedType) => { if (namedType.astNode) { let type = namedType.astNode; // Unions can only contain objects if (type.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION) { // Get selections let selectionSet = undefined; const res = getSelectionSetAndVars(schema, type, config, depth); selectionSet = res.selectionSet; variableDefinitionsMap = Object.assign(Object.assign({}, variableDefinitionsMap), res.variableDefinitionsMap); variableValues = Object.assign(Object.assign({}, variableValues), res.variableValues); let fragment = { kind: graphql_1.Kind.INLINE_FRAGMENT, typeCondition: { kind: graphql_1.Kind.NAMED_TYPE, name: { kind: graphql_1.Kind.NAME, value: type.name.value } }, selectionSet: selectionSet }; selections.push(fragment); } else { throw Error(`There should only be object types ` + `in the selectionSet but found: ` + `"${JSON.stringify(type, null, 2)}"`); } } else { selections.push({ kind: graphql_1.Kind.FIELD, name: { kind: graphql_1.Kind.NAME, value: namedType.name } }); } }); } let aliasIndexes = {}; let cleanselections = []; // Ensure unique field names/aliases selections.forEach((selectionNode) => { if (selectionNode.kind === graphql_1.Kind.FIELD) { let fieldName = selectionNode.name.value; if (fieldName in aliasIndexes) { cleanselections.push(Object.assign(Object.assign({}, selectionNode), { alias: { kind: graphql_1.Kind.NAME, value: `${fieldName}${aliasIndexes[fieldName]++}` } })); } else { aliasIndexes[fieldName] = 2; cleanselections.push(selectionNode); } } else if (selectionNode.kind === graphql_1.Kind.INLINE_FRAGMENT) { let cleanFragmentSelections = []; selectionNode.selectionSet.selections.forEach((fragmentSelectionNode) => { if (fragmentSelectionNode.kind === graphql_1.Kind.FIELD) { let fieldName = fragmentSelectionNode.name.value; if (fieldName in aliasIndexes) { cleanFragmentSelections.push(Object.assign(Object.assign({}, fragmentSelectionNode), { alias: { kind: graphql_1.Kind.NAME, value: `${fieldName}${aliasIndexes[fieldName]++}` } })); } else { aliasIndexes[fieldName] = 2; cleanFragmentSelections.push(fragmentSelectionNode); } } }); selectionNode.selectionSet.selections = cleanFragmentSelections; cleanselections.push(selectionNode); } else { throw Error(`There should not be any fragment spreads in the selectionNode "${JSON.stringify(selectionNode, null, 2)}"`); } }); return { selectionSet: cleanselections.length > 0 ? { kind: graphql_1.Kind.SELECTION_SET, selections: cleanselections } : undefined, variableDefinitionsMap, variableValues }; } function generateRandomMutation(schema, config = {}) { const finalConfig = Object.assign(Object.assign(Object.assign({}, DEFAULT_CONFIG), config), { seed: typeof config.seed !== 'undefined' ? config.seed : Math.random(), nodeFactor: 1, typeCount: 0, resolveCount: 0 }); const { mutationDocument, variableValues } = getMutationOperationDefinition(schema, finalConfig); const definitions = [mutationDocument]; return { mutationDocument: getDocumentDefinition(definitions), variableValues, seed: finalConfig.seed, typeCount: finalConfig.typeCount, resolveCount: finalConfig.resolveCount }; } exports.generateRandomMutation = generateRandomMutation; function generateRandomQuery(schema, config = {}) { const finalConfig = Object.assign(Object.assign(Object.assign({}, DEFAULT_CONFIG), config), { seed: typeof config.seed !== 'undefined' ? config.seed : Math.random(), nodeFactor: 1, typeCount: 0, resolveCount: 0 }); const { queryDocument, variableValues } = getQueryOperationDefinition(schema, finalConfig); const definitions = [queryDocument]; return { queryDocument: getDocumentDefinition(definitions), variableValues, seed: finalConfig.seed, typeCount: finalConfig.typeCount, resolveCount: finalConfig.resolveCount }; } exports.generateRandomQuery = generateRandomQuery; function random(config) { if (typeof config.nextSeed !== 'undefined') { config.nextSeed = seedrandom(config.nextSeed)(); return config.nextSeed; } else { config.nextSeed = seedrandom(config.seed)(); return config.nextSeed; } } //# sourceMappingURL=generate-query.js.map