{"version":3,"sources":["../src/json.ts"],"sourcesContent":["/**\n * Mapping between GQL primitive types and JSON Schema property types\n *\n * @type       {<type>}\n */\nimport {\n  type FieldNode,\n  type GraphQLType,\n  isAbstractType,\n  isEnumType,\n  isListType,\n  isNonNullType,\n  isObjectType,\n  isScalarType\n} from \"graphql\";\nimport {\n  type BooleanSchema,\n  type IntegerSchema,\n  type NumberSchema,\n  type ObjectSchema,\n  type RefSchema,\n  type Schema,\n  type StringSchema\n} from \"fast-json-stringify\";\nimport { collectFields, collectSubfields, resolveFieldDef } from \"./ast.js\";\nimport { getOperationRootType } from \"./compat.js\";\nimport { type CompilationContext } from \"./execution.js\";\n\nconst PRIMITIVES: {\n  [key: string]:\n    | IntegerSchema[\"type\"]\n    | NumberSchema[\"type\"]\n    | StringSchema[\"type\"]\n    | BooleanSchema[\"type\"];\n} = {\n  Int: \"integer\",\n  Float: \"number\",\n  String: \"string\",\n  Boolean: \"boolean\",\n  ID: \"string\"\n};\n\n/**\n * GQL -> JSON Schema transform\n *\n * @param compilationContext\n * @return     {object}  A plain JavaScript object which conforms to JSON Schema\n */\nexport function queryToJSONSchema(\n  compilationContext: CompilationContext\n): Schema {\n  const type = getOperationRootType(\n    compilationContext.schema,\n    compilationContext.operation\n  );\n  const fields = collectFields(\n    compilationContext,\n    type,\n    compilationContext.operation.selectionSet,\n    Object.create(null),\n    Object.create(null)\n  );\n  const fieldProperties = Object.create(null);\n  for (const responseName of Object.keys(fields)) {\n    const fieldType = resolveFieldDef(\n      compilationContext,\n      type,\n      fields[responseName]\n    );\n    if (!fieldType) {\n      // if field does not exist, it should be ignored for compatibility concerns.\n      // Usually, validation would stop it before getting here but this could be an old query\n      continue;\n    }\n    fieldProperties[responseName] = transformNode(\n      compilationContext,\n      fields[responseName],\n      fieldType.type\n    );\n  }\n  return {\n    type: \"object\",\n    properties: {\n      data: {\n        type: \"object\",\n        properties: fieldProperties,\n        nullable: true\n      },\n      errors: {\n        type: \"array\",\n        items: {\n          type: \"object\",\n          additionalProperties: true,\n          properties: {\n            message: {\n              type: \"string\"\n            },\n            path: {\n              type: \"array\",\n              items: {\n                type: [\"string\", \"number\"]\n              }\n            },\n            locations: {\n              type: \"array\",\n              items: {\n                type: \"object\",\n                properties: {\n                  line: {\n                    type: \"number\"\n                  },\n                  column: {\n                    type: \"number\"\n                  }\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  };\n}\n\nfunction transformNode(\n  compilationContext: CompilationContext,\n  fieldNodes: FieldNode[],\n  type: GraphQLType\n): Exclude<Schema, RefSchema> {\n  if (isObjectType(type)) {\n    const subfields = collectSubfields(compilationContext, type, fieldNodes);\n    const properties = Object.create(null);\n    for (const responseName of Object.keys(subfields)) {\n      const fieldType = resolveFieldDef(\n        compilationContext,\n        type,\n        subfields[responseName]\n      );\n      if (!fieldType) {\n        // if field does not exist, it should be ignored for compatibility concerns.\n        // Usually, validation would stop it before getting here but this could be an old query\n        continue;\n      }\n      properties[responseName] = transformNode(\n        compilationContext,\n        subfields[responseName],\n        fieldType.type\n      );\n    }\n    return {\n      type: \"object\",\n      properties,\n      nullable: true\n    };\n  }\n  if (isListType(type)) {\n    return {\n      type: \"array\",\n      items: transformNode(compilationContext, fieldNodes, type.ofType),\n      nullable: true\n    };\n  }\n  if (isNonNullType(type)) {\n    const nullable = transformNode(compilationContext, fieldNodes, type.ofType);\n    nullable.nullable = false;\n    return nullable;\n  }\n  if (isEnumType(type)) {\n    return {\n      type: \"string\",\n      nullable: true\n    };\n  }\n  if (isScalarType(type)) {\n    const jsonSchemaType = PRIMITIVES[type.name];\n    if (!jsonSchemaType) {\n      throw new Error(`Got unexpected PRIMITIVES type: ${type.name}`);\n    }\n    return {\n      type: jsonSchemaType,\n      nullable: true\n    };\n  }\n  if (isAbstractType(type)) {\n    return compilationContext.schema.getPossibleTypes(type).reduce(\n      (res, t) => {\n        const jsonSchema = transformNode(compilationContext, fieldNodes, t);\n        (res as ObjectSchema).properties = {\n          ...(res as ObjectSchema).properties,\n          ...(jsonSchema as ObjectSchema).properties\n        };\n        return res;\n      },\n      {\n        type: \"object\",\n        properties: {},\n        nullable: true\n      }\n    );\n  }\n  throw new Error(`Got unhandled type: ${type.name}`);\n}\n"],"mappings":"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","names":[]}