module Insights::API::Common::GraphQL::Generator
Constants
- PARAMETERS_PATH
- SCHEMAS_PATH
Public Class Methods
app_name()
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 31 def self.app_name Rails.application.class.parent.name.underscore end
base_init_schema(request, graphql_options, schema_overlay = {})
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 113 def self.base_init_schema(request, graphql_options, schema_overlay = {}) api_version = ::Insights::API::Common::GraphQL.version(request) version_namespace = "V#{api_version.tr('.', 'x')}" openapi_doc = ::Insights::API::Common::OpenApi::Docs.instance[api_version] openapi_content = openapi_doc.content graphql_namespace = if ::Insights::API::Common::GraphQL::Api.const_defined?(version_namespace, false) ::Insights::API::Common::GraphQL::Api.const_get(version_namespace) else ::Insights::API::Common::GraphQL::Api.const_set(version_namespace, Module.new) end return graphql_namespace.const_get("Schema") if graphql_namespace.const_defined?("Schema", false) resources = openapi_content["paths"].keys.sort collections = [] resources.each do |resource| next unless openapi_content.dig("paths", resource, "get") # we only care for queries rmatch = resource.match("^/(.*/)?([^/]*)/{[[a-z]*_]*id}$") next unless rmatch collection = rmatch[2] klass_name = collection.camelize.singularize next if graphql_namespace.const_defined?("#{klass_name}Type", false) _schema_name, this_schema = openapi_schema(openapi_doc, klass_name) next if this_schema.nil? || this_schema["type"] != "object" || this_schema["properties"].nil? collections << collection model_class = klass_name.constantize model_encrypted_columns_set = (model_class.try(:encrypted_columns) || []).to_set model_properties = [] properties = this_schema["properties"] properties.keys.sort.each do |property_name| next if model_encrypted_columns_set.include?(property_name) property_schema = properties[property_name] property_schema = openapi_content.dig(*path_parts(property_schema["$ref"])) if property_schema["$ref"] property_format = property_schema["format"] || "" property_type = property_schema["type"] description = property_schema["description"] property_graphql_type = graphql_type(property_name, property_format, property_type) model_properties << [property_name, property_graphql_type, description] if property_graphql_type end field_resolvers = collection_field_resolvers(schema_overlay, klass_name) model_is_associated, model_associations = resource_associations(openapi_content, collection) graphql_model_type_template = ERB.new(template("model_type"), nil, '<>').result(binding) graphql_namespace.module_eval(graphql_model_type_template) unless graphql_namespace.const_defined?("#{klass_name}AggregateType", false) graphql_aggregate_model_type_template = ERB.new(template("aggregate_model_type"), nil, '<>').result(binding) graphql_namespace.module_eval(graphql_aggregate_model_type_template) end end graphql_aggregate_type_template = ERB.new(template("aggregate_type"), nil, '<>').result(binding) graphql_namespace.module_eval(graphql_aggregate_type_template) graphql_query_type_template = ERB.new(template("query_type"), nil, '<>').result(binding) graphql_namespace.module_eval(graphql_query_type_template) graphql_schema_template = ERB.new(template("schema"), nil, '<>').result(binding) graphql_namespace.module_eval(graphql_schema_template) graphql_namespace.const_get("Schema") end
collection_field_resolvers(schema_overlay, collection)
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 87 def self.collection_field_resolvers(schema_overlay, collection) field_resolvers = {} schema_overlay.keys.each do |collection_regex| next unless collection.match(collection_regex) field_resolvers.merge!(schema_overlay.fetch_path(collection_regex, "field_resolvers") || {}) end field_resolvers end
collection_schema_overlay(schema_overlay, collection)
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 97 def self.collection_schema_overlay(schema_overlay, collection) schema_overlay.keys.each_with_object({}) do |collection_regex, collection_schema_overlay| next unless collection.match?(collection_regex) collection_schema_overlay.merge!(schema_overlay[collection_regex] || {}) end end
graphql_type(property_name, property_format, property_type)
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 51 def self.graphql_type(property_name, property_format, property_type) return "!types.ID" if property_name == "id" case property_type when "string" property_format == "date-time" ? "::Insights::API::Common::GraphQL::Types::DateTime" : "types.String" when "number" "types.Float" when "boolean" "types.Boolean" when "integer" "::Insights::API::Common::GraphQL::Types::BigInt" end end
init_schema(request, schema_overlay = {})
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 105 def self.init_schema(request, schema_overlay = {}) base_init_schema(request, { :use_pagination_v2 => false }, schema_overlay) end
init_schema_v2(request, schema_overlay = {})
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 109 def self.init_schema_v2(request, schema_overlay = {}) base_init_schema(request, { :use_pagination_v2 => true }, schema_overlay) end
openapi_schema(openapi_doc, klass_name)
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 11 def self.openapi_schema(openapi_doc, klass_name) schemas = openapi_doc.content.dig(*path_parts(SCHEMAS_PATH)) [klass_name, "#{klass_name}Out"].each do |name| schema = schemas[name] return [name, schema] if schema end end
path_parts(openapi_path)
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 19 def self.path_parts(openapi_path) openapi_path.split("/")[1..-1] end
pluggable_template_file_by(type)
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 35 def self.pluggable_template_file_by(type) templates_relative_path = "lib/#{app_name}/api/graphql/templates" template_path = File.expand_path(templates_relative_path, root_dir) Pathname.new(root_dir).join(template_path, "#{type}.erb") end
resource_associations(openapi_content, collection)
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 66 def self.resource_associations(openapi_content, collection) collection_is_associated = openapi_content["paths"].keys.any? do |path| path.match?("^/[^/]*/{[[a-z]*_]*id}/#{collection}$") && openapi_content.dig("paths", path, "get").present? end collection_associations = [] openapi_content["paths"].keys.each do |path| subcollection_match = path.match("^/#{collection}/{[[a-z]*_]*id}/([^/]*)$") next unless subcollection_match subcollection = subcollection_match[1] next unless openapi_content["paths"].keys.any? do |subcollection_path| subcollection_path.match?("^/#{subcollection}/{[[a-z]*_]*id}$") && openapi_content.dig("paths", subcollection_path, "get").present? end collection_associations << subcollection end [collection_is_associated ? true : false, collection_associations.sort] end
root_dir()
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 27 def self.root_dir Rails.root end
template(type)
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 47 def self.template(type) File.read(template_path_by(type)) end
template_file_by(type, root_dir = __dir__)
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 23 def self.template_file_by(type, root_dir = __dir__) Pathname.new(root_dir).join(File.expand_path("templates", root_dir), "#{type}.erb") end
template_path_by(type)
click to toggle source
# File lib/insights/api/common/graphql/generator.rb, line 41 def self.template_path_by(type) template_path_pluggable = pluggable_template_file_by(type) template_path_default = template_file_by(type) template_path_pluggable.exist? ? template_path_pluggable : template_path_default end