Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bitbucket.org/graph-ql-schema/sbuilder

Package Overview
Dependencies
Alerts
File Explorer
Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bitbucket.org/graph-ql-schema/sbuilder

  • v1.6.0
  • Source
  • Go
  • Socket score

Version published
Created
Source

Библиотека генерации GraphQL API

Стандартный набор бибилиотек, предназначенных для реализации API с использованием GraphQL, не предоставляет ни какой возможности для генерации API, все параметры/типы/методы приходится прописывать вручную или генерировать при помощи аннотаций, что не всегда удобно, например, когда необходимо реализовать достаточно динамичное API для запросов. Данная библиотека решает эту проблему, предоставляя взоможность сгенерировать API GraphQL по определенному шаблону.

Возможности

Библиотека предоставляет слудующие возможности:

Генерация запроса выборки листинга сущности.

Библиотека может сформировать набор параметров для стандартной библиотеки GraphQL для выбора листинга сущностей определенного вида. Для этого используется следующий формат:

query Test {
  test_list (
    # Набор параметров фильтрации
    where: {
      is_active: {
        _equals: true
      }
    }
    # Параметры пагенации запроса
    offset: 0
    limit: 0
    # Параметры сортировки
    order: [{
      by: name
      direction: asc
      priority: 1
    }]
  ) {
    id
    name
    stat
    active_date
    is_active
  }
}

Доступные для выбора параметры:

 where - Фильтрация запроса
 limit - Количество записей в результате
 offset - Смещение (для пагенации)
 rder - Сортировка запроса
Генерация запроса аггрегации

На основе переданного объекта библиотека формирует новый запрос на аггрегацию значений сущности. Формат:

query Test {
  test_aggregate(
    # Аналог SQL GroupBy
    groupBy:[name, active_date]
    # Аналог SQL Having
    having: {
      is_active: {
        _equals: true
      }
    }
    # Сортировка результата
    order: [{
      by: name
      direction: asc
      priority: 1
    }]
  ){
    count
    avg {
      stat
    }
    variants {
      name
      id
    }
    min {
      stat
    }
    max {
      stat
    }
    sum {
      stat
    }
  }
}

Доступные для выбора параметры:

 where - Фильтрация запроса
 limit - Количество записей в результате
 offset - Смещение (для пагенации)
 rder - Сортировка запроса
 groupBy - Аналог SQL GroupBy
 having - Аналог SQL Having

Доступные операторы аггрегации:

 count - Количество записей
 avg - Вычисление среднего значения
 min - Поиск минимального значения
 max - Поиск максимального значения
 sum - Сумма всех значений
 variants - Уникальные варианты значений для переданных полей
Генерация мутации вставки значений

Библиотека может сгенерировать мутацию вставки значений для сущности. Формат:

mutation Test {
  test_insert(
    objects: [{
      name: "test"
      is_active: true
      active_date: "2002-02-02T21:00:16.000Z"
    }]
  ) {
    affected_rows
    returning {
      id
      active_date
      name
      is_active
      stat
    }
  }
}

Для передачи вставляемых значений используется параметр objects, который представляет собой массив объектов.

В качестве результата доступны 2 параметра:

 affected_rows - Количество вставленных значений
 returning - Массив вставленных объектов.
Генерация мутации обновления значений

Библиотека генерирует мутацию обновления значений по следующему формату:

mutation Test {
  test_update(
    set: {
      is_active: false
    }
    where: {
      is_active: {
        _equals: true
      }   
    }
  ) {
    affected_rows
    returning {
      id
      name
    }
  }
}

Для передачи устанавливаемого значения используется параметр set, в котором передаются только те значения, которые необходимо изменить.

В качестве результата доступны 2 параметра:

 affected_rows - Количество обновленных значений
 returning - Массив обновленных объектов.
Генерация мутации удаления значений

Библиотека генерирует мутацию удаления записей об объектах по следующему формату:

mutation Test {
  test_delete(
    where: {
      is_active: {
        _equals: false
      }
    }
  ) {
    affected_rows
  }
}

Для фильтрации удаления используется параметр where, который позволяет ограничить удаляемые значения.

В качестве результата можно получить количество удаленных значений, используя поле: affected_rows

Генерация параметров Where/Having

Данные поля могут быть сгенерированы только для следующих полей сущности:

  • Поле не является объектом

  • Поле не является массивом

Доступные операторы:

  1. _and - Логическое И для дочерних подопераций

  2. _or - Логическое ИЛИ для дочерних подопераций

  3. _not - Отрицание дочерней подоперации

Для операторов И и ИЛИ указывается массив групп операций. Внутри каждой группы операции объединяются оператором И. Пример:

Для переданного параметра

where: {
    is_active: {
        _equals: true
    }
    _or: [
        {
            id: {
                _equals: 1
            }
        }
        {
            id: {
                _equals: 2
            }
            stat: {
                _equals: 5
            }
        }
    ]
}

будет эквивалентна следующая запись:

is_active = true AND (id = 1 OR (id = 2 AND stat = 5))

Доступные операции:

  1. _equals - Операция равенства. Доступна для всех подходящих полей.

  2. _more - Операция >. Доступна для числовых значений и дат.

  3. _more_or_equals - Операция >=. Доступна для числовых значений и дат.

  4. _less - Операция <. Доступна для числовых значений и дат.

  5. _less_or_equals - Операция <=. Доступна для числовых значений и дат.

  6. _like - Операция поиска подстроки. Доступна только для строковых полей.

  7. _in - Операция поиска по массиву значений. Доступна для всех полей

  8. _between - Операция поиска значений в промежутке. Доступна для числовых значений и дат.

Установка

Для установки достаточно выполнить команду:

go get -u bitbucket.org/graph-ql-schema/sbuilder
Использование

Для использования библиотеки необходимо импортировать ее в какой либо скрипт:

import "bitbucket.org/graph-ql-schema/sbuilder"

Для генерации API необходимо использовать фабрику генератора:

// Фабрика Configurable Logger. Можно опустить, если у вас уже есть
var loggerFactory = configurable_logger.LoggerFactoryGenerator(false)

// Фабрика GraphQlSchemaBuilder
var schemaBuilder = sbuilder.NewGraphQlSchemaBuilder(loggerFactory)

После генерации фабрики станет доступн следующий функционал:

// Интерфейс билдера GraphQL сервера
type GraphQlSchemaBuilderInterface interface {
	// Регистрация сущности для обработки сервером.
	// Метод генерирует валидное GraphQL API для данной сущности при помощи переданных параметров
	// запросов (queries), где в качестве ключа передается тип запроса для генерации, а в качестве
	// значения - резолвер сущности.
	RegisterEntity(object *graphql.Object, queries EntityQueries, operations []configurable_logger.LogOperation)

	// Регистрация базового запроса без какой либо обработки со стороны сервиса
	// Метод предназначен для регистрации кастома GraphQL API, не входящего в библиотеку
	RegisterQuery(key string, field *graphql.Field)

	// Регистрация базовой мутации без какой либо обработки со стороны сервиса
	// Метод предназначен для регистрации кастома GraphQL API, не входящего в библиотеку
	RegisterMutation(key string, field *graphql.Field)

	// Установка кастомных параметров конфигурации сервера
	// По умолчанию используются:
	// 	- Host: 0.0.0.0
	//  - Port: 8080
	//  - Uri: /graphql
	SetServerConfig(config GraphQlServerConfig)

	// Создание экземпляра сервера для обработки GraphQL запросов.
	BuildServer() (GraphQlServerInterface, error)
}

Использвоать данный функционал можно следующим образом:

// Подготавливаем сущность GraphQL
var sqlTestObj = graphql.NewObject(
	graphql.ObjectConfig{
		Name: "test",
		Fields: graphql.Fields{
			"id": &graphql.Field{
				Type: graphql.ID,
				Name: "id",
			},
			"name": &graphql.Field{
				Type: graphql.String,
				Name: "name",
			},
			"active_date": &graphql.Field{
				Type: graphql.NewNonNull(graphql.DateTime),
				Name: "active_date",
			},
			"stat": &graphql.Field{
				Type: graphql.Int,
				Name: "stat",
			},
			"is_active": &graphql.Field{
				Type: graphql.NewNonNull(graphql.Boolean),
				Name: "is_active",
			},
		},
		Description: "test entity",
	},
)
// Реализуем резолверы сущности
type TestData struct {
	Id         int64     `db:"id"`
	ActiveDate time.Time `db:"active_from" json:"active_date"`
	Name       string    `db:"name"`
	Stat       int       `db:"stat"`
	IsActive   bool      `db:"is_active" json:"is_active"`
}

func testEntityResolver(params sbuilder.Parameters) (i interface{}, err error) {
	sql := ""
	if nil != params.Arguments.Where {
		sql, err = params.Arguments.Where.ToSQL(params.GraphQlObject, map[string]string{
			"active_date": "active_from",
		})

		if nil != err {
			return nil, err
		}
	}

	results := pgsqlTestDataLoad(sql)
	return results, nil
}
// Генерируем API для сущности
schemaBuilder.RegisterEntity(sqlTestObj, sbuilder.EntityQueries{
		sbuilder.ListQuery: testEntityResolver,
		sbuilder.AggregateQuery: func(params sbuilder.Parameters) (i interface{}, err error) {
			return nil, nil
		},
		sbuilder.InsertMutation: func(params sbuilder.Parameters) (i interface{}, err error) {
			return nil, nil
		},
		sbuilder.UpdateMutation: func(params sbuilder.Parameters) (i interface{}, err error) {
			return nil, nil
		},
		sbuilder.DeleteMutation: func(params sbuilder.Parameters) (i interface{}, err error) {
			return nil, nil
		},
	}, nil)
// Генерируем сервер GraphQL
server, err := schemaBuilder.BuildServer()
if nil != err {
    log.Fatal(err)
}
// Запускаем сервер
log.Fatal(server.Run())

В качестве Web сервера библиотека использует FastHTTP - https://github.com/valyala/fasthttp

Входные параметры для резолвера
// Параметры запроса, передаваемые в контроллер
type Parameters struct {
	Arguments 	    ParsedArguments         // Аргументы запроса: Where, Order и т.д.
	Context   		context.Context         // Контекст запроса. RequestWriter, Request и т.д.
	Fields          GraphQlRequestedFields  // Запрошенные поля
	GraphQlObject   *graphql.Object         // Объект сущности схемы GraphQL, для которого выполняется запрос.
	GraphqlParams   graphql.ResolveParams   // Оригинальный набор параметров GraphQL
}

Подтипы для ParsedArguments

// Результирующая структура парсинга параметров запроса
type ParsedArguments struct {
	Objects    Objects
	Set        Set
	GroupBy    GroupBy
	OrderBy    []Order
	Pagination *Pagination
	Where      Operation
	Having     Operation
}

// Типы, описывающие переданные парамтеры объектов
type Object = map[string]interface{}
type Objects = []Object

// Тип, описывающий параметры обновления сущности
type Set = map[string]interface{}

// Тип, описывающий срез полей группировки
type GroupBy = []string

// Результат парсинга параметров сортировки
type Order struct {
	Priority  int            `json:"priority"`
	By        string         `json:"by"`
	Direction OrderDirection `json:"order"`
}

// Результат парсинга параметров пагенации
type Pagination struct {
	Limit  uint64
	Offset uint64
}

// Операция для применения фильтра
type Operation interface {
	// Получение типа текущей операции
	Type() string

	// Получение значения для текущей операции
	Value() interface{}

	// Получение кода поля для операции
	Field() string

	// Конвертация в SQL
	ToSQL(object *graphql.Object, fieldsMap map[string]string) (string, error)
}

Для операций Where и Having доступна автоматизированная конвертация в SQL. Для этого необходимо использовать:

sql, err = params.Arguments.Where.ToSQL(params.GraphQlObject, nil)

Поля контекста запроса (context.Context)

В контексте передаются следующие поля:

type context struct {
	context        *fasthttp.RequestCtx
	operations     []configurable_logger.LogOperation
}
где:
    context - Контекст запроса FastHTTP
    operations - Корневые операции запроса для каскадного логирования.

Подтипы для GraphQlRequestedFields

Данный тип предназначен для описания запрошенных полей сущности GraphQL

// Интерфейс сущности запрошенного поля
type GraphQlRequestedFieldInterface interface {
	// Получение названия поля
	GetFieldName() string

	// Есть ли у поля дочерние элементы
	HasSubFields() bool

	// Получение дочерних элементов поля
	GetSubFields() []GraphQlRequestedFieldInterface
}

// Срез запрошенных полей
type GraphQlRequestedFields = []GraphQlRequestedFieldInterface

FAQs

Package last updated on 05 Oct 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc