[
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.idea\n.vscode\n\n# Tarantool output files\n*.xlog\n*.snap\n\n# Test data files\n6-databases/10_rabbit/images/*.jpg\n\n\n# Ignore binary files\n*.exe\n\n# Ignore tmp output files\n*.out"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"5-architecture/8_clean_arch\"]\n\tpath = 5-architecture/8_clean_arch\n\turl = https://github.com/bxcodec/go-clean-arch\n[submodule \"5-architecture/9_go_project_layout\"]\n\tpath = 5-architecture/9_go_project_layout\n\turl = https://github.com/golang-standards/project-layout\n"
  },
  {
    "path": "1-basics/1_basics/01_vars_1/01_vars_1.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\t// значение по умолчанию\n\tvar num0 int\n\n\t// значение при инициализации\n\tvar num1 int = 1\n\n\t// пропуск типа\n\tvar num2 = 20\n\tfmt.Println(num0, num1, num2)\n\n\t// короткое объявление переменной\n\tnum := 30\n\t// только для новых переменных\n\t// no new variables on left side of :=\n\t// num := 31\n\n\tnum += 1\n\tfmt.Println(\"+=\", num)\n\n\t// ++num нету\n\tnum++\n\tfmt.Println(\"++\", num)\n\n\t// camelCase - принятый стиль\n\tuserIndex := 10\n\t// under_score - не принято\n\tuser_index := 10\n\tfmt.Println(userIndex, user_index)\n\n\t// объявление нескольких переменных\n\tvar weight, height int = 10, 20\n\n\t// присваивание в существующие переменные\n\tweight, height = 11, 21\n\n\t// короткое присваивание\n\t// хотя-бы одна переменная должна быть новой!\n\tweight, age := 12, 22\n\n\tfmt.Println(weight, height, age)\n}\n"
  },
  {
    "path": "1-basics/1_basics/02_vars_2/02_vars_2.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\t// int - платформозависимый тип, 32/64\n\tvar i int = 10\n\n\t// автоматически выбранный int\n\tvar autoInt = -10\n\n\t// int8, int16, int32, int64\n\tvar bigInt int64 = 1<<32 - 1\n\n\t// платформозависимый тип, 32/64\n\tvar unsignedInt uint = 123\n\n\t// uint8, unit16, uint32, unit64\n\tvar unsignedBigInt uint64 = 1<<64 - 1\n\tunsignedBigInt = 0x01fe\n\tunsignedBigInt = 0b00001010101\n\n\tfmt.Println(i, autoInt, bigInt, unsignedInt, unsignedBigInt)\n\n\t// вывод в других системах счисления\n\tfmt.Printf(\"в 16-ричной: %x\\n\", unsignedBigInt)\n\tfmt.Printf(\"в двоичной: %b\\n\", unsignedBigInt)\n\tfmt.Printf(\"в 8-ричной: %o\\n\", unsignedBigInt)\n\n\t// float32, float64\n\tvar pi float32 = 3.141\n\tvar e = 2.718\n\tgoldenRatio := 1.618\n\n\tfmt.Println(pi, e, goldenRatio)\n\n\t// bool\n\tvar b bool // false по-умолчанию\n\tvar isOk bool = true\n\tvar success = false\n\tcond := true\n\n\tfmt.Println(b, isOk, success, cond)\n\n\t// complex64, complex128\n\tvar c complex128 = -1.1 + 7.12i\n\tc2 := -1.1 + 7.12i\n\n\tfmt.Println(c, c2)\n}\n"
  },
  {
    "path": "1-basics/1_basics/03_const/03_const.go",
    "content": "package main\n\nimport \"fmt\"\n\nconst pi = 3.141\nconst (\n\thello = \"Привет\"\n\te     = 2.718\n)\nconst (\n\tzero = iota\n\t_    // пустая переменная, пропуск iota\n\ttwo\n\tthree // = 3\n)\nconst (\n\t_         = iota             // пропускаем первое значение\n\tKB uint64 = 1 << (10 * iota) // 1 << (10 * 1) = 1024\n\tMB                           // 1 << (10 * 2) = 1048576\n)\nconst (\n\t// нетипизированная константа\n\tyear = 2017\n\t// типизированная константа\n\tyearTyped int = 2017\n)\n\nfunc main() {\n\tvar month int32 = 13\n\tfmt.Println(month + year)\n\n\t// month + yearTyped (mismatched types int32 and int)\n\t// fmt.Println( month + yearTyped )\n}\n"
  },
  {
    "path": "1-basics/1_basics/04_pointers/04_pointers.go",
    "content": "package main\n\nfunc main() {\n\ta := 2\n\tb := &a\n\t*b = 3  // a = 3\n\tc := &a // новый указатель на переменную a\n\n\t// получение указателя на переменнут типа int\n\t// инициализировано значением по-умолчанию\n\td := new(int)\n\t*d = 12\n\t*c = *d // c = 12 -> a = 12\n\t*d = 13 // c и a не изменились\n\n\t// nil указатель\n\tvar n *int\n\t_ = n\n\n\tc = d   // теперь с указывает туда же, куда d\n\t*c = 14 // с = 14 -> d = 14, a = 12\n}\n"
  },
  {
    "path": "1-basics/1_basics/05_array/05_array.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\t// размер массива является частью его типа\n\n\t// инициализация значениями по-умолчанию\n\tvar a1 [3]int // [0,0,0]\n\tfmt.Println(\"a1 short\", a1)\n\tfmt.Printf(\"a1 short %v\\n\", a1)\n\tfmt.Printf(\"a1 full %#v\\n\", a1)\n\n\tconst size = 2\n\tvar a2 [2 * size]bool // [false,false,false,false]\n\tfmt.Println(\"a2\", a2)\n\n\t// определение размера при объявлении\n\ta3 := [...]int{1, 2, 3}\n\tfmt.Println(\"a2\", a3)\n\n\t// проверка при компиляции или при выполнении\n\t// invalid array index 4 (out of bounds for 3-element array)\n\t// a3[idx] = 12\n}\n"
  },
  {
    "path": "1-basics/1_basics/06_slice_1/06_slice_1.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\t// создание\n\tvar buf0 []int             // len=0, cap=0\n\tbuf1 := []int{}            // len=0, cap=0\n\tbuf2 := []int{42}          // len=1, cap=1\n\tbuf3 := make([]int, 0)     // len=0, cap=0\n\tbuf4 := make([]int, 5)     // len=5, cap=5\n\tbuf5 := make([]int, 5, 10) // len=5, cap=10\n\n\tprintln(\"buffers \", buf0, buf1, buf2, buf3, buf4, buf5)\n\n\t// обращение к элементам\n\tsomeInt := buf2[0]\n\n\t// ошибка при выполнении\n\t// panic: runtime error: index out of range\n\t// someOtherInt := buf2[1]\n\n\tfmt.Println(someInt)\n\n\t// добавление элементов\n\tvar buf []int            // len=0, cap=0\n\tbuf = append(buf, 9, 10) // len=2, cap=2\n\tbuf = append(buf, 12)    // len=3, cap=4\n\n\t// добавление друго слайса\n\totherBuf := make([]int, 3)     // [0,0,0]\n\tbuf = append(buf, otherBuf...) // len=6, cap=8\n\n\tfmt.Println(buf, otherBuf)\n\n\t// просмотр информации о слайсе\n\tvar bufLen, bufCap int = len(buf), cap(buf)\n\n\tfmt.Println(bufLen, bufCap)\n}\n"
  },
  {
    "path": "1-basics/1_basics/07_slice_2/07_slice_2.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tbuf := []int{1, 2, 3, 4, 5}\n\tfmt.Println(buf)\n\n\t/*\n\t\t buf:    [1, 2, 3, 4, 5]   ← базовый массив\n\t\t         ↑   ↑   ↑   ↑   ↑\n\t\t         │   │   │   │   │\n\t\tsl2[:2]: │───│   │   │   │ → len=2, cap=5\n\t\tsl1[1:4]:    │───┼───┤   │ → len=3, cap=4\n\t\tsl3[2:]:         │───┼───┼───┤ → len=3, cap=3\n\n\t*/\n\n\t// получение среза, указывающего на ту же память\n\tsl1 := buf[1:4] // [2, 3, 4]    (с 1-го до 4-го, не включая 4-й)\n\tsl2 := buf[:2]  // [1, 2]       (с начала до 2-го, не включая 2-й)\n\tsl3 := buf[2:]  // [3, 4, 5]    (со 2-го до конца)\n\tfmt.Println(sl1, sl2, sl3)\n\n\tfmt.Println()\n\n\tnewBuf := buf[:] // [1, 2, 3, 4, 5]\n\t// buf = [9, 2, 3, 4, 5], т.к. та же память\n\tnewBuf[0] = 9\n\n\t// newBuf теперь указывает на другие данные\n\tnewBuf = append(newBuf, 6)\n\n\t// buf    = [9, 2, 3, 4, 5], не изменился\n\t// newBuf = [1, 2, 3, 4, 5, 6], изменился\n\tnewBuf[0] = 1\n\tfmt.Println(\"buf\", buf)\n\tfmt.Println(\"newBuf\", newBuf)\n\n\tfmt.Println()\n\n\t// копирование одного слайса в другой\n\tvar emptyBuf []int // len=0, cap=0\n\t// неправильно - скопирует меньшее (по len) из 2-х слайсов\n\tcopied := copy(emptyBuf, buf) // copied = 0\n\tfmt.Println(\"Invalid copy \", copied, emptyBuf)\n\n\t// правильно\n\tnewBuf = make([]int, len(buf), len(buf))\n\tcopy(newBuf, buf)\n\tfmt.Println(\"Valid copy \", newBuf)\n\n\t// можно копировать в часть существующего слайса\n\tints := []int{1, 2, 3, 4}\n\tcopy(ints[1:3], []int{5, 6}) // ints = [1, 5, 6, 4]\n\tfmt.Println(\"Part copy \", ints)\n}\n"
  },
  {
    "path": "1-basics/1_basics/08_strings/08_strings.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"unicode/utf8\"\n)\n\nfunc main() {\n\t// пустая строка по-умолчанию\n\tvar str string\n\n\t// со спец символами\n\tvar hello string = \"Привет\\n\\t\"\n\n\t// без спец символов\n\tvar world string = `Мир\\n\\t`\n\n\tfmt.Println(\"str\", str)\n\tfmt.Println(\"hello\", hello)\n\tfmt.Println(\"world\", world)\n\n\t// UTF-8 из коробки\n\tvar helloWorld = \"Привет, Мир!\"\n\thi := \"你好，世界\"\n\n\tfmt.Println(\"helloWorld\", helloWorld)\n\tfmt.Println(\"hi\", hi)\n\n\t// одинарные кавычки для байт (uint8)\n\tvar rawBinary byte = '\\x27'\n\n\t// rune (uint32) для UTF-8 символов\n\tvar someChinese rune = '茶'\n\n\tfmt.Println(rawBinary, someChinese)\n\n\thelloWorld = \"Привет Мир\"\n\t// конкатенация строк\n\tandGoodMorning := helloWorld + \" и доброе утро!\"\n\n\tfmt.Println(helloWorld, andGoodMorning)\n\n\t// строки неизменяемы\n\t// cannot assign to helloWorld[0]\n\t// helloWorld[0] = 72\n\n\t// получение длины строки\n\tbyteLen := len(helloWorld)                    // 19 байт\n\tsymbols := utf8.RuneCountInString(helloWorld) // 10 рун\n\n\tfmt.Println(byteLen, symbols)\n\n\t// получение подстроки, в байтах, не символах!\n\thello = helloWorld[:12] // Привет, 0-11 байты\n\tH := helloWorld[0]      // byte, 72, не \"П\"\n\tfmt.Println(H)\n\n\t// конвертация в слайс байт и обратно\n\tbyteString := []byte(helloWorld)\n\thelloWorld = string(byteString)\n\n\tfmt.Println(byteString, helloWorld)\n}\n"
  },
  {
    "path": "1-basics/1_basics/09_map/09_map.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\t// инициализация при создании\n\tvar user map[string]string = map[string]string{\n\t\t\"name\":     \"Anton\",\n\t\t\"lastName\": \"Sulaev\",\n\t}\n\n\t// сразу с нужной ёмкостью\n\tprofile := make(map[string]string, 10)\n\n\t// nil мапа\n\t//var profileEmpty map[string]string\n\t//fmt.Println(\"profileEmpty get \", profileEmpty[\"key\"])\n\t//profileEmpty[\"key\"] = \"1\"  // panic\n\t//fmt.Println(\"profileEmpty set \", profileEmpty[\"key\"])\n\n\t// количество элементов\n\tmapLength := len(user)\n\n\tfmt.Printf(\"%d %+v\\n\", mapLength, profile)\n\n\t/*\n\n\t\t\t1. Ключ всегда comparable\n\t\t\t= !=\n\n\t\t\t2.\n\t\t\tsha1, crc32, crc64\n\n\t\t\tFh = func (toHash Comparable, d int)  int\n\n\t\t\tVasya -> Fh(Vasya) -> 10\n\t\t\tKolya ->  Fh(Kolya) -> 10\n\n\t\t\t-----------&----- 15 адресов\n\t\t\t\t\t   V\n\t\t\t\t\t   K\n\t\t\tO(1)\n\n\t\tМожет быть не конкурентно\n\t*/\n\n\t// если ключа нет - вернёт значение по умолчанию для типа\n\tmName := user[\"middleName\"]\n\tfmt.Println(\"mName:\", mName)\n\n\t// проверка на существование ключа\n\tmName, mNameExist := user[\"middleName\"]\n\tfmt.Println(\"mName:\", mName, \"mNameExist:\", mNameExist)\n\n\t// пустая переменная - только проверяем что ключ есть\n\t_, mNameExist2 := user[\"middleName\"]\n\tfmt.Println(\"mNameExist2\", mNameExist2)\n\n\t// удаление ключа\n\tdelete(user, \"lastName\")\n\tfmt.Printf(\"%#v\\n\", user)\n}\n"
  },
  {
    "path": "1-basics/1_basics/10_control/10_control.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\t// простое условие\n\tboolVal := true\n\tif boolVal {\n\t\tfmt.Println(\"boolVal is true\")\n\t}\n\n\tmapVal := map[string]string{\"name\": \"vasya\"}\n\t// условие с блоком инициализации\n\tif keyValue, keyExist := mapVal[\"name\"]; keyExist {\n\t\tfmt.Println(\"name =\", keyValue)\n\t}\n\t// получаем только признак сущестования ключа\n\tif _, keyExist := mapVal[\"name\"]; keyExist {\n\t\tfmt.Println(\"key 'name' exist\")\n\t}\n\n\tcond := 1\n\t// множественные if else\n\tif cond == 1 {\n\t\tfmt.Println(\"cond is 1\")\n\t} else if cond == 2 {\n\t\tfmt.Println(\"cond is 2\")\n\t}\n\n\t// switch по 1 переменной\n\tstrVal := \"name\"\n\tswitch strVal {\n\tcase \"name\":\n\t\tfallthrough\n\tcase \"test\", \"lastName\":\n\t\t// some work\n\tdefault:\n\t\t// some work\n\t}\n\n\t// switch как замена многим ifelse\n\tvar val1, val2 = 2, 2\n\tswitch {\n\tcase val1 > 1 || val2 < 11:\n\t\tfmt.Println(\"first block\")\n\tcase val2 > 10:\n\t\tfmt.Println(\"second block\")\n\t}\n\n\t// выход из цикла, находясь внутри switch\nLoop:\n\tfor key, val := range mapVal {\n\t\tprintln(\"switch in loop\", key, val)\n\t\tswitch {\n\t\tcase key == \"lastName\":\n\t\t\tbreak\n\t\t\tprintln(\"dont pront this\")\n\t\tcase key == \"firstName\" && val == \"Vasily\":\n\t\t\tprintln(\"switch - break loop here\")\n\t\t\tbreak Loop\n\t\t}\n\t} // конец for\n\n}\n"
  },
  {
    "path": "1-basics/1_basics/11_loop/11_loop.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\t// цикл без условия, while(true) OR for(;;;)\n\tfor {\n\t\tfmt.Println(\"loop iteration\")\n\t\tbreak\n\t}\n\n\t// цикл без условия, while(isRun)\n\tisRun := true\n\tfor isRun {\n\t\tfmt.Println(\"loop iteration with condition\")\n\t\tisRun = false\n\t}\n\n\t// цикл с условие и блоком инициализации\n\tfor i := 0; i < 2; i++ {\n\t\tfmt.Println(\"loop iteration\", i)\n\t\tif i == 1 {\n\t\t\tcontinue\n\t\t}\n\t}\n\n\t// операции по slice\n\tsl := []int{1, 2, 3}\n\tidx := 0\n\n\tfor idx < len(sl) {\n\t\tfmt.Println(\"while-stype loop, idx:\", idx, \"value:\", sl[idx])\n\t\tidx++\n\t}\n\n\tfor i := 0; i < len(sl); i++ {\n\t\tfmt.Println(\"c-style loop\", i, sl[i])\n\t}\n\tfor idx := range sl {\n\t\tfmt.Println(\"range slice by index\", sl[idx])\n\t}\n\tfor idx, val := range sl {\n\t\tval = idx + 1     // не поменяем\n\t\tsl[idx] = idx + 2 // поменяем\n\t\tfmt.Println(\"range slice by idx-value\", idx, val)\n\t}\n\n\tfmt.Printf(\"slice by idx-value %v\\n\", sl)\n\n\t// операции по map\n\tprofile := map[int]string{1: \"Vasily\", 2: \"Romanov\"}\n\n\tfor key := range profile {\n\t\tfmt.Println(\"range map by key\", key)\n\t}\n\n\tfor key, val := range profile {\n\t\tfmt.Println(\"range map by key-val\", key, val)\n\t}\n\n\tfor _, val := range profile {\n\t\tfmt.Println(\"range map by val\", val)\n\t}\n\n\t//added in go 1.22\n\tfor i := range 10 {\n\t\tprintln(i)\n\t}\n\n\tstr := \"Привет, Мир!\"\n\tfor pos, char := range str {\n\t\tfmt.Printf(\"%#U at pos %d\\n\", char, pos)\n\t}\n\n}\n"
  },
  {
    "path": "1-basics/1_basics/12_types/12_types.go",
    "content": "package main \n\ntype UserID int\n\nfunc main() {\n\tidx := 1\n\tvar uid UserID = 42\n\n\t// даже если базовый тип одинаковый, разные типы несовместимы\n\t// cannot use uid (type UserID) as type int64 in assignment\n\t// myID := idx\n\n\tmyID := UserID(idx)\n\t\n\tprintln(uid, myID)\n}"
  },
  {
    "path": "1-basics/1_basics/13_generic/1_generic/main.go",
    "content": "package main\n\n// Зачем нужны?\n// ДУБЛИРОВАНИЕ КОДА!\nfunc equalInt(a, b int) bool {\n\treturn a == b\n}\n\nfunc equalFloat(a, b float64) bool {\n\treturn a == b\n}\n\n// одна функция для многих типов\n// [T int | float64] - объявление типа-параметра (Type parameter)\nfunc equal[T int | float64](a, b T) bool {\n\treturn a == b\n}\n\n// Алиасы\ntype MyType int\n\nfunc equalWithAlias[T ~int | ~float64](a, b T) bool {\n\treturn a == b\n}\n\nfunc KeyExists[T any](m map[string]T, key string) bool {\n\t_, exists := m[key]\n\treturn exists\n}\n\nfunc main() {\n\tprintln(equalInt(1, 2))\n\tprintln(equalFloat(1.0, 2.0))\n\n\t// Компилятор сам подставит нужный тип\n\tprintln(equal(1, 2))     // T - int\n\tprintln(equal(1.0, 2.0)) // T - float64\n\n\t// Cannot use MyType as the type interface{ int | float64 }\n\t// Type does not implement constraint interface{ int | float64 } because type is not included in type set (int, float64)\n\t//\n\t//\n\t//println(equal(MyType(1),MyType(2)))\n\tprintln(equalWithAlias(MyType(1), MyType(2)))\n\n\tm1 := make(map[string]int)\n\tm2 := make(map[string]bool)\n\n\tprintln(KeyExists(m2, \"test\"))\n\tprintln(KeyExists(m1, \"test\"))\n\n}\n"
  },
  {
    "path": "1-basics/1_basics/13_generic/2_methods/methods.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\n// 1. Базовая дженерик-структура с методами\ntype Box[T any] struct {\n\tValue T\n}\n\n// Метод получает значение. T уже объявлен в структуре.\nfunc (b Box[T]) GetValue() T {\n\treturn b.Value\n}\n\n// Метод устанавливает значение\nfunc (b *Box[T]) SetValue(v T) {\n\tb.Value = v\n}\n\n// 2. Структура с ограничением типов\ntype Number interface {\n\t~int | ~float64\n}\n\ntype Calculator[T Number] struct {\n\tValue T\n}\n\n// Методы используют то же ограничение T Number\nfunc (c Calculator[T]) Add(a T) T {\n\treturn c.Value + a\n}\n\nfunc (c Calculator[T]) Multiply(a T) T {\n\treturn c.Value * a\n}\n\n// 3. Методы с преобразованием данных\ntype Container[T any] struct {\n\tData T\n}\n\nfunc (c Container[T]) ToJSON() ([]byte, error) {\n\treturn json.Marshal(c.Data)\n}\n\nfunc (c *Container[T]) FromJSON(data []byte) error {\n\treturn json.Unmarshal(data, &c.Data)\n}\n\n// 4. Функция с дополнительным generic-параметром (методы не могут иметь свои параметры типов)\nfunc CompareWith[T any, U any](b Box[T], other U, compareFunc func(T, U) bool) bool {\n\treturn compareFunc(b.Value, other)\n}\n\n// 5. Практический пример: кэш с разными типами значений\ntype Cache[K comparable, V any] struct {\n\tdata map[K]V\n}\n\nfunc NewCache[K comparable, V any]() *Cache[K, V] {\n\treturn &Cache[K, V]{\n\t\tdata: make(map[K]V),\n\t}\n}\n\nfunc (c *Cache[K, V]) Set(key K, value V) {\n\tc.data[key] = value\n}\n\nfunc (c *Cache[K, V]) Get(key K) (V, bool) {\n\tval, exists := c.data[key]\n\treturn val, exists\n}\n\nfunc (c *Cache[K, V]) Delete(key K) {\n\tdelete(c.data, key)\n}\n\n// 6. Пример с интерфейсным ограничением\ntype Stringer interface {\n\tString() string\n}\n\ntype Printer[T Stringer] struct {\n\tItem T\n}\n\nfunc (p Printer[T]) Print() string {\n\treturn p.Item.String()\n}\n\n// Реализуем интерфейс Stringer для кастомного типа\ntype MyInt int\n\nfunc (m MyInt) String() string {\n\treturn fmt.Sprintf(\"MyInt: %d\", m)\n}\n\nfunc main() {\n\t// 1. Работа с Box\n\tintBox := Box[int]{Value: 42}\n\tstrBox := Box[string]{Value: \"hello\"}\n\n\tfmt.Printf(\"intBox value: %d\\n\", intBox.GetValue())\n\tfmt.Printf(\"strBox value: %s\\n\", strBox.GetValue())\n\n\tintBox.SetValue(100)\n\tfmt.Printf(\"New intBox value: %d\\n\", intBox.GetValue())\n\n\t// 2. Работа с Calculator\n\tintCalc := Calculator[int]{Value: 10}\n\tfloatCalc := Calculator[float64]{Value: 3.14}\n\n\tfmt.Printf(\"10 * 2 = %d\\n\", intCalc.Multiply(2))\n\tfmt.Printf(\"3.14 + 1.5 = %.2f\\n\", floatCalc.Add(1.5))\n\n\t// 3. Работа с Cache\n\tstringCache := NewCache[string, string]()\n\tstringCache.Set(\"name\", \"Alice\")\n\tstringCache.Set(\"city\", \"Moscow\")\n\n\tif name, exists := stringCache.Get(\"name\"); exists {\n\t\tfmt.Printf(\"Name from cache: %s\\n\", name)\n\t}\n\n\tintCache := NewCache[string, int]()\n\tintCache.Set(\"age\", 25)\n\tintCache.Set(\"score\", 100)\n\n\tif age, exists := intCache.Get(\"age\"); exists {\n\t\tfmt.Printf(\"Age from cache: %d\\n\", age)\n\t}\n\n\t// 4. Работа с методом, имеющим дополнительный generic-параметр\n\tbox := Box[int]{Value: 42}\n\tresult := CompareWith(box, \"42\", func(a int, b string) bool {\n\t\treturn fmt.Sprint(a) == b\n\t})\n\tfmt.Printf(\"Compare 42 with '42': %t\\n\", result)\n\n\t// 5. Работа с интерфейсным ограничением\n\tmyInt := MyInt(42)\n\tprinter := Printer[MyInt]{Item: myInt}\n\tfmt.Println(printer.Print())\n}\n"
  },
  {
    "path": "1-basics/2_functions/1_functions/1_functions.go",
    "content": "package main\n\nimport \"fmt\"\n\n// обычное объявление\nfunc singleIn(in int) int {\n\treturn in\n}\n\n// много параметров\nfunc multIn(a, b int, c int) int {\n\treturn a + b + c\n}\n\n// именованный результат\nfunc namedReturn() (out int) {\n\tout = 2\n\treturn\n}\n\n// несколько результатов\nfunc multipleReturn(in int) (int, error) {\n\tif in > 2 {\n\t\treturn 0, fmt.Errorf(\"some error happend\")\n\t}\n\treturn in, nil\n}\n\n// несколько именованных результатов\nfunc multipleNamedReturn(ok bool) (rez int, err error) {\n\trez = 1\n\tif ok {\n\t\terr = fmt.Errorf(\"some error happend\")\n\t\t// аналогично return rez, err\n\t\treturn 3, fmt.Errorf(\"some error happend\")\n\t}\n\trez = 2\n\treturn\n}\n\n// не фиксированное количество параметров\nfunc sum(in ...int) (result int) {\n\tfmt.Printf(\"in := %#v \\n\", in)\n\tfor _, val := range in {\n\t\tresult += val\n\t}\n\treturn\n}\n\nfunc main() {\n\t// fmt.Println(multipleNamedReturn(false))\n\t// return\n\n\tnums := []int{1, 2, 3, 4}\n\tfmt.Println(nums, sum(nums...))\n\treturn\n}\n"
  },
  {
    "path": "1-basics/2_functions/2_firstclass/2_firstclass.go",
    "content": "package main\n\nimport \"fmt\"\n\n// обычная функция\nfunc doNothing() {\n\tfmt.Println(\"i'm regular function\")\n}\n\nfunc main() {\n\t// анонимная функция\n\tfunc(in string) {\n\t\tfmt.Println(\"anon func out:\", in)\n\t}(\"nobody\")\n\n\t// присванивание анонимной функции в переменную\n\tprinter := func(in string) {\n\t\tfmt.Println(\"printer outs:\", in)\n\t}\n\tprinter(\"as variable\")\n\n\t// определяем тип функции\n\ttype strFuncType func(string)\n\n\t// функция принимает коллбек\n\tworker := func(callback strFuncType) {\n\t\tcallback(\"as callback\")\n\t}\n\tworker(printer)\n\n\t// функиция возвращает замыкание\n\tprefixer := func(prefix string) strFuncType {\n\t\treturn func(in string) {\n\t\t\tfmt.Printf(\"[%s] %s\\n\", prefix, in)\n\t\t}\n\t}\n\tsuccessLogger := prefixer(\"SUCCESS\")\n\tsuccessLogger(\"expected behaviour\")\n}\n"
  },
  {
    "path": "1-basics/2_functions/3_defer/3_defer.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc getSomeVars() string {\n\tfmt.Println(\"getSomeVars execution\")\n\treturn \"getSomeVars result\"\n}\n\nfunc main() {\n\tdefer fmt.Println(\"After work\")\n\tdefer func() {\n\t\tfmt.Println(getSomeVars())\n\t}()\n\tfmt.Println(\"Some userful work\")\n}\n"
  },
  {
    "path": "1-basics/2_functions/4_recover/4_recover.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc deferTest() {\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\tfmt.Println(\"panic happend FIRST:\", err)\n\t\t}\n\t}()\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\tfmt.Println(\"panic happend SECOND:\", err)\n\t\t\t// panic(\"second panic\")\n\t\t}\n\t}()\n\tfmt.Println(\"Some userful work\")\n\tpanic(\"something bad happend\")\n\treturn\n}\n\nfunc main() {\n\tdeferTest()\n\treturn\n}\n"
  },
  {
    "path": "1-basics/3_structs/1_structs/1_structs.go",
    "content": "package main\n\nimport \"fmt\"\n\ntype Person struct {\n\tId      int\n\tName    string\n\tAddress string\n}\n\ntype Account struct {\n\tId int\n\t// Name    string\n\tCleaner func(string) string\n\tOwner   Person\n\tPerson\n}\n\nfunc main() {\n\t// полное объявление структуры\n\tvar acc Account = Account{\n\t\tId: 1,\n\t\t// Name: \"vasya\",\n\t\tPerson: Person{\n\t\t\tName:    \"Василий\",\n\t\t\tAddress: \"Москва\",\n\t\t},\n\t}\n\tfmt.Printf(\"%#v\\n\", acc)\n\n\t// короткое объявление структуры\n\tacc.Owner = Person{2, \"Romanov Vasily\", \"Moscow\"}\n\n\tfmt.Printf(\"%#v\\n\", acc)\n\n\tfmt.Println(acc.Name)\n\tfmt.Println(acc.Person.Name)\n}\n"
  },
  {
    "path": "1-basics/3_structs/2_methods/2_methods.go",
    "content": "package main\n\nimport \"fmt\"\n\ntype Person struct {\n\tId   int\n\tName string\n}\n\n// не изменит оригинальной структуры, для который вызван\nfunc (p Person) UpdateName(name string) {\n\tp.Name = name\n}\n\n// изменяет оригинальную структуру\nfunc (p *Person) SetName(name string) {\n\tp.Name = name\n}\n\ntype Account struct {\n\tId   int\n\tName string\n\tPerson\n}\n\nfunc (p *Account) SetName(name string) {\n\tp.Name = name\n}\n\ntype MySlice []int\n\nfunc (sl *MySlice) Add(val int) {\n\t*sl = append(*sl, val)\n}\n\nfunc (sl *MySlice) Count() int {\n\treturn len(*sl)\n}\n\nfunc main() {\n\t// pers := &Person{1, \"Vasily\"}\n\tpers := new(Person)\n\tpers.SetName(\"Vasily Romanov\")\n\t// (&pers).SetName(\"Vasily Romanov\")\n\t// fmt.Printf(\"updated person: %#v\\n\", pers)\n\n\tvar acc Account = Account{\n\t\tId:   1,\n\t\tName: \"vasya\",\n\t\tPerson: Person{\n\t\t\tId:   2,\n\t\t\tName: \"Vasily Romanov\",\n\t\t},\n\t}\n\n\tacc.SetName(\"romanov.vasily\")\n\tacc.Person.SetName(\"Test\")\n\n\t// fmt.Printf(\"%#v \\n\", acc)\n\n\tsl := MySlice([]int{1, 2})\n\tsl.Add(5)\n\tfmt.Println(sl.Count(), sl)\n}\n"
  },
  {
    "path": "1-basics/4_interfaces/1.2_basic_sort/1_sort.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n)\n\ntype Student struct {\n\tAge  int\n\tName string\n}\n\ntype Students []Student\n\nfunc (sts Students) Len() int           { return len(sts) }\nfunc (sts Students) Swap(a, b int)      { sts[a], sts[b] = sts[b], sts[a] }\nfunc (sts Students) Less(a, b int) bool { return sts[a].Age < sts[b].Age }\n\nfunc main() {\n\tstudents := Students{\n\t\t{Age: 18, Name: \"Harry\"},\n\t\t{Age: 76, Name: \"Benjamin\"},\n\t\t{Age: 20, Name: \"Bob\"},\n\t\t{Age: 19, Name: \"Alice\"},\n\t}\n\n\tsort.Sort(students)\n\n\tfor _, s := range students {\n\t\tfmt.Printf(\"%d %s\\n\", s.Age, s.Name)\n\t}\n}\n"
  },
  {
    "path": "1-basics/4_interfaces/1_basic/1_basic.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\ntype Payer interface {\n\tPay(int) error\n}\n\ntype Wallet struct {\n\tCash int\n}\n\nfunc (w *Wallet) Pay(amount int) error {\n\tif w.Cash < amount {\n\t\treturn fmt.Errorf(\"Не хватает денег в кошельке\")\n\t}\n\tw.Cash -= amount\n\treturn nil\n}\n\nfunc Buy(p Payer) {\n\terr := p.Pay(10)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Спасибо за покупку через %T\\n\\n\", p)\n}\n\nfunc main() {\n\tmyWallet := &Wallet{Cash: 100}\n\tBuy(myWallet)\n}\n"
  },
  {
    "path": "1-basics/4_interfaces/2_many/2_many.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\n// --------------\n\ntype Wallet struct {\n\tCash int\n}\n\nfunc (w *Wallet) Pay(amount int) error {\n\tif w.Cash < amount {\n\t\treturn fmt.Errorf(\"Не хватает денег в кошельке\")\n\t}\n\tw.Cash -= amount\n\treturn nil\n}\n\n// --------------\n\ntype Card struct {\n\tBalance    int\n\tValidUntil string\n\tCardholder string\n\tCVV        string\n\tNumber     string\n}\n\nfunc (c *Card) Pay(amount int) error {\n\tif c.Balance < amount {\n\t\treturn fmt.Errorf(\"Не хватает денег на карте\")\n\t}\n\tc.Balance -= amount\n\treturn nil\n}\n\n// --------------\n\ntype ApplePay struct {\n\tMoney   int\n\tAppleID string\n}\n\nfunc (a *ApplePay) Pay(amount int) error {\n\tif a.Money < amount {\n\t\treturn fmt.Errorf(\"Не хватает денег на аккаунте\")\n\t}\n\ta.Money -= amount\n\treturn nil\n}\n\n// --------------\n\ntype Payer interface {\n\tPay(int) error\n}\n\nfunc Buy(p Payer) {\n\terr := p.Pay(10)\n\tif err != nil {\n\t\tfmt.Printf(\"Ошибка при оплате %T: %v\\n\\n\", p, err)\n\t\treturn\n\t}\n\tfmt.Printf(\"Спасибо за покупку через %T\\n\\n\", p)\n}\n\n// --------------\n\nfunc main() {\n\n\tmyWallet := &Wallet{Cash: 100}\n\tBuy(myWallet)\n\n\tvar myMoney Payer\n\tmyMoney = &Card{Balance: 100, Cardholder: \"vasya\"}\n\tBuy(myMoney)\n\n\tmyMoney = &ApplePay{Money: 9}\n\tBuy(myMoney)\n}\n"
  },
  {
    "path": "1-basics/4_interfaces/3_embed/3_embed.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\ntype Phone struct {\n\tMoney   int\n\tAppleID string\n}\n\nfunc (p *Phone) Pay(amount int) error {\n\tif p.Money < amount {\n\t\treturn fmt.Errorf(\"Not enough money on account\")\n\t}\n\tp.Money -= amount\n\treturn nil\n}\n\nfunc (p *Phone) Ring(number string) error {\n\tif number == \"\" {\n\t\treturn fmt.Errorf(\"PLease, enter phone\")\n\t}\n\treturn nil\n}\n\n// --------------\n\ntype Payer interface {\n\tPay(int) error\n}\n\ntype Ringer interface {\n\tRing(string) error\n}\n\ntype NFCPhone interface {\n\tPayer\n\tRinger\n}\n\n// --------------\n\nfunc PayForMetwiWithPhone(phone NFCPhone) {\n\terr := phone.Pay(1)\n\tif err != nil {\n\t\tfmt.Printf(\"Ошибка при оплате %v\\n\\n\", err)\n\t\treturn\n\t}\n\tfmt.Printf(\"Турникет открыт через %T\\n\\n\", phone)\n}\n\n// --------------\n\nfunc main() {\n\tmyPhone := &Phone{Money: 9}\n\tPayForMetwiWithPhone(myPhone)\n}\n"
  },
  {
    "path": "1-basics/4_interfaces/4_cast/4_cast.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\n// --------------\n\ntype Wallet struct {\n\tCash int\n}\n\nfunc (w *Wallet) Pay(amount int) error {\n\tif w.Cash < amount {\n\t\treturn fmt.Errorf(\"Not enough cash\")\n\t}\n\tw.Cash -= amount\n\treturn nil\n}\n\n// --------------\n\ntype Card struct {\n\tBalance    int\n\tValidUntil string\n\tCardholder string\n\tCVV        string\n\tNumber     string\n}\n\nfunc (c *Card) Pay(amount int) error {\n\tif c.Balance < amount {\n\t\treturn fmt.Errorf(\"Not enough money on balance\")\n\t}\n\tc.Balance -= amount\n\treturn nil\n}\n\n// --------------\n\ntype ApplePay struct {\n\tMoney   int\n\tAppleID string\n}\n\nfunc (a *ApplePay) Pay(amount int) error {\n\tif a.Money < amount {\n\t\treturn fmt.Errorf(\"Not enough money on account\")\n\t}\n\ta.Money -= amount\n\treturn nil\n}\n\n// --------------\n\ntype Payer interface {\n\tPay(int) error\n}\n\n// --------------\n\nfunc Buy(p Payer) {\n\tswitch p.(type) {\n\tcase *Wallet:\n\t\tfmt.Println(\"Оплата наличными?\")\n\tcase *Card:\n\t\tplasticCard, ok := p.(*Card)\n\t\tif !ok {\n\t\t\tfmt.Println(\"Не удалось преобразовать к типу *Card\")\n\t\t}\n\t\tfmt.Println(\"Вставляйте карту,\", plasticCard.Cardholder)\n\tdefault:\n\t\tfmt.Println(\"Что-то новое!\")\n\t}\n\n\terr := p.Pay(10)\n\tif err != nil {\n\t\tfmt.Printf(\"Ошибка при оплате %T: %v\\n\\n\", p, err)\n\t\treturn\n\t}\n\tfmt.Printf(\"Спасибо за покупку через %T\\n\\n\", p)\n}\n\n// --------------\n\nfunc main() {\n\n\tmyWallet := &Wallet{Cash: 100}\n\tBuy(myWallet)\n\n\tvar myMoney Payer\n\tmyMoney = &Card{Balance: 100, Cardholder: \"vasya\"}\n\tBuy(myMoney)\n\n\tmyMoney = &ApplePay{Money: 9}\n\tBuy(myMoney)\n}\n"
  },
  {
    "path": "1-basics/4_interfaces/5_empty_1/5_empty_1.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n)\n\ntype Wallet struct {\n\tCash int\n}\n\nfunc (w *Wallet) Pay(amount int) error {\n\tif w.Cash < amount {\n\t\treturn fmt.Errorf(\"Not enough cash\")\n\t}\n\tw.Cash -= amount\n\treturn nil\n}\n\nfunc (w *Wallet) String() string {\n\treturn \"Кошелёк в котором \" + strconv.Itoa(w.Cash) + \" денег\"\n}\n\n// -----\n\nfunc main() {\n\tmyWallet := &Wallet{Cash: 100}\n\tfmt.Printf(\"Raw payment : %#v\\n\", myWallet)\n\tfmt.Printf(\"Способ оплаты: %s\\n\", myWallet)\n}\n"
  },
  {
    "path": "1-basics/4_interfaces/6_empty_2/6_empty_2.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n)\n\n// --------------\n\ntype Wallet struct {\n\tCash int\n}\n\nfunc (w *Wallet) Pay(amount int) error {\n\tif w.Cash < amount {\n\t\treturn fmt.Errorf(\"Not enough cash\")\n\t}\n\tw.Cash -= amount\n\treturn nil\n}\n\nfunc (w *Wallet) String() string {\n\treturn \"Кошелёк в котором \" + strconv.Itoa(w.Cash) + \" денег\"\n}\n\n// --------------\n\ntype Payer interface {\n\tPay(int) error\n}\n\n// --------------\n\nfunc Buy(in interface{}) {\n\tvar p Payer\n\tvar ok bool\n\tif p, ok = in.(Payer); !ok {\n\t\tfmt.Printf(\"%T не не является платежным средством\\n\\n\", in)\n\t\treturn\n\t}\n\n\terr := p.Pay(10)\n\tif err != nil {\n\t\tfmt.Printf(\"Ошибка при оплате %T: %v\\n\\n\", p, err)\n\t\treturn\n\t}\n\tfmt.Printf(\"Спасибо за покупку через %T\\n\\n\", p)\n\n}\n\n// --------------\n\nfunc main() {\n\tmyWallet := &Wallet{Cash: 100}\n\tBuy(myWallet)\n\tBuy([]int{1, 2, 3})\n\tBuy(3.14)\n}\n"
  },
  {
    "path": "1-basics/5_visibility/dir.txt",
    "content": "C:\\Users\\User\\go\n├───bin\n├───pkg\n└───src\n    ├───coursera\n    │   ├───visibility\n    │   │   │───person\n    │   │   │   │───person.go\n    │   │   │   └───func.go\n    │   │   └───main.go\n    └───github.com\n        └───rvasily\n            └───examplerepo"
  },
  {
    "path": "1-basics/5_visibility/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\n\tprsonModule \"github.com/go-park-mail-ru/lectures/1-basics/5_visibility/person\"\n)\n\nfunc init() {\n\tfmt.Println(\"I am init in main\")\n}\n\nfunc main() {\n\tperson := 1\n\tfmt.Println(\"I am main\", person, prsonModule.Person{})\n}\n"
  },
  {
    "path": "1-basics/5_visibility/person/func.go",
    "content": "package person\n\nimport (\n\t\"fmt\"\n)\n\nfunc NewPerson(id int, name, secret string) *Person {\n\treturn &Person{\n\t\tID:     1,\n\t\tName:   \"rvasily\",\n\t\tsecret: \"secret\",\n\t}\n}\n\nfunc GetSecret(p *Person) string {\n\treturn p.secret\n}\n\nfunc printSecret(p *Person) {\n\tfmt.Println(p.secret)\n}\n"
  },
  {
    "path": "1-basics/5_visibility/person/person.go",
    "content": "package person\n\nimport \"fmt\"\n\nvar (\n\tPublic  = 1\n\tprivate = 1\n)\n\nfunc init() {\n\tfmt.Println(\"I am init 1\")\n}\n\nfunc init() {\n\tfmt.Println(\"I am init 2\")\n}\n\ntype Person struct {\n\tID     int\n\tName   string\n\tsecret string\n}\n\nfunc (p Person) UpdateSecret(secret string) {\n\tfmt.Println(private)\n\tp.secret = secret\n}\n"
  },
  {
    "path": "1-basics/6_uniq/basic/data.txt",
    "content": "1\n2\n3\n3\n3\n3\n4\n5"
  },
  {
    "path": "1-basics/6_uniq/basic/data_bad.txt",
    "content": "1\n1\n2\n1"
  },
  {
    "path": "1-basics/6_uniq/basic/data_map.txt",
    "content": "1\n3\n2\n1\n2"
  },
  {
    "path": "1-basics/6_uniq/basic/main.go",
    "content": "package main\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"os\"\n)\n\nfunc main() {\n\tin := bufio.NewScanner(os.Stdin)\n\tvar prev string\n\tfor in.Scan() {\n\t\ttxt := in.Text()\n\t\tif txt == prev {\n\t\t\tcontinue\n\t\t}\n\t\tif txt < prev {\n\t\t\tpanic(\"file not sorted\")\n\t\t}\n\t\tprev = txt\n\t\tfmt.Println(txt)\n\t}\n}\n"
  },
  {
    "path": "1-basics/6_uniq/with_tests/data.txt",
    "content": "1\n2\n3\n3\n3\n3\n4\n5"
  },
  {
    "path": "1-basics/6_uniq/with_tests/data_bad.txt",
    "content": "1\n1\n2\n1"
  },
  {
    "path": "1-basics/6_uniq/with_tests/data_map.txt",
    "content": "1\n3\n2\n1\n2"
  },
  {
    "path": "1-basics/6_uniq/with_tests/main.go",
    "content": "package main\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n)\n\nfunc uniq(input io.Reader, output io.Writer) error {\n\tin := bufio.NewScanner(input)\n\tvar prev string\n\tfor in.Scan() {\n\t\ttxt := in.Text()\n\t\tif txt == prev {\n\t\t\tcontinue\n\t\t}\n\t\tif txt < prev {\n\t\t\treturn fmt.Errorf(\"file not sorted\")\n\t\t}\n\t\tprev = txt\n\t\tfmt.Fprintln(output, txt)\n\t}\n\treturn nil\n}\n\nfunc main() {\n\terr := uniq(os.Stdin, os.Stdout)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\tos.Exit(1)\n\t}\n}\n"
  },
  {
    "path": "1-basics/6_uniq/with_tests/main_test.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"testing\"\n)\n\nvar testOkInput = `1\n2\n3\n3\n4\n5`\n\nvar testOkResult = `1\n2\n3\n4\n5\n`\n\nvar testFailInput = `1\n2\n1`\n\nfunc TestOK(t *testing.T) {\n\tin := bytes.NewBufferString(testOkInput)\n\tout := bytes.NewBuffer(nil)\n\terr := uniq(in, out)\n\tif err != nil {\n\t\tt.Errorf(\"Test OK failed: %s\", err)\n\t}\n\tresult := out.String()\n\tif result != testOkResult {\n\t\tt.Errorf(\"Test OK failed, result not match\")\n\t}\n}\n\nfunc TestFail(t *testing.T) {\n\tin := bytes.NewBufferString(testFailInput)\n\tout := bytes.NewBuffer(nil)\n\terr := uniq(in, out)\n\tif err == nil {\n\t\tt.Errorf(\"Test FAIL failed: expected error\")\n\t}\n}\n"
  },
  {
    "path": "1-basics/homework/readme.md",
    "content": "# Домашнее задание 1\n\n## Дисклеймер\n\nЭто задание состоит из 2х частей, которые нужно сдавать вместе.\nОтдельно первая часть, как и отдельно вторая часть, не оценивается\nкак половина задания.\n\nЗадачи включают в себя как написание функциональности, так и её\nтестирование.\n\nВсе домашние задания должны выполняться в приватных репозиториях.\n\n## Часть 1. Uniq\n\nНужно реализовать утилиту, с помощью которой можно вывести или отфильтровать\nповторяющиеся строки в файле (аналог UNIX утилиты `uniq`). Причём повторяющиеся\nвходные строки не должны распозноваться, если они не следуют строго друг за другом.\nСама утилита имеет набор параметров, которые необходимо поддержать.\n\n### Параметры\n\n`-с` - подсчитать количество встречаний строки во входных данных.\nВывести это число перед строкой отделив пробелом.\n\n`-d` - вывести только те строки, которые повторились во входных данных.\n\n`-u` - вывести только те строки, которые не повторились во входных данных.\n\n`-f num_fields` - не учитывать первые `num_fields` полей в строке.\nПолем в строке является непустой набор символов отделённый пробелом.\n\n`-s num_chars` - не учитывать первые `num_chars` символов в строке.\nПри использовании вместе с параметром `-f` учитываются первые символы\nпосле `num_fields` полей (не учитывая пробел-разделитель после\nпоследнего поля).\n\n`-i` - не учитывать регистр букв.\n\n### Использование\n\n`uniq [-c | -d | -u] [-i] [-f num] [-s chars] [input_file [output_file]]`\n\n1. Все параметры опциональны. Поведения утилиты без параметров --\nпростой вывод уникальных строк из входных данных.\n\n2. Параметры c, d, u взаимозаменяемы. Необходимо учитывать,\nчто параллельно эти параметры не имеют никакого смысла. При\nпередаче одного вместе с другим нужно отобразить пользователю\nправильное использование утилиты\n\n3. Если не передан input_file, то входным потоком считать stdin\n\n4. Если не передан output_file, то выходным потоком считать stdout\n\n### Пример работы\n\n<details>\n    <summary>Без параметров</summary>\n\n```bash\n$cat input.txt\nI love music.\nI love music.\nI love music.\n\nI love music of Kartik.\nI love music of Kartik.\nThanks.\nI love music of Kartik.\nI love music of Kartik.\n$cat input.txt | go run uniq.go\nI love music.\n\nI love music of Kartik.\nThanks.\nI love music of Kartik.\n```\n\n</details>\n\n<details>\n    <summary>С параметром input_file</summary>\n\n```bash\n$cat input.txt\nI love music.\nI love music.\nI love music.\n\nI love music of Kartik.\nI love music of Kartik.\nThanks.\nI love music of Kartik.\nI love music of Kartik.\n$go run uniq.go input.txt\nI love music.\n\nI love music of Kartik.\nThanks.\nI love music of Kartik.\n```\n\n</details>\n\n<details>\n    <summary>С параметрами input_file и output_file</summary>\n\n```bash\n$cat input.txt\nI love music.\nI love music.\nI love music.\n\nI love music of Kartik.\nI love music of Kartik.\nThanks.\nI love music of Kartik.\nI love music of Kartik.\n$go run uniq.go input.txt output.txt\n$cat output.txt\nI love music.\n\nI love music of Kartik.\nThanks.\nI love music of Kartik.\n```\n\n</details>\n\n<details>\n    <summary>С параметром -c</summary>\n\n```bash\n$cat input.txt\nI love music.\nI love music.\nI love music.\n\nI love music of Kartik.\nI love music of Kartik.\nThanks.\nI love music of Kartik.\nI love music of Kartik.\n$cat input.txt | go run uniq.go -c\n3 I love music.\n1 \n2 I love music of Kartik.\n1 Thanks.\n2 I love music of Kartik.\n```\n\n</details>\n\n<details>\n    <summary>С параметром -d</summary>\n\n```bash\n$cat input.txt\nI love music.\nI love music.\nI love music.\n\nI love music of Kartik.\nI love music of Kartik.\nThanks.\nI love music of Kartik.\nI love music of Kartik.\n$cat input.txt | go run uniq.go -d\nI love music.\nI love music of Kartik.\nI love music of Kartik.\n```\n\n</details>\n\n<details>\n    <summary>С параметром -u</summary>\n\n```bash\n$cat input.txt\nI love music.\nI love music.\nI love music.\n\nI love music of Kartik.\nI love music of Kartik.\nThanks.\nI love music of Kartik.\nI love music of Kartik.\n$cat input.txt | go run uniq.go -u\n\nThanks.\n```\n\n</details>\n\n<details>\n    <summary>С параметром -i</summary>\n\n```bash\n$cat input.txt\nI LOVE MUSIC.\nI love music.\nI LoVe MuSiC.\n\nI love MuSIC of Kartik.\nI love music of kartik.\nThanks.\nI love music of kartik.\nI love MuSIC of Kartik.\n$cat input.txt | go run uniq.go -i\nI LOVE MUSIC.\n\nI love MuSIC of Kartik.\nThanks.\nI love music of kartik.\n```\n\n</details>\n\n<details>\n    <summary>С параметром -f num</summary>\n\n```bash\n$cat input.txt\nWe love music.\nI love music.\nThey love music.\n\nI love music of Kartik.\nWe love music of Kartik.\nThanks.\n$cat input.txt | go run uniq.go -f 1\nWe love music.\n\nI love music of Kartik.\nThanks.\n```\n\n</details>\n\n<details>\n    <summary>С параметром -s num</summary>\n\n```bash\n$cat input.txt\nI love music.\nA love music.\nC love music.\n\nI love music of Kartik.\nWe love music of Kartik.\nThanks.\n$cat input.txt | go run uniq.go -s 1\nI love music.\n\nI love music of Kartik.\nWe love music of Kartik.\nThanks.\n```\n\n</details>\n\n### Тестирование\n\nНужно протестировать поведение написанной функциональности\nс различными параметрами. Для тестирования нужно написать unit-тесты\nна эту функциональность. Тесты нужны как для успешных случаев,\nтак и для неуспешных. Примеры с тестами мы будем показывать ещё на\nследующих лекциях, но сейчас можно посмотреть в [шестом примере первой лекции](https://github.com/go-park-mail-ru/lectures/blob/master/1-basics/6_is_sorted/sorted/sorted_test.go).\n\n### Материалы в помощь\n\nВ `1-basics/readme.md` есть список книг по го, а так же по всем частым и нужным операциям, там вы можете найти многие примеры кода, которые вам пригодятся.\n\nМатериалы в помощь:\n\n* https://habrahabr.ru/post/306914/ - пакет io\n\n* https://golang.org/pkg/sort/\n\n* https://golang.org/pkg/io/\n\n* https://golang.org/pkg/io/ioutil/\n\n* https://godoc.org/flag - пакет для флагов\n\n* https://godoc.org/github.com/stretchr/testify - удобный набор\nпакетов для тестирования\n\n* https://golang.org/pkg/bufio/#Scanner - удобный способ прочитать\nлинии из потока данных\n\n### Best practices\n\n1. Уникализация строк может понадобиться не только как утилита,\nно и как часть более крупной логики. Для этого саму функцию\nуникализации можно вынести в отдельный пакет. Поскольку\nболее крупная логика не всегда связана с чтением аргументов\nи данных из файла или stdin, то на вход этой функции нужно\nпередавать слайс строк и аргументы.\n\n2. Множество параметров, которые вдобавок и опциональны, лучше\nпередавать структурой (например Options). Так проще расширять\nфункциональность, а внешнему пользователю функции (не всей утилиты)\nбудет проще передать правильные аргументы внутрь.\n\n3. Как файл, так и stdin удовлетворяет интерфейсу io.Reader.\nПоэтому логику по чтению можно сделать универсальной. Аналогично\nи с записью -- io.Writer\n\n4. Для написания однотипных тестовых случаев используется\n[табличное тестирование](https://github.com/golang/go/wiki/TableDrivenTests). Получается, что можно написать две функции\nтестов: успешные тестовые случаи и неуспешные тестовые случаи.\n\n5. Для сравнения ожидаемого и действительного можно использовать\nпакет [require](https://godoc.org/github.com/stretchr/testify/require).\nКроме простых сравнений на равенство пакет предоставляет много\nдругих ассертов.\n\n6. Тесты не должны зависеть от внешних ресурсов. Не нужно читать\nфайлы внутри теста. Так же не нужно тестировать передачу параметров\nпри вызове утилиты. Никакого внешнего взаимодействия. Тестирование\nфункции должно быть построено на том, что мы передаём некоторые\nвходные данные в функцию и сравниваем ответ функции с ожидаемыми\nвыходными данными.\n\n## Часть 2. Calc\n\nНужно написать калькулятор, умеющий вычислять выражение, подаваемое на STDIN.\n\nДостаточно реализовать сложение, вычитание, умножение, деление (поддержать дробное), поддержку скобок и унарный минус.\n\nТут также нужны тесты 🙂 Тестами нужно покрыть все операции.\n\n### Пример работы\n\n```bash\n    $ go run calc.go \"(1+2)-3\"\n    0\n\n    $ go run calc.go \"(1+2)*3\"\n    9\n```\n"
  },
  {
    "path": "1-basics/readme.md",
    "content": "Материалы для дополнительного чтения на английском:\r\n\r\n* https://golang.org/ref/spec - спецификация по язык\r\n* https://golang.org/ref/mem - модель памяти го. на начальном этапе не надо, но знать полезно\r\n* https://golang.org/doc/code.html - про организацию кода. GOPATH и пакеты\r\n* https://golang.org/cmd/go/\r\n* https://blog.golang.org/strings\r\n* https://blog.golang.org/slices\r\n* https://blog.golang.org/go-slices-usage-and-internals\r\n* https://github.com/golang/go/wiki - вики го на гитхабе. очень много полезной информации\r\n* https://blog.golang.org/go-maps-in-action\r\n* https://blog.golang.org/organizing-go-code\r\n* https://golang.org/doc/effective_go.html - основной сборник тайного знания, сюда вы будуте обращатсья в первое время часто\r\n* https://github.com/golang/go/wiki/CodeReviewComments как ревьювить (и писать код). обязательно к прочтению\r\n* https://divan.github.io/posts/avoid_gotchas/ - материал аналогичный 50 оттенков го\r\n* https://research.swtch.com/interfaces\r\n* https://research.swtch.com/godata\r\n* http://jordanorelli.com/post/42369331748/function-types-in-go-golang\r\n* https://www.devdungeon.com/content/working-files-go - работа с файлами\r\n* http://www.golangprograms.com - много how-to касательно базовых вещей в go\r\n* http://yourbasic.org/golang/ - ещё большой набор how-to где можно получить углублённую информацию по всем базовым вещам. очень полезны http://yourbasic.org/golang/blueprint/\r\n* https://github.com/Workiva/go-datastructures\r\n* https://github.com/enocom/gopher-reading-list - большая подборка статей по многим темам ( не только данной лекции )\r\n\r\nМатериалы для дополнительного чтения на русском:\r\n* https://habrahabr.ru/company/mailru/blog/314804/ - 50 оттенков го. обязательно к прочтению. многое оттуда мы ещё не проходили, но на будущее - имейте ввиду\r\n* https://habrahabr.ru/post/306914/ - Разбираемся в Go: пакет io\r\n* https://habrahabr.ru/post/272383/ - постулаты go. Маленькая статья об основными принципах языка\r\n* https://habrahabr.ru/company/mailru/blog/301036/ - лучшие практики go\r\n* https://habrahabr.ru/post/308198/ - организация кода в go\r\n* https://habrahabr.ru/post/339192/ - Зачем в Go амперсанд и звёздочка (& и *)\r\n* https://habrahabr.ru/post/325468/ - как не наступать на грабли в Go\r\n* https://habrahabr.ru/post/276981/ - Краш-курс по интерфейсам в Go\r\n* http://golang-book.ru\r\n\r\nЛитература по го на русском языке:\r\n\r\n* Язык программирования Go, Алан А. А. Донован, Брайан У. Керниган\r\n* Go на практике, Matt Butcher, Мэтт Фарина Мэтт\r\n* Программирование на Go. Разработка приложений XXI века, Марк Саммерфильд\r\n\r\nДополнительные упражнения:\r\n\r\n* https://go-tour-ru-ru.appspot.com/list - упражнения на овладение базовым синтаксисом, на случай если вам нужна небольшая практика перед первым заданием курса\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "10-performance/1_reflect/1_print/reflect_1.go",
    "content": "package main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"reflect\"\r\n)\r\n\r\ntype UserID int\r\n\r\ntype UserID2 UserID\r\n\r\ntype User struct {\r\n\tID       UserID2\r\n\tRealName string `unpack:\"-\"`\r\n\tLogin    string\r\n\tFlags    int\r\n}\r\n\r\nfunc PrintReflect(u interface{}) error {\r\n\tval := reflect.ValueOf(u).Elem()\r\n\r\n\tfmt.Printf(\"%T have %d fields:\\n\", u, val.NumField())\r\n\tfor i := 0; i < val.NumField(); i++ {\r\n\t\tvalueField := val.Field(i)\r\n\t\ttypeField := val.Type().Field(i)\r\n\r\n\t\tfmt.Printf(\"\\tname=%v, type=%v, value=%v, tag=`%v`\\n\", typeField.Name,\r\n\t\t\ttypeField.Type.Kind(),\r\n\t\t\tvalueField,\r\n\t\t\ttypeField.Tag.Get(\"unpack\"),\r\n\t\t)\r\n\t}\r\n\treturn nil\r\n}\r\n\r\nfunc main() {\r\n\tu := &User{\r\n\t\tID:       42,\r\n\t\tRealName: \"unrealname\",\r\n\t\tFlags:    32,\r\n\t}\r\n\terr := PrintReflect(u)\r\n\tif err != nil {\r\n\t\tpanic(err)\r\n\t}\r\n}\r\n"
  },
  {
    "path": "10-performance/1_reflect/2_unpack/reflect_2.go",
    "content": "package main\r\n\r\nimport (\r\n\t\"bytes\"\r\n\t\"encoding/binary\"\r\n\t\"fmt\"\r\n\t\"reflect\"\r\n)\r\n\r\ntype User struct {\r\n\tID       int\r\n\tRealName string `unpack:\"-\"`\r\n\tLogin    string\r\n\tFlags    int\r\n}\r\n\r\nfunc UnpackReflect(u interface{}, data []byte) error {\r\n\tr := bytes.NewReader(data)\r\n\r\n\tval := reflect.ValueOf(u)\r\n\tif val.Kind() != reflect.Ptr {\r\n\t\treturn fmt.Errorf(\"input is not pointer\")\r\n\t}\r\n\r\n\tval = val.Elem()\r\n\r\n\tfor i := 0; i < val.NumField(); i++ {\r\n\t\tvalueField := val.Field(i)\r\n\t\ttypeField := val.Type().Field(i)\r\n\r\n\t\tif typeField.Tag.Get(\"unpack\") == \"-\" {\r\n\t\t\tcontinue\r\n\t\t}\r\n\r\n\t\tswitch typeField.Type.Kind() {\r\n\t\tcase reflect.Int:\r\n\t\t\tvar value uint32\r\n\t\t\tbinary.Read(r, binary.LittleEndian, &value)\r\n\t\t\tvalueField.SetInt(int64(value))\r\n\t\tcase reflect.String:\r\n\t\t\tvar lenRaw uint32\r\n\t\t\tbinary.Read(r, binary.LittleEndian, &lenRaw)\r\n\r\n\t\t\tdataRaw := make([]byte, lenRaw)\r\n\t\t\tbinary.Read(r, binary.LittleEndian, &dataRaw)\r\n\r\n\t\t\tvalueField.SetString(string(dataRaw))\r\n\t\tdefault:\r\n\t\t\treturn fmt.Errorf(\"bad type: %v for field %v\", typeField.Type.Kind(), typeField.Name)\r\n\t\t}\r\n\t}\r\n\r\n\treturn nil\r\n}\r\n\r\nfunc main() {\r\n\t/*\r\n\t\tperl -E '$b = pack(\"L L/a* L\", 1_123_456, \"kek.kekovitch\", 16);\r\n\t\t\tprint map { ord.\", \"  } split(\"\", $b); '\r\n\t*/\r\n\tdata := []byte{\r\n\t\t128, 36, 17, 0,\r\n\r\n\t\t13, 0, 0, 0,\r\n\t\t107, 101, 107, 46, 107, 101, 107, 111, 118, 105, 116, 99, 104,\r\n\r\n\t\t16, 0, 0, 0,\r\n\t}\r\n\tu := &User{}\r\n\terr := UnpackReflect(u, data)\r\n\tif err != nil {\r\n\t\tpanic(err)\r\n\t}\r\n\r\n\tfmt.Printf(\"%#v\", u)\r\n}\r\n"
  },
  {
    "path": "10-performance/2_codegen/gen/codegen.go",
    "content": "// go build gen/* && ./codegen.exe pack/unpack.go  pack/marshaller.go\r\n// go run pack/*\r\npackage main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"go/ast\"\r\n\t\"go/parser\"\r\n\t\"go/token\"\r\n\t\"log\"\r\n\t\"os\"\r\n\t\"reflect\"\r\n\t\"strings\"\r\n\t\"text/template\"\r\n)\r\n\r\ntype tpl struct {\r\n\tFieldName string\r\n}\r\n\r\nvar (\r\n\tintTpl = template.Must(template.New(\"intTpl\").Parse(`\r\n\t// {{.FieldName}}\r\n\tvar {{.FieldName}}Raw uint32\r\n\tbinary.Read(r, binary.LittleEndian, &{{.FieldName}}Raw)\r\n\tin.{{.FieldName}} = int({{.FieldName}}Raw)\r\n`))\r\n\r\n\tstrTpl = template.Must(template.New(\"strTpl\").Parse(`\r\n\t// {{.FieldName}}\r\n\tvar {{.FieldName}}LenRaw uint32\r\n\tbinary.Read(r, binary.LittleEndian, &{{.FieldName}}LenRaw)\r\n\t{{.FieldName}}Raw := make([]byte, {{.FieldName}}LenRaw)\r\n\tbinary.Read(r, binary.LittleEndian, &{{.FieldName}}Raw)\r\n\tin.{{.FieldName}} = string({{.FieldName}}Raw)\r\n`))\r\n)\r\n\r\nfunc main() {\r\n\tfset := token.NewFileSet()\r\n\tnode, err := parser.ParseFile(fset, os.Args[1], nil, parser.ParseComments)\r\n\tif err != nil {\r\n\t\tlog.Fatal(err)\r\n\t}\r\n\r\n\tout, _ := os.Create(os.Args[2])\r\n\r\n\tfmt.Fprintln(out, `package `+node.Name.Name)\r\n\tfmt.Fprintln(out) // empty line\r\n\tfmt.Fprintln(out, `import \"encoding/binary\"`)\r\n\tfmt.Fprintln(out, `import \"bytes\"`)\r\n\tfmt.Fprintln(out) // empty line\r\n\r\n\tfor _, f := range node.Decls {\r\n\t\tg, ok := f.(*ast.GenDecl)\r\n\t\tif !ok {\r\n\t\t\tfmt.Printf(\"SKIP %#T is not *ast.GenDecl\\n\", f)\r\n\t\t\tcontinue\r\n\t\t}\r\n\tSPECS_LOOP:\r\n\t\tfor _, spec := range g.Specs {\r\n\t\t\tcurrType, ok := spec.(*ast.TypeSpec)\r\n\t\t\tif !ok {\r\n\t\t\t\tfmt.Printf(\"SKIP %#T is not ast.TypeSpec\\n\", spec)\r\n\t\t\t\tcontinue\r\n\t\t\t}\r\n\r\n\t\t\tcurrStruct, ok := currType.Type.(*ast.StructType)\r\n\t\t\tif !ok {\r\n\t\t\t\tfmt.Printf(\"SKIP %#T is not ast.StructType\\n\", currStruct)\r\n\t\t\t\tcontinue\r\n\t\t\t}\r\n\r\n\t\t\tif g.Doc == nil {\r\n\t\t\t\tfmt.Printf(\"SKIP struct %#v doesnt have comments\\n\", currType.Name.Name)\r\n\t\t\t\tcontinue\r\n\t\t\t}\r\n\r\n\t\t\tneedCodegen := false\r\n\t\t\tfor _, comment := range g.Doc.List {\r\n\t\t\t\tneedCodegen = needCodegen || strings.HasPrefix(comment.Text, \"// cgen: binpack\")\r\n\t\t\t}\r\n\t\t\tif !needCodegen {\r\n\t\t\t\tfmt.Printf(\"SKIP struct %#v doesnt have cgen mark\\n\", currType.Name.Name)\r\n\t\t\t\tcontinue SPECS_LOOP\r\n\t\t\t}\r\n\r\n\t\t\tfmt.Printf(\"process struct %s\\n\", currType.Name.Name)\r\n\t\t\tfmt.Printf(\"\\tgenerating Unpack method\\n\")\r\n\r\n\t\t\tfmt.Fprintln(out, \"func (in *\"+currType.Name.Name+\") Unpack(data []byte) error {\")\r\n\t\t\tfmt.Fprintln(out, \"\tr := bytes.NewReader(data)\")\r\n\r\n\t\tFIELDS_LOOP:\r\n\t\t\tfor _, field := range currStruct.Fields.List {\r\n\r\n\t\t\t\tif field.Tag != nil {\r\n\t\t\t\t\ttag := reflect.StructTag(field.Tag.Value[1 : len(field.Tag.Value)-1])\r\n\t\t\t\t\tif tag.Get(\"cgen\") == \"-\" {\r\n\t\t\t\t\t\tcontinue FIELDS_LOOP\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfieldName := field.Names[0].Name\r\n\t\t\t\tfieldType := field.Type.(*ast.Ident).Name\r\n\r\n\t\t\t\tfmt.Printf(\"\\tgenerating code for field %s.%s\\n\", currType.Name.Name, fieldName)\r\n\r\n\t\t\t\tswitch fieldType {\r\n\t\t\t\tcase \"int\":\r\n\t\t\t\t\tintTpl.Execute(out, tpl{fieldName})\r\n\t\t\t\tcase \"string\":\r\n\t\t\t\t\tstrTpl.Execute(out, tpl{fieldName})\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tlog.Fatalln(\"unsupported\", fieldType)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tfmt.Fprintln(out, \"\treturn nil\")\r\n\t\t\tfmt.Fprintln(out, \"}\") // end of Unpack func\r\n\t\t\tfmt.Fprintln(out)      // empty line\r\n\r\n\t\t}\r\n\t}\r\n}\r\n\r\n// go build gen/* && ./codegen.exe pack/unpack.go  pack/marshaller.go\r\n// go run pack/*\r\n"
  },
  {
    "path": "10-performance/2_codegen/pack/marshaller.go",
    "content": "package main\n\nimport \"encoding/binary\"\nimport \"bytes\"\n\nfunc (in *User) Unpack(data []byte) error {\n\tr := bytes.NewReader(data)\n\n\t// ID\n\tvar IDRaw uint32\n\tbinary.Read(r, binary.LittleEndian, &IDRaw)\n\tin.ID = int(IDRaw)\n\n\t// Name\n\tvar NameLenRaw uint32\n\tbinary.Read(r, binary.LittleEndian, &NameLenRaw)\n\tNameRaw := make([]byte, NameLenRaw)\n\tbinary.Read(r, binary.LittleEndian, &NameRaw)\n\tin.Name = string(NameRaw)\n\n\t// Flags\n\tvar FlagsRaw uint32\n\tbinary.Read(r, binary.LittleEndian, &FlagsRaw)\n\tin.Flags = int(FlagsRaw)\n\treturn nil\n}\n\n"
  },
  {
    "path": "10-performance/2_codegen/pack/unpack.go",
    "content": "// go build -o ./codegen.exe gen/*  && ./codegen.exe pack/unpack.go  pack/marshaller.go\npackage main\n\nimport \"fmt\"\n\n// lets generate code for this struct\n// cgen: binpack\ntype User struct {\n\tID       int\n\tRealName string `cgen:\"-\"`\n\tName     string\n\tFlags    int\n}\n\ntype Avatar struct {\n\tID  int\n\tUrl string\n}\n\nvar test = 42\n\nfunc main() {\n\t/*\n\t\tperl -E '$b = pack(\"L L/a* L\", 1_123_456, \"kek.kekovitch\", 16);\n\t\t\tprint map { ord.\", \"  } split(\"\", $b); '\n\t*/\n\tdata := []byte{\n\t\t128, 36, 17, 0,\n\n\t\t13, 0, 0, 0,\n\t\t107, 101, 107, 46, 107, 101, 107, 111, 118, 105, 116, 99, 104,\n\n\t\t16, 0, 0, 0,\n\t}\n\n\tu := User{}\n\tu.Unpack(data)\n\tfmt.Printf(\"Unpacked user %#v\", u)\n}\n"
  },
  {
    "path": "10-performance/3_perfomance_1/1_unpack/unpack_test.go",
    "content": "package unpack\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"testing\"\n)\n\n/*\n\tgo test -bench . unpack_test.go\n\tgo test -bench . -benchmem unpack_test.go\n*/\n\nvar (\n\tdata = []byte{\n\t\t128, 36, 17, 0,\n\n\t\t9, 0, 0, 0,\n\t\t118, 46, 114, 111, 109, 97, 110, 111, 118,\n\n\t\t16, 0, 0, 0,\n\t}\n)\n\ntype User struct {\n\tID       int\n\tRealName string `cgen:\"-\"`\n\tLogin    string\n\tFlags    int\n}\n\nfunc BenchmarkCodegen(b *testing.B) {\n\tu := &User{}\n\tfor i := 0; i < b.N; i++ {\n\t\tu = &User{}\n\t\tu.UnpackBin(data)\n\t}\n}\n\nfunc BenchmarkReflect(b *testing.B) {\n\tu := &User{}\n\tfor i := 0; i < b.N; i++ {\n\t\tu = &User{}\n\t\tUnpackReflect(u, data)\n\t}\n}\n\nfunc (in *User) UnpackBin(data []byte) error {\n\tr := bytes.NewReader(data)\n\n\t// ID\n\tvar IDRaw uint32\n\tbinary.Read(r, binary.LittleEndian, &IDRaw)\n\tin.ID = int(IDRaw)\n\n\t// Login\n\tvar LoginLenRaw uint32\n\tbinary.Read(r, binary.LittleEndian, &LoginLenRaw)\n\tLoginRaw := make([]byte, LoginLenRaw)\n\tbinary.Read(r, binary.LittleEndian, &LoginRaw)\n\tin.Login = string(LoginRaw)\n\n\t// Flags\n\tvar FlagsRaw uint32\n\tbinary.Read(r, binary.LittleEndian, &FlagsRaw)\n\tin.Flags = int(FlagsRaw)\n\treturn nil\n}\n\nfunc UnpackReflect(u interface{}, data []byte) error {\n\tr := bytes.NewReader(data)\n\n\tval := reflect.ValueOf(u).Elem()\n\n\tfor i := 0; i < val.NumField(); i++ {\n\t\tvalueField := val.Field(i)\n\t\ttypeField := val.Type().Field(i)\n\n\t\tif typeField.Tag.Get(\"unpack\") == \"-\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tswitch typeField.Type.Kind() {\n\t\tcase reflect.Int:\n\t\t\tvar value int\n\t\t\tbinary.Read(r, binary.LittleEndian, &value)\n\t\t\tvalueField.Set(reflect.ValueOf(value))\n\t\tcase reflect.String:\n\t\t\tvar lenRaw int\n\t\t\tbinary.Read(r, binary.LittleEndian, &lenRaw)\n\n\t\t\tdataRaw := make([]byte, lenRaw)\n\t\t\tbinary.Read(r, binary.LittleEndian, &dataRaw)\n\n\t\t\tvalueField.SetString(string(dataRaw))\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"bad type: %v for field %v\", typeField.Type.Kind(), typeField.Name)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n/*\n\tgo test -bench . unpack_test.go\n\tgo test -bench . -benchmem unpack_test.go\n\n\tgo test -bench . -benchmem -cpuprofile=cpu.out -memprofile=mem.out -memprofilerate=1 unpack_test.go\n\n\tgo tool pprof -http=:8083 unpack.test cpu.out\n\tgo tool pprof unpack.test cpu.out\n\tgo tool pprof unpack.test mem.out\n\n\tgo get github.com/uber/go-torch\n\tgo-torch unpack.test cpu.out\n\n*/\n"
  },
  {
    "path": "10-performance/3_perfomance_1/2_prealloc/prealloc_test.go",
    "content": "// go test -bench . -benchmem prealloc_test.go\npackage prealloc\n\nimport (\n\t\"testing\"\n)\n\nconst iterNum = 1000\n\nfunc BenchmarkEmptyAppend(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\tdata := make([]int, 0)\n\t\tfor j := 0; j < iterNum; j++ {\n\t\t\tdata = append(data, j)\n\t\t}\n\t}\n}\n\nfunc BenchmarkPreallocAppend(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\tdata := make([]int, 0, iterNum)\n\t\tfor j := 0; j < iterNum; j++ {\n\t\t\tdata = append(data, j)\n\t\t}\n\t}\n}\n\n/*\ngo test -bench . -benchmem -cpuprofile=cpu.out -memprofile=mem.out -memprofilerate=1 prealloc/prealloc_test.go\n\n\tgo tool pprof -http=:8083 prealloc.test cpu.out\n\tgo tool pprof prealloc.test cpu.out\n\tgo tool pprof prealloc.test mem.out\n\n\tgo tool pprof -svg -inuse_space prealloc.test mem.out > mem_is.svg\n\tgo tool pprof -svg -inuse_objects prealloc.test mem.out > mem_io.svg\n\tgo tool pprof -svg prealloc.test cpu.out > cpu.svg\n\n\tgo tool pprof -png prealloc.test cpu.out > cpu.png\n\n\n*/\n"
  },
  {
    "path": "10-performance/3_perfomance_1/3_pool/pool_test.go",
    "content": "package pool\r\n\r\nimport (\r\n\t\"bytes\"\r\n\t\"encoding/json\"\r\n\t\"sync\"\r\n\t\"testing\"\r\n)\r\n\r\nconst iterNum = 100\r\n\r\ntype PublicPage struct {\r\n\tID          int\r\n\tName        string\r\n\tUrl         string\r\n\tOwnerID     int\r\n\tImageUrl    string\r\n\tTags        []string\r\n\tDescription string\r\n\tRules       string\r\n}\r\n\r\nvar CoolGolangPublic = PublicPage{\r\n\tID:          1,\r\n\tName:        \"CoolGolangPublic\",\r\n\tUrl:         \"http://example.com\",\r\n\tOwnerID:     100500,\r\n\tImageUrl:    \"http://example.com/img.png\",\r\n\tTags:        []string{\"programming\", \"go\", \"golang\"},\r\n\tDescription: \"Best page about golang programming\",\r\n\tRules:       \"\",\r\n}\r\n\r\nvar Pages = []PublicPage{\r\n\tCoolGolangPublic,\r\n\tCoolGolangPublic,\r\n\tCoolGolangPublic,\r\n}\r\n\r\nfunc BenchmarkAllocNew(b *testing.B) {\r\n\tb.RunParallel(func(pb *testing.PB) {\r\n\t\tfor pb.Next() {\r\n\t\t\tdata := bytes.NewBuffer(make([]byte, 0, 64))\r\n\t\t\t_ = json.NewEncoder(data).Encode(Pages)\r\n\t\t}\r\n\t})\r\n}\r\n\r\nvar dataPool = sync.Pool{\r\n\tNew: func() interface{} {\r\n\t\treturn bytes.NewBuffer(make([]byte, 0, 64))\r\n\t},\r\n}\r\n\r\nfunc BenchmarkAllocPool(b *testing.B) {\r\n\tb.RunParallel(func(pb *testing.PB) {\r\n\t\tfor pb.Next() {\r\n\t\t\tdata := dataPool.Get().(*bytes.Buffer)\r\n\t\t\t_ = json.NewEncoder(data).Encode(Pages)\r\n\t\t\tdata.Reset()\r\n\t\t\tdataPool.Put(data)\r\n\t\t}\r\n\t})\r\n}\r\n\r\n/*\r\n\tgo test -bench . -benchmem pool/pool_test.go\r\n*/\r\n"
  },
  {
    "path": "10-performance/3_perfomance_1/4_string/string_test.go",
    "content": "package string\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n)\n\nvar (\n\tbrowser = \"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36\"\n\tre      = regexp.MustCompile(\"Android\")\n)\n\n// regexp.MatchString компилирует регулярку каждый раз\nfunc BenchmarkRegExp(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_, _ = regexp.MatchString(\"Android\", browser)\n\t}\n}\n\n// используем прекомпилированную регулярку\nfunc BenchmarkRegCompiled(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\tre.MatchString(browser)\n\t}\n}\n\n// просто ищем вхождение подстроки\nfunc BenchmarkStrContains(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = strings.Contains(browser, \"Android\")\n\t}\n}\n\n/*\n\tgo test -bench . string/string_test.go\n\tgo test -bench . -benchmem string/string_test.go\n\tgo test -bench . -benchmem -benchtime=100000x -cpuprofile=cpu.out -memprofile=mem.out -memprofilerate=1 string/string_test.go\n\n\tgo tool pprof -http=:8083 string.test cpu.out\n\tgo tool pprof string.test cpu.out\n\tgo tool pprof string.test mem.out\n\n\tgo tool pprof -svg -inuse_space string.test mem.out > mem_is.svg\n\tgo tool pprof -svg -inuse_objects string.test mem.out > mem_io.svg\n\tgo tool pprof -svg string.test cpu.out > cpu.svg\n\n\tgo tool pprof -png string.test cpu.out > cpu.png\n*/\n"
  },
  {
    "path": "10-performance/3_perfomance_1/5_json/json_test.go",
    "content": "package json\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nvar (\n\tdata = []byte(`{\"RealName\":\"Vasily\", \"Login\":\"v.romanov\", \"Status\":1, \"Flags\": 1}`)\n\tu    = User{}\n\tc    = Client{}\n)\n\n// go test -v -bench=. -benchmem json/*.go\n// go test -v -bench=. json/*.go\n\nfunc BenchmarkDecodeStandart(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = json.Unmarshal(data, &c)\n\t}\n}\n\nfunc BenchmarkDecodeEasyjson(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = u.UnmarshalJSON(data)\n\t}\n}\n\nfunc BenchmarkEncodeStandart(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_, _ = json.Marshal(&c)\n\t}\n}\n\nfunc BenchmarkEncodeEasyjson(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_, _ = u.MarshalJSON()\n\t}\n}\n"
  },
  {
    "path": "10-performance/3_perfomance_1/5_json/struct.go",
    "content": "package json\n\n//easyjson:json\ntype User struct {\n\tId       int\n\tRealName string\n\tLogin    string\n\tFlags    int\n\tStatus   int\n}\n\ntype Client struct {\n\tId       int\n\tRealName string\n\tLogin    string\n\tFlags    int\n\tStatus   int\n}\n"
  },
  {
    "path": "10-performance/3_perfomance_1/5_json/struct_easyjson.go",
    "content": "// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.\n\npackage json\n\nimport (\n\tjson \"encoding/json\"\n\teasyjson \"github.com/mailru/easyjson\"\n\tjlexer \"github.com/mailru/easyjson/jlexer\"\n\tjwriter \"github.com/mailru/easyjson/jwriter\"\n)\n\n// suppress unused package warning\nvar (\n\t_ *json.RawMessage\n\t_ *jlexer.Lexer\n\t_ *jwriter.Writer\n\t_ easyjson.Marshaler\n)\n\nfunc easyjson9f2eff5fDecodeSt(in *jlexer.Lexer, out *User) {\n\tisTopLevel := in.IsStart()\n\tif in.IsNull() {\n\t\tif isTopLevel {\n\t\t\tin.Consumed()\n\t\t}\n\t\tin.Skip()\n\t\treturn\n\t}\n\tin.Delim('{')\n\tfor !in.IsDelim('}') {\n\t\tkey := in.UnsafeString()\n\t\tin.WantColon()\n\t\tif in.IsNull() {\n\t\t\tin.Skip()\n\t\t\tin.WantComma()\n\t\t\tcontinue\n\t\t}\n\t\tswitch key {\n\t\tcase \"Id\":\n\t\t\tout.Id = int(in.Int())\n\t\tcase \"RealName\":\n\t\t\tout.RealName = string(in.String())\n\t\tcase \"Login\":\n\t\t\tout.Login = string(in.String())\n\t\tcase \"Flags\":\n\t\t\tout.Flags = int(in.Int())\n\t\tcase \"Status\":\n\t\t\tout.Status = int(in.Int())\n\t\tdefault:\n\t\t\tin.SkipRecursive()\n\t\t}\n\t\tin.WantComma()\n\t}\n\tin.Delim('}')\n\tif isTopLevel {\n\t\tin.Consumed()\n\t}\n}\nfunc easyjson9f2eff5fEncodeSt(out *jwriter.Writer, in User) {\n\tout.RawByte('{')\n\tfirst := true\n\t_ = first\n\tif !first {\n\t\tout.RawByte(',')\n\t}\n\tfirst = false\n\tout.RawString(\"\\\"Id\\\":\")\n\tout.Int(int(in.Id))\n\tif !first {\n\t\tout.RawByte(',')\n\t}\n\tfirst = false\n\tout.RawString(\"\\\"RealName\\\":\")\n\tout.String(string(in.RealName))\n\tif !first {\n\t\tout.RawByte(',')\n\t}\n\tfirst = false\n\tout.RawString(\"\\\"Login\\\":\")\n\tout.String(string(in.Login))\n\tif !first {\n\t\tout.RawByte(',')\n\t}\n\tfirst = false\n\tout.RawString(\"\\\"Flags\\\":\")\n\tout.Int(int(in.Flags))\n\tif !first {\n\t\tout.RawByte(',')\n\t}\n\tfirst = false\n\tout.RawString(\"\\\"Status\\\":\")\n\tout.Int(int(in.Status))\n\tout.RawByte('}')\n}\n\n// MarshalJSON supports json.Marshaler interface\nfunc (v User) MarshalJSON() ([]byte, error) {\n\tw := jwriter.Writer{}\n\teasyjson9f2eff5fEncodeSt(&w, v)\n\treturn w.Buffer.BuildBytes(), w.Error\n}\n\n// MarshalEasyJSON supports easyjson.Marshaler interface\nfunc (v User) MarshalEasyJSON(w *jwriter.Writer) {\n\teasyjson9f2eff5fEncodeSt(w, v)\n}\n\n// UnmarshalJSON supports json.Unmarshaler interface\nfunc (v *User) UnmarshalJSON(data []byte) error {\n\tr := jlexer.Lexer{Data: data}\n\teasyjson9f2eff5fDecodeSt(&r, v)\n\treturn r.Error()\n}\n\n// UnmarshalEasyJSON supports easyjson.Unmarshaler interface\nfunc (v *User) UnmarshalEasyJSON(l *jlexer.Lexer) {\n\teasyjson9f2eff5fDecodeSt(l, v)\n}\n"
  },
  {
    "path": "10-performance/4_perfomance_2/1_optimize/pprof_1.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"net/http\"\n\t_ \"net/http/pprof\"\n\t\"sync\"\n\t\"time\"\n)\n\ntype Post struct {\n\tID       int\n\tText     string\n\tAuthor   string\n\tComments int\n\tTime     time.Time\n}\n\nfunc handleSlow(w http.ResponseWriter, req *http.Request) {\n\ts := \"\"\n\tfor i := 0; i < 1000; i++ {\n\t\tp := &Post{ID: i, Text: \"new post\"}\n\t\ts += fmt.Sprintf(\"%#v\", p)\n\t}\n\tw.Write([]byte(s))\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handleSlow)\n\thttp.HandleFunc(\"/fast\", handleFast)\n\n\tfmt.Println(\"starting server at :8080\")\n\tfmt.Println(http.ListenAndServe(\":8080\", nil))\n}\n\n/*\ngo build -o pprof_1.exe pprof_1.go && ./pprof_1.exe\n\nhey -z 20s http://127.0.0.1:8080\nhey -z 20s http://127.0.0.1:8080/fast\n\ncurl http://127.0.0.1:8080/debug/pprof/heap -o mem_out.txt\ncurl http://127.0.0.1:8080/debug/pprof/profile?seconds=5 -o cpu_out.txt\n\ngo tool pprof -svg -inuse_space pprof_1.exe mem_out.txt > mem_is.svg\ngo tool pprof -svg -inuse_objects pprof_1.exe mem_out.txt > mem_oo.svg\ngo tool pprof -svg -alloc_space pprof_1.exe mem_out.txt > mem_as.svg\ngo tool pprof -svg -alloc_objects pprof_1.exe mem_out.txt > mem_ao.svg\ngo tool pprof -svg pprof_1.exe cpu_out.txt > cpu.svg\n\n*/\n\nvar dataPool = sync.Pool{\n\tNew: func() interface{} {\n\t\treturn &Post{}\n\t},\n}\n\nvar bufPool = sync.Pool{\n\tNew: func() interface{} {\n\t\treturn bytes.NewBuffer(make([]byte, 0, 50000))\n\t},\n}\n\nfunc handleFast(w http.ResponseWriter, req *http.Request) {\n\tbuf := bufPool.Get().(*bytes.Buffer)\n\tfor i := 0; i < 1000; i++ {\n\t\tp := dataPool.Get().(*Post)\n\t\tp.ID = i\n\t\tp.Text = \"new post\"\n\t\tfmt.Fprintf(buf, \"%#v\", p)\n\t\t*p = Post{}\n\t\tdataPool.Put(p)\n\t}\n\tbuf.Reset()\n\tbufPool.Put(buf)\n\tw.Write(buf.Bytes())\n}\n"
  },
  {
    "path": "10-performance/4_perfomance_2/1_optimize/pprof_1.sh",
    "content": "curl http://127.0.0.1:8080/debug/pprof/profile?seconds=5 -o cpu_out.txt\ncurl http://127.0.0.1:8080/debug/pprof/heap -o mem_out.txt\n\n# go tool pprof -svg -alloc_objects pprof_1.exe mem_out.txt > mem_ao.svg\n# go tool pprof -svg -alloc_space pprof_1.exe mem_out.txt > mem_as.svg\n# go tool pprof -svg -inuse_objects pprof_1.exe mem_out.txt > mem_io.svg\n# go tool pprof -svg -inuse_space pprof_1.exe mem_out.txt > mem_is.svg\n# go tool pprof -svg pprof_1.exe cpu_out.txt > cpu.svg\n\n# go tool pprof pprof_1.exe mem_out.txt\n# go tool pprof pprof_1.exe cpu_out.txt\n\n# go tool pprof -http=:8081 -alloc_objects pprof_1.exe mem_out.txt\n# go tool pprof -http=:8081 pprof_1.exe cpu_out.txt\n"
  },
  {
    "path": "10-performance/4_perfomance_2/2_leak_grtn/pprof_2.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t_ \"net/http/pprof\"\n\t\"time\"\n)\n\ntype Post struct {\n\tID       int\n\tText     string\n\tAuthor   string\n\tComments int\n\tTime     time.Time\n}\n\nfunc getPost(out chan []Post) {\n\tposts := []Post{}\n\tfor i := 1; i < 10; i++ {\n\t\tpost := Post{ID: 1, Text: \"text\"}\n\t\tposts = append(posts, post)\n\t}\n\tout <- posts\n}\n\nfunc longHeavyWork(ch chan bool) {\n\ttime.Sleep(1 * time.Minute)\n\tch <- true\n}\n\nfunc handleLeak(w http.ResponseWriter, req *http.Request) {\n\tres := make(chan []Post)\n\tgo getPost(res)\n\treturn\n\t<-res\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handleLeak)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\n/*\n\ngo build -o pprof_2.exe pprof_2.go && ./pprof_2.exe\n\nhey -z 30s -q 100 http://127.0.0.1:8080/\n\n./pprof_2.sh\n\n*/\n"
  },
  {
    "path": "10-performance/4_perfomance_2/2_leak_grtn/pprof_2.sh",
    "content": "curl http://localhost:8080/debug/pprof/goroutine?debug=2 -o goroutines.txt\ncurl http://127.0.0.1:8080/debug/pprof/heap -o mem_out.txt\n\n# go tool pprof -svg -inuse_objects pprof_2.exe mem_out.txt > mem_io.svg\n# go tool pprof -svg -inuse_space pprof_2.exe mem_out.txt > mem_is.svg\n"
  },
  {
    "path": "10-performance/4_perfomance_2/3_tracing/tracing.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t_ \"net/http/pprof\"\n\t\"runtime\"\n\t\"time\"\n)\n\ntype Post struct {\n\tID       int\n\tText     string\n\tAuthor   string\n\tComments int\n\tTime     time.Time\n}\n\nfunc handle(w http.ResponseWriter, req *http.Request) {\n\tresult := \"\"\n\tfor i := 0; i < 100; i++ {\n\t\tcurrPost := &Post{ID: i, Text: \"new post\", Time: time.Now()}\n\t\tjsonRaw, _ := json.Marshal(currPost)\n\t\tresult += string(jsonRaw)\n\t}\n\ttime.Sleep(3 * time.Millisecond)\n\tw.Write([]byte(result))\n}\n\nfunc main() {\n\truntime.GOMAXPROCS(4)\n\thttp.HandleFunc(\"/\", handle)\n\n\tfmt.Println(\"starting server at :8080\")\n\tfmt.Println(http.ListenAndServe(\":8080\", nil))\n}\n\n/*\n\n\n\n\n\ngo build -o tracing.exe tracing.go && ./tracing.exe\n\nab -t 300 -n 10000000 -c 10 http://127.0.0.1:8080/\n\ncurl http://localhost:8080/debug/pprof/trace?seconds=10 -o trace.out\n\ngo tool trace -http \"0.0.0.0:8081\" tracing.exe trace.out\n\n\n*/\n"
  },
  {
    "path": "10-performance/4_perfomance_2/note.txt",
    "content": "go tool pprof -http=:8080 pprof_2.exe cpu_out.txt\n"
  },
  {
    "path": "10-performance/5_testing/cover.html",
    "content": "\r\n<!DOCTYPE html>\r\n<html>\r\n\t<head>\r\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\r\n\t\t<style>\r\n\t\t\tbody {\r\n\t\t\t\tbackground: black;\r\n\t\t\t\tcolor: rgb(80, 80, 80);\r\n\t\t\t}\r\n\t\t\tbody, pre, #legend span {\r\n\t\t\t\tfont-family: Menlo, monospace;\r\n\t\t\t\tfont-weight: bold;\r\n\t\t\t}\r\n\t\t\t#topbar {\r\n\t\t\t\tbackground: black;\r\n\t\t\t\tposition: fixed;\r\n\t\t\t\ttop: 0; left: 0; right: 0;\r\n\t\t\t\theight: 42px;\r\n\t\t\t\tborder-bottom: 1px solid rgb(80, 80, 80);\r\n\t\t\t}\r\n\t\t\t#content {\r\n\t\t\t\tmargin-top: 50px;\r\n\t\t\t}\r\n\t\t\t#nav, #legend {\r\n\t\t\t\tfloat: left;\r\n\t\t\t\tmargin-left: 10px;\r\n\t\t\t}\r\n\t\t\t#legend {\r\n\t\t\t\tmargin-top: 12px;\r\n\t\t\t}\r\n\t\t\t#nav {\r\n\t\t\t\tmargin-top: 10px;\r\n\t\t\t}\r\n\t\t\t#legend span {\r\n\t\t\t\tmargin: 0 5px;\r\n\t\t\t}\r\n\t\t\t.cov0 { color: rgb(192, 0, 0) }\r\n.cov1 { color: rgb(128, 128, 128) }\r\n.cov2 { color: rgb(116, 140, 131) }\r\n.cov3 { color: rgb(104, 152, 134) }\r\n.cov4 { color: rgb(92, 164, 137) }\r\n.cov5 { color: rgb(80, 176, 140) }\r\n.cov6 { color: rgb(68, 188, 143) }\r\n.cov7 { color: rgb(56, 200, 146) }\r\n.cov8 { color: rgb(44, 212, 149) }\r\n.cov9 { color: rgb(32, 224, 152) }\r\n.cov10 { color: rgb(20, 236, 155) }\r\n\r\n\t\t</style>\r\n\t</head>\r\n\t<body>\r\n\t\t<div id=\"topbar\">\r\n\t\t\t<div id=\"nav\">\r\n\t\t\t\t<select id=\"files\">\r\n\t\t\t\t\r\n\t\t\t\t<option value=\"file0\">coursera\\testing\\main.go (85.7%)</option>\r\n\t\t\t\t\r\n\t\t\t\t</select>\r\n\t\t\t</div>\r\n\t\t\t<div id=\"legend\">\r\n\t\t\t\t<span>not tracked</span>\r\n\t\t\t\r\n\t\t\t\t<span class=\"cov0\">not covered</span>\r\n\t\t\t\t<span class=\"cov8\">covered</span>\r\n\t\t\t\r\n\t\t\t</div>\r\n\t\t</div>\r\n\t\t<div id=\"content\">\r\n\t\t\r\n\t\t<pre class=\"file\" id=\"file0\" style=\"display: none\">package main\r\n\r\nimport (\r\n        \"encoding/json\"\r\n        \"fmt\"\r\n)\r\n\r\ntype User struct {\r\n        ID int\r\n}\r\n\r\nvar data = map[string][]byte{\r\n        \"ok\": []byte(`{\"ID\": 27}`),\r\n        \"fail\": []byte(`{\"ID\": 27`),\r\n}\r\n\r\nfunc GetUser(key string) (*User, error) <span class=\"cov8\" title=\"1\">{\r\n        if jsonStr, ok := data[key]; ok </span><span class=\"cov8\" title=\"1\">{\r\n                user := &amp;User{}\r\n                err := json.Unmarshal(jsonStr, user)\r\n                if err != nil </span><span class=\"cov0\" title=\"0\">{\r\n                        return nil, fmt.Errorf(\"Cant decode json\")\r\n                }</span>\r\n                <span class=\"cov8\" title=\"1\">return user, nil</span>\r\n        }\r\n        <span class=\"cov8\" title=\"1\">return nil, fmt.Errorf(\"User doesnt exist\")</span>\r\n}\r\n</pre>\r\n\t\t\r\n\t\t</div>\r\n\t</body>\r\n\t<script>\r\n\t(function() {\r\n\t\tvar files = document.getElementById('files');\r\n\t\tvar visible;\r\n\t\tfiles.addEventListener('change', onChange, false);\r\n\t\tfunction select(part) {\r\n\t\t\tif (visible)\r\n\t\t\t\tvisible.style.display = 'none';\r\n\t\t\tvisible = document.getElementById(part);\r\n\t\t\tif (!visible)\r\n\t\t\t\treturn;\r\n\t\t\tfiles.value = part;\r\n\t\t\tvisible.style.display = 'block';\r\n\t\t\tlocation.hash = part;\r\n\t\t}\r\n\t\tfunction onChange() {\r\n\t\t\tselect(files.value);\r\n\t\t\twindow.scrollTo(0, 0);\r\n\t\t}\r\n\t\tif (location.hash != \"\") {\r\n\t\t\tselect(location.hash.substr(1));\r\n\t\t}\r\n\t\tif (!visible) {\r\n\t\t\tselect(\"file0\");\r\n\t\t}\r\n\t})();\r\n\t</script>\r\n</html>\r\n"
  },
  {
    "path": "10-performance/5_testing/coverage_test.go",
    "content": "package main\r\n\r\nimport (\r\n\t\"testing\"\r\n\t\"reflect\"\r\n)\r\n\r\ntype TestCase struct{\r\n\tKey string\r\n\tUser *User\r\n\tIsError bool\r\n}\r\n\r\nfunc TestGetUser(t *testing.T) {\r\n\tcases := []TestCase{\r\n\t\tTestCase{\"ok\", &User{ID: 27}, false},\r\n\t\t// TestCase{\"fail\", nil, true},\r\n\t\tTestCase{\"not_exist\", nil, true},\r\n\t}\r\n\r\n\tfor caseNum, item := range cases {\r\n\t\tu, err := GetUser(item.Key)\r\n\r\n\t\tif item.IsError && err == nil {\r\n\t\t\tt.Errorf(\"[%d] expected error, got nil\", caseNum)\r\n\t\t}\r\n\t\tif !item.IsError && err != nil {\r\n\t\t\tt.Errorf(\"[%d] unexpected error\", caseNum, err)\r\n\t\t}\r\n\t\tif !reflect.DeepEqual(u, item.User) {\r\n\t\t\tt.Errorf(\"[%d] wrong results: got %+v, expected %+v\",\r\n\t\t\tcaseNum, u, item.User)\r\n\t\t}\r\n\t}\r\n\r\n}\r\n\r\n/*\r\n\tgo test -coverprofile=cover.out\r\n\tgo tool cover -html=cover.out -o cover.html\r\n\r\n*/"
  },
  {
    "path": "10-performance/5_testing/main.go",
    "content": "package main\r\n\r\nimport (\r\n\t\"encoding/json\"\r\n\t\"fmt\"\r\n)\r\n\r\ntype User struct {\r\n\tID int\r\n}\r\n\r\nvar data = map[string][]byte{\r\n\t\"ok\":   []byte(`{\"ID\": 27}`),\r\n\t\"fail\": []byte(`{\"ID\": 27`),\r\n}\r\n\r\nfunc GetUser(key string) (*User, error) {\r\n\tif jsonStr, ok := data[key]; ok {\r\n\t\tuser := &User{}\r\n\t\terr := json.Unmarshal(jsonStr, user)\r\n\t\tif err != nil {\r\n\t\t\treturn nil, fmt.Errorf(\"Cant decode json\")\r\n\t\t}\r\n\t\treturn user, nil\r\n\t}\r\n\treturn nil, fmt.Errorf(\"User doesnt exist\")\r\n}\r\n"
  },
  {
    "path": "10-performance/6_xml_stream/main.go",
    "content": "package main\r\n\r\nimport (\r\n\t\"encoding/xml\"\r\n\t\"fmt\"\r\n\t\"bytes\"\r\n\t\"io\"\r\n)\r\n\r\ntype User struct {\r\n\tID int `xml:\"id,attr\"`\r\n\tLogin string `xml:\"login\"`\r\n\tName string `xml:\"name\"`\r\n\tBrowser string `xml:\"browser\"`\r\n}\r\n\r\ntype Users struct {\r\n    Version     string   `xml:\"version,attr\"`\r\n    List        []User   `xml:\"user\"`\r\n}\r\n\r\nvar xmlData = []byte(`<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<users>\r\n\t<user id=\"1\">\r\n\t\t<login>user1</login>\r\n\t\t<name>Василий Романов</name>\r\n\t\t<browser>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36\r\n</browser>\r\n\t</user>\r\n\t<user id=\"2\">\r\n\t\t<login>user2</login>\r\n\t\t<name>Иван Иванов</name>\r\n\t\t<browser>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36\r\n</browser>\r\n\t</user>\r\n\t<user id=\"2\">\r\n\t\t<login>user3</login>\r\n\t\t<name>Иван Петров</name>\r\n\t\t<browser>Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Trident/5.0)</browser>\r\n\t</user>\r\n\t<user id=\"1\">\r\n\t\t<login>user1</login>\r\n\t\t<name>Василий Романов</name>\r\n\t\t<browser>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36\r\n</browser>\r\n\t</user>\r\n\t<user id=\"2\">\r\n\t\t<login>user2</login>\r\n\t\t<name>Иван Иванов</name>\r\n\t\t<browser>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36\r\n</browser>\r\n\t</user>\r\n\t<user id=\"2\">\r\n\t\t<login>user3</login>\r\n\t\t<name>Иван Петров</name>\r\n\t\t<browser>Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Trident/5.0)</browser>\r\n\t</user>\r\n</users>`)\r\n\r\nfunc CountStruct() {\r\n\tlogins := make([]string, 0)\r\n\tv := new(Users)\r\n\terr := xml.Unmarshal(xmlData, &v)\r\n    if err != nil {\r\n        fmt.Printf(\"error: %v\", err)\r\n        return\r\n\t}\r\n\tfor _, u := range v.List {\r\n\t\tlogins = append(logins, u.Login)\r\n\t}\r\n}\r\n\r\nfunc CountDecoder() {\r\n\tinput := bytes.NewReader(xmlData)\r\n\tdecoder := xml.NewDecoder(input)\r\n\tlogins := make([]string, 0)\r\n\tvar login string\r\n\tfor {\r\n\t\ttok, tokenErr := decoder.Token()\r\n\t\tif tokenErr != nil && tokenErr != io.EOF {\r\n\t\t\tfmt.Println(\"error happend\", tokenErr)\r\n\t\t\tbreak\r\n\t\t} else if tokenErr == io.EOF {\r\n\t\t\tbreak\r\n\t\t}\r\n\t\tif tok == nil {\r\n\t\t\tfmt.Println(\"t is nil break\")\r\n\t\t}\r\n\t\tswitch tok := tok.(type) {\r\n\t\tcase xml.StartElement:\r\n\t\t\tif tok.Name.Local == \"login\" {\r\n\t\t\t\tif err := decoder.DecodeElement(&login, &tok); err != nil {\r\n\t\t\t\t\tfmt.Println(\"error happend\", err)\r\n\t\t\t\t}\r\n\t\t\t\tlogins = append(logins, login)\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/*\r\n\tgo test -bench . -benchmem xml_test.go\r\n*/\r\n\r\nfunc main() {\r\n\tCountStruct()\r\n\tCountDecoder()\r\n}"
  },
  {
    "path": "10-performance/6_xml_stream/xml_test.go",
    "content": "package main\r\n\r\nimport (\r\n\t\"testing\"\r\n)\r\n\r\nfunc BenchmarkCountStruct(b *testing.B) {\r\n\tfor i := 0; i < b.N; i++ {\r\n\t\tCountStruct()\r\n\t}\r\n}\r\n\r\nfunc BenchmarkCountDecoder(b *testing.B) {\r\n\tfor i := 0; i < b.N; i++ {\r\n\t\tCountDecoder()\r\n\t}\r\n}\r\n"
  },
  {
    "path": "10-performance/7_inline_escape/main.go",
    "content": "package main\r\n\r\nimport (\r\n\t\"fmt\"\r\n)\r\n\r\n/*\r\n\tgo run -gcflags -m main.go\r\n\tgo run -gcflags '-m -m' main.go\r\n*/\r\n\r\ntype User struct {\r\n\tID int\r\n\tLogin string\r\n}\r\n\r\nfunc (u *User) GetID() int {\r\n\treturn u.ID\r\n}\r\n\r\nfunc newUser(login string) *User {\r\n\treturn &User{123, login}\r\n}\r\n\r\nfunc setToZero(in *int) {\r\n\t// for i := 0; i<3; i++ {\r\n\t// \t*in = 1\r\n\t// }\r\n\t*in = 0\r\n}\r\n\r\nfunc main() {\r\n\r\n\tu := newUser(\"test\")\r\n\tu.ID = 1\r\n\r\n\tdata := make([]string, 20)\r\n\tdata = append(data, \"test\")\r\n\r\n\ti := 1\r\n\tsetToZero(&i)\r\n\r\n\t// _ = fmt.Sprint(data)\r\n\t// _ = fmt.Sprint(u)\r\n\tfmt.Println(\"test\")\r\n}\r\n"
  },
  {
    "path": "10-performance/8_cgo/1_example/main.go",
    "content": "package main\n\n/*\n#include <math.h>\n*/\nimport \"C\"\nimport \"fmt\"\n\nfunc main() {\n\tnum := C.double(16)\n\tresult := C.sqrt(num)\n\tfmt.Printf(\"Квадратный корень из %.2f равен %.2f\\n\", num, result)\n}\n"
  },
  {
    "path": "10-performance/8_cgo/2_performance/main.go",
    "content": "package main\n\n/*\n#include <stdio.h>\n\nlong long factorialC(long long n) {\n    long long result = 1;\n    for (long long i = 2; i <= n; i++) {\n        result *= i;\n    }\n    return result;\n}\n*/\nimport \"C\"\nimport (\n\t\"fmt\"\n\t\"math/big\"\n)\n\nfunc factorialCGo(n int64) int64 {\n\treturn int64(C.factorialC(C.longlong(n)))\n}\n\nfunc factorialGo(n int64) *big.Int {\n\tresult := big.NewInt(1)\n\tfor i := int64(2); i <= n; i++ {\n\t\tresult.Mul(result, big.NewInt(i))\n\t}\n\treturn result\n}\n\nfunc main() {\n\tn := int64(20)\n\tfmt.Println(\"Факториал на C через CGO:\", factorialCGo(n))\n}\n"
  },
  {
    "path": "10-performance/8_cgo/3_usage/README.md",
    "content": "```\nbrew install pkg-config\n```\nhttps://github.com/klippa-app/go-pdfium"
  },
  {
    "path": "10-performance/8_cgo/3_usage/go.mod",
    "content": "module pdfium\n\ngo 1.23.3\n\nrequire github.com/klippa-app/go-pdfium v1.13.0\n\nrequire (\n\tgithub.com/fatih/color v1.13.0 // indirect\n\tgithub.com/golang/protobuf v1.5.3 // indirect\n\tgithub.com/google/uuid v1.6.0 // indirect\n\tgithub.com/hashicorp/go-hclog v1.6.3 // indirect\n\tgithub.com/hashicorp/go-plugin v1.6.1 // indirect\n\tgithub.com/hashicorp/yamux v0.1.1 // indirect\n\tgithub.com/mattn/go-colorable v0.1.12 // indirect\n\tgithub.com/mattn/go-isatty v0.0.14 // indirect\n\tgithub.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 // indirect\n\tgithub.com/oklog/run v1.0.0 // indirect\n\tgolang.org/x/net v0.29.0 // indirect\n\tgolang.org/x/sys v0.25.0 // indirect\n\tgolang.org/x/text v0.18.0 // indirect\n\tgoogle.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect\n\tgoogle.golang.org/grpc v1.58.3 // indirect\n\tgoogle.golang.org/protobuf v1.34.1 // indirect\n)\n"
  },
  {
    "path": "10-performance/8_cgo/3_usage/go.sum",
    "content": "github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=\ngithub.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=\ngithub.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=\ngithub.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=\ngithub.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=\ngithub.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=\ngithub.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=\ngithub.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=\ngithub.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=\ngithub.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=\ngithub.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=\ngithub.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=\ngithub.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=\ngithub.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=\ngithub.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=\ngithub.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=\ngithub.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI=\ngithub.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0=\ngithub.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=\ngithub.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=\ngithub.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=\ngithub.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=\ngithub.com/klippa-app/go-pdfium v1.13.0 h1:Ow9+cPhhcmKdxp3GCwds79zWyOZHyJIJGGt70R/nUWc=\ngithub.com/klippa-app/go-pdfium v1.13.0/go.mod h1:eVVeeXJkk+W6KLaJy4fizsERYUaMqJulSXD9JQjx+8s=\ngithub.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=\ngithub.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=\ngithub.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=\ngithub.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=\ngithub.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=\ngithub.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=\ngithub.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 h1:7GoSOOW2jpsfkntVKaS2rAr1TJqfcxotyaUcuxoZSzg=\ngithub.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=\ngithub.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=\ngithub.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=\ngithub.com/onsi/ginkgo/v2 v2.20.0 h1:PE84V2mHqoT1sglvHc8ZdQtPcwmvvt29WLEEO3xmdZw=\ngithub.com/onsi/ginkgo/v2 v2.20.0/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI=\ngithub.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=\ngithub.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=\ngithub.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=\ngithub.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=\ngithub.com/tetratelabs/wazero v1.8.1 h1:NrcgVbWfkWvVc4UtT4LRLDf91PsOzDzefMdwhLfA550=\ngithub.com/tetratelabs/wazero v1.8.1/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs=\ngolang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=\ngolang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=\ngolang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=\ngolang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=\ngolang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=\ngolang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=\ngolang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=\ngolang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=\ngolang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=\ngoogle.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=\ngoogle.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=\ngoogle.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=\ngoogle.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=\ngoogle.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=\ngoogle.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\n"
  },
  {
    "path": "10-performance/8_cgo/3_usage/main.go",
    "content": "package main\n\nimport (\n\t\"image/png\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/klippa-app/go-pdfium\"\n\t\"github.com/klippa-app/go-pdfium/requests\"\n\t\"github.com/klippa-app/go-pdfium/single_threaded\"\n)\n\n// Be sure to close pools/instances when you're done with them.\nvar pool pdfium.Pool\nvar instance pdfium.Pdfium\n\nfunc init() {\n\t// Init the PDFium library and return the instance to open documents.\n\tpool = single_threaded.Init(single_threaded.Config{})\n\n\tvar err error\n\tinstance, err = pool.GetInstance(time.Second * 30)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc main() {\n\tfilePath := \"example.pdf\"\n\toutput := \"example.pdf.png\"\n\terr := renderPage(filePath, 1, output)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc renderPage(filePath string, page int, output string) error {\n\t// Load the PDF file into a byte array.\n\tpdfBytes, err := ioutil.ReadFile(filePath)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Open the PDF using PDFium (and claim a worker)\n\tdoc, err := instance.OpenDocument(&requests.OpenDocument{\n\t\tFile: &pdfBytes,\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Always close the document, this will release its resources.\n\tdefer instance.FPDF_CloseDocument(&requests.FPDF_CloseDocument{\n\t\tDocument: doc.Document,\n\t})\n\n\t// Render the page in DPI 200.\n\tpageRender, err := instance.RenderPageInDPI(&requests.RenderPageInDPI{\n\t\tDPI: 200, // The DPI to render the page in.\n\t\tPage: requests.Page{\n\t\t\tByIndex: &requests.PageByIndex{\n\t\t\t\tDocument: doc,\n\t\t\t\tIndex:    0,\n\t\t\t},\n\t\t}, // The page to render, 0-indexed.\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Write the output to a file.\n\tf, err := os.Create(output)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer f.Close()\n\n\terr = png.Encode(f, pageRender.Image)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "10-performance/8_cgo/README.md",
    "content": "# CGO\n\n- Wiki: https://go.dev/wiki/cgo\n\nCGO мощный инструмент, используемый в основном для использования\nлогики библиотек, которые изначально написаны на C и включают сложную логику."
  },
  {
    "path": "10-performance/readme.md",
    "content": "go test -bench . -benchmem -cpuprofile=cpu.out -memprofile=mem.out -memprofilerate=1 -benchtime=50000x unpack_test.go\ngo tool pprof -http=:8083 main.test cpu.out\ngo tool pprof -http=:8083 main.test mem.out"
  },
  {
    "path": "2-async/0_basic_error_handling/1_ignore_errors/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nvar idToUsername = map[int]string{\n\t0: \"romanov\",\n\t1: \"sulaev\",\n\t2: \"dorofeev\",\n}\n\nfunc main() {\n\tvar id int\n\tfor {\n\t\t_, err := fmt.Scanf(\"%d\", &id)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"err scanf %v\\n\", err)\n\t\t\tcontinue\n\t\t}\n\t\tfmt.Printf(\"username for id %d: %s\\n\", id, idToUsername[id])\n\t}\n}\n"
  },
  {
    "path": "2-async/0_basic_error_handling/2_panic/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nvar idToUsername = map[int]string{\n\t0: \"romanov\",\n\t1: \"sulaev\",\n\t2: \"dorofeev\",\n}\n\nfunc main() {\n\tvar id int\n\tfor {\n\t\t_, err := fmt.Scanf(\"%d\", &id)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\n\t\tusername, ok := idToUsername[id]\n\t\tif !ok {\n\t\t\tpanic(fmt.Sprintf(\"no user with id %d\", id))\n\t\t}\n\n\t\tfmt.Printf(\"username for id %d: %s\\n\", id, username)\n\t}\n}\n"
  },
  {
    "path": "2-async/0_basic_error_handling/3_handling/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nvar idToUsername = map[int]string{\n\t0: \"romanov\",\n\t1: \"sulaev\",\n\t2: \"dorofeev\",\n}\n\nfunc handling() error {\n\tvar id int\n\t_, err := fmt.Scanf(\"%d\", &id) // ask, why so many errors?\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get username: %w\", err)\n\t}\n\n\tusername, ok := idToUsername[id]\n\tif !ok {\n\t\treturn fmt.Errorf(\"no user with id %d\", id)\n\t}\n\n\tfmt.Printf(\"username for id %d: %s\\n\", id, username)\n\n\treturn nil\n}\n\nfunc main() {\n\tfor {\n\t\terr := handling()\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"error happened: %v\\n\", err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "2-async/0_basic_error_handling/4_return/main.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\ntype MyError struct {\n\tCode int\n}\n\nfunc (e MyError) Error() string {\n\treturn fmt.Sprintf(\"my error, code=%d\", e.Code)\n}\n\nfunc bad() error {\n\tvar err *MyError = nil\n\tfmt.Println(\"in bad\", err == nil)\n\treturn nil // явно указываем nil\n}\n\nfunc main() {\n\terr := bad()\n\tvar me MyError\n\tfmt.Println(\"errors as: \", errors.As(err, &me))\n\tfmt.Println(\"in main\", err == nil)\n\tfmt.Printf(\"err: %#v\\n\", err)\n}\n"
  },
  {
    "path": "2-async/1_async/10_context_cancel/context_cancel.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"time\"\n)\n\nfunc student(ctx context.Context, workerNum int, out chan<- int) {\n\twaitTime := time.Duration(rand.Intn(100)+10) * time.Millisecond\n\tfmt.Println(workerNum, \"студент думает\", waitTime)\n\tselect {\n\tcase <-ctx.Done():\n\t\tfmt.Println(\"студент\", workerNum, \"не успел придумать вопрос\")\n\t\treturn\n\tcase <-time.After(waitTime):\n\t\tfmt.Println(\"студент\", workerNum, \"придумал\")\n\t\tout <- workerNum\n\t}\n}\n\nfunc main() {\n\tctx, cancel := context.WithCancel(context.Background())\n\tresult := make(chan int, 1)\n\n\tfor i := 0; i <= 10; i++ {\n\t\tgo student(ctx, i, result)\n\t}\n\n\tfoundBy := <-result\n\tfmt.Println(\"вопрос был задан студентом\", foundBy)\n\tcancel()\n\n\ttime.Sleep(time.Second)\n}\n"
  },
  {
    "path": "2-async/1_async/10_context_timeout/context_parent/main.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc worker(ctx context.Context, name string) {\n\tfmt.Println(name, \"стартовал\")\n\n\tselect {\n\tcase <-ctx.Done():\n\t\tfmt.Println(name, \"остановлен:\", ctx.Err())\n\tcase <-time.After(3 * time.Second):\n\t\tfmt.Println(name, \"успел закончить работу\", ctx.Err())\n\t}\n}\n\nfunc main() {\n\tparentCtx, cancelParent := context.WithCancel(context.Background())\n\t//\tparentCtx, cancelParent := context.WithTimeout(context.Background(), 500*time.Millisecond)\n\n\tchildCtx1, _ := context.WithCancel(parentCtx)\n\t//childCtx2, _ := context.WithTimeout(parentCtx, 3*time.Second)\n\n\tgo worker(childCtx1, \"child-1\")\n\tgo worker(childCtx1, \"child-2\")\n\n\ttime.Sleep(4 * time.Second)\n\n\tfmt.Println(\"main: отменяем родительский контекст\")\n\tcancelParent()\n\n\ttime.Sleep(1 * time.Second)\n}\n"
  },
  {
    "path": "2-async/1_async/10_context_timeout/context_timeout.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"time\"\n)\n\nfunc worker(ctx context.Context, workerNum int, out chan<- int) {\n\twaitTime := time.Duration(rand.Intn(100)+10) * time.Millisecond\n\tfmt.Println(workerNum, \"студент \", waitTime)\n\tselect {\n\tcase <-ctx.Done():\n\t\tfmt.Println(\"студент\", workerNum, \"не успел придумать вопрос\")\n\t\treturn\n\tcase <-time.After(waitTime):\n\t\tfmt.Println(\"студент\", workerNum, \"придумал вопрос\")\n\t\tout <- workerNum\n\t}\n}\n\nfunc main() {\n\tworkTime := 50 * time.Millisecond\n\tctx, _ := context.WithTimeout(context.Background(), workTime)\n\tresult := make(chan int, 1)\n\n\tfor i := 0; i <= 10; i++ {\n\t\tgo worker(ctx, i, result)\n\t}\n\n\ttotalFound := 0\nLOOP:\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\tbreak LOOP\n\t\tcase foundBy := <-result:\n\t\t\ttotalFound++\n\t\t\tfmt.Println(\"студент\", foundBy, \"задал вопрос\")\n\t\t}\n\t}\n\tfmt.Println(\"всего вопросов\", totalFound)\n\ttime.Sleep(time.Second)\n}\n"
  },
  {
    "path": "2-async/1_async/11_errgroup_1/errgroup_1.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n)\n\nconst (\n\tgoroutinesNum  = 3\n\tbadGorutineNum = 2\n)\n\nfunc printGorutineNum(num int) error {\n\tfmt.Println(num, \"gorutine will work after\")\n\n\tif num == badGorutineNum {\n\t\tfmt.Println(\"error found in gorutine\", num)\n\t\treturn fmt.Errorf(\"bad gorutine number %d\", num)\n\t}\n\n\tfmt.Println(\"goroutine number\", num)\n\treturn nil\n}\n\nfunc main() {\n\teg := errgroup.Group{} // Инициализируем группу\n\tfor i := 0; i < goroutinesNum; i++ {\n\t\teg.Go(func() error {\n\t\t\treturn printGorutineNum(i + 1)\n\t\t})\n\t}\n\ttime.Sleep(time.Millisecond)\n\terr := eg.Wait()\n\tif err != nil {\n\t\tfmt.Println(err)\n\t} else {\n\t\tfmt.Println(\"done\")\n\t}\n}\n"
  },
  {
    "path": "2-async/1_async/11_errgroup_2/errgroup_2.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"golang.org/x/sync/errgroup\"\n\t\"time\"\n)\n\nconst (\n\tgoroutinesNum  = 3\n\tbadGorutineNum = 2\n)\n\nfunc printGorutineNum(ctx context.Context, num int) error {\n\twaitTime := time.Duration(10*(num+1)) * time.Millisecond\n\tfmt.Println(num, \"gorutine wil work after\", waitTime)\n\n\tselect {\n\tcase <-ctx.Done():\n\t\tfmt.Printf(\"gorutine %d cancelled\\n\", num)\n\t\treturn nil\n\tcase <-time.After(waitTime):\n\t\tif num == badGorutineNum {\n\t\t\tfmt.Println(\"error found in gorutine\", num)\n\t\t\treturn fmt.Errorf(\"bad gorutine number %d\", num)\n\t\t}\n\t\tfmt.Println(\"goroutine number\", num)\n\t}\n\n\treturn nil\n}\n\nfunc main() {\n\teg, ctx := errgroup.WithContext(context.Background()) // Инициализируем группу с контекстом\n\tfor i := 0; i < goroutinesNum; i++ {\n\t\teg.Go(func() error {\n\t\t\treturn printGorutineNum(ctx, i+1)\n\t\t})\n\t}\n\ttime.Sleep(time.Millisecond)\n\terr := eg.Wait()\n\tif err != nil {\n\t\tfmt.Println(err)\n\t} else {\n\t\tfmt.Println(\"done\")\n\t}\n}\n"
  },
  {
    "path": "2-async/1_async/12_atomic_1/atomic_1.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n)\n\nvar totalOperations int32 = 0\nvar mu = &sync.Mutex{}\n\nfunc inc() {\n\t//mu.Lock()\n\t//defer mu.Unlock()\n\n\t// Не атомарная операция\n\ttotalOperations++\n}\n\nfunc main() {\n\t//runtime.GOMAXPROCS(1)\n\tfor i := 0; i < 1000; i++ {\n\t\tgo inc()\n\t}\n\ttime.Sleep(100 * time.Millisecond)\n\n\t// Ожидается 1000\n\t//mu.Lock()\n\tfmt.Println(\"total operation = \", totalOperations)\n\t//mu.Unlock()\n}\n"
  },
  {
    "path": "2-async/1_async/12_atomic_2/atomic_2.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"sync/atomic\" // atomic_2.go\n\t\"time\"\n)\n\nvar totalOperations int32\n\nfunc inc() {\n\tatomic.AddInt32(&totalOperations, 1) // атомарно\n}\n\nfunc main() {\n\tfor i := 0; i < 1000; i++ {\n\t\tgo inc()\n\t}\n\ttime.Sleep(2 * time.Millisecond)\n\tfmt.Println(\"total operation = \", totalOperations)\n}\n"
  },
  {
    "path": "2-async/1_async/12_atomic_2/with_bench/mutex_test.go",
    "content": "package main\n\nimport (\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"testing\"\n)\n\nvar (\n\ttotalMutex  int32\n\ttotalAtomic int32\n\tmutex       = &sync.Mutex{}\n)\n\nfunc BenchmarkMutexParallel(b *testing.B) {\n\tb.RunParallel(func(pb *testing.PB) {\n\t\tfor pb.Next() {\n\t\t\tmutex.Lock()\n\t\t\ttotalMutex++\n\t\t\tmutex.Unlock()\n\t\t}\n\t})\n}\n\nfunc BenchmarkAtomicParallel(b *testing.B) {\n\tb.RunParallel(func(pb *testing.PB) {\n\t\tfor pb.Next() {\n\t\t\tatomic.AddInt32(&totalAtomic, 1)\n\t\t}\n\t})\n}\n\nfunc BenchmarkLocalCounter(b *testing.B) {\n\tvar localCounter int64\n\tfor i := 0; i < b.N; i++ {\n\t\tlocalCounter++\n\t}\n\t_ = localCounter\n}\n"
  },
  {
    "path": "2-async/1_async/13_ratelim/ratelim.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n)\n\nconst (\n\titerationsNum = 6\n\tgoroutinesNum = 5\n\tquotaLimit    = 2\n)\n\nfunc startWorker(in int, wg *sync.WaitGroup, quotaCh chan struct{}) {\n\tdefer wg.Done()\n\n\tfmt.Printf(\"start %d\\n\", in)\n\ttime.Sleep(time.Millisecond)\n\n\tquotaCh <- struct{}{}\n\tdefer func() { <-quotaCh }()\n\tfor j := 0; j < iterationsNum; j++ {\n\t\tfmt.Println(formatWork(in, j))\n\n\t\t// if j%2 == 0 {\n\t\t// \t<-quotaCh             // ratelim.go, возвращаем слот\n\t\t// \tquotaCh <- struct{}{} // ratelim.go, берём слот\n\t\t// }\n\n\t\truntime.Gosched() // даём поработать другим горутинам\n\t}\n}\n\nfunc main() {\n\twg := &sync.WaitGroup{}\n\tquotaCh := make(chan struct{}, quotaLimit)\n\tfor i := 0; i < goroutinesNum; i++ {\n\t\twg.Add(1)\n\t\tgo startWorker(i, wg, quotaCh)\n\t}\n\ttime.Sleep(time.Millisecond)\n\twg.Wait()\n}\n\nfunc formatWork(in, j int) string {\n\treturn fmt.Sprintln(strings.Repeat(\"  \", in), \"█\",\n\t\tstrings.Repeat(\"  \", goroutinesNum-in),\n\t\t\"th\", in,\n\t\t\"iter\", j, strings.Repeat(\"■\", j))\n}\n"
  },
  {
    "path": "2-async/1_async/14_once/once.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n)\n\nfunc Init() {\n\tfmt.Println(\"Init once\")\n}\n\nfunc init() {\n\tfmt.Println(\"Init at start of program\")\n}\n\nfunc main() {\n\tconst routinesNum = 10\n\n\tonce := &sync.Once{}\n\n\twg := &sync.WaitGroup{}\n\twg.Add(routinesNum)\n\tfor i := 0; i < routinesNum; i++ {\n\t\tgo func() {\n\t\t\tdefer wg.Done()\n\t\t\tonce.Do(Init)\n\t\t}()\n\t}\n\twg.Wait()\n}\n"
  },
  {
    "path": "2-async/1_async/1_goroutines/goroutines.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nconst goroutinesNum = 7\n\nfunc main() {\n\tfor i := 0; i < goroutinesNum; i++ {\n\t\t//i := i\n\t\tgo func() { // А если go < 1.22?\n\t\t\tfmt.Println(i)\n\t\t}()\n\t}\n\n\ttime.Sleep(time.Second)\n}\n"
  },
  {
    "path": "2-async/1_async/1_goroutines/i_ptr/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nconst goroutinesNum = 7\n\nfunc main() {\n\tvar ptrs []*int\n\n\tfor i := 0; i < goroutinesNum; i++ {\n\t\t//i := i\n\t\tfmt.Println(\"адрес i:\", &i)\n\t\tptrs = append(ptrs, &i)\n\t}\n\n\tfor i, pt := range ptrs {\n\t\tfmt.Println(\"адрес в range i:\", &i)\n\t\tptrs = append(ptrs, &i)\n\t\tfmt.Println(*pt)\n\t}\n}\n"
  },
  {
    "path": "2-async/1_async/1_goroutines/mem/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\t\"time\"\n)\n\nfunc main() {\n\tvar m1, m2 runtime.MemStats\n\truntime.ReadMemStats(&m1)\n\n\tfor i := 0; i < 10; i++ {\n\t\tgo func() {\n\t\t\t//var b [2048]byte\n\t\t\t//_ = b\n\t\t\t//fmt.Println(b)\n\t\t\t//fmt.Println(i)\n\t\t}()\n\t}\n\n\ttime.Sleep(time.Second)\n\n\truntime.ReadMemStats(&m2)\n\n\tfmt.Printf(\"Allocated before: %d KB\\n\", m1.Alloc/1024)\n\tfmt.Printf(\"Allocated after : %d KB\\n\", m2.Alloc/1024)\n\tfmt.Printf(\"Per goroutine   : ~%d bytes\\n\", (m2.Alloc-m1.Alloc)/10)\n}\n"
  },
  {
    "path": "2-async/1_async/1_goroutines_2/goroutines.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n)\n\nconst (\n\titerationsNum = 6\n\tgoroutinesNum = 6\n)\n\nfunc doWork(th int) {\n\tfor j := 0; j < iterationsNum; j++ {\n\t\t/*if j%2 != 0 {\n\t\t\ttime.Sleep(1 * time.Millisecond)\n\t\t}*/\n\t\tfmt.Printf(formatWork(th, j))\n\t\t//runtime.Gosched()\n\t}\n}\n\nfunc main() {\n\t//runtime.GOMAXPROCS(1)\n\tfor i := 0; i < goroutinesNum; i++ {\n\t\tgo doWork(i)\n\t}\n\n\ttime.Sleep(time.Second)\n}\n\nfunc formatWork(in, j int) string {\n\treturn fmt.Sprintln(strings.Repeat(\"  \", in), \"█\",\n\t\tstrings.Repeat(\"  \", goroutinesNum-in),\n\t\t\"th\", in,\n\t\t\"iter\", j, strings.Repeat(\"■\", j))\n}\n"
  },
  {
    "path": "2-async/1_async/2_chan/chan_1.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tch1 := make(chan int)\n\n\tgo func(in chan int) {\n\t\tfmt.Println(\"GO: before read from chan\")\n\t\t// time.Sleep(1000 * time.Millisecond)\n\t\tval := <-in\n\t\tfmt.Println(\"GO: get from chan\", val)\n\t\tfmt.Println(\"GO: after read from chan\")\n\t}(ch1)\n\tfmt.Println(\"MAIN: before put to chan\")\n\t// time.Sleep(1000 * time.Millisecond)\n\n\tch1 <- 42\n\t//ch1 <- 100500\n\n\tfmt.Println(\"MAIN: after put to chan\")\n\tfmt.Scanln()\n}\n"
  },
  {
    "path": "2-async/1_async/2_chan_2/chan_2.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc main() {\n\tin := make(chan int)\n\n\tgo func(out chan<- int) {\n\t\tfor i := 0; i <= 10; i++ {\n\t\t\tfmt.Println(\"before\", i)\n\t\t\tout <- i\n\t\t\tfmt.Println(\"after\", i)\n\t\t}\n\n\t\tclose(out)\n\t\tfmt.Println(\"generator finish\")\n\t}(in)\n\n\ttime.Sleep(2 * time.Second)\n\n\tfor i := range in {\n\t\tfmt.Println(\"\\tget\", i)\n\t}\n\n\t/*\tfor {\n\t\tv, ok := <-in\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t\tfmt.Println(\"\\tget\", v)\n\t}*/\n\n\tfmt.Scanln()\n}\n"
  },
  {
    "path": "2-async/1_async/3_workerpool/1_workerpool.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\t\"strings\"\n\t\"time\"\n)\n\nconst goroutinesNum = 3\n\nfunc startWorker(workerNum int, in <-chan string) {\n\tfor input := range in {\n\t\tfmt.Println(formatWork(workerNum, input))\n\t\ttime.Sleep(10 * time.Millisecond)\n\t}\n\tprintFinishWork(workerNum)\n}\n\nfunc formatWork(in int, input string) string {\n\treturn fmt.Sprintln(strings.Repeat(\"  \", in), \"█\",\n\t\tstrings.Repeat(\"  \", goroutinesNum-in),\n\t\t\"th\", in,\n\t\t\"recieved\", input)\n}\n\nfunc printFinishWork(in int) {\n\tfmt.Println(strings.Repeat(\"==\", in), \"█\",\n\t\tstrings.Repeat(\"==\", goroutinesNum-in),\n\t\t\"===\", in,\n\t\t\"finished\")\n}\n\nfunc main() {\n\truntime.GOMAXPROCS(0)\n\tworkerInput := make(chan string)\n\tfor i := 0; i < goroutinesNum; i++ {\n\t\tgo startWorker(i, workerInput)\n\t}\n\n\tmonths := []string{\"Январь\", \"Февраль\", \"Март\",\n\t\t\"Апрель\", \"Май\", \"Июнь\",\n\t\t\"Июль\", \"Август\", \"Сентябрь\",\n\t\t\"Октябрь\", \"Ноябрь\", \"Декабрь\",\n\t\t\"123\",\n\t}\n\n\tfor _, monthName := range months {\n\t\tworkerInput <- monthName\n\t}\n\tclose(workerInput) // попробуйте закомментировать\n\n\ttime.Sleep(time.Second)\n}\n"
  },
  {
    "path": "2-async/1_async/3_workerpool/2_workerpool_reusable.go",
    "content": "package main\n\ntype workerPool struct {\n\tlocker chan struct{}\n\tqueue  chan func()\n}\n\nfunc NewWorkerPool(maxWorkers int) workerPool {\n\twp := workerPool{\n\t\tlocker: make(chan struct{}, maxWorkers),\n\t\tqueue:  make(chan func(), maxWorkers),\n\t}\n\tgo wp.work()\n\n\treturn wp\n}\n\nfunc (wp workerPool) work() {\n\tfor {\n\t\ttask := <-wp.queue\n\t\twp.locker <- struct{}{}\n\n\t\tgo func() {\n\t\t\tdefer func() { <-wp.locker }()\n\t\t\ttask()\n\t\t}()\n\t}\n}\n\nfunc (wp workerPool) PutTask(task func()) {\n\twp.queue <- task\n}\n"
  },
  {
    "path": "2-async/1_async/4_race_1/race_1.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tvar counters = map[int]int{}\n\tfor i := 0; i < 5; i++ {\n\t\tgo func(counters map[int]int, th int) {\n\t\t\tfor j := 0; j < 5; j++ {\n\t\t\t\tcounters[th*10+j]++\n\t\t\t}\n\t\t}(counters, i)\n\t}\n\tfmt.Scanln()\n\tfmt.Println(\"counters result\", counters)\n}\n"
  },
  {
    "path": "2-async/1_async/4_race_2/race_2.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n)\n\nfunc main() {\n\tvar counters = map[int]int{}\n\tmu := &sync.Mutex{}\n\tfor i := 0; i < 5; i++ {\n\t\tgo func(counters map[int]int, th int, mu *sync.Mutex) {\n\t\t\tfor j := 0; j < 5; j++ {\n\t\t\t\tmu.Lock()\n\t\t\t\tcounters[th*10+j]++\n\t\t\t\tmu.Unlock()\n\t\t\t}\n\t\t}(counters, i, mu)\n\t}\n\tfmt.Scanln()\n\tmu.Lock()\n\tfmt.Println(\"counters result\", counters)\n\tmu.Unlock()\n}\n\n// -race\n"
  },
  {
    "path": "2-async/1_async/4_race_2/race_flag/working_race.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\n// add race flag\nfunc main() {\n\tvar counter int\n\tfor i := 0; i < 4; i++ {\n\t\tgo func() {\n\t\t\tfor j := 0; j < 1000; j++ {\n\t\t\t\tcounter++\n\t\t\t}\n\t\t}()\n\t}\n\ttime.Sleep(2 * time.Second)\n\tfmt.Println(\"counter =\", counter)\n}\n"
  },
  {
    "path": "2-async/1_async/4_race_3/race_3.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n)\n\n// look sync.Map\n\nfunc main() {\n\tvar counters = map[int]int{}\n\tmu := &sync.RWMutex{}\n\tfor i := 0; i < 5; i++ {\n\t\tgo func(counters map[int]int, th int, mu *sync.RWMutex) {\n\t\t\tfor j := 0; j < 5; j++ {\n\t\t\t\tif (th*10+j)%7 == 0 {\n\t\t\t\t\tmu.Lock()\n\t\t\t\t\tcounters[th*10+j]++\n\t\t\t\t\tmu.Unlock()\n\t\t\t\t} else {\n\t\t\t\t\tmu.RLock()\n\t\t\t\t\tfmt.Printf(\"[%d,%d] result %v\\n\", th, j, counters)\n\t\t\t\t\tmu.RUnlock()\n\t\t\t\t}\n\t\t\t}\n\t\t}(counters, i, mu)\n\t}\n\ttime.Sleep(100 * time.Millisecond)\n\tmu.RLock()\n\tfmt.Println(\"counters result\", counters)\n\tmu.RUnlock()\n}\n"
  },
  {
    "path": "2-async/1_async/4_race_3_bench/race_test.go",
    "content": "package main\n\nimport (\n\t\"sync\"\n\t\"testing\"\n)\n\nfunc BenchmarkMapWithRWMutex(b *testing.B) {\n\tcounters := make(map[int]int)\n\tvar mu sync.RWMutex\n\n\tb.ResetTimer()\n\n\tb.RunParallel(func(pb *testing.PB) {\n\t\ti := 0\n\t\tfor pb.Next() {\n\t\t\tkey := i % 1000\n\n\t\t\tif key%7 == 0 {\n\t\t\t\tmu.Lock()\n\t\t\t\tcounters[key]++\n\t\t\t\tmu.Unlock()\n\t\t\t} else {\n\t\t\t\tmu.RLock()\n\t\t\t\t_ = counters[key]\n\t\t\t\tmu.RUnlock()\n\t\t\t}\n\n\t\t\ti++\n\t\t}\n\t})\n}\n\nfunc BenchmarkMapWithMutex(b *testing.B) {\n\tcounters := make(map[int]int)\n\tvar mu sync.Mutex\n\n\tb.ResetTimer()\n\n\tb.RunParallel(func(pb *testing.PB) {\n\t\ti := 0\n\t\tfor pb.Next() {\n\t\t\tkey := i % 1000\n\n\t\t\tif key%7 == 0 {\n\t\t\t\tmu.Lock()\n\t\t\t\tcounters[key]++\n\t\t\t\tmu.Unlock()\n\t\t\t} else {\n\t\t\t\tmu.Lock()\n\t\t\t\t_ = counters[key]\n\t\t\t\tmu.Unlock()\n\t\t\t}\n\n\t\t\ti++\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "2-async/1_async/5_tick/tick.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc main() {\n\tticker := time.NewTicker(time.Second)\n\ti := 0\n\tfor tickTime := range ticker.C {\n\t\ti++\n\t\tfmt.Println(\"step\", i, \"time\", tickTime)\n\t\tif i >= 5 {\n\t\t\t// Надо останавливать, иначе потечет (но с Go 1.23 не надо 🙂)\n\t\t\tticker.Stop()\n\t\t\t//os.Exit(3)\n\t\t\tbreak\n\t\t}\n\t}\n\tfmt.Println(\"total\", i)\n\n\treturn\n\n\t// Не может быть остановлен и собран сборщиком мусора\n\t// Используйте, если должен работать вечно\n\tc := time.Tick(time.Second)\n\ti = 0\n\tfor tickTime := range c {\n\t\ti++\n\t\tfmt.Println(\"step\", i, \"time\", tickTime)\n\t\tif i >= 5 {\n\t\t\tbreak\n\t\t}\n\t}\n\n}\n\n//while true; do echo \"Starting program...\"; go run tick.go; echo \"Program exited with code $?\"; sleep 1; done;\n"
  },
  {
    "path": "2-async/1_async/5_tick_example/5_ping_pong/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tch := make(chan string)\n\n\tgo func() {\n\t\tfor pong := range ch {\n\t\t\tfmt.Println(pong)\n\t\t\tch <- \"ping\"\n\t\t}\n\t}()\n\n\tgo func() {\n\t\tfor ping := range ch {\n\t\t\tfmt.Println(ping)\n\t\t\tch <- \"pong\"\n\t\t}\n\t}()\n\n\tch <- \"ping\"\n\n\tvar blockNil chan int\n\t<-blockNil\n}\n"
  },
  {
    "path": "2-async/1_async/5_tick_example/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc main() {\n\ttick1s := time.Tick(1 * time.Second)\n\ttick3s := time.Tick(3 * time.Second)\n\ttick4s := time.Tick(4 * time.Second)\n\t//var blockNil chan int\n\t//done := make(chan struct{})\n\n\tgo func() {\n\t\tfor t := range tick1s {\n\t\t\tfmt.Println(\"worker-1s tick at\", t.Format(\"15:04:05\"))\n\t\t}\n\t}()\n\n\tgo func() {\n\t\tfor t := range tick3s {\n\t\t\tfmt.Println(\"worker-3s tick at\", t.Format(\"15:04:05\"))\n\t\t}\n\t}()\n\n\tgo func() {\n\t\tfor t := range tick4s {\n\t\t\tfmt.Println(\"worker-4s start\", t.Format(\"15:04:05\"))\n\t\t\t//close(blockNil) //panic\n\t\t\t//close(done) // \"сигнал\" для завершения\n\t\t\t//done <- struct{}{}\n\t\t\t//var blockInGo chan int\n\t\t\t//blockInGo <- 1\n\t\t\tfmt.Println(\"worker-4s finish\", t.Format(\"15:04:05\"))\n\t\t}\n\t}()\n\n\t//select {}\n\t//var blockNil chan int\n\t//<-blockNil\n\n\t/*\tvar ch chan string\n\t\tif ch == nil {\n\n\t\t}*/\n\n\t//blockNil <- 1\n\t//<-done\n\t//valCh := <-done\n\t//fmt.Println(\"valCh\", valCh)\n\t//fmt.Println(<-done)\n}\n"
  },
  {
    "path": "2-async/1_async/6_afterfunc/afterfunc.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc sayHello() {\n\tfmt.Println(\"Hello World\")\n}\n\nfunc main() {\n\ttimer := time.AfterFunc(1*time.Second, sayHello)\n\n\tfmt.Scanln()\n\ttimer.Stop()\n\n\tfmt.Scanln()\n}\n"
  },
  {
    "path": "2-async/1_async/7_select_1/select_1.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tch1 := make(chan int, 1)\n\tch2 := make(chan int, 1)\n\n\tch1 <- 1\n\t//ch2 <- 1\n\n\tselect {\n\tcase val := <-ch1:\n\t\tfmt.Println(\"ch1 val\", val)\n\tcase ch2 <- 1:\n\t\tfmt.Println(\"put val to ch2\")\n\tdefault:\n\t\tfmt.Println(\"default case\")\n\t}\n\tfmt.Println(\"finish\")\n}\n"
  },
  {
    "path": "2-async/1_async/7_select_2/select_2.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tch1 := make(chan int, 2)\n\tch1 <- 1\n\tch1 <- 2\n\tch2 := make(chan int, 2)\n\tch2 <- 3\n\nLOOP:\n\tfor {\n\t\tselect {\n\t\tcase v1 := <-ch1:\n\t\t\tfmt.Println(\"chan1 val\", v1)\n\t\tcase v2 := <-ch2:\n\t\t\tfmt.Println(\"chan2 val\", v2)\n\t\tdefault:\n\t\t\tbreak LOOP\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "2-async/1_async/7_select_2_new/close_buff/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tch := make(chan int, 3)\n\n\tch <- 1\n\tch <- 2\n\tch <- 3\n\n\tclose(ch)\n\tfmt.Println(\"channel closed\")\n\n\t/*\tfor v := range ch {\n\t\tfmt.Println(\"read:\", v)\n\t}*/\n\tfor {\n\t\tselect {\n\t\tcase v, ok := <-ch:\n\t\t\tif !ok {\n\t\t\t\tfmt.Println(\"select: channel empty and closed — exit\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfmt.Println(\"select: read value\", v)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "2-async/1_async/7_select_2_new/select_2_new.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\n// Read 2 channels till they are closed\n\nfunc main() {\n\tch1 := make(chan int)\n\tch2 := make(chan int)\n\tgo func() {\n\t\tch2 <- 0\n\t\tclose(ch2)\n\t\tch1 <- 1\n\t\tch1 <- 2\n\t\tch1 <- 3\n\t\tch1 <- 4\n\t\tch1 <- 5\n\t\tch1 <- 6\n\t\tclose(ch1)\n\t}()\n\n\tfor {\n\t\tselect {\n\t\tcase v1, ok := <-ch1:\n\t\t\tif !ok {\n\t\t\t\tfmt.Println(\"ch1 closed\")\n\t\t\t\tch1 = nil\n\t\t\t}\n\t\t\tfmt.Println(\"chan1 val\", v1)\n\t\tcase v2, ok := <-ch2:\n\t\t\tif !ok {\n\t\t\t\tfmt.Println(\"ch2 closed\")\n\t\t\t\tch2 = nil\n\t\t\t}\n\t\t\tfmt.Println(\"chan2 val\", v2)\n\t\t}\n\t\tif ch1 == nil && ch2 == nil {\n\t\t\tfmt.Print(\"Two channels closed\")\n\t\t\tbreak\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "2-async/1_async/7_select_3/close_all/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc worker(id int, cancelCh chan struct{}) {\n\tfmt.Println(\"worker\", id, \"started\")\n\n\tfor {\n\t\tselect {\n\t\tcase <-cancelCh:\n\t\t\tfmt.Println(\"worker\", id, \"stopped\")\n\t\t\treturn\n\t\tdefault:\n\t\t\ttime.Sleep(300 * time.Millisecond)\n\t\t}\n\t}\n}\n\nfunc main() {\n\tcancelCh := make(chan struct{})\n\n\tfor i := 1; i <= 3; i++ {\n\t\tgo worker(i, cancelCh)\n\t}\n\n\ttime.Sleep(1 * time.Second)\n\n\tfmt.Println(\"sending cancel signal\")\n\t//cancelCh <- struct{}{}\n\tclose(cancelCh)\n\n\ttime.Sleep(1 * time.Second)\n}\n"
  },
  {
    "path": "2-async/1_async/7_select_3/close_signal/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\t\"time\"\n)\n\nfunc worker(id int, done <-chan struct{}) {\n\tfor {\n\t\tselect {\n\t\tcase <-done:\n\t\t\tfmt.Println(\"worker\", id, \"stopped\")\n\t\t\treturn\n\t\tdefault:\n\t\t\tfmt.Println(\"worker\", id, \"working\")\n\t\t\ttime.Sleep(1 * time.Second)\n\t\t}\n\t}\n}\n\nfunc main() {\n\tdone := make(chan struct{})\n\n\tgo worker(1, done)\n\tgo worker(2, done)\n\n\t// канал для сигналов ОС\n\tsigCh := make(chan os.Signal)\n\tsignal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)\n\n\t// ждём Ctrl+C\n\t<-sigCh\n\tfmt.Println(\"\\nCtrl+C pressed\")\n\n\t// оповещаем все горутины\n\t// можем обновить конфиг и т.д.\n\tclose(done)\n\n\ttime.Sleep(1 * time.Second) //подождем вывод\n\tfmt.Println(\"main exit\")\n}\n"
  },
  {
    "path": "2-async/1_async/7_select_3/select_3.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tcancelCh := make(chan bool)\n\tdataCh := make(chan int)\n\n\tgo func(cancelCh chan bool, dataCh chan int) {\n\t\tval := 0\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase <-cancelCh:\n\t\t\t\t// Закрываем канал там, где пишем\n\t\t\t\t// А что если много генераторов?\n\t\t\t\tclose(dataCh)\n\t\t\t\treturn\n\t\t\tcase dataCh <- val:\n\t\t\t\tval++\n\t\t\t}\n\t\t}\n\t}(cancelCh, dataCh)\n\n\tfor curVal := range dataCh {\n\t\tfmt.Println(\"read\", curVal)\n\t\tif curVal > 3 {\n\t\t\tfmt.Println(\"send cancel\")\n\t\t\tcancelCh <- true\n\t\t\t// Что если этот канал должен остановить множество генераторов?\n\t\t\t// close(cancelCh)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "2-async/1_async/8_wait_1/wait_1.go",
    "content": "package main\n\nimport (\n\t\"log\"\n\t\"time\"\n)\n\nfunc main() {\n\tresult := make(chan string)\n\tgo func(out chan<- string) {\n\t\ttime.Sleep(1 * time.Second)\n\t\tlog.Println(\"async operation ready, return result\")\n\t\tout <- \"success\"\n\t}(result)\n\n\ttime.Sleep(2 * time.Second)\n\tlog.Println(\"some useful work done\")\n\n\topStatus := <-result\n\tlog.Println(\"main goroutine:\", opStatus)\n}\n"
  },
  {
    "path": "2-async/1_async/8_wait_2/ping_pong/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n)\n\nfunc main() {\n\tballCh := make(chan string)\n\twg := &sync.WaitGroup{}\n\n\twg.Add(1)\n\t// Ping\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase ball := <-ballCh:\n\t\t\t\tfmt.Println(ball)\n\t\t\t\ttime.Sleep(500 * time.Millisecond)\n\t\t\t\tballCh <- \"ping\"\n\t\t\t}\n\t\t}\n\t}()\n\n\twg.Add(1)\n\t// Pong\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase ball := <-ballCh:\n\t\t\t\tfmt.Println(ball)\n\t\t\t\ttime.Sleep(500 * time.Millisecond)\n\t\t\t\tballCh <- \"pong\"\n\t\t\t}\n\t\t}\n\t}()\n\n\t// Стартовый удар\n\tballCh <- \"ping\"\n\n\t//select {}\n\twg.Wait()\n}\n"
  },
  {
    "path": "2-async/1_async/8_wait_2/wait_2.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n)\n\nconst (\n\titerationsNum = 7\n\tgoroutinesNum = 5\n)\n\nfunc doWork(in int, wg *sync.WaitGroup) {\n\tdefer wg.Done() // Уменьшаем счетчик на 1\n\tfor j := 0; j < iterationsNum; j++ {\n\t\tfmt.Printf(formatWork(in, j))\n\t\ttime.Sleep(time.Millisecond)\n\t}\n}\n\nfunc main() {\n\twg := &sync.WaitGroup{} // Инициализируем группу\n\tfor i := 0; i < goroutinesNum; i++ {\n\t\t// wg.Add надо вызывать в той горутине, которая порождает воркеров\n\t\t// В ином случае другая горутина может не успеть запуститься и выполнится Wait\n\t\twg.Add(1) // Добавляем 1 к счетчику\n\t\tgo doWork(i, wg)\n\t}\n\ttime.Sleep(time.Millisecond)\n\twg.Wait() // Ожидаем, пока wg.Done() не приведёт счетчик к 0\n}\n\nfunc formatWork(in, j int) string {\n\treturn fmt.Sprintln(strings.Repeat(\"  \", in), \"█\",\n\t\tstrings.Repeat(\"  \", goroutinesNum-in),\n\t\t\"th\", in,\n\t\t\"iter\", j, strings.Repeat(\"■\", j))\n}\n"
  },
  {
    "path": "2-async/1_async/8_wait_3/wait_3.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\t//github.com/neonxp/rutina\n)\n\nconst (\n\titerationsNum = 7\n\tgoroutinesNum = 5\n)\n\nfunc doWork(in int) {\n\tfor j := 0; j < iterationsNum; j++ {\n\t\tfmt.Printf(formatWork(in, j))\n\t\ttime.Sleep(time.Millisecond)\n\t}\n}\n\nfunc main() {\n\twg := &sync.WaitGroup{} // Инициализируем группу\n\tfor i := 0; i < goroutinesNum; i++ {\n\t\twg.Go(func() { // С go 1.25\n\t\t\tdoWork(i)\n\t\t})\n\t}\n\ttime.Sleep(time.Millisecond)\n\twg.Wait() // Ожидаем, пока wg.Done() не приведёт счетчик к 0\n}\n\nfunc formatWork(in, j int) string {\n\treturn fmt.Sprintln(strings.Repeat(\"  \", in), \"█\",\n\t\tstrings.Repeat(\"  \", goroutinesNum-in),\n\t\t\"th\", in,\n\t\t\"iter\", j, strings.Repeat(\"■\", j))\n}\n"
  },
  {
    "path": "2-async/1_async/9_timeout/timeout.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc longSQLQuery() chan bool {\n\tch := make(chan bool, 1)\n\tgo func() {\n\t\ttime.Sleep(2 * time.Second)\n\t\tch <- true\n\t}()\n\treturn ch\n}\n\nfunc main() {\n\t// При 1 выполнится таймаут, при 3 - выполнится операция\n\ttimer := time.NewTimer(3 * time.Second)\n\tselect {\n\tcase <-timer.C:\n\t\tfmt.Println(\"timer.C timeout happend\")\n\tcase result := <-longSQLQuery():\n\t\t// Освобождаем ресурс\n\t\tif !timer.Stop() {\n\t\t\t<-timer.C\n\t\t}\n\t\tfmt.Println(\"operation result:\", result)\n\t}\n}\n"
  },
  {
    "path": "2-async/readings_2.md",
    "content": "На русском:\r\n* https://habrahabr.ru/post/141853/ - как работают горутины\r\n* https://habrahabr.ru/post/308070/ - как работают каналы\r\n* https://habrahabr.ru/post/333654/ - как работает планировщик ( https://rakyll.org/scheduler/ )\r\n* https://habrahabr.ru/post/271789/ - танцы с мютексами\r\n\r\nНа английском:\r\n* https://blog.golang.org/race-detector\r\n* https://blog.golang.org/pipelines\r\n* https://blog.golang.org/advanced-go-concurrency-patterns\r\n* https://blog.golang.org/go-concurrency-patterns-timing-out-and\r\n* https://talks.golang.org/2012/concurrency.slide#1\r\n* https://www.goinggo.net/2017/10/the-behavior-of-channels.html\r\n* http://marcio.io/2015/07/handling-1-million-requests-per-minute-with-golang/ - рассказ про оптимизацию воркер пула\r\n* http://www.tapirgames.com/blog/golang-channel\r\n* http://www.tapirgames.com/blog/golang-channel-closing\r\n* https://github.com/golang/go/wiki/CommonMistakes\r\n\r\nВидео:\r\n* https://www.youtube.com/watch?v=5buaPyJ0XeQ - классное выступление Dave Cheney про функции первого класса и использование их с горутинами, очень рекомендую, оно небольшое\r\n* https://www.youtube.com/watch?v=f6kdp27TYZs - Google I/O 2012 - Go Concurrency Patterns - очень рекомендую\r\n* https://www.youtube.com/watch?v=rDRa23k70CU&list=PLDWZ5uzn69eyM81omhIZLzvRhTOXvpeX9&index=15 - ещё одно хорошее видео про паттерны конкуренции в го\r\n* https://www.youtube.com/watch?v=KAWeC9evbGM - видео Андрея Смирнова с конференции Highload - в нём вы можете получить более детальную информацию по теме вводного видео (методы обработки запросов и плюсы неблокирующего подхода), о том, что там творится на системном уровне. На русском, не про go\r\n\r\nКниги:\r\n* Язык программирования Go, Алан А. А. Донован, Брайан У. Керниган - глава 8\r\n* Concurrency in Go: Tools and Techniques for Developers, by Katherine Cox-Buday\r\n"
  },
  {
    "path": "3-web/0_json/0_simple_json/simple_json.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\ntype User struct {\n\tID       int\n\tUsername string\n\tphone    string\n}\n\nvar jsonStr = `{\"id\": 42, \"username\": \"rvasily\", \"phone\": \"123\"}`\n\nfunc main() {\n\tdata := []byte(jsonStr)\n\n\tu := &User{}\n\tjson.Unmarshal(data, u)\n\tfmt.Printf(\"struct:\\n\\t%#v\\n\\n\", u)\n\n\tu.phone = \"987654321\"\n\tresult, err := json.Marshal(u)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"json string:\\n\\t%s\\n\", string(result))\n}\n"
  },
  {
    "path": "3-web/0_json/1_struct_tags/struct_tags.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\ntype User struct {\n\tID       int `json:\"user_id,string\"`\n\tUsername string\n\tAddress  string `json:\",omitempty\"`\n\tCompany  string `json:\"-\"`\n}\n\nfunc main() {\n\tu := &User{\n\t\tID:       42,\n\t\tUsername: \"rvasily\",\n\t\tAddress:  \"test\",\n\t\tCompany:  \"Mail.Ru Group\",\n\t}\n\tresult, _ := json.Marshal(u)\n\tfmt.Printf(\"json string: %s\\n\", string(result))\n}\n"
  },
  {
    "path": "3-web/0_json/2_custom/custom.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype Company string\n\n// MarshalJSON удовлетворяет интерфейсу json.Marshaler\nfunc (c Company) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(fmt.Sprintf(\"ООО «%s»\", c))\n}\n\n// UnmarshalJSON удовлетворяет интерфейсу json.Unmarshaler\nfunc (c *Company) UnmarshalJSON(data []byte) error {\n\tvar company string\n\tif err := json.Unmarshal(data, &company); err != nil {\n\t\treturn err\n\t}\n\n\t*c = Company(strings.TrimSuffix(strings.TrimPrefix(company, \"ООО «\"), \"»\"))\n\treturn nil\n}\n\ntype User struct {\n\tID             int\n\tPassportSeries int\n\tPassportNumber int\n\tCompany        Company\n}\n\n// MarshalJSON удовлетворяет интерфейсу json.Marshaler\nfunc (u *User) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(struct {\n\t\tID       int     `json:\"user_id\"`\n\t\tPassport string  `json:\"passport\"`\n\t\tCompany  Company `json:\"company\"`\n\t}{\n\t\tID:       u.ID,\n\t\tPassport: fmt.Sprintf(\"%d %d\", u.PassportSeries, u.PassportNumber),\n\t\tCompany:  u.Company,\n\t})\n}\n\n// UnmarshalJSON удовлетворяет интерфейсу json.Unmarshaler\nfunc (u *User) UnmarshalJSON(data []byte) error {\n\tvar temp struct {\n\t\tID       int     `json:\"user_id\"`\n\t\tPassport string  `json:\"passport\"`\n\t\tCompany  Company `json:\"company\"`\n\t}\n\n\tif err := json.Unmarshal(data, &temp); err != nil {\n\t\treturn err\n\t}\n\n\tu.ID = temp.ID\n\tu.Company = temp.Company\n\n\tpassportParts := strings.SplitN(temp.Passport, \" \", 2)\n\tu.PassportSeries, _ = strconv.Atoi(passportParts[0])\n\tu.PassportNumber, _ = strconv.Atoi(passportParts[1])\n\n\treturn nil\n}\n\nfunc main() {\n\tu := &User{\n\t\tID:             42,\n\t\tPassportSeries: 4512,\n\t\tPassportNumber: 123456,\n\t\tCompany:        \"VK\",\n\t}\n\tresult, err := json.Marshal(u)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"json string: %s\\n\", string(result))\n\n\tvar unmarshalledUser User\n\terr = json.Unmarshal(result, &unmarshalledUser)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Printf(\"unmarshalledUser: %+v\\n\", unmarshalledUser)\n}\n"
  },
  {
    "path": "3-web/0_json/3_dynamic/dynamic.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\nvar jsonStr = `[\n\t{\"id\": 17, \"username\": \"iivan\", \"phone\": 0},\n\t{\"id\": \"17\", \"address\": \"none\", \"company\": \"Mail.ru\"},\n\t5,\n\t[]\n]`\n\nfunc main() {\n\tdata := []byte(jsonStr)\n\n\tvar users interface{}\n\tjson.Unmarshal(data, &users)\n\tfmt.Printf(\"unpacked in empty interface:\\n%#v\\n\\n\", users)\n\n\tuser2 := map[string]interface{}{\n\t\t\"id\":       42,\n\t\t\"username\": \"rvasily\",\n\t}\n\tvar user2i interface{} = user2\n\tresult, _ := json.Marshal(user2i)\n\tfmt.Printf(\"json string from map:\\n %s\\n\", string(result))\n}\n"
  },
  {
    "path": "3-web/1_net/net_listen.go",
    "content": "package main\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"net\"\n)\n\nfunc handleConnection(conn net.Conn) {\n\tname := conn.RemoteAddr().String()\n\n\tfmt.Printf(\"%+v connected\\n\", name)\n\tconn.Write([]byte(\"Hello, \" + name + \"\\n\\r\"))\n\n\tdefer conn.Close()\n\n\tscanner := bufio.NewScanner(conn)\n\tfor scanner.Scan() {\n\t\ttext := scanner.Text()\n\t\tif text == \"Exit\" {\n\t\t\tconn.Write([]byte(\"Bye\\n\\r\"))\n\t\t\tfmt.Println(name, \"disconnected\")\n\t\t\tbreak\n\t\t} else if text != \"\" {\n\t\t\tfmt.Println(name, \"enters\", text)\n\t\t\tconn.Write([]byte(\"You enter \" + text + \"\\n\\r\"))\n\t\t}\n\t}\n}\n\nfunc main() {\n\tlistener, err := net.Listen(\"tcp\", \":8080\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfor {\n\t\tconn, err := listener.Accept()\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tgo handleConnection(conn)\n\t}\n}\n"
  },
  {
    "path": "3-web/2_http/0_http_server/0_basic/basic.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\t// fmt.Fprintln(w, \"<h1>Привет, мир!</h1>\")\n\tw.Write([]byte(\"{}\"))\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handler)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/2_http/0_http_server/1_pages/pages.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintln(w, \"Main page\")\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/page\",\n\t\tfunc(w http.ResponseWriter, r *http.Request) {\n\t\t\tfmt.Fprintln(w, \"Single page:\", r.URL.String())\n\t\t})\n\n\thttp.HandleFunc(\"/pages/\",\n\t\tfunc(w http.ResponseWriter, r *http.Request) {\n\t\t\tfmt.Fprintln(w, \"Multiple pages:\", r.URL.String())\n\t\t})\n\n\thttp.HandleFunc(\"/\", handler)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/2_http/0_http_server/2_servehttp/servehttp.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\ntype Handler struct {\n\tName string\n}\n\nfunc (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintln(w, \"Name:\", h.Name, \"URL:\", r.URL.String())\n}\n\nfunc main() {\n\ttestHandler := &Handler{Name: \"test\"}\n\thttp.Handle(\"/test/\", testHandler)\n\n\trootHandler := &Handler{Name: \"root\"}\n\thttp.Handle(\"/\", rootHandler)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/2_http/0_http_server/3_mux/mux.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n)\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintln(w, \"URL:\", r.URL.String())\n}\n\nfunc main() {\n\tmux := http.NewServeMux()\n\tmux.HandleFunc(\"/\", handler)\n\n\tserver := http.Server{\n\t\tAddr:         \":8080\",\n\t\tHandler:      mux,\n\t\tReadTimeout:  10 * time.Second,\n\t\tWriteTimeout: 10 * time.Second,\n\t}\n\n\tfmt.Println(\"starting server at :8080\")\n\tserver.ListenAndServe()\n}\n"
  },
  {
    "path": "3-web/2_http/0_http_server/4_servers/servers.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc runServer(addr string) {\n\tmux := http.NewServeMux()\n\tmux.HandleFunc(\"/\",\n\t\tfunc(w http.ResponseWriter, r *http.Request) {\n\t\t\tfmt.Fprintln(w, \"Addr:\", addr, \"URL:\", r.URL.String())\n\t\t})\n\n\tserver := http.Server{\n\t\tAddr:    addr,\n\t\tHandler: mux,\n\t}\n\n\tfmt.Println(\"starting server at\", addr)\n\tserver.ListenAndServe()\n}\n\nfunc main() {\n\tgo runServer(\":8081\")\n\trunServer(\":8080\")\n}\n"
  },
  {
    "path": "3-web/2_http/1_request/0_get/get.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\tfor key, value := range r.URL.Query() {\n\t\tfmt.Println(key, value)\n\t}\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handler)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/2_http/1_request/1_post/post.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nvar loginFormTmpl = []byte(`\n<html>\n\t<body>\n\t<form action=\"/\" method=\"post\">\n\t\tLogin: <input type=\"text\" name=\"login\">\n\t\tPassword: <input type=\"password\" name=\"password\">\n\t\t<input type=\"submit\" value=\"Login\">\n\t</form>\n\t</body>\n</html>\n`)\n\nfunc mainPage(w http.ResponseWriter, r *http.Request) {\n\tif r.Method != http.MethodPost {\n\t\tw.Write(loginFormTmpl)\n\t\treturn\n\t}\n\n\tr.ParseForm()\n\tinputLogin := r.Form[\"login\"][0]\n\n\t//inputLogin := r.FormValue(\"login\")\n\tfmt.Fprintln(w, \"you enter: \", inputLogin)\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", mainPage)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/2_http/1_request/2_cookies/cookies.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n)\n\nfunc mainPage(w http.ResponseWriter, r *http.Request) {\n\tsession, err := r.Cookie(\"session_id\")\n\tloggedIn := (err != http.ErrNoCookie)\n\n\tif loggedIn {\n\t\tfmt.Fprintln(w, `<a href=\"/logout\">logout</a>`)\n\t\tfmt.Fprintln(w, \"Welcome, \"+session.Value)\n\t} else {\n\t\tfmt.Fprintln(w, `<a href=\"/login\">login</a>`)\n\t\tfmt.Fprintln(w, \"You need to login\")\n\t}\n}\n\nfunc loginPage(w http.ResponseWriter, r *http.Request) {\n\texpiration := time.Now().Add(10 * time.Hour)\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   \"Dmitry\",\n\t\tExpires: expiration,\n\t\tHttpOnly: true,\n\t}\n\thttp.SetCookie(w, &cookie)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc logoutPage(w http.ResponseWriter, r *http.Request) {\n\tsession, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t\treturn\n\t}\n\n\tsession.Expires = time.Now().AddDate(0, 0, -1)\n\thttp.SetCookie(w, session)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/login\", loginPage)\n\thttp.HandleFunc(\"/logout\", logoutPage)\n\thttp.HandleFunc(\"/\", mainPage)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/2_http/1_request/3_headers/headers.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\tw.Header().Set(\"RequestID\", \"d41d8cd98f00b204\")\n\n\tfmt.Fprintln(w, \"You browser is\", r.UserAgent())\n\tfmt.Fprintln(w, \"You accept\", r.Header.Get(\"Accept\"))\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handler)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/2_http/2_http_client/client.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strconv\"\n\t\"time\"\n)\n\nfunc startServer() {\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tfmt.Fprintf(w, \"getHandler: incoming request %#v\\n\", r)\n\t\tfmt.Fprintf(w, \"getHandler: r.Url %#v\\n\", r.URL)\n\t})\n\n\thttp.HandleFunc(\"/raw_body\", func(w http.ResponseWriter, r *http.Request) {\n\t\tbody, err := io.ReadAll(r.Body)\n\t\tdefer r.Body.Close() // важный пункт!\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), 500)\n\t\t\treturn\n\t\t}\n\t\tfmt.Fprintf(w, \"postHandler: raw body %s\\n\", string(body))\n\t})\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\nfunc runGet() {\n\turl := \"http://127.0.0.1:8080/?param=123&param2=test\"\n\tresp, err := http.Get(url)\n\tif err != nil {\n\t\tfmt.Println(\"error happend\", err)\n\t\treturn\n\t}\n\tdefer resp.Body.Close() // важный пункт!\n\n\trespBody, err := io.ReadAll(resp.Body)\n\n\tfmt.Printf(\"http.Get body %#v\\n\\n\\n\", string(respBody))\n}\n\nfunc runGetFullReq() {\n\n\treq := &http.Request{\n\t\tMethod: http.MethodGet,\n\t\tHeader: http.Header{\n\t\t\t\"User-Agent\": {\"coursera/golang\"},\n\t\t},\n\t}\n\n\treq.URL, _ = url.Parse(\"http://127.0.0.1:8080/?id=42\")\n\treq.URL.Query().Set(\"user\", \"rvasily\")\n\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tfmt.Println(\"error happend\", err)\n\t\treturn\n\t}\n\tdefer resp.Body.Close() // важный пункт!\n\n\trespBody, err := io.ReadAll(resp.Body)\n\n\tfmt.Printf(\"testGetFullReq resp %#v\\n\\n\\n\", string(respBody))\n}\n\nfunc runTransportAndPost() {\n\ttransport := &http.Transport{\n\t\tDialContext: (&net.Dialer{\n\t\t\tTimeout:   30 * time.Second,\n\t\t\tKeepAlive: 30 * time.Second,\n\t\t\tDualStack: true,\n\t\t}).DialContext,\n\t\tMaxIdleConns:          100,\n\t\tIdleConnTimeout:       90 * time.Second,\n\t\tTLSHandshakeTimeout:   10 * time.Second,\n\t\tExpectContinueTimeout: 1 * time.Second,\n\t}\n\n\tclient := &http.Client{\n\t\tTimeout:   time.Second * 10,\n\t\tTransport: transport,\n\t}\n\n\tdata := `{\"id\": 42, \"user\": \"rvasily\"}`\n\tbody := bytes.NewBufferString(data)\n\n\turl := \"http://127.0.0.1:8080/raw_body\"\n\treq, _ := http.NewRequest(http.MethodPost, url, body)\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\treq.Header.Add(\"Content-Length\", strconv.Itoa(len(data)))\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\tfmt.Println(\"error happend\", err)\n\t\treturn\n\t}\n\tdefer resp.Body.Close() // важный пункт!\n\n\trespBody, err := io.ReadAll(resp.Body)\n\n\tfmt.Printf(\"runTransport %#v\\n\\n\\n\", string(respBody))\n}\n\nfunc main() {\n\tgo startServer()\n\n\ttime.Sleep(100 * time.Millisecond)\n\n\trunGet()\n\trunGetFullReq()\n\trunTransportAndPost()\n}\n"
  },
  {
    "path": "3-web/2_http/3_files/0_file_upload/file_upload.go",
    "content": "package main\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nvar uploadFormTmpl = []byte(`\n<html>\n\t<body>\n\t<form action=\"/upload\" method=\"post\" enctype=\"multipart/form-data\">\n\t\tImage: <input type=\"file\" name=\"my_file\">\n\t\t<input type=\"submit\" value=\"Upload\">\n\t</form>\n\t</body>\n</html>\n`)\n\nfunc mainPage(w http.ResponseWriter, r *http.Request) {\n\tw.Write(uploadFormTmpl)\n}\n\nfunc uploadPage(w http.ResponseWriter, r *http.Request) {\n\tr.ParseMultipartForm(5 * 1024 * 1025)\n\tfile, header, err := r.FormFile(\"my_file\")\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\treturn\n\t}\n\tdefer file.Close()\n\n\tfmt.Fprintf(w, \"header.Filename %v\\n\", header.Filename)\n\tfmt.Fprintf(w, \"header.Header %#v\\n\", header.Header)\n\n\thasher := md5.New()\n\tio.Copy(hasher, file)\n\n\tfmt.Fprintf(w, \"md5 %x\\n\", hasher.Sum(nil))\n}\n\ntype Params struct {\n\tID   int\n\tUser string\n}\n\n/*\ncurl -v -X POST -H \"Content-Type: application/json\" -d '{\"id\": 2, \"user\": \"rvasily\"}' http://localhost:8080/raw_body\n*/\n\nfunc uploadRawBody(w http.ResponseWriter, r *http.Request) {\n\n\tbody, err := io.ReadAll(r.Body)\n\tdefer r.Body.Close()\n\n\tp := &Params{}\n\terr = json.Unmarshal(body, p)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), 500)\n\t\treturn\n\t}\n\n\tfmt.Fprintf(w, \"content-type %#v\\n\",\n\t\tr.Header.Get(\"Content-Type\"))\n\tfmt.Fprintf(w, \"params %#v\\n\", p)\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", mainPage)\n\thttp.HandleFunc(\"/upload\", uploadPage)\n\thttp.HandleFunc(\"/raw_body\", uploadRawBody)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/2_http/3_files/1_static/static/super_secret_password",
    "content": "BestPassword!\nqwerty1234567890"
  },
  {
    "path": "3-web/2_http/3_files/1_static/static.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\tw.Header().Set(\"Content-Type\", \"text/html\")\n\tw.Write([]byte(`\n\t\tHello World! <br />\n\t\t<img src=\"/data/img/gopher.png\" />\n\t`))\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handler)\n\n\tstaticHandler := http.StripPrefix(\n\t\t\"/data/\",\n\t\thttp.FileServer(http.Dir(\"./static\")),\n\t)\n\thttp.Handle(\"/data/\", staticHandler)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/2_http/4_httptest/0_client/client_test.go",
    "content": "package client\n\nimport (\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n)\n\ntype TestCase struct {\n\tID         string\n\tResponse   string\n\tStatusCode int\n}\n\nfunc GetUser(w http.ResponseWriter, r *http.Request) {\n\tkey := r.FormValue(\"id\")\n\tif key == \"42\" {\n\t\tw.WriteHeader(http.StatusOK)\n\t\tio.WriteString(w, `{\"status\": 200, \"resp\": {\"user\": 42}}`)\n\t} else {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\tio.WriteString(w, `{\"status\": 500, \"err\": \"db_error\"}`)\n\t}\n}\n\nfunc TestGetUser(t *testing.T) {\n\tcases := []TestCase{\n\t\tTestCase{\n\t\t\tID:         \"42\",\n\t\t\tResponse:   `{\"status\": 200, \"resp\": {\"user\": 42}}`,\n\t\t\tStatusCode: http.StatusOK,\n\t\t},\n\t\tTestCase{\n\t\t\tID:         \"500\",\n\t\t\tResponse:   `{\"status\": 500, \"err\": \"db_error\"}`,\n\t\t\tStatusCode: http.StatusInternalServerError,\n\t\t},\n\t}\n\tfor caseNum, item := range cases {\n\t\turl := \"http://example.com/api/user?id=\" + item.ID\n\t\treq := httptest.NewRequest(\"GET\", url, nil)\n\t\tw := httptest.NewRecorder()\n\n\t\tGetUser(w, req)\n\n\t\tif w.Code != item.StatusCode {\n\t\t\tt.Errorf(\"[%d] wrong StatusCode: got %d, expected %d\",\n\t\t\t\tcaseNum, w.Code, item.StatusCode)\n\t\t}\n\n\t\tresp := w.Result()\n\t\tbody, _ := io.ReadAll(resp.Body)\n\n\t\tbodyStr := string(body)\n\t\tif bodyStr != item.Response {\n\t\t\tt.Errorf(\"[%d] wrong Response: got %+v, expected %+v\",\n\t\t\t\tcaseNum, bodyStr, item.Response)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "3-web/2_http/4_httptest/1_server/server_test.go",
    "content": "package server\n\nimport (\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"reflect\"\n\t\"testing\"\n)\n\ntype TestCase struct {\n\tID      string\n\tResult  *CheckoutResult\n\tIsError bool\n}\n\ntype CheckoutResult struct {\n\tStatus  int\n\tBalance int\n\tErr     string\n}\n\nfunc CheckoutDummy(w http.ResponseWriter, r *http.Request) {\n\tkey := r.FormValue(\"id\")\n\tswitch key {\n\tcase \"42\":\n\t\tw.WriteHeader(http.StatusOK)\n\t\tio.WriteString(w, `{\"status\": 200, \"balance\": 100500}`)\n\tcase \"100500\":\n\t\tw.WriteHeader(http.StatusOK)\n\t\tio.WriteString(w, `{\"status\": 400, \"err\": \"bad_balance\"}`)\n\tcase \"__broken_json\":\n\t\tw.WriteHeader(http.StatusOK)\n\t\tio.WriteString(w, `{\"status\": 400`) //broken json\n\tcase \"__internal_error\":\n\t\tfallthrough\n\tdefault:\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t}\n}\n\ntype Cart struct {\n\tPaymentApiURL string\n}\n\nfunc (c *Cart) Checkout(id string) (*CheckoutResult, error) {\n\turl := c.PaymentApiURL + \"?id=\" + id\n\tresp, err := http.Get(url)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer resp.Body.Close()\n\n\tdata, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tresult := &CheckoutResult{}\n\n\terr = json.Unmarshal(data, result)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\n\nfunc TestCartCheckout(t *testing.T) {\n\tcases := []TestCase{\n\t\tTestCase{\n\t\t\tID: \"42\",\n\t\t\tResult: &CheckoutResult{\n\t\t\t\tStatus:  200,\n\t\t\t\tBalance: 100500,\n\t\t\t\tErr:     \"\",\n\t\t\t},\n\t\t\tIsError: false,\n\t\t},\n\t\tTestCase{\n\t\t\tID: \"100500\",\n\t\t\tResult: &CheckoutResult{\n\t\t\t\tStatus:  400,\n\t\t\t\tBalance: 0,\n\t\t\t\tErr:     \"bad_balance\",\n\t\t\t},\n\t\t\tIsError: false,\n\t\t},\n\t\tTestCase{\n\t\t\tID:      \"__broken_json\",\n\t\t\tResult:  nil,\n\t\t\tIsError: true,\n\t\t},\n\t\tTestCase{\n\t\t\tID:      \"__internal_error\",\n\t\t\tResult:  nil,\n\t\t\tIsError: true,\n\t\t},\n\t}\n\n\tts := httptest.NewServer(http.HandlerFunc(CheckoutDummy))\n\n\tfor caseNum, item := range cases {\n\t\tc := &Cart{\n\t\t\tPaymentApiURL: ts.URL,\n\t\t}\n\t\tresult, err := c.Checkout(item.ID)\n\n\t\tif err != nil && !item.IsError {\n\t\t\tt.Errorf(\"[%d] unexpected error: %#v\", caseNum, err)\n\t\t}\n\t\tif err == nil && item.IsError {\n\t\t\tt.Errorf(\"[%d] expected error, got nil\", caseNum)\n\t\t}\n\t\tif !reflect.DeepEqual(item.Result, result) {\n\t\t\tt.Errorf(\"[%d] wrong result, expected %#v, got %#v\", caseNum, item.Result, result)\n\t\t}\n\t}\n\tts.Close()\n}\n"
  },
  {
    "path": "3-web/3_template/0_inline/inline.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"text/template\"\n)\n\ntype tplParams struct {\n\tURL     string\n\tBrowser string\n}\n\nconst EXAMPLE = `\nBrowser {{.Browser}}\n\nyou at {{.URL}}\n`\n\nfunc handle(w http.ResponseWriter, r *http.Request) {\n\ttmpl := template.New(`example`)\n\ttmpl, _ = tmpl.Parse(EXAMPLE)\n\n\tparams := tplParams{\n\t\tURL:     r.URL.String(),\n\t\tBrowser: r.UserAgent(),\n\t}\n\n\ttmpl.Execute(w, params)\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handle)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/3_template/1_file/file.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"html/template\"\n\t\"net/http\"\n)\n\ntype User struct {\n\tID     int\n\tName   string\n\tActive bool\n}\n\nfunc main() {\n\ttmpl := template.Must(template.ParseFiles(\"users.html\"))\n\n\tusers := []User{\n\t\tUser{1, \"Vasily\", true},\n\t\tUser{2, \"<i>Ivan</i>\", false},\n\t\tUser{3, \"Dmitry\", true},\n\t}\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\ttmpl.Execute(w,\n\t\t\tstruct {\n\t\t\t\tUsers []User\n\t\t\t}{\n\t\t\t\tusers,\n\t\t\t})\n\t})\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/3_template/1_file/users.html",
    "content": "<html>\n<body>\n\t<h1>Users</h1>\n\t{{range .Users}}\n\t\t<b>{{.Name}}</b>\n\t\t{{if .Active}}active{{end}}\n\t\t<br />\n\t{{end}}\n</body>\n</html>\n"
  },
  {
    "path": "3-web/3_template/2_func/func.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"html/template\"\n\t\"net/http\"\n)\n\ntype User struct {\n\tID     int\n\tName   string\n\tActive bool\n}\n\nfunc IsUserOdd(u *User) bool {\n\treturn u.ID%2 != 0\n}\n\nfunc main() {\n\ttmplFuncs := template.FuncMap{\n\t\t\"OddUser\": IsUserOdd,\n\t}\n\n\ttmpl, err := template.\n\t\tNew(\"\").\n\t\tFuncs(tmplFuncs).\n\t\tParseFiles(\"func.html\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tusers := []User{\n\t\tUser{1, \"Vasily\", true},\n\t\tUser{2, \"Ivan\", false},\n\t\tUser{3, \"Dmitry\", true},\n\t}\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\terr := tmpl.ExecuteTemplate(w, \"func.html\",\n\t\t\tstruct {\n\t\t\t\tUsers []User\n\t\t\t}{\n\t\t\t\tusers,\n\t\t\t})\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t})\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/3_template/2_func/func.html",
    "content": "<html>\n<body>\n\t<h1>Users</h1>\n\t{{range .Users}}\n\t\t<b>{{.Name}}</b>,\n\t\t{{if OddUser .}}\n\t\t\tid {{.ID}} is odd\n\t\t{{end}}\n\t\t<br />\n\t{{end}}\n</body>\n</html>\n"
  },
  {
    "path": "3-web/3_template/3_method/method.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"html/template\"\n\t\"net/http\"\n)\n\ntype User struct {\n\tID     int\n\tName   string\n\tActive bool\n}\n\nfunc (u *User) PrintActive() string {\n\tif !u.Active {\n\t\treturn \"\"\n\t}\n\treturn \"method says user \" + u.Name + \" active\"\n}\n\nfunc main() {\n\ttmpl, err := template.\n\t\tNew(\"\").\n\t\tParseFiles(\"method.html\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tusers := []User{\n\t\tUser{1, \"Vasily\", true},\n\t\tUser{2, \"Ivan\", false},\n\t\tUser{3, \"Dmitry\", true},\n\t}\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\terr := tmpl.ExecuteTemplate(w, \"method.html\",\n\t\t\tstruct {\n\t\t\t\tUsers []User\n\t\t\t}{\n\t\t\t\tusers,\n\t\t\t})\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t})\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/3_template/3_method/method.html",
    "content": "<html>\n<body>\n\t<h1>Users</h1>\n\t{{range .Users}}\n\t\t<b>{{.Name}}</b> \n\t\t{{.PrintActive}}\n\t\t<br />\n\t{{end}}\n</body>\n</html>\n"
  },
  {
    "path": "3-web/4_json_http/main.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"sync\"\n)\n\ntype UserInput struct {\n\tName     string `json:\"name\"`\n\tPassword string `json:\"password\"`\n}\n\ntype User struct {\n\tID       uint64 `json:\"id\"`\n\tName     string `json:\"name\"`\n\tPassword string `json:\"-\"`\n}\n\ntype Handlers struct {\n\tusers []User\n\tmu    *sync.Mutex\n}\n\nfunc (h *Handlers) HandleCreateUser(w http.ResponseWriter, r *http.Request) {\n\tdefer r.Body.Close()\n\n\tdecoder := json.NewDecoder(r.Body)\n\n\tnewUserInput := new(UserInput)\n\terr := decoder.Decode(newUserInput)\n\tif err != nil {\n\t\tlog.Printf(\"error while unmarshalling JSON: %s\", err)\n\t\tw.Write([]byte(\"{}\"))\n\t\treturn\n\t}\n\n\tfmt.Println(newUserInput)\n\th.mu.Lock()\n\n\tvar id uint64 = 0\n\tif len(h.users) > 0 {\n\t\tid = h.users[len(h.users)-1].ID + 1\n\t}\n\n\th.users = append(h.users, User{\n\t\tID:       id,\n\t\tName:     newUserInput.Name,\n\t\tPassword: newUserInput.Password,\n\t})\n\th.mu.Unlock()\n}\n\nfunc (h *Handlers) HandleListUsers(w http.ResponseWriter, r *http.Request) {\n\tencoder := json.NewEncoder(w)\n\th.mu.Lock()\n\terr := encoder.Encode(h.users)\n\th.mu.Unlock()\n\tif err != nil {\n\t\tlog.Printf(\"error while marshalling JSON: %s\", err)\n\t\tw.Write([]byte(\"{}\"))\n\t\treturn\n\t}\n}\n\nfunc main() {\n\thandlers := Handlers{\n\t\tusers: make([]User, 0),\n\t\tmu:    &sync.Mutex{},\n\t}\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tw.Header().Set(\"Content-Type\", \"application/json\")\n\t\tw.Write([]byte(\"{}\"))\n\t})\n\n\thttp.HandleFunc(\"/users/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tw.Header().Set(\"Content-Type\", \"application/json\")\n\n\t\tlog.Println(r.URL.Path)\n\n\t\tif r.Method == http.MethodPost {\n\t\t\thandlers.HandleCreateUser(w, r)\n\t\t\treturn\n\t\t}\n\n\t\thandlers.HandleListUsers(w, r)\n\t})\n\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "3-web/4_json_http/main_test.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"reflect\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n)\n\nfunc TestCreateUsers(t *testing.T) {\n\tt.Parallel()\n\n\th := Handlers{\n\t\tusers: []User{},\n\t\tmu:    &sync.Mutex{},\n\t}\n\n\tbody := bytes.NewReader([]byte(`{\"name\": \"Vasily\", \"password\": \"qwerty\"}`))\n\n\texpectedUsers := []User{\n\t\t{\n\t\t\tID:       3,\n\t\t\tName:     \"Vasily\",\n\t\t\tPassword: \"qwerty\",\n\t\t},\n\t}\n\n\tr := httptest.NewRequest(\"POST\", \"/users/\", body)\n\tw := httptest.NewRecorder()\n\n\th.HandleCreateUser(w, r)\n\n\tif w.Code != http.StatusOK {\n\t\tt.Error(\"status is not ok\")\n\t}\n\n\treflect.DeepEqual(h.users, expectedUsers)\n}\n\nvar expectedJSON = `[{\"id\":1,\"name\":\"Afanasiy\"},{\"id\":2,\"name\":\"Ka\"}]`\n\nfunc TestGetUsers(t *testing.T) {\n\n\th := Handlers{\n\t\tusers: []User{\n\t\t\t{\n\t\t\t\tID:       1,\n\t\t\t\tName:     \"Afanasiy\",\n\t\t\t\tPassword: \"1234\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tID:       2,\n\t\t\t\tName:     \"Ka\",\n\t\t\t\tPassword: \"jdjfaljhfljehfs;l3345354\",\n\t\t\t},\n\t\t},\n\t\tmu: &sync.Mutex{},\n\t}\n\n\tt.Parallel()\n\n\tr := httptest.NewRequest(\"GET\", \"/users/\", nil)\n\tw := httptest.NewRecorder()\n\n\th.HandleListUsers(w, r)\n\n\tif w.Code != http.StatusOK {\n\t\tt.Error(\"status is not ok\")\n\t}\n\n\tbytes, _ := io.ReadAll(w.Body)\n\tif strings.Trim(string(bytes), \"\\n\") != expectedJSON {\n\t\tt.Errorf(\"expected: [%s], got: [%s]\", expectedJSON, string(bytes))\n\t}\n}\n"
  },
  {
    "path": "3-web/readings_3.md",
    "content": "Конечно же документация:\n* https://golang.org/pkg/net/http/\n\nДополнительные материалы\n\n* https://gowebexamples.github.io/ - примеры касательно разработки веба\n* https://golang.org/doc/articles/wiki/\n* https://astaxie.gitbooks.io/build-web-application-with-golang/\n* https://github.com/thewhitetulip/web-dev-golang-anti-textbook/\n* https://codegangsta.gitbooks.io/building-web-apps-with-go/content/\n* http://www.golangprograms.com/\n* http://marcio.io/2015/07/cheap-mapreduce-in-go/\n* https://www.rzaluska.com/blog/important-go-interfaces/\n* https://blog.cloudflare.com/the-complete-guide-to-golang-net-http-timeouts/ - про таймауты\n* http://polyglot.ninja/golang-making-http-requests/\n* http://tumregels.github.io/Network-Programming-with-Go/\n\nНа русском:\n\n* https://habrahabr.ru/post/330512/ - Многопользовательская игра на Go через telnet - чисто сеть"
  },
  {
    "path": "4-api/1_rpc/jsonrpc/books.go",
    "content": "package main\n\nimport (\n\t\"log\"\n\t\"sync\"\n)\n\ntype Book struct {\n\tID    uint   `json:\"id\"`\n\tTitle string `json:\"title\"`\n\tPrice uint   `json:\"price\"`\n}\n\ntype BookStore struct {\n\tbooks []*Book\n\tmu    sync.RWMutex\n}\n\nfunc NewBookStore() *BookStore {\n\treturn &BookStore{\n\t\tmu:    sync.RWMutex{},\n\t\tbooks: []*Book{},\n\t}\n}\n\nfunc (bs *BookStore) AddBook(in *Book, out *Book) error {\n\tlog.Println(\"AddBook called\")\n\n\tbs.mu.Lock()\n\tbs.books = append(bs.books, in)\n\tbs.mu.Unlock()\n\t*out = *in\n\treturn nil\n}\n\nfunc (bs *BookStore) GetBooks(in int, out *[]*Book) error {\n\tlog.Println(\"GetBooks called\")\n\n\tbs.mu.Lock()\n\tdefer bs.mu.Unlock()\n\t*out = bs.books\n\treturn nil\n}\n"
  },
  {
    "path": "4-api/1_rpc/jsonrpc/server.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"net/rpc\"\n\t\"net/rpc/jsonrpc\"\n)\n\ntype HttpConn struct {\n\tin  io.Reader\n\tout io.Writer\n}\n\nfunc (c *HttpConn) Read(p []byte) (n int, err error)  { return c.in.Read(p) }\nfunc (c *HttpConn) Write(d []byte) (n int, err error) { return c.out.Write(d) }\nfunc (c *HttpConn) Close() error                      { return nil }\n\n/*\n{\n   \"jsonrpc\":\"2.0\",\n   \"id\":1,\n   \"method\":\"BookStore.AddBook\",\n   \"params\":[\n      {\n         \"title\": \"The Moon is a harsh mistress\",\n         \"price\": 200\n      }\n   ]\n}\n*/\n\n/*\n\ncurl -v -X POST -H \"Content-Type: application/json\" -H \"X-Auth: 123\" -d '{\"jsonrpc\":\"2.0\", \"id\": 1, \"method\": \"BookStore.AddBook\", \"params\": [{\"title\":\"The Moon is a harsh mistress\", \"price\": 200}]}' http://localhost:8081/rpc\n\ncurl -v -X POST -H \"Content-Type: application/json\" -H \"X-Auth: 123\" -d '{\"jsonrpc\":\"2.0\", \"id\": 2, \"method\": \"BookStore.GetBooks\", \"params\": []}' http://localhost:8081/rpc\n\n*/\n\ntype Handler struct {\n\trpcServer *rpc.Server\n}\n\nfunc (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n\tfmt.Println(\"rpc auth: \", r.Header.Get(\"X-Auth\"))\n\n\tserverCodec := jsonrpc.NewServerCodec(&HttpConn{\n\t\tin:  r.Body,\n\t\tout: w,\n\t})\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\terr := h.rpcServer.ServeRequest(serverCodec)\n\tif err != nil {\n\t\tlog.Printf(\"Error while serving JSON request: %v\", err)\n\t\thttp.Error(w, `{\"error\":\"cant serve request\"}`, 500)\n\t} else {\n\t\tw.WriteHeader(200)\n\t}\n}\n\nfunc main() {\n\tbookStore := NewBookStore()\n\n\tserver := rpc.NewServer()\n\tserver.Register(bookStore)\n\n\tsessionHandler := &Handler{\n\t\trpcServer: server,\n\t}\n\thttp.Handle(\"/rpc\", sessionHandler)\n\n\tfmt.Println(\"starting server at :8081\")\n\thttp.ListenAndServe(\":8081\", nil)\n\n}\n"
  },
  {
    "path": "4-api/1_rpc/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc login(w http.ResponseWriter, r *http.Request) {\n\tfmt.Println(\"login\")\n\tw.Write([]byte(\"login\"))\n}\n\nfunc signup(w http.ResponseWriter, r *http.Request) {\n\tfmt.Println(\"signup\")\n\tw.Write([]byte(\"signup\"))\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tmethod := r.FormValue(\"method\")\n\n\t\tswitch method {\n\t\tcase \"login\":\n\t\t\tlogin(w, r)\n\n\t\tcase \"signup\":\n\t\t\tsignup(w, r)\n\t\t}\n\t})\n\thttp.ListenAndServe(\":9090\", nil)\n}\n"
  },
  {
    "path": "4-api/1_rpc/net-rpc/books.go",
    "content": "package main\n\nimport (\n\t\"log\"\n\t\"sync\"\n)\n\ntype Book struct {\n\tID    uint\n\tTitle string\n\tPrice uint\n}\n\ntype BookStore struct {\n\tbooks []*Book\n\tmu    sync.RWMutex\n}\n\nfunc NewBookStore() *BookStore {\n\treturn &BookStore{\n\t\tmu:    sync.RWMutex{},\n\t\tbooks: []*Book{},\n\t}\n}\n\nfunc (bs *BookStore) AddBook(in *Book, out *Book) error {\n\tlog.Println(\"AddBook called\")\n\n\tbs.mu.Lock()\n\tbs.books = append(bs.books, in)\n\tbs.mu.Unlock()\n\t*out = *in\n\treturn nil\n}\n\nfunc (bs *BookStore) GetBooks(in int, out *[]*Book) error {\n\tlog.Println(\"GetBooks called\")\n\n\tbs.mu.Lock()\n\tdefer bs.mu.Unlock()\n\t*out = bs.books\n\treturn nil\n}\n"
  },
  {
    "path": "4-api/1_rpc/net-rpc/client.go",
    "content": "package main\n\nimport (\n\t\"log\"\n\t\"net/rpc\"\n)\n\nfunc main() {\n\n\tclient, err := rpc.DialHTTP(\"tcp\", \"localhost:8081\")\n\tif err != nil {\n\t\tlog.Fatal(\"dialing:\", err)\n\t}\n\n\tres := new(Book)\n\tclient.Call(\"BookStore.AddBook\", &Book{Title: \"The Moon is a harsh mistress\"}, res)\n\tif err != nil {\n\t\tlog.Printf(\"AddBook error: %s\\n\", err)\n\t}\n\tlog.Printf(\"AddBook: %#v\", res)\n\n\tbooks := &[]*Book{}\n\n\terr = client.Call(\"BookStore.GetBooks\", 0, books)\n\tif err != nil {\n\t\tlog.Printf(\"GetBooks error: %s\\n\", err)\n\t}\n\n\tlog.Printf(\"GetBooks: %#v\", *books)\n}\n"
  },
  {
    "path": "4-api/1_rpc/net-rpc/server.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/rpc\"\n)\n\nfunc main() {\n\tbookStore := NewBookStore()\n\n\trpc.Register(bookStore)\n\trpc.HandleHTTP()\n\n\tl, e := net.Listen(\"tcp\", \":8081\")\n\tif e != nil {\n\t\tlog.Fatal(\"listen error:\", e)\n\t}\n\n\tfmt.Println(\"starting server at :8081\")\n\thttp.Serve(l, nil)\n}\n"
  },
  {
    "path": "4-api/2_rest/books.go",
    "content": "package main\n\nimport (\n\t\"log\"\n\t\"sync\"\n)\n\ntype Book struct {\n\tID    uint   `json:\"id\"`\n\tTitle string `json:\"title\"`\n\tPrice uint   `json:\"price\"`\n}\n\ntype BookStore struct {\n\tbooks  []*Book\n\tmu     sync.RWMutex\n\tnextID uint\n}\n\nfunc NewBookStore() *BookStore {\n\treturn &BookStore{\n\t\tmu:    sync.RWMutex{},\n\t\tbooks: []*Book{},\n\t}\n}\n\nfunc (bs *BookStore) AddBook(in *Book) (uint, error) {\n\tlog.Println(\"AddBook called\")\n\n\tbs.mu.Lock()\n\tbs.nextID++\n\tin.ID = bs.nextID\n\tlog.Println(\"nextID\", bs.nextID)\n\tbs.books = append(bs.books, in)\n\tbs.mu.Unlock()\n\n\treturn in.ID, nil\n}\n\nfunc (bs *BookStore) GetBooks() ([]*Book, error) {\n\tlog.Println(\"GetBooks called\")\n\n\tbs.mu.RLock()\n\tdefer bs.mu.RUnlock()\n\n\treturn bs.books, nil\n}\n"
  },
  {
    "path": "4-api/2_rest/main.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"log\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/gorilla/mux\"\n)\n\ntype Result struct {\n\tBody interface{} `json:\"body,omitempty\"`\n\tErr  string      `json:\"err,omitempty\"`\n}\n\ntype BooksHandler struct {\n\tstore *BookStore\n}\n\nfunc (api *BooksHandler) List(w http.ResponseWriter, r *http.Request) {\n\n\tbooks, err := api.store.GetBooks()\n\tif err != nil {\n\t\thttp.Error(w, `{\"error\":\"db\"}`, 500)\n\t\treturn\n\t}\n\n\tbody := map[string]interface{}{\n\t\t\"books\": books,\n\t}\n\tjson.NewEncoder(w).Encode(&Result{Body: body})\n}\n\n// http://127.0.0.1:8080/add?title=test&price=123\n\nfunc (api *BooksHandler) Add(w http.ResponseWriter, r *http.Request) {\n\ttitle := r.FormValue(\"title\")\n\tprice, _ := strconv.Atoi(r.FormValue(\"price\"))\n\n\tin := &Book{\n\t\tTitle: title,\n\t\tPrice: uint(price),\n\t}\n\tid, err := api.store.AddBook(in)\n\tif err != nil {\n\t\thttp.Error(w, `{\"error\":\"db\"}`, 500)\n\t\treturn\n\t}\n\n\tbody := map[string]interface{}{\n\t\t\"id\": id,\n\t}\n\tjson.NewEncoder(w).Encode(&Result{Body: body})\n}\n\nfunc (api *BooksHandler) BookByID(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tif err != nil {\n\t\thttp.Error(w, `{\"error\":\"bad id\"}`, 400)\n\t\treturn\n\t}\n\n\tbooks, err := api.store.GetBooks()\n\tif err != nil {\n\t\thttp.Error(w, `{\"error\":\"db\"}`, 500)\n\t\treturn\n\t}\n\n\tvar book *Book\n\tfor _, b := range books {\n\t\tif b.ID == uint(id) {\n\t\t\tbook = b\n\t\t\tbreak\n\t\t}\n\t}\n\tif book == nil {\n\t\thttp.Error(w, `{\"body\":{\"book\":null}}`, 404)\n\t\treturn\n\t}\n\n\tbody := map[string]interface{}{\n\t\t\"book\": book,\n\t}\n\tjson.NewEncoder(w).Encode(&Result{Body: body})\n}\n\nfunc main() {\n\tr := mux.NewRouter()\n\n\tapi := &BooksHandler{\n\t\tstore: NewBookStore(),\n\t}\n\n\tr.HandleFunc(\"/\", api.List)\n\tr.HandleFunc(\"/add\", api.Add)\n\tr.HandleFunc(\"/book/{id:[0-9]+}\", api.BookByID)\n\n\tlog.Println(\"start serving :8080\")\n\thttp.ListenAndServe(\":8080\", r)\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen/generated.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"strconv\"\n\t\"sync\"\n\t\"sync/atomic\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\t\"github.com/99designs/gqlgen/graphql/introspection\"\n\t\"github.com/vektah/gqlparser\"\n\t\"github.com/vektah/gqlparser/ast\"\n)\n\n// region    ************************** generated!.gotpl **************************\n\n// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.\nfunc NewExecutableSchema(cfg Config) graphql.ExecutableSchema {\n\treturn &executableSchema{\n\t\tresolvers:  cfg.Resolvers,\n\t\tdirectives: cfg.Directives,\n\t\tcomplexity: cfg.Complexity,\n\t}\n}\n\ntype Config struct {\n\tResolvers  ResolverRoot\n\tDirectives DirectiveRoot\n\tComplexity ComplexityRoot\n}\n\ntype ResolverRoot interface {\n\tQuery() QueryResolver\n}\n\ntype DirectiveRoot struct {\n}\n\ntype ComplexityRoot struct {\n\tAuthor struct {\n\t\tName func(childComplexity int) int\n\t}\n\n\tBook struct {\n\t\tAuthor func(childComplexity int) int\n\t\tID     func(childComplexity int) int\n\t\tPrice  func(childComplexity int) int\n\t\tTitle  func(childComplexity int) int\n\t}\n\n\tQuery struct {\n\t\tBooks func(childComplexity int) int\n\t}\n}\n\ntype QueryResolver interface {\n\tBooks(ctx context.Context) ([]*Book, error)\n}\n\ntype executableSchema struct {\n\tresolvers  ResolverRoot\n\tdirectives DirectiveRoot\n\tcomplexity ComplexityRoot\n}\n\nfunc (e *executableSchema) Schema() *ast.Schema {\n\treturn parsedSchema\n}\n\nfunc (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) {\n\tec := executionContext{nil, e}\n\t_ = ec\n\tswitch typeName + \".\" + field {\n\n\tcase \"Author.name\":\n\t\tif e.complexity.Author.Name == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Author.Name(childComplexity), true\n\n\tcase \"Book.author\":\n\t\tif e.complexity.Book.Author == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Book.Author(childComplexity), true\n\n\tcase \"Book.id\":\n\t\tif e.complexity.Book.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Book.ID(childComplexity), true\n\n\tcase \"Book.price\":\n\t\tif e.complexity.Book.Price == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Book.Price(childComplexity), true\n\n\tcase \"Book.title\":\n\t\tif e.complexity.Book.Title == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Book.Title(childComplexity), true\n\n\tcase \"Query.books\":\n\t\tif e.complexity.Query.Books == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Query.Books(childComplexity), true\n\n\t}\n\treturn 0, false\n}\n\nfunc (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {\n\tec := executionContext{graphql.GetRequestContext(ctx), e}\n\n\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\tdata := ec._Query(ctx, op.SelectionSet)\n\t\tvar buf bytes.Buffer\n\t\tdata.MarshalGQL(&buf)\n\t\treturn buf.Bytes()\n\t})\n\n\treturn &graphql.Response{\n\t\tData:       buf,\n\t\tErrors:     ec.Errors,\n\t\tExtensions: ec.Extensions,\n\t}\n}\n\nfunc (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {\n\treturn graphql.ErrorResponse(ctx, \"mutations are not supported\")\n}\n\nfunc (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response {\n\treturn graphql.OneShot(graphql.ErrorResponse(ctx, \"subscriptions are not supported\"))\n}\n\ntype executionContext struct {\n\t*graphql.RequestContext\n\t*executableSchema\n}\n\nfunc (ec *executionContext) introspectSchema() (*introspection.Schema, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapSchema(parsedSchema), nil\n}\n\nfunc (ec *executionContext) introspectType(name string) (*introspection.Type, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil\n}\n\nvar parsedSchema = gqlparser.MustLoadSchema(\n\t&ast.Source{Name: \"schema.graphql\", Input: `type Author {\n  name: String!\n}\n\ntype Book {\n  id: ID!\n  title: String!\n  price: Float!\n  author: Author\n}\n\ntype Query {\n  books: [Book!]!\n}\n`},\n)\n\n// endregion ************************** generated!.gotpl **************************\n\n// region    ***************************** args.gotpl *****************************\n\nfunc (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"name\"]; ok {\n\t\targ0, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"name\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\n// endregion ***************************** args.gotpl *****************************\n\n// region    ************************** directives.gotpl **************************\n\n// endregion ************************** directives.gotpl **************************\n\n// region    **************************** field.gotpl *****************************\n\nfunc (ec *executionContext) _Author_name(ctx context.Context, field graphql.CollectedField, obj *Author) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Author\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Book_id(ctx context.Context, field graphql.CollectedField, obj *Book) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Book\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.ID, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Book_title(ctx context.Context, field graphql.CollectedField, obj *Book) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Book\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Title, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Book_price(ctx context.Context, field graphql.CollectedField, obj *Book) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Book\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Price, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(float64)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNFloat2float64(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Book_author(ctx context.Context, field graphql.CollectedField, obj *Book) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Book\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Author, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*Author)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOAuthor2ᚖgithubᚗcomᚋgoᚑparkᚑmailᚑruᚋlecturesᚋ4ᚋ3_graphqlᚋgqlgenᚐAuthor(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_books(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Books(rctx)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Book)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNBook2ᚕᚖgithubᚗcomᚋgoᚑparkᚑmailᚑruᚋlecturesᚋ4ᚋ3_graphqlᚋgqlgenᚐBook(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query___type_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\trctx.Args = args\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectType(args[\"name\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectSchema()\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Schema)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Locations, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__DirectiveLocation2ᚕstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DefaultValue, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Types(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.QueryType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.MutationType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.SubscriptionType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Directives(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Directive)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Kind(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__TypeKind2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_fields_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\trctx.Args = args\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Fields(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Field)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Interfaces(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.PossibleTypes(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_enumValues_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\trctx.Args = args\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.EnumValues(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.EnumValue)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.InputFields(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.OfType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\n// endregion **************************** field.gotpl *****************************\n\n// region    **************************** input.gotpl *****************************\n\n// endregion **************************** input.gotpl *****************************\n\n// region    ************************** interface.gotpl ***************************\n\n// endregion ************************** interface.gotpl ***************************\n\n// region    **************************** object.gotpl ****************************\n\nvar authorImplementors = []string{\"Author\"}\n\nfunc (ec *executionContext) _Author(ctx context.Context, sel ast.SelectionSet, obj *Author) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, authorImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Author\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec._Author_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar bookImplementors = []string{\"Book\"}\n\nfunc (ec *executionContext) _Book(ctx context.Context, sel ast.SelectionSet, obj *Book) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, bookImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Book\")\n\t\tcase \"id\":\n\t\t\tout.Values[i] = ec._Book_id(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"title\":\n\t\t\tout.Values[i] = ec._Book_title(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"price\":\n\t\t\tout.Values[i] = ec._Book_price(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"author\":\n\t\t\tout.Values[i] = ec._Book_author(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar queryImplementors = []string{\"Query\"}\n\nfunc (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, queryImplementors)\n\n\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\tObject: \"Query\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Query\")\n\t\tcase \"books\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_books(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"__type\":\n\t\t\tout.Values[i] = ec._Query___type(ctx, field)\n\t\tcase \"__schema\":\n\t\t\tout.Values[i] = ec._Query___schema(ctx, field)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __DirectiveImplementors = []string{\"__Directive\"}\n\nfunc (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, __DirectiveImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Directive\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Directive_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Directive_description(ctx, field, obj)\n\t\tcase \"locations\":\n\t\t\tout.Values[i] = ec.___Directive_locations(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Directive_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __EnumValueImplementors = []string{\"__EnumValue\"}\n\nfunc (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, __EnumValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__EnumValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___EnumValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___EnumValue_description(ctx, field, obj)\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __FieldImplementors = []string{\"__Field\"}\n\nfunc (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, __FieldImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Field\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Field_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Field_description(ctx, field, obj)\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Field_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___Field_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___Field_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___Field_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __InputValueImplementors = []string{\"__InputValue\"}\n\nfunc (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, __InputValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__InputValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___InputValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___InputValue_description(ctx, field, obj)\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___InputValue_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"defaultValue\":\n\t\t\tout.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __SchemaImplementors = []string{\"__Schema\"}\n\nfunc (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, __SchemaImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Schema\")\n\t\tcase \"types\":\n\t\t\tout.Values[i] = ec.___Schema_types(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"queryType\":\n\t\t\tout.Values[i] = ec.___Schema_queryType(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"mutationType\":\n\t\t\tout.Values[i] = ec.___Schema_mutationType(ctx, field, obj)\n\t\tcase \"subscriptionType\":\n\t\t\tout.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj)\n\t\tcase \"directives\":\n\t\t\tout.Values[i] = ec.___Schema_directives(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __TypeImplementors = []string{\"__Type\"}\n\nfunc (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, __TypeImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Type\")\n\t\tcase \"kind\":\n\t\t\tout.Values[i] = ec.___Type_kind(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Type_name(ctx, field, obj)\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Type_description(ctx, field, obj)\n\t\tcase \"fields\":\n\t\t\tout.Values[i] = ec.___Type_fields(ctx, field, obj)\n\t\tcase \"interfaces\":\n\t\t\tout.Values[i] = ec.___Type_interfaces(ctx, field, obj)\n\t\tcase \"possibleTypes\":\n\t\t\tout.Values[i] = ec.___Type_possibleTypes(ctx, field, obj)\n\t\tcase \"enumValues\":\n\t\t\tout.Values[i] = ec.___Type_enumValues(ctx, field, obj)\n\t\tcase \"inputFields\":\n\t\t\tout.Values[i] = ec.___Type_inputFields(ctx, field, obj)\n\t\tcase \"ofType\":\n\t\t\tout.Values[i] = ec.___Type_ofType(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\n// endregion **************************** object.gotpl ****************************\n\n// region    ***************************** type.gotpl *****************************\n\nfunc (ec *executionContext) marshalNBook2githubᚗcomᚋgoᚑparkᚑmailᚑruᚋlecturesᚋ4ᚋ3_graphqlᚋgqlgenᚐBook(ctx context.Context, sel ast.SelectionSet, v Book) graphql.Marshaler {\n\treturn ec._Book(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNBook2ᚕᚖgithubᚗcomᚋgoᚑparkᚑmailᚑruᚋlecturesᚋ4ᚋ3_graphqlᚋgqlgenᚐBook(ctx context.Context, sel ast.SelectionSet, v []*Book) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalNBook2ᚖgithubᚗcomᚋgoᚑparkᚑmailᚑruᚋlecturesᚋ4ᚋ3_graphqlᚋgqlgenᚐBook(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalNBook2ᚖgithubᚗcomᚋgoᚑparkᚑmailᚑruᚋlecturesᚋ4ᚋ3_graphqlᚋgqlgenᚐBook(ctx context.Context, sel ast.SelectionSet, v *Book) graphql.Marshaler {\n\tif v == nil {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._Book(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\tres := graphql.MarshalBoolean(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNFloat2float64(ctx context.Context, v interface{}) (float64, error) {\n\treturn graphql.UnmarshalFloat(v)\n}\n\nfunc (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.SelectionSet, v float64) graphql.Marshaler {\n\tres := graphql.MarshalFloat(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalID(v)\n}\n\nfunc (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalID(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler {\n\treturn ec.___Directive(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstring(ctx context.Context, v interface{}) ([]string, error) {\n\tvar vSlice []interface{}\n\tif v != nil {\n\t\tif tmp1, ok := v.([]interface{}); ok {\n\t\t\tvSlice = tmp1\n\t\t} else {\n\t\t\tvSlice = []interface{}{v}\n\t\t}\n\t}\n\tvar err error\n\tres := make([]string, len(vSlice))\n\tfor i := range vSlice {\n\t\tres[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn res, nil\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2ᚕstring(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler {\n\treturn ec.___EnumValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler {\n\treturn ec.___Field(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler {\n\treturn ec.___InputValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalOAuthor2githubᚗcomᚋgoᚑparkᚑmailᚑruᚋlecturesᚋ4ᚋ3_graphqlᚋgqlgenᚐAuthor(ctx context.Context, sel ast.SelectionSet, v Author) graphql.Marshaler {\n\treturn ec._Author(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalOAuthor2ᚖgithubᚗcomᚋgoᚑparkᚑmailᚑruᚋlecturesᚋ4ᚋ3_graphqlᚋgqlgenᚐAuthor(ctx context.Context, sel ast.SelectionSet, v *Author) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec._Author(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\treturn graphql.MarshalBoolean(v)\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOBoolean2bool(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOBoolean2bool(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\treturn graphql.MarshalString(v)\n}\n\nfunc (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOString2string(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOString2string(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Schema2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v introspection.Schema) graphql.Marshaler {\n\treturn ec.___Schema(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Schema(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalO__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\n// endregion ***************************** type.gotpl *****************************\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen/gqlgen.yml",
    "content": "# .gqlgen.yml example\n#\n# Refer to https://gqlgen.com/config/\n# for detailed .gqlgen.yml documentation.\n\nschema:\n- schema.graphql\nexec:\n  filename: generated.go\nmodel:\n  filename: models_gen.go\nresolver:\n  filename: resolver.go\n  type: Resolver\nautobind: []\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen/models_gen.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen\n\ntype Author struct {\n\tName string `json:\"name\"`\n}\n\ntype Book struct {\n\tID     string  `json:\"id\"`\n\tTitle  string  `json:\"title\"`\n\tPrice  float64 `json:\"price\"`\n\tAuthor *Author `json:\"author\"`\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen/resolver.go",
    "content": "package gqlgen\n\nimport (\n\t\"context\"\n) // THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.\n\ntype Resolver struct{}\n\nfunc (r *Resolver) Query() QueryResolver {\n\treturn &queryResolver{r}\n}\n\ntype queryResolver struct{ *Resolver }\n\nfunc (r *queryResolver) Books(ctx context.Context) ([]*Book, error) {\n\treturn []*Book{\n\t\t{\n\t\t\tID:     \"1\",\n\t\t\tTitle:  \"The Moon is a harsh mistress\",\n\t\t\tPrice:  200,\n\t\t\tAuthor: &Author{Name: \"John\"},\n\t\t},\n\t}, nil\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen/schema.graphql",
    "content": "type Author {\n  name: String!\n}\n\ntype Book {\n  id: ID!\n  title: String!\n  price: Float!\n  author: Author\n}\n\ntype Query {\n  books: [Book!]!\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen/server/server.go",
    "content": "package main\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\n\tgql \"github.com/go-park-mail-ru/lectures/4-api/3_graphql/gqlgen\"\n\n\t\"github.com/99designs/gqlgen/handler\"\n)\n\nconst defaultPort = \"8080\"\n\nfunc main() {\n\tport := os.Getenv(\"PORT\")\n\tif port == \"\" {\n\t\tport = defaultPort\n\t}\n\n\thttp.Handle(\"/\", handler.Playground(\"GraphQL playground\", \"/query\"))\n\thttp.Handle(\"/query\", handler.GraphQL(gql.NewExecutableSchema(gql.Config{Resolvers: &gql.Resolver{}})))\n\n\tlog.Printf(\"connect to http://localhost:%s/ for GraphQL playground\", port)\n\tlog.Fatal(http.ListenAndServe(\":\"+port, nil))\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen1/generated.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen1\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"strconv\"\n\t\"sync\"\n\t\"sync/atomic\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\t\"github.com/99designs/gqlgen/graphql/introspection\"\n\tgqlparser \"github.com/vektah/gqlparser/v2\"\n\t\"github.com/vektah/gqlparser/v2/ast\"\n)\n\n// region    ************************** generated!.gotpl **************************\n\n// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.\nfunc NewExecutableSchema(cfg Config) graphql.ExecutableSchema {\n\treturn &executableSchema{\n\t\tresolvers:  cfg.Resolvers,\n\t\tdirectives: cfg.Directives,\n\t\tcomplexity: cfg.Complexity,\n\t}\n}\n\ntype Config struct {\n\tResolvers  ResolverRoot\n\tDirectives DirectiveRoot\n\tComplexity ComplexityRoot\n}\n\ntype ResolverRoot interface {\n\tMutation() MutationResolver\n\tQuery() QueryResolver\n}\n\ntype DirectiveRoot struct {\n}\n\ntype ComplexityRoot struct {\n\tMutation struct {\n\t\tRatePhoto func(childComplexity int, photoID string, direction string) int\n\t}\n\n\tPhoto struct {\n\t\tComment  func(childComplexity int) int\n\t\tFollowed func(childComplexity int) int\n\t\tID       func(childComplexity int) int\n\t\tLiked    func(childComplexity int) int\n\t\tRating   func(childComplexity int) int\n\t\tURL      func(childComplexity int) int\n\t\tUser     func(childComplexity int) int\n\t}\n\n\tQuery struct {\n\t\tPhotos   func(childComplexity int, userID string) int\n\t\tTimeline func(childComplexity int) int\n\t\tUser     func(childComplexity int, userID string) int\n\t}\n\n\tUser struct {\n\t\tAvatar func(childComplexity int) int\n\t\tID     func(childComplexity int) int\n\t\tName   func(childComplexity int) int\n\t}\n}\n\ntype MutationResolver interface {\n\tRatePhoto(ctx context.Context, photoID string, direction string) (*Photo, error)\n}\ntype QueryResolver interface {\n\tTimeline(ctx context.Context) ([]*Photo, error)\n\tUser(ctx context.Context, userID string) (*User, error)\n\tPhotos(ctx context.Context, userID string) ([]*Photo, error)\n}\n\ntype executableSchema struct {\n\tresolvers  ResolverRoot\n\tdirectives DirectiveRoot\n\tcomplexity ComplexityRoot\n}\n\nfunc (e *executableSchema) Schema() *ast.Schema {\n\treturn parsedSchema\n}\n\nfunc (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) {\n\tec := executionContext{nil, e}\n\t_ = ec\n\tswitch typeName + \".\" + field {\n\n\tcase \"Mutation.ratePhoto\":\n\t\tif e.complexity.Mutation.RatePhoto == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Mutation_ratePhoto_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Mutation.RatePhoto(childComplexity, args[\"photoID\"].(string), args[\"direction\"].(string)), true\n\n\tcase \"Photo.comment\":\n\t\tif e.complexity.Photo.Comment == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Comment(childComplexity), true\n\n\tcase \"Photo.followed\":\n\t\tif e.complexity.Photo.Followed == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Followed(childComplexity), true\n\n\tcase \"Photo.id\":\n\t\tif e.complexity.Photo.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.ID(childComplexity), true\n\n\tcase \"Photo.liked\":\n\t\tif e.complexity.Photo.Liked == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Liked(childComplexity), true\n\n\tcase \"Photo.rating\":\n\t\tif e.complexity.Photo.Rating == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Rating(childComplexity), true\n\n\tcase \"Photo.url\":\n\t\tif e.complexity.Photo.URL == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.URL(childComplexity), true\n\n\tcase \"Photo.user\":\n\t\tif e.complexity.Photo.User == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.User(childComplexity), true\n\n\tcase \"Query.photos\":\n\t\tif e.complexity.Query.Photos == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Query_photos_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Query.Photos(childComplexity, args[\"userID\"].(string)), true\n\n\tcase \"Query.timeline\":\n\t\tif e.complexity.Query.Timeline == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Query.Timeline(childComplexity), true\n\n\tcase \"Query.user\":\n\t\tif e.complexity.Query.User == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Query_user_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Query.User(childComplexity, args[\"userID\"].(string)), true\n\n\tcase \"User.avatar\":\n\t\tif e.complexity.User.Avatar == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Avatar(childComplexity), true\n\n\tcase \"User.id\":\n\t\tif e.complexity.User.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.ID(childComplexity), true\n\n\tcase \"User.name\":\n\t\tif e.complexity.User.Name == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Name(childComplexity), true\n\n\t}\n\treturn 0, false\n}\n\nfunc (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {\n\trc := graphql.GetOperationContext(ctx)\n\tec := executionContext{rc, e}\n\tfirst := true\n\n\tswitch rc.Operation.Operation {\n\tcase ast.Query:\n\t\treturn func(ctx context.Context) *graphql.Response {\n\t\t\tif !first {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tfirst = false\n\t\t\tdata := ec._Query(ctx, rc.Operation.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf.Bytes(),\n\t\t\t}\n\t\t}\n\tcase ast.Mutation:\n\t\treturn func(ctx context.Context) *graphql.Response {\n\t\t\tif !first {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tfirst = false\n\t\t\tdata := ec._Mutation(ctx, rc.Operation.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf.Bytes(),\n\t\t\t}\n\t\t}\n\n\tdefault:\n\t\treturn graphql.OneShot(graphql.ErrorResponse(ctx, \"unsupported GraphQL operation\"))\n\t}\n}\n\ntype executionContext struct {\n\t*graphql.OperationContext\n\t*executableSchema\n}\n\nfunc (ec *executionContext) introspectSchema() (*introspection.Schema, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapSchema(parsedSchema), nil\n}\n\nfunc (ec *executionContext) introspectType(name string) (*introspection.Type, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil\n}\n\nvar sources = []*ast.Source{\n\t&ast.Source{Name: \"schema.graphql\", Input: `type User {\n  id: ID!\n  name: String!\n  avatar: String!\n}\n\ntype Photo {\n  id: ID!\n  user: User!\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n  followed: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  user(userID: ID!): User!\n\n  # query{photos(userID:\"1\"){id,url,user{id,name}}}\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n}\n\n# go run github.com/99designs/gqlgen init\n# go run github.com/99designs/gqlgen -v\n\n# rm -rf generated.go models_generated gqlgen.yml models_gen.go resolver.go server.go`, BuiltIn: false},\n}\nvar parsedSchema = gqlparser.MustLoadSchema(sources...)\n\n// endregion ************************** generated!.gotpl **************************\n\n// region    ***************************** args.gotpl *****************************\n\nfunc (ec *executionContext) field_Mutation_ratePhoto_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"photoID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"photoID\"] = arg0\n\tvar arg1 string\n\tif tmp, ok := rawArgs[\"direction\"]; ok {\n\t\targ1, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"direction\"] = arg1\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"name\"]; ok {\n\t\targ0, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"name\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query_photos_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"userID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"userID\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"userID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"userID\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\n// endregion ***************************** args.gotpl *****************************\n\n// region    ************************** directives.gotpl **************************\n\n// endregion ************************** directives.gotpl **************************\n\n// region    **************************** field.gotpl *****************************\n\nfunc (ec *executionContext) _Mutation_ratePhoto(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Mutation\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Mutation_ratePhoto_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Mutation().RatePhoto(rctx, args[\"photoID\"].(string), args[\"direction\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚖgqlgen1ᚐPhoto(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_id(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.ID, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_user(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.User, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*User)\n\tfc.Result = res\n\treturn ec.marshalNUser2ᚖgqlgen1ᚐUser(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_url(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.URL, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_comment(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Comment, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_rating(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Rating, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(int)\n\tfc.Result = res\n\treturn ec.marshalNInt2int(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_liked(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Liked, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_followed(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Followed, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_timeline(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Timeline(rctx)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen1ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_user(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query_user_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().User(rctx, args[\"userID\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*User)\n\tfc.Result = res\n\treturn ec.marshalNUser2ᚖgqlgen1ᚐUser(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_photos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query_photos_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Photos(rctx, args[\"userID\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen1ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query___type_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectType(args[\"name\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectSchema()\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Schema)\n\tfc.Result = res\n\treturn ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.ID, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_name(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_avatar(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Avatar, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Locations, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]string)\n\tfc.Result = res\n\treturn ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DefaultValue, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Types(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.QueryType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.MutationType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.SubscriptionType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Directives(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Directive)\n\tfc.Result = res\n\treturn ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Kind(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalN__TypeKind2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_fields_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Fields(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Field)\n\tfc.Result = res\n\treturn ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Interfaces(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.PossibleTypes(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_enumValues_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.EnumValues(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.EnumValue)\n\tfc.Result = res\n\treturn ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.InputFields(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.OfType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\n// endregion **************************** field.gotpl *****************************\n\n// region    **************************** input.gotpl *****************************\n\n// endregion **************************** input.gotpl *****************************\n\n// region    ************************** interface.gotpl ***************************\n\n// endregion ************************** interface.gotpl ***************************\n\n// region    **************************** object.gotpl ****************************\n\nvar mutationImplementors = []string{\"Mutation\"}\n\nfunc (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors)\n\n\tctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{\n\t\tObject: \"Mutation\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Mutation\")\n\t\tcase \"ratePhoto\":\n\t\t\tout.Values[i] = ec._Mutation_ratePhoto(ctx, field)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar photoImplementors = []string{\"Photo\"}\n\nfunc (ec *executionContext) _Photo(ctx context.Context, sel ast.SelectionSet, obj *Photo) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, photoImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Photo\")\n\t\tcase \"id\":\n\t\t\tout.Values[i] = ec._Photo_id(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"user\":\n\t\t\tout.Values[i] = ec._Photo_user(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"url\":\n\t\t\tout.Values[i] = ec._Photo_url(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"comment\":\n\t\t\tout.Values[i] = ec._Photo_comment(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"rating\":\n\t\t\tout.Values[i] = ec._Photo_rating(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"liked\":\n\t\t\tout.Values[i] = ec._Photo_liked(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"followed\":\n\t\t\tout.Values[i] = ec._Photo_followed(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar queryImplementors = []string{\"Query\"}\n\nfunc (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, queryImplementors)\n\n\tctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{\n\t\tObject: \"Query\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Query\")\n\t\tcase \"timeline\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_timeline(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"user\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_user(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"photos\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_photos(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"__type\":\n\t\t\tout.Values[i] = ec._Query___type(ctx, field)\n\t\tcase \"__schema\":\n\t\t\tout.Values[i] = ec._Query___schema(ctx, field)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar userImplementors = []string{\"User\"}\n\nfunc (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *User) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, userImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"User\")\n\t\tcase \"id\":\n\t\t\tout.Values[i] = ec._User_id(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec._User_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"avatar\":\n\t\t\tout.Values[i] = ec._User_avatar(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __DirectiveImplementors = []string{\"__Directive\"}\n\nfunc (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __DirectiveImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Directive\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Directive_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Directive_description(ctx, field, obj)\n\t\tcase \"locations\":\n\t\t\tout.Values[i] = ec.___Directive_locations(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Directive_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __EnumValueImplementors = []string{\"__EnumValue\"}\n\nfunc (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__EnumValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___EnumValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___EnumValue_description(ctx, field, obj)\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __FieldImplementors = []string{\"__Field\"}\n\nfunc (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __FieldImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Field\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Field_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Field_description(ctx, field, obj)\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Field_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___Field_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___Field_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___Field_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __InputValueImplementors = []string{\"__InputValue\"}\n\nfunc (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __InputValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__InputValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___InputValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___InputValue_description(ctx, field, obj)\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___InputValue_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"defaultValue\":\n\t\t\tout.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __SchemaImplementors = []string{\"__Schema\"}\n\nfunc (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __SchemaImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Schema\")\n\t\tcase \"types\":\n\t\t\tout.Values[i] = ec.___Schema_types(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"queryType\":\n\t\t\tout.Values[i] = ec.___Schema_queryType(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"mutationType\":\n\t\t\tout.Values[i] = ec.___Schema_mutationType(ctx, field, obj)\n\t\tcase \"subscriptionType\":\n\t\t\tout.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj)\n\t\tcase \"directives\":\n\t\t\tout.Values[i] = ec.___Schema_directives(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __TypeImplementors = []string{\"__Type\"}\n\nfunc (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Type\")\n\t\tcase \"kind\":\n\t\t\tout.Values[i] = ec.___Type_kind(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Type_name(ctx, field, obj)\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Type_description(ctx, field, obj)\n\t\tcase \"fields\":\n\t\t\tout.Values[i] = ec.___Type_fields(ctx, field, obj)\n\t\tcase \"interfaces\":\n\t\t\tout.Values[i] = ec.___Type_interfaces(ctx, field, obj)\n\t\tcase \"possibleTypes\":\n\t\t\tout.Values[i] = ec.___Type_possibleTypes(ctx, field, obj)\n\t\tcase \"enumValues\":\n\t\t\tout.Values[i] = ec.___Type_enumValues(ctx, field, obj)\n\t\tcase \"inputFields\":\n\t\t\tout.Values[i] = ec.___Type_inputFields(ctx, field, obj)\n\t\tcase \"ofType\":\n\t\t\tout.Values[i] = ec.___Type_ofType(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\n// endregion **************************** object.gotpl ****************************\n\n// region    ***************************** type.gotpl *****************************\n\nfunc (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\tres := graphql.MarshalBoolean(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalID(v)\n}\n\nfunc (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalID(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) {\n\treturn graphql.UnmarshalInt(v)\n}\n\nfunc (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler {\n\tres := graphql.MarshalInt(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalNPhoto2gqlgen1ᚐPhoto(ctx context.Context, sel ast.SelectionSet, v Photo) graphql.Marshaler {\n\treturn ec._Photo(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNPhoto2ᚕᚖgqlgen1ᚐPhotoᚄ(ctx context.Context, sel ast.SelectionSet, v []*Photo) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalNPhoto2ᚖgqlgen1ᚐPhoto(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalNPhoto2ᚖgqlgen1ᚐPhoto(ctx context.Context, sel ast.SelectionSet, v *Photo) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._Photo(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalNUser2gqlgen1ᚐUser(ctx context.Context, sel ast.SelectionSet, v User) graphql.Marshaler {\n\treturn ec._User(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNUser2ᚖgqlgen1ᚐUser(ctx context.Context, sel ast.SelectionSet, v *User) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._User(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler {\n\treturn ec.___Directive(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) {\n\tvar vSlice []interface{}\n\tif v != nil {\n\t\tif tmp1, ok := v.([]interface{}); ok {\n\t\t\tvSlice = tmp1\n\t\t} else {\n\t\t\tvSlice = []interface{}{v}\n\t\t}\n\t}\n\tvar err error\n\tres := make([]string, len(vSlice))\n\tfor i := range vSlice {\n\t\tres[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn res, nil\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler {\n\treturn ec.___EnumValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler {\n\treturn ec.___Field(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler {\n\treturn ec.___InputValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\treturn graphql.MarshalBoolean(v)\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOBoolean2bool(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOBoolean2bool(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\treturn graphql.MarshalString(v)\n}\n\nfunc (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOString2string(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOString2string(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Schema2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v introspection.Schema) graphql.Marshaler {\n\treturn ec.___Schema(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Schema(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalO__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\n// endregion ***************************** type.gotpl *****************************\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen1/go.mod",
    "content": "module gqlgen1\n\ngo 1.13\n\nrequire (\n\tgithub.com/99designs/gqlgen v0.11.1\n\tgithub.com/vektah/gqlparser v1.3.1\n\tgithub.com/vektah/gqlparser/v2 v2.0.1\n)\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen1/go.sum",
    "content": "github.com/99designs/gqlgen v0.11.1 h1:QoSL8/AAJ2T3UOeQbdnBR32JcG4pO08+P/g5jdbFkUg=\ngithub.com/99designs/gqlgen v0.11.1/go.mod h1:vjFOyBZ7NwDl+GdSD4PFn7BQn5Fy7ohJwXn7Vk8zz+c=\ngithub.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=\ngithub.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=\ngithub.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=\ngithub.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=\ngithub.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=\ngithub.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=\ngithub.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=\ngithub.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=\ngithub.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=\ngithub.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=\ngithub.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=\ngithub.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=\ngithub.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=\ngithub.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=\ngithub.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=\ngithub.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=\ngithub.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8=\ngithub.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=\ngithub.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=\ngithub.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=\ngithub.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=\ngithub.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=\ngithub.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=\ngithub.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=\ngithub.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=\ngithub.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=\ngithub.com/vektah/gqlparser v1.3.1 h1:8b0IcD3qZKWJQHSzynbDlrtP3IxVydZ2DZepCGofqfU=\ngithub.com/vektah/gqlparser v1.3.1/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74=\ngithub.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o=\ngithub.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM=\ngolang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=\ngopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\nsourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=\nsourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen1/gqlgen.yml",
    "content": "# .gqlgen.yml example\n#\n# Refer to https://gqlgen.com/config/\n# for detailed .gqlgen.yml documentation.\n\nschema:\n- schema.graphql\nexec:\n  filename: generated.go\nmodel:\n  filename: models_gen.go\nresolver:\n  filename: resolver.go\n  type: Resolver\nautobind: []\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen1/models_gen.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen1\n\ntype Photo struct {\n\tID       string `json:\"id\"`\n\tUser     *User  `json:\"user\"`\n\tURL      string `json:\"url\"`\n\tComment  string `json:\"comment\"`\n\tRating   int    `json:\"rating\"`\n\tLiked    bool   `json:\"liked\"`\n\tFollowed bool   `json:\"followed\"`\n}\n\ntype User struct {\n\tID     string `json:\"id\"`\n\tName   string `json:\"name\"`\n\tAvatar string `json:\"avatar\"`\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen1/resolver.go",
    "content": "package gqlgen1\n\nimport (\n\t\"context\"\n) // THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.\n\ntype Resolver struct{}\n\nfunc (r *Resolver) Mutation() MutationResolver {\n\treturn &mutationResolver{r}\n}\nfunc (r *Resolver) Query() QueryResolver {\n\treturn &queryResolver{r}\n}\n\ntype mutationResolver struct{ *Resolver }\n\nfunc (r *mutationResolver) RatePhoto(ctx context.Context, photoID string, direction string) (*Photo, error) {\n\tpanic(\"not implemented\")\n}\n\ntype queryResolver struct{ *Resolver }\n\nfunc (r *queryResolver) Timeline(ctx context.Context) ([]*Photo, error) {\n\tpanic(\"not implemented\")\n}\nfunc (r *queryResolver) User(ctx context.Context, userID string) (*User, error) {\n\tpanic(\"not implemented\")\n}\nfunc (r *queryResolver) Photos(ctx context.Context, userID string) ([]*Photo, error) {\n\tpanic(\"not implemented\")\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen1/schema.graphql",
    "content": "type User {\n  id: ID!\n  name: String!\n  avatar: String!\n}\n\ntype Photo {\n  id: ID!\n  user: User!\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n  followed: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  user(userID: ID!): User!\n\n  # query{photos(userID:\"1\"){id,url,user{id,name}}}\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n}\n\n# go run github.com/99designs/gqlgen init\n# go run github.com/99designs/gqlgen -v\n\n# rm -rf generated.go models_generated gqlgen.yml models_gen.go resolver.go server.go"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen1/server/server.go",
    "content": "package main\n\nimport (\n\tgqlgen \"gqlgen1\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/99designs/gqlgen/handler\"\n)\n\nconst defaultPort = \"8080\"\n\nfunc main() {\n\tport := os.Getenv(\"PORT\")\n\tif port == \"\" {\n\t\tport = defaultPort\n\t}\n\n\thttp.Handle(\"/\", handler.Playground(\"GraphQL playground\", \"/query\"))\n\thttp.Handle(\"/query\", handler.GraphQL(gqlgen.NewExecutableSchema(gqlgen.Config{Resolvers: &gqlgen.Resolver{}})))\n\n\tlog.Printf(\"connect to http://localhost:%s/ for GraphQL playground\", port)\n\tlog.Fatal(http.ListenAndServe(\":\"+port, nil))\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen2/generated.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen2\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"strconv\"\n\t\"sync\"\n\t\"sync/atomic\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\t\"github.com/99designs/gqlgen/graphql/introspection\"\n\tgqlparser \"github.com/vektah/gqlparser/v2\"\n\t\"github.com/vektah/gqlparser/v2/ast\"\n)\n\n// region    ************************** generated!.gotpl **************************\n\n// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.\nfunc NewExecutableSchema(cfg Config) graphql.ExecutableSchema {\n\treturn &executableSchema{\n\t\tresolvers:  cfg.Resolvers,\n\t\tdirectives: cfg.Directives,\n\t\tcomplexity: cfg.Complexity,\n\t}\n}\n\ntype Config struct {\n\tResolvers  ResolverRoot\n\tDirectives DirectiveRoot\n\tComplexity ComplexityRoot\n}\n\ntype ResolverRoot interface {\n\tMutation() MutationResolver\n\tPhoto() PhotoResolver\n\tQuery() QueryResolver\n}\n\ntype DirectiveRoot struct {\n}\n\ntype ComplexityRoot struct {\n\tMutation struct {\n\t\tRatePhoto func(childComplexity int, photoID string, direction string) int\n\t}\n\n\tPhoto struct {\n\t\tComment  func(childComplexity int) int\n\t\tFollowed func(childComplexity int) int\n\t\tID       func(childComplexity int) int\n\t\tLiked    func(childComplexity int) int\n\t\tRating   func(childComplexity int) int\n\t\tURL      func(childComplexity int) int\n\t\tUser     func(childComplexity int) int\n\t}\n\n\tQuery struct {\n\t\tPhotos   func(childComplexity int, userID string) int\n\t\tTimeline func(childComplexity int) int\n\t\tUser     func(childComplexity int, userID string) int\n\t}\n\n\tUser struct {\n\t\tAvatar func(childComplexity int) int\n\t\tID     func(childComplexity int) int\n\t\tName   func(childComplexity int) int\n\t}\n}\n\ntype MutationResolver interface {\n\tRatePhoto(ctx context.Context, photoID string, direction string) (*Photo, error)\n}\ntype PhotoResolver interface {\n\tID(ctx context.Context, obj *Photo) (string, error)\n\tUser(ctx context.Context, obj *Photo) (*User, error)\n}\ntype QueryResolver interface {\n\tTimeline(ctx context.Context) ([]*Photo, error)\n\tUser(ctx context.Context, userID string) (*User, error)\n\tPhotos(ctx context.Context, userID string) ([]*Photo, error)\n}\n\ntype executableSchema struct {\n\tresolvers  ResolverRoot\n\tdirectives DirectiveRoot\n\tcomplexity ComplexityRoot\n}\n\nfunc (e *executableSchema) Schema() *ast.Schema {\n\treturn parsedSchema\n}\n\nfunc (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) {\n\tec := executionContext{nil, e}\n\t_ = ec\n\tswitch typeName + \".\" + field {\n\n\tcase \"Mutation.ratePhoto\":\n\t\tif e.complexity.Mutation.RatePhoto == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Mutation_ratePhoto_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Mutation.RatePhoto(childComplexity, args[\"photoID\"].(string), args[\"direction\"].(string)), true\n\n\tcase \"Photo.comment\":\n\t\tif e.complexity.Photo.Comment == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Comment(childComplexity), true\n\n\tcase \"Photo.followed\":\n\t\tif e.complexity.Photo.Followed == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Followed(childComplexity), true\n\n\tcase \"Photo.id\":\n\t\tif e.complexity.Photo.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.ID(childComplexity), true\n\n\tcase \"Photo.liked\":\n\t\tif e.complexity.Photo.Liked == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Liked(childComplexity), true\n\n\tcase \"Photo.rating\":\n\t\tif e.complexity.Photo.Rating == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Rating(childComplexity), true\n\n\tcase \"Photo.url\":\n\t\tif e.complexity.Photo.URL == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.URL(childComplexity), true\n\n\tcase \"Photo.user\":\n\t\tif e.complexity.Photo.User == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.User(childComplexity), true\n\n\tcase \"Query.photos\":\n\t\tif e.complexity.Query.Photos == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Query_photos_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Query.Photos(childComplexity, args[\"userID\"].(string)), true\n\n\tcase \"Query.timeline\":\n\t\tif e.complexity.Query.Timeline == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Query.Timeline(childComplexity), true\n\n\tcase \"Query.user\":\n\t\tif e.complexity.Query.User == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Query_user_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Query.User(childComplexity, args[\"userID\"].(string)), true\n\n\tcase \"User.avatar\":\n\t\tif e.complexity.User.Avatar == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Avatar(childComplexity), true\n\n\tcase \"User.id\":\n\t\tif e.complexity.User.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.ID(childComplexity), true\n\n\tcase \"User.name\":\n\t\tif e.complexity.User.Name == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Name(childComplexity), true\n\n\t}\n\treturn 0, false\n}\n\nfunc (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {\n\trc := graphql.GetOperationContext(ctx)\n\tec := executionContext{rc, e}\n\tfirst := true\n\n\tswitch rc.Operation.Operation {\n\tcase ast.Query:\n\t\treturn func(ctx context.Context) *graphql.Response {\n\t\t\tif !first {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tfirst = false\n\t\t\tdata := ec._Query(ctx, rc.Operation.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf.Bytes(),\n\t\t\t}\n\t\t}\n\tcase ast.Mutation:\n\t\treturn func(ctx context.Context) *graphql.Response {\n\t\t\tif !first {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tfirst = false\n\t\t\tdata := ec._Mutation(ctx, rc.Operation.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf.Bytes(),\n\t\t\t}\n\t\t}\n\n\tdefault:\n\t\treturn graphql.OneShot(graphql.ErrorResponse(ctx, \"unsupported GraphQL operation\"))\n\t}\n}\n\ntype executionContext struct {\n\t*graphql.OperationContext\n\t*executableSchema\n}\n\nfunc (ec *executionContext) introspectSchema() (*introspection.Schema, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapSchema(parsedSchema), nil\n}\n\nfunc (ec *executionContext) introspectType(name string) (*introspection.Type, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil\n}\n\nvar sources = []*ast.Source{\n\t&ast.Source{Name: \"schema.graphql\", Input: `type User {\n  id: ID!\n  name: String!\n  avatar: String!\n}\n\ntype Photo {\n  id: ID!\n  user: User!\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n  followed: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,url,user{id,name}}}\n  user(userID: ID!): User!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n}\n\n# go run github.com/99designs/gqlgen init\n# go run github.com/99designs/gqlgen -v\n`, BuiltIn: false},\n}\nvar parsedSchema = gqlparser.MustLoadSchema(sources...)\n\n// endregion ************************** generated!.gotpl **************************\n\n// region    ***************************** args.gotpl *****************************\n\nfunc (ec *executionContext) field_Mutation_ratePhoto_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"photoID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"photoID\"] = arg0\n\tvar arg1 string\n\tif tmp, ok := rawArgs[\"direction\"]; ok {\n\t\targ1, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"direction\"] = arg1\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"name\"]; ok {\n\t\targ0, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"name\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query_photos_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"userID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"userID\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"userID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"userID\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\n// endregion ***************************** args.gotpl *****************************\n\n// region    ************************** directives.gotpl **************************\n\n// endregion ************************** directives.gotpl **************************\n\n// region    **************************** field.gotpl *****************************\n\nfunc (ec *executionContext) _Mutation_ratePhoto(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Mutation\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Mutation_ratePhoto_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Mutation().RatePhoto(rctx, args[\"photoID\"].(string), args[\"direction\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚖgqlgen2ᚐPhoto(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_id(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Photo().ID(rctx, obj)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_user(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Photo().User(rctx, obj)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*User)\n\tfc.Result = res\n\treturn ec.marshalNUser2ᚖgqlgen2ᚐUser(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_url(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.URL, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_comment(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Comment, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_rating(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Rating, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(int)\n\tfc.Result = res\n\treturn ec.marshalNInt2int(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_liked(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Liked, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_followed(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Followed, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_timeline(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Timeline(rctx)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen2ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_user(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query_user_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().User(rctx, args[\"userID\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*User)\n\tfc.Result = res\n\treturn ec.marshalNUser2ᚖgqlgen2ᚐUser(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_photos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query_photos_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Photos(rctx, args[\"userID\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen2ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query___type_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectType(args[\"name\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectSchema()\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Schema)\n\tfc.Result = res\n\treturn ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.ID, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_name(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_avatar(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Avatar, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Locations, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]string)\n\tfc.Result = res\n\treturn ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DefaultValue, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Types(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.QueryType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.MutationType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.SubscriptionType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Directives(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Directive)\n\tfc.Result = res\n\treturn ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Kind(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalN__TypeKind2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_fields_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Fields(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Field)\n\tfc.Result = res\n\treturn ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Interfaces(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.PossibleTypes(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_enumValues_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.EnumValues(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.EnumValue)\n\tfc.Result = res\n\treturn ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.InputFields(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.OfType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\n// endregion **************************** field.gotpl *****************************\n\n// region    **************************** input.gotpl *****************************\n\n// endregion **************************** input.gotpl *****************************\n\n// region    ************************** interface.gotpl ***************************\n\n// endregion ************************** interface.gotpl ***************************\n\n// region    **************************** object.gotpl ****************************\n\nvar mutationImplementors = []string{\"Mutation\"}\n\nfunc (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors)\n\n\tctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{\n\t\tObject: \"Mutation\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Mutation\")\n\t\tcase \"ratePhoto\":\n\t\t\tout.Values[i] = ec._Mutation_ratePhoto(ctx, field)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar photoImplementors = []string{\"Photo\"}\n\nfunc (ec *executionContext) _Photo(ctx context.Context, sel ast.SelectionSet, obj *Photo) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, photoImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Photo\")\n\t\tcase \"id\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Photo_id(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"user\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Photo_user(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"url\":\n\t\t\tout.Values[i] = ec._Photo_url(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"comment\":\n\t\t\tout.Values[i] = ec._Photo_comment(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"rating\":\n\t\t\tout.Values[i] = ec._Photo_rating(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"liked\":\n\t\t\tout.Values[i] = ec._Photo_liked(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"followed\":\n\t\t\tout.Values[i] = ec._Photo_followed(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar queryImplementors = []string{\"Query\"}\n\nfunc (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, queryImplementors)\n\n\tctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{\n\t\tObject: \"Query\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Query\")\n\t\tcase \"timeline\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_timeline(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"user\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_user(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"photos\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_photos(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"__type\":\n\t\t\tout.Values[i] = ec._Query___type(ctx, field)\n\t\tcase \"__schema\":\n\t\t\tout.Values[i] = ec._Query___schema(ctx, field)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar userImplementors = []string{\"User\"}\n\nfunc (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *User) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, userImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"User\")\n\t\tcase \"id\":\n\t\t\tout.Values[i] = ec._User_id(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec._User_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"avatar\":\n\t\t\tout.Values[i] = ec._User_avatar(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __DirectiveImplementors = []string{\"__Directive\"}\n\nfunc (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __DirectiveImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Directive\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Directive_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Directive_description(ctx, field, obj)\n\t\tcase \"locations\":\n\t\t\tout.Values[i] = ec.___Directive_locations(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Directive_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __EnumValueImplementors = []string{\"__EnumValue\"}\n\nfunc (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__EnumValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___EnumValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___EnumValue_description(ctx, field, obj)\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __FieldImplementors = []string{\"__Field\"}\n\nfunc (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __FieldImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Field\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Field_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Field_description(ctx, field, obj)\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Field_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___Field_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___Field_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___Field_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __InputValueImplementors = []string{\"__InputValue\"}\n\nfunc (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __InputValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__InputValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___InputValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___InputValue_description(ctx, field, obj)\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___InputValue_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"defaultValue\":\n\t\t\tout.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __SchemaImplementors = []string{\"__Schema\"}\n\nfunc (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __SchemaImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Schema\")\n\t\tcase \"types\":\n\t\t\tout.Values[i] = ec.___Schema_types(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"queryType\":\n\t\t\tout.Values[i] = ec.___Schema_queryType(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"mutationType\":\n\t\t\tout.Values[i] = ec.___Schema_mutationType(ctx, field, obj)\n\t\tcase \"subscriptionType\":\n\t\t\tout.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj)\n\t\tcase \"directives\":\n\t\t\tout.Values[i] = ec.___Schema_directives(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __TypeImplementors = []string{\"__Type\"}\n\nfunc (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Type\")\n\t\tcase \"kind\":\n\t\t\tout.Values[i] = ec.___Type_kind(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Type_name(ctx, field, obj)\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Type_description(ctx, field, obj)\n\t\tcase \"fields\":\n\t\t\tout.Values[i] = ec.___Type_fields(ctx, field, obj)\n\t\tcase \"interfaces\":\n\t\t\tout.Values[i] = ec.___Type_interfaces(ctx, field, obj)\n\t\tcase \"possibleTypes\":\n\t\t\tout.Values[i] = ec.___Type_possibleTypes(ctx, field, obj)\n\t\tcase \"enumValues\":\n\t\t\tout.Values[i] = ec.___Type_enumValues(ctx, field, obj)\n\t\tcase \"inputFields\":\n\t\t\tout.Values[i] = ec.___Type_inputFields(ctx, field, obj)\n\t\tcase \"ofType\":\n\t\t\tout.Values[i] = ec.___Type_ofType(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\n// endregion **************************** object.gotpl ****************************\n\n// region    ***************************** type.gotpl *****************************\n\nfunc (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\tres := graphql.MarshalBoolean(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalID(v)\n}\n\nfunc (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalID(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) {\n\treturn graphql.UnmarshalInt(v)\n}\n\nfunc (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler {\n\tres := graphql.MarshalInt(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalNPhoto2gqlgen2ᚐPhoto(ctx context.Context, sel ast.SelectionSet, v Photo) graphql.Marshaler {\n\treturn ec._Photo(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNPhoto2ᚕᚖgqlgen2ᚐPhotoᚄ(ctx context.Context, sel ast.SelectionSet, v []*Photo) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalNPhoto2ᚖgqlgen2ᚐPhoto(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalNPhoto2ᚖgqlgen2ᚐPhoto(ctx context.Context, sel ast.SelectionSet, v *Photo) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._Photo(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalNUser2gqlgen2ᚐUser(ctx context.Context, sel ast.SelectionSet, v User) graphql.Marshaler {\n\treturn ec._User(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNUser2ᚖgqlgen2ᚐUser(ctx context.Context, sel ast.SelectionSet, v *User) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._User(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler {\n\treturn ec.___Directive(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) {\n\tvar vSlice []interface{}\n\tif v != nil {\n\t\tif tmp1, ok := v.([]interface{}); ok {\n\t\t\tvSlice = tmp1\n\t\t} else {\n\t\t\tvSlice = []interface{}{v}\n\t\t}\n\t}\n\tvar err error\n\tres := make([]string, len(vSlice))\n\tfor i := range vSlice {\n\t\tres[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn res, nil\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler {\n\treturn ec.___EnumValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler {\n\treturn ec.___Field(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler {\n\treturn ec.___InputValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\treturn graphql.MarshalBoolean(v)\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOBoolean2bool(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOBoolean2bool(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\treturn graphql.MarshalString(v)\n}\n\nfunc (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOString2string(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOString2string(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Schema2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v introspection.Schema) graphql.Marshaler {\n\treturn ec.___Schema(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Schema(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalO__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\n// endregion ***************************** type.gotpl *****************************\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen2/go.mod",
    "content": "module gqlgen2\n\ngo 1.13\n\nrequire (\n\tgithub.com/99designs/gqlgen v0.11.1\n\tgithub.com/vektah/gqlparser/v2 v2.0.1\n)\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen2/go.sum",
    "content": "github.com/99designs/gqlgen v0.11.1 h1:QoSL8/AAJ2T3UOeQbdnBR32JcG4pO08+P/g5jdbFkUg=\ngithub.com/99designs/gqlgen v0.11.1/go.mod h1:vjFOyBZ7NwDl+GdSD4PFn7BQn5Fy7ohJwXn7Vk8zz+c=\ngithub.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=\ngithub.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=\ngithub.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=\ngithub.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=\ngithub.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=\ngithub.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=\ngithub.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=\ngithub.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=\ngithub.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=\ngithub.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=\ngithub.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=\ngithub.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=\ngithub.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=\ngithub.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=\ngithub.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=\ngithub.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=\ngithub.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8=\ngithub.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=\ngithub.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=\ngithub.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=\ngithub.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=\ngithub.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=\ngithub.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=\ngithub.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=\ngithub.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=\ngithub.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o=\ngithub.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM=\ngolang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=\ngopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\nsourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=\nsourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen2/gqlgen.yml",
    "content": "# .gqlgen.yml example\n#\n# Refer to https://gqlgen.com/config/\n# for detailed .gqlgen.yml documentation.\n\nschema:\n- schema.graphql\nexec:\n  filename: generated.go\nmodel:\n  filename: models_gen.go\nresolver:\n  filename: resolver.go\n  type: Resolver\n\nmodels:\n  Photo:\n    model: gqlgen2.Photo\n    fields:\n      user:\n        resolver: true\n\nautobind: []\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen2/models_gen.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen2\n\ntype User struct {\n\tID     string `json:\"id\"`\n\tName   string `json:\"name\"`\n\tAvatar string `json:\"avatar\"`\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen2/photo.go",
    "content": "package gqlgen2\n\nimport (\n\t\"log\"\n\t\"strconv\"\n)\n\ntype Photo struct {\n\tID     uint `json:\"id\"`\n\tUserID uint `json:\"-\"`\n\t// User     *User  `json:\"user\"`\n\tURL      string `json:\"url\"`\n\tComment  string `json:\"comment\"`\n\tRating   int    `json:\"rating\"`\n\tLiked    bool   `json:\"liked\"`\n\tFollowed bool   `json:\"followed\"`\n}\n\nfunc (ph *Photo) Id() string {\n\tlog.Println(\"call Photo.Id method\", ph.ID)\n\treturn strconv.Itoa(int(ph.ID))\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen2/resolver.go",
    "content": "package gqlgen2\n\n//go:generate go run github.com/99designs/gqlgen\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"strconv\"\n) // THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.\n\ntype Resolver struct {\n\tPhotosData map[string]*Photo\n\tUsers      map[uint]*User\n}\n\nfunc (r *Resolver) Mutation() MutationResolver {\n\treturn &mutationResolver{r}\n}\nfunc (r *Resolver) Photo() PhotoResolver {\n\treturn &photoResolver{r}\n}\nfunc (r *Resolver) Query() QueryResolver {\n\treturn &queryResolver{r}\n}\n\ntype mutationResolver struct{ *Resolver }\n\nfunc (r *mutationResolver) RatePhoto(ctx context.Context, id string, direction string) (*Photo, error) {\n\tlog.Println(\"call mutationResolver.RatePhoto method with id\", id, direction)\n\trate := 1\n\tif direction != \"up\" {\n\t\trate = -1\n\t}\n\tph, ok := r.PhotosData[id]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no photo %v found\", id)\n\t}\n\tph.Rating += rate\n\treturn ph, nil\n}\n\ntype photoResolver struct{ *Resolver }\n\nfunc (r *photoResolver) ID(ctx context.Context, obj *Photo) (string, error) {\n\treturn obj.Id(), nil\n}\n\nfunc (r *photoResolver) User(ctx context.Context, obj *Photo) (*User, error) {\n\t// log.Println(\"call photoResolver.User\", obj.UserID)\n\tlog.Printf(\"photoResolver.User: SELECT id, name FROM user WHERE ID = %d\\n\", obj.UserID)\n\treturn r.Users[obj.UserID], nil\n}\n\ntype queryResolver struct{ *Resolver }\n\nfunc (r *queryResolver) Timeline(ctx context.Context) ([]*Photo, error) {\n\tlog.Println(\"call queryResolver.Timeline with ctx.userID\", ctx.Value(\"userID\"))\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n\nfunc (r *queryResolver) User(ctx context.Context, userID string) (*User, error) {\n\tlog.Println(\"call queryResolver.User for\", userID)\n\tid, _ := strconv.Atoi(userID)\n\treturn r.Users[uint(id)], nil\n}\n\nfunc (r *queryResolver) Photos(ctx context.Context, userID string) ([]*Photo, error) {\n\tlog.Println(\"call queryResolver.Photos\")\n\tid, _ := strconv.Atoi(userID)\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\tif ph.UserID != uint(id) {\n\t\t\tcontinue\n\t\t}\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen2/schema.graphql",
    "content": "type User {\n  id: ID!\n  name: String!\n  avatar: String!\n}\n\ntype Photo {\n  id: ID!\n  user: User!\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n  followed: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,url,user{id,name}}}\n  user(userID: ID!): User!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n}\n\n# go run github.com/99designs/gqlgen init\n# go run github.com/99designs/gqlgen -v\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen2/schema_alt.graphql",
    "content": "directive @goModel(model: String, models: [String!]) on OBJECT \n    | INPUT_OBJECT \n    | SCALAR \n    | ENUM \n    | INTERFACE \n    | UNION\n\ndirective @goField(forceResolver: Boolean, name: String) on INPUT_FIELD_DEFINITION \n    | FIELD_DEFINITION\n\ntype User {\n  id: ID!\n  name: String!\n  avatar: String\n}\n\ntype Photo @goModel(model:\"coursera/3p/graphql/gqlgen2.Photo\") {\n  id: ID!\n  user: User! @goField(forceResolver: true)\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n  followed: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,url,user{id,name}}}\n  user(userID: ID!): User!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen2/server/server.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\tgqlgen \"gqlgen2\"\n\t\"log\"\n\t\"net/http\"\n\n\t\"github.com/99designs/gqlgen/handler\"\n)\n\n/*\nquery{timeline{id,url,user{id,name}}}\nquery{user(userID:\"1\"){id,avatar, name}}\nmutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n*/\n\nvar users = map[uint]*gqlgen.User{\n\t1: {\n\t\tID:     \"1\",\n\t\tName:   \"rvasily\",\n\t\tAvatar: \"https://via.placeholder.com/150\",\n\t},\n\t2: {\n\t\tID:     \"2\",\n\t\tName:   \"v.romanov\",\n\t\tAvatar: \"https://via.placeholder.com/150\",\n\t},\n}\n\nvar photos = map[string]*gqlgen.Photo{\n\t\"1\": {\n\t\tID:       1,\n\t\tUserID:   1,\n\t\tURL:      \"https://via.placeholder.com/300\",\n\t\tComment:  \"fromn studio\",\n\t\tRating:   1,\n\t\tLiked:    true,\n\t\tFollowed: false,\n\t},\n\t\"2\": {\n\t\tID:       2,\n\t\tUserID:   1,\n\t\tURL:      \"https://via.placeholder.com/300\",\n\t\tComment:  \"cool view\",\n\t\tRating:   0,\n\t\tLiked:    false,\n\t\tFollowed: false,\n\t},\n\t\"3\": {\n\t\tID:       3,\n\t\tUserID:   2,\n\t\tURL:      \"https://via.placeholder.com/300\",\n\t\tComment:  \"at work\",\n\t\tRating:   0,\n\t\tLiked:    false,\n\t\tFollowed: false,\n\t},\n}\n\nfunc AuthMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tlog.Println(\"new request\")\n\t\tctx := context.WithValue(r.Context(), \"userID\", 1)\n\t\tr = r.WithContext(ctx)\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n\nfunc main() {\n\thttp.Handle(\"/\", handler.Playground(\"GraphQL playground\", \"/query\"))\n\n\tcfg := gqlgen.Config{\n\t\tResolvers: &gqlgen.Resolver{\n\t\t\tUsers:      users,\n\t\t\tPhotosData: photos,\n\t\t},\n\t}\n\tgqlHandler := handler.GraphQL(gqlgen.NewExecutableSchema(cfg))\n\thandler := AuthMiddleware(gqlHandler)\n\thttp.Handle(\"/query\", handler)\n\n\tport := \"8080\"\n\tlog.Printf(\"connect to http://localhost:%s/ for GraphQL playground\", port)\n\tlog.Fatal(http.ListenAndServe(\":\"+port, nil))\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen3/generated.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen3\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"strconv\"\n\t\"sync\"\n\t\"sync/atomic\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\t\"github.com/99designs/gqlgen/graphql/introspection\"\n\tgqlparser \"github.com/vektah/gqlparser/v2\"\n\t\"github.com/vektah/gqlparser/v2/ast\"\n)\n\n// region    ************************** generated!.gotpl **************************\n\n// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.\nfunc NewExecutableSchema(cfg Config) graphql.ExecutableSchema {\n\treturn &executableSchema{\n\t\tresolvers:  cfg.Resolvers,\n\t\tdirectives: cfg.Directives,\n\t\tcomplexity: cfg.Complexity,\n\t}\n}\n\ntype Config struct {\n\tResolvers  ResolverRoot\n\tDirectives DirectiveRoot\n\tComplexity ComplexityRoot\n}\n\ntype ResolverRoot interface {\n\tMutation() MutationResolver\n\tPhoto() PhotoResolver\n\tQuery() QueryResolver\n}\n\ntype DirectiveRoot struct {\n}\n\ntype ComplexityRoot struct {\n\tMutation struct {\n\t\tRatePhoto func(childComplexity int, photoID string, direction string) int\n\t}\n\n\tPhoto struct {\n\t\tComment func(childComplexity int) int\n\t\tID      func(childComplexity int) int\n\t\tLiked   func(childComplexity int) int\n\t\tRating  func(childComplexity int) int\n\t\tURL     func(childComplexity int) int\n\t\tUser    func(childComplexity int) int\n\t}\n\n\tQuery struct {\n\t\tPhotos   func(childComplexity int, userID string) int\n\t\tTimeline func(childComplexity int) int\n\t\tUser     func(childComplexity int, userID string) int\n\t}\n\n\tUser struct {\n\t\tAvatar   func(childComplexity int) int\n\t\tFollowed func(childComplexity int) int\n\t\tID       func(childComplexity int) int\n\t\tName     func(childComplexity int) int\n\t}\n}\n\ntype MutationResolver interface {\n\tRatePhoto(ctx context.Context, photoID string, direction string) (*Photo, error)\n}\ntype PhotoResolver interface {\n\tID(ctx context.Context, obj *Photo) (string, error)\n\tUser(ctx context.Context, obj *Photo) (*User, error)\n}\ntype QueryResolver interface {\n\tTimeline(ctx context.Context) ([]*Photo, error)\n\tUser(ctx context.Context, userID string) (*User, error)\n\tPhotos(ctx context.Context, userID string) ([]*Photo, error)\n}\n\ntype executableSchema struct {\n\tresolvers  ResolverRoot\n\tdirectives DirectiveRoot\n\tcomplexity ComplexityRoot\n}\n\nfunc (e *executableSchema) Schema() *ast.Schema {\n\treturn parsedSchema\n}\n\nfunc (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) {\n\tec := executionContext{nil, e}\n\t_ = ec\n\tswitch typeName + \".\" + field {\n\n\tcase \"Mutation.ratePhoto\":\n\t\tif e.complexity.Mutation.RatePhoto == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Mutation_ratePhoto_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Mutation.RatePhoto(childComplexity, args[\"photoID\"].(string), args[\"direction\"].(string)), true\n\n\tcase \"Photo.comment\":\n\t\tif e.complexity.Photo.Comment == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Comment(childComplexity), true\n\n\tcase \"Photo.id\":\n\t\tif e.complexity.Photo.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.ID(childComplexity), true\n\n\tcase \"Photo.liked\":\n\t\tif e.complexity.Photo.Liked == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Liked(childComplexity), true\n\n\tcase \"Photo.rating\":\n\t\tif e.complexity.Photo.Rating == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Rating(childComplexity), true\n\n\tcase \"Photo.url\":\n\t\tif e.complexity.Photo.URL == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.URL(childComplexity), true\n\n\tcase \"Photo.user\":\n\t\tif e.complexity.Photo.User == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.User(childComplexity), true\n\n\tcase \"Query.photos\":\n\t\tif e.complexity.Query.Photos == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Query_photos_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Query.Photos(childComplexity, args[\"userID\"].(string)), true\n\n\tcase \"Query.timeline\":\n\t\tif e.complexity.Query.Timeline == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Query.Timeline(childComplexity), true\n\n\tcase \"Query.user\":\n\t\tif e.complexity.Query.User == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Query_user_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Query.User(childComplexity, args[\"userID\"].(string)), true\n\n\tcase \"User.avatar\":\n\t\tif e.complexity.User.Avatar == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Avatar(childComplexity), true\n\n\tcase \"User.followed\":\n\t\tif e.complexity.User.Followed == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Followed(childComplexity), true\n\n\tcase \"User.id\":\n\t\tif e.complexity.User.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.ID(childComplexity), true\n\n\tcase \"User.name\":\n\t\tif e.complexity.User.Name == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Name(childComplexity), true\n\n\t}\n\treturn 0, false\n}\n\nfunc (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {\n\trc := graphql.GetOperationContext(ctx)\n\tec := executionContext{rc, e}\n\tfirst := true\n\n\tswitch rc.Operation.Operation {\n\tcase ast.Query:\n\t\treturn func(ctx context.Context) *graphql.Response {\n\t\t\tif !first {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tfirst = false\n\t\t\tdata := ec._Query(ctx, rc.Operation.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf.Bytes(),\n\t\t\t}\n\t\t}\n\tcase ast.Mutation:\n\t\treturn func(ctx context.Context) *graphql.Response {\n\t\t\tif !first {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tfirst = false\n\t\t\tdata := ec._Mutation(ctx, rc.Operation.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf.Bytes(),\n\t\t\t}\n\t\t}\n\n\tdefault:\n\t\treturn graphql.OneShot(graphql.ErrorResponse(ctx, \"unsupported GraphQL operation\"))\n\t}\n}\n\ntype executionContext struct {\n\t*graphql.OperationContext\n\t*executableSchema\n}\n\nfunc (ec *executionContext) introspectSchema() (*introspection.Schema, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapSchema(parsedSchema), nil\n}\n\nfunc (ec *executionContext) introspectType(name string) (*introspection.Type, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil\n}\n\nvar sources = []*ast.Source{\n\t&ast.Source{Name: \"schema.graphql\", Input: `type User {\n  id: ID!\n  name: String!\n  avatar: String!\n  followed: Boolean!\n}\n\ntype Photo {\n  id: ID!\n  user: User!\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,url,user{id,name}}}\n  user(userID: ID!): User!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n}\n\n# go run github.com/99designs/gqlgen init\n# go run github.com/99designs/gqlgen -v\n`, BuiltIn: false},\n}\nvar parsedSchema = gqlparser.MustLoadSchema(sources...)\n\n// endregion ************************** generated!.gotpl **************************\n\n// region    ***************************** args.gotpl *****************************\n\nfunc (ec *executionContext) field_Mutation_ratePhoto_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"photoID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"photoID\"] = arg0\n\tvar arg1 string\n\tif tmp, ok := rawArgs[\"direction\"]; ok {\n\t\targ1, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"direction\"] = arg1\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"name\"]; ok {\n\t\targ0, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"name\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query_photos_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"userID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"userID\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"userID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"userID\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\n// endregion ***************************** args.gotpl *****************************\n\n// region    ************************** directives.gotpl **************************\n\n// endregion ************************** directives.gotpl **************************\n\n// region    **************************** field.gotpl *****************************\n\nfunc (ec *executionContext) _Mutation_ratePhoto(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Mutation\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Mutation_ratePhoto_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Mutation().RatePhoto(rctx, args[\"photoID\"].(string), args[\"direction\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚖgqlgen3ᚐPhoto(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_id(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Photo().ID(rctx, obj)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_user(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Photo().User(rctx, obj)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*User)\n\tfc.Result = res\n\treturn ec.marshalNUser2ᚖgqlgen3ᚐUser(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_url(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.URL, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_comment(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Comment, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_rating(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Rating, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(int)\n\tfc.Result = res\n\treturn ec.marshalNInt2int(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_liked(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Liked, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_timeline(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Timeline(rctx)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen3ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_user(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query_user_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().User(rctx, args[\"userID\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*User)\n\tfc.Result = res\n\treturn ec.marshalNUser2ᚖgqlgen3ᚐUser(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_photos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query_photos_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Photos(rctx, args[\"userID\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen3ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query___type_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectType(args[\"name\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectSchema()\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Schema)\n\tfc.Result = res\n\treturn ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.ID, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_name(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_avatar(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Avatar, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_followed(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Followed, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Locations, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]string)\n\tfc.Result = res\n\treturn ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DefaultValue, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Types(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.QueryType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.MutationType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.SubscriptionType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Directives(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Directive)\n\tfc.Result = res\n\treturn ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Kind(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalN__TypeKind2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_fields_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Fields(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Field)\n\tfc.Result = res\n\treturn ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Interfaces(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.PossibleTypes(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_enumValues_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.EnumValues(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.EnumValue)\n\tfc.Result = res\n\treturn ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.InputFields(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.OfType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\n// endregion **************************** field.gotpl *****************************\n\n// region    **************************** input.gotpl *****************************\n\n// endregion **************************** input.gotpl *****************************\n\n// region    ************************** interface.gotpl ***************************\n\n// endregion ************************** interface.gotpl ***************************\n\n// region    **************************** object.gotpl ****************************\n\nvar mutationImplementors = []string{\"Mutation\"}\n\nfunc (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors)\n\n\tctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{\n\t\tObject: \"Mutation\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Mutation\")\n\t\tcase \"ratePhoto\":\n\t\t\tout.Values[i] = ec._Mutation_ratePhoto(ctx, field)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar photoImplementors = []string{\"Photo\"}\n\nfunc (ec *executionContext) _Photo(ctx context.Context, sel ast.SelectionSet, obj *Photo) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, photoImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Photo\")\n\t\tcase \"id\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Photo_id(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"user\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Photo_user(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"url\":\n\t\t\tout.Values[i] = ec._Photo_url(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"comment\":\n\t\t\tout.Values[i] = ec._Photo_comment(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"rating\":\n\t\t\tout.Values[i] = ec._Photo_rating(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"liked\":\n\t\t\tout.Values[i] = ec._Photo_liked(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar queryImplementors = []string{\"Query\"}\n\nfunc (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, queryImplementors)\n\n\tctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{\n\t\tObject: \"Query\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Query\")\n\t\tcase \"timeline\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_timeline(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"user\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_user(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"photos\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_photos(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"__type\":\n\t\t\tout.Values[i] = ec._Query___type(ctx, field)\n\t\tcase \"__schema\":\n\t\t\tout.Values[i] = ec._Query___schema(ctx, field)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar userImplementors = []string{\"User\"}\n\nfunc (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *User) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, userImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"User\")\n\t\tcase \"id\":\n\t\t\tout.Values[i] = ec._User_id(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec._User_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"avatar\":\n\t\t\tout.Values[i] = ec._User_avatar(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"followed\":\n\t\t\tout.Values[i] = ec._User_followed(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __DirectiveImplementors = []string{\"__Directive\"}\n\nfunc (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __DirectiveImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Directive\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Directive_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Directive_description(ctx, field, obj)\n\t\tcase \"locations\":\n\t\t\tout.Values[i] = ec.___Directive_locations(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Directive_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __EnumValueImplementors = []string{\"__EnumValue\"}\n\nfunc (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__EnumValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___EnumValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___EnumValue_description(ctx, field, obj)\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __FieldImplementors = []string{\"__Field\"}\n\nfunc (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __FieldImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Field\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Field_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Field_description(ctx, field, obj)\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Field_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___Field_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___Field_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___Field_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __InputValueImplementors = []string{\"__InputValue\"}\n\nfunc (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __InputValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__InputValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___InputValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___InputValue_description(ctx, field, obj)\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___InputValue_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"defaultValue\":\n\t\t\tout.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __SchemaImplementors = []string{\"__Schema\"}\n\nfunc (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __SchemaImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Schema\")\n\t\tcase \"types\":\n\t\t\tout.Values[i] = ec.___Schema_types(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"queryType\":\n\t\t\tout.Values[i] = ec.___Schema_queryType(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"mutationType\":\n\t\t\tout.Values[i] = ec.___Schema_mutationType(ctx, field, obj)\n\t\tcase \"subscriptionType\":\n\t\t\tout.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj)\n\t\tcase \"directives\":\n\t\t\tout.Values[i] = ec.___Schema_directives(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __TypeImplementors = []string{\"__Type\"}\n\nfunc (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Type\")\n\t\tcase \"kind\":\n\t\t\tout.Values[i] = ec.___Type_kind(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Type_name(ctx, field, obj)\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Type_description(ctx, field, obj)\n\t\tcase \"fields\":\n\t\t\tout.Values[i] = ec.___Type_fields(ctx, field, obj)\n\t\tcase \"interfaces\":\n\t\t\tout.Values[i] = ec.___Type_interfaces(ctx, field, obj)\n\t\tcase \"possibleTypes\":\n\t\t\tout.Values[i] = ec.___Type_possibleTypes(ctx, field, obj)\n\t\tcase \"enumValues\":\n\t\t\tout.Values[i] = ec.___Type_enumValues(ctx, field, obj)\n\t\tcase \"inputFields\":\n\t\t\tout.Values[i] = ec.___Type_inputFields(ctx, field, obj)\n\t\tcase \"ofType\":\n\t\t\tout.Values[i] = ec.___Type_ofType(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\n// endregion **************************** object.gotpl ****************************\n\n// region    ***************************** type.gotpl *****************************\n\nfunc (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\tres := graphql.MarshalBoolean(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalID(v)\n}\n\nfunc (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalID(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) {\n\treturn graphql.UnmarshalInt(v)\n}\n\nfunc (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler {\n\tres := graphql.MarshalInt(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalNPhoto2gqlgen3ᚐPhoto(ctx context.Context, sel ast.SelectionSet, v Photo) graphql.Marshaler {\n\treturn ec._Photo(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNPhoto2ᚕᚖgqlgen3ᚐPhotoᚄ(ctx context.Context, sel ast.SelectionSet, v []*Photo) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalNPhoto2ᚖgqlgen3ᚐPhoto(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalNPhoto2ᚖgqlgen3ᚐPhoto(ctx context.Context, sel ast.SelectionSet, v *Photo) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._Photo(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalNUser2gqlgen3ᚐUser(ctx context.Context, sel ast.SelectionSet, v User) graphql.Marshaler {\n\treturn ec._User(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNUser2ᚖgqlgen3ᚐUser(ctx context.Context, sel ast.SelectionSet, v *User) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._User(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler {\n\treturn ec.___Directive(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) {\n\tvar vSlice []interface{}\n\tif v != nil {\n\t\tif tmp1, ok := v.([]interface{}); ok {\n\t\t\tvSlice = tmp1\n\t\t} else {\n\t\t\tvSlice = []interface{}{v}\n\t\t}\n\t}\n\tvar err error\n\tres := make([]string, len(vSlice))\n\tfor i := range vSlice {\n\t\tres[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn res, nil\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler {\n\treturn ec.___EnumValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler {\n\treturn ec.___Field(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler {\n\treturn ec.___InputValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\treturn graphql.MarshalBoolean(v)\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOBoolean2bool(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOBoolean2bool(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\treturn graphql.MarshalString(v)\n}\n\nfunc (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOString2string(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOString2string(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Schema2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v introspection.Schema) graphql.Marshaler {\n\treturn ec.___Schema(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Schema(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalO__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\n// endregion ***************************** type.gotpl *****************************\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen3/go.mod",
    "content": "module gqlgen3\n\ngo 1.13\n\nrequire (\n\tgithub.com/99designs/gqlgen v0.11.1\n\tgithub.com/vektah/gqlparser/v2 v2.0.1\n)\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen3/go.sum",
    "content": "github.com/99designs/gqlgen v0.11.1 h1:QoSL8/AAJ2T3UOeQbdnBR32JcG4pO08+P/g5jdbFkUg=\ngithub.com/99designs/gqlgen v0.11.1/go.mod h1:vjFOyBZ7NwDl+GdSD4PFn7BQn5Fy7ohJwXn7Vk8zz+c=\ngithub.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=\ngithub.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=\ngithub.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=\ngithub.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=\ngithub.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=\ngithub.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=\ngithub.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=\ngithub.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=\ngithub.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=\ngithub.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=\ngithub.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=\ngithub.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=\ngithub.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=\ngithub.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=\ngithub.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=\ngithub.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=\ngithub.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8=\ngithub.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=\ngithub.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=\ngithub.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=\ngithub.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=\ngithub.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=\ngithub.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=\ngithub.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=\ngithub.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=\ngithub.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o=\ngithub.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM=\ngolang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=\ngopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\nsourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=\nsourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen3/gqlgen.yml",
    "content": "# .gqlgen.yml example\n#\n# Refer to https://gqlgen.com/config/\n# for detailed .gqlgen.yml documentation.\n\nschema:\n- schema.graphql\nexec:\n  filename: generated.go\nmodel:\n  filename: models_gen.go\nresolver:\n  filename: resolver.go\n  type: Resolver\n\nmodels:\n  Photo:\n    model: gqlgen3.Photo\n    fields:\n      user:\n        resolver: true\n\nautobind: []\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen3/models_gen.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen3\n\ntype User struct {\n\tID       string `json:\"id\"`\n\tName     string `json:\"name\"`\n\tAvatar   string `json:\"avatar\"`\n\tFollowed bool   `json:\"followed\"`\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen3/photo.go",
    "content": "package gqlgen3\n\nimport (\n\t// \"log\"\n\t\"strconv\"\n)\n\ntype Photo struct {\n\tID     uint `json:\"id\"`\n\tUserID uint `json:\"-\"`\n\t// User     *User  `json:\"user\"`\n\tURL     string `json:\"url\"`\n\tComment string `json:\"comment\"`\n\tRating  int    `json:\"rating\"`\n\tLiked   bool   `json:\"liked\"`\n}\n\nfunc (ph *Photo) Id() string {\n\t// log.Println(\"call Photo.Id method\", ph.ID)\n\treturn strconv.Itoa(int(ph.ID))\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen3/resolver.go",
    "content": "package gqlgen3\n\n//go:generate go run github.com/99designs/gqlgen\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"strconv\"\n\t\"time\"\n) // THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.\n\ntype Resolver struct {\n\tPhotosData map[string]*Photo\n\tUsers      map[uint]*User\n}\n\nfunc (r *Resolver) Mutation() MutationResolver {\n\treturn &mutationResolver{r}\n}\nfunc (r *Resolver) Photo() PhotoResolver {\n\treturn &photoResolver{r}\n}\nfunc (r *Resolver) Query() QueryResolver {\n\treturn &queryResolver{r}\n}\n\ntype mutationResolver struct{ *Resolver }\n\nfunc (r *mutationResolver) RatePhoto(ctx context.Context, id string, direction string) (*Photo, error) {\n\tlog.Println(\"call mutationResolver.RatePhoto method with id\", id, direction)\n\trate := 1\n\tif direction != \"up\" {\n\t\trate = -1\n\t}\n\tph, ok := r.PhotosData[id]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no photo %v found\", id)\n\t}\n\tph.Rating += rate\n\treturn ph, nil\n}\n\ntype photoResolver struct{ *Resolver }\n\nfunc (r *photoResolver) ID(ctx context.Context, obj *Photo) (string, error) {\n\treturn obj.Id(), nil\n}\n\nfunc (r *photoResolver) User(ctx context.Context, obj *Photo) (*User, error) {\n\t// return r.Users[obj.UserID], nil\n\tlog.Println(\"call photoResolver.User\", obj.UserID)\n\tstart := time.Now()\n\tuser, err := ctx.Value(\"userLoaderKey\").(*UserLoader).Load(obj.UserID)\n\tlog.Println(\"get photoResolver.User\", obj.UserID, \"from UserLoader, time \", time.Since(start))\n\treturn user, err\n}\n\ntype queryResolver struct{ *Resolver }\n\nfunc (r *queryResolver) Timeline(ctx context.Context) ([]*Photo, error) {\n\tlog.Println(\"call queryResolver.Timeline with ctx.userID\", ctx.Value(\"userID\"))\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n\nfunc (r *queryResolver) User(ctx context.Context, userID string) (*User, error) {\n\tlog.Println(\"call queryResolver.User for\", userID)\n\tid, _ := strconv.Atoi(userID)\n\treturn r.Users[uint(id)], nil\n}\n\nfunc (r *queryResolver) Photos(ctx context.Context, userID string) ([]*Photo, error) {\n\tlog.Println(\"call queryResolver.Photos\")\n\tid, _ := strconv.Atoi(userID)\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\tif ph.UserID != uint(id) {\n\t\t\tcontinue\n\t\t}\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen3/schema.graphql",
    "content": "type User {\n  id: ID!\n  name: String!\n  avatar: String!\n  followed: Boolean!\n}\n\ntype Photo {\n  id: ID!\n  user: User!\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,url,user{id,name}}}\n  user(userID: ID!): User!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n}\n\n# go run github.com/99designs/gqlgen init\n# go run github.com/99designs/gqlgen -v\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen3/schema_alt.graphql",
    "content": "directive @goModel(model: String, models: [String!]) on OBJECT \n    | INPUT_OBJECT \n    | SCALAR \n    | ENUM \n    | INTERFACE \n    | UNION\n\ndirective @goField(forceResolver: Boolean, name: String) on INPUT_FIELD_DEFINITION \n    | FIELD_DEFINITION\n\ntype User {\n  id: ID!\n  name: String!\n  avatar: String\n  followed: Boolean!\n}\n\ntype Photo @goModel(model:\"coursera/3p/graphql/gqlgen3.Photo\") {\n  id: ID!\n  user: User! @goField(forceResolver: true)\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,url,user{id,name}}}\n  user(userID: ID!): User!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen3/server/server.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\tgqlgen \"gqlgen3\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/99designs/gqlgen/handler\"\n)\n\n/*\nquery{timeline{id,url,user{id,name}}}\nquery{user(userID:\"1\"){id,avatar, name}}\nmutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n*/\n\nvar users = map[uint]*gqlgen.User{\n\t1: {\n\t\tID:     \"1\",\n\t\tName:   \"rvasily\",\n\t\tAvatar: \"https://via.placeholder.com/150\",\n\t},\n\t2: {\n\t\tID:     \"2\",\n\t\tName:   \"v.romanov\",\n\t\tAvatar: \"https://via.placeholder.com/150\",\n\t},\n}\n\nvar photos = map[string]*gqlgen.Photo{\n\t\"1\": {\n\t\tID:      1,\n\t\tUserID:  1,\n\t\tURL:     \"https://via.placeholder.com/300\",\n\t\tComment: \"fromn studio\",\n\t\tRating:  1,\n\t\tLiked:   true,\n\t},\n\t\"2\": {\n\t\tID:      2,\n\t\tUserID:  1,\n\t\tURL:     \"https://via.placeholder.com/300\",\n\t\tComment: \"cool view\",\n\t\tRating:  0,\n\t\tLiked:   false,\n\t},\n\t\"3\": {\n\t\tID:      3,\n\t\tUserID:  2,\n\t\tURL:     \"https://via.placeholder.com/300\",\n\t\tComment: \"at work\",\n\t\tRating:  0,\n\t\tLiked:   false,\n\t},\n}\n\n// go run github.com/vektah/dataloaden UserLoader uint *coursera/3p/graphql/gqlgen3.User\n\nfunc UserLoaderMiddleware(resolver *gqlgen.Resolver, next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tcfg := gqlgen.UserLoaderConfig{\n\t\t\tMaxBatch: 100,\n\t\t\tWait:     1 * time.Millisecond,\n\t\t\tFetch: func(ids []uint) ([]*gqlgen.User, []error) {\n\t\t\t\t// имеем доступ до r *http.Request - там context с сессией пользователя\n\t\t\t\tsessionUserID := r.Context().Value(\"userID\").(uint)\n\t\t\t\tlog.Printf(\"UserLoader Request - ids %v for user %v\\n\", ids, sessionUserID)\n\n\t\t\t\tlog.Println(\"\\n\\tSELECT id, name FROM user WHERE id IN (1,2)\")\n\t\t\t\tlog.Println(`\n\tSELECT id, name, user_follows.follow_id FROM users\n\tLEFT JOIN user_follows ON user_follows.follow_id=photos.user_id AND user_follows.user_id = ?\n\tWHERE users.id IN (1,2)`)\n\n\t\t\t\tusers := make([]*gqlgen.User, len(ids))\n\t\t\t\tfor i, id := range ids {\n\t\t\t\t\t// имеем доступ до resolver *gqlgen.Resolver - там коннет к базе\n\t\t\t\t\tusers[i] = resolver.Users[id]\n\t\t\t\t}\n\t\t\t\treturn users, nil\n\t\t\t},\n\t\t}\n\t\tuserLoader := gqlgen.NewUserLoader(cfg)\n\t\tctx := context.WithValue(r.Context(), \"userLoaderKey\", userLoader)\n\t\tr = r.WithContext(ctx)\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n\nfunc AuthMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t// log.Println(\"new request\")\n\t\tctx := context.WithValue(r.Context(), \"userID\", uint(1))\n\t\tr = r.WithContext(ctx)\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n\nfunc main() {\n\thttp.Handle(\"/\", handler.Playground(\"GraphQL playground\", \"/query\"))\n\n\tresolver := &gqlgen.Resolver{\n\t\tUsers:      users,\n\t\tPhotosData: photos,\n\t}\n\tcfg := gqlgen.Config{\n\t\tResolvers: resolver,\n\t}\n\tgqlHandler := handler.GraphQL(gqlgen.NewExecutableSchema(cfg))\n\thandler := UserLoaderMiddleware(resolver, gqlHandler)\n\thandler = AuthMiddleware(handler)\n\thttp.Handle(\"/query\", handler)\n\n\tport := \"8080\"\n\tlog.Printf(\"connect to http://localhost:%s/ for GraphQL playground\", port)\n\tlog.Fatal(http.ListenAndServe(\":\"+port, nil))\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen3/userloader_gen.go",
    "content": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage gqlgen3\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\n// UserLoaderConfig captures the config to create a new UserLoader\ntype UserLoaderConfig struct {\n\t// Fetch is a method that provides the data for the loader\n\tFetch func(keys []uint) ([]*User, []error)\n\n\t// Wait is how long wait before sending a batch\n\tWait time.Duration\n\n\t// MaxBatch will limit the maximum number of keys to send in one batch, 0 = not limit\n\tMaxBatch int\n}\n\n// NewUserLoader creates a new UserLoader given a fetch, wait, and maxBatch\nfunc NewUserLoader(config UserLoaderConfig) *UserLoader {\n\treturn &UserLoader{\n\t\tfetch:    config.Fetch,\n\t\twait:     config.Wait,\n\t\tmaxBatch: config.MaxBatch,\n\t}\n}\n\n// UserLoader batches and caches requests\ntype UserLoader struct {\n\t// this method provides the data for the loader\n\tfetch func(keys []uint) ([]*User, []error)\n\n\t// how long to done before sending a batch\n\twait time.Duration\n\n\t// this will limit the maximum number of keys to send in one batch, 0 = no limit\n\tmaxBatch int\n\n\t// INTERNAL\n\n\t// lazily created cache\n\tcache map[uint]*User\n\n\t// the current batch. keys will continue to be collected until timeout is hit,\n\t// then everything will be sent to the fetch method and out to the listeners\n\tbatch *userLoaderBatch\n\n\t// mutex to prevent races\n\tmu sync.Mutex\n}\n\ntype userLoaderBatch struct {\n\tkeys    []uint\n\tdata    []*User\n\terror   []error\n\tclosing bool\n\tdone    chan struct{}\n}\n\n// Load a User by key, batching and caching will be applied automatically\nfunc (l *UserLoader) Load(key uint) (*User, error) {\n\treturn l.LoadThunk(key)()\n}\n\n// LoadThunk returns a function that when called will block waiting for a User.\n// This method should be used if you want one goroutine to make requests to many\n// different data loaders without blocking until the thunk is called.\nfunc (l *UserLoader) LoadThunk(key uint) func() (*User, error) {\n\tl.mu.Lock()\n\tif it, ok := l.cache[key]; ok {\n\t\tl.mu.Unlock()\n\t\treturn func() (*User, error) {\n\t\t\treturn it, nil\n\t\t}\n\t}\n\tif l.batch == nil {\n\t\tl.batch = &userLoaderBatch{done: make(chan struct{})}\n\t}\n\tbatch := l.batch\n\tpos := batch.keyIndex(l, key)\n\tl.mu.Unlock()\n\n\treturn func() (*User, error) {\n\t\t<-batch.done\n\n\t\tvar data *User\n\t\tif pos < len(batch.data) {\n\t\t\tdata = batch.data[pos]\n\t\t}\n\n\t\tvar err error\n\t\t// its convenient to be able to return a single error for everything\n\t\tif len(batch.error) == 1 {\n\t\t\terr = batch.error[0]\n\t\t} else if batch.error != nil {\n\t\t\terr = batch.error[pos]\n\t\t}\n\n\t\tif err == nil {\n\t\t\tl.mu.Lock()\n\t\t\tl.unsafeSet(key, data)\n\t\t\tl.mu.Unlock()\n\t\t}\n\n\t\treturn data, err\n\t}\n}\n\n// LoadAll fetches many keys at once. It will be broken into appropriate sized\n// sub batches depending on how the loader is configured\nfunc (l *UserLoader) LoadAll(keys []uint) ([]*User, []error) {\n\tresults := make([]func() (*User, error), len(keys))\n\n\tfor i, key := range keys {\n\t\tresults[i] = l.LoadThunk(key)\n\t}\n\n\tusers := make([]*User, len(keys))\n\terrors := make([]error, len(keys))\n\tfor i, thunk := range results {\n\t\tusers[i], errors[i] = thunk()\n\t}\n\treturn users, errors\n}\n\n// LoadAllThunk returns a function that when called will block waiting for a Users.\n// This method should be used if you want one goroutine to make requests to many\n// different data loaders without blocking until the thunk is called.\nfunc (l *UserLoader) LoadAllThunk(keys []uint) func() ([]*User, []error) {\n\tresults := make([]func() (*User, error), len(keys))\n\tfor i, key := range keys {\n\t\tresults[i] = l.LoadThunk(key)\n\t}\n\treturn func() ([]*User, []error) {\n\t\tusers := make([]*User, len(keys))\n\t\terrors := make([]error, len(keys))\n\t\tfor i, thunk := range results {\n\t\t\tusers[i], errors[i] = thunk()\n\t\t}\n\t\treturn users, errors\n\t}\n}\n\n// Prime the cache with the provided key and value. If the key already exists, no change is made\n// and false is returned.\n// (To forcefully prime the cache, clear the key first with loader.clear(key).prime(key, value).)\nfunc (l *UserLoader) Prime(key uint, value *User) bool {\n\tl.mu.Lock()\n\tvar found bool\n\tif _, found = l.cache[key]; !found {\n\t\t// make a copy when writing to the cache, its easy to pass a pointer in from a loop var\n\t\t// and end up with the whole cache pointing to the same value.\n\t\tcpy := *value\n\t\tl.unsafeSet(key, &cpy)\n\t}\n\tl.mu.Unlock()\n\treturn !found\n}\n\n// Clear the value at key from the cache, if it exists\nfunc (l *UserLoader) Clear(key uint) {\n\tl.mu.Lock()\n\tdelete(l.cache, key)\n\tl.mu.Unlock()\n}\n\nfunc (l *UserLoader) unsafeSet(key uint, value *User) {\n\tif l.cache == nil {\n\t\tl.cache = map[uint]*User{}\n\t}\n\tl.cache[key] = value\n}\n\n// keyIndex will return the location of the key in the batch, if its not found\n// it will add the key to the batch\nfunc (b *userLoaderBatch) keyIndex(l *UserLoader, key uint) int {\n\tfor i, existingKey := range b.keys {\n\t\tif key == existingKey {\n\t\t\treturn i\n\t\t}\n\t}\n\n\tpos := len(b.keys)\n\tb.keys = append(b.keys, key)\n\tif pos == 0 {\n\t\tgo b.startTimer(l)\n\t}\n\n\tif l.maxBatch != 0 && pos >= l.maxBatch-1 {\n\t\tif !b.closing {\n\t\t\tb.closing = true\n\t\t\tl.batch = nil\n\t\t\tgo b.end(l)\n\t\t}\n\t}\n\n\treturn pos\n}\n\nfunc (b *userLoaderBatch) startTimer(l *UserLoader) {\n\ttime.Sleep(l.wait)\n\tl.mu.Lock()\n\n\t// we must have hit a batch limit and are already finalizing this batch\n\tif b.closing {\n\t\tl.mu.Unlock()\n\t\treturn\n\t}\n\n\tl.batch = nil\n\tl.mu.Unlock()\n\n\tb.end(l)\n}\n\nfunc (b *userLoaderBatch) end(l *UserLoader) {\n\tb.data, b.error = l.fetch(b.keys)\n\tclose(b.done)\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen4/generated.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen4\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"strconv\"\n\t\"sync\"\n\t\"sync/atomic\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\t\"github.com/99designs/gqlgen/graphql/introspection\"\n\tgqlparser \"github.com/vektah/gqlparser/v2\"\n\t\"github.com/vektah/gqlparser/v2/ast\"\n)\n\n// region    ************************** generated!.gotpl **************************\n\n// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.\nfunc NewExecutableSchema(cfg Config) graphql.ExecutableSchema {\n\treturn &executableSchema{\n\t\tresolvers:  cfg.Resolvers,\n\t\tdirectives: cfg.Directives,\n\t\tcomplexity: cfg.Complexity,\n\t}\n}\n\ntype Config struct {\n\tResolvers  ResolverRoot\n\tDirectives DirectiveRoot\n\tComplexity ComplexityRoot\n}\n\ntype ResolverRoot interface {\n\tMutation() MutationResolver\n\tPhoto() PhotoResolver\n\tQuery() QueryResolver\n\tUser() UserResolver\n}\n\ntype DirectiveRoot struct {\n}\n\ntype ComplexityRoot struct {\n\tMutation struct {\n\t\tRatePhoto func(childComplexity int, photoID string, direction string) int\n\t}\n\n\tPhoto struct {\n\t\tComment func(childComplexity int) int\n\t\tID      func(childComplexity int) int\n\t\tLiked   func(childComplexity int) int\n\t\tRating  func(childComplexity int) int\n\t\tURL     func(childComplexity int) int\n\t\tUser    func(childComplexity int) int\n\t}\n\n\tQuery struct {\n\t\tPhotos   func(childComplexity int, userID string) int\n\t\tTimeline func(childComplexity int) int\n\t\tUser     func(childComplexity int, userID string) int\n\t}\n\n\tUser struct {\n\t\tAvatar   func(childComplexity int) int\n\t\tFollowed func(childComplexity int) int\n\t\tID       func(childComplexity int) int\n\t\tName     func(childComplexity int) int\n\t\tPhotos   func(childComplexity int, count int) int\n\t}\n}\n\ntype MutationResolver interface {\n\tRatePhoto(ctx context.Context, photoID string, direction string) (*Photo, error)\n}\ntype PhotoResolver interface {\n\tID(ctx context.Context, obj *Photo) (string, error)\n\tUser(ctx context.Context, obj *Photo) (*User, error)\n}\ntype QueryResolver interface {\n\tTimeline(ctx context.Context) ([]*Photo, error)\n\tUser(ctx context.Context, userID string) (*User, error)\n\tPhotos(ctx context.Context, userID string) ([]*Photo, error)\n}\ntype UserResolver interface {\n\tPhotos(ctx context.Context, obj *User, count int) ([]*Photo, error)\n}\n\ntype executableSchema struct {\n\tresolvers  ResolverRoot\n\tdirectives DirectiveRoot\n\tcomplexity ComplexityRoot\n}\n\nfunc (e *executableSchema) Schema() *ast.Schema {\n\treturn parsedSchema\n}\n\nfunc (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) {\n\tec := executionContext{nil, e}\n\t_ = ec\n\tswitch typeName + \".\" + field {\n\n\tcase \"Mutation.ratePhoto\":\n\t\tif e.complexity.Mutation.RatePhoto == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Mutation_ratePhoto_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Mutation.RatePhoto(childComplexity, args[\"photoID\"].(string), args[\"direction\"].(string)), true\n\n\tcase \"Photo.comment\":\n\t\tif e.complexity.Photo.Comment == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Comment(childComplexity), true\n\n\tcase \"Photo.id\":\n\t\tif e.complexity.Photo.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.ID(childComplexity), true\n\n\tcase \"Photo.liked\":\n\t\tif e.complexity.Photo.Liked == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Liked(childComplexity), true\n\n\tcase \"Photo.rating\":\n\t\tif e.complexity.Photo.Rating == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Rating(childComplexity), true\n\n\tcase \"Photo.url\":\n\t\tif e.complexity.Photo.URL == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.URL(childComplexity), true\n\n\tcase \"Photo.user\":\n\t\tif e.complexity.Photo.User == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.User(childComplexity), true\n\n\tcase \"Query.photos\":\n\t\tif e.complexity.Query.Photos == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Query_photos_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Query.Photos(childComplexity, args[\"userID\"].(string)), true\n\n\tcase \"Query.timeline\":\n\t\tif e.complexity.Query.Timeline == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Query.Timeline(childComplexity), true\n\n\tcase \"Query.user\":\n\t\tif e.complexity.Query.User == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Query_user_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Query.User(childComplexity, args[\"userID\"].(string)), true\n\n\tcase \"User.avatar\":\n\t\tif e.complexity.User.Avatar == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Avatar(childComplexity), true\n\n\tcase \"User.followed\":\n\t\tif e.complexity.User.Followed == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Followed(childComplexity), true\n\n\tcase \"User.id\":\n\t\tif e.complexity.User.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.ID(childComplexity), true\n\n\tcase \"User.name\":\n\t\tif e.complexity.User.Name == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Name(childComplexity), true\n\n\tcase \"User.photos\":\n\t\tif e.complexity.User.Photos == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_User_photos_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.User.Photos(childComplexity, args[\"count\"].(int)), true\n\n\t}\n\treturn 0, false\n}\n\nfunc (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {\n\trc := graphql.GetOperationContext(ctx)\n\tec := executionContext{rc, e}\n\tfirst := true\n\n\tswitch rc.Operation.Operation {\n\tcase ast.Query:\n\t\treturn func(ctx context.Context) *graphql.Response {\n\t\t\tif !first {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tfirst = false\n\t\t\tdata := ec._Query(ctx, rc.Operation.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf.Bytes(),\n\t\t\t}\n\t\t}\n\tcase ast.Mutation:\n\t\treturn func(ctx context.Context) *graphql.Response {\n\t\t\tif !first {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tfirst = false\n\t\t\tdata := ec._Mutation(ctx, rc.Operation.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf.Bytes(),\n\t\t\t}\n\t\t}\n\n\tdefault:\n\t\treturn graphql.OneShot(graphql.ErrorResponse(ctx, \"unsupported GraphQL operation\"))\n\t}\n}\n\ntype executionContext struct {\n\t*graphql.OperationContext\n\t*executableSchema\n}\n\nfunc (ec *executionContext) introspectSchema() (*introspection.Schema, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapSchema(parsedSchema), nil\n}\n\nfunc (ec *executionContext) introspectType(name string) (*introspection.Type, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil\n}\n\nvar sources = []*ast.Source{\n\t&ast.Source{Name: \"schema.graphql\", Input: `type User {\n  id: ID!\n  name: String!\n  avatar: String!\n  followed: Boolean!\n\n  # subscriptions(count: Int! = 10): [User!]!\n  # subscribers(count: Int! = 10): [User!]!\n  \"\"\"возвращает фотограции данного пользователя\"\"\"\n  photos(count: Int! = 10): [Photo!]!\n}\n\ntype Photo {\n  id: ID!\n  user: User!\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  \"\"\"возвращает ленту текущего пользователя - фото тех, на кого он подписан\"\"\"\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,name,avatar}}\n  \"\"\"возвращает выбранного пользователя\"\"\"\n  user(userID: ID!): User!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  \"\"\"возвращает фотограции выбранного пользователя\"\"\"\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n}\n\n# go run github.com/99designs/gqlgen init\n# go run github.com/99designs/gqlgen -v\n`, BuiltIn: false},\n}\nvar parsedSchema = gqlparser.MustLoadSchema(sources...)\n\n// endregion ************************** generated!.gotpl **************************\n\n// region    ***************************** args.gotpl *****************************\n\nfunc (ec *executionContext) field_Mutation_ratePhoto_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"photoID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"photoID\"] = arg0\n\tvar arg1 string\n\tif tmp, ok := rawArgs[\"direction\"]; ok {\n\t\targ1, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"direction\"] = arg1\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"name\"]; ok {\n\t\targ0, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"name\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query_photos_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"userID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"userID\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"userID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"userID\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_User_photos_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 int\n\tif tmp, ok := rawArgs[\"count\"]; ok {\n\t\targ0, err = ec.unmarshalNInt2int(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"count\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\n// endregion ***************************** args.gotpl *****************************\n\n// region    ************************** directives.gotpl **************************\n\n// endregion ************************** directives.gotpl **************************\n\n// region    **************************** field.gotpl *****************************\n\nfunc (ec *executionContext) _Mutation_ratePhoto(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Mutation\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Mutation_ratePhoto_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Mutation().RatePhoto(rctx, args[\"photoID\"].(string), args[\"direction\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚖgqlgen4ᚐPhoto(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_id(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Photo().ID(rctx, obj)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_user(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Photo().User(rctx, obj)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*User)\n\tfc.Result = res\n\treturn ec.marshalNUser2ᚖgqlgen4ᚐUser(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_url(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.URL, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_comment(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Comment, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_rating(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Rating, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(int)\n\tfc.Result = res\n\treturn ec.marshalNInt2int(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_liked(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Liked, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_timeline(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Timeline(rctx)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen4ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_user(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query_user_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().User(rctx, args[\"userID\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*User)\n\tfc.Result = res\n\treturn ec.marshalNUser2ᚖgqlgen4ᚐUser(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_photos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query_photos_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Photos(rctx, args[\"userID\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen4ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query___type_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectType(args[\"name\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectSchema()\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Schema)\n\tfc.Result = res\n\treturn ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.ID, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_name(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_avatar(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Avatar, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_followed(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Followed, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_photos(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_User_photos_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.User().Photos(rctx, obj, args[\"count\"].(int))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen4ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Locations, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]string)\n\tfc.Result = res\n\treturn ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DefaultValue, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Types(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.QueryType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.MutationType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.SubscriptionType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Directives(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Directive)\n\tfc.Result = res\n\treturn ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Kind(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalN__TypeKind2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_fields_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Fields(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Field)\n\tfc.Result = res\n\treturn ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Interfaces(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.PossibleTypes(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_enumValues_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.EnumValues(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.EnumValue)\n\tfc.Result = res\n\treturn ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.InputFields(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.OfType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\n// endregion **************************** field.gotpl *****************************\n\n// region    **************************** input.gotpl *****************************\n\n// endregion **************************** input.gotpl *****************************\n\n// region    ************************** interface.gotpl ***************************\n\n// endregion ************************** interface.gotpl ***************************\n\n// region    **************************** object.gotpl ****************************\n\nvar mutationImplementors = []string{\"Mutation\"}\n\nfunc (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors)\n\n\tctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{\n\t\tObject: \"Mutation\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Mutation\")\n\t\tcase \"ratePhoto\":\n\t\t\tout.Values[i] = ec._Mutation_ratePhoto(ctx, field)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar photoImplementors = []string{\"Photo\"}\n\nfunc (ec *executionContext) _Photo(ctx context.Context, sel ast.SelectionSet, obj *Photo) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, photoImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Photo\")\n\t\tcase \"id\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Photo_id(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"user\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Photo_user(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"url\":\n\t\t\tout.Values[i] = ec._Photo_url(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"comment\":\n\t\t\tout.Values[i] = ec._Photo_comment(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"rating\":\n\t\t\tout.Values[i] = ec._Photo_rating(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"liked\":\n\t\t\tout.Values[i] = ec._Photo_liked(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar queryImplementors = []string{\"Query\"}\n\nfunc (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, queryImplementors)\n\n\tctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{\n\t\tObject: \"Query\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Query\")\n\t\tcase \"timeline\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_timeline(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"user\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_user(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"photos\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_photos(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"__type\":\n\t\t\tout.Values[i] = ec._Query___type(ctx, field)\n\t\tcase \"__schema\":\n\t\t\tout.Values[i] = ec._Query___schema(ctx, field)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar userImplementors = []string{\"User\"}\n\nfunc (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *User) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, userImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"User\")\n\t\tcase \"id\":\n\t\t\tout.Values[i] = ec._User_id(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec._User_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"avatar\":\n\t\t\tout.Values[i] = ec._User_avatar(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"followed\":\n\t\t\tout.Values[i] = ec._User_followed(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"photos\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._User_photos(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __DirectiveImplementors = []string{\"__Directive\"}\n\nfunc (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __DirectiveImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Directive\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Directive_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Directive_description(ctx, field, obj)\n\t\tcase \"locations\":\n\t\t\tout.Values[i] = ec.___Directive_locations(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Directive_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __EnumValueImplementors = []string{\"__EnumValue\"}\n\nfunc (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__EnumValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___EnumValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___EnumValue_description(ctx, field, obj)\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __FieldImplementors = []string{\"__Field\"}\n\nfunc (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __FieldImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Field\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Field_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Field_description(ctx, field, obj)\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Field_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___Field_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___Field_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___Field_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __InputValueImplementors = []string{\"__InputValue\"}\n\nfunc (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __InputValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__InputValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___InputValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___InputValue_description(ctx, field, obj)\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___InputValue_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"defaultValue\":\n\t\t\tout.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __SchemaImplementors = []string{\"__Schema\"}\n\nfunc (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __SchemaImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Schema\")\n\t\tcase \"types\":\n\t\t\tout.Values[i] = ec.___Schema_types(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"queryType\":\n\t\t\tout.Values[i] = ec.___Schema_queryType(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"mutationType\":\n\t\t\tout.Values[i] = ec.___Schema_mutationType(ctx, field, obj)\n\t\tcase \"subscriptionType\":\n\t\t\tout.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj)\n\t\tcase \"directives\":\n\t\t\tout.Values[i] = ec.___Schema_directives(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __TypeImplementors = []string{\"__Type\"}\n\nfunc (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Type\")\n\t\tcase \"kind\":\n\t\t\tout.Values[i] = ec.___Type_kind(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Type_name(ctx, field, obj)\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Type_description(ctx, field, obj)\n\t\tcase \"fields\":\n\t\t\tout.Values[i] = ec.___Type_fields(ctx, field, obj)\n\t\tcase \"interfaces\":\n\t\t\tout.Values[i] = ec.___Type_interfaces(ctx, field, obj)\n\t\tcase \"possibleTypes\":\n\t\t\tout.Values[i] = ec.___Type_possibleTypes(ctx, field, obj)\n\t\tcase \"enumValues\":\n\t\t\tout.Values[i] = ec.___Type_enumValues(ctx, field, obj)\n\t\tcase \"inputFields\":\n\t\t\tout.Values[i] = ec.___Type_inputFields(ctx, field, obj)\n\t\tcase \"ofType\":\n\t\t\tout.Values[i] = ec.___Type_ofType(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\n// endregion **************************** object.gotpl ****************************\n\n// region    ***************************** type.gotpl *****************************\n\nfunc (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\tres := graphql.MarshalBoolean(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalID(v)\n}\n\nfunc (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalID(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) {\n\treturn graphql.UnmarshalInt(v)\n}\n\nfunc (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler {\n\tres := graphql.MarshalInt(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalNPhoto2gqlgen4ᚐPhoto(ctx context.Context, sel ast.SelectionSet, v Photo) graphql.Marshaler {\n\treturn ec._Photo(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNPhoto2ᚕᚖgqlgen4ᚐPhotoᚄ(ctx context.Context, sel ast.SelectionSet, v []*Photo) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalNPhoto2ᚖgqlgen4ᚐPhoto(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalNPhoto2ᚖgqlgen4ᚐPhoto(ctx context.Context, sel ast.SelectionSet, v *Photo) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._Photo(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalNUser2gqlgen4ᚐUser(ctx context.Context, sel ast.SelectionSet, v User) graphql.Marshaler {\n\treturn ec._User(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNUser2ᚖgqlgen4ᚐUser(ctx context.Context, sel ast.SelectionSet, v *User) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._User(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler {\n\treturn ec.___Directive(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) {\n\tvar vSlice []interface{}\n\tif v != nil {\n\t\tif tmp1, ok := v.([]interface{}); ok {\n\t\t\tvSlice = tmp1\n\t\t} else {\n\t\t\tvSlice = []interface{}{v}\n\t\t}\n\t}\n\tvar err error\n\tres := make([]string, len(vSlice))\n\tfor i := range vSlice {\n\t\tres[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn res, nil\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler {\n\treturn ec.___EnumValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler {\n\treturn ec.___Field(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler {\n\treturn ec.___InputValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\treturn graphql.MarshalBoolean(v)\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOBoolean2bool(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOBoolean2bool(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\treturn graphql.MarshalString(v)\n}\n\nfunc (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOString2string(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOString2string(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Schema2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v introspection.Schema) graphql.Marshaler {\n\treturn ec.___Schema(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Schema(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalO__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\n// endregion ***************************** type.gotpl *****************************\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen4/go.mod",
    "content": "module gqlgen4\n\ngo 1.13\n\nrequire (\n\tgithub.com/99designs/gqlgen v0.11.1\n\tgithub.com/vektah/gqlparser/v2 v2.0.1\n)\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen4/go.sum",
    "content": "github.com/99designs/gqlgen v0.11.1 h1:QoSL8/AAJ2T3UOeQbdnBR32JcG4pO08+P/g5jdbFkUg=\ngithub.com/99designs/gqlgen v0.11.1/go.mod h1:vjFOyBZ7NwDl+GdSD4PFn7BQn5Fy7ohJwXn7Vk8zz+c=\ngithub.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=\ngithub.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=\ngithub.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=\ngithub.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=\ngithub.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=\ngithub.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=\ngithub.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=\ngithub.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=\ngithub.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=\ngithub.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=\ngithub.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=\ngithub.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=\ngithub.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=\ngithub.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=\ngithub.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=\ngithub.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=\ngithub.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8=\ngithub.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=\ngithub.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=\ngithub.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=\ngithub.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=\ngithub.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=\ngithub.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=\ngithub.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=\ngithub.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=\ngithub.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o=\ngithub.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM=\ngolang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=\ngopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\nsourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=\nsourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen4/gqlgen.yml",
    "content": "schema:\n- schema.graphql\nexec:\n  filename: generated.go\nmodel:\n  filename: models_gen.go\nresolver:\n  filename: resolver.go\n  type: Resolver\n\nmodels:\n  Photo:\n    model: gqlgen4.Photo\n    fields:\n      user:\n        resolver: true\n  User:\n    fields:\n      photos:\n        resolver: true\n\nautobind: []\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen4/models_gen.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen4\n\ntype User struct {\n\tID       string `json:\"id\"`\n\tName     string `json:\"name\"`\n\tAvatar   string `json:\"avatar\"`\n\tFollowed bool   `json:\"followed\"`\n\t// возвращает фотограции данного пользователя\n\tPhotos []*Photo `json:\"photos\"`\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen4/photo.go",
    "content": "package gqlgen4\n\nimport (\n\t// \"log\"\n\t\"strconv\"\n)\n\ntype Photo struct {\n\tID     uint `json:\"id\"`\n\tUserID uint `json:\"-\"`\n\t// User     *User  `json:\"user\"`\n\tURL     string `json:\"url\"`\n\tComment string `json:\"comment\"`\n\tRating  int    `json:\"rating\"`\n\tLiked   bool   `json:\"liked\"`\n}\n\nfunc (ph *Photo) Id() string {\n\t// log.Println(\"call Photo.Id method\", ph.ID)\n\treturn strconv.Itoa(int(ph.ID))\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen4/queries.txt",
    "content": "query {\n  user(userID: \"1\") {\n    id\n    name\n    avatar\n  }\n}\n\n# -----\n\nquery {\n  user(userID: \"1\") {\n    id\n    name\n    avatar\n    photos {\n      id\n      url\n      user {\n        id\n        name\n        photos {\n          id\n          url\n        }\n      }\n    }\n  }\n}\n\n# -----\n\nquery {\n  user(userID: \"1\") {\n    id\n    name\n    avatar\n    photos(count:20) {\n      id\n      url\n      user {\n        id\n        name\n        photos(count:100) {\n          id\n          url\n        }\n      }\n    }\n  }\n}\n\n# ----\n\nquery getFullUser($userID: ID!, $cnt1:Int!, $cnt2:Int! ) {\n  user(userID: $userID) {\n    id\n    name\n    avatar\n    photos(count:$cnt1) {\n      id\n      url\n      user {\n        id\n        name\n        photos(count:$cnt2) {\n          id\n          url\n        }\n      }\n    }\n  }\n  photos(userID:$userID) {id, url}\n}\n\n\n{\n  \"userID\":\"1\",\n  \"cnt1\":10,\n  \"cnt2\":20\n}"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen4/resolver.go",
    "content": "package gqlgen4\n\n//go:generate go run github.com/99designs/gqlgen\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"strconv\"\n\t\"time\"\n) // THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.\n\ntype Resolver struct {\n\tPhotosData map[string]*Photo\n\tUsers      map[uint]*User\n}\n\nfunc (r *Resolver) Mutation() MutationResolver {\n\treturn &mutationResolver{r}\n}\nfunc (r *Resolver) Photo() PhotoResolver {\n\treturn &photoResolver{r}\n}\nfunc (r *Resolver) User() UserResolver {\n\treturn &userResolver{r}\n}\nfunc (r *Resolver) Query() QueryResolver {\n\treturn &queryResolver{r}\n}\n\ntype mutationResolver struct{ *Resolver }\n\nfunc (r *mutationResolver) RatePhoto(ctx context.Context, id string, direction string) (*Photo, error) {\n\tlog.Println(\"call mutationResolver.RatePhoto method with id\", id, direction)\n\trate := 1\n\tif direction != \"up\" {\n\t\trate = -1\n\t}\n\tph, ok := r.PhotosData[id]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no photo %v found\", id)\n\t}\n\tph.Rating += rate\n\treturn ph, nil\n}\n\ntype userResolver struct{ *Resolver }\n\nfunc (r *userResolver) Photos(ctx context.Context, obj *User, count int) ([]*Photo, error) {\n\tlog.Println(\"call userResolver.Photos with count\", count)\n\tid, _ := strconv.Atoi(obj.ID)\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\tif ph.UserID != uint(id) {\n\t\t\tcontinue\n\t\t}\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n\ntype photoResolver struct{ *Resolver }\n\nfunc (r *photoResolver) ID(ctx context.Context, obj *Photo) (string, error) {\n\treturn obj.Id(), nil\n}\n\nfunc (r *photoResolver) User(ctx context.Context, obj *Photo) (*User, error) {\n\t// return r.Users[obj.UserID], nil\n\tlog.Println(\"call photoResolver.User\", obj.UserID)\n\tstart := time.Now()\n\tuser, err := ctx.Value(\"userLoaderKey\").(*UserLoader).Load(obj.UserID)\n\tlog.Println(\"get photoResolver.User\", obj.UserID, \"from UserLoader, time \", time.Since(start))\n\treturn user, err\n}\n\ntype queryResolver struct{ *Resolver }\n\nfunc (r *queryResolver) Timeline(ctx context.Context) ([]*Photo, error) {\n\tlog.Println(\"call queryResolver.Timeline with ctx.userID\", ctx.Value(\"userID\"))\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n\nfunc (r *queryResolver) User(ctx context.Context, userID string) (*User, error) {\n\tlog.Println(\"call queryResolver.User for\", userID)\n\tid, _ := strconv.Atoi(userID)\n\treturn r.Users[uint(id)], nil\n}\n\nfunc (r *queryResolver) Photos(ctx context.Context, userID string) ([]*Photo, error) {\n\tlog.Println(\"call queryResolver.Photos\")\n\tid, _ := strconv.Atoi(userID)\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\tif ph.UserID != uint(id) {\n\t\t\tcontinue\n\t\t}\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen4/schema.graphql",
    "content": "type User {\n  id: ID!\n  name: String!\n  avatar: String!\n  followed: Boolean!\n\n  # subscriptions(count: Int! = 10): [User!]!\n  # subscribers(count: Int! = 10): [User!]!\n  \"\"\"возвращает фотограции данного пользователя\"\"\"\n  photos(count: Int! = 10): [Photo!]!\n}\n\ntype Photo {\n  id: ID!\n  user: User!\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  \"\"\"возвращает ленту текущего пользователя - фото тех, на кого он подписан\"\"\"\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,name,avatar}}\n  \"\"\"возвращает выбранного пользователя\"\"\"\n  user(userID: ID!): User!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  \"\"\"возвращает фотограции выбранного пользователя\"\"\"\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n}\n\n# go run github.com/99designs/gqlgen init\n# go run github.com/99designs/gqlgen -v\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen4/server/server.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\tgqlgen \"gqlgen4\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/99designs/gqlgen/handler\"\n)\n\n/*\nquery{timeline{id,url,user{id,name}}}\nquery{user(userID:\"1\"){id,avatar, name}}\nmutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n*/\n\nvar users = map[uint]*gqlgen.User{\n\t1: {\n\t\tID:     \"1\",\n\t\tName:   \"rvasily\",\n\t\tAvatar: \"https://via.placeholder.com/150\",\n\t},\n\t2: {\n\t\tID:     \"2\",\n\t\tName:   \"v.romanov\",\n\t\tAvatar: \"https://via.placeholder.com/150\",\n\t},\n}\n\nvar photos = map[string]*gqlgen.Photo{\n\t\"1\": {\n\t\tID:      1,\n\t\tUserID:  1,\n\t\tURL:     \"https://via.placeholder.com/300\",\n\t\tComment: \"fromn studio\",\n\t\tRating:  1,\n\t\tLiked:   true,\n\t},\n\t\"2\": {\n\t\tID:      2,\n\t\tUserID:  1,\n\t\tURL:     \"https://via.placeholder.com/300\",\n\t\tComment: \"cool view\",\n\t\tRating:  0,\n\t\tLiked:   false,\n\t},\n\t\"3\": {\n\t\tID:      3,\n\t\tUserID:  2,\n\t\tURL:     \"https://via.placeholder.com/300\",\n\t\tComment: \"at work\",\n\t\tRating:  0,\n\t\tLiked:   false,\n\t},\n}\n\n// go run github.com/vektah/dataloaden UserLoader uint *coursera/3p/graphql/gqlgen3.User\n\nfunc UserLoaderMiddleware(resolver *gqlgen.Resolver, next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tcfg := gqlgen.UserLoaderConfig{\n\t\t\tMaxBatch: 100,\n\t\t\tWait:     1 * time.Millisecond,\n\t\t\tFetch: func(ids []uint) ([]*gqlgen.User, []error) {\n\t\t\t\t// имеем доступ до r *http.Request - там context с сессией пользователя\n\t\t\t\tsessionUserID := r.Context().Value(\"userID\").(uint)\n\t\t\t\tlog.Printf(\"UserLoader Request - ids %v for user %v\\n\", ids, sessionUserID)\n\n\t\t\t\tusers := make([]*gqlgen.User, len(ids))\n\t\t\t\tfor i, id := range ids {\n\t\t\t\t\t// имеем доступ до resolver *gqlgen.Resolver - там коннет к базе\n\t\t\t\t\tusers[i] = resolver.Users[id]\n\t\t\t\t}\n\t\t\t\treturn users, nil\n\t\t\t},\n\t\t}\n\t\tuserLoader := gqlgen.NewUserLoader(cfg)\n\t\tctx := context.WithValue(r.Context(), \"userLoaderKey\", userLoader)\n\t\tr = r.WithContext(ctx)\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n\nfunc AuthMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t// log.Println(\"new request\")\n\t\tctx := context.WithValue(r.Context(), \"userID\", uint(1))\n\t\tr = r.WithContext(ctx)\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n\nfunc main() {\n\thttp.Handle(\"/\", handler.Playground(\"GraphQL playground\", \"/query\"))\n\n\tresolver := &gqlgen.Resolver{\n\t\tUsers:      users,\n\t\tPhotosData: photos,\n\t}\n\tcfg := gqlgen.Config{\n\t\tResolvers: resolver,\n\t}\n\tcfg.Complexity.User.Photos = func(childComplexity, count int) int {\n\t\treturn count * childComplexity\n\t}\n\n\tgqlHandler := handler.GraphQL(\n\t\tgqlgen.NewExecutableSchema(cfg),\n\t\thandler.ComplexityLimit(500),\n\t)\n\thandler := UserLoaderMiddleware(resolver, gqlHandler)\n\thandler = AuthMiddleware(handler)\n\thttp.Handle(\"/query\", handler)\n\n\tport := \"8080\"\n\tlog.Printf(\"connect to http://localhost:%s/ for GraphQL playground\", port)\n\tlog.Fatal(http.ListenAndServe(\":\"+port, nil))\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen4/userloader_gen.go",
    "content": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage gqlgen4\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\n// UserLoaderConfig captures the config to create a new UserLoader\ntype UserLoaderConfig struct {\n\t// Fetch is a method that provides the data for the loader\n\tFetch func(keys []uint) ([]*User, []error)\n\n\t// Wait is how long wait before sending a batch\n\tWait time.Duration\n\n\t// MaxBatch will limit the maximum number of keys to send in one batch, 0 = not limit\n\tMaxBatch int\n}\n\n// NewUserLoader creates a new UserLoader given a fetch, wait, and maxBatch\nfunc NewUserLoader(config UserLoaderConfig) *UserLoader {\n\treturn &UserLoader{\n\t\tfetch:    config.Fetch,\n\t\twait:     config.Wait,\n\t\tmaxBatch: config.MaxBatch,\n\t}\n}\n\n// UserLoader batches and caches requests\ntype UserLoader struct {\n\t// this method provides the data for the loader\n\tfetch func(keys []uint) ([]*User, []error)\n\n\t// how long to done before sending a batch\n\twait time.Duration\n\n\t// this will limit the maximum number of keys to send in one batch, 0 = no limit\n\tmaxBatch int\n\n\t// INTERNAL\n\n\t// lazily created cache\n\tcache map[uint]*User\n\n\t// the current batch. keys will continue to be collected until timeout is hit,\n\t// then everything will be sent to the fetch method and out to the listeners\n\tbatch *userLoaderBatch\n\n\t// mutex to prevent races\n\tmu sync.Mutex\n}\n\ntype userLoaderBatch struct {\n\tkeys    []uint\n\tdata    []*User\n\terror   []error\n\tclosing bool\n\tdone    chan struct{}\n}\n\n// Load a User by key, batching and caching will be applied automatically\nfunc (l *UserLoader) Load(key uint) (*User, error) {\n\treturn l.LoadThunk(key)()\n}\n\n// LoadThunk returns a function that when called will block waiting for a User.\n// This method should be used if you want one goroutine to make requests to many\n// different data loaders without blocking until the thunk is called.\nfunc (l *UserLoader) LoadThunk(key uint) func() (*User, error) {\n\tl.mu.Lock()\n\tif it, ok := l.cache[key]; ok {\n\t\tl.mu.Unlock()\n\t\treturn func() (*User, error) {\n\t\t\treturn it, nil\n\t\t}\n\t}\n\tif l.batch == nil {\n\t\tl.batch = &userLoaderBatch{done: make(chan struct{})}\n\t}\n\tbatch := l.batch\n\tpos := batch.keyIndex(l, key)\n\tl.mu.Unlock()\n\n\treturn func() (*User, error) {\n\t\t<-batch.done\n\n\t\tvar data *User\n\t\tif pos < len(batch.data) {\n\t\t\tdata = batch.data[pos]\n\t\t}\n\n\t\tvar err error\n\t\t// its convenient to be able to return a single error for everything\n\t\tif len(batch.error) == 1 {\n\t\t\terr = batch.error[0]\n\t\t} else if batch.error != nil {\n\t\t\terr = batch.error[pos]\n\t\t}\n\n\t\tif err == nil {\n\t\t\tl.mu.Lock()\n\t\t\tl.unsafeSet(key, data)\n\t\t\tl.mu.Unlock()\n\t\t}\n\n\t\treturn data, err\n\t}\n}\n\n// LoadAll fetches many keys at once. It will be broken into appropriate sized\n// sub batches depending on how the loader is configured\nfunc (l *UserLoader) LoadAll(keys []uint) ([]*User, []error) {\n\tresults := make([]func() (*User, error), len(keys))\n\n\tfor i, key := range keys {\n\t\tresults[i] = l.LoadThunk(key)\n\t}\n\n\tusers := make([]*User, len(keys))\n\terrors := make([]error, len(keys))\n\tfor i, thunk := range results {\n\t\tusers[i], errors[i] = thunk()\n\t}\n\treturn users, errors\n}\n\n// LoadAllThunk returns a function that when called will block waiting for a Users.\n// This method should be used if you want one goroutine to make requests to many\n// different data loaders without blocking until the thunk is called.\nfunc (l *UserLoader) LoadAllThunk(keys []uint) func() ([]*User, []error) {\n\tresults := make([]func() (*User, error), len(keys))\n\tfor i, key := range keys {\n\t\tresults[i] = l.LoadThunk(key)\n\t}\n\treturn func() ([]*User, []error) {\n\t\tusers := make([]*User, len(keys))\n\t\terrors := make([]error, len(keys))\n\t\tfor i, thunk := range results {\n\t\t\tusers[i], errors[i] = thunk()\n\t\t}\n\t\treturn users, errors\n\t}\n}\n\n// Prime the cache with the provided key and value. If the key already exists, no change is made\n// and false is returned.\n// (To forcefully prime the cache, clear the key first with loader.clear(key).prime(key, value).)\nfunc (l *UserLoader) Prime(key uint, value *User) bool {\n\tl.mu.Lock()\n\tvar found bool\n\tif _, found = l.cache[key]; !found {\n\t\t// make a copy when writing to the cache, its easy to pass a pointer in from a loop var\n\t\t// and end up with the whole cache pointing to the same value.\n\t\tcpy := *value\n\t\tl.unsafeSet(key, &cpy)\n\t}\n\tl.mu.Unlock()\n\treturn !found\n}\n\n// Clear the value at key from the cache, if it exists\nfunc (l *UserLoader) Clear(key uint) {\n\tl.mu.Lock()\n\tdelete(l.cache, key)\n\tl.mu.Unlock()\n}\n\nfunc (l *UserLoader) unsafeSet(key uint, value *User) {\n\tif l.cache == nil {\n\t\tl.cache = map[uint]*User{}\n\t}\n\tl.cache[key] = value\n}\n\n// keyIndex will return the location of the key in the batch, if its not found\n// it will add the key to the batch\nfunc (b *userLoaderBatch) keyIndex(l *UserLoader, key uint) int {\n\tfor i, existingKey := range b.keys {\n\t\tif key == existingKey {\n\t\t\treturn i\n\t\t}\n\t}\n\n\tpos := len(b.keys)\n\tb.keys = append(b.keys, key)\n\tif pos == 0 {\n\t\tgo b.startTimer(l)\n\t}\n\n\tif l.maxBatch != 0 && pos >= l.maxBatch-1 {\n\t\tif !b.closing {\n\t\t\tb.closing = true\n\t\t\tl.batch = nil\n\t\t\tgo b.end(l)\n\t\t}\n\t}\n\n\treturn pos\n}\n\nfunc (b *userLoaderBatch) startTimer(l *UserLoader) {\n\ttime.Sleep(l.wait)\n\tl.mu.Lock()\n\n\t// we must have hit a batch limit and are already finalizing this batch\n\tif b.closing {\n\t\tl.mu.Unlock()\n\t\treturn\n\t}\n\n\tl.batch = nil\n\tl.mu.Unlock()\n\n\tb.end(l)\n}\n\nfunc (b *userLoaderBatch) end(l *UserLoader) {\n\tb.data, b.error = l.fetch(b.keys)\n\tclose(b.done)\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen5/generated.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen5\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"strconv\"\n\t\"sync\"\n\t\"sync/atomic\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\t\"github.com/99designs/gqlgen/graphql/introspection\"\n\tgqlparser \"github.com/vektah/gqlparser/v2\"\n\t\"github.com/vektah/gqlparser/v2/ast\"\n)\n\n// region    ************************** generated!.gotpl **************************\n\n// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.\nfunc NewExecutableSchema(cfg Config) graphql.ExecutableSchema {\n\treturn &executableSchema{\n\t\tresolvers:  cfg.Resolvers,\n\t\tdirectives: cfg.Directives,\n\t\tcomplexity: cfg.Complexity,\n\t}\n}\n\ntype Config struct {\n\tResolvers  ResolverRoot\n\tDirectives DirectiveRoot\n\tComplexity ComplexityRoot\n}\n\ntype ResolverRoot interface {\n\tMutation() MutationResolver\n\tPhoto() PhotoResolver\n\tQuery() QueryResolver\n\tUser() UserResolver\n}\n\ntype DirectiveRoot struct {\n}\n\ntype ComplexityRoot struct {\n\tMutation struct {\n\t\tRatePhoto   func(childComplexity int, photoID string, direction string) int\n\t\tUploadPhoto func(childComplexity int, comment string, file graphql.Upload) int\n\t}\n\n\tPhoto struct {\n\t\tComment func(childComplexity int) int\n\t\tID      func(childComplexity int) int\n\t\tLiked   func(childComplexity int) int\n\t\tRating  func(childComplexity int) int\n\t\tURL     func(childComplexity int) int\n\t\tUser    func(childComplexity int) int\n\t}\n\n\tQuery struct {\n\t\tPhotos   func(childComplexity int, userID string) int\n\t\tTimeline func(childComplexity int) int\n\t\tUser     func(childComplexity int, userID string) int\n\t}\n\n\tUser struct {\n\t\tAvatar   func(childComplexity int) int\n\t\tFollowed func(childComplexity int) int\n\t\tID       func(childComplexity int) int\n\t\tName     func(childComplexity int) int\n\t\tPhotos   func(childComplexity int, count int) int\n\t}\n}\n\ntype MutationResolver interface {\n\tRatePhoto(ctx context.Context, photoID string, direction string) (*Photo, error)\n\tUploadPhoto(ctx context.Context, comment string, file graphql.Upload) (*Photo, error)\n}\ntype PhotoResolver interface {\n\tID(ctx context.Context, obj *Photo) (string, error)\n\tUser(ctx context.Context, obj *Photo) (*User, error)\n}\ntype QueryResolver interface {\n\tTimeline(ctx context.Context) ([]*Photo, error)\n\tUser(ctx context.Context, userID string) (*User, error)\n\tPhotos(ctx context.Context, userID string) ([]*Photo, error)\n}\ntype UserResolver interface {\n\tPhotos(ctx context.Context, obj *User, count int) ([]*Photo, error)\n}\n\ntype executableSchema struct {\n\tresolvers  ResolverRoot\n\tdirectives DirectiveRoot\n\tcomplexity ComplexityRoot\n}\n\nfunc (e *executableSchema) Schema() *ast.Schema {\n\treturn parsedSchema\n}\n\nfunc (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) {\n\tec := executionContext{nil, e}\n\t_ = ec\n\tswitch typeName + \".\" + field {\n\n\tcase \"Mutation.ratePhoto\":\n\t\tif e.complexity.Mutation.RatePhoto == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Mutation_ratePhoto_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Mutation.RatePhoto(childComplexity, args[\"photoID\"].(string), args[\"direction\"].(string)), true\n\n\tcase \"Mutation.uploadPhoto\":\n\t\tif e.complexity.Mutation.UploadPhoto == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Mutation_uploadPhoto_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Mutation.UploadPhoto(childComplexity, args[\"comment\"].(string), args[\"file\"].(graphql.Upload)), true\n\n\tcase \"Photo.comment\":\n\t\tif e.complexity.Photo.Comment == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Comment(childComplexity), true\n\n\tcase \"Photo.id\":\n\t\tif e.complexity.Photo.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.ID(childComplexity), true\n\n\tcase \"Photo.liked\":\n\t\tif e.complexity.Photo.Liked == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Liked(childComplexity), true\n\n\tcase \"Photo.rating\":\n\t\tif e.complexity.Photo.Rating == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Rating(childComplexity), true\n\n\tcase \"Photo.url\":\n\t\tif e.complexity.Photo.URL == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.URL(childComplexity), true\n\n\tcase \"Photo.user\":\n\t\tif e.complexity.Photo.User == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.User(childComplexity), true\n\n\tcase \"Query.photos\":\n\t\tif e.complexity.Query.Photos == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Query_photos_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Query.Photos(childComplexity, args[\"userID\"].(string)), true\n\n\tcase \"Query.timeline\":\n\t\tif e.complexity.Query.Timeline == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Query.Timeline(childComplexity), true\n\n\tcase \"Query.user\":\n\t\tif e.complexity.Query.User == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Query_user_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Query.User(childComplexity, args[\"userID\"].(string)), true\n\n\tcase \"User.avatar\":\n\t\tif e.complexity.User.Avatar == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Avatar(childComplexity), true\n\n\tcase \"User.followed\":\n\t\tif e.complexity.User.Followed == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Followed(childComplexity), true\n\n\tcase \"User.id\":\n\t\tif e.complexity.User.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.ID(childComplexity), true\n\n\tcase \"User.name\":\n\t\tif e.complexity.User.Name == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Name(childComplexity), true\n\n\tcase \"User.photos\":\n\t\tif e.complexity.User.Photos == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_User_photos_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.User.Photos(childComplexity, args[\"count\"].(int)), true\n\n\t}\n\treturn 0, false\n}\n\nfunc (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {\n\trc := graphql.GetOperationContext(ctx)\n\tec := executionContext{rc, e}\n\tfirst := true\n\n\tswitch rc.Operation.Operation {\n\tcase ast.Query:\n\t\treturn func(ctx context.Context) *graphql.Response {\n\t\t\tif !first {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tfirst = false\n\t\t\tdata := ec._Query(ctx, rc.Operation.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf.Bytes(),\n\t\t\t}\n\t\t}\n\tcase ast.Mutation:\n\t\treturn func(ctx context.Context) *graphql.Response {\n\t\t\tif !first {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tfirst = false\n\t\t\tdata := ec._Mutation(ctx, rc.Operation.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf.Bytes(),\n\t\t\t}\n\t\t}\n\n\tdefault:\n\t\treturn graphql.OneShot(graphql.ErrorResponse(ctx, \"unsupported GraphQL operation\"))\n\t}\n}\n\ntype executionContext struct {\n\t*graphql.OperationContext\n\t*executableSchema\n}\n\nfunc (ec *executionContext) introspectSchema() (*introspection.Schema, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapSchema(parsedSchema), nil\n}\n\nfunc (ec *executionContext) introspectType(name string) (*introspection.Type, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil\n}\n\nvar sources = []*ast.Source{\n\t&ast.Source{Name: \"schema.graphql\", Input: `# gqlgen знает как с этим работать и что парсить это надо через multipart-form\nscalar Upload\n\ntype User {\n  id: ID!\n  name: String!\n  avatar: String!\n  followed: Boolean!\n\n  # subscriptions(count: Int! = 10): [User!]!\n  # subscribers(count: Int! = 10): [User!]!\n  \"\"\"возвращает фотограции данного пользователя\"\"\"\n  photos(count: Int! = 10): [Photo!]!\n}\n\ntype Photo {\n  id: ID!\n  user: User!\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  \"\"\"возвращает ленту текущего пользователя - фото тех, на кого он подписан\"\"\"\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,name,avatar}}\n  \"\"\"возвращает выбранного пользователя\"\"\"\n  user(userID: ID!): User!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  \"\"\"возвращает фотограции выбранного пользователя\"\"\"\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n\n  uploadPhoto(comment: String!, file: Upload!): Photo!\n}\n\n# go run github.com/99designs/gqlgen init\n# go run github.com/99designs/gqlgen -v\n`, BuiltIn: false},\n}\nvar parsedSchema = gqlparser.MustLoadSchema(sources...)\n\n// endregion ************************** generated!.gotpl **************************\n\n// region    ***************************** args.gotpl *****************************\n\nfunc (ec *executionContext) field_Mutation_ratePhoto_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"photoID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"photoID\"] = arg0\n\tvar arg1 string\n\tif tmp, ok := rawArgs[\"direction\"]; ok {\n\t\targ1, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"direction\"] = arg1\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Mutation_uploadPhoto_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"comment\"]; ok {\n\t\targ0, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"comment\"] = arg0\n\tvar arg1 graphql.Upload\n\tif tmp, ok := rawArgs[\"file\"]; ok {\n\t\targ1, err = ec.unmarshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"file\"] = arg1\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"name\"]; ok {\n\t\targ0, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"name\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query_photos_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"userID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"userID\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"userID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"userID\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_User_photos_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 int\n\tif tmp, ok := rawArgs[\"count\"]; ok {\n\t\targ0, err = ec.unmarshalNInt2int(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"count\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\n// endregion ***************************** args.gotpl *****************************\n\n// region    ************************** directives.gotpl **************************\n\n// endregion ************************** directives.gotpl **************************\n\n// region    **************************** field.gotpl *****************************\n\nfunc (ec *executionContext) _Mutation_ratePhoto(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Mutation\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Mutation_ratePhoto_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Mutation().RatePhoto(rctx, args[\"photoID\"].(string), args[\"direction\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚖgqlgen5ᚐPhoto(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Mutation_uploadPhoto(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Mutation\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Mutation_uploadPhoto_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Mutation().UploadPhoto(rctx, args[\"comment\"].(string), args[\"file\"].(graphql.Upload))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚖgqlgen5ᚐPhoto(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_id(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Photo().ID(rctx, obj)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_user(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Photo().User(rctx, obj)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*User)\n\tfc.Result = res\n\treturn ec.marshalNUser2ᚖgqlgen5ᚐUser(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_url(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.URL, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_comment(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Comment, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_rating(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Rating, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(int)\n\tfc.Result = res\n\treturn ec.marshalNInt2int(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_liked(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Liked, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_timeline(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Timeline(rctx)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen5ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_user(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query_user_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().User(rctx, args[\"userID\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*User)\n\tfc.Result = res\n\treturn ec.marshalNUser2ᚖgqlgen5ᚐUser(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_photos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query_photos_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Photos(rctx, args[\"userID\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen5ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query___type_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectType(args[\"name\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectSchema()\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Schema)\n\tfc.Result = res\n\treturn ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.ID, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_name(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_avatar(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Avatar, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_followed(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Followed, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_photos(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_User_photos_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.User().Photos(rctx, obj, args[\"count\"].(int))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\tfc.Result = res\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen5ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Locations, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]string)\n\tfc.Result = res\n\treturn ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\tfc.Result = res\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DefaultValue, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Types(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.QueryType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.MutationType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.SubscriptionType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Directives(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Directive)\n\tfc.Result = res\n\treturn ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Kind(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !graphql.HasFieldError(ctx, fc) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalN__TypeKind2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\tfc.Result = res\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\tfc.Result = res\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_fields_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Fields(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Field)\n\tfc.Result = res\n\treturn ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Interfaces(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.PossibleTypes(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_enumValues_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tfc.Args = args\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.EnumValues(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.EnumValue)\n\tfc.Result = res\n\treturn ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.InputFields(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\tfc.Result = res\n\treturn ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t}()\n\tfc := &graphql.FieldContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\n\tctx = graphql.WithFieldContext(ctx, fc)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.OfType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\tfc.Result = res\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\n// endregion **************************** field.gotpl *****************************\n\n// region    **************************** input.gotpl *****************************\n\n// endregion **************************** input.gotpl *****************************\n\n// region    ************************** interface.gotpl ***************************\n\n// endregion ************************** interface.gotpl ***************************\n\n// region    **************************** object.gotpl ****************************\n\nvar mutationImplementors = []string{\"Mutation\"}\n\nfunc (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors)\n\n\tctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{\n\t\tObject: \"Mutation\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Mutation\")\n\t\tcase \"ratePhoto\":\n\t\t\tout.Values[i] = ec._Mutation_ratePhoto(ctx, field)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"uploadPhoto\":\n\t\t\tout.Values[i] = ec._Mutation_uploadPhoto(ctx, field)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar photoImplementors = []string{\"Photo\"}\n\nfunc (ec *executionContext) _Photo(ctx context.Context, sel ast.SelectionSet, obj *Photo) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, photoImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Photo\")\n\t\tcase \"id\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Photo_id(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"user\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Photo_user(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"url\":\n\t\t\tout.Values[i] = ec._Photo_url(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"comment\":\n\t\t\tout.Values[i] = ec._Photo_comment(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"rating\":\n\t\t\tout.Values[i] = ec._Photo_rating(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"liked\":\n\t\t\tout.Values[i] = ec._Photo_liked(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar queryImplementors = []string{\"Query\"}\n\nfunc (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, queryImplementors)\n\n\tctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{\n\t\tObject: \"Query\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Query\")\n\t\tcase \"timeline\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_timeline(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"user\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_user(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"photos\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_photos(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"__type\":\n\t\t\tout.Values[i] = ec._Query___type(ctx, field)\n\t\tcase \"__schema\":\n\t\t\tout.Values[i] = ec._Query___schema(ctx, field)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar userImplementors = []string{\"User\"}\n\nfunc (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *User) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, userImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"User\")\n\t\tcase \"id\":\n\t\t\tout.Values[i] = ec._User_id(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec._User_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"avatar\":\n\t\t\tout.Values[i] = ec._User_avatar(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"followed\":\n\t\t\tout.Values[i] = ec._User_followed(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"photos\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._User_photos(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __DirectiveImplementors = []string{\"__Directive\"}\n\nfunc (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __DirectiveImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Directive\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Directive_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Directive_description(ctx, field, obj)\n\t\tcase \"locations\":\n\t\t\tout.Values[i] = ec.___Directive_locations(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Directive_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __EnumValueImplementors = []string{\"__EnumValue\"}\n\nfunc (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__EnumValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___EnumValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___EnumValue_description(ctx, field, obj)\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __FieldImplementors = []string{\"__Field\"}\n\nfunc (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __FieldImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Field\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Field_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Field_description(ctx, field, obj)\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Field_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___Field_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___Field_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___Field_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __InputValueImplementors = []string{\"__InputValue\"}\n\nfunc (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __InputValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__InputValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___InputValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___InputValue_description(ctx, field, obj)\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___InputValue_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"defaultValue\":\n\t\t\tout.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __SchemaImplementors = []string{\"__Schema\"}\n\nfunc (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __SchemaImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Schema\")\n\t\tcase \"types\":\n\t\t\tout.Values[i] = ec.___Schema_types(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"queryType\":\n\t\t\tout.Values[i] = ec.___Schema_queryType(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"mutationType\":\n\t\t\tout.Values[i] = ec.___Schema_mutationType(ctx, field, obj)\n\t\tcase \"subscriptionType\":\n\t\t\tout.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj)\n\t\tcase \"directives\":\n\t\t\tout.Values[i] = ec.___Schema_directives(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __TypeImplementors = []string{\"__Type\"}\n\nfunc (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Type\")\n\t\tcase \"kind\":\n\t\t\tout.Values[i] = ec.___Type_kind(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Type_name(ctx, field, obj)\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Type_description(ctx, field, obj)\n\t\tcase \"fields\":\n\t\t\tout.Values[i] = ec.___Type_fields(ctx, field, obj)\n\t\tcase \"interfaces\":\n\t\t\tout.Values[i] = ec.___Type_interfaces(ctx, field, obj)\n\t\tcase \"possibleTypes\":\n\t\t\tout.Values[i] = ec.___Type_possibleTypes(ctx, field, obj)\n\t\tcase \"enumValues\":\n\t\t\tout.Values[i] = ec.___Type_enumValues(ctx, field, obj)\n\t\tcase \"inputFields\":\n\t\t\tout.Values[i] = ec.___Type_inputFields(ctx, field, obj)\n\t\tcase \"ofType\":\n\t\t\tout.Values[i] = ec.___Type_ofType(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\n// endregion **************************** object.gotpl ****************************\n\n// region    ***************************** type.gotpl *****************************\n\nfunc (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\tres := graphql.MarshalBoolean(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalID(v)\n}\n\nfunc (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalID(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) {\n\treturn graphql.UnmarshalInt(v)\n}\n\nfunc (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler {\n\tres := graphql.MarshalInt(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalNPhoto2gqlgen5ᚐPhoto(ctx context.Context, sel ast.SelectionSet, v Photo) graphql.Marshaler {\n\treturn ec._Photo(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNPhoto2ᚕᚖgqlgen5ᚐPhotoᚄ(ctx context.Context, sel ast.SelectionSet, v []*Photo) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalNPhoto2ᚖgqlgen5ᚐPhoto(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalNPhoto2ᚖgqlgen5ᚐPhoto(ctx context.Context, sel ast.SelectionSet, v *Photo) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._Photo(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx context.Context, v interface{}) (graphql.Upload, error) {\n\treturn graphql.UnmarshalUpload(v)\n}\n\nfunc (ec *executionContext) marshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx context.Context, sel ast.SelectionSet, v graphql.Upload) graphql.Marshaler {\n\tres := graphql.MarshalUpload(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalNUser2gqlgen5ᚐUser(ctx context.Context, sel ast.SelectionSet, v User) graphql.Marshaler {\n\treturn ec._User(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNUser2ᚖgqlgen5ᚐUser(ctx context.Context, sel ast.SelectionSet, v *User) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._User(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler {\n\treturn ec.___Directive(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) {\n\tvar vSlice []interface{}\n\tif v != nil {\n\t\tif tmp1, ok := v.([]interface{}); ok {\n\t\t\tvSlice = tmp1\n\t\t} else {\n\t\t\tvSlice = []interface{}{v}\n\t\t}\n\t}\n\tvar err error\n\tres := make([]string, len(vSlice))\n\tfor i := range vSlice {\n\t\tres[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn res, nil\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler {\n\treturn ec.___EnumValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler {\n\treturn ec.___Field(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler {\n\treturn ec.___InputValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\treturn graphql.MarshalBoolean(v)\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOBoolean2bool(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOBoolean2bool(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\treturn graphql.MarshalString(v)\n}\n\nfunc (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOString2string(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOString2string(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Schema2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v introspection.Schema) graphql.Marshaler {\n\treturn ec.___Schema(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Schema(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalO__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\tfc := &graphql.FieldContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithFieldContext(ctx, fc)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\n// endregion ***************************** type.gotpl *****************************\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen5/go.mod",
    "content": "module gqlgen5\n\ngo 1.13\n\nrequire (\n\tgithub.com/99designs/gqlgen v0.11.1\n\tgithub.com/vektah/gqlparser/v2 v2.0.1\n)\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen5/go.sum",
    "content": "github.com/99designs/gqlgen v0.11.1 h1:QoSL8/AAJ2T3UOeQbdnBR32JcG4pO08+P/g5jdbFkUg=\ngithub.com/99designs/gqlgen v0.11.1/go.mod h1:vjFOyBZ7NwDl+GdSD4PFn7BQn5Fy7ohJwXn7Vk8zz+c=\ngithub.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=\ngithub.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=\ngithub.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=\ngithub.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=\ngithub.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=\ngithub.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=\ngithub.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=\ngithub.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=\ngithub.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=\ngithub.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=\ngithub.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=\ngithub.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=\ngithub.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=\ngithub.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=\ngithub.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=\ngithub.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=\ngithub.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8=\ngithub.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=\ngithub.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=\ngithub.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=\ngithub.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=\ngithub.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=\ngithub.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=\ngithub.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=\ngithub.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=\ngithub.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o=\ngithub.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM=\ngolang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=\ngopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\nsourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=\nsourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen5/gqlgen.yml",
    "content": "schema:\n- schema.graphql\nexec:\n  filename: generated.go\nmodel:\n  filename: models_gen.go\nresolver:\n  filename: resolver.go\n  type: Resolver\n\nmodels:\n  Photo:\n    model: gqlgen5.Photo\n    fields:\n      user:\n        resolver: true\n  User:\n    fields:\n      photos:\n        resolver: true\n\nautobind: []\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen5/models_gen.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen5\n\ntype User struct {\n\tID       string `json:\"id\"`\n\tName     string `json:\"name\"`\n\tAvatar   string `json:\"avatar\"`\n\tFollowed bool   `json:\"followed\"`\n\t// возвращает фотограции данного пользователя\n\tPhotos []*Photo `json:\"photos\"`\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen5/photo.go",
    "content": "package gqlgen5\n\nimport (\n\t// \"log\"\n\t\"strconv\"\n)\n\ntype Photo struct {\n\tID     uint `json:\"id\"`\n\tUserID uint `json:\"-\"`\n\t// User     *User  `json:\"user\"`\n\tURL     string `json:\"url\"`\n\tComment string `json:\"comment\"`\n\tRating  int    `json:\"rating\"`\n\tLiked   bool   `json:\"liked\"`\n}\n\nfunc (ph *Photo) Id() string {\n\t// log.Println(\"call Photo.Id method\", ph.ID)\n\treturn strconv.Itoa(int(ph.ID))\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen5/queries.txt",
    "content": "query {\n  user(userID: \"1\") {\n    id\n    name\n    avatar\n  }\n}\n\n\n\n\nquery {\n  user(userID: \"1\") {\n    id\n    name\n    avatar\n    photos {id, url, user{\n        id\n        name\n        photos {\n            id, url\n        }\n    }}\n  }\n}\n\n# -----\n\nquery {\n  user(userID: \"1\") {\n    id\n    name\n    avatar\n    photos(count:20) {\n      id\n      url\n      user {\n        id\n        name\n        photos(count:100) {\n          id\n          url\n        }\n      }\n    }\n  }\n}\n\n# ----\n\nquery($userID: ID!, $cnt1:Int!, $cnt2:Int! ) {\n  user(userID: $userID) {\n    id\n    name\n    avatar\n    photos(count:$cnt1) {\n      id\n      url\n      user {\n        id\n        name\n        photos(count:$cnt2) {\n          id\n          url\n        }\n      }\n    }\n  }\n  photos(userID:$userID) {id, url}\n}\n\n\n{\n  \"userID\":\"1\",\n  \"cnt1\":10,\n  \"cnt2\":20\n}"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen5/resolver.go",
    "content": "package gqlgen5\n\n//go:generate go run github.com/99designs/gqlgen -v\n\nimport (\n\t\"context\"\n\t\"crypto/md5\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n)\n\ntype Resolver struct {\n\tPhotosData map[string]*Photo\n\tUsers      map[uint]*User\n}\n\nfunc (r *Resolver) Mutation() MutationResolver {\n\treturn &mutationResolver{r}\n}\nfunc (r *Resolver) Photo() PhotoResolver {\n\treturn &photoResolver{r}\n}\nfunc (r *Resolver) User() UserResolver {\n\treturn &userResolver{r}\n}\nfunc (r *Resolver) Query() QueryResolver {\n\treturn &queryResolver{r}\n}\n\ntype mutationResolver struct{ *Resolver }\n\nfunc (r *mutationResolver) RatePhoto(ctx context.Context, id string, direction string) (*Photo, error) {\n\tlog.Println(\"call mutationResolver.RatePhoto method with id\", id, direction)\n\trate := 1\n\tif direction != \"up\" {\n\t\trate = -1\n\t}\n\tph, ok := r.PhotosData[id]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no photo %v found\", id)\n\t}\n\tph.Rating += rate\n\treturn ph, nil\n}\n\nfunc (r *mutationResolver) UploadPhoto(ctx context.Context, comment string, file graphql.Upload) (*Photo, error) {\n\tsessionUserID := ctx.Value(\"userID\").(uint)\n\n\tcontent, err := ioutil.ReadAll(file.File)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\thasher := md5.New()\n\thasher.Write(content)\n\n\tlog.Printf(\"incoming file %v, %v bytes, md5 %x\", file.Filename, file.Size, hasher.Sum(nil))\n\tph := &Photo{\n\t\tID:      42,\n\t\tUserID:  sessionUserID,\n\t\tComment: comment,\n\t\tURL:     \"/photos/\" + file.Filename,\n\t}\n\tr.PhotosData[strconv.Itoa(int(ph.ID))] = ph\n\treturn ph, nil\n}\n\ntype userResolver struct{ *Resolver }\n\nfunc (r *userResolver) Photos(ctx context.Context, obj *User, count int) ([]*Photo, error) {\n\tlog.Println(\"call userResolver.Photos with count\", count)\n\tid, _ := strconv.Atoi(obj.ID)\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\tif ph.UserID != uint(id) {\n\t\t\tcontinue\n\t\t}\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n\ntype photoResolver struct{ *Resolver }\n\nfunc (r *photoResolver) ID(ctx context.Context, obj *Photo) (string, error) {\n\treturn obj.Id(), nil\n}\n\nfunc (r *photoResolver) User(ctx context.Context, obj *Photo) (*User, error) {\n\t// return r.Users[obj.UserID], nil\n\tlog.Println(\"call photoResolver.User\", obj.UserID)\n\tstart := time.Now()\n\tuser, err := ctx.Value(\"userLoaderKey\").(*UserLoader).Load(obj.UserID)\n\tlog.Println(\"get photoResolver.User\", obj.UserID, \"from UserLoader, time \", time.Since(start))\n\treturn user, err\n}\n\ntype queryResolver struct{ *Resolver }\n\nfunc (r *queryResolver) Timeline(ctx context.Context) ([]*Photo, error) {\n\tlog.Println(\"call queryResolver.Timeline with ctx.userID\", ctx.Value(\"userID\"))\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n\nfunc (r *queryResolver) User(ctx context.Context, userID string) (*User, error) {\n\tlog.Println(\"call queryResolver.User for\", userID)\n\tid, _ := strconv.Atoi(userID)\n\treturn r.Users[uint(id)], nil\n}\n\nfunc (r *queryResolver) Photos(ctx context.Context, userID string) ([]*Photo, error) {\n\tlog.Println(\"call queryResolver.Photos\")\n\tid, _ := strconv.Atoi(userID)\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\tif ph.UserID != uint(id) {\n\t\t\tcontinue\n\t\t}\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen5/schema.graphql",
    "content": "# gqlgen знает как с этим работать и что парсить это надо через multipart-form\nscalar Upload\n\ntype User {\n  id: ID!\n  name: String!\n  avatar: String!\n  followed: Boolean!\n\n  # subscriptions(count: Int! = 10): [User!]!\n  # subscribers(count: Int! = 10): [User!]!\n  \"\"\"возвращает фотограции данного пользователя\"\"\"\n  photos(count: Int! = 10): [Photo!]!\n}\n\ntype Photo {\n  id: ID!\n  user: User!\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  \"\"\"возвращает ленту текущего пользователя - фото тех, на кого он подписан\"\"\"\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,name,avatar}}\n  \"\"\"возвращает выбранного пользователя\"\"\"\n  user(userID: ID!): User!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  \"\"\"возвращает фотограции выбранного пользователя\"\"\"\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n\n  uploadPhoto(comment: String!, file: Upload!): Photo!\n}\n\n# go run github.com/99designs/gqlgen init\n# go run github.com/99designs/gqlgen -v\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen5/server/server.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\tgqlgen \"gqlgen5\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/99designs/gqlgen/handler\"\n)\n\n/*\ncurl localhost:8080/query \\\n  -F operations='{ \"query\": \"mutation($comment: String!, $file: Upload!) { uploadPhoto(comment: $comment, file: $file) { id } }\", \"variables\": { \"comment\": \"building 5 comment\", \"file\": null } }' \\\n  -F map='{ \"0\": [\"variables.file\"] }' \\\n  -F 0=@./test_file.txt \\\n  --trace-ascii -\n\n\n  {\n  query: `\n    mutation($comment: String!, $file: Upload!) {\n      uploadPhoto(comment: $comment, file: $file) {\n        id\n      }\n    }\n  `,\n  variables: {\n\tcomment: \"building 5 comment\",\n    file: File // test_file.txt\n  }\n}\n\n\n\n*/\n\nvar users = map[uint]*gqlgen.User{\n\t1: {\n\t\tID:     \"1\",\n\t\tName:   \"rvasily\",\n\t\tAvatar: \"https://via.placeholder.com/150\",\n\t},\n\t2: {\n\t\tID:     \"2\",\n\t\tName:   \"v.romanov\",\n\t\tAvatar: \"https://via.placeholder.com/150\",\n\t},\n}\n\nvar photos = map[string]*gqlgen.Photo{\n\t\"1\": {\n\t\tID:      1,\n\t\tUserID:  1,\n\t\tURL:     \"https://via.placeholder.com/300\",\n\t\tComment: \"from studio\",\n\t\tRating:  1,\n\t\tLiked:   true,\n\t},\n\t// \"2\": {\n\t// \tID:      2,\n\t// \tUserID:  1,\n\t// \tURL:     \"https://via.placeholder.com/300\",\n\t// \tComment: \"cool view\",\n\t// \tRating:  0,\n\t// \tLiked:   false,\n\t// },\n\t\"3\": {\n\t\tID:      3,\n\t\tUserID:  2,\n\t\tURL:     \"https://via.placeholder.com/300\",\n\t\tComment: \"at work\",\n\t\tRating:  0,\n\t\tLiked:   false,\n\t},\n}\n\n// go run github.com/vektah/dataloaden UserLoader uint *coursera/3p/graphql/gqlgen3.User\n\nfunc UserLoaderMiddleware(resolver *gqlgen.Resolver, next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tcfg := gqlgen.UserLoaderConfig{\n\t\t\tMaxBatch: 100,\n\t\t\tWait:     1 * time.Millisecond,\n\t\t\tFetch: func(ids []uint) ([]*gqlgen.User, []error) {\n\t\t\t\t// имеем доступ до r *http.Request - там context с сессией пользователя\n\t\t\t\tsessionUserID := r.Context().Value(\"userID\").(uint)\n\t\t\t\tlog.Printf(\"UserLoader Request - ids %v for user %v\\n\", ids, sessionUserID)\n\n\t\t\t\tlog.Printf(\"request %v\\n\", r)\n\t\t\t\tlog.Printf(\"ctx %v\\n\", r.Context())\n\n\t\t\t\tusers := make([]*gqlgen.User, len(ids))\n\t\t\t\tfor i, id := range ids {\n\t\t\t\t\t// имеем доступ до resolver *gqlgen.Resolver - там коннет к базе\n\t\t\t\t\tusers[i] = resolver.Users[id]\n\t\t\t\t}\n\t\t\t\treturn users, nil\n\t\t\t},\n\t\t}\n\t\tuserLoader := gqlgen.NewUserLoader(cfg)\n\t\tctx := context.WithValue(r.Context(), \"userLoaderKey\", userLoader)\n\t\tr = r.WithContext(ctx)\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n\nfunc AuthMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t// log.Println(\"new request\")\n\t\tctx := context.WithValue(r.Context(), \"userID\", uint(1))\n\t\tr = r.WithContext(ctx)\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n\nfunc main() {\n\thttp.Handle(\"/\", handler.Playground(\"GraphQL playground\", \"/query\"))\n\n\tresolver := &gqlgen.Resolver{\n\t\tUsers:      users,\n\t\tPhotosData: photos,\n\t}\n\tcfg := gqlgen.Config{\n\t\tResolvers: resolver,\n\t}\n\tcfg.Complexity.User.Photos = func(childComplexity, count int) int {\n\t\treturn count * childComplexity\n\t}\n\n\tgqlHandler := handler.GraphQL(\n\t\tgqlgen.NewExecutableSchema(cfg),\n\t\thandler.ComplexityLimit(500),\n\t)\n\thandler := UserLoaderMiddleware(resolver, gqlHandler)\n\thandler = AuthMiddleware(handler)\n\thttp.Handle(\"/query\", handler)\n\n\tport := \"8080\"\n\tlog.Printf(\"connect to http://localhost:%s/ for GraphQL playground\", port)\n\tlog.Fatal(http.ListenAndServe(\":\"+port, nil))\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen5/test_file.txt",
    "content": "TEST_FILE_XXXXXXXXXXXXXXXXXX"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen5/userloader_gen.go",
    "content": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage gqlgen5\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\n// UserLoaderConfig captures the config to create a new UserLoader\ntype UserLoaderConfig struct {\n\t// Fetch is a method that provides the data for the loader\n\tFetch func(keys []uint) ([]*User, []error)\n\n\t// Wait is how long wait before sending a batch\n\tWait time.Duration\n\n\t// MaxBatch will limit the maximum number of keys to send in one batch, 0 = not limit\n\tMaxBatch int\n}\n\n// NewUserLoader creates a new UserLoader given a fetch, wait, and maxBatch\nfunc NewUserLoader(config UserLoaderConfig) *UserLoader {\n\treturn &UserLoader{\n\t\tfetch:    config.Fetch,\n\t\twait:     config.Wait,\n\t\tmaxBatch: config.MaxBatch,\n\t}\n}\n\n// UserLoader batches and caches requests\ntype UserLoader struct {\n\t// this method provides the data for the loader\n\tfetch func(keys []uint) ([]*User, []error)\n\n\t// how long to done before sending a batch\n\twait time.Duration\n\n\t// this will limit the maximum number of keys to send in one batch, 0 = no limit\n\tmaxBatch int\n\n\t// INTERNAL\n\n\t// lazily created cache\n\tcache map[uint]*User\n\n\t// the current batch. keys will continue to be collected until timeout is hit,\n\t// then everything will be sent to the fetch method and out to the listeners\n\tbatch *userLoaderBatch\n\n\t// mutex to prevent races\n\tmu sync.Mutex\n}\n\ntype userLoaderBatch struct {\n\tkeys    []uint\n\tdata    []*User\n\terror   []error\n\tclosing bool\n\tdone    chan struct{}\n}\n\n// Load a User by key, batching and caching will be applied automatically\nfunc (l *UserLoader) Load(key uint) (*User, error) {\n\treturn l.LoadThunk(key)()\n}\n\n// LoadThunk returns a function that when called will block waiting for a User.\n// This method should be used if you want one goroutine to make requests to many\n// different data loaders without blocking until the thunk is called.\nfunc (l *UserLoader) LoadThunk(key uint) func() (*User, error) {\n\tl.mu.Lock()\n\tif it, ok := l.cache[key]; ok {\n\t\tl.mu.Unlock()\n\t\treturn func() (*User, error) {\n\t\t\treturn it, nil\n\t\t}\n\t}\n\tif l.batch == nil {\n\t\tl.batch = &userLoaderBatch{done: make(chan struct{})}\n\t}\n\tbatch := l.batch\n\tpos := batch.keyIndex(l, key)\n\tl.mu.Unlock()\n\n\treturn func() (*User, error) {\n\t\t<-batch.done\n\n\t\tvar data *User\n\t\tif pos < len(batch.data) {\n\t\t\tdata = batch.data[pos]\n\t\t}\n\n\t\tvar err error\n\t\t// its convenient to be able to return a single error for everything\n\t\tif len(batch.error) == 1 {\n\t\t\terr = batch.error[0]\n\t\t} else if batch.error != nil {\n\t\t\terr = batch.error[pos]\n\t\t}\n\n\t\tif err == nil {\n\t\t\tl.mu.Lock()\n\t\t\tl.unsafeSet(key, data)\n\t\t\tl.mu.Unlock()\n\t\t}\n\n\t\treturn data, err\n\t}\n}\n\n// LoadAll fetches many keys at once. It will be broken into appropriate sized\n// sub batches depending on how the loader is configured\nfunc (l *UserLoader) LoadAll(keys []uint) ([]*User, []error) {\n\tresults := make([]func() (*User, error), len(keys))\n\n\tfor i, key := range keys {\n\t\tresults[i] = l.LoadThunk(key)\n\t}\n\n\tusers := make([]*User, len(keys))\n\terrors := make([]error, len(keys))\n\tfor i, thunk := range results {\n\t\tusers[i], errors[i] = thunk()\n\t}\n\treturn users, errors\n}\n\n// LoadAllThunk returns a function that when called will block waiting for a Users.\n// This method should be used if you want one goroutine to make requests to many\n// different data loaders without blocking until the thunk is called.\nfunc (l *UserLoader) LoadAllThunk(keys []uint) func() ([]*User, []error) {\n\tresults := make([]func() (*User, error), len(keys))\n\tfor i, key := range keys {\n\t\tresults[i] = l.LoadThunk(key)\n\t}\n\treturn func() ([]*User, []error) {\n\t\tusers := make([]*User, len(keys))\n\t\terrors := make([]error, len(keys))\n\t\tfor i, thunk := range results {\n\t\t\tusers[i], errors[i] = thunk()\n\t\t}\n\t\treturn users, errors\n\t}\n}\n\n// Prime the cache with the provided key and value. If the key already exists, no change is made\n// and false is returned.\n// (To forcefully prime the cache, clear the key first with loader.clear(key).prime(key, value).)\nfunc (l *UserLoader) Prime(key uint, value *User) bool {\n\tl.mu.Lock()\n\tvar found bool\n\tif _, found = l.cache[key]; !found {\n\t\t// make a copy when writing to the cache, its easy to pass a pointer in from a loop var\n\t\t// and end up with the whole cache pointing to the same value.\n\t\tcpy := *value\n\t\tl.unsafeSet(key, &cpy)\n\t}\n\tl.mu.Unlock()\n\treturn !found\n}\n\n// Clear the value at key from the cache, if it exists\nfunc (l *UserLoader) Clear(key uint) {\n\tl.mu.Lock()\n\tdelete(l.cache, key)\n\tl.mu.Unlock()\n}\n\nfunc (l *UserLoader) unsafeSet(key uint, value *User) {\n\tif l.cache == nil {\n\t\tl.cache = map[uint]*User{}\n\t}\n\tl.cache[key] = value\n}\n\n// keyIndex will return the location of the key in the batch, if its not found\n// it will add the key to the batch\nfunc (b *userLoaderBatch) keyIndex(l *UserLoader, key uint) int {\n\tfor i, existingKey := range b.keys {\n\t\tif key == existingKey {\n\t\t\treturn i\n\t\t}\n\t}\n\n\tpos := len(b.keys)\n\tb.keys = append(b.keys, key)\n\tif pos == 0 {\n\t\tgo b.startTimer(l)\n\t}\n\n\tif l.maxBatch != 0 && pos >= l.maxBatch-1 {\n\t\tif !b.closing {\n\t\t\tb.closing = true\n\t\t\tl.batch = nil\n\t\t\tgo b.end(l)\n\t\t}\n\t}\n\n\treturn pos\n}\n\nfunc (b *userLoaderBatch) startTimer(l *UserLoader) {\n\ttime.Sleep(l.wait)\n\tl.mu.Lock()\n\n\t// we must have hit a batch limit and are already finalizing this batch\n\tif b.closing {\n\t\tl.mu.Unlock()\n\t\treturn\n\t}\n\n\tl.batch = nil\n\tl.mu.Unlock()\n\n\tb.end(l)\n}\n\nfunc (b *userLoaderBatch) end(l *UserLoader) {\n\tb.data, b.error = l.fetch(b.keys)\n\tclose(b.done)\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen6/generated.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen6\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"sync\"\n\t\"sync/atomic\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\t\"github.com/99designs/gqlgen/graphql/introspection\"\n\t\"github.com/vektah/gqlparser\"\n\t\"github.com/vektah/gqlparser/ast\"\n)\n\n// region    ************************** generated!.gotpl **************************\n\n// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.\nfunc NewExecutableSchema(cfg Config) graphql.ExecutableSchema {\n\treturn &executableSchema{\n\t\tresolvers:  cfg.Resolvers,\n\t\tdirectives: cfg.Directives,\n\t\tcomplexity: cfg.Complexity,\n\t}\n}\n\ntype Config struct {\n\tResolvers  ResolverRoot\n\tDirectives DirectiveRoot\n\tComplexity ComplexityRoot\n}\n\ntype ResolverRoot interface {\n\tMutation() MutationResolver\n\tPhoto() PhotoResolver\n\tQuery() QueryResolver\n\tUser() UserResolver\n}\n\ntype DirectiveRoot struct {\n\tIsSubscribed func(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error)\n\n\tValidation func(ctx context.Context, obj interface{}, next graphql.Resolver, funcs []string) (res interface{}, err error)\n}\n\ntype ComplexityRoot struct {\n\tMutation struct {\n\t\tRatePhoto   func(childComplexity int, photoID string, direction string) int\n\t\tUploadPhoto func(childComplexity int, comment string, file graphql.Upload) int\n\t}\n\n\tPhoto struct {\n\t\tComment func(childComplexity int) int\n\t\tID      func(childComplexity int) int\n\t\tLiked   func(childComplexity int) int\n\t\tRating  func(childComplexity int) int\n\t\tURL     func(childComplexity int) int\n\t\tUser    func(childComplexity int) int\n\t}\n\n\tQuery struct {\n\t\tPhotos   func(childComplexity int, userID string) int\n\t\tTimeline func(childComplexity int) int\n\t\tUser     func(childComplexity int, userID string) int\n\t}\n\n\tUser struct {\n\t\tAvatar   func(childComplexity int) int\n\t\tFollowed func(childComplexity int) int\n\t\tID       func(childComplexity int) int\n\t\tName     func(childComplexity int) int\n\t\tPhotos   func(childComplexity int, count int) int\n\t}\n}\n\ntype MutationResolver interface {\n\tRatePhoto(ctx context.Context, photoID string, direction string) (*Photo, error)\n\tUploadPhoto(ctx context.Context, comment string, file graphql.Upload) (*Photo, error)\n}\ntype PhotoResolver interface {\n\tID(ctx context.Context, obj *Photo) (string, error)\n\tUser(ctx context.Context, obj *Photo) (*User, error)\n}\ntype QueryResolver interface {\n\tTimeline(ctx context.Context) ([]*Photo, error)\n\tUser(ctx context.Context, userID string) (*User, error)\n\tPhotos(ctx context.Context, userID string) ([]*Photo, error)\n}\ntype UserResolver interface {\n\tPhotos(ctx context.Context, obj *User, count int) ([]*Photo, error)\n}\n\ntype executableSchema struct {\n\tresolvers  ResolverRoot\n\tdirectives DirectiveRoot\n\tcomplexity ComplexityRoot\n}\n\nfunc (e *executableSchema) Schema() *ast.Schema {\n\treturn parsedSchema\n}\n\nfunc (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) {\n\tec := executionContext{nil, e}\n\t_ = ec\n\tswitch typeName + \".\" + field {\n\n\tcase \"Mutation.ratePhoto\":\n\t\tif e.complexity.Mutation.RatePhoto == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Mutation_ratePhoto_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Mutation.RatePhoto(childComplexity, args[\"photoID\"].(string), args[\"direction\"].(string)), true\n\n\tcase \"Mutation.uploadPhoto\":\n\t\tif e.complexity.Mutation.UploadPhoto == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Mutation_uploadPhoto_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Mutation.UploadPhoto(childComplexity, args[\"comment\"].(string), args[\"file\"].(graphql.Upload)), true\n\n\tcase \"Photo.comment\":\n\t\tif e.complexity.Photo.Comment == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Comment(childComplexity), true\n\n\tcase \"Photo.id\":\n\t\tif e.complexity.Photo.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.ID(childComplexity), true\n\n\tcase \"Photo.liked\":\n\t\tif e.complexity.Photo.Liked == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Liked(childComplexity), true\n\n\tcase \"Photo.rating\":\n\t\tif e.complexity.Photo.Rating == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.Rating(childComplexity), true\n\n\tcase \"Photo.url\":\n\t\tif e.complexity.Photo.URL == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.URL(childComplexity), true\n\n\tcase \"Photo.user\":\n\t\tif e.complexity.Photo.User == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Photo.User(childComplexity), true\n\n\tcase \"Query.photos\":\n\t\tif e.complexity.Query.Photos == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Query_photos_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Query.Photos(childComplexity, args[\"userID\"].(string)), true\n\n\tcase \"Query.timeline\":\n\t\tif e.complexity.Query.Timeline == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.Query.Timeline(childComplexity), true\n\n\tcase \"Query.user\":\n\t\tif e.complexity.Query.User == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_Query_user_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.Query.User(childComplexity, args[\"userID\"].(string)), true\n\n\tcase \"User.avatar\":\n\t\tif e.complexity.User.Avatar == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Avatar(childComplexity), true\n\n\tcase \"User.followed\":\n\t\tif e.complexity.User.Followed == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Followed(childComplexity), true\n\n\tcase \"User.id\":\n\t\tif e.complexity.User.ID == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.ID(childComplexity), true\n\n\tcase \"User.name\":\n\t\tif e.complexity.User.Name == nil {\n\t\t\tbreak\n\t\t}\n\n\t\treturn e.complexity.User.Name(childComplexity), true\n\n\tcase \"User.photos\":\n\t\tif e.complexity.User.Photos == nil {\n\t\t\tbreak\n\t\t}\n\n\t\targs, err := ec.field_User_photos_args(context.TODO(), rawArgs)\n\t\tif err != nil {\n\t\t\treturn 0, false\n\t\t}\n\n\t\treturn e.complexity.User.Photos(childComplexity, args[\"count\"].(int)), true\n\n\t}\n\treturn 0, false\n}\n\nfunc (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {\n\tec := executionContext{graphql.GetRequestContext(ctx), e}\n\n\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\tdata := ec._Query(ctx, op.SelectionSet)\n\t\tvar buf bytes.Buffer\n\t\tdata.MarshalGQL(&buf)\n\t\treturn buf.Bytes()\n\t})\n\n\treturn &graphql.Response{\n\t\tData:       buf,\n\t\tErrors:     ec.Errors,\n\t\tExtensions: ec.Extensions,\n\t}\n}\n\nfunc (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {\n\tec := executionContext{graphql.GetRequestContext(ctx), e}\n\n\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\tdata := ec._Mutation(ctx, op.SelectionSet)\n\t\tvar buf bytes.Buffer\n\t\tdata.MarshalGQL(&buf)\n\t\treturn buf.Bytes()\n\t})\n\n\treturn &graphql.Response{\n\t\tData:       buf,\n\t\tErrors:     ec.Errors,\n\t\tExtensions: ec.Extensions,\n\t}\n}\n\nfunc (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response {\n\treturn graphql.OneShot(graphql.ErrorResponse(ctx, \"subscriptions are not supported\"))\n}\n\ntype executionContext struct {\n\t*graphql.RequestContext\n\t*executableSchema\n}\n\nfunc (ec *executionContext) introspectSchema() (*introspection.Schema, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapSchema(parsedSchema), nil\n}\n\nfunc (ec *executionContext) introspectType(name string) (*introspection.Type, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil\n}\n\nvar parsedSchema = gqlparser.MustLoadSchema(\n\t&ast.Source{Name: \"schema.graphql\", Input: `# gqlgen знает как с этим работать и что парсить это надо через multipart-form\nscalar Upload\n\ndirective @isSubscribed on FIELD_DEFINITION\ndirective @validation(funcs: [String!]!) on ARGUMENT_DEFINITION\n\ntype User {\n  id: ID!\n  name: String!\n  avatar: String!\n  followed: Boolean!\n\n  # subscriptions(count: Int! = 10): [User!]!\n  # subscribers(count: Int! = 10): [User!]!\n  \"\"\"возвращает фотограции данного пользователя\"\"\"\n  photos(count: Int! = 10): [Photo!]! @isSubscribed\n}\n\ntype Photo {\n  id: ID!\n  user: User!\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  \"\"\"возвращает ленту текущего пользователя - фото тех, на кого он подписан\"\"\"\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,name,avatar}}\n  \"\"\"возвращает выбранного пользователя\"\"\"\n  user(userID: ID!): User!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  \"\"\"возвращает фотограции выбранного пользователя\"\"\"\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n\n  uploadPhoto(\n    comment: String! @validation(funcs: [\"noBadUrls\", \"noMatureLanguage\"])\n    file: Upload!\n  ): Photo! \n}\n\n# go run github.com/99designs/gqlgen init\n# go run github.com/99designs/gqlgen -v\n`},\n)\n\n// endregion ************************** generated!.gotpl **************************\n\n// region    ***************************** args.gotpl *****************************\n\nfunc (ec *executionContext) dir_validation_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 []string\n\tif tmp, ok := rawArgs[\"funcs\"]; ok {\n\t\targ0, err = ec.unmarshalNString2ᚕstringᚄ(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"funcs\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Mutation_ratePhoto_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"photoID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"photoID\"] = arg0\n\tvar arg1 string\n\tif tmp, ok := rawArgs[\"direction\"]; ok {\n\t\targ1, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"direction\"] = arg1\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Mutation_uploadPhoto_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"comment\"]; ok {\n\t\tdirective0 := func(ctx context.Context) (interface{}, error) { return ec.unmarshalNString2string(ctx, tmp) }\n\t\tdirective1 := func(ctx context.Context) (interface{}, error) {\n\t\t\tfuncs, err := ec.unmarshalNString2ᚕstringᚄ(ctx, []interface{}{\"noBadUrls\", \"noMatureLanguage\"})\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif ec.directives.Validation == nil {\n\t\t\t\treturn nil, errors.New(\"directive validation is not implemented\")\n\t\t\t}\n\t\t\treturn ec.directives.Validation(ctx, rawArgs, directive0, funcs)\n\t\t}\n\n\t\ttmp, err = directive1(ctx)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif data, ok := tmp.(string); ok {\n\t\t\targ0 = data\n\t\t} else {\n\t\t\treturn nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp)\n\t\t}\n\t}\n\targs[\"comment\"] = arg0\n\tvar arg1 graphql.Upload\n\tif tmp, ok := rawArgs[\"file\"]; ok {\n\t\targ1, err = ec.unmarshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"file\"] = arg1\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"name\"]; ok {\n\t\targ0, err = ec.unmarshalNString2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"name\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query_photos_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"userID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"userID\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 string\n\tif tmp, ok := rawArgs[\"userID\"]; ok {\n\t\targ0, err = ec.unmarshalNID2string(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"userID\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field_User_photos_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 int\n\tif tmp, ok := rawArgs[\"count\"]; ok {\n\t\targ0, err = ec.unmarshalNInt2int(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"count\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\nfunc (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\tvar err error\n\targs := map[string]interface{}{}\n\tvar arg0 bool\n\tif tmp, ok := rawArgs[\"includeDeprecated\"]; ok {\n\t\targ0, err = ec.unmarshalOBoolean2bool(ctx, tmp)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\targs[\"includeDeprecated\"] = arg0\n\treturn args, nil\n}\n\n// endregion ***************************** args.gotpl *****************************\n\n// region    ************************** directives.gotpl **************************\n\n// endregion ************************** directives.gotpl **************************\n\n// region    **************************** field.gotpl *****************************\n\nfunc (ec *executionContext) _Mutation_ratePhoto(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Mutation\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Mutation_ratePhoto_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\trctx.Args = args\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Mutation().RatePhoto(rctx, args[\"photoID\"].(string), args[\"direction\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*Photo)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNPhoto2ᚖgqlgen6ᚐPhoto(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Mutation_uploadPhoto(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Mutation\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Mutation_uploadPhoto_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\trctx.Args = args\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Mutation().UploadPhoto(rctx, args[\"comment\"].(string), args[\"file\"].(graphql.Upload))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*Photo)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNPhoto2ᚖgqlgen6ᚐPhoto(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_id(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Photo().ID(rctx, obj)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_user(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Photo().User(rctx, obj)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*User)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNUser2ᚖgqlgen6ᚐUser(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_url(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.URL, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_comment(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Comment, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_rating(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Rating, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(int)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNInt2int(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Photo_liked(ctx context.Context, field graphql.CollectedField, obj *Photo) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Photo\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Liked, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_timeline(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Timeline(rctx)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen6ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_user(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query_user_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\trctx.Args = args\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().User(rctx, args[\"userID\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*User)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNUser2ᚖgqlgen6ᚐUser(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query_photos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query_photos_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\trctx.Args = args\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.resolvers.Query().Photos(rctx, args[\"userID\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen6ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_Query___type_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\trctx.Args = args\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectType(args[\"name\"].(string))\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"Query\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn ec.introspectSchema()\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Schema)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.ID, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNID2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_name(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_avatar(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Avatar, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_followed(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Followed, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) _User_photos(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"User\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field_User_photos_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\trctx.Args = args\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tdirective0 := func(rctx context.Context) (interface{}, error) {\n\t\t\tctx = rctx // use context from middleware stack in children\n\t\t\treturn ec.resolvers.User().Photos(rctx, obj, args[\"count\"].(int))\n\t\t}\n\t\tdirective1 := func(ctx context.Context) (interface{}, error) {\n\t\t\tif ec.directives.IsSubscribed == nil {\n\t\t\t\treturn nil, errors.New(\"directive isSubscribed is not implemented\")\n\t\t\t}\n\t\t\treturn ec.directives.IsSubscribed(ctx, obj, directive0)\n\t\t}\n\n\t\ttmp, err := directive1(rctx)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif tmp == nil {\n\t\t\treturn nil, nil\n\t\t}\n\t\tif data, ok := tmp.([]*Photo); ok {\n\t\t\treturn data, nil\n\t\t}\n\t\treturn nil, fmt.Errorf(`unexpected type %T from directive, should be []*gqlgen6.Photo`, tmp)\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]*Photo)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNPhoto2ᚕᚖgqlgen6ᚐPhotoᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Locations, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Directive\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__EnumValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Args, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.IsDeprecated(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(bool)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNBoolean2bool(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Field\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DeprecationReason(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalNString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Type, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__InputValue\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: false,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.DefaultValue, nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Types(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.QueryType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.MutationType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.SubscriptionType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Schema\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Directives(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Directive)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Kind(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\tif !ec.HasError(rctx) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalN__TypeKind2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Name(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2ᚖstring(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Description(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(string)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalOString2string(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_fields_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\trctx.Args = args\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Fields(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Field)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.Interfaces(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.PossibleTypes(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\trawArgs := field.ArgumentMap(ec.Variables)\n\targs, err := ec.field___Type_enumValues_args(ctx, rawArgs)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\trctx.Args = args\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.EnumValues(args[\"includeDeprecated\"].(bool)), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.EnumValue)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.InputFields(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.([]introspection.InputValue)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res)\n}\n\nfunc (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) {\n\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = graphql.Null\n\t\t}\n\t\tec.Tracer.EndFieldExecution(ctx)\n\t}()\n\trctx := &graphql.ResolverContext{\n\t\tObject:   \"__Type\",\n\t\tField:    field,\n\t\tArgs:     nil,\n\t\tIsMethod: true,\n\t}\n\tctx = graphql.WithResolverContext(ctx, rctx)\n\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\tresTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {\n\t\tctx = rctx // use context from middleware stack in children\n\t\treturn obj.OfType(), nil\n\t})\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn graphql.Null\n\t}\n\tif resTmp == nil {\n\t\treturn graphql.Null\n\t}\n\tres := resTmp.(*introspection.Type)\n\trctx.Result = res\n\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\treturn ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)\n}\n\n// endregion **************************** field.gotpl *****************************\n\n// region    **************************** input.gotpl *****************************\n\n// endregion **************************** input.gotpl *****************************\n\n// region    ************************** interface.gotpl ***************************\n\n// endregion ************************** interface.gotpl ***************************\n\n// region    **************************** object.gotpl ****************************\n\nvar mutationImplementors = []string{\"Mutation\"}\n\nfunc (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, mutationImplementors)\n\n\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\tObject: \"Mutation\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Mutation\")\n\t\tcase \"ratePhoto\":\n\t\t\tout.Values[i] = ec._Mutation_ratePhoto(ctx, field)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"uploadPhoto\":\n\t\t\tout.Values[i] = ec._Mutation_uploadPhoto(ctx, field)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar photoImplementors = []string{\"Photo\"}\n\nfunc (ec *executionContext) _Photo(ctx context.Context, sel ast.SelectionSet, obj *Photo) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, photoImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Photo\")\n\t\tcase \"id\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Photo_id(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"user\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Photo_user(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"url\":\n\t\t\tout.Values[i] = ec._Photo_url(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"comment\":\n\t\t\tout.Values[i] = ec._Photo_comment(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"rating\":\n\t\t\tout.Values[i] = ec._Photo_rating(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"liked\":\n\t\t\tout.Values[i] = ec._Photo_liked(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar queryImplementors = []string{\"Query\"}\n\nfunc (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, queryImplementors)\n\n\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\tObject: \"Query\",\n\t})\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"Query\")\n\t\tcase \"timeline\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_timeline(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"user\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_user(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"photos\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._Query_photos(ctx, field)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tcase \"__type\":\n\t\t\tout.Values[i] = ec._Query___type(ctx, field)\n\t\tcase \"__schema\":\n\t\t\tout.Values[i] = ec._Query___schema(ctx, field)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar userImplementors = []string{\"User\"}\n\nfunc (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *User) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, userImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"User\")\n\t\tcase \"id\":\n\t\t\tout.Values[i] = ec._User_id(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec._User_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"avatar\":\n\t\t\tout.Values[i] = ec._User_avatar(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"followed\":\n\t\t\tout.Values[i] = ec._User_followed(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t}\n\t\tcase \"photos\":\n\t\t\tfield := field\n\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\tres = ec._User_photos(ctx, field, obj)\n\t\t\t\tif res == graphql.Null {\n\t\t\t\t\tatomic.AddUint32(&invalids, 1)\n\t\t\t\t}\n\t\t\t\treturn res\n\t\t\t})\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __DirectiveImplementors = []string{\"__Directive\"}\n\nfunc (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, __DirectiveImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Directive\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Directive_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Directive_description(ctx, field, obj)\n\t\tcase \"locations\":\n\t\t\tout.Values[i] = ec.___Directive_locations(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Directive_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __EnumValueImplementors = []string{\"__EnumValue\"}\n\nfunc (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, __EnumValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__EnumValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___EnumValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___EnumValue_description(ctx, field, obj)\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __FieldImplementors = []string{\"__Field\"}\n\nfunc (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, __FieldImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Field\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Field_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Field_description(ctx, field, obj)\n\t\tcase \"args\":\n\t\t\tout.Values[i] = ec.___Field_args(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___Field_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"isDeprecated\":\n\t\t\tout.Values[i] = ec.___Field_isDeprecated(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"deprecationReason\":\n\t\t\tout.Values[i] = ec.___Field_deprecationReason(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __InputValueImplementors = []string{\"__InputValue\"}\n\nfunc (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, __InputValueImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__InputValue\")\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___InputValue_name(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___InputValue_description(ctx, field, obj)\n\t\tcase \"type\":\n\t\t\tout.Values[i] = ec.___InputValue_type(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"defaultValue\":\n\t\t\tout.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __SchemaImplementors = []string{\"__Schema\"}\n\nfunc (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, __SchemaImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Schema\")\n\t\tcase \"types\":\n\t\t\tout.Values[i] = ec.___Schema_types(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"queryType\":\n\t\t\tout.Values[i] = ec.___Schema_queryType(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"mutationType\":\n\t\t\tout.Values[i] = ec.___Schema_mutationType(ctx, field, obj)\n\t\tcase \"subscriptionType\":\n\t\t\tout.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj)\n\t\tcase \"directives\":\n\t\t\tout.Values[i] = ec.___Schema_directives(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\nvar __TypeImplementors = []string{\"__Type\"}\n\nfunc (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.RequestContext, sel, __TypeImplementors)\n\n\tout := graphql.NewFieldSet(fields)\n\tvar invalids uint32\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString(\"__Type\")\n\t\tcase \"kind\":\n\t\t\tout.Values[i] = ec.___Type_kind(ctx, field, obj)\n\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\tinvalids++\n\t\t\t}\n\t\tcase \"name\":\n\t\t\tout.Values[i] = ec.___Type_name(ctx, field, obj)\n\t\tcase \"description\":\n\t\t\tout.Values[i] = ec.___Type_description(ctx, field, obj)\n\t\tcase \"fields\":\n\t\t\tout.Values[i] = ec.___Type_fields(ctx, field, obj)\n\t\tcase \"interfaces\":\n\t\t\tout.Values[i] = ec.___Type_interfaces(ctx, field, obj)\n\t\tcase \"possibleTypes\":\n\t\t\tout.Values[i] = ec.___Type_possibleTypes(ctx, field, obj)\n\t\tcase \"enumValues\":\n\t\t\tout.Values[i] = ec.___Type_enumValues(ctx, field, obj)\n\t\tcase \"inputFields\":\n\t\t\tout.Values[i] = ec.___Type_inputFields(ctx, field, obj)\n\t\tcase \"ofType\":\n\t\t\tout.Values[i] = ec.___Type_ofType(ctx, field, obj)\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalids > 0 {\n\t\treturn graphql.Null\n\t}\n\treturn out\n}\n\n// endregion **************************** object.gotpl ****************************\n\n// region    ***************************** type.gotpl *****************************\n\nfunc (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\tres := graphql.MarshalBoolean(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalID(v)\n}\n\nfunc (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalID(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) {\n\treturn graphql.UnmarshalInt(v)\n}\n\nfunc (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler {\n\tres := graphql.MarshalInt(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalNPhoto2gqlgen6ᚐPhoto(ctx context.Context, sel ast.SelectionSet, v Photo) graphql.Marshaler {\n\treturn ec._Photo(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNPhoto2ᚕᚖgqlgen6ᚐPhotoᚄ(ctx context.Context, sel ast.SelectionSet, v []*Photo) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalNPhoto2ᚖgqlgen6ᚐPhoto(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalNPhoto2ᚖgqlgen6ᚐPhoto(ctx context.Context, sel ast.SelectionSet, v *Photo) graphql.Marshaler {\n\tif v == nil {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._Photo(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalNString2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) {\n\tvar vSlice []interface{}\n\tif v != nil {\n\t\tif tmp1, ok := v.([]interface{}); ok {\n\t\t\tvSlice = tmp1\n\t\t} else {\n\t\t\tvSlice = []interface{}{v}\n\t\t}\n\t}\n\tvar err error\n\tres := make([]string, len(vSlice))\n\tfor i := range vSlice {\n\t\tres[i], err = ec.unmarshalNString2string(ctx, vSlice[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn res, nil\n}\n\nfunc (ec *executionContext) marshalNString2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tfor i := range v {\n\t\tret[i] = ec.marshalNString2string(ctx, sel, v[i])\n\t}\n\n\treturn ret\n}\n\nfunc (ec *executionContext) unmarshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx context.Context, v interface{}) (graphql.Upload, error) {\n\treturn graphql.UnmarshalUpload(v)\n}\n\nfunc (ec *executionContext) marshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx context.Context, sel ast.SelectionSet, v graphql.Upload) graphql.Marshaler {\n\tres := graphql.MarshalUpload(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) marshalNUser2gqlgen6ᚐUser(ctx context.Context, sel ast.SelectionSet, v User) graphql.Marshaler {\n\treturn ec._User(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalNUser2ᚖgqlgen6ᚐUser(ctx context.Context, sel ast.SelectionSet, v *User) graphql.Marshaler {\n\tif v == nil {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec._User(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler {\n\treturn ec.___Directive(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) {\n\tvar vSlice []interface{}\n\tif v != nil {\n\t\tif tmp1, ok := v.([]interface{}); ok {\n\t\t\tvSlice = tmp1\n\t\t} else {\n\t\t\tvSlice = []interface{}{v}\n\t\t}\n\t}\n\tvar err error\n\tres := make([]string, len(vSlice))\n\tfor i := range vSlice {\n\t\tres[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn res, nil\n}\n\nfunc (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler {\n\treturn ec.___EnumValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler {\n\treturn ec.___Field(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler {\n\treturn ec.___InputValue(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\nfunc (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\tres := graphql.MarshalString(v)\n\tif res == graphql.Null {\n\t\tif !ec.HasError(graphql.GetResolverContext(ctx)) {\n\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t}\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) {\n\treturn graphql.UnmarshalBoolean(v)\n}\n\nfunc (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler {\n\treturn graphql.MarshalBoolean(v)\n}\n\nfunc (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOBoolean2bool(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOBoolean2bool(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) {\n\treturn graphql.UnmarshalString(v)\n}\n\nfunc (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {\n\treturn graphql.MarshalString(v)\n}\n\nfunc (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tres, err := ec.unmarshalOString2string(ctx, v)\n\treturn &res, err\n}\n\nfunc (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.marshalOString2string(ctx, sel, *v)\n}\n\nfunc (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Schema2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v introspection.Schema) graphql.Marshaler {\n\treturn ec.___Schema(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Schema(ctx, sel, v)\n}\n\nfunc (ec *executionContext) marshalO__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler {\n\treturn ec.___Type(ctx, sel, &v)\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\tret := make(graphql.Array, len(v))\n\tvar wg sync.WaitGroup\n\tisLen1 := len(v) == 1\n\tif !isLen1 {\n\t\twg.Add(len(v))\n\t}\n\tfor i := range v {\n\t\ti := i\n\t\trctx := &graphql.ResolverContext{\n\t\t\tIndex:  &i,\n\t\t\tResult: &v[i],\n\t\t}\n\t\tctx := graphql.WithResolverContext(ctx, rctx)\n\t\tf := func(i int) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\t\t\tret = nil\n\t\t\t\t}\n\t\t\t}()\n\t\t\tif !isLen1 {\n\t\t\t\tdefer wg.Done()\n\t\t\t}\n\t\t\tret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i])\n\t\t}\n\t\tif isLen1 {\n\t\t\tf(i)\n\t\t} else {\n\t\t\tgo f(i)\n\t\t}\n\n\t}\n\twg.Wait()\n\treturn ret\n}\n\nfunc (ec *executionContext) marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler {\n\tif v == nil {\n\t\treturn graphql.Null\n\t}\n\treturn ec.___Type(ctx, sel, v)\n}\n\n// endregion ***************************** type.gotpl *****************************\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen6/go.mod",
    "content": "module gqlgen6\n\ngo 1.13\n\nrequire (\n\tgithub.com/99designs/gqlgen v0.10.2\n\tgithub.com/vektah/gqlparser v1.2.0\n)\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen6/go.sum",
    "content": "github.com/99designs/gqlgen v0.10.2 h1:FfjCqIWejHDJeLpQTI0neoZo5vDO3sdo5oNCucet3A0=\ngithub.com/99designs/gqlgen v0.10.2/go.mod h1:aDB7oabSAyZ4kUHLEySsLxnWrBy3lA0A2gWKU+qoHwI=\ngithub.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ=\ngithub.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=\ngithub.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=\ngithub.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=\ngithub.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=\ngithub.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=\ngithub.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=\ngithub.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=\ngithub.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=\ngithub.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=\ngithub.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=\ngithub.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=\ngithub.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=\ngithub.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=\ngithub.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=\ngithub.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=\ngithub.com/vektah/gqlparser v1.2.0 h1:ntkSCX7F5ZJKl+HIVnmLaO269MruasVpNiMOjX9kgo0=\ngithub.com/vektah/gqlparser v1.2.0/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd h1:oMEQDWVXVNpceQoVd1JN3CQ7LYJJzs5qWqZIUcxXHHw=\ngolang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\nsourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=\nsourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen6/gqlgen.yml",
    "content": "schema:\n- schema.graphql\nexec:\n  filename: generated.go\nmodel:\n  filename: models_gen.go\nresolver:\n  filename: resolver.go\n  type: Resolver\n\nmodels:\n  Photo:\n    model: gqlgen6.Photo\n    fields:\n      user:\n        resolver: true\n  User:\n    fields:\n      photos:\n        resolver: true\n\nautobind: []\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen6/models_gen.go",
    "content": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage gqlgen6\n\ntype User struct {\n\tID       string `json:\"id\"`\n\tName     string `json:\"name\"`\n\tAvatar   string `json:\"avatar\"`\n\tFollowed bool   `json:\"followed\"`\n\t// возвращает фотограции данного пользователя\n\tPhotos []*Photo `json:\"photos\"`\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen6/photo.go",
    "content": "package gqlgen6\n\nimport (\n\t// \"log\"\n\t\"strconv\"\n)\n\ntype Photo struct {\n\tID     uint `json:\"id\"`\n\tUserID uint `json:\"-\"`\n\t// User     *User  `json:\"user\"`\n\tURL     string `json:\"url\"`\n\tComment string `json:\"comment\"`\n\tRating  int    `json:\"rating\"`\n\tLiked   bool   `json:\"liked\"`\n}\n\nfunc (ph *Photo) Id() string {\n\t// log.Println(\"call Photo.Id method\", ph.ID)\n\treturn strconv.Itoa(int(ph.ID))\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen6/queries.txt",
    "content": "query {\n  user(userID: \"1\") {\n    id\n    name\n    avatar\n  }\n}\n\n\n\n\nquery {\n  user(userID: \"1\") {\n    id\n    name\n    avatar\n    photos {id, url, user{\n        id\n        name\n        photos {\n            id, url\n        }\n    }}\n  }\n}\n\n# -----\n\nquery {\n  user(userID: \"1\") {\n    id\n    name\n    avatar\n    photos(count:20) {\n      id\n      url\n      user {\n        id\n        name\n        photos(count:100) {\n          id\n          url\n        }\n      }\n    }\n  }\n}\n\n# ----\n\nquery($userID: ID!, $cnt1:Int!, $cnt2:Int! ) {\n  user(userID: $userID) {\n    id\n    name\n    avatar\n    photos(count:$cnt1) {\n      id\n      url\n      user {\n        id\n        name\n        photos(count:$cnt2) {\n          id\n          url\n        }\n      }\n    }\n  }\n  photos(userID:$userID) {id, url}\n}\n\n\n{\n  \"userID\":\"1\",\n  \"cnt1\":10,\n  \"cnt2\":20\n}"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen6/resolver.go",
    "content": "package gqlgen6\n\n//go:generate go run github.com/99designs/gqlgen -v\n\nimport (\n\t\"context\"\n\t\"crypto/md5\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n)\n\ntype Resolver struct {\n\tPhotosData map[string]*Photo\n\tUsers      map[uint]*User\n}\n\nfunc (r *Resolver) Mutation() MutationResolver {\n\treturn &mutationResolver{r}\n}\nfunc (r *Resolver) Photo() PhotoResolver {\n\treturn &photoResolver{r}\n}\nfunc (r *Resolver) User() UserResolver {\n\treturn &userResolver{r}\n}\nfunc (r *Resolver) Query() QueryResolver {\n\treturn &queryResolver{r}\n}\n\ntype mutationResolver struct{ *Resolver }\n\nfunc (r *mutationResolver) RatePhoto(ctx context.Context, id string, direction string) (*Photo, error) {\n\tlog.Println(\"call mutationResolver.RatePhoto method with id\", id, direction)\n\trate := 1\n\tif direction != \"up\" {\n\t\trate = -1\n\t}\n\tph, ok := r.PhotosData[id]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no photo %v found\", id)\n\t}\n\tph.Rating += rate\n\treturn ph, nil\n}\n\nfunc (r *mutationResolver) UploadPhoto(ctx context.Context, comment string, file graphql.Upload) (*Photo, error) {\n\tsessionUserID := ctx.Value(\"userID\").(uint)\n\n\tcontent, err := ioutil.ReadAll(file.File)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\thasher := md5.New()\n\thasher.Write(content)\n\n\tlog.Printf(\"incoming file %v, %v bytes, md5 %x\", file.Filename, file.Size, hasher.Sum(nil))\n\tph := &Photo{\n\t\tID:      42,\n\t\tUserID:  sessionUserID,\n\t\tComment: comment,\n\t\tURL:     \"/photos/\" + file.Filename,\n\t}\n\tr.PhotosData[strconv.Itoa(int(ph.ID))] = ph\n\treturn ph, nil\n}\n\ntype userResolver struct{ *Resolver }\n\nfunc (r *userResolver) Photos(ctx context.Context, obj *User, count int) ([]*Photo, error) {\n\tlog.Println(\"call userResolver.Photos with count\", count)\n\tid, _ := strconv.Atoi(obj.ID)\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\tif ph.UserID != uint(id) {\n\t\t\tcontinue\n\t\t}\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n\ntype photoResolver struct{ *Resolver }\n\nfunc (r *photoResolver) ID(ctx context.Context, obj *Photo) (string, error) {\n\treturn obj.Id(), nil\n}\n\nfunc (r *photoResolver) User(ctx context.Context, obj *Photo) (*User, error) {\n\t// return r.Users[obj.UserID], nil\n\tlog.Println(\"call photoResolver.User\", obj.UserID)\n\tstart := time.Now()\n\tuser, err := ctx.Value(\"userLoaderKey\").(*UserLoader).Load(obj.UserID)\n\tlog.Println(\"get photoResolver.User\", obj.UserID, \"from UserLoader, time \", time.Since(start))\n\treturn user, err\n}\n\ntype queryResolver struct{ *Resolver }\n\nfunc (r *queryResolver) Timeline(ctx context.Context) ([]*Photo, error) {\n\tlog.Println(\"call queryResolver.Timeline with ctx.userID\", ctx.Value(\"userID\"))\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n\nfunc (r *queryResolver) User(ctx context.Context, userID string) (*User, error) {\n\tlog.Println(\"call queryResolver.User for\", userID)\n\tid, _ := strconv.Atoi(userID)\n\treturn r.Users[uint(id)], nil\n}\n\nfunc (r *queryResolver) Photos(ctx context.Context, userID string) ([]*Photo, error) {\n\tlog.Println(\"call queryResolver.Photos\")\n\tid, _ := strconv.Atoi(userID)\n\titems := []*Photo{}\n\tfor _, ph := range r.PhotosData {\n\t\tif ph.UserID != uint(id) {\n\t\t\tcontinue\n\t\t}\n\t\titems = append(items, ph)\n\t}\n\treturn items, nil\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen6/schema.graphql",
    "content": "# gqlgen знает как с этим работать и что парсить это надо через multipart-form\nscalar Upload\n\ndirective @isSubscribed on FIELD_DEFINITION\ndirective @validation(funcs: [String!]!) on ARGUMENT_DEFINITION\n\ntype User {\n  id: ID!\n  name: String!\n  avatar: String!\n  followed: Boolean!\n\n  # subscriptions(count: Int! = 10): [User!]!\n  # subscribers(count: Int! = 10): [User!]!\n  \"\"\"возвращает фотограции данного пользователя\"\"\"\n  photos(count: Int! = 10): [Photo!]! @isSubscribed\n}\n\ntype Photo {\n  id: ID!\n  user: User!\n  url: String!\n  comment: String!\n  rating: Int!\n  liked: Boolean!\n}\n\ntype Query {\n  # query{timeline{id,url,user{id,name}}}\n  \"\"\"возвращает ленту текущего пользователя - фото тех, на кого он подписан\"\"\"\n  timeline: [Photo!]!\n\n  # query{user(userID:\"1\"){id,name,avatar}}\n  \"\"\"возвращает выбранного пользователя\"\"\"\n  user(userID: ID!): User!\n\n  # query{user(userID:\"1\"){id,avatar,name}}\n  \"\"\"возвращает фотограции выбранного пользователя\"\"\"\n  photos(userID: ID!): [Photo!]!\n}\n\ntype Mutation {\n  # mutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}\n  ratePhoto(photoID: ID!, direction: String!): Photo!\n\n  uploadPhoto(\n    comment: String! @validation(funcs: [\"noBadUrls\", \"noMatureLanguage\"])\n    file: Upload!\n  ): Photo! \n}\n\n# go run github.com/99designs/gqlgen init\n# go run github.com/99designs/gqlgen -v\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen6/server/server.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\tgqlgen \"gqlgen6\"\n\t\"log\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/99designs/gqlgen/graphql\"\n\t\"github.com/99designs/gqlgen/handler\"\n)\n\n/*\n# ok\ncurl localhost:8080/query \\\n  -F operations='{ \"query\": \"mutation($comment: String!, $file: Upload!) { uploadPhoto(comment: $comment, file: $file) { id } }\", \"variables\": { \"comment\": \"cool photo\", \"file\": null } }' \\\n  -F map='{ \"0\": [\"variables.file\"] }' \\\n  -F 0=@./test_file.txt \\\n  --trace-ascii -\n\n# mature language\ncurl localhost:8080/query \\\n  -F operations='{ \"query\": \"mutation($comment: String!, $file: Upload!) { uploadPhoto(comment: $comment, file: $file) { id } }\", \"variables\": { \"comment\": \"блин!\", \"file\": null } }' \\\n  -F map='{ \"0\": [\"variables.file\"] }' \\\n  -F 0=@./test_file.txt\n\n# bad url\ncurl localhost:8080/query \\\n  -F operations='{ \"query\": \"mutation($comment: String!, $file: Upload!) { uploadPhoto(comment: $comment, file: $file) { id } }\", \"variables\": { \"comment\": \"https://evil.com\", \"file\": null } }' \\\n  -F map='{ \"0\": [\"variables.file\"] }' \\\n  -F 0=@./test_file.txt\n\n\nquery($userID: ID!){\n  user(userID: $userID) {\n    id\n    avatar\n    name\n    photos {\n      id\n    }\n  }\n}\n\n\n\n\n*/\n\nvar users = map[uint]*gqlgen.User{\n\t1: {\n\t\tID:     \"1\",\n\t\tName:   \"rvasily\",\n\t\tAvatar: \"https://via.placeholder.com/150\",\n\t},\n\t2: {\n\t\tID:     \"2\",\n\t\tName:   \"v.romanov\",\n\t\tAvatar: \"https://via.placeholder.com/150\",\n\t},\n\t3: {\n\t\tID:     \"3\",\n\t\tName:   \"romanov.vasily\",\n\t\tAvatar: \"https://via.placeholder.com/150\",\n\t},\n}\n\nvar photos = map[string]*gqlgen.Photo{\n\t\"1\": {\n\t\tID:      1,\n\t\tUserID:  1,\n\t\tURL:     \"https://via.placeholder.com/300\",\n\t\tComment: \"from studio\",\n\t\tRating:  1,\n\t\tLiked:   true,\n\t},\n\t\"2\": {\n\t\tID:      2,\n\t\tUserID:  1,\n\t\tURL:     \"https://via.placeholder.com/300\",\n\t\tComment: \"cool view\",\n\t\tRating:  0,\n\t\tLiked:   false,\n\t},\n\t\"3\": {\n\t\tID:      3,\n\t\tUserID:  2,\n\t\tURL:     \"https://via.placeholder.com/300\",\n\t\tComment: \"at work\",\n\t\tRating:  0,\n\t\tLiked:   false,\n\t},\n\t\"4\": {\n\t\tID:      3,\n\t\tUserID:  3,\n\t\tURL:     \"https://via.placeholder.com/300\",\n\t\tComment: \"at work\",\n\t\tRating:  0,\n\t\tLiked:   false,\n\t},\n}\n\n// go run github.com/vektah/dataloaden UserLoader uint *coursera/3p/graphql/gqlgen3.User\n\nfunc UserLoaderMiddleware(resolver *gqlgen.Resolver, next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tcfg := gqlgen.UserLoaderConfig{\n\t\t\tMaxBatch: 100,\n\t\t\tWait:     1 * time.Millisecond,\n\t\t\tFetch: func(ids []uint) ([]*gqlgen.User, []error) {\n\t\t\t\t// имеем доступ до r *http.Request - там context с сессией пользователя\n\t\t\t\tsessionUserID := r.Context().Value(\"userID\").(uint)\n\t\t\t\tlog.Printf(\"UserLoader Request - ids %v for user %v\\n\", ids, sessionUserID)\n\n\t\t\t\tlog.Printf(\"request %v\\n\", r)\n\t\t\t\tlog.Printf(\"ctx %v\\n\", r.Context())\n\n\t\t\t\tusers := make([]*gqlgen.User, len(ids))\n\t\t\t\tfor i, id := range ids {\n\t\t\t\t\t// имеем доступ до resolver *gqlgen.Resolver - там коннет к базе\n\t\t\t\t\tusers[i] = resolver.Users[id]\n\t\t\t\t}\n\t\t\t\treturn users, nil\n\t\t\t},\n\t\t}\n\t\tuserLoader := gqlgen.NewUserLoader(cfg)\n\t\tctx := context.WithValue(r.Context(), \"userLoaderKey\", userLoader)\n\t\tr = r.WithContext(ctx)\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n\nfunc AuthMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t// log.Println(\"new request\")\n\t\tctx := context.WithValue(r.Context(), \"userID\", uint(1))\n\t\tr = r.WithContext(ctx)\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n\n// 1-й подписан на 2-го\nvar followedData = map[uint]map[uint]struct{}{\n\t1: map[uint]struct{}{\n\t\t2: struct{}{},\n\t},\n}\n\nfunc IsFollowed(userID, currUserID uint) bool {\n\tcurrSubs, ok := followedData[currUserID]\n\tif !ok {\n\t\treturn false\n\t}\n\t_, isFollowed := currSubs[userID]\n\treturn isFollowed\n}\n\nfunc CheckIsSubscribed(ctx context.Context, obj interface{}, next graphql.Resolver) (interface{}, error) {\n\tlog.Printf(\"CheckIsSubscribed %T %#V\", obj, obj)\n\tsessionUserID := ctx.Value(\"userID\").(uint)\n\tswitch obj.(type) {\n\tcase *gqlgen.User:\n\t\tu := obj.(*gqlgen.User)\n\t\tuserID, _ := strconv.Atoi(u.ID)\n\t\tif uint(userID) == sessionUserID {\n\t\t\tbreak\n\t\t}\n\t\tif !IsFollowed(uint(userID), sessionUserID) {\n\t\t\treturn nil, fmt.Errorf(\"availible only for followers\")\n\t\t}\n\t}\n\treturn next(ctx)\n}\n\nfunc noBadUrls(vars map[string]interface{}) bool {\n\tval, ok := vars[\"comment\"].(string)\n\tif !ok {\n\t\treturn false\n\t}\n\treturn !strings.Contains(val, \"evil.com\")\n}\n\nfunc noMatureLanguage(vars map[string]interface{}) bool {\n\tval, ok := vars[\"comment\"].(string)\n\tif !ok {\n\t\treturn false\n\t}\n\treturn !strings.Contains(val, \"блин\")\n}\n\nvar validators = map[string]func(map[string]interface{}) bool{\n\t\"noBadUrls\":        noBadUrls,\n\t\"noMatureLanguage\": noMatureLanguage,\n}\n\nfunc CheckValidation(ctx context.Context, obj interface{}, next graphql.Resolver, callbacks []string) (interface{}, error) {\n\tlog.Printf(\"CheckValidation %T %#V %#v\", obj, obj, callbacks)\n\n\tfor _, cbName := range callbacks {\n\t\tcb, ok := validators[cbName]\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"cant find callback %s\", cbName)\n\t\t}\n\t\tvars, ok := obj.(map[string]interface{})\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"unexpected args type: %T\", obj)\n\t\t}\n\t\tif !cb(vars) {\n\t\t\treturn nil, fmt.Errorf(\"check %s failed\", cbName)\n\t\t}\n\t}\n\n\treturn next(ctx)\n}\n\nfunc main() {\n\thttp.Handle(\"/\", handler.Playground(\"GraphQL playground\", \"/query\"))\n\n\tresolver := &gqlgen.Resolver{\n\t\tUsers:      users,\n\t\tPhotosData: photos,\n\t}\n\tcfg := gqlgen.Config{\n\t\tResolvers: resolver,\n\t}\n\tcfg.Complexity.User.Photos = func(childComplexity, count int) int {\n\t\treturn count * childComplexity\n\t}\n\n\tcfg.Directives.IsSubscribed = CheckIsSubscribed\n\tcfg.Directives.Validation = CheckValidation\n\n\tgqlHandler := handler.GraphQL(\n\t\tgqlgen.NewExecutableSchema(cfg),\n\t\thandler.ComplexityLimit(500),\n\t)\n\thandler := UserLoaderMiddleware(resolver, gqlHandler)\n\thandler = AuthMiddleware(handler)\n\thttp.Handle(\"/query\", handler)\n\n\tport := \"8080\"\n\tlog.Printf(\"connect to http://localhost:%s/ for GraphQL playground\", port)\n\tlog.Fatal(http.ListenAndServe(\":\"+port, nil))\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen6/test_file.txt",
    "content": "TEST_FILE_XXXXXXXXXXXXXXXXXX"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/gqlgen6/userloader_gen.go",
    "content": "// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.\n\npackage gqlgen6\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\n// UserLoaderConfig captures the config to create a new UserLoader\ntype UserLoaderConfig struct {\n\t// Fetch is a method that provides the data for the loader\n\tFetch func(keys []uint) ([]*User, []error)\n\n\t// Wait is how long wait before sending a batch\n\tWait time.Duration\n\n\t// MaxBatch will limit the maximum number of keys to send in one batch, 0 = not limit\n\tMaxBatch int\n}\n\n// NewUserLoader creates a new UserLoader given a fetch, wait, and maxBatch\nfunc NewUserLoader(config UserLoaderConfig) *UserLoader {\n\treturn &UserLoader{\n\t\tfetch:    config.Fetch,\n\t\twait:     config.Wait,\n\t\tmaxBatch: config.MaxBatch,\n\t}\n}\n\n// UserLoader batches and caches requests\ntype UserLoader struct {\n\t// this method provides the data for the loader\n\tfetch func(keys []uint) ([]*User, []error)\n\n\t// how long to done before sending a batch\n\twait time.Duration\n\n\t// this will limit the maximum number of keys to send in one batch, 0 = no limit\n\tmaxBatch int\n\n\t// INTERNAL\n\n\t// lazily created cache\n\tcache map[uint]*User\n\n\t// the current batch. keys will continue to be collected until timeout is hit,\n\t// then everything will be sent to the fetch method and out to the listeners\n\tbatch *userLoaderBatch\n\n\t// mutex to prevent races\n\tmu sync.Mutex\n}\n\ntype userLoaderBatch struct {\n\tkeys    []uint\n\tdata    []*User\n\terror   []error\n\tclosing bool\n\tdone    chan struct{}\n}\n\n// Load a User by key, batching and caching will be applied automatically\nfunc (l *UserLoader) Load(key uint) (*User, error) {\n\treturn l.LoadThunk(key)()\n}\n\n// LoadThunk returns a function that when called will block waiting for a User.\n// This method should be used if you want one goroutine to make requests to many\n// different data loaders without blocking until the thunk is called.\nfunc (l *UserLoader) LoadThunk(key uint) func() (*User, error) {\n\tl.mu.Lock()\n\tif it, ok := l.cache[key]; ok {\n\t\tl.mu.Unlock()\n\t\treturn func() (*User, error) {\n\t\t\treturn it, nil\n\t\t}\n\t}\n\tif l.batch == nil {\n\t\tl.batch = &userLoaderBatch{done: make(chan struct{})}\n\t}\n\tbatch := l.batch\n\tpos := batch.keyIndex(l, key)\n\tl.mu.Unlock()\n\n\treturn func() (*User, error) {\n\t\t<-batch.done\n\n\t\tvar data *User\n\t\tif pos < len(batch.data) {\n\t\t\tdata = batch.data[pos]\n\t\t}\n\n\t\tvar err error\n\t\t// its convenient to be able to return a single error for everything\n\t\tif len(batch.error) == 1 {\n\t\t\terr = batch.error[0]\n\t\t} else if batch.error != nil {\n\t\t\terr = batch.error[pos]\n\t\t}\n\n\t\tif err == nil {\n\t\t\tl.mu.Lock()\n\t\t\tl.unsafeSet(key, data)\n\t\t\tl.mu.Unlock()\n\t\t}\n\n\t\treturn data, err\n\t}\n}\n\n// LoadAll fetches many keys at once. It will be broken into appropriate sized\n// sub batches depending on how the loader is configured\nfunc (l *UserLoader) LoadAll(keys []uint) ([]*User, []error) {\n\tresults := make([]func() (*User, error), len(keys))\n\n\tfor i, key := range keys {\n\t\tresults[i] = l.LoadThunk(key)\n\t}\n\n\tusers := make([]*User, len(keys))\n\terrors := make([]error, len(keys))\n\tfor i, thunk := range results {\n\t\tusers[i], errors[i] = thunk()\n\t}\n\treturn users, errors\n}\n\n// LoadAllThunk returns a function that when called will block waiting for a Users.\n// This method should be used if you want one goroutine to make requests to many\n// different data loaders without blocking until the thunk is called.\nfunc (l *UserLoader) LoadAllThunk(keys []uint) func() ([]*User, []error) {\n\tresults := make([]func() (*User, error), len(keys))\n\tfor i, key := range keys {\n\t\tresults[i] = l.LoadThunk(key)\n\t}\n\treturn func() ([]*User, []error) {\n\t\tusers := make([]*User, len(keys))\n\t\terrors := make([]error, len(keys))\n\t\tfor i, thunk := range results {\n\t\t\tusers[i], errors[i] = thunk()\n\t\t}\n\t\treturn users, errors\n\t}\n}\n\n// Prime the cache with the provided key and value. If the key already exists, no change is made\n// and false is returned.\n// (To forcefully prime the cache, clear the key first with loader.clear(key).prime(key, value).)\nfunc (l *UserLoader) Prime(key uint, value *User) bool {\n\tl.mu.Lock()\n\tvar found bool\n\tif _, found = l.cache[key]; !found {\n\t\t// make a copy when writing to the cache, its easy to pass a pointer in from a loop var\n\t\t// and end up with the whole cache pointing to the same value.\n\t\tcpy := *value\n\t\tl.unsafeSet(key, &cpy)\n\t}\n\tl.mu.Unlock()\n\treturn !found\n}\n\n// Clear the value at key from the cache, if it exists\nfunc (l *UserLoader) Clear(key uint) {\n\tl.mu.Lock()\n\tdelete(l.cache, key)\n\tl.mu.Unlock()\n}\n\nfunc (l *UserLoader) unsafeSet(key uint, value *User) {\n\tif l.cache == nil {\n\t\tl.cache = map[uint]*User{}\n\t}\n\tl.cache[key] = value\n}\n\n// keyIndex will return the location of the key in the batch, if its not found\n// it will add the key to the batch\nfunc (b *userLoaderBatch) keyIndex(l *UserLoader, key uint) int {\n\tfor i, existingKey := range b.keys {\n\t\tif key == existingKey {\n\t\t\treturn i\n\t\t}\n\t}\n\n\tpos := len(b.keys)\n\tb.keys = append(b.keys, key)\n\tif pos == 0 {\n\t\tgo b.startTimer(l)\n\t}\n\n\tif l.maxBatch != 0 && pos >= l.maxBatch-1 {\n\t\tif !b.closing {\n\t\t\tb.closing = true\n\t\t\tl.batch = nil\n\t\t\tgo b.end(l)\n\t\t}\n\t}\n\n\treturn pos\n}\n\nfunc (b *userLoaderBatch) startTimer(l *UserLoader) {\n\ttime.Sleep(l.wait)\n\tl.mu.Lock()\n\n\t// we must have hit a batch limit and are already finalizing this batch\n\tif b.closing {\n\t\tl.mu.Unlock()\n\t\treturn\n\t}\n\n\tl.batch = nil\n\tl.mu.Unlock()\n\n\tb.end(l)\n}\n\nfunc (b *userLoaderBatch) end(l *UserLoader) {\n\tb.data, b.error = l.fetch(b.keys)\n\tclose(b.done)\n}\n"
  },
  {
    "path": "4-api/3_graphql/gqlgen_full/note.txt",
    "content": "go run github.com/99designs/gqlgen init\n\ngo run github.com/99designs/gqlgen -v\n\ngo generate ./...\n\n\n\ndataloaden coursera/3p/graphql/gqlgen3.User\n\nhttps://github.com/99designs/gqlgen/blob/master/example/dataloader/dataloaders.go\ngo run github.com/vektah/dataloaden UserLoader uint *coursera/3p/graphql/gqlgen3.User\n\n\n\n\n\n\n  uploadPhoto(comment: String!, file: Upload!) Photo!\n\n\ncurl localhost:8080/graphql \\\n  -F operations='{ \"query\": \"mutation ($file: Upload!) { singleUpload(file: $file) { id } }\", \"variables\": { \"file\": null } }' \\\n  -F map='{ \"0\": [\"variables.file\"] }' \\\n  -F 0=@../photo_samples/building_1.jpg\n\n\n{\n  query: `\n    mutation($file: Upload!) {\n      singleUpload(file: $file) {\n        id\n      }\n    }\n  `,\n  variables: {\n    file: File // a.txt\n  }\n}\n\n\n\n\nhttps://99designs.com/blog/engineering/gqlgen-a-graphql-server-generator-for-go/\n\n\n\nhttps://github.com/99designs/gqlgen\n\n\n\nquery{timeline{id,url,user{id,name}}}\nquery{user(userID:\"1\"){id,avatar, name}}\nmutation _{ratePhoto(photoID:\"1\", direction:\"up\"){id,url,rating,user{id,name}}}"
  },
  {
    "path": "4-api/3_graphql/graphql-go/main.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/graphql-go/graphql\"\n)\n\n/*\nCreate\nhttp://127.0.0.1:8080/graphql?query=mutation+_{create(title:%22taocp%22,price:2500,author:1){id,title,price}}\n\nRead\nhttp://127.0.0.1:8080/graphql?query={books{id,title,author{name}}}\nhttp://127.0.0.1:8080/graphql?query={book(id:1){id,title,author{name}}}\n\nUpdate\nhttp://127.0.0.1:8080/graphql?query=mutation+_{update(id:1,price:42.0,title:\"test\"){id,title,price}}\n\nDelete\nhttp://127.0.0.1:8080/graphql?query=mutation+_{delete(id:1){id,title,price}}\n*/\n\ntype Author struct {\n\tName string `json:\"string\"`\n}\n\ntype Book struct {\n\tID     int64   `json:\"id\"`\n\tTitle  string  `json:\"title\"`\n\tAuthor uint    `json:\"author\"`\n\tPrice  float64 `json:\"price\"`\n}\n\nvar authors = map[uint]Author{\n\t1: Author{\n\t\tName: \"Robert Heinlein\",\n\t},\n}\n\nvar books = []Book{\n\tBook{\n\t\tID:     1,\n\t\tTitle:  \"The Moon is a harsh mistress\",\n\t\tAuthor: 1,\n\t\tPrice:  200,\n\t},\n}\n\nvar authorType = graphql.NewObject(\n\tgraphql.ObjectConfig{\n\t\tName: \"Author\",\n\t\tFields: graphql.Fields{\n\t\t\t\"name\": &graphql.Field{\n\t\t\t\tType: graphql.String,\n\t\t\t},\n\t\t},\n\t},\n)\n\nvar bookType = graphql.NewObject(\n\tgraphql.ObjectConfig{\n\t\tName: \"Book\",\n\t\tFields: graphql.Fields{\n\t\t\t\"id\": &graphql.Field{\n\t\t\t\tType: graphql.Int,\n\t\t\t},\n\t\t\t\"title\": &graphql.Field{\n\t\t\t\tType: graphql.String,\n\t\t\t},\n\t\t\t\"author\": &graphql.Field{\n\t\t\t\tType: authorType,\n\t\t\t\tResolve: func(params graphql.ResolveParams) (interface{}, error) {\n\t\t\t\t\tbook, ok := params.Source.(Book)\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"cannot convert source to Book\")\n\t\t\t\t\t}\n\n\t\t\t\t\treturn authors[book.Author], nil\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"price\": &graphql.Field{\n\t\t\t\tType: graphql.Float,\n\t\t\t},\n\t\t},\n\t},\n)\n\nvar mutationType = graphql.NewObject(graphql.ObjectConfig{\n\tName: \"Mutation\",\n\tFields: graphql.Fields{\n\t\t\"create\": &graphql.Field{\n\t\t\tType:        bookType,\n\t\t\tDescription: \"Create new book\",\n\t\t\tArgs: graphql.FieldConfigArgument{\n\t\t\t\t\"title\": &graphql.ArgumentConfig{\n\t\t\t\t\tType: graphql.NewNonNull(graphql.String),\n\t\t\t\t},\n\t\t\t\t\"author\": &graphql.ArgumentConfig{\n\t\t\t\t\tType: graphql.NewNonNull(graphql.Int),\n\t\t\t\t},\n\t\t\t\t\"price\": &graphql.ArgumentConfig{\n\t\t\t\t\tType: graphql.NewNonNull(graphql.Float),\n\t\t\t\t},\n\t\t\t},\n\t\t\tResolve: func(params graphql.ResolveParams) (interface{}, error) {\n\t\t\t\trand.Seed(time.Now().UnixNano())\n\n\t\t\t\tlog.Println(params.Args)\n\n\t\t\t\tbook := Book{\n\t\t\t\t\tID:     int64(rand.Intn(100000)), // генерируем случайный ID\n\t\t\t\t\tTitle:  params.Args[\"title\"].(string),\n\t\t\t\t\tAuthor: uint(params.Args[\"author\"].(int)),\n\t\t\t\t\tPrice:  params.Args[\"price\"].(float64),\n\t\t\t\t}\n\t\t\t\tbooks = append(books, book)\n\t\t\t\treturn book, nil\n\t\t\t},\n\t\t},\n\n\t\t\"update\": &graphql.Field{\n\t\t\tType:        bookType,\n\t\t\tDescription: \"Update book by id\",\n\t\t\tArgs: graphql.FieldConfigArgument{\n\t\t\t\t\"id\": &graphql.ArgumentConfig{\n\t\t\t\t\tType: graphql.NewNonNull(graphql.Int),\n\t\t\t\t},\n\t\t\t\t\"title\": &graphql.ArgumentConfig{\n\t\t\t\t\tType: graphql.String,\n\t\t\t\t},\n\t\t\t\t\"author\": &graphql.ArgumentConfig{\n\t\t\t\t\tType: graphql.Int,\n\t\t\t\t},\n\t\t\t\t\"price\": &graphql.ArgumentConfig{\n\t\t\t\t\tType: graphql.Float,\n\t\t\t\t},\n\t\t\t},\n\t\t\tResolve: func(params graphql.ResolveParams) (interface{}, error) {\n\t\t\t\tid, _ := params.Args[\"id\"].(int)\n\t\t\t\ttitle, titleOk := params.Args[\"title\"].(string)\n\t\t\t\tauthor, authorOk := params.Args[\"author\"].(int)\n\t\t\t\tprice, priceOk := params.Args[\"price\"].(float64)\n\t\t\t\tbook := Book{}\n\t\t\t\tfor i, p := range books {\n\t\t\t\t\tif int64(id) != p.ID {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tif titleOk {\n\t\t\t\t\t\tbooks[i].Title = title\n\t\t\t\t\t}\n\t\t\t\t\tif authorOk {\n\t\t\t\t\t\tbooks[i].Author = uint(author)\n\t\t\t\t\t}\n\t\t\t\t\tif priceOk {\n\t\t\t\t\t\tbooks[i].Price = price\n\t\t\t\t\t}\n\t\t\t\t\tbook = books[i]\n\t\t\t\t}\n\t\t\t\treturn book, nil\n\t\t\t},\n\t\t},\n\n\t\t\"delete\": &graphql.Field{\n\t\t\tType:        bookType,\n\t\t\tDescription: \"Delete book by id\",\n\t\t\tArgs: graphql.FieldConfigArgument{\n\t\t\t\t\"id\": &graphql.ArgumentConfig{\n\t\t\t\t\tType: graphql.NewNonNull(graphql.Int),\n\t\t\t\t},\n\t\t\t},\n\t\t\tResolve: func(params graphql.ResolveParams) (interface{}, error) {\n\t\t\t\tid, _ := params.Args[\"id\"].(int)\n\t\t\t\tbook := Book{}\n\t\t\t\tfor i, p := range books {\n\t\t\t\t\tif int64(id) == p.ID {\n\t\t\t\t\t\tbook = books[i]\n\t\t\t\t\t\tbooks = append(books[:i], books[i+1:]...)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn book, nil\n\t\t\t},\n\t\t},\n\t},\n})\n\nvar queryType = graphql.NewObject(\n\tgraphql.ObjectConfig{\n\t\tName: \"Query\",\n\t\tFields: graphql.Fields{\n\t\t\t\"book\": &graphql.Field{\n\t\t\t\tType:        bookType,\n\t\t\t\tDescription: \"Get book by id\",\n\t\t\t\tArgs: graphql.FieldConfigArgument{\n\t\t\t\t\t\"id\": &graphql.ArgumentConfig{\n\t\t\t\t\t\tType: graphql.Int,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tResolve: func(p graphql.ResolveParams) (interface{}, error) {\n\t\t\t\t\tid, ok := p.Args[\"id\"].(int)\n\t\t\t\t\tif ok {\n\t\t\t\t\t\tfor _, book := range books {\n\t\t\t\t\t\t\tif int(book.ID) == id {\n\t\t\t\t\t\t\t\treturn book, nil\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn nil, nil\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"books\": &graphql.Field{\n\t\t\t\tType:        graphql.NewList(bookType),\n\t\t\t\tDescription: \"Get books list\",\n\t\t\t\tResolve: func(params graphql.ResolveParams) (interface{}, error) {\n\t\t\t\t\treturn books, nil\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t})\n\nvar schema, _ = graphql.NewSchema(\n\tgraphql.SchemaConfig{\n\t\tQuery:    queryType,\n\t\tMutation: mutationType,\n\t},\n)\n\nfunc executeQuery(query string, schema graphql.Schema) *graphql.Result {\n\tresult := graphql.Do(graphql.Params{\n\t\tSchema:        schema,\n\t\tRequestString: query,\n\t})\n\tif len(result.Errors) > 0 {\n\t\tfmt.Printf(\"errors: %v\", result.Errors)\n\t}\n\treturn result\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/graphql\", func(w http.ResponseWriter, r *http.Request) {\n\t\tresult := executeQuery(r.URL.Query().Get(\"query\"), schema)\n\t\tjson.NewEncoder(w).Encode(result)\n\t})\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "4-api/3_graphql/intro/instagram_gql.txt",
    "content": "{\"5095\":\"viewer() {\n    eligible_promotions.ig_parameters(<ig_parameters>).surface_nux_id(<surface>).external_gating_permitted_qps(<external_gating_permitted_qps>) {\n      edges {\n        priority,\n        time_range {\n          start,\n          end\n        },\n        node {\n          id,\n          promotion_id,\n          max_impressions,\n          triggers,\n          template {\n            name,\n            parameters {\n              name,\n              string_value\n            }\n          },\n          creatives {\n            title {\n              text\n            },\n            content {\n              text\n            },\n            footer {\n              text\n            },\n            social_context {\n              text\n            },\n            primary_action{\n              title {\n                text\n              },\n              url,\n              limit,\n              dismiss_promotion\n            },\n            secondary_action{\n              title {\n                text\n              },\n              url,\n              limit,\n              dismiss_promotion\n            },\n            dismiss_action{\n              title {\n                text\n              },\n              url,\n              limit,\n              dismiss_promotion\n            },\n            image {\n              uri\n            }\n          }\n        }\n      }\n    }\n\n}\",\"5780\":\"viewer() {\n    eligible_promotions.ig_parameters(<ig_parameters>).surface_nux_id(<surface>).external_gating_permitted_qps(<external_gating_permitted_qps>) {\n      edges {\n        priority,\n        time_range {\n          start,\n          end\n        },\n        node {\n          id,\n          promotion_id,\n          max_impressions,\n          triggers,\n          template {\n            name,\n            parameters {\n              name,\n              string_value\n            }\n          },\n          creatives {\n            title {\n              text\n            },\n            content {\n              text\n            },\n            footer {\n              text\n            },\n            social_context {\n              text\n            },\n            primary_action{\n              title {\n                text\n              },\n              url,\n              limit,\n              dismiss_promotion\n            },\n            secondary_action{\n              title {\n                text\n              },\n              url,\n              limit,\n              dismiss_promotion\n            },\n            dismiss_action{\n              title {\n                text\n              },\n              url,\n              limit,\n              dismiss_promotion\n            },\n            image {\n              uri\n            }\n          }\n        }\n      }\n    }\n\n}\"}"
  },
  {
    "path": "4-api/3_graphql/intro/instagram_sql_resp.json",
    "content": "{  \n   \"data\":{  \n      \"user\":{  \n         \"id\":\"8783838119\",\n         \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/62df74739256182ff0c6e649b92af2e1/5DF8D1FD/t51.2885-19/s150x150/47581251_1143495042491718_7332190549358673920_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n         \"username\":\"rvasily.msk\",\n         \"edge_web_feed_timeline\":{  \n            \"page_info\":{  \n               \"has_next_page\":true,\n               \"end_cursor\":\"KKkBARAAAAIoABgAEAAQAAgACAAIAP____9_______-______5___9f____3______v6f__9___-__v_7__7_____5_________9___7_______f9_-vS-94VU4v6MKqzsf8f__2-_____nfr___79v_7f_-f__7v_P___1_f_v7v__9vf__79___-_7__7_3__7___-b8___-173_____3_5_d7vfKyMEsCABb8tfaXmVsA\"\n            },\n            \"edges\":[  \n               {  \n                  \"node\":{  \n                     \"__typename\":\"GraphImage\",\n                     \"id\":\"2118287177818397102\",\n                     \"dimensions\":{  \n                        \"height\":1080,\n                        \"width\":1080\n                     },\n                     \"display_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/0e72e01774b67986c7956914c964d537/5E05EFA3/t51.2885-15/e35/67194079_764206027315731_4716759996914198074_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                     \"display_resources\":[  \n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/e8d3c843e8d18da582ad809e6fc33339/5DFF9846/t51.2885-15/sh0.08/e35/s640x640/67194079_764206027315731_4716759996914198074_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":640,\n                           \"config_height\":640\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/eff3cb4a484f7c4116778a638e004441/5E0A8746/t51.2885-15/sh0.08/e35/s750x750/67194079_764206027315731_4716759996914198074_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":750,\n                           \"config_height\":750\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/0e72e01774b67986c7956914c964d537/5E05EFA3/t51.2885-15/e35/67194079_764206027315731_4716759996914198074_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":1080,\n                           \"config_height\":1080\n                        }\n                     ],\n                     \"follow_hashtag_info\":null,\n                     \"is_video\":false,\n                     \"should_log_client_event\":false,\n                     \"tracking_token\":\"eyJ2ZXJzaW9uIjo1LCJwYXlsb2FkIjp7ImlzX2FuYWx5dGljc190cmFja2VkIjp0cnVlLCJ1dWlkIjoiZDNkNWVkZTkzNjg3NDM0MmI5MzdmMGMzNDA1NWVlMTIyMTE4Mjg3MTc3ODE4Mzk3MTAyIiwic2VydmVyX3Rva2VuIjoiMTU2Njc0ODY2MTIyMXwyMTE4Mjg3MTc3ODE4Mzk3MTAyfDg3ODM4MzgxMTl8YzliZjQyYTcxMjU2OTQ5YzRjNWI4ZGYyNzVjYmQ4YmU4NmM4NDQzZGZmNzQ0OTE1Y2M5YjM2NTczOThkZmQ5OSJ9LCJzaWduYXR1cmUiOiIifQ==\",\n                     \"edge_media_to_tagged_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"accessibility_caption\":\"\\u041d\\u0430 \\u0438\\u0437\\u043e\\u0431\\u0440\\u0430\\u0436\\u0435\\u043d\\u0438\\u0438 \\u043c\\u043e\\u0436\\u0435\\u0442 \\u043d\\u0430\\u0445\\u043e\\u0434\\u0438\\u0442\\u044c\\u0441\\u044f: \\u0432 \\u043f\\u043e\\u043c\\u0435\\u0449\\u0435\\u043d\\u0438\\u0438\",\n                     \"attribution\":null,\n                     \"shortcode\":\"B1lqvcOIVmu\",\n                     \"edge_media_to_caption\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"text\":\"@_nguan_\\n#dreamermagazine\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_preview_comment\":{  \n                        \"count\":5,\n                        \"page_info\":{  \n                           \"has_next_page\":true,\n                           \"end_cursor\":\"QVFCUFJ4TjhSWUNORmpoc1JuY0NpU3N3ZFo5R2M4ZnJyNC1CWmowTG55ZHd6bzI1QkNHSGFGZUhwdTY0OVA2UkhXeS0yaFU1NVQ3VDNiY1JMQ0ItQWp4cA==\"\n                        },\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"17926872490309142\",\n                                 \"text\":\"Love these soft colours \\ud83d\\ude0d\",\n                                 \"created_at\":1566742952,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"178548294\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/4e56dc1ed1127c6aa7143cdfe4fbc757/5DFB45AF/t51.2885-19/s150x150/60207369_1069359416582248_7611132281343705088_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"clancywhiteside\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"id\":\"17886040774395916\",\n                                 \"text\":\"\\u606d\\u559c\\u53d1\\u8d22\\u8d22\\u8fd0\\u6eda\\u6eda\",\n                                 \"created_at\":1566746198,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"296852447\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/803fc113b05cd13756959c302ea38632/5DF8E15A/t51.2885-19/s150x150/42494087_269469293907798_1214459997887397888_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"lingyang37\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           }\n                        ]\n                     },\n                     \"gating_info\":null,\n                     \"media_preview\":\"ACoqsyRFee34UwHNaQwfzP8AD/n86pzxbBuTHJxj3/z60DKu8LwSAaUMG6HNROu7kgZNIMx9hz2FRd3sVZWvrcsFgoy1Q+cx6Co5Ac85JzgADp7emfzqE7gfuH/vo1RmdDn/ANCP8Wf0/pVaWTIx3BzUAvWMm3GFyTnABx68/wA6gnZhkjJH8qTd9i2miQyCR+TjA7cdaJgMAjoP/r1SjTfznH+e9X43AbnoSAPfPWmkK5E03JGcbG+lRM7Ek5PU9/8A61XZrNJMkcFutZx02T1/Q1Vn0J9Vcvtk5zyTWfL8xbFaB6VQkHzn6CpYyWEYFPZXLAjG0EH3oSphVokug5paij6VJTGf/9k=\",\n                     \"comments_disabled\":false,\n                     \"taken_at_timestamp\":1566739531,\n                     \"edge_media_preview_like\":{  \n                        \"count\":2432,\n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"edge_media_to_sponsor_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"location\":null,\n                     \"viewer_has_liked\":false,\n                     \"viewer_has_saved\":false,\n                     \"viewer_has_saved_to_collection\":false,\n                     \"viewer_in_photo_of_you\":false,\n                     \"viewer_can_reshare\":true,\n                     \"owner\":{  \n                        \"id\":\"3468082085\",\n                        \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/1f1d7f216ca0db2ef61fb3c97684bd1f/5E09D9AF/t51.2885-19/s150x150/29088365_857696394412136_6657610564803493888_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                        \"username\":\"dreamermagazine\",\n                        \"followed_by_viewer\":true,\n                        \"full_name\":\"Dreamer Magazine\",\n                        \"is_private\":false,\n                        \"requested_by_viewer\":false,\n                        \"blocked_by_viewer\":false,\n                        \"has_blocked_viewer\":false\n                     }\n                  }\n               },\n               {  \n                  \"node\":{  \n                     \"__typename\":\"GraphImage\",\n                     \"id\":\"2118363188411259641\",\n                     \"dimensions\":{  \n                        \"height\":720,\n                        \"width\":1080\n                     },\n                     \"display_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/815edcb93bf99ca182af26333e782a2d/5DDA3A0C/t51.2885-15/e35/67758159_228810251346840_1820141147555273790_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                     \"display_resources\":[  \n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/c381a9e65286f7d7532472225eff2ccd/5DDBCFE9/t51.2885-15/sh0.08/e35/s640x640/67758159_228810251346840_1820141147555273790_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":640,\n                           \"config_height\":426\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/1b6b9a47b22180dc18f2e953284ee1f7/5E078CE9/t51.2885-15/sh0.08/e35/s750x750/67758159_228810251346840_1820141147555273790_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":750,\n                           \"config_height\":500\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/815edcb93bf99ca182af26333e782a2d/5DDA3A0C/t51.2885-15/e35/67758159_228810251346840_1820141147555273790_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":1080,\n                           \"config_height\":720\n                        }\n                     ],\n                     \"follow_hashtag_info\":null,\n                     \"is_video\":false,\n                     \"should_log_client_event\":false,\n                     \"tracking_token\":\"eyJ2ZXJzaW9uIjo1LCJwYXlsb2FkIjp7ImlzX2FuYWx5dGljc190cmFja2VkIjp0cnVlLCJ1dWlkIjoiZDNkNWVkZTkzNjg3NDM0MmI5MzdmMGMzNDA1NWVlMTIyMTE4MzYzMTg4NDExMjU5NjQxIiwic2VydmVyX3Rva2VuIjoiMTU2Njc0ODY2MTIyMnwyMTE4MzYzMTg4NDExMjU5NjQxfDg3ODM4MzgxMTl8ZGEzMDQxM2Y2NTBiYmM0ZWM2Nzc1Y2FjMzE0YjQxNTExNzcxZDE0M2QxNTU3MGM3YmNjZmIxNjY4M2FlZWY5NyJ9LCJzaWduYXR1cmUiOiIifQ==\",\n                     \"edge_media_to_tagged_user\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"user\":{  \n                                    \"full_name\":\"National Geographic\",\n                                    \"id\":\"787132\",\n                                    \"is_verified\":true,\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/06ec75947ace6228666ef7ac7c8d9e1b/5E1141E8/t51.2885-19/s150x150/13597791_261499887553333_1855531912_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"natgeo\"\n                                 },\n                                 \"x\":0.16064453,\n                                 \"y\":0.29320475\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"user\":{  \n                                    \"full_name\":\"Emily Harrington\",\n                                    \"id\":\"2111892\",\n                                    \"is_verified\":true,\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/14de7d046fbc7832e15492b14cbac7c2/5DF87F25/t51.2885-19/s150x150/30841415_118979385642417_7215694693940592640_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"emilyaharrington\"\n                                 },\n                                 \"x\":0.8378906,\n                                 \"y\":0.4833903\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"user\":{  \n                                    \"full_name\":\"Renan Ozturk\",\n                                    \"id\":\"4326362\",\n                                    \"is_verified\":true,\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/0778dbbd7fdc7259847bd3107455345c/5DFF0858/t51.2885-19/10818112_782853255108470_946076930_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"renan_ozturk\"\n                                 },\n                                 \"x\":0.8527832,\n                                 \"y\":0.13703613\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"user\":{  \n                                    \"full_name\":\"Hilaree Nelson (ONeill)\",\n                                    \"id\":\"14999609\",\n                                    \"is_verified\":true,\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/d8d07b6f6c6d8aac8954134754fe7c25/5E0528F1/t51.2885-19/s150x150/40542885_2133241663559023_7643319590893649920_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"hilareenelson\"\n                                 },\n                                 \"x\":0.6057129,\n                                 \"y\":0.19656576\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"user\":{  \n                                    \"full_name\":\"Cory Richards\",\n                                    \"id\":\"19028900\",\n                                    \"is_verified\":true,\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/34065202c8a29a3c4b6e4ef8a02a0491/5E165C53/t51.2885-19/57674276_1190161047810775_5208218548769390592_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"coryrichards\"\n                                 },\n                                 \"x\":0.6813965,\n                                 \"y\":0.8799967\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"user\":{  \n                                    \"full_name\":\"National Geographic Travel\",\n                                    \"id\":\"23947096\",\n                                    \"is_verified\":true,\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/e56487890a4a526c8e866eadbc3159fb/5DF5DD39/t51.2885-19/s150x150/12132724_850743081710560_180824582_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"natgeotravel\"\n                                 },\n                                 \"x\":0.35473633,\n                                 \"y\":0.529777\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"user\":{  \n                                    \"full_name\":\"National Geographic Adventure\",\n                                    \"id\":\"414805671\",\n                                    \"is_verified\":true,\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/6c8274ce8b5c0eba7753b77e1a61800e/5DFA6E24/t51.2885-19/s150x150/12724642_511974045653432_550060489_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"natgeoadventure\"\n                                 },\n                                 \"x\":0.2944336,\n                                 \"y\":0.7671224\n                              }\n                           }\n                        ]\n                     },\n                     \"accessibility_caption\":\"\\u041d\\u0430 \\u0438\\u0437\\u043e\\u0431\\u0440\\u0430\\u0436\\u0435\\u043d\\u0438\\u0438 \\u043c\\u043e\\u0436\\u0435\\u0442 \\u043d\\u0430\\u0445\\u043e\\u0434\\u0438\\u0442\\u044c\\u0441\\u044f: \\u043d\\u0435\\u0431\\u043e, \\u043f\\u0440\\u0438\\u0440\\u043e\\u0434\\u0430 \\u0438 \\u043d\\u0430 \\u0443\\u043b\\u0438\\u0446\\u0435\",\n                     \"attribution\":null,\n                     \"shortcode\":\"B1l8BimhFr5\",\n                     \"edge_media_to_caption\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"text\":\"Photo by @coryrichards | Believing and doubting are very much two sides of the same coin for me. It follows me through life.. I believe I can accomplish the goals I attempt, yet the journey of exploring this potential success is littered with doubt. Or another example would be: Doubt feeds my discernment on the mountain keeping me safe. At the same time, intense doubt can create stagnation, preventing me from going deeper or trying harder, which as result, could end in final failure. Join the conversation about this on my main feed: @coryrichards \\nPictured here: An expedition teammate sets up a tent while on #expedition to attempt summiting Hkakabo Razi, Southeast Asia\\u2019s tallest mountain.  Shot #onassignment for #natgeo magazine\\u2019s article \\u201cHow A remote Peak in Myanmar Nearly Broke an Elite Team of Climbers\\u201d. #followme @coryrichards for more stories about the tallest #mountains of the world shot #onassignment for #natgeo.\\n\\n#yeswesleptthere #travel #adventure #climbing #mountains #nature\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_preview_comment\":{  \n                        \"count\":1,\n                        \"page_info\":{  \n                           \"has_next_page\":false,\n                           \"end_cursor\":null\n                        },\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"17981765863273328\",\n                                 \"text\":\"\\ud83d\\ude0d\",\n                                 \"created_at\":1566748621,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"9065557070\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/4d50996537fb9c6ac3889c5c87e70911/5DFD7A80/t51.2885-19/s150x150/66647324_473121356862840_463404860746760192_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"xipolita_maria\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           }\n                        ]\n                     },\n                     \"gating_info\":null,\n                     \"media_preview\":\"ACoctWrYAxWtHJkc1z9vLitBJc1z83KzS1zU3ComK+tVPMzULyVTmLlLrFfUVX+T1FZjzFelVjcGldhYhDhcAVdjlrFVyTVxCcUpLUpGqJQKgkkP51XRiTipXNTHXQb7leRyCQeCKq76nkqrgVryk3P/2Q==\",\n                     \"comments_disabled\":false,\n                     \"taken_at_timestamp\":1566748592,\n                     \"edge_media_preview_like\":{  \n                        \"count\":247,\n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"edge_media_to_sponsor_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"location\":{  \n                        \"id\":\"566972341\",\n                        \"has_public_page\":true,\n                        \"name\":\"Myanmar\",\n                        \"slug\":\"myanmar\"\n                     },\n                     \"viewer_has_liked\":false,\n                     \"viewer_has_saved\":false,\n                     \"viewer_has_saved_to_collection\":false,\n                     \"viewer_in_photo_of_you\":false,\n                     \"viewer_can_reshare\":true,\n                     \"owner\":{  \n                        \"id\":\"414805671\",\n                        \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/6c8274ce8b5c0eba7753b77e1a61800e/5DFA6E24/t51.2885-19/s150x150/12724642_511974045653432_550060489_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                        \"username\":\"natgeoadventure\",\n                        \"followed_by_viewer\":true,\n                        \"full_name\":\"National Geographic Adventure\",\n                        \"is_private\":false,\n                        \"requested_by_viewer\":false,\n                        \"blocked_by_viewer\":false,\n                        \"has_blocked_viewer\":false\n                     }\n                  }\n               },\n               {  \n                  \"node\":{  \n                     \"__typename\":\"GraphImage\",\n                     \"id\":\"2118332148355221552\",\n                     \"dimensions\":{  \n                        \"height\":1260,\n                        \"width\":1080\n                     },\n                     \"display_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/737829f54a4db52c3d96a4d12e35cf01/5DFD5F4B/t51.2885-15/e35/67503943_151408589261654_3928871968013976403_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                     \"display_resources\":[  \n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/0314f5bc174611bb6b7ff191be8bac33/5E09F0BD/t51.2885-15/sh0.08/e35/p640x640/67503943_151408589261654_3928871968013976403_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":640,\n                           \"config_height\":746\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/df12b15d492d1866a0172a98fea6383e/5DF366BD/t51.2885-15/sh0.08/e35/p750x750/67503943_151408589261654_3928871968013976403_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":750,\n                           \"config_height\":875\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/737829f54a4db52c3d96a4d12e35cf01/5DFD5F4B/t51.2885-15/e35/67503943_151408589261654_3928871968013976403_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":1080,\n                           \"config_height\":1260\n                        }\n                     ],\n                     \"follow_hashtag_info\":null,\n                     \"is_video\":false,\n                     \"should_log_client_event\":false,\n                     \"tracking_token\":\"eyJ2ZXJzaW9uIjo1LCJwYXlsb2FkIjp7ImlzX2FuYWx5dGljc190cmFja2VkIjp0cnVlLCJ1dWlkIjoiZDNkNWVkZTkzNjg3NDM0MmI5MzdmMGMzNDA1NWVlMTIyMTE4MzMyMTQ4MzU1MjIxNTUyIiwic2VydmVyX3Rva2VuIjoiMTU2Njc0ODY2MTIyMnwyMTE4MzMyMTQ4MzU1MjIxNTUyfDg3ODM4MzgxMTl8YjFhOTQ4OWYwMmNmNGM3NDcyN2NkZjUzZDE2YWZlYThmY2U3Nzg3YTY5NDQ0NDdkNjVkZjljNjFlOWU1MGFmOSJ9LCJzaWduYXR1cmUiOiIifQ==\",\n                     \"edge_media_to_tagged_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"accessibility_caption\":\"\\u041d\\u0435\\u0442 \\u043e\\u043f\\u0438\\u0441\\u0430\\u043d\\u0438\\u044f \\u0444\\u043e\\u0442\\u043e.\",\n                     \"attribution\":null,\n                     \"shortcode\":\"B1l092TAMgw\",\n                     \"edge_media_to_caption\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"text\":\"\\u041f\\u043e\\u043b\\u0443\\u043e\\u0441\\u0442\\u0440\\u043e\\u0432 \\u0420\\u044b\\u0431\\u0430\\u0447\\u0438\\u0439, \\u041c\\u0443\\u0440\\u043c\\u0430\\u043d\\u0441\\u043a\\u0430\\u044f \\u043e\\u0431\\u043b\\u0430\\u0441\\u0442\\u044c. \\u0410\\u0432\\u0442\\u043e\\u0440 \\u0444\\u043e\\u0442\\u043e: @ksergart.\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_preview_comment\":{  \n                        \"count\":12,\n                        \"page_info\":{  \n                           \"has_next_page\":true,\n                           \"end_cursor\":\"QVFDNUtWVWFJaDBYc0xvRE52bHh4SFVCaGI3bV9VNnhzWTNDS0ZzRUQzS2ZiSG80cU5IZGtVMTROMm9oa0dac1pVbHhBS2ZJVjlkX3JBNV9EaXVtMWFscg==\"\n                        },\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"17890215628384852\",\n                                 \"text\":\"\\u0411\\u0443\\u0434\\u0442\\u043e \\u0441\\u043a\\u0430\\u0437\\u043a\\u0430 \\ud83d\\udc9a\",\n                                 \"created_at\":1566747768,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"1318188656\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/ddae0523184feb0c3f7532b1116552f4/5E0BAB9A/t51.2885-19/s150x150/35999127_2123071171056159_1209990032148922368_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"elvira_mva\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"id\":\"18075684361128313\",\n                                 \"text\":\"\\ud83d\\udc4d\",\n                                 \"created_at\":1566748420,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"827758337\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/aa82522da7085d993a1a63584067dd77/5DF0BA2B/t51.2885-19/s150x150/12353182_1009321239130297_1860918634_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"petrkob62\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           }\n                        ]\n                     },\n                     \"gating_info\":null,\n                     \"media_preview\":\"ACQqgECSDKkGowhiPqKoWzKjZbOPatyLZJ91s+xrJ+76HO046bopPAHG5aznj2mt0x+Wcr0PUVDcW+4bh0oUiou2nQwmGDRUsi4bFFbGxMIyeasRK0ZBXrTIlT+Mj6DJ/wDrVJIFZfkJGOpIAz+XP4VDfQi5fNyxHQA/oajaUkfOxPfAxj6etUoJ0ZdjD6N3x70SIoOcZXsynBH1ByKiyQtiJ1BOefyNFRFVz95h9R/hxRWhQAqg55JHA9Pc/wBKcsm0YqseopaAsODnOTTmfP4VF3pwpjE3GikNFAz/2Q==\",\n                     \"comments_disabled\":false,\n                     \"taken_at_timestamp\":1566744892,\n                     \"edge_media_preview_like\":{  \n                        \"count\":1757,\n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"edge_media_to_sponsor_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"location\":null,\n                     \"viewer_has_liked\":false,\n                     \"viewer_has_saved\":false,\n                     \"viewer_has_saved_to_collection\":false,\n                     \"viewer_in_photo_of_you\":false,\n                     \"viewer_can_reshare\":true,\n                     \"owner\":{  \n                        \"id\":\"22563005\",\n                        \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/adbf0833f39d8466c28cd856428cb57c/5DF0D946/t51.2885-19/s150x150/29416770_171824350185992_3381245009872289792_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                        \"username\":\"natgeomagazineru\",\n                        \"followed_by_viewer\":true,\n                        \"full_name\":\"National Geographic Russia\",\n                        \"is_private\":false,\n                        \"requested_by_viewer\":false,\n                        \"blocked_by_viewer\":false,\n                        \"has_blocked_viewer\":false\n                     }\n                  }\n               },\n               {  \n                  \"node\":{  \n                     \"__typename\":\"GraphImage\",\n                     \"id\":\"2118335134316253776\",\n                     \"dimensions\":{  \n                        \"height\":1080,\n                        \"width\":1080\n                     },\n                     \"display_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/bce316215da7fb723aae9918b9c788b9/5DF82138/t51.2885-15/e35/67887681_2465654650378600_5958631488163850516_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                     \"display_resources\":[  \n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/9c10d2e28c91592f0193b0dc4e4e21db/5E0A2282/t51.2885-15/sh0.08/e35/s640x640/67887681_2465654650378600_5958631488163850516_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":640,\n                           \"config_height\":640\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/177982c8ccc90e94d75f85dcf9b18433/5E0DA546/t51.2885-15/sh0.08/e35/s750x750/67887681_2465654650378600_5958631488163850516_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":750,\n                           \"config_height\":750\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/bce316215da7fb723aae9918b9c788b9/5DF82138/t51.2885-15/e35/67887681_2465654650378600_5958631488163850516_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":1080,\n                           \"config_height\":1080\n                        }\n                     ],\n                     \"follow_hashtag_info\":null,\n                     \"is_video\":false,\n                     \"should_log_client_event\":false,\n                     \"tracking_token\":\"eyJ2ZXJzaW9uIjo1LCJwYXlsb2FkIjp7ImlzX2FuYWx5dGljc190cmFja2VkIjp0cnVlLCJ1dWlkIjoiZDNkNWVkZTkzNjg3NDM0MmI5MzdmMGMzNDA1NWVlMTIyMTE4MzM1MTM0MzE2MjUzNzc2Iiwic2VydmVyX3Rva2VuIjoiMTU2Njc0ODY2MTIyMnwyMTE4MzM1MTM0MzE2MjUzNzc2fDg3ODM4MzgxMTl8MDdkZTJjZjE4OWEwMmMwM2E1ZWExNWJmM2VlMzJjNmQ0MDAzNzcxNzgwZTJkYmU0ZDczNGNhOTg3YzIwY2Y5OCJ9LCJzaWduYXR1cmUiOiIifQ==\",\n                     \"edge_media_to_tagged_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"accessibility_caption\":\"\\u041d\\u0430 \\u0438\\u0437\\u043e\\u0431\\u0440\\u0430\\u0436\\u0435\\u043d\\u0438\\u0438 \\u043c\\u043e\\u0436\\u0435\\u0442 \\u043d\\u0430\\u0445\\u043e\\u0434\\u0438\\u0442\\u044c\\u0441\\u044f: \\u0442\\u0435\\u043a\\u0441\\u0442\",\n                     \"attribution\":null,\n                     \"shortcode\":\"B1l1pTMJlJQ\",\n                     \"edge_media_to_caption\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"text\":\"\\u041f\\u0440\\u0435\\u0434\\u043b\\u0430\\u0433\\u0430\\u0439\\u0442\\u0435 \\u0441\\u0432\\u043e\\u0438 \\u0432\\u0430\\u0440\\u0438\\u0430\\u043d\\u0442\\u044b \\u0432 \\u043a\\u043e\\u043c\\u043c\\u0435\\u043d\\u0442\\u0430\\u0440\\u0438\\u044f\\u0445\\u00a0\\ud83d\\ude09\\n\\u2800\\n#adme #adme_\\u0432\\u043e\\u043f\\u0440\\u043e\\u0441\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_preview_comment\":{  \n                        \"count\":54,\n                        \"page_info\":{  \n                           \"has_next_page\":true,\n                           \"end_cursor\":\"QVFBbk9vUFR3M0FCRFZMZE9LRTFHYjlKbHdvRlFxbVhZdUJoMFFjZzhPRUxYaEpELU5NYjRhQ3dWQWJET0VMcGJ6TWY4R0g2U2VSQm5SUXh4N2ZpbHBpYw==\"\n                        },\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"18094140058027449\",\n                                 \"text\":\"\\u042f\\u0431\\u043b\\u043e\\u043a\\u043e\",\n                                 \"created_at\":1566748247,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"10749647140\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/35267ebedde45d759e1d13e7cc8ccfc1/5DFC312A/t51.2885-19/s150x150/68706303_492164288009157_6648378867608190976_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"thisislauka\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"id\":\"17900024605364359\",\n                                 \"text\":\"\\ud83c\\udf4b\",\n                                 \"created_at\":1566748421,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"8441599909\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/29365d002b2a3e2fa551e6803d2c87c4/5DFCADF9/t51.2885-19/s150x150/66410920_2440993229292400_5166820540119252992_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"photo_by_vlados\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           }\n                        ]\n                     },\n                     \"gating_info\":null,\n                     \"media_preview\":\"ACoqzwtPC1IFqQJXPcRCFp22pwtLtpXEV9tG2pytNxRcCWOFjg4yOD16jP8A9arAjHTZz/vVVWpBQUT+XgZK9P8AaoMeOq/+Pf57VDSE07/1/SAe0ZPQY/HP41BSk0zNSIaGp4aq4pwpjJ91IXqLNNNFgHlqZuphptMR/9k=\",\n                     \"comments_disabled\":false,\n                     \"taken_at_timestamp\":1566745248,\n                     \"edge_media_preview_like\":{  \n                        \"count\":561,\n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"edge_media_to_sponsor_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"location\":null,\n                     \"viewer_has_liked\":false,\n                     \"viewer_has_saved\":false,\n                     \"viewer_has_saved_to_collection\":false,\n                     \"viewer_in_photo_of_you\":false,\n                     \"viewer_can_reshare\":true,\n                     \"owner\":{  \n                        \"id\":\"2779425302\",\n                        \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/62dd5481e860975939110e0651cf9499/5E08C764/t51.2885-19/s150x150/12816771_994305067322963_421387549_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                        \"username\":\"adme.ru\",\n                        \"followed_by_viewer\":true,\n                        \"full_name\":\"AdMe\",\n                        \"is_private\":false,\n                        \"requested_by_viewer\":false,\n                        \"blocked_by_viewer\":false,\n                        \"has_blocked_viewer\":false\n                     }\n                  }\n               },\n               {  \n                  \"node\":{  \n                     \"__typename\":\"GraphImage\",\n                     \"id\":\"2118305769246977062\",\n                     \"dimensions\":{  \n                        \"height\":1349,\n                        \"width\":1080\n                     },\n                     \"display_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/d4d22101153d599c04ac36ead09e446f/5E008836/t51.2885-15/e35/p1080x1080/67303980_161116331703747_7430462062728824761_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                     \"display_resources\":[  \n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/93653283a63e13cca89203de4c9d6724/5DF766D3/t51.2885-15/sh0.08/e35/p640x640/67303980_161116331703747_7430462062728824761_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":640,\n                           \"config_height\":799\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/1e32a346c9a3949c35ae6225f133c5f2/5DF18DD3/t51.2885-15/sh0.08/e35/p750x750/67303980_161116331703747_7430462062728824761_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":750,\n                           \"config_height\":937\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/d4d22101153d599c04ac36ead09e446f/5E008836/t51.2885-15/e35/p1080x1080/67303980_161116331703747_7430462062728824761_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":1080,\n                           \"config_height\":1349\n                        }\n                     ],\n                     \"follow_hashtag_info\":null,\n                     \"is_video\":false,\n                     \"should_log_client_event\":false,\n                     \"tracking_token\":\"eyJ2ZXJzaW9uIjo1LCJwYXlsb2FkIjp7ImlzX2FuYWx5dGljc190cmFja2VkIjp0cnVlLCJ1dWlkIjoiZDNkNWVkZTkzNjg3NDM0MmI5MzdmMGMzNDA1NWVlMTIyMTE4MzA1NzY5MjQ2OTc3MDYyIiwic2VydmVyX3Rva2VuIjoiMTU2Njc0ODY2MTIyMnwyMTE4MzA1NzY5MjQ2OTc3MDYyfDg3ODM4MzgxMTl8NTVlZDEyYzAzNjMwMWQ4ZDgzOTdmMWJlZDgyMWY5ZmM2ZmRiYmY3ZDBiNTNjODNlMTAxNjAxNWQ5ZjU4MTVlOSJ9LCJzaWduYXR1cmUiOiIifQ==\",\n                     \"edge_media_to_tagged_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"accessibility_caption\":\"\\u041d\\u0430 \\u0438\\u0437\\u043e\\u0431\\u0440\\u0430\\u0436\\u0435\\u043d\\u0438\\u0438 \\u043c\\u043e\\u0436\\u0435\\u0442 \\u043d\\u0430\\u0445\\u043e\\u0434\\u0438\\u0442\\u044c\\u0441\\u044f: \\u043e\\u0434\\u0438\\u043d \\u0438\\u043b\\u0438 \\u043d\\u0435\\u0441\\u043a\\u043e\\u043b\\u044c\\u043a\\u043e \\u0447\\u0435\\u043b\\u043e\\u0432\\u0435\\u043a, \\u043b\\u044e\\u0434\\u0438 \\u0441\\u0438\\u0434\\u044f\\u0442, \\u0431\\u043e\\u0440\\u043e\\u0434\\u0430, \\u0432 \\u043f\\u043e\\u043c\\u0435\\u0449\\u0435\\u043d\\u0438\\u0438 \\u0438 \\u0447\\u0430\\u0441\\u0442\\u044c \\u0442\\u0435\\u043b\\u0430 \\u043a\\u0440\\u0443\\u043f\\u043d\\u044b\\u043c \\u043f\\u043b\\u0430\\u043d\\u043e\\u043c\",\n                     \"attribution\":null,\n                     \"shortcode\":\"B1lu9-1oGwm\",\n                     \"edge_media_to_caption\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"text\":\"Sunday is for shopping! Get inspired by @anthony_colette who is wearing our new Grand Petite in Melrose. Tap to shop the look! #DanielWellington\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_preview_comment\":{  \n                        \"count\":7,\n                        \"page_info\":{  \n                           \"has_next_page\":true,\n                           \"end_cursor\":\"QVFEOHp1TzZoOHE0V0VnXzNfVEFiQmZQY3hHa3daNmRUSGNyVkpxNWpZNVNBWkpPanNuNmdLdTRIZG12Rmd3MzlhSVFMM1VUSm5zVERGWmdCOFE3NkdVSQ==\"\n                        },\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"17883424486407650\",\n                                 \"text\":\"#cool\",\n                                 \"created_at\":1566747095,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"3023386633\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/5590a713d4dde5cdba6bdc9b45c87f94/5E0FC332/t51.2885-19/s150x150/65580253_2161849217447103_2123178831798861824_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"arcadieus_arcd\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"id\":\"17854795318526180\",\n                                 \"text\":\"Woow \\u2764\\ufe0f\",\n                                 \"created_at\":1566747735,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"5908938021\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/52a8f3c8d912f774be052aee4c1f445b/5DFED1BC/t51.2885-19/s150x150/65314269_521974431700622_5216210486474833920_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"capturemoments__\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           }\n                        ]\n                     },\n                     \"gating_info\":null,\n                     \"media_preview\":\"ACEqdNcxx98t6Dn/AOtWbZxJI7GT7iDOPX/PWqm8DGBgd607VVSMyH5iw4PoeRioeiLjqyrcRJHiWM456VqqMgE+gqo86fIjgBcjO3/Z7n6k1LLqUacKNxo1YO1ybYaKo/2m/wDd/nRRYVyDTyomDOQFUHk4HXjuR/X6VozoRzG2C3p6n6evtWECCPeprSfypM5wCMfT0P4Gm11BO2gm0qTu4PcentWjaIWBZQuQerDn8KoM+5iW5PPPue9aemtw4PqD/OjoJbljbL6r+VFWcj1H5iipLORFJTn60ytTItAF13AHj9ff/Gmn9KvCqX8VSMOPSilop3A//9k=\",\n                     \"comments_disabled\":false,\n                     \"taken_at_timestamp\":1566741747,\n                     \"edge_media_preview_like\":{  \n                        \"count\":6507,\n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"edge_media_to_sponsor_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"location\":null,\n                     \"viewer_has_liked\":false,\n                     \"viewer_has_saved\":false,\n                     \"viewer_has_saved_to_collection\":false,\n                     \"viewer_in_photo_of_you\":false,\n                     \"viewer_can_reshare\":true,\n                     \"owner\":{  \n                        \"id\":\"47340181\",\n                        \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/200d102d62d14fdc91b31fcae730ebc4/5DF76D17/t51.2885-19/s150x150/36159707_670363839963003_7852937393920278528_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                        \"username\":\"danielwellington\",\n                        \"followed_by_viewer\":true,\n                        \"full_name\":\"Daniel Wellington\",\n                        \"is_private\":false,\n                        \"requested_by_viewer\":false,\n                        \"blocked_by_viewer\":false,\n                        \"has_blocked_viewer\":false\n                     }\n                  }\n               },\n               {  \n                  \"node\":{  \n                     \"__typename\":\"GraphImage\",\n                     \"id\":\"2118272670440360478\",\n                     \"dimensions\":{  \n                        \"height\":1349,\n                        \"width\":1080\n                     },\n                     \"display_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/437b34008def65237fd1b313fad3ab7b/5DDA21AC/t51.2885-15/e35/p1080x1080/67787998_3521450197881108_6632484576980197817_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                     \"display_resources\":[  \n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/3c8fb0eb371ac8523281acb4132498c8/5E076C69/t51.2885-15/sh0.08/e35/p640x640/67787998_3521450197881108_6632484576980197817_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":640,\n                           \"config_height\":799\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/a172a928cd4caebe457e999d76d63040/5DF25CAD/t51.2885-15/sh0.08/e35/p750x750/67787998_3521450197881108_6632484576980197817_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":750,\n                           \"config_height\":936\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/437b34008def65237fd1b313fad3ab7b/5DDA21AC/t51.2885-15/e35/p1080x1080/67787998_3521450197881108_6632484576980197817_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":1080,\n                           \"config_height\":1349\n                        }\n                     ],\n                     \"follow_hashtag_info\":null,\n                     \"is_video\":false,\n                     \"should_log_client_event\":false,\n                     \"tracking_token\":\"eyJ2ZXJzaW9uIjo1LCJwYXlsb2FkIjp7ImlzX2FuYWx5dGljc190cmFja2VkIjp0cnVlLCJ1dWlkIjoiZDNkNWVkZTkzNjg3NDM0MmI5MzdmMGMzNDA1NWVlMTIyMTE4MjcyNjcwNDQwMzYwNDc4Iiwic2VydmVyX3Rva2VuIjoiMTU2Njc0ODY2MTIyM3wyMTE4MjcyNjcwNDQwMzYwNDc4fDg3ODM4MzgxMTl8NTExZTA0Y2M2ZmFmY2UyNGVmNjdhMThiMmZkOWE5MzhmOTYyMDllZmMxMTk0MWY5ZWI2NjM1MWQ4YWFlNWNkNCJ9LCJzaWduYXR1cmUiOiIifQ==\",\n                     \"edge_media_to_tagged_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"accessibility_caption\":\"\\u041d\\u0430 \\u0438\\u0437\\u043e\\u0431\\u0440\\u0430\\u0436\\u0435\\u043d\\u0438\\u0438 \\u043c\\u043e\\u0436\\u0435\\u0442 \\u043d\\u0430\\u0445\\u043e\\u0434\\u0438\\u0442\\u044c\\u0441\\u044f: \\u043d\\u0430 \\u0443\\u043b\\u0438\\u0446\\u0435 \\u0438 \\u043f\\u0440\\u0438\\u0440\\u043e\\u0434\\u0430\",\n                     \"attribution\":null,\n                     \"shortcode\":\"B1lncVLBAoe\",\n                     \"edge_media_to_caption\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"text\":\"Photo @coreyrichproductions | For most of us, every day is a chance to celebrate climbing around the world. Still, happy global climbing day to everyone who has built a life around chasing rock, making friends in different places, and having incredible adventures with people you love.\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_preview_comment\":{  \n                        \"count\":71,\n                        \"page_info\":{  \n                           \"has_next_page\":true,\n                           \"end_cursor\":\"QVFEeE50bWJ4XzNSY0FWclVyRkpKcThOQkZVSmdlM3lyZ0tjckxpS0djMUlCdlA0d2J0eXgwU3pER0thRzhvZ0hXei0tcGprdy13NzJXWnh5bVlPb1pyQQ==\"\n                        },\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"17862621742481329\",\n                                 \"text\":\"Amazing\",\n                                 \"created_at\":1566748582,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"2137876030\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/c0879fb2bdc75469c347736caeb177f6/5DF3DC1E/t51.2885-19/s150x150/12950311_1031636496901792_515202217_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"ahmad.qabaa\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"id\":\"17922483298316433\",\n                                 \"text\":\"Courage and strength\\ud83d\\udc99\\ud83c\\udf35\\ud83d\\ude0e\",\n                                 \"created_at\":1566748648,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"8621536104\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/e328e713e61401462754448c98026483/5DD98E7F/t51.2885-19/s150x150/41280361_319736438803081_2140821784356716544_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"janiceimbeault\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           }\n                        ]\n                     },\n                     \"gating_info\":null,\n                     \"media_preview\":\"ACEq5miniNj0BPOOnf0+tMoAKKKKACiiigDqo1VBgDvu/GkaCJzuZQTnPPf6+o9B0FVxLTvNrqsc9ylc6eAGeM+4X278/wAqySMV0ZkBGDyDWTdgM2R2AB9//r1lKNtUaRlfQpUUuKKyNC95hp3mmqpNJW3OzHkRYaY9BUGaSkNQ23uaJJbC0U2ikM//2Q==\",\n                     \"comments_disabled\":false,\n                     \"taken_at_timestamp\":1566737801,\n                     \"edge_media_preview_like\":{  \n                        \"count\":21183,\n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"edge_media_to_sponsor_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"location\":null,\n                     \"viewer_has_liked\":false,\n                     \"viewer_has_saved\":false,\n                     \"viewer_has_saved_to_collection\":false,\n                     \"viewer_in_photo_of_you\":false,\n                     \"viewer_can_reshare\":true,\n                     \"owner\":{  \n                        \"id\":\"414805671\",\n                        \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/6c8274ce8b5c0eba7753b77e1a61800e/5DFA6E24/t51.2885-19/s150x150/12724642_511974045653432_550060489_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                        \"username\":\"natgeoadventure\",\n                        \"followed_by_viewer\":true,\n                        \"full_name\":\"National Geographic Adventure\",\n                        \"is_private\":false,\n                        \"requested_by_viewer\":false,\n                        \"blocked_by_viewer\":false,\n                        \"has_blocked_viewer\":false\n                     }\n                  }\n               },\n               {  \n                  \"node\":{  \n                     \"__typename\":\"GraphImage\",\n                     \"id\":\"2118327269893232788\",\n                     \"dimensions\":{  \n                        \"height\":1350,\n                        \"width\":1080\n                     },\n                     \"display_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/26e647d89ce68cf54d82bfa1cec7f185/5DDC96D3/t51.2885-15/fr/e15/p1080x1080/67479187_1080461632158935_7347868240441614334_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                     \"display_resources\":[  \n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/c9fd2abd0cb13cd260ba38c3bbfec748/5E05151B/t51.2885-15/sh0.08/e35/p640x640/67479187_1080461632158935_7347868240441614334_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":640,\n                           \"config_height\":800\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/83a3b2437c88a515cd7127fb74614606/5DDA05DF/t51.2885-15/sh0.08/e35/p750x750/67479187_1080461632158935_7347868240441614334_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":750,\n                           \"config_height\":937\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/26e647d89ce68cf54d82bfa1cec7f185/5DDC96D3/t51.2885-15/fr/e15/p1080x1080/67479187_1080461632158935_7347868240441614334_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":1080,\n                           \"config_height\":1350\n                        }\n                     ],\n                     \"follow_hashtag_info\":null,\n                     \"is_video\":false,\n                     \"should_log_client_event\":false,\n                     \"tracking_token\":\"eyJ2ZXJzaW9uIjo1LCJwYXlsb2FkIjp7ImlzX2FuYWx5dGljc190cmFja2VkIjp0cnVlLCJ1dWlkIjoiZDNkNWVkZTkzNjg3NDM0MmI5MzdmMGMzNDA1NWVlMTIyMTE4MzI3MjY5ODkzMjMyNzg4Iiwic2VydmVyX3Rva2VuIjoiMTU2Njc0ODY2MTIyM3wyMTE4MzI3MjY5ODkzMjMyNzg4fDg3ODM4MzgxMTl8NjIyMTFhZWY2M2QwOTcyNDgwNTIzYzExYjUyMzJmZGRkODcyNWVmMTdkNzcwYzZkOTllYTI1ODFhYmZjYmNmOSJ9LCJzaWduYXR1cmUiOiIifQ==\",\n                     \"edge_media_to_tagged_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"accessibility_caption\":\"\\u041d\\u0430 \\u0438\\u0437\\u043e\\u0431\\u0440\\u0430\\u0436\\u0435\\u043d\\u0438\\u0438 \\u043c\\u043e\\u0436\\u0435\\u0442 \\u043d\\u0430\\u0445\\u043e\\u0434\\u0438\\u0442\\u044c\\u0441\\u044f: \\u043d\\u0435\\u0431\\u043e, \\u0433\\u043e\\u0440\\u0430, \\u043d\\u0430 \\u0443\\u043b\\u0438\\u0446\\u0435 \\u0438 \\u0435\\u0434\\u0430\",\n                     \"attribution\":null,\n                     \"shortcode\":\"B1lz224AliU\",\n                     \"edge_media_to_caption\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"text\":\"repost @yogabyada : apero with a view \\ud83d\\ude0d\\u2600 #myasconalocarno .\\n.\\n.\\n#switzerland #urlaub #suisse #schweiz #landschaft #switzerland\\ud83c\\udde8\\ud83c\\udded #myswitzerland #inlovewithswitzerland #svizzera #visitswitzerland #ticino #switzerlandwonderland #switzerlandpictures #switzerland_vacations #blickheimat #amazingswitzerland #tessin #ticinomoments #visitticino #reise #reisen #reizen #voyage #voyages #voyager #ferien #vakantie #vacances\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_preview_comment\":{  \n                        \"count\":1,\n                        \"page_info\":{  \n                           \"has_next_page\":false,\n                           \"end_cursor\":null\n                        },\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"17888396074385239\",\n                                 \"text\":\"\\u2665\\ufe0f\\ud83c\\udde8\\ud83c\\udded\\ud83c\\udf79\\ud83c\\udfe8\\ud83c\\udf0a\\u2600\\ufe0f\\ud83e\\udd20\\ud83d\\udc4d\",\n                                 \"created_at\":1566745792,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"9489672931\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/8cb5d0fbc56bb46034a11a83256753f9/5E0F79A5/t51.2885-19/s150x150/59814578_318105222220041_1893677838452654080_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"sandrolandi88\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           }\n                        ]\n                     },\n                     \"gating_info\":null,\n                     \"media_preview\":\"ACEqsBKesZNZXnzYxk4/X8+tXLe9kHBG4evQ/wD166LmFh8NsjSSFlBIfHI/2Qa0UQDtmspLtw8m0Y3MDzz/AAgU57ic8BsfTj9ako19ntRWBsm9/wDvr/69FAFaRtncHPpk/wAqYk5z6j6VblgBKhMLxnnj1/OpUsRjJJz2yMf5FYuVtWacqK0DFmbA68nLY6D6elSCcH1H4A/4VrR2oEW1TyQcFh6/TqB29qxZrWW2OHHH94dP/rfjSTY7Ik84/wB4/wDfH/16Kq7hRTu+4rLsdU/I4AYjoD29/wAKy2tJdxkLDex5AJ/zxVOFiZASSTuHf3roqT0K3Mzy5YVy7gDGBkknn04z9PSq7XKmAw8t7uc5z+vB6VJqRO5R7H+dU5VAgBxyS+T+FCXUL9DH80+tFRUUxH//2Q==\",\n                     \"comments_disabled\":false,\n                     \"taken_at_timestamp\":1566744310,\n                     \"edge_media_preview_like\":{  \n                        \"count\":276,\n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"edge_media_to_sponsor_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"location\":{  \n                        \"id\":\"2368275479952352\",\n                        \"has_public_page\":true,\n                        \"name\":\"Hotel Casa Berno\",\n                        \"slug\":\"hotel-casa-berno\"\n                     },\n                     \"viewer_has_liked\":false,\n                     \"viewer_has_saved\":false,\n                     \"viewer_has_saved_to_collection\":false,\n                     \"viewer_in_photo_of_you\":false,\n                     \"viewer_can_reshare\":true,\n                     \"owner\":{  \n                        \"id\":\"10326379\",\n                        \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/61a298fb784d22c06efc77d9d5c5773c/5DDBF4FA/t51.2885-19/10958802_763286217112123_367851535_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                        \"username\":\"ascona_locarno\",\n                        \"followed_by_viewer\":true,\n                        \"full_name\":\"#MyAsconaLocarno\",\n                        \"is_private\":false,\n                        \"requested_by_viewer\":false,\n                        \"blocked_by_viewer\":false,\n                        \"has_blocked_viewer\":false\n                     }\n                  }\n               },\n               {  \n                  \"node\":{  \n                     \"__typename\":\"GraphImage\",\n                     \"id\":\"2118271896163192516\",\n                     \"dimensions\":{  \n                        \"height\":1350,\n                        \"width\":1080\n                     },\n                     \"display_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/9e429a54698127e4232e575e00115e18/5DF001DA/t51.2885-15/fr/e15/p1080x1080/68694466_466076210902073_853238738301639785_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                     \"display_resources\":[  \n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/37d826be8c9d7f9b5840d90faa0769e7/5DFD78E3/t51.2885-15/sh0.08/e35/p640x640/68694466_466076210902073_853238738301639785_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":640,\n                           \"config_height\":800\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/233b68b468dad0b6251556f2f6d377d1/5E0CFB1C/t51.2885-15/sh0.08/e35/p750x750/68694466_466076210902073_853238738301639785_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":750,\n                           \"config_height\":937\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/9e429a54698127e4232e575e00115e18/5DF001DA/t51.2885-15/fr/e15/p1080x1080/68694466_466076210902073_853238738301639785_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":1080,\n                           \"config_height\":1350\n                        }\n                     ],\n                     \"follow_hashtag_info\":null,\n                     \"is_video\":false,\n                     \"should_log_client_event\":false,\n                     \"tracking_token\":\"eyJ2ZXJzaW9uIjo1LCJwYXlsb2FkIjp7ImlzX2FuYWx5dGljc190cmFja2VkIjp0cnVlLCJ1dWlkIjoiZDNkNWVkZTkzNjg3NDM0MmI5MzdmMGMzNDA1NWVlMTIyMTE4MjcxODk2MTYzMTkyNTE2Iiwic2VydmVyX3Rva2VuIjoiMTU2Njc0ODY2MTIyM3wyMTE4MjcxODk2MTYzMTkyNTE2fDg3ODM4MzgxMTl8ZDExMTdlNmU0ZDM0Y2Y2NGZlODYyYTUxZjY5NTkxNmY4NTk1ZTFiNGYzYmFjNzhkOTg0OTNiMWYwZTEwZjdiNSJ9LCJzaWduYXR1cmUiOiIifQ==\",\n                     \"edge_media_to_tagged_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"accessibility_caption\":\"\\u041d\\u0430 \\u0438\\u0437\\u043e\\u0431\\u0440\\u0430\\u0436\\u0435\\u043d\\u0438\\u0438 \\u043c\\u043e\\u0436\\u0435\\u0442 \\u043d\\u0430\\u0445\\u043e\\u0434\\u0438\\u0442\\u044c\\u0441\\u044f: \\u0433\\u043e\\u0440\\u0430, \\u043d\\u0435\\u0431\\u043e, \\u043d\\u0430 \\u0443\\u043b\\u0438\\u0446\\u0435, \\u043f\\u0440\\u0438\\u0440\\u043e\\u0434\\u0430 \\u0438 \\u0432\\u043e\\u0434\\u0430\",\n                     \"attribution\":null,\n                     \"shortcode\":\"B1lnREEgA7E\",\n                     \"edge_media_to_caption\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"text\":\"\\ud83d\\udccdMALLORCA \\ud83c\\uddea\\ud83c\\uddf8\\n-\\nNestled perfectly between the mountains and the sea, this little group of houses seemed to melt right into the landscape. The pop of green from the surrounding nature brought this charming scene to life. -\\n\\ufffdPhoto by @vickarellaaa #visitmallorca #mallorca #spain #discovermallorca #ig_mallorca #earthpix #tourtheplanet #discoverglobe #ourplanetdaily #earthfocus #amazingdestinations #cheapflights #jacksflightclub\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_preview_comment\":{  \n                        \"count\":4,\n                        \"page_info\":{  \n                           \"has_next_page\":true,\n                           \"end_cursor\":\"QVFENTd4Wl93N3p5TGt0eHFxWnNHc1A2QnZoay1iWlpUejUxbWVaZzdDT0ZsWTdFRVB4YUtScGloTGYwWmgxZm1VV085NkFQbmRqT2lDQTg5eUUtN1gzbQ==\"\n                        },\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"17981334010272066\",\n                                 \"text\":\"@benrichardson23\",\n                                 \"created_at\":1566741489,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"338824606\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/12cdd412282fd2612c2a558c6c1c424e/5DF20C07/t51.2885-19/s150x150/39336092_1694262494012680_2312725105895014400_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"britanyleigh_\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"id\":\"17867827162457041\",\n                                 \"text\":\"@cristina_f_dasilva\",\n                                 \"created_at\":1566743315,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"1139258710\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/b28175041513b9672e7f5ca479735304/5DF088CF/t51.2885-19/s150x150/30589941_540396623023288_5576886880621821952_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"ddsergio07\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           }\n                        ]\n                     },\n                     \"gating_info\":null,\n                     \"media_preview\":\"ACEq30kVxkYINSZFctBeFOD0PJ9a0hcjbu3ZUDJ//V1oEa+RUUkqxjJIrBk1Mn7oyPWqcl075LYwe3+eaTb6DNv7Sv8Ae/nRXPfaX/vfoKKm0guidbU7vmI+Xrzx9OtJsBZhjP8AdAJx+ffiriwpuLHqef8A9Xv+NJIoLZHDHpzyfb6VoSUY+Tjpx1qRrJgNy/MP55qVcRnLckZPzDH4jmpnk80dSp4xg/n3pDKPlyf3RRV3c3qKKVgJ4wB7/Wq28qxP5VNVd+9bGRRd2c/NzjpTDLjripHqB6llIf5lFQ0VJR//2Q==\",\n                     \"comments_disabled\":false,\n                     \"taken_at_timestamp\":1566737709,\n                     \"edge_media_preview_like\":{  \n                        \"count\":353,\n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"edge_media_to_sponsor_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"location\":null,\n                     \"viewer_has_liked\":false,\n                     \"viewer_has_saved\":false,\n                     \"viewer_has_saved_to_collection\":false,\n                     \"viewer_in_photo_of_you\":false,\n                     \"viewer_can_reshare\":true,\n                     \"owner\":{  \n                        \"id\":\"3945672602\",\n                        \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/12bc576c6aac1a0e7fea5cbbe72fab68/5DFCC502/t51.2885-19/s150x150/26430072_177513656188084_7526879711784337408_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                        \"username\":\"jacksflightclub\",\n                        \"followed_by_viewer\":true,\n                        \"full_name\":\"Jack's Flight Club\",\n                        \"is_private\":false,\n                        \"requested_by_viewer\":false,\n                        \"blocked_by_viewer\":false,\n                        \"has_blocked_viewer\":false\n                     }\n                  }\n               },\n               {  \n                  \"node\":{  \n                     \"__typename\":\"GraphVideo\",\n                     \"id\":\"2118325174486904341\",\n                     \"dimensions\":{  \n                        \"height\":937,\n                        \"width\":750\n                     },\n                     \"display_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/13be8d30a48eb14ed80671b299ef12b9/5D64C46D/t51.2885-15/e35/69264712_912030972487091_8762021111054461246_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                     \"display_resources\":[  \n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/ecdf9ae3cf91b76e7d42650ea14b984b/5D65BB5B/t51.2885-15/sh0.08/e35/p640x640/69264712_912030972487091_8762021111054461246_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":640,\n                           \"config_height\":800\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/13be8d30a48eb14ed80671b299ef12b9/5D64C46D/t51.2885-15/e35/69264712_912030972487091_8762021111054461246_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":750,\n                           \"config_height\":937\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/13be8d30a48eb14ed80671b299ef12b9/5D64C46D/t51.2885-15/e35/69264712_912030972487091_8762021111054461246_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":1080,\n                           \"config_height\":1350\n                        }\n                     ],\n                     \"follow_hashtag_info\":null,\n                     \"is_video\":true,\n                     \"should_log_client_event\":false,\n                     \"tracking_token\":\"eyJ2ZXJzaW9uIjo1LCJwYXlsb2FkIjp7ImlzX2FuYWx5dGljc190cmFja2VkIjp0cnVlLCJ1dWlkIjoiZDNkNWVkZTkzNjg3NDM0MmI5MzdmMGMzNDA1NWVlMTIyMTE4MzI1MTc0NDg2OTA0MzQxIiwic2VydmVyX3Rva2VuIjoiMTU2Njc0ODY2MTIyNHwyMTE4MzI1MTc0NDg2OTA0MzQxfDg3ODM4MzgxMTl8ZDA1NTk3MzQ4NWMzNDRlYWVhNDI3NGU5YmY2N2YxM2NjYmQ0NjczNjE3ZGFhZTUwMzcwOTM4OWY1OTRjMmYzMyJ9LCJzaWduYXR1cmUiOiIifQ==\",\n                     \"edge_media_to_tagged_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"dash_info\":{  \n                        \"is_dash_eligible\":true,\n                        \"video_dash_manifest\":\"<MPD xmlns=\\\"urn:mpeg:dash:schema:mpd:2011\\\" minBufferTime=\\\"PT1.500S\\\" type=\\\"static\\\" mediaPresentationDuration=\\\"PT0H0M52.234S\\\" maxSegmentDuration=\\\"PT0H0M2.233S\\\" profiles=\\\"urn:mpeg:dash:profile:isoff-on-demand:2011,http://dashif.org/guidelines/dash264\\\">\\n <Period duration=\\\"PT0H0M52.234S\\\">\\n  <AdaptationSet segmentAlignment=\\\"true\\\" maxWidth=\\\"720\\\" maxHeight=\\\"900\\\" maxFrameRate=\\\"30\\\" par=\\\"720:900\\\" lang=\\\"und\\\" subsegmentAlignment=\\\"true\\\" subsegmentStartsWithSAP=\\\"1\\\">\\n   <Representation id=\\\"18076811335100267vd\\\" mimeType=\\\"video/mp4\\\" codecs=\\\"avc1.4D401F\\\" width=\\\"720\\\" height=\\\"900\\\" frameRate=\\\"30\\\" sar=\\\"1:1\\\" startWithSAP=\\\"1\\\" bandwidth=\\\"1237126\\\" FBQualityClass=\\\"hd\\\" FBQualityLabel=\\\"720w\\\" FBPlaybackResolutionMos=\\\"0:100.00,480:98.51,640:97.75,720:96.41\\\">\\n    <BaseURL>https://instagram.fhel2-1.fna.fbcdn.net/v/t50.2886-16/69645550_480225799441722_2175072939320684476_n.mp4?_nc_ht=instagram.fhel2-1.fna.fbcdn.net&amp;oh=8e9fe032ea72563a8391957fe1e0a895&amp;oe=5D6536D1</BaseURL>\\n    <SegmentBase indexRangeExact=\\\"true\\\" indexRange=\\\"906-1249\\\" FBFirstSegmentRange=\\\"1250-269057\\\" FBSecondSegmentRange=\\\"269058-536029\\\">\\n      <Initialization range=\\\"0-905\\\"/>\\n    </SegmentBase>\\n   </Representation>\\n  <Representation id=\\\"18076811584100267v\\\" mimeType=\\\"video/mp4\\\" codecs=\\\"avc1.4D401F\\\" width=\\\"240\\\" height=\\\"300\\\" frameRate=\\\"30\\\" sar=\\\"1:1\\\" startWithSAP=\\\"1\\\" bandwidth=\\\"152130\\\" FBQualityClass=\\\"sd\\\" FBQualityLabel=\\\"240w\\\" FBPlaybackResolutionMos=\\\"0:100.00,480:83.60,640:79.50,720:74.50\\\">\\n    <BaseURL>https://instagram.fhel2-1.fna.fbcdn.net/v/t50.2886-16/70183676_117711399319110_8282320485829783906_n.mp4?_nc_ht=instagram.fhel2-1.fna.fbcdn.net&amp;oh=6bd92b8c63be58720bbe47d6397f6e02&amp;oe=5D65BD57</BaseURL>\\n    <SegmentBase indexRangeExact=\\\"true\\\" indexRange=\\\"905-1248\\\" FBFirstSegmentRange=\\\"1249-44610\\\" FBSecondSegmentRange=\\\"44611-82773\\\">\\n      <Initialization range=\\\"0-904\\\"/>\\n    </SegmentBase>\\n   </Representation>\\n  <Representation id=\\\"18076811509100267v\\\" mimeType=\\\"video/mp4\\\" codecs=\\\"avc1.4D401F\\\" width=\\\"298\\\" height=\\\"372\\\" frameRate=\\\"30\\\" sar=\\\"1:1\\\" startWithSAP=\\\"1\\\" bandwidth=\\\"297569\\\" FBQualityClass=\\\"sd\\\" FBQualityLabel=\\\"298w\\\" FBPlaybackResolutionMos=\\\"0:100.00,480:91.34,640:87.68,720:82.82\\\">\\n    <BaseURL>https://instagram.fhel2-1.fna.fbcdn.net/v/t50.2886-16/69881952_350061425899503_7193270124713242713_n.mp4?_nc_ht=instagram.fhel2-1.fna.fbcdn.net&amp;oh=9c1db1af31c9b1171a2d03408111fb4d&amp;oe=5D658FEF</BaseURL>\\n    <SegmentBase indexRangeExact=\\\"true\\\" indexRange=\\\"906-1249\\\" FBFirstSegmentRange=\\\"1250-67133\\\" FBSecondSegmentRange=\\\"67134-134698\\\">\\n      <Initialization range=\\\"0-905\\\"/>\\n    </SegmentBase>\\n   </Representation>\\n  <Representation id=\\\"18076811431100267v\\\" mimeType=\\\"video/mp4\\\" codecs=\\\"avc1.4D401F\\\" width=\\\"474\\\" height=\\\"592\\\" frameRate=\\\"30\\\" sar=\\\"1:1\\\" startWithSAP=\\\"1\\\" bandwidth=\\\"627440\\\" FBQualityClass=\\\"sd\\\" FBQualityLabel=\\\"474w\\\" FBPlaybackResolutionMos=\\\"0:100.00,480:96.72,640:94.94,720:91.83\\\">\\n    <BaseURL>https://instagram.fhel2-1.fna.fbcdn.net/v/t50.2886-16/70118498_425225504779268_5310078796542193137_n.mp4?_nc_ht=instagram.fhel2-1.fna.fbcdn.net&amp;oh=ade57d5a98faec912206f45a540d029f&amp;oe=5D65C070</BaseURL>\\n    <SegmentBase indexRangeExact=\\\"true\\\" indexRange=\\\"905-1248\\\" FBFirstSegmentRange=\\\"1249-132342\\\" FBSecondSegmentRange=\\\"132343-273644\\\">\\n      <Initialization range=\\\"0-904\\\"/>\\n    </SegmentBase>\\n   </Representation>\\n  </AdaptationSet>\\n <AdaptationSet segmentAlignment=\\\"true\\\" lang=\\\"und\\\" subsegmentAlignment=\\\"true\\\" subsegmentStartsWithSAP=\\\"1\\\">\\n   <Representation id=\\\"18076811158100267ad\\\" mimeType=\\\"audio/mp4\\\" codecs=\\\"mp4a.40.2\\\" audioSamplingRate=\\\"44100\\\" startWithSAP=\\\"1\\\" bandwidth=\\\"66093\\\">\\n    <AudioChannelConfiguration schemeIdUri=\\\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\\\" value=\\\"2\\\"/>\\n    <BaseURL>https://instagram.fhel2-1.fna.fbcdn.net/v/t50.2886-16/69832620_374445850122732_9090818804720417562_n.mp4?_nc_ht=instagram.fhel2-1.fna.fbcdn.net&amp;oh=608f815048c27e043dc498ecdfcea94c&amp;oe=5D6594B8</BaseURL>\\n    <SegmentBase indexRangeExact=\\\"true\\\" indexRange=\\\"866-1221\\\" FBFirstSegmentRange=\\\"1222-17668\\\" FBSecondSegmentRange=\\\"17669-34115\\\">\\n      <Initialization range=\\\"0-865\\\"/>\\n    </SegmentBase>\\n   </Representation>\\n  </AdaptationSet>\\n </Period>\\n</MPD>\",\n                        \"number_of_qualities\":4\n                     },\n                     \"video_url\":\"https://scontent.cdninstagram.com/vp/1011cfdd3e091df8c1ad7564efa6964f/5D64B41F/t50.2886-16/69649533_141762473707062_42645298134425542_n.mp4?_nc_ht=scontent.cdninstagram.com\",\n                     \"video_view_count\":567703,\n                     \"attribution\":null,\n                     \"shortcode\":\"B1lzYXYDy4V\",\n                     \"edge_media_to_caption\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"text\":\"Video by Ronan Donovan @ronan_donovan | As with many social mammals, the adolescent males always seem to engage in the roughest play. Here, two yearling arctic wolves play with 10-week-old pups on the tundra of Canada\\u2019s Ellesmere Island. Even though Gray Mane, as he's called, was only a year old, he was the largest wolf in his pack and he clearly liked to play a little rough with the small pups. \\nAs with humans, play reinforces social bonds, promotes physical awareness, and just plain feels good. Check out the current issue of National Geographic for my article on the wolves (written by Neil Shea @neilshea13). A related three-part series on @natgeowild premieres tonight, August 25 at 8 p.m. EST, directed by Tony Gerber and filmed by Luke Padgett and me.\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_preview_comment\":{  \n                        \"count\":745,\n                        \"page_info\":{  \n                           \"has_next_page\":true,\n                           \"end_cursor\":\"QVFDeGZZQzFMNVZFUVpUbVREVlRaZDJRZmh1dEp4N1lDOENPRmt1OFlfdVNFUDVvQXJ1NGVKUXVwTnJHdEJFZV9ENXQtd3lUUlM5M2MwVGhpNkhjQ2U0dQ==\"\n                        },\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"18023172757222524\",\n                                 \"text\":\"Superb!!!!!\",\n                                 \"created_at\":1566748647,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"1697221883\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/d5b51f68d742d6eec423e0dcca920832/5DF7CBDC/t51.2885-19/s150x150/12120393_999447203470795_784571526_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"fernandacremilde\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"id\":\"17911987840339602\",\n                                 \"text\":\"This guy has to be the best\",\n                                 \"created_at\":1566748654,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"11707329041\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/74f911388bb105752598dcfd75ca7337/5E0EEAE2/t51.2885-19/s150x150/59919097_331233930837803_9049611661652000768_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"jeremyakin_\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           }\n                        ]\n                     },\n                     \"gating_info\":null,\n                     \"media_preview\":\"ACEqhFs3qKBbZP3v0qVZMHB6fypcjsQcdfX2pDIDaYGQd36GqzKV61aMpUZHFNkIIDdSaAKePeip+KKVx2HCTnHelU7c46t1pEXOTTjGexAB6g0wIRwCW5wM07duG7HHb/PvUoQL1OfpUQfrx7UgG5PpRS80UhkoYj3PrSFmpppe1FwsIcmjmlNMzQAbj7UUlFMR/9k=\",\n                     \"comments_disabled\":false,\n                     \"taken_at_timestamp\":1566744093,\n                     \"edge_media_preview_like\":{  \n                        \"count\":173756,\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"320965496\",\n                                 \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/26f2a6b06a14d18ff8a1915317b7561e/5DF8A6A4/t51.2885-19/s150x150/40533016_1968510403450030_7907013785250955264_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                 \"username\":\"irinchik55\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_to_sponsor_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"location\":null,\n                     \"viewer_has_liked\":false,\n                     \"viewer_has_saved\":false,\n                     \"viewer_has_saved_to_collection\":false,\n                     \"viewer_in_photo_of_you\":false,\n                     \"viewer_can_reshare\":true,\n                     \"owner\":{  \n                        \"id\":\"787132\",\n                        \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/06ec75947ace6228666ef7ac7c8d9e1b/5E1141E8/t51.2885-19/s150x150/13597791_261499887553333_1855531912_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                        \"username\":\"natgeo\",\n                        \"followed_by_viewer\":true,\n                        \"full_name\":\"National Geographic\",\n                        \"is_private\":false,\n                        \"requested_by_viewer\":false,\n                        \"blocked_by_viewer\":false,\n                        \"has_blocked_viewer\":false\n                     }\n                  }\n               },\n               {  \n                  \"node\":{  \n                     \"__typename\":\"GraphVideo\",\n                     \"id\":\"2117022749628464153\",\n                     \"dimensions\":{  \n                        \"height\":422,\n                        \"width\":750\n                     },\n                     \"display_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/0e69ec5084ff3c9ede40d3159f8e6c26/5D65210A/t51.2885-15/e35/67119652_2559484460769742_3380884424279150627_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                     \"display_resources\":[  \n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/745529ffa742381f0e885ad745152391/5D652070/t51.2885-15/sh0.08/e35/s640x640/67119652_2559484460769742_3380884424279150627_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":640,\n                           \"config_height\":360\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/0e69ec5084ff3c9ede40d3159f8e6c26/5D65210A/t51.2885-15/e35/67119652_2559484460769742_3380884424279150627_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":750,\n                           \"config_height\":422\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/0e69ec5084ff3c9ede40d3159f8e6c26/5D65210A/t51.2885-15/e35/67119652_2559484460769742_3380884424279150627_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":1080,\n                           \"config_height\":609\n                        }\n                     ],\n                     \"follow_hashtag_info\":null,\n                     \"is_video\":true,\n                     \"should_log_client_event\":false,\n                     \"tracking_token\":\"eyJ2ZXJzaW9uIjo1LCJwYXlsb2FkIjp7ImlzX2FuYWx5dGljc190cmFja2VkIjp0cnVlLCJ1dWlkIjoiZDNkNWVkZTkzNjg3NDM0MmI5MzdmMGMzNDA1NWVlMTIyMTE3MDIyNzQ5NjI4NDY0MTUzIiwic2VydmVyX3Rva2VuIjoiMTU2Njc0ODY2MTIyNHwyMTE3MDIyNzQ5NjI4NDY0MTUzfDg3ODM4MzgxMTl8ODYzN2Y4NDFlNzNlYmQ5YjM0NjE1ZjkxOWQzMmZlZDViZGYxYzYzZGVmODI4MDY1MjkxNTUwNWEwYmYzNTEyZCJ9LCJzaWduYXR1cmUiOiIifQ==\",\n                     \"edge_media_to_tagged_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"dash_info\":{  \n                        \"is_dash_eligible\":true,\n                        \"video_dash_manifest\":\"<MPD xmlns=\\\"urn:mpeg:dash:schema:mpd:2011\\\" minBufferTime=\\\"PT1.500S\\\" type=\\\"static\\\" mediaPresentationDuration=\\\"PT0H1M0.000S\\\" maxSegmentDuration=\\\"PT0H0M2.020S\\\" profiles=\\\"urn:mpeg:dash:profile:isoff-on-demand:2011,http://dashif.org/guidelines/dash264\\\">\\n <Period duration=\\\"PT0H1M0.000S\\\">\\n  <AdaptationSet segmentAlignment=\\\"true\\\" maxWidth=\\\"720\\\" maxHeight=\\\"406\\\" maxFrameRate=\\\"30\\\" par=\\\"720:406\\\" lang=\\\"und\\\" subsegmentAlignment=\\\"true\\\" subsegmentStartsWithSAP=\\\"1\\\">\\n   <Representation id=\\\"18061309372193151vd\\\" mimeType=\\\"video/mp4\\\" codecs=\\\"avc1.4D401F\\\" width=\\\"720\\\" height=\\\"406\\\" frameRate=\\\"30\\\" sar=\\\"1:1\\\" startWithSAP=\\\"1\\\" bandwidth=\\\"145264\\\" FBQualityClass=\\\"hd\\\" FBQualityLabel=\\\"720w\\\" FBPlaybackResolutionMos=\\\"0:100.00,480:99.17,640:99.21,720:99.24\\\">\\n    <BaseURL>https://instagram.fhel2-1.fna.fbcdn.net/v/t50.2886-16/69414956_547626535980296_8152974537214640359_n.mp4?_nc_ht=instagram.fhel2-1.fna.fbcdn.net&amp;oh=df28f713b5f700d0f1d561374fde63c6&amp;oe=5D65B685</BaseURL>\\n    <SegmentBase indexRangeExact=\\\"true\\\" indexRange=\\\"905-1296\\\" FBFirstSegmentRange=\\\"1297-18253\\\" FBSecondSegmentRange=\\\"18254-41816\\\">\\n      <Initialization range=\\\"0-904\\\"/>\\n    </SegmentBase>\\n   </Representation>\\n  </AdaptationSet>\\n <AdaptationSet segmentAlignment=\\\"true\\\" lang=\\\"und\\\" subsegmentAlignment=\\\"true\\\" subsegmentStartsWithSAP=\\\"1\\\">\\n   <Representation id=\\\"18061309336193151ad\\\" mimeType=\\\"audio/mp4\\\" codecs=\\\"mp4a.40.2\\\" audioSamplingRate=\\\"44100\\\" startWithSAP=\\\"1\\\" bandwidth=\\\"66204\\\">\\n    <AudioChannelConfiguration schemeIdUri=\\\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\\\" value=\\\"2\\\"/>\\n    <BaseURL>https://instagram.fhel2-1.fna.fbcdn.net/v/t50.2886-16/69600379_665246090552701_572347131944147546_n.mp4?_nc_ht=instagram.fhel2-1.fna.fbcdn.net&amp;oh=704693dd3a1591790d21b88563f39423&amp;oe=5D653B89</BaseURL>\\n    <SegmentBase indexRangeExact=\\\"true\\\" indexRange=\\\"866-1269\\\" FBFirstSegmentRange=\\\"1270-18668\\\" FBSecondSegmentRange=\\\"18669-35147\\\">\\n      <Initialization range=\\\"0-865\\\"/>\\n    </SegmentBase>\\n   </Representation>\\n  </AdaptationSet>\\n </Period>\\n</MPD>\",\n                        \"number_of_qualities\":1\n                     },\n                     \"video_url\":\"https://scontent.cdninstagram.com/vp/ca404406fa1161b8c621bca6dc651fbc/5D65BE04/t50.2886-16/69750299_170045060719808_7002627152866847262_n.mp4?_nc_ht=scontent.cdninstagram.com\",\n                     \"video_view_count\":776,\n                     \"attribution\":null,\n                     \"shortcode\":\"B1hLPltBnwZg1BhgTymFZBu_SMeXTQBw0o7Kx40\",\n                     \"edge_media_to_caption\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"text\":\"\\u041f\\u0440\\u0435\\u0434\\u043d\\u0430\\u0437\\u043d\\u0430\\u0447\\u0435\\u043d\\u0438\\u0435! \\u0414\\u0435\\u043d\\u0435\\u0436\\u043d\\u0430\\u044f \\u0447\\u0430\\u043a\\u0440\\u0430! \\u0414\\u0435\\u043d\\u0435\\u0436\\u043d\\u0430\\u044f \\u041c\\u0435\\u0434\\u0438\\u0442\\u0430\\u0446\\u0438\\u044f! \\u0410\\u043b\\u043b\\u0438\\u043b\\u0443\\u044f! #227\\n\\n\\u041f\\u043e\\u043b\\u043d\\u043e\\u0441\\u0442\\u044c\\u044e \\u0432\\u0438\\u0434\\u0435\\u043e \\u043c\\u043e\\u0436\\u0435\\u0442\\u0435 \\u043f\\u043e\\u0441\\u043c\\u043e\\u0442\\u0440\\u0435\\u0442\\u044c \\u043d\\u0430 \\u043c\\u043e\\u0435\\u043c \\u044e\\u0442\\u0443\\u0431 \\u043a\\u0430\\u043d\\u0430\\u043b\\u0435.\\n\\n#\\u0441\\u043c\\u044b\\u0441\\u043b\\u0436\\u0438\\u0437\\u043d\\u0438 #\\u0434\\u0443\\u0445\\u043e\\u0432\\u043d\\u043e\\u0441\\u0442\\u044c #\\u0430\\u043b\\u0435\\u043a\\u0441\\u0430\\u043d\\u0434\\u0440\\u043a\\u043e\\u0440\\u043e\\u043b\\u044c #\\u0434\\u0437\\u0435\\u043d #\\u043c\\u0430\\u0433\\u0438\\u044f #\\u0430\\u0441\\u0442\\u0440\\u043e\\u043b\\u043e\\u0433\\u0438\\u044f #\\u0441\\u0430\\u043c\\u043e\\u0440\\u0430\\u0437\\u0432\\u0438\\u0442\\u0438\\u0435 #\\u0441\\u0430\\u043c\\u043e\\u043f\\u043e\\u0437\\u043d\\u0430\\u043d\\u0438\\u0435\\n#\\u043f\\u0441\\u0438\\u0445\\u043e\\u043b\\u043e\\u0433\\u0438\\u044f #\\u0442\\u0435\\u043e\\u043b\\u043e\\u0433\\u0438\\u044f #\\u0431\\u0443\\u0434\\u0434\\u0438\\u0437\\u043c #\\u0439\\u043e\\u0433\\u0430 #\\u0441\\u0430\\u043c\\u043e\\u0440\\u0430\\u0437\\u0432\\u0438\\u0442\\u0438\\u0435 #\\u0441\\u043e\\u0446\\u0438\\u043e\\u043b\\u043e\\u0433\\u0438\\u044f #\\u043b\\u0430\\u0439\\u0444\\u0445\\u0430\\u043a #\\u0444\\u0438\\u043b\\u043e\\u0441\\u043e\\u0444\\u0438\\u044f #\\u043c\\u0435\\u0434\\u0438\\u0442\\u0430\\u0446\\u0438\\u044f\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_preview_comment\":{  \n                        \"count\":2,\n                        \"page_info\":{  \n                           \"has_next_page\":false,\n                           \"end_cursor\":null\n                        },\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"17971027423303829\",\n                                 \"text\":\"\\ud83d\\udc4d\",\n                                 \"created_at\":1566632816,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"5614861126\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/d2b48cf5e1baf77aca502892b92e5a9b/5DF8C99F/t51.2885-19/s150x150/35988631_1734823516608919_2917821848269881344_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"guryanova_natalya_555\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"id\":\"17846204974594318\",\n                                 \"text\":\"\\u0412 \\u0414\\u043d\\u0435\\u0432\\u043d\\u0438\\u043a\\u0435 \\u043e\\u0431\\u0441\\u0442\\u043e\\u044f\\u0442\\u0435\\u043b\\u044c\\u0441\\u0442\\u0432 \\u043c\\u043e\\u0435 \\u0432\\u043d\\u0438\\u043c\\u0430\\u043d\\u0438\\u0435 \\u043f\\u0440\\u0438\\u0432\\u043b\\u0435\\u043a\\u043b\\u043e \\u0437\\u0430\\u0434\\u0430\\u043d\\u0438\\u0435 \\u043d\\u0430 29.06. \\u041f\\u043b\\u0430\\u043d\\u0438\\u0440\\u0443\\u044e \\u0432\\u043a\\u043b\\u044e\\u0447\\u0438\\u0442\\u044c \\u0435\\u0433\\u043e \\u0432 \\u043f\\u0440\\u0430\\u043a\\u0442\\u0438\\u043a\\u0443 \\u0432 \\u0434\\u0430\\u043b\\u044c\\u043d\\u0435\\u0439\\u0448\\u0435\\u043c.\",\n                                 \"created_at\":1566741569,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"728458486\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/eb3ee5eb1ec510158bd7549df47a337f/5DFD0D63/t51.2885-19/s150x150/52328454_325651801433400_6764441670063751168_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"natalia_peshkova_\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           }\n                        ]\n                     },\n                     \"gating_info\":null,\n                     \"media_preview\":\"ACoXuItThcDNRpTpZRGhJpgRLdI0nlYOem7+HOM4+v8AXip2UVipI6vkL8zHcBjjjvjvWssnmKGPB6EehHWgCtKoqkVFXJTVSgZoK1MuFDoQelFFAjG3FjliSRwD3Hpj0/CtaEKicZ+b5jk5JJHNFFICKQ1XzRRTA//Z\",\n                     \"comments_disabled\":false,\n                     \"taken_at_timestamp\":1566588862,\n                     \"edge_media_preview_like\":{  \n                        \"count\":110,\n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"edge_media_to_sponsor_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"location\":null,\n                     \"viewer_has_liked\":false,\n                     \"viewer_has_saved\":false,\n                     \"viewer_has_saved_to_collection\":false,\n                     \"viewer_in_photo_of_you\":false,\n                     \"viewer_can_reshare\":true,\n                     \"owner\":{  \n                        \"id\":\"13846418535\",\n                        \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/c799dbeb8dd63a90765c788cc2203fa9/5E0071C7/t51.2885-19/s150x150/60779355_2621644501196839_286519566123663360_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                        \"username\":\"akchapters\",\n                        \"followed_by_viewer\":true,\n                        \"full_name\":\"\\u0410\\u043b\\u0435\\u043a\\u0441\\u0430\\u043d\\u0434\\u0440 \\u041a\\u043e\\u0440\\u043e\\u043b\\u044c | \\u0413\\u043b\\u0430\\u0432\\u044b\",\n                        \"is_private\":true,\n                        \"requested_by_viewer\":false,\n                        \"blocked_by_viewer\":false,\n                        \"has_blocked_viewer\":false\n                     }\n                  }\n               },\n               {  \n                  \"node\":{  \n                     \"__typename\":\"GraphImage\",\n                     \"id\":\"2118275964722976214\",\n                     \"dimensions\":{  \n                        \"height\":720,\n                        \"width\":1080\n                     },\n                     \"display_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/1085b370651736213d955a4b230d0778/5E04B310/t51.2885-15/fr/e15/s1080x1080/67730127_467681310751565_4014535606315768508_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                     \"display_resources\":[  \n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/7f43bcc1f960132f210de3f3fb2bfc9e/5E1126AA/t51.2885-15/sh0.08/e35/s640x640/67730127_467681310751565_4014535606315768508_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":640,\n                           \"config_height\":426\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/02030df1e61d53d8e363e956b6003d50/5DF4D6AA/t51.2885-15/sh0.08/e35/s750x750/67730127_467681310751565_4014535606315768508_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":750,\n                           \"config_height\":500\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/1085b370651736213d955a4b230d0778/5E04B310/t51.2885-15/fr/e15/s1080x1080/67730127_467681310751565_4014535606315768508_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":1080,\n                           \"config_height\":720\n                        }\n                     ],\n                     \"follow_hashtag_info\":null,\n                     \"is_video\":false,\n                     \"should_log_client_event\":false,\n                     \"tracking_token\":\"eyJ2ZXJzaW9uIjo1LCJwYXlsb2FkIjp7ImlzX2FuYWx5dGljc190cmFja2VkIjp0cnVlLCJ1dWlkIjoiZDNkNWVkZTkzNjg3NDM0MmI5MzdmMGMzNDA1NWVlMTIyMTE4Mjc1OTY0NzIyOTc2MjE0Iiwic2VydmVyX3Rva2VuIjoiMTU2Njc0ODY2MTIyNXwyMTE4Mjc1OTY0NzIyOTc2MjE0fDg3ODM4MzgxMTl8ZTk3NWRhMTFkOTMyYWE5MTlhYTBlODM5YzQzNjE3OTRmZTZkNDU2ODI1YTUwYWEwNjA2MTFkZDJkODZmZjM0NyJ9LCJzaWduYXR1cmUiOiIifQ==\",\n                     \"edge_media_to_tagged_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"accessibility_caption\":\"\\u041d\\u0430 \\u0438\\u0437\\u043e\\u0431\\u0440\\u0430\\u0436\\u0435\\u043d\\u0438\\u0438 \\u043c\\u043e\\u0436\\u0435\\u0442 \\u043d\\u0430\\u0445\\u043e\\u0434\\u0438\\u0442\\u044c\\u0441\\u044f: \\u043d\\u0435\\u0431\\u043e, \\u043e\\u0431\\u043b\\u0430\\u043a\\u043e, \\u043e\\u043a\\u0435\\u0430\\u043d, \\u043d\\u0430 \\u0443\\u043b\\u0438\\u0446\\u0435, \\u043f\\u0440\\u0438\\u0440\\u043e\\u0434\\u0430 \\u0438 \\u0432\\u043e\\u0434\\u0430\",\n                     \"attribution\":null,\n                     \"shortcode\":\"B1loMRNj5XW\",\n                     \"edge_media_to_caption\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"text\":\"Photo by @bethjwald | The sun sets over a panoramic view looking towards the White Rim region of Canyonlands National Park in southeastern Utah. The vast Canyonlands National Park protects dramatic landscapes of canyons carved by the Colorado River, fragile desert ecosystems, Native American rock paintings, dark skies and important watersheds and rivers from an array of threats, including mining, over-grazing, off-road vehicle use and development so that visitors will forever be able to lose themselves amongst its canyons and natural wonders. I have spent many weeks exploring the canyon worlds of this national park and its dramatic vistas helped form my photographic eye. National parks make available to all the natural wonders and heritage of our country and are an intrinsic part of America. In honor of the 103rd anniversary of the founding of the National Park Service we celebrate the National Parks today. For more photos of our ancient and modern relationship with nature and of national parks around the world, follow me at @bethjwald.  #canyonlove #canyonlandsnationalpark #americasbestidea #nationalparklove #findyourpark\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_preview_comment\":{  \n                        \"count\":242,\n                        \"page_info\":{  \n                           \"has_next_page\":true,\n                           \"end_cursor\":\"QVFCbGdQZnNMSG9IWE0yNkp0YXRlQjVtTG5tcXR0WWhacmREdDktZWxpWlpKYjlwYWFxRm9MTUdBaGluWG14eFlLSlpZVjFjMGs0UjRRVUNvVnY0anNjMg==\"\n                        },\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"18014094958243085\",\n                                 \"text\":\"@ohhverbatim\",\n                                 \"created_at\":1566748562,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"511750325\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/436f8a8d5a3e49237fdec94b16cd7b2a/5DF7E380/t51.2885-19/s150x150/28433529_154752318545706_5371696231099662336_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"pave_my_own_path\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"id\":\"17843042854610326\",\n                                 \"text\":\"I got the GREATEST SPEAKING VOICE of all time If you doubt me check my IG and see!\\ud83d\\ude4f\\ud83c\\udfff\\ud83d\\ude4f\\ud83c\\udfff\",\n                                 \"created_at\":1566748606,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"3166297639\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/5ee97b877de5019265b5d87331dca9e9/5DF39CF8/t51.2885-19/s150x150/66825378_2154949204810780_4891192315273543680_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"peoplesparadisepodcast\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           }\n                        ]\n                     },\n                     \"gating_info\":null,\n                     \"media_preview\":\"ACoclEk46qp/z9aPPfPMYx3rJ30F6jlfVr7v+CaXXZ/ebHmk/wAGPrjH8qiMgPZfzFZLvn1phI7UW8xaGx16KPzpmG/uiswISMk4FGxvf8qd/MnlXYZmk3UAZwPWpY0HWncoiALdBmp/Lx7nPAqw3yDirSKFGQO1ZuRoolbkHGCMD8B/n/JpmD/lv/r0E7pMHp1/L+lSbF9KBH//2Q==\",\n                     \"comments_disabled\":false,\n                     \"taken_at_timestamp\":1566738194,\n                     \"edge_media_preview_like\":{  \n                        \"count\":116360,\n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"edge_media_to_sponsor_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"location\":null,\n                     \"viewer_has_liked\":false,\n                     \"viewer_has_saved\":false,\n                     \"viewer_has_saved_to_collection\":false,\n                     \"viewer_in_photo_of_you\":false,\n                     \"viewer_can_reshare\":true,\n                     \"owner\":{  \n                        \"id\":\"23947096\",\n                        \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/e56487890a4a526c8e866eadbc3159fb/5DF5DD39/t51.2885-19/s150x150/12132724_850743081710560_180824582_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                        \"username\":\"natgeotravel\",\n                        \"followed_by_viewer\":true,\n                        \"full_name\":\"National Geographic Travel\",\n                        \"is_private\":false,\n                        \"requested_by_viewer\":false,\n                        \"blocked_by_viewer\":false,\n                        \"has_blocked_viewer\":false\n                     }\n                  }\n               },\n               {  \n                  \"node\":{  \n                     \"__typename\":\"GraphImage\",\n                     \"id\":\"2118003247143649215\",\n                     \"dimensions\":{  \n                        \"height\":771,\n                        \"width\":1080\n                     },\n                     \"display_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/d45df7f87a045312aa73523f8b210777/5DF280A0/t51.2885-15/fr/e15/s1080x1080/67617540_2065364250426167_7422279937392285823_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                     \"display_resources\":[  \n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/562fd3830b407d0b9efb49a7f8521535/5DF50E69/t51.2885-15/sh0.08/e35/s640x640/67617540_2065364250426167_7422279937392285823_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":640,\n                           \"config_height\":456\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/a6985f213dc53c31a14ac50b003494de/5DF091AD/t51.2885-15/sh0.08/e35/s750x750/67617540_2065364250426167_7422279937392285823_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":750,\n                           \"config_height\":535\n                        },\n                        {  \n                           \"src\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/d45df7f87a045312aa73523f8b210777/5DF280A0/t51.2885-15/fr/e15/s1080x1080/67617540_2065364250426167_7422279937392285823_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                           \"config_width\":1080,\n                           \"config_height\":771\n                        }\n                     ],\n                     \"follow_hashtag_info\":null,\n                     \"is_video\":false,\n                     \"should_log_client_event\":false,\n                     \"tracking_token\":\"eyJ2ZXJzaW9uIjo1LCJwYXlsb2FkIjp7ImlzX2FuYWx5dGljc190cmFja2VkIjp0cnVlLCJ1dWlkIjoiZDNkNWVkZTkzNjg3NDM0MmI5MzdmMGMzNDA1NWVlMTIyMTE4MDAzMjQ3MTQzNjQ5MjE1Iiwic2VydmVyX3Rva2VuIjoiMTU2Njc0ODY2MTIyNXwyMTE4MDAzMjQ3MTQzNjQ5MjE1fDg3ODM4MzgxMTl8NmYwMWQ1OTBhZjkxY2ZhZTFkYzlhOTAzZDdhYWZhYzNmOTc1Y2ExZDQzZTFlZTJlZjAwZTYxZGZjY2QxMzc3MyJ9LCJzaWduYXR1cmUiOiIifQ==\",\n                     \"edge_media_to_tagged_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"accessibility_caption\":\"\\u041d\\u0430 \\u0438\\u0437\\u043e\\u0431\\u0440\\u0430\\u0436\\u0435\\u043d\\u0438\\u0438 \\u043c\\u043e\\u0436\\u0435\\u0442 \\u043d\\u0430\\u0445\\u043e\\u0434\\u0438\\u0442\\u044c\\u0441\\u044f: \\u043d\\u0435\\u0431\\u043e, \\u0434\\u0435\\u0440\\u0435\\u0432\\u043e, \\u043d\\u0430 \\u0443\\u043b\\u0438\\u0446\\u0435 \\u0438 \\u043f\\u0440\\u0438\\u0440\\u043e\\u0434\\u0430\",\n                     \"attribution\":null,\n                     \"shortcode\":\"B1kqLtLHv-_\",\n                     \"edge_media_to_caption\":{  \n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"text\":\"Photo by @MichaelGeorge | If cities are the heart of the US, National Parks are its soul. Every time I get the opportunity to wander into this wild silence of nature I am humbled beyond measure. Our National Parks also showcase the diversity of land that makes up this country. From the face-melting swamps of the Everglades, to the crisp serene setting seen here. This image was taken during a hike on Hurricane Ridge in Olympic National Park. These two deer stood silently on the ridge, as the fog began to roll in. Their silhouettes illustrate one of many painterly moments I experienced on this hike. Visiting a National Park is one of the best (and least expensive!) adventures you can take yourself on. For this 103rd anniversary of the National Park\\u2019s founding, I am forever grateful for this protected land. #nationalparks #hurricaneridge #olympicnationalpark #washington #deer\"\n                              }\n                           }\n                        ]\n                     },\n                     \"edge_media_preview_comment\":{  \n                        \"count\":505,\n                        \"page_info\":{  \n                           \"has_next_page\":true,\n                           \"end_cursor\":\"QVFEY0tTNkNhcnV2Qm5CSnF2NjJwXzlFaUE0VXdPVzF4b0ZqbVItMmNVeEFCbC00aGdqRTdRNGxSOW9WOHc2dGhad0RBOFJJOHNOWnMzSV85NWhRUW9rVg==\"\n                        },\n                        \"edges\":[  \n                           {  \n                              \"node\":{  \n                                 \"id\":\"17847469972575823\",\n                                 \"text\":\"I love this\\ud83d\\udc4c\\ud83d\\udc4c\\ud83d\\udc4c\\ud83d\\udc4c\",\n                                 \"created_at\":1566748528,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"16635492189\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/048f2e98959113e152b2c5c002153adb/5E14C866/t51.2885-19/s150x150/69955433_1465673260242266_8501495765061861376_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"supertramp_ll\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           },\n                           {  \n                              \"node\":{  \n                                 \"id\":\"17860151434493563\",\n                                 \"text\":\"\\u2618\\ufe0f\\u2618\\ufe0f\",\n                                 \"created_at\":1566748544,\n                                 \"did_report_as_spam\":false,\n                                 \"owner\":{  \n                                    \"id\":\"4075637980\",\n                                    \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/ce544a4474591eae6598094134630083/5E13CF05/t51.2885-19/s150x150/15803591_236849253431666_2280179815115915264_n.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                                    \"username\":\"alexandermmaltsev\"\n                                 },\n                                 \"viewer_has_liked\":false\n                              }\n                           }\n                        ]\n                     },\n                     \"gating_info\":null,\n                     \"media_preview\":\"ACod6GlqPdSeYvrQK5JS1lPqsYVnUMQgzyNvOcADPXPP5U06vDkj0AOfXPpRYLmqTioROhGQwwfcVkz6zDtITLMQccYAPuf8K5nJ9TTA07jVZZT8nyL6d/xqot3KpyDyM4zzjP8AWq1FMRO91LIuxmJX0zxUFFFABRRRQB//2Q==\",\n                     \"comments_disabled\":false,\n                     \"taken_at_timestamp\":1566705684,\n                     \"edge_media_preview_like\":{  \n                        \"count\":235639,\n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"edge_media_to_sponsor_user\":{  \n                        \"edges\":[  \n\n                        ]\n                     },\n                     \"location\":null,\n                     \"viewer_has_liked\":false,\n                     \"viewer_has_saved\":false,\n                     \"viewer_has_saved_to_collection\":false,\n                     \"viewer_in_photo_of_you\":false,\n                     \"viewer_can_reshare\":true,\n                     \"owner\":{  \n                        \"id\":\"23947096\",\n                        \"profile_pic_url\":\"https://instagram.fhel2-1.fna.fbcdn.net/vp/e56487890a4a526c8e866eadbc3159fb/5DF5DD39/t51.2885-19/s150x150/12132724_850743081710560_180824582_a.jpg?_nc_ht=instagram.fhel2-1.fna.fbcdn.net\",\n                        \"username\":\"natgeotravel\",\n                        \"followed_by_viewer\":true,\n                        \"full_name\":\"National Geographic Travel\",\n                        \"is_private\":false,\n                        \"requested_by_viewer\":false,\n                        \"blocked_by_viewer\":false,\n                        \"has_blocked_viewer\":false\n                     }\n                  }\n               }\n            ]\n         }\n      }\n   },\n   \"status\":\"ok\"\n}"
  },
  {
    "path": "4-api/3_graphql/intro/readme.md",
    "content": "query ($number_of_repos: Int!) {\n  viewer {\n    name\n    login\n    repositories {\n      totalCount\n    }\n    followers {\n      totalCount\n    }\n    starredRepositories(last: $number_of_repos) {\n      totalCount\n      nodes {\n        name\n        description\n        forkCount\n        homepageUrl\n        stargazers {\n          totalCount\n        }\n        updatedAt\n      }\n    }\n  }\n}\n\n\n\n-----\n\n\n\nquery ($number_of_repos: Int!) {\n  viewer {\n    name\n    login\n    starredRepositories(last: $number_of_repos) {\n      totalCount\n      nodes {\n        name\n        description\n        homepageUrl\n        updatedAt\n        issues(last: 3, states: OPEN) {\n          edges {\n            node {\n              title\n              url\n            }\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "4-api/3_graphql/intro/schema.public.graphql",
    "content": "\"\"\"\nDefines what type of global IDs are accepted for a mutation argument of type ID.\n\"\"\"\ndirective @possibleTypes(\n  \"\"\"\n  Abstract type of accepted global ID\n  \"\"\"\n  abstractType: String\n\n  \"\"\"\n  Accepted types of global IDs.\n  \"\"\"\n  concreteTypes: [String!]!\n) on INPUT_FIELD_DEFINITION\n\n\"\"\"\nMarks an element of a GraphQL schema as only available via a preview header\n\"\"\"\ndirective @preview(\n  \"\"\"\n  The identifier of the API preview that toggles this field.\n  \"\"\"\n  toggledBy: String\n) on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION\n\n\"\"\"\nAutogenerated input type of AcceptBusinessMemberInvitation\n\"\"\"\ninput AcceptBusinessMemberInvitationInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The id of the invitation being accepted\n  \"\"\"\n  invitationId: ID! @possibleTypes(concreteTypes: [\"BusinessMemberInvitation\"])\n}\n\n\"\"\"\nAutogenerated return type of AcceptBusinessMemberInvitation\n\"\"\"\ntype AcceptBusinessMemberInvitationPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The invitation that was accepted.\n  \"\"\"\n  invitation: BusinessMemberInvitation @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A message confirming the result of accepting an administrator invitation.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of AcceptTopicSuggestion\n\"\"\"\ninput AcceptTopicSuggestionInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The name of the suggested topic.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The Node ID of the repository.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n}\n\n\"\"\"\nAutogenerated return type of AcceptTopicSuggestion\n\"\"\"\ntype AcceptTopicSuggestionPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The accepted topic.\n  \"\"\"\n  topic: Topic\n}\n\n\"\"\"\nRepresents an object which can take actions on GitHub. Typically a User or Bot.\n\"\"\"\ninterface Actor {\n  \"\"\"\n  A URL pointing to the actor's public avatar.\n  \"\"\"\n  avatarUrl(\n    \"\"\"\n    The size of the resulting square image.\n    \"\"\"\n    size: Int\n  ): URI!\n\n  \"\"\"\n  The username of the actor.\n  \"\"\"\n  login: String!\n\n  \"\"\"\n  The HTTP path for this actor.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this actor.\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nAutogenerated input type of AddAssigneesToAssignable\n\"\"\"\ninput AddAssigneesToAssignableInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  The id of the assignable object to add assignees to.\n  \"\"\"\n  assignableId: ID! @possibleTypes(concreteTypes: [\"Issue\", \"PullRequest\"], abstractType: \"Assignable\")\n\n  \"\"\"\n  The id of users to add as assignees.\n  \"\"\"\n  assigneeIds: [ID!]! @possibleTypes(concreteTypes: [\"User\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated return type of AddAssigneesToAssignable\n\"\"\"\ntype AddAssigneesToAssignablePayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  The item that was assigned.\n  \"\"\"\n  assignable: Assignable\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of AddComment\n\"\"\"\ninput AddCommentInput {\n  \"\"\"\n  The contents of the comment.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the subject to modify.\n  \"\"\"\n  subjectId: ID! @possibleTypes(concreteTypes: [\"Issue\", \"PullRequest\"], abstractType: \"IssueOrPullRequest\")\n}\n\n\"\"\"\nAutogenerated return type of AddComment\n\"\"\"\ntype AddCommentPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The edge from the subject's comment connection.\n  \"\"\"\n  commentEdge: IssueCommentEdge\n\n  \"\"\"\n  The subject\n  \"\"\"\n  subject: Node\n\n  \"\"\"\n  The edge from the subject's timeline connection.\n  \"\"\"\n  timelineEdge: IssueTimelineItemEdge\n}\n\n\"\"\"\nAutogenerated input type of AddLabelsToLabelable\n\"\"\"\ninput AddLabelsToLabelableInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ids of the labels to add.\n  \"\"\"\n  labelIds: [ID!]! @possibleTypes(concreteTypes: [\"Label\"])\n\n  \"\"\"\n  The id of the labelable object to add labels to.\n  \"\"\"\n  labelableId: ID! @possibleTypes(concreteTypes: [\"Issue\", \"PullRequest\"], abstractType: \"Labelable\")\n}\n\n\"\"\"\nAutogenerated return type of AddLabelsToLabelable\n\"\"\"\ntype AddLabelsToLabelablePayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The item that was labeled.\n  \"\"\"\n  labelable: Labelable\n}\n\n\"\"\"\nAutogenerated input type of AddProjectCard\n\"\"\"\ninput AddProjectCardInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The content of the card. Must be a member of the ProjectCardItem union\n  \"\"\"\n  contentId: ID @possibleTypes(concreteTypes: [\"Issue\", \"PullRequest\"], abstractType: \"ProjectCardItem\")\n\n  \"\"\"\n  The note on the card.\n  \"\"\"\n  note: String\n\n  \"\"\"\n  The Node ID of the ProjectColumn.\n  \"\"\"\n  projectColumnId: ID! @possibleTypes(concreteTypes: [\"ProjectColumn\"])\n}\n\n\"\"\"\nAutogenerated return type of AddProjectCard\n\"\"\"\ntype AddProjectCardPayload {\n  \"\"\"\n  The edge from the ProjectColumn's card connection.\n  \"\"\"\n  cardEdge: ProjectCardEdge\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ProjectColumn\n  \"\"\"\n  projectColumn: ProjectColumn\n}\n\n\"\"\"\nAutogenerated input type of AddProjectColumn\n\"\"\"\ninput AddProjectColumnInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The name of the column.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The Node ID of the project.\n  \"\"\"\n  projectId: ID! @possibleTypes(concreteTypes: [\"Project\"])\n}\n\n\"\"\"\nAutogenerated return type of AddProjectColumn\n\"\"\"\ntype AddProjectColumnPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The edge from the project's column connection.\n  \"\"\"\n  columnEdge: ProjectColumnEdge\n\n  \"\"\"\n  The project\n  \"\"\"\n  project: Project\n}\n\n\"\"\"\nAutogenerated input type of AddPullRequestReviewComment\n\"\"\"\ninput AddPullRequestReviewCommentInput {\n  \"\"\"\n  The text of the comment.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The SHA of the commit to comment on.\n  \"\"\"\n  commitOID: GitObjectID\n\n  \"\"\"\n  The comment id to reply to.\n  \"\"\"\n  inReplyTo: ID @possibleTypes(concreteTypes: [\"PullRequestReviewComment\"])\n\n  \"\"\"\n  The relative path of the file to comment on.\n  \"\"\"\n  path: String\n\n  \"\"\"\n  The line index in the diff to comment on.\n  \"\"\"\n  position: Int\n\n  \"\"\"\n  The Node ID of the review to modify.\n  \"\"\"\n  pullRequestReviewId: ID! @possibleTypes(concreteTypes: [\"PullRequestReview\"])\n}\n\n\"\"\"\nAutogenerated return type of AddPullRequestReviewComment\n\"\"\"\ntype AddPullRequestReviewCommentPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The newly created comment.\n  \"\"\"\n  comment: PullRequestReviewComment\n\n  \"\"\"\n  The edge from the review's comment connection.\n  \"\"\"\n  commentEdge: PullRequestReviewCommentEdge\n}\n\n\"\"\"\nAutogenerated input type of AddPullRequestReview\n\"\"\"\ninput AddPullRequestReviewInput {\n  \"\"\"\n  The contents of the review body comment.\n  \"\"\"\n  body: String\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The review line comments.\n  \"\"\"\n  comments: [DraftPullRequestReviewComment]\n\n  \"\"\"\n  The commit OID the review pertains to.\n  \"\"\"\n  commitOID: GitObjectID\n\n  \"\"\"\n  The event to perform on the pull request review.\n  \"\"\"\n  event: PullRequestReviewEvent\n\n  \"\"\"\n  The Node ID of the pull request to modify.\n  \"\"\"\n  pullRequestId: ID! @possibleTypes(concreteTypes: [\"PullRequest\"])\n}\n\n\"\"\"\nAutogenerated return type of AddPullRequestReview\n\"\"\"\ntype AddPullRequestReviewPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The newly created pull request review.\n  \"\"\"\n  pullRequestReview: PullRequestReview\n\n  \"\"\"\n  The edge from the pull request's review connection.\n  \"\"\"\n  reviewEdge: PullRequestReviewEdge\n}\n\n\"\"\"\nAutogenerated input type of AddReaction\n\"\"\"\ninput AddReactionInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The name of the emoji to react with.\n  \"\"\"\n  content: ReactionContent!\n\n  \"\"\"\n  The Node ID of the subject to modify.\n  \"\"\"\n  subjectId: ID! @possibleTypes(concreteTypes: [\"CommitComment\", \"Issue\", \"IssueComment\", \"PullRequest\", \"PullRequestReview\", \"PullRequestReviewComment\", \"TeamDiscussion\", \"TeamDiscussionComment\"], abstractType: \"Reactable\")\n}\n\n\"\"\"\nAutogenerated return type of AddReaction\n\"\"\"\ntype AddReactionPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The reaction object.\n  \"\"\"\n  reaction: Reaction\n\n  \"\"\"\n  The reactable subject.\n  \"\"\"\n  subject: Reactable\n}\n\n\"\"\"\nAutogenerated input type of AddStar\n\"\"\"\ninput AddStarInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Starrable ID to star.\n  \"\"\"\n  starrableId: ID! @possibleTypes(concreteTypes: [\"Gist\", \"Repository\", \"Topic\"], abstractType: \"Starrable\")\n}\n\n\"\"\"\nAutogenerated return type of AddStar\n\"\"\"\ntype AddStarPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The starrable.\n  \"\"\"\n  starrable: Starrable\n}\n\n\"\"\"\nRepresents a 'added_to_project' event on a given issue or pull request.\n\"\"\"\ntype AddedToProjectEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  Project referenced by event.\n  \"\"\"\n  project: Project @preview(toggledBy: \"starfox-preview\")\n\n  \"\"\"\n  Project card referenced by this project event.\n  \"\"\"\n  projectCard: ProjectCard @preview(toggledBy: \"starfox-preview\")\n\n  \"\"\"\n  Column name referenced by this project event.\n  \"\"\"\n  projectColumnName: String! @preview(toggledBy: \"starfox-preview\")\n}\n\n\"\"\"\nA GitHub App.\n\"\"\"\ntype App implements Node {\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The description of the app.\n  \"\"\"\n  description: String\n  id: ID!\n\n  \"\"\"\n  The hex color code, without the leading '#', for the logo background.\n  \"\"\"\n  logoBackgroundColor: String!\n\n  \"\"\"\n  A URL pointing to the app's logo.\n  \"\"\"\n  logoUrl(\n    \"\"\"\n    The size of the resulting image.\n    \"\"\"\n    size: Int\n  ): URI!\n\n  \"\"\"\n  The name of the app.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  A slug based on the name of the app for use in URLs.\n  \"\"\"\n  slug: String!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The URL to the app's homepage.\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nAn object that can have users assigned to it.\n\"\"\"\ninterface Assignable {\n  \"\"\"\n  A list of Users assigned to this object.\n  \"\"\"\n  assignees(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserConnection!\n}\n\n\"\"\"\nRepresents an 'assigned' event on any assignable object.\n\"\"\"\ntype AssignedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the assignable associated with the event.\n  \"\"\"\n  assignable: Assignable!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Identifies the user who was assigned.\n  \"\"\"\n  user: User\n}\n\n\"\"\"\nRepresents a 'base_ref_changed' event on a given issue or pull request.\n\"\"\"\ntype BaseRefChangedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n}\n\n\"\"\"\nRepresents a 'base_ref_force_pushed' event on a given pull request.\n\"\"\"\ntype BaseRefForcePushedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the after commit SHA for the 'base_ref_force_pushed' event.\n  \"\"\"\n  afterCommit: Commit\n\n  \"\"\"\n  Identifies the before commit SHA for the 'base_ref_force_pushed' event.\n  \"\"\"\n  beforeCommit: Commit\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  PullRequest referenced by event.\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  Identifies the fully qualified ref name for the 'base_ref_force_pushed' event.\n  \"\"\"\n  ref: Ref\n}\n\n\"\"\"\nRepresents a Git blame.\n\"\"\"\ntype Blame {\n  \"\"\"\n  The list of ranges from a Git blame.\n  \"\"\"\n  ranges: [BlameRange!]!\n}\n\n\"\"\"\nRepresents a range of information from a Git blame.\n\"\"\"\ntype BlameRange {\n  \"\"\"\n  Identifies the recency of the change, from 1 (new) to 10 (old). This is\n  calculated as a 2-quantile and determines the length of distance between the\n  median age of all the changes in the file and the recency of the current\n  range's change.\n  \"\"\"\n  age: Int!\n\n  \"\"\"\n  Identifies the line author\n  \"\"\"\n  commit: Commit!\n\n  \"\"\"\n  The ending line for the range\n  \"\"\"\n  endingLine: Int!\n\n  \"\"\"\n  The starting line for the range\n  \"\"\"\n  startingLine: Int!\n}\n\n\"\"\"\nRepresents a Git blob.\n\"\"\"\ntype Blob implements GitObject & Node {\n  \"\"\"\n  An abbreviated version of the Git object ID\n  \"\"\"\n  abbreviatedOid: String!\n\n  \"\"\"\n  Byte size of Blob object\n  \"\"\"\n  byteSize: Int!\n\n  \"\"\"\n  The HTTP path for this Git object\n  \"\"\"\n  commitResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this Git object\n  \"\"\"\n  commitUrl: URI!\n  id: ID!\n\n  \"\"\"\n  Indicates whether the Blob is binary or text\n  \"\"\"\n  isBinary: Boolean!\n\n  \"\"\"\n  Indicates whether the contents is truncated\n  \"\"\"\n  isTruncated: Boolean!\n\n  \"\"\"\n  The Git object ID\n  \"\"\"\n  oid: GitObjectID!\n\n  \"\"\"\n  The Repository the Git object belongs to\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  UTF8 text data or null if the Blob is binary\n  \"\"\"\n  text: String\n}\n\n\"\"\"\nA special type of user which takes actions on behalf of GitHub Apps.\n\"\"\"\ntype Bot implements Actor & Node & UniformResourceLocatable {\n  \"\"\"\n  A URL pointing to the GitHub App's public avatar.\n  \"\"\"\n  avatarUrl(\n    \"\"\"\n    The size of the resulting square image.\n    \"\"\"\n    size: Int\n  ): URI!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  The username of the actor.\n  \"\"\"\n  login: String!\n\n  \"\"\"\n  The HTTP path for this bot\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this bot\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nA branch protection rule.\n\"\"\"\ntype BranchProtectionRule implements Node {\n  \"\"\"\n  A list of conflicts matching branches protection rule and other branch protection rules\n  \"\"\"\n  branchProtectionRuleConflicts(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): BranchProtectionRuleConflictConnection!\n\n  \"\"\"\n  The actor who created this branch protection rule.\n  \"\"\"\n  creator: Actor\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  Will new commits pushed to matching branches dismiss pull request review approvals.\n  \"\"\"\n  dismissesStaleReviews: Boolean!\n  id: ID!\n\n  \"\"\"\n  Can admins overwrite branch protection.\n  \"\"\"\n  isAdminEnforced: Boolean!\n\n  \"\"\"\n  Repository refs that are protected by this rule\n  \"\"\"\n  matchingRefs(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): RefConnection!\n\n  \"\"\"\n  Identifies the protection rule pattern.\n  \"\"\"\n  pattern: String!\n\n  \"\"\"\n  A list push allowances for this branch protection rule.\n  \"\"\"\n  pushAllowances(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): PushAllowanceConnection!\n\n  \"\"\"\n  The repository associated with this branch protection rule.\n  \"\"\"\n  repository: Repository\n\n  \"\"\"\n  Number of approving reviews required to update matching branches.\n  \"\"\"\n  requiredApprovingReviewCount: Int\n\n  \"\"\"\n  List of required status check contexts that must pass for commits to be accepted to matching branches.\n  \"\"\"\n  requiredStatusCheckContexts: [String]\n\n  \"\"\"\n  Are approving reviews required to update matching branches.\n  \"\"\"\n  requiresApprovingReviews: Boolean!\n\n  \"\"\"\n  Are commits required to be signed.\n  \"\"\"\n  requiresCommitSignatures: Boolean!\n\n  \"\"\"\n  Are status checks required to update matching branches.\n  \"\"\"\n  requiresStatusChecks: Boolean!\n\n  \"\"\"\n  Are branches required to be up to date before merging.\n  \"\"\"\n  requiresStrictStatusChecks: Boolean!\n\n  \"\"\"\n  Is pushing to matching branches restricted.\n  \"\"\"\n  restrictsPushes: Boolean!\n\n  \"\"\"\n  Is dismissal of pull request reviews restricted.\n  \"\"\"\n  restrictsReviewDismissals: Boolean!\n\n  \"\"\"\n  A list review dismissal allowances for this branch protection rule.\n  \"\"\"\n  reviewDismissalAllowances(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): ReviewDismissalAllowanceConnection!\n}\n\n\"\"\"\nA conflict between two branch protection rules.\n\"\"\"\ntype BranchProtectionRuleConflict {\n  \"\"\"\n  Identifies the branch protection rule.\n  \"\"\"\n  branchProtectionRule: BranchProtectionRule\n\n  \"\"\"\n  Identifies the conflicting branch protection rule.\n  \"\"\"\n  conflictingBranchProtectionRule: BranchProtectionRule\n\n  \"\"\"\n  Identifies the branch ref that has conflicting rules\n  \"\"\"\n  ref: Ref\n}\n\n\"\"\"\nThe connection type for BranchProtectionRuleConflict.\n\"\"\"\ntype BranchProtectionRuleConflictConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [BranchProtectionRuleConflictEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [BranchProtectionRuleConflict]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype BranchProtectionRuleConflictEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: BranchProtectionRuleConflict\n}\n\n\"\"\"\nThe connection type for BranchProtectionRule.\n\"\"\"\ntype BranchProtectionRuleConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [BranchProtectionRuleEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [BranchProtectionRule]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype BranchProtectionRuleEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: BranchProtectionRule\n}\n\n\"\"\"\nA group of one or more organizations with consolidated billing.\n\"\"\"\ntype Business implements Node @preview(toggledBy: \"gwenpool-preview\") {\n  \"\"\"\n  Business information only visible to admins\n  \"\"\"\n  adminInfo: BusinessAdminInfo\n\n  \"\"\"\n  A URL pointing to the business's public avatar.\n  \"\"\"\n  avatarUrl(\n    \"\"\"\n    The size of the resulting square image.\n    \"\"\"\n    size: Int\n  ): URI!\n\n  \"\"\"\n  Business billing information visible to billing managers\n  \"\"\"\n  billingInfo: BusinessBillingInfo\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The description of the business\n  \"\"\"\n  description: String\n\n  \"\"\"\n  The description of the business as HTML.\n  \"\"\"\n  descriptionHTML: HTML!\n  id: ID!\n\n  \"\"\"\n  The location of the business\n  \"\"\"\n  location: String\n\n  \"\"\"\n  The name of the business\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  A list of organizations that belong to this business.\n  \"\"\"\n  organizations(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for organizations returned from the connection.\n    \"\"\"\n    orderBy: OrganizationOrder = {field: LOGIN, direction: ASC}\n  ): OrganizationConnection!\n\n  \"\"\"\n  The HTTP path for this business.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this business.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  Is the current viewer an admin of this business?\n  \"\"\"\n  viewerIsAdmin: Boolean!\n\n  \"\"\"\n  The URL for the business's website\n  \"\"\"\n  websiteUrl: URI\n}\n\n\"\"\"\nBusiness information only visible to admins\n\"\"\"\ntype BusinessAdminInfo @preview(toggledBy: \"gwenpool-preview\") {\n  \"\"\"\n  A list of all of the admins for this business.\n  \"\"\"\n  admins(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    The search string to look for.\n    \"\"\"\n    query: String\n  ): UserConnection!\n\n  \"\"\"\n  A list of users in the business who currently have two-factor authentication disabled\n  \"\"\"\n  affiliatedUsersWithTwoFactorDisabled(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserConnection!\n\n  \"\"\"\n  Whether or not affiliated users with two-factor auth disabled exist in the business.\n  \"\"\"\n  affiliatedUsersWithTwoFactorDisabledExist: Boolean!\n\n  \"\"\"\n  The setting value for whether private repository forking is enabled for repositories in organizations in this business.\n  \"\"\"\n  allowPrivateRepositoryForkingSetting: BusinessEnabledDisabledSettingValue!\n\n  \"\"\"\n  The setting value for base repository permissions for organizations in this business.\n  \"\"\"\n  defaultRepositoryPermissionSetting: BusinessDefaultRepositoryPermissionSettingValue!\n\n  \"\"\"\n  Whether or not the default repository permission is currently being updated.\n  \"\"\"\n  isUpdatingDefaultRepositoryPermission: Boolean!\n\n  \"\"\"\n  Whether the two factor requirement is currently being enforced\n  \"\"\"\n  isUpdatingTwoFactorRequirement: Boolean!\n\n  \"\"\"\n  The setting value for whether organization members with admin permissions on a\n  repository can change repository visibility.\n  \"\"\"\n  membersCanChangeRepositoryVisibilitySetting: BusinessEnabledDisabledSettingValue!\n\n  \"\"\"\n  The setting value for whether members of organizations in the business can create repositories.\n  \"\"\"\n  membersCanCreateRepositoriesSetting: BusinessMembersCanCreateRepositoriesSettingValue!\n\n  \"\"\"\n  The setting value for whether members with admin permissions for repositories can delete issues.\n  \"\"\"\n  membersCanDeleteIssuesSetting: BusinessEnabledDisabledSettingValue!\n\n  \"\"\"\n  The setting value for whether members with admin permissions for repositories can delete or transfer repositories.\n  \"\"\"\n  membersCanDeleteRepositoriesSetting: BusinessEnabledDisabledSettingValue!\n\n  \"\"\"\n  The setting value for whether members of organizations in the business can invite outside collaborators.\n  \"\"\"\n  membersCanInviteCollaboratorsSetting: BusinessEnabledDisabledSettingValue!\n\n  \"\"\"\n  The setting value for whether members with admin permissions for repositories can update protected branches.\n  \"\"\"\n  membersCanUpdateProtectedBranchesSetting: BusinessEnabledDisabledSettingValue!\n\n  \"\"\"\n  The setting value for whether organization projects are enabled for organizations in this business.\n  \"\"\"\n  organizationProjectsSetting: BusinessEnabledDisabledSettingValue!\n\n  \"\"\"\n  A list of pending admin invitations for the business.\n  \"\"\"\n  pendingAdminInvitations(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    The search string to look for.\n    \"\"\"\n    query: String\n  ): BusinessMemberInvitationConnection!\n\n  \"\"\"\n  A list of pending member invitations in the business.\n  \"\"\"\n  pendingMemberInvitations(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    The search string to look for.\n    \"\"\"\n    query: String\n  ): BusinessPendingMemberInvitationConnection!\n\n  \"\"\"\n  The setting value for whether repository projects are enabled in this business.\n  \"\"\"\n  repositoryProjectsSetting: BusinessEnabledDisabledSettingValue!\n\n  \"\"\"\n  The setting value for whether team discussions are enabled for organizations in this business.\n  \"\"\"\n  teamDiscussionsSetting: BusinessEnabledDisabledSettingValue!\n\n  \"\"\"\n  The setting value for whether the business requires two factor authentication for its organizations and users\n  \"\"\"\n  twoFactorRequiredSetting: BusinessEnabledSettingValue!\n}\n\n\"\"\"\nBusiness billing information visible to billing managers and admins\n\"\"\"\ntype BusinessBillingInfo @preview(toggledBy: \"gwenpool-preview\") {\n  \"\"\"\n  The number of data packs used by all organizations owned by the business\n  \"\"\"\n  assetPacks: Int!\n\n  \"\"\"\n  The number of available seats across all owned organizations based on the unique number of billable users\n  \"\"\"\n  availableSeats: Int!\n\n  \"\"\"\n  The bandwidth quota in GB for all organizations owned by the business\n  \"\"\"\n  bandwidthQuota: Float!\n\n  \"\"\"\n  The bandwidth usage in GB for all organizations owned by the business\n  \"\"\"\n  bandwidthUsage: Float!\n\n  \"\"\"\n  The bandwidth usage as a percentage of the bandwidth quota\n  \"\"\"\n  bandwidthUsagePercentage: Int!\n\n  \"\"\"\n  A list of all of the billing managers for this business.\n  \"\"\"\n  billingManagers(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserConnection!\n\n  \"\"\"\n  A list of pending billing manager invitations for the business.\n  \"\"\"\n  pendingBillingManagerInvitations(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    The search string to look for.\n    \"\"\"\n    query: String\n  ): BusinessMemberInvitationConnection!\n\n  \"\"\"\n  The total seats across all organizations owned by the business\n  \"\"\"\n  seats: Int!\n\n  \"\"\"\n  The storage quota in GB for all organizations owned by the business\n  \"\"\"\n  storageQuota: Float!\n\n  \"\"\"\n  The storage usage in GB for all organizations owned by the business\n  \"\"\"\n  storageUsage: Float!\n\n  \"\"\"\n  The storage usage as a percentage of the storage quota\n  \"\"\"\n  storageUsagePercentage: Int!\n\n  \"\"\"\n  The total number of billable users across all organizations owned by the business\n  \"\"\"\n  totalBillableUsers: Int!\n\n  \"\"\"\n  The unique number of billable users across all organizations owned by the business\n  \"\"\"\n  uniqueBillableUsersCount: Int!\n\n  \"\"\"\n  The unique number of billable users as a percentage of seats\n  \"\"\"\n  uniqueBillableUsersPercent: Int!\n}\n\n\"\"\"\nThe possible values for the business default repository permission setting.\n\"\"\"\nenum BusinessDefaultRepositoryPermissionSettingValue @preview(toggledBy: \"gwenpool-preview\") {\n  \"\"\"\n  Organization members will be able to clone, pull, push, and add new collaborators to all organization repositories.\n  \"\"\"\n  ADMIN\n\n  \"\"\"\n  Organization members will only be able to clone and pull public repositories.\n  \"\"\"\n  NONE\n\n  \"\"\"\n  Organizations in the business choose default repository permissions for their members.\n  \"\"\"\n  NO_POLICY\n\n  \"\"\"\n  Organization members will be able to clone and pull all organization repositories.\n  \"\"\"\n  READ\n\n  \"\"\"\n  Organization members will be able to clone, pull, and push all organization repositories.\n  \"\"\"\n  WRITE\n}\n\n\"\"\"\nThe possible values for an enabled/disabled business setting.\n\"\"\"\nenum BusinessEnabledDisabledSettingValue @preview(toggledBy: \"gwenpool-preview\") {\n  \"\"\"\n  The setting is disabled for organizations in the business.\n  \"\"\"\n  DISABLED\n\n  \"\"\"\n  The setting is enabled for organizations in the business.\n  \"\"\"\n  ENABLED\n\n  \"\"\"\n  There is no policy set for organizations in the business.\n  \"\"\"\n  NO_POLICY\n}\n\n\"\"\"\nThe possible values for an enabled/no policy business setting.\n\"\"\"\nenum BusinessEnabledSettingValue @preview(toggledBy: \"gwenpool-preview\") {\n  \"\"\"\n  The setting is enabled for organizations in the business.\n  \"\"\"\n  ENABLED\n\n  \"\"\"\n  There is no policy set for organizations in the business.\n  \"\"\"\n  NO_POLICY\n}\n\n\"\"\"\nAn invitation for a user to become an admin or billing manager of a business.\n\"\"\"\ntype BusinessMemberInvitation implements Node @preview(toggledBy: \"gwenpool-preview\") {\n  \"\"\"\n  The business the invitation is for.\n  \"\"\"\n  business: Business!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  The email of the person who was invited to the business.\n  \"\"\"\n  email: String\n  id: ID!\n\n  \"\"\"\n  The user who was invited to the business.\n  \"\"\"\n  invitee: User\n\n  \"\"\"\n  The user who created the invitation.\n  \"\"\"\n  inviter: User!\n\n  \"\"\"\n  The invitee's pending role in the business (admin or billing_manager).\n  \"\"\"\n  role: BusinessMemberInvitationRole!\n}\n\n\"\"\"\nThe connection type for BusinessMemberInvitation.\n\"\"\"\ntype BusinessMemberInvitationConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [BusinessMemberInvitationEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [BusinessMemberInvitation] @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype BusinessMemberInvitationEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: BusinessMemberInvitation @preview(toggledBy: \"gwenpool-preview\")\n}\n\n\"\"\"\nThe possible business member invitation roles.\n\"\"\"\nenum BusinessMemberInvitationRole @preview(toggledBy: \"gwenpool-preview\") {\n  \"\"\"\n  The invitee is invited to be an administrator of the business.\n  \"\"\"\n  ADMIN\n\n  \"\"\"\n  The invitee is invited to be a billing manager of the business.\n  \"\"\"\n  BILLING_MANAGER\n}\n\n\"\"\"\nThe possible values for the business members can create repositories setting.\n\"\"\"\nenum BusinessMembersCanCreateRepositoriesSettingValue @preview(toggledBy: \"gwenpool-preview\") {\n  \"\"\"\n  Members will be able to create public and private repositories.\n  \"\"\"\n  ALL\n\n  \"\"\"\n  Members will not be able to create public or private repositories.\n  \"\"\"\n  DISABLED\n\n  \"\"\"\n  Organization administrators choose whether to allow members to create repositories.\n  \"\"\"\n  NO_POLICY\n\n  \"\"\"\n  Members will be able to create only private repositories.\n  \"\"\"\n  PRIVATE\n}\n\n\"\"\"\nThe connection type for OrganizationInvitation.\n\"\"\"\ntype BusinessPendingMemberInvitationConnection @preview(toggledBy: \"gwenpool-preview\") {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [OrganizationInvitationEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [OrganizationInvitation]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n\n  \"\"\"\n  Identifies the total count of unique users in the connection.\n  \"\"\"\n  totalUniqueUserCount: Int!\n}\n\n\"\"\"\nA subset of repository information queryable from a business.\n\"\"\"\ntype BusinessRepositoryInfo implements Node @preview(toggledBy: \"gwenpool-preview\") {\n  id: ID!\n\n  \"\"\"\n  The repository's name.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The repository's name with owner.\n  \"\"\"\n  nameWithOwner: String!\n}\n\n\"\"\"\nAutogenerated input type of CancelBusinessAdminInvitation\n\"\"\"\ninput CancelBusinessAdminInvitationInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the pending business admin invitation.\n  \"\"\"\n  invitationId: ID! @possibleTypes(concreteTypes: [\"BusinessMemberInvitation\"])\n}\n\n\"\"\"\nAutogenerated return type of CancelBusinessAdminInvitation\n\"\"\"\ntype CancelBusinessAdminInvitationPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The invitation that was canceled.\n  \"\"\"\n  invitation: BusinessMemberInvitation @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A message confirming the result of canceling an administrator invitation.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of CancelBusinessBillingManagerInvitation\n\"\"\"\ninput CancelBusinessBillingManagerInvitationInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the pending business billing manager invitation.\n  \"\"\"\n  invitationId: ID! @possibleTypes(concreteTypes: [\"BusinessMemberInvitation\"])\n}\n\n\"\"\"\nAutogenerated return type of CancelBusinessBillingManagerInvitation\n\"\"\"\ntype CancelBusinessBillingManagerInvitationPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The invitation that was canceled.\n  \"\"\"\n  invitation: BusinessMemberInvitation @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A message confirming the result of canceling a billing manager invitation.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nA single check annotation.\n\"\"\"\ntype CheckAnnotation @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The annotation's severity level.\n  \"\"\"\n  annotationLevel: CheckAnnotationLevel\n\n  \"\"\"\n  The path to the file that this annotation was made on.\n  \"\"\"\n  blobUrl: URI!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The position of this annotation.\n  \"\"\"\n  location: CheckAnnotationSpan!\n\n  \"\"\"\n  The annotation's message.\n  \"\"\"\n  message: String!\n\n  \"\"\"\n  The path that this annotation was made on.\n  \"\"\"\n  path: String!\n\n  \"\"\"\n  Additional information about the annotation.\n  \"\"\"\n  rawDetails: String\n\n  \"\"\"\n  The annotation's title\n  \"\"\"\n  title: String\n}\n\n\"\"\"\nThe connection type for CheckAnnotation.\n\"\"\"\ntype CheckAnnotationConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [CheckAnnotationEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [CheckAnnotation] @preview(toggledBy: \"antiope-preview\")\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nInformation from a check run analysis to specific lines of code.\n\"\"\"\ninput CheckAnnotationData @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  Represents an annotation's information level\n  \"\"\"\n  annotationLevel: CheckAnnotationLevel!\n\n  \"\"\"\n  The location of the annotation\n  \"\"\"\n  location: CheckAnnotationRange!\n\n  \"\"\"\n  A short description of the feedback for these lines of code.\n  \"\"\"\n  message: String!\n\n  \"\"\"\n  The path of the file to add an annotation to.\n  \"\"\"\n  path: String!\n\n  \"\"\"\n  Details about this annotation.\n  \"\"\"\n  rawDetails: String\n\n  \"\"\"\n  The title that represents the annotation.\n  \"\"\"\n  title: String\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype CheckAnnotationEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: CheckAnnotation @preview(toggledBy: \"antiope-preview\")\n}\n\n\"\"\"\nRepresents an annotation's information level.\n\"\"\"\nenum CheckAnnotationLevel @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  An annotation indicating an inescapable error.\n  \"\"\"\n  FAILURE\n\n  \"\"\"\n  An annotation indicating some information.\n  \"\"\"\n  NOTICE\n\n  \"\"\"\n  An annotation indicating an ignorable error.\n  \"\"\"\n  WARNING\n}\n\n\"\"\"\nA character position in a check annotation.\n\"\"\"\ntype CheckAnnotationPosition @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  Column number (1 indexed).\n  \"\"\"\n  column: Int\n\n  \"\"\"\n  Line number (1 indexed).\n  \"\"\"\n  line: Int!\n}\n\n\"\"\"\nInformation from a check run analysis to specific lines of code.\n\"\"\"\ninput CheckAnnotationRange @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The ending column of the range.\n  \"\"\"\n  endColumn: Int\n\n  \"\"\"\n  The ending line of the range.\n  \"\"\"\n  endLine: Int!\n\n  \"\"\"\n  The starting column of the range.\n  \"\"\"\n  startColumn: Int\n\n  \"\"\"\n  The starting line of the range.\n  \"\"\"\n  startLine: Int!\n}\n\n\"\"\"\nAn inclusive pair of positions for a check annotation.\n\"\"\"\ntype CheckAnnotationSpan @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  End position (inclusive).\n  \"\"\"\n  end: CheckAnnotationPosition!\n\n  \"\"\"\n  Start position (inclusive).\n  \"\"\"\n  start: CheckAnnotationPosition!\n}\n\n\"\"\"\nThe possible states for a check suite or run conclusion.\n\"\"\"\nenum CheckConclusionState @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The check suite or run requires action.\n  \"\"\"\n  ACTION_REQUIRED\n\n  \"\"\"\n  The check suite or run has been cancelled.\n  \"\"\"\n  CANCELLED\n\n  \"\"\"\n  The check suite or run has failed.\n  \"\"\"\n  FAILURE\n\n  \"\"\"\n  The check suite or run was neutral.\n  \"\"\"\n  NEUTRAL\n\n  \"\"\"\n  The check suite or run has succeeded.\n  \"\"\"\n  SUCCESS\n\n  \"\"\"\n  The check suite or run has timed out.\n  \"\"\"\n  TIMED_OUT\n}\n\n\"\"\"\nA check run.\n\"\"\"\ntype CheckRun implements Node & UniformResourceLocatable @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The check run's annotations\n  \"\"\"\n  annotations(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): CheckAnnotationConnection\n\n  \"\"\"\n  The check suite that this run is a part of.\n  \"\"\"\n  checkSuite: CheckSuite!\n\n  \"\"\"\n  Identifies the date and time when the check run was completed.\n  \"\"\"\n  completedAt: DateTime\n\n  \"\"\"\n  The conclusion of the check run.\n  \"\"\"\n  conclusion: CheckConclusionState\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The URL from which to find full details of the check run on the integrator's site.\n  \"\"\"\n  detailsUrl: URI\n\n  \"\"\"\n  A reference for the check run on the integrator's system.\n  \"\"\"\n  externalId: String\n  id: ID!\n\n  \"\"\"\n  The name of the check for this check run.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The permalink to the check run summary.\n  \"\"\"\n  permalink: URI!\n\n  \"\"\"\n  The repository associated with this check run.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The HTTP path for this check run.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Identifies the date and time when the check run was started.\n  \"\"\"\n  startedAt: DateTime\n\n  \"\"\"\n  The current status of the check run.\n  \"\"\"\n  status: CheckStatusState!\n\n  \"\"\"\n  A string representing the check run's summary\n  \"\"\"\n  summary: String\n\n  \"\"\"\n  A string representing the check run's text\n  \"\"\"\n  text: String\n\n  \"\"\"\n  A string representing the check run\n  \"\"\"\n  title: String\n\n  \"\"\"\n  The HTTP URL for this check run.\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nPossible further actions the integrator can perform.\n\"\"\"\ninput CheckRunAction @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  A short explanation of what this action would do.\n  \"\"\"\n  description: String!\n\n  \"\"\"\n  A reference for the action on the integrator's system.\n  \"\"\"\n  identifier: String!\n\n  \"\"\"\n  The text to be displayed on a button in the web UI.\n  \"\"\"\n  label: String!\n}\n\n\"\"\"\nThe connection type for CheckRun.\n\"\"\"\ntype CheckRunConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [CheckRunEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [CheckRun] @preview(toggledBy: \"antiope-preview\")\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype CheckRunEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: CheckRun @preview(toggledBy: \"antiope-preview\")\n}\n\n\"\"\"\nThe filters that are available when fetching check runs.\n\"\"\"\ninput CheckRunFilter @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  Filters the check runs created by this application ID.\n  \"\"\"\n  appId: Int\n\n  \"\"\"\n  Filters the check runs by this name.\n  \"\"\"\n  checkName: String\n\n  \"\"\"\n  Filters the check runs by this type.\n  \"\"\"\n  checkType: CheckRunType\n\n  \"\"\"\n  Filters the check runs by this status.\n  \"\"\"\n  status: CheckStatusState\n}\n\n\"\"\"\nDescriptive details about the check run.\n\"\"\"\ninput CheckRunOutput @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The annotations that are made as part of the check run.\n  \"\"\"\n  annotations: [CheckAnnotationData!]\n\n  \"\"\"\n  Images attached to the check run output displayed in the GitHub pull request UI.\n  \"\"\"\n  images: [CheckRunOutputImage!]\n\n  \"\"\"\n  The summary of the check run (supports Commonmark).\n  \"\"\"\n  summary: String!\n\n  \"\"\"\n  The details of the check run (supports Commonmark).\n  \"\"\"\n  text: String\n\n  \"\"\"\n  A title to provide for this check run.\n  \"\"\"\n  title: String!\n}\n\n\"\"\"\nImages attached to the check run output displayed in the GitHub pull request UI.\n\"\"\"\ninput CheckRunOutputImage @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The alternative text for the image.\n  \"\"\"\n  alt: String!\n\n  \"\"\"\n  A short image description.\n  \"\"\"\n  caption: String\n\n  \"\"\"\n  The full URL of the image.\n  \"\"\"\n  imageUrl: URI!\n}\n\n\"\"\"\nThe possible types of check runs.\n\"\"\"\nenum CheckRunType @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  Every check run available.\n  \"\"\"\n  ALL\n\n  \"\"\"\n  The latest check run.\n  \"\"\"\n  LATEST\n}\n\n\"\"\"\nThe possible states for a check suite or run status.\n\"\"\"\nenum CheckStatusState @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The check suite or run has been completed.\n  \"\"\"\n  COMPLETED\n\n  \"\"\"\n  The check suite or run is in progress.\n  \"\"\"\n  IN_PROGRESS\n\n  \"\"\"\n  The check suite or run has been queued.\n  \"\"\"\n  QUEUED\n\n  \"\"\"\n  The check suite or run has been requested.\n  \"\"\"\n  REQUESTED\n}\n\n\"\"\"\nA check suite.\n\"\"\"\ntype CheckSuite implements Node @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The GitHub App which created this check suite.\n  \"\"\"\n  app: App\n\n  \"\"\"\n  The name of the branch for this check suite.\n  \"\"\"\n  branch: Ref\n\n  \"\"\"\n  The check runs associated with a check suite.\n  \"\"\"\n  checkRuns(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Filters the check runs by this type.\n    \"\"\"\n    filterBy: CheckRunFilter\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): CheckRunConnection\n\n  \"\"\"\n  The commit for this check suite\n  \"\"\"\n  commit: Commit!\n\n  \"\"\"\n  The conclusion of this check suite.\n  \"\"\"\n  conclusion: CheckConclusionState\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  A list of open pull requests matching the check suite.\n  \"\"\"\n  matchingPullRequests(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    The base ref name to filter the pull requests by.\n    \"\"\"\n    baseRefName: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    The head ref name to filter the pull requests by.\n    \"\"\"\n    headRefName: String\n\n    \"\"\"\n    A list of label names to filter the pull requests by.\n    \"\"\"\n    labels: [String!]\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for pull requests returned from the connection.\n    \"\"\"\n    orderBy: IssueOrder\n\n    \"\"\"\n    A list of states to filter the pull requests by.\n    \"\"\"\n    states: [PullRequestState!]\n  ): PullRequestConnection\n\n  \"\"\"\n  The push that triggered this check suite.\n  \"\"\"\n  push: Push\n\n  \"\"\"\n  The repository associated with this check suite.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The status of this check suite.\n  \"\"\"\n  status: CheckStatusState!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n}\n\n\"\"\"\nThe auto-trigger preferences that are available for check suites.\n\"\"\"\ninput CheckSuiteAutoTriggerPreference @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The node ID of the application that owns the check suite.\n  \"\"\"\n  appId: ID!\n\n  \"\"\"\n  Set to `true` to enable automatic creation of CheckSuite events upon pushes to the repository.\n  \"\"\"\n  setting: Boolean!\n}\n\n\"\"\"\nThe connection type for CheckSuite.\n\"\"\"\ntype CheckSuiteConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [CheckSuiteEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [CheckSuite] @preview(toggledBy: \"antiope-preview\")\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype CheckSuiteEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: CheckSuite @preview(toggledBy: \"antiope-preview\")\n}\n\n\"\"\"\nThe filters that are available when fetching check suites.\n\"\"\"\ninput CheckSuiteFilter @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  Filters the check suites created by this application ID.\n  \"\"\"\n  appId: Int\n\n  \"\"\"\n  Filters the check suites by this name.\n  \"\"\"\n  checkName: String\n}\n\n\"\"\"\nAutogenerated input type of ClearLabelsFromLabelable\n\"\"\"\ninput ClearLabelsFromLabelableInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The id of the labelable object to clear the labels from.\n  \"\"\"\n  labelableId: ID! @possibleTypes(concreteTypes: [\"Issue\", \"PullRequest\"], abstractType: \"Labelable\")\n}\n\n\"\"\"\nAutogenerated return type of ClearLabelsFromLabelable\n\"\"\"\ntype ClearLabelsFromLabelablePayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The item that was unlabeled.\n  \"\"\"\n  labelable: Labelable\n}\n\n\"\"\"\nAn object that can be closed\n\"\"\"\ninterface Closable {\n  \"\"\"\n  `true` if the object is closed (definition of closed may depend on type)\n  \"\"\"\n  closed: Boolean!\n\n  \"\"\"\n  Identifies the date and time when the object was closed.\n  \"\"\"\n  closedAt: DateTime\n}\n\n\"\"\"\nAutogenerated input type of CloseIssue\n\"\"\"\ninput CloseIssueInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  ID of the issue to be closed.\n  \"\"\"\n  issueId: ID! @possibleTypes(concreteTypes: [\"Issue\"])\n}\n\n\"\"\"\nAutogenerated return type of CloseIssue\n\"\"\"\ntype CloseIssuePayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The issue that was closed.\n  \"\"\"\n  issue: Issue\n}\n\n\"\"\"\nAutogenerated input type of ClosePullRequest\n\"\"\"\ninput ClosePullRequestInput @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  ID of the pull request to be closed.\n  \"\"\"\n  pullRequestId: ID! @possibleTypes(concreteTypes: [\"PullRequest\"])\n}\n\n\"\"\"\nAutogenerated return type of ClosePullRequest\n\"\"\"\ntype ClosePullRequestPayload @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The pull request that was closed.\n  \"\"\"\n  pullRequest: PullRequest\n}\n\n\"\"\"\nRepresents a 'closed' event on any `Closable`.\n\"\"\"\ntype ClosedEvent implements Node & UniformResourceLocatable {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Object that was closed.\n  \"\"\"\n  closable: Closable!\n\n  \"\"\"\n  Object which triggered the creation of this event.\n  \"\"\"\n  closer: Closer\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  The HTTP path for this closed event.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this closed event.\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nThe object which triggered a `ClosedEvent`.\n\"\"\"\nunion Closer = Commit | PullRequest\n\n\"\"\"\nThe Code of Conduct for a repository\n\"\"\"\ntype CodeOfConduct implements Node {\n  \"\"\"\n  The body of the Code of Conduct\n  \"\"\"\n  body: String\n  id: ID!\n\n  \"\"\"\n  The key for the Code of Conduct\n  \"\"\"\n  key: String!\n\n  \"\"\"\n  The formal name of the Code of Conduct\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The HTTP path for this Code of Conduct\n  \"\"\"\n  resourcePath: URI\n\n  \"\"\"\n  The HTTP URL for this Code of Conduct\n  \"\"\"\n  url: URI\n}\n\n\"\"\"\nCollaborators affiliation level with a subject.\n\"\"\"\nenum CollaboratorAffiliation {\n  \"\"\"\n  All collaborators the authenticated user can see.\n  \"\"\"\n  ALL\n\n  \"\"\"\n  All collaborators with permissions to an organization-owned subject, regardless of organization membership status.\n  \"\"\"\n  DIRECT\n\n  \"\"\"\n  All outside collaborators of an organization-owned subject.\n  \"\"\"\n  OUTSIDE\n}\n\n\"\"\"\nTypes that can be inside Collection Items.\n\"\"\"\nunion CollectionItemContent = Organization | Repository | User\n\n\"\"\"\nRepresents a comment.\n\"\"\"\ninterface Comment {\n  \"\"\"\n  The actor who authored the comment.\n  \"\"\"\n  author: Actor\n\n  \"\"\"\n  Author's association with the subject of the comment.\n  \"\"\"\n  authorAssociation: CommentAuthorAssociation!\n\n  \"\"\"\n  The body as Markdown.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  The body rendered to HTML.\n  \"\"\"\n  bodyHTML: HTML!\n\n  \"\"\"\n  The body rendered to text.\n  \"\"\"\n  bodyText: String!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Check if this comment was created via an email reply.\n  \"\"\"\n  createdViaEmail: Boolean!\n\n  \"\"\"\n  The actor who edited the comment.\n  \"\"\"\n  editor: Actor\n  id: ID!\n\n  \"\"\"\n  Check if this comment was edited and includes an edit with the creation data\n  \"\"\"\n  includesCreatedEdit: Boolean!\n\n  \"\"\"\n  The moment the editor made the last edit\n  \"\"\"\n  lastEditedAt: DateTime\n\n  \"\"\"\n  Identifies when the comment was published at.\n  \"\"\"\n  publishedAt: DateTime\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  A list of edits to this content.\n  \"\"\"\n  userContentEdits(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserContentEditConnection\n\n  \"\"\"\n  Did the viewer author this comment.\n  \"\"\"\n  viewerDidAuthor: Boolean!\n}\n\n\"\"\"\nA comment author association with repository.\n\"\"\"\nenum CommentAuthorAssociation {\n  \"\"\"\n  Author has been invited to collaborate on the repository.\n  \"\"\"\n  COLLABORATOR\n\n  \"\"\"\n  Author has previously committed to the repository.\n  \"\"\"\n  CONTRIBUTOR\n\n  \"\"\"\n  Author has not previously committed to GitHub.\n  \"\"\"\n  FIRST_TIMER\n\n  \"\"\"\n  Author has not previously committed to the repository.\n  \"\"\"\n  FIRST_TIME_CONTRIBUTOR\n\n  \"\"\"\n  Author is a member of the organization that owns the repository.\n  \"\"\"\n  MEMBER\n\n  \"\"\"\n  Author has no association with the repository.\n  \"\"\"\n  NONE\n\n  \"\"\"\n  Author is the owner of the repository.\n  \"\"\"\n  OWNER\n}\n\n\"\"\"\nThe possible errors that will prevent a user from updating a comment.\n\"\"\"\nenum CommentCannotUpdateReason {\n  \"\"\"\n  You cannot update this comment\n  \"\"\"\n  DENIED\n\n  \"\"\"\n  You must be the author or have write access to this repository to update this comment.\n  \"\"\"\n  INSUFFICIENT_ACCESS\n\n  \"\"\"\n  Unable to create comment because issue is locked.\n  \"\"\"\n  LOCKED\n\n  \"\"\"\n  You must be logged in to update this comment.\n  \"\"\"\n  LOGIN_REQUIRED\n\n  \"\"\"\n  Repository is under maintenance.\n  \"\"\"\n  MAINTENANCE\n\n  \"\"\"\n  At least one email address must be verified to update this comment.\n  \"\"\"\n  VERIFIED_EMAIL_REQUIRED\n}\n\n\"\"\"\nRepresents a 'comment_deleted' event on a given issue or pull request.\n\"\"\"\ntype CommentDeletedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n}\n\n\"\"\"\nRepresents a Git commit.\n\"\"\"\ntype Commit implements GitObject & Node & Subscribable & UniformResourceLocatable {\n  \"\"\"\n  An abbreviated version of the Git object ID\n  \"\"\"\n  abbreviatedOid: String!\n\n  \"\"\"\n  The number of additions in this commit.\n  \"\"\"\n  additions: Int!\n\n  \"\"\"\n  Authorship details of the commit.\n  \"\"\"\n  author: GitActor\n\n  \"\"\"\n  Check if the committer and the author match.\n  \"\"\"\n  authoredByCommitter: Boolean!\n\n  \"\"\"\n  The datetime when this commit was authored.\n  \"\"\"\n  authoredDate: DateTime!\n\n  \"\"\"\n  Fetches `git blame` information.\n  \"\"\"\n  blame(\n    \"\"\"\n    The file whose Git blame information you want.\n    \"\"\"\n    path: String!\n  ): Blame!\n\n  \"\"\"\n  The number of changed files in this commit.\n  \"\"\"\n  changedFiles: Int!\n\n  \"\"\"\n  The check suites associated with a commit.\n  \"\"\"\n  checkSuites(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Filters the check suites by this type.\n    \"\"\"\n    filterBy: CheckSuiteFilter\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): CheckSuiteConnection @preview(toggledBy: \"antiope-preview\")\n\n  \"\"\"\n  Comments made on the commit.\n  \"\"\"\n  comments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): CommitCommentConnection!\n\n  \"\"\"\n  The HTTP path for this Git object\n  \"\"\"\n  commitResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this Git object\n  \"\"\"\n  commitUrl: URI!\n\n  \"\"\"\n  The datetime when this commit was committed.\n  \"\"\"\n  committedDate: DateTime!\n\n  \"\"\"\n  Check if commited via GitHub web UI.\n  \"\"\"\n  committedViaWeb: Boolean!\n\n  \"\"\"\n  Committership details of the commit.\n  \"\"\"\n  committer: GitActor\n\n  \"\"\"\n  The number of deletions in this commit.\n  \"\"\"\n  deletions: Int!\n\n  \"\"\"\n  The deployments associated with a commit.\n  \"\"\"\n  deployments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Environments to list deployments for\n    \"\"\"\n    environments: [String!]\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for deployments returned from the connection.\n    \"\"\"\n    orderBy: DeploymentOrder = {field: CREATED_AT, direction: ASC}\n  ): DeploymentConnection\n\n  \"\"\"\n  The linear commit history starting from (and including) this commit, in the same order as `git log`.\n  \"\"\"\n  history(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    If non-null, filters history to only show commits with matching authorship.\n    \"\"\"\n    author: CommitAuthor\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    If non-null, filters history to only show commits touching files under this path.\n    \"\"\"\n    path: String\n\n    \"\"\"\n    Allows specifying a beginning time or date for fetching commits.\n    \"\"\"\n    since: GitTimestamp\n\n    \"\"\"\n    Allows specifying an ending time or date for fetching commits.\n    \"\"\"\n    until: GitTimestamp\n  ): CommitHistoryConnection!\n  id: ID!\n\n  \"\"\"\n  The Git commit message\n  \"\"\"\n  message: String!\n\n  \"\"\"\n  The Git commit message body\n  \"\"\"\n  messageBody: String!\n\n  \"\"\"\n  The commit message body rendered to HTML.\n  \"\"\"\n  messageBodyHTML: HTML!\n\n  \"\"\"\n  The Git commit message headline\n  \"\"\"\n  messageHeadline: String!\n\n  \"\"\"\n  The commit message headline rendered to HTML.\n  \"\"\"\n  messageHeadlineHTML: HTML!\n\n  \"\"\"\n  The Git object ID\n  \"\"\"\n  oid: GitObjectID!\n\n  \"\"\"\n  The parents of a commit.\n  \"\"\"\n  parents(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): CommitConnection!\n\n  \"\"\"\n  The datetime when this commit was pushed.\n  \"\"\"\n  pushedDate: DateTime\n\n  \"\"\"\n  The Repository this commit belongs to\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The HTTP path for this commit\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Commit signing information, if present.\n  \"\"\"\n  signature: GitSignature\n\n  \"\"\"\n  Status information for this commit\n  \"\"\"\n  status: Status\n\n  \"\"\"\n  Returns a URL to download a tarball archive for a repository.\n  Note: For private repositories, these links are temporary and expire after five minutes.\n  \"\"\"\n  tarballUrl: URI!\n\n  \"\"\"\n  Commit's root Tree\n  \"\"\"\n  tree: Tree!\n\n  \"\"\"\n  The HTTP path for the tree of this commit\n  \"\"\"\n  treeResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for the tree of this commit\n  \"\"\"\n  treeUrl: URI!\n\n  \"\"\"\n  The HTTP URL for this commit\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  Check if the viewer is able to change their subscription status for the repository.\n  \"\"\"\n  viewerCanSubscribe: Boolean!\n\n  \"\"\"\n  Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.\n  \"\"\"\n  viewerSubscription: SubscriptionState\n\n  \"\"\"\n  Returns a URL to download a zipball archive for a repository.\n  Note: For private repositories, these links are temporary and expire after five minutes.\n  \"\"\"\n  zipballUrl: URI!\n}\n\n\"\"\"\nSpecifies an author for filtering Git commits.\n\"\"\"\ninput CommitAuthor {\n  \"\"\"\n  Email addresses to filter by. Commits authored by any of the specified email addresses will be returned.\n  \"\"\"\n  emails: [String!]\n\n  \"\"\"\n  ID of a User to filter by. If non-null, only commits authored by this user\n  will be returned. This field takes precedence over emails.\n  \"\"\"\n  id: ID\n}\n\n\"\"\"\nRepresents a comment on a given Commit.\n\"\"\"\ntype CommitComment implements Comment & Deletable & Minimizable & Node & Reactable & RepositoryNode & Updatable & UpdatableComment {\n  \"\"\"\n  The actor who authored the comment.\n  \"\"\"\n  author: Actor\n\n  \"\"\"\n  Author's association with the subject of the comment.\n  \"\"\"\n  authorAssociation: CommentAuthorAssociation!\n\n  \"\"\"\n  Identifies the comment body.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  Identifies the comment body rendered to HTML.\n  \"\"\"\n  bodyHTML: HTML!\n\n  \"\"\"\n  The body rendered to text.\n  \"\"\"\n  bodyText: String!\n\n  \"\"\"\n  Identifies the commit associated with the comment, if the commit exists.\n  \"\"\"\n  commit: Commit\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Check if this comment was created via an email reply.\n  \"\"\"\n  createdViaEmail: Boolean!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The actor who edited the comment.\n  \"\"\"\n  editor: Actor\n  id: ID!\n\n  \"\"\"\n  Check if this comment was edited and includes an edit with the creation data\n  \"\"\"\n  includesCreatedEdit: Boolean!\n\n  \"\"\"\n  Returns whether or not a comment has been minimized.\n  \"\"\"\n  isMinimized: Boolean!\n\n  \"\"\"\n  The moment the editor made the last edit\n  \"\"\"\n  lastEditedAt: DateTime\n\n  \"\"\"\n  Returns why the comment was minimized.\n  \"\"\"\n  minimizedReason: String\n\n  \"\"\"\n  Identifies the file path associated with the comment.\n  \"\"\"\n  path: String\n\n  \"\"\"\n  Identifies the line position associated with the comment.\n  \"\"\"\n  position: Int\n\n  \"\"\"\n  Identifies when the comment was published at.\n  \"\"\"\n  publishedAt: DateTime\n\n  \"\"\"\n  A list of reactions grouped by content left on the subject.\n  \"\"\"\n  reactionGroups: [ReactionGroup!]\n\n  \"\"\"\n  A list of Reactions left on the Issue.\n  \"\"\"\n  reactions(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Allows filtering Reactions by emoji.\n    \"\"\"\n    content: ReactionContent\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Allows specifying the order in which reactions are returned.\n    \"\"\"\n    orderBy: ReactionOrder\n  ): ReactionConnection!\n\n  \"\"\"\n  The repository associated with this node.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The HTTP path permalink for this commit comment.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL permalink for this commit comment.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  A list of edits to this content.\n  \"\"\"\n  userContentEdits(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserContentEditConnection\n\n  \"\"\"\n  Check if the current viewer can delete this object.\n  \"\"\"\n  viewerCanDelete: Boolean!\n\n  \"\"\"\n  Check if the current viewer can minimize this object.\n  \"\"\"\n  viewerCanMinimize: Boolean!\n\n  \"\"\"\n  Can user react to this subject\n  \"\"\"\n  viewerCanReact: Boolean!\n\n  \"\"\"\n  Check if the current viewer can update this object.\n  \"\"\"\n  viewerCanUpdate: Boolean!\n\n  \"\"\"\n  Reasons why the current viewer can not update this comment.\n  \"\"\"\n  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!\n\n  \"\"\"\n  Did the viewer author this comment.\n  \"\"\"\n  viewerDidAuthor: Boolean!\n}\n\n\"\"\"\nThe connection type for CommitComment.\n\"\"\"\ntype CommitCommentConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [CommitCommentEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [CommitComment]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype CommitCommentEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: CommitComment\n}\n\n\"\"\"\nA thread of comments on a commit.\n\"\"\"\ntype CommitCommentThread implements Node & RepositoryNode {\n  \"\"\"\n  The comments that exist in this thread.\n  \"\"\"\n  comments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): CommitCommentConnection!\n\n  \"\"\"\n  The commit the comments were made on.\n  \"\"\"\n  commit: Commit!\n  id: ID!\n\n  \"\"\"\n  The file the comments were made on.\n  \"\"\"\n  path: String\n\n  \"\"\"\n  The position in the diff for the commit that the comment was made on.\n  \"\"\"\n  position: Int\n\n  \"\"\"\n  The repository associated with this node.\n  \"\"\"\n  repository: Repository!\n}\n\n\"\"\"\nThe connection type for Commit.\n\"\"\"\ntype CommitConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [CommitEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Commit]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype CommitEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Commit\n}\n\n\"\"\"\nThe connection type for Commit.\n\"\"\"\ntype CommitHistoryConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [CommitEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Commit]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nA content attachment\n\"\"\"\ntype ContentAttachment {\n  \"\"\"\n  The body text of the content attachment. This parameter supports markdown.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  The content reference that the content attachment is attached to.\n  \"\"\"\n  contentReference: ContentReference!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int!\n  id: ID!\n\n  \"\"\"\n  The title of the content attachment.\n  \"\"\"\n  title: String!\n}\n\n\"\"\"\nA content reference\n\"\"\"\ntype ContentReference {\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int!\n  id: ID!\n\n  \"\"\"\n  The reference of the content reference.\n  \"\"\"\n  reference: String!\n}\n\n\"\"\"\nRepresents a contribution a user made on GitHub, such as opening an issue.\n\"\"\"\ninterface Contribution {\n  \"\"\"\n  Whether this contribution is associated with a record you do not have access to. For\n  example, your own 'first issue' contribution may have been made on a repository you can no\n  longer access.\n  \"\"\"\n  isRestricted: Boolean!\n\n  \"\"\"\n  When this contribution was made.\n  \"\"\"\n  occurredAt: DateTime!\n\n  \"\"\"\n  The HTTP path for this contribution.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this contribution.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  The user who made this contribution.\n  \"\"\"\n  user: User!\n}\n\n\"\"\"\nA calendar of contributions made on GitHub by a user.\n\"\"\"\ntype ContributionCalendar {\n  \"\"\"\n  A list of hex color codes used in this calendar. The darker the color, the more contributions it represents.\n  \"\"\"\n  colors: [String!]!\n\n  \"\"\"\n  Determine if the color set was chosen because it's currently Halloween.\n  \"\"\"\n  isHalloween: Boolean!\n\n  \"\"\"\n  A list of the months of contributions in this calendar.\n  \"\"\"\n  months: [ContributionCalendarMonth!]!\n\n  \"\"\"\n  The count of total contributions in the calendar.\n  \"\"\"\n  totalContributions: Int!\n\n  \"\"\"\n  A list of the weeks of contributions in this calendar.\n  \"\"\"\n  weeks: [ContributionCalendarWeek!]!\n}\n\n\"\"\"\nRepresents a single day of contributions on GitHub by a user.\n\"\"\"\ntype ContributionCalendarDay {\n  \"\"\"\n  The hex color code that represents how many contributions were made on this day compared to others in the calendar.\n  \"\"\"\n  color: String!\n\n  \"\"\"\n  How many contributions were made by the user on this day.\n  \"\"\"\n  contributionCount: Int!\n\n  \"\"\"\n  The day this square represents.\n  \"\"\"\n  date: Date!\n\n  \"\"\"\n  A number representing which day of the week this square represents, e.g., 1 is Monday.\n  \"\"\"\n  weekday: Int!\n}\n\n\"\"\"\nA month of contributions in a user's contribution graph.\n\"\"\"\ntype ContributionCalendarMonth {\n  \"\"\"\n  The date of the first day of this month.\n  \"\"\"\n  firstDay: Date!\n\n  \"\"\"\n  The name of the month.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  How many weeks started in this month.\n  \"\"\"\n  totalWeeks: Int!\n\n  \"\"\"\n  The year the month occurred in.\n  \"\"\"\n  year: Int!\n}\n\n\"\"\"\nA week of contributions in a user's contribution graph.\n\"\"\"\ntype ContributionCalendarWeek {\n  \"\"\"\n  The days of contributions in this week.\n  \"\"\"\n  contributionDays: [ContributionCalendarDay!]!\n\n  \"\"\"\n  The date of the earliest square in this week.\n  \"\"\"\n  firstDay: Date!\n}\n\n\"\"\"\nA contributions collection aggregates contributions such as opened issues and commits created by a user.\n\"\"\"\ntype ContributionsCollection {\n  \"\"\"\n  A calendar of this user's contributions on GitHub.\n  \"\"\"\n  contributionCalendar: ContributionCalendar!\n\n  \"\"\"\n  Determine if this collection's time span ends in the current month.\n  \"\"\"\n  doesEndInCurrentMonth: Boolean!\n\n  \"\"\"\n  The date of the first restricted contribution the user made in this time\n  period. Can only be non-null when the user has enabled private contribution counts.\n  \"\"\"\n  earliestRestrictedContributionDate: Date\n\n  \"\"\"\n  The ending date and time of this collection.\n  \"\"\"\n  endedAt: DateTime!\n\n  \"\"\"\n  The first issue the user opened on GitHub. This will be null if that issue was\n  opened outside the collection's time range and ignoreTimeRange is false. If\n  the issue is not visible but the user has opted to show private contributions,\n  a RestrictedContribution will be returned.\n  \"\"\"\n  firstIssueContribution(\n    \"\"\"\n    If true, the first issue will be returned even if it was opened outside of the collection's time range.\n    \"\"\"\n    ignoreTimeRange: Boolean = false\n  ): CreatedIssueOrRestrictedContribution\n\n  \"\"\"\n  The first pull request the user opened on GitHub. This will be null if that\n  pull request was opened outside the collection's time range and\n  ignoreTimeRange is not true. If the pull request is not visible but the user\n  has opted to show private contributions, a RestrictedContribution will be returned.\n  \"\"\"\n  firstPullRequestContribution(\n    \"\"\"\n    If true, the first pull request will be returned even if it was opened outside of the collection's time range.\n    \"\"\"\n    ignoreTimeRange: Boolean = false\n  ): CreatedPullRequestOrRestrictedContribution\n\n  \"\"\"\n  Does the user have any more activity in the timeline that occurred prior to the collection's time range?\n  \"\"\"\n  hasActivityInThePast: Boolean!\n\n  \"\"\"\n  Determine if there are any contributions in this collection.\n  \"\"\"\n  hasAnyContributions: Boolean!\n\n  \"\"\"\n  Determine if the user made any contributions in this time frame whose details\n  are not visible because they were made in a private repository. Can only be\n  true if the user enabled private contribution counts.\n  \"\"\"\n  hasAnyRestrictedContributions: Boolean!\n\n  \"\"\"\n  Whether or not the collector's time span is all within the same day.\n  \"\"\"\n  isSingleDay: Boolean!\n\n  \"\"\"\n  A list of issues the user opened.\n  \"\"\"\n  issueContributions(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Should the user's first issue ever be excluded from the result.\n    \"\"\"\n    excludeFirst: Boolean = false\n\n    \"\"\"\n    Should the user's most commented issue be excluded from the result.\n    \"\"\"\n    excludePopular: Boolean = false\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): CreatedIssueContributionConnection!\n\n  \"\"\"\n  When the user signed up for GitHub. This will be null if that sign up date\n  falls outside the collection's time range and ignoreTimeRange is false.\n  \"\"\"\n  joinedGitHubContribution(\n    \"\"\"\n    If true, the contribution will be returned even if the user signed up outside of the collection's time range.\n    \"\"\"\n    ignoreTimeRange: Boolean = false\n  ): JoinedGitHubContribution\n\n  \"\"\"\n  The date of the most recent restricted contribution the user made in this time\n  period. Can only be non-null when the user has enabled private contribution counts.\n  \"\"\"\n  latestRestrictedContributionDate: Date\n\n  \"\"\"\n  When this collection's time range does not include any activity from the user, use this\n  to get a different collection from an earlier time range that does have activity.\n  \"\"\"\n  mostRecentCollectionWithActivity: ContributionsCollection\n\n  \"\"\"\n  Returns a different contributions collection from an earlier time range than this one\n  that does not have any contributions.\n  \"\"\"\n  mostRecentCollectionWithoutActivity: ContributionsCollection\n\n  \"\"\"\n  The issue the user opened on GitHub that received the most comments in the specified\n  time frame.\n  \"\"\"\n  popularIssueContribution: CreatedIssueContribution\n\n  \"\"\"\n  The pull request the user opened on GitHub that received the most comments in the\n  specified time frame.\n  \"\"\"\n  popularPullRequestContribution: CreatedPullRequestContribution\n\n  \"\"\"\n  A count of contributions made by the user that the viewer cannot access. Only\n  non-zero when the user has chosen to share their private contribution counts.\n  \"\"\"\n  restrictedContributionsCount: Int!\n\n  \"\"\"\n  The beginning date and time of this collection.\n  \"\"\"\n  startedAt: DateTime!\n\n  \"\"\"\n  How many commits were made by the user in this time span.\n  \"\"\"\n  totalCommitContributions: Int!\n\n  \"\"\"\n  How many issues the user opened.\n  \"\"\"\n  totalIssueContributions(\n    \"\"\"\n    Should the user's first issue ever be excluded from this count.\n    \"\"\"\n    excludeFirst: Boolean = false\n\n    \"\"\"\n    Should the user's most commented issue be excluded from this count.\n    \"\"\"\n    excludePopular: Boolean = false\n  ): Int!\n\n  \"\"\"\n  How many pull requests the user opened.\n  \"\"\"\n  totalPullRequestContributions(\n    \"\"\"\n    Should the user's first pull request ever be excluded from this count.\n    \"\"\"\n    excludeFirst: Boolean = false\n\n    \"\"\"\n    Should the user's most commented pull request be excluded from this count.\n    \"\"\"\n    excludePopular: Boolean = false\n  ): Int!\n\n  \"\"\"\n  How many pull request reviews the user left.\n  \"\"\"\n  totalPullRequestReviewContributions: Int!\n\n  \"\"\"\n  How many different repositories the user committed to.\n  \"\"\"\n  totalRepositoriesWithContributedCommits: Int!\n\n  \"\"\"\n  How many different repositories the user opened issues in.\n  \"\"\"\n  totalRepositoriesWithContributedIssues(\n    \"\"\"\n    Should the user's first issue ever be excluded from this count.\n    \"\"\"\n    excludeFirst: Boolean = false\n\n    \"\"\"\n    Should the user's most commented issue be excluded from this count.\n    \"\"\"\n    excludePopular: Boolean = false\n  ): Int!\n\n  \"\"\"\n  How many different repositories the user left pull request reviews in.\n  \"\"\"\n  totalRepositoriesWithContributedPullRequestReviews: Int!\n\n  \"\"\"\n  How many different repositories the user opened pull requests in.\n  \"\"\"\n  totalRepositoriesWithContributedPullRequests(\n    \"\"\"\n    Should the user's first pull request ever be excluded from this count.\n    \"\"\"\n    excludeFirst: Boolean = false\n\n    \"\"\"\n    Should the user's most commented pull request be excluded from this count.\n    \"\"\"\n    excludePopular: Boolean = false\n  ): Int!\n\n  \"\"\"\n  How many repositories the user created.\n  \"\"\"\n  totalRepositoryContributions(\n    \"\"\"\n    Should the user's first repository ever be excluded from this count.\n    \"\"\"\n    excludeFirst: Boolean = false\n  ): Int!\n\n  \"\"\"\n  The user who made the contributions in this collection.\n  \"\"\"\n  user: User!\n}\n\n\"\"\"\nAutogenerated input type of ConvertProjectCardNoteToIssue\n\"\"\"\ninput ConvertProjectCardNoteToIssueInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  The body of the newly created issue.\n  \"\"\"\n  body: String\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ProjectCard ID to convert.\n  \"\"\"\n  projectCardId: ID! @possibleTypes(concreteTypes: [\"ProjectCard\"])\n\n  \"\"\"\n  The ID of the repository to create the issue in.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n\n  \"\"\"\n  The title of the newly created issue. Defaults to the card's note text.\n  \"\"\"\n  title: String\n}\n\n\"\"\"\nAutogenerated return type of ConvertProjectCardNoteToIssue\n\"\"\"\ntype ConvertProjectCardNoteToIssuePayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The updated ProjectCard.\n  \"\"\"\n  projectCard: ProjectCard\n}\n\n\"\"\"\nRepresents a 'converted_note_to_issue' event on a given issue or pull request.\n\"\"\"\ntype ConvertedNoteToIssueEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  Project referenced by event.\n  \"\"\"\n  project: Project @preview(toggledBy: \"starfox-preview\")\n\n  \"\"\"\n  Project card referenced by this project event.\n  \"\"\"\n  projectCard: ProjectCard @preview(toggledBy: \"starfox-preview\")\n\n  \"\"\"\n  Column name referenced by this project event.\n  \"\"\"\n  projectColumnName: String! @preview(toggledBy: \"starfox-preview\")\n}\n\n\"\"\"\nAutogenerated input type of CreateBranchProtectionRule\n\"\"\"\ninput CreateBranchProtectionRuleInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  Will new commits pushed to matching branches dismiss pull request review approvals.\n  \"\"\"\n  dismissesStaleReviews: Boolean\n\n  \"\"\"\n  Can admins overwrite branch protection.\n  \"\"\"\n  isAdminEnforced: Boolean\n\n  \"\"\"\n  The glob-like pattern used to determine matching branches.\n  \"\"\"\n  pattern: String!\n\n  \"\"\"\n  A list of User or Team IDs allowed to push to matching branches.\n  \"\"\"\n  pushActorIds: [ID!]\n\n  \"\"\"\n  The global relay id of the repository in which a new branch protection rule should be created in.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n\n  \"\"\"\n  Number of approving reviews required to update matching branches.\n  \"\"\"\n  requiredApprovingReviewCount: Int\n\n  \"\"\"\n  List of required status check contexts that must pass for commits to be accepted to matching branches.\n  \"\"\"\n  requiredStatusCheckContexts: [String!]\n\n  \"\"\"\n  Are approving reviews required to update matching branches.\n  \"\"\"\n  requiresApprovingReviews: Boolean\n\n  \"\"\"\n  Are reviews from code owners required to update matching branches.\n  \"\"\"\n  requiresCodeOwnerReviews: Boolean\n\n  \"\"\"\n  Are commits required to be signed.\n  \"\"\"\n  requiresCommitSignatures: Boolean\n\n  \"\"\"\n  Are status checks required to update matching branches.\n  \"\"\"\n  requiresStatusChecks: Boolean\n\n  \"\"\"\n  Are branches required to be up to date before merging.\n  \"\"\"\n  requiresStrictStatusChecks: Boolean\n\n  \"\"\"\n  Is pushing to matching branches restricted.\n  \"\"\"\n  restrictsPushes: Boolean\n\n  \"\"\"\n  Is dismissal of pull request reviews restricted.\n  \"\"\"\n  restrictsReviewDismissals: Boolean\n\n  \"\"\"\n  A list of User or Team IDs allowed to dismiss reviews on pull requests targeting matching branches.\n  \"\"\"\n  reviewDismissalActorIds: [ID!]\n}\n\n\"\"\"\nAutogenerated return type of CreateBranchProtectionRule\n\"\"\"\ntype CreateBranchProtectionRulePayload {\n  \"\"\"\n  The newly created BranchProtectionRule.\n  \"\"\"\n  branchProtectionRule: BranchProtectionRule\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of CreateCheckRun\n\"\"\"\ninput CreateCheckRunInput @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  Possible further actions the integrator can perform, which a user may trigger.\n  \"\"\"\n  actions: [CheckRunAction!]\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The time that the check run finished.\n  \"\"\"\n  completedAt: DateTime\n\n  \"\"\"\n  The final conclusion of the check.\n  \"\"\"\n  conclusion: CheckConclusionState\n\n  \"\"\"\n  The URL of the integrator's site that has the full details of the check.\n  \"\"\"\n  detailsUrl: URI\n\n  \"\"\"\n  A reference for the run on the integrator's system.\n  \"\"\"\n  externalId: String\n\n  \"\"\"\n  The SHA of the head commit.\n  \"\"\"\n  headSha: GitObjectID!\n\n  \"\"\"\n  The name of the check.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  Descriptive details about the run.\n  \"\"\"\n  output: CheckRunOutput\n\n  \"\"\"\n  The node ID of the repository.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n\n  \"\"\"\n  The time that the check run began.\n  \"\"\"\n  startedAt: DateTime\n\n  \"\"\"\n  The current status.\n  \"\"\"\n  status: RequestableCheckStatusState\n}\n\n\"\"\"\nAutogenerated return type of CreateCheckRun\n\"\"\"\ntype CreateCheckRunPayload @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The newly created check run.\n  \"\"\"\n  checkRun: CheckRun\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of CreateCheckSuite\n\"\"\"\ninput CreateCheckSuiteInput @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The SHA of the head commit.\n  \"\"\"\n  headSha: GitObjectID!\n\n  \"\"\"\n  The Node ID of the repository.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n}\n\n\"\"\"\nAutogenerated return type of CreateCheckSuite\n\"\"\"\ntype CreateCheckSuitePayload @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The newly created check suite.\n  \"\"\"\n  checkSuite: CheckSuite\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of CreateContentAttachment\n\"\"\"\ninput CreateContentAttachmentInput {\n  \"\"\"\n  The body of the content attachment, which may contain markdown.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The node ID of the content_reference.\n  \"\"\"\n  contentReferenceId: ID! @possibleTypes(concreteTypes: [\"ContentReference\"])\n\n  \"\"\"\n  The title of the content attachment.\n  \"\"\"\n  title: String!\n}\n\n\"\"\"\nAutogenerated return type of CreateContentAttachment\n\"\"\"\ntype CreateContentAttachmentPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The newly created content attachment.\n  \"\"\"\n  contentAttachment: ContentAttachment\n}\n\n\"\"\"\nAutogenerated input type of CreateDeployment\n\"\"\"\ninput CreateDeploymentInput @preview(toggledBy: \"flash-preview\") {\n  \"\"\"\n  Attempt to automatically merge the default branch into the requested ref, defaults to true.\n  \"\"\"\n  autoMerge: Boolean = true\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  Short description of the deployment.\n  \"\"\"\n  description: String = \"\"\n\n  \"\"\"\n  Name for the target deployment environment.\n  \"\"\"\n  environment: String = \"production\"\n\n  \"\"\"\n  JSON payload with extra information about the deployment.\n  \"\"\"\n  payload: String = \"{}\"\n\n  \"\"\"\n  The node ID of the ref to be deployed.\n  \"\"\"\n  refId: ID! @possibleTypes(concreteTypes: [\"Ref\"])\n\n  \"\"\"\n  The node ID of the repository.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n\n  \"\"\"\n  The status contexts to verify against commit status checks. To bypass required\n  contexts, pass an empty array. Defaults to all unique contexts.\n  \"\"\"\n  requiredContexts: [String!]\n\n  \"\"\"\n  Specifies a task to execute.\n  \"\"\"\n  task: String = \"deploy\"\n}\n\n\"\"\"\nAutogenerated return type of CreateDeployment\n\"\"\"\ntype CreateDeploymentPayload @preview(toggledBy: \"flash-preview\") {\n  \"\"\"\n  True if the default branch has been auto-merged into the deployment ref.\n  \"\"\"\n  autoMerged: Boolean\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The new deployment.\n  \"\"\"\n  deployment: Deployment\n}\n\n\"\"\"\nAutogenerated input type of CreateDeploymentStatus\n\"\"\"\ninput CreateDeploymentStatusInput @preview(toggledBy: \"flash-preview\") {\n  \"\"\"\n  Adds a new inactive status to all non-transient, non-production environment\n  deployments with the same repository and environment name as the created\n  status's deployment.\n  \"\"\"\n  autoInactive: Boolean = true\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The node ID of the deployment.\n  \"\"\"\n  deploymentId: ID! @possibleTypes(concreteTypes: [\"Deployment\"])\n\n  \"\"\"\n  A short description of the status. Maximum length of 140 characters.\n  \"\"\"\n  description: String = \"\"\n\n  \"\"\"\n  If provided, updates the environment of the deploy. Otherwise, does not modify the environment.\n  \"\"\"\n  environment: String\n\n  \"\"\"\n  Sets the URL for accessing your environment.\n  \"\"\"\n  environmentUrl: String = \"\"\n\n  \"\"\"\n  The log URL to associate with this status.       This URL should contain\n  output to keep the user updated while the task is running       or serve as\n  historical information for what happened in the deployment.\n  \"\"\"\n  logUrl: String = \"\"\n\n  \"\"\"\n  The state of the deployment.\n  \"\"\"\n  state: DeploymentStatusState!\n}\n\n\"\"\"\nAutogenerated return type of CreateDeploymentStatus\n\"\"\"\ntype CreateDeploymentStatusPayload @preview(toggledBy: \"flash-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The new deployment status.\n  \"\"\"\n  deploymentStatus: DeploymentStatus\n}\n\n\"\"\"\nAutogenerated input type of CreateIssue\n\"\"\"\ninput CreateIssueInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  The Node ID for the user assignee for this issue.\n  \"\"\"\n  assigneeIds: [ID!] @possibleTypes(concreteTypes: [\"User\"])\n\n  \"\"\"\n  The body for the issue description.\n  \"\"\"\n  body: String\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  An array of Node IDs of labels for this issue.\n  \"\"\"\n  labelIds: [ID!] @possibleTypes(concreteTypes: [\"Label\"])\n\n  \"\"\"\n  The Node ID of the milestone for this issue.\n  \"\"\"\n  milestoneId: ID @possibleTypes(concreteTypes: [\"Milestone\"])\n\n  \"\"\"\n  An array of Node IDs for projects associated with this issue.\n  \"\"\"\n  projectIds: [ID!] @possibleTypes(concreteTypes: [\"Project\"])\n\n  \"\"\"\n  The Node ID of the repository.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n\n  \"\"\"\n  The title for the issue.\n  \"\"\"\n  title: String!\n}\n\n\"\"\"\nAutogenerated return type of CreateIssue\n\"\"\"\ntype CreateIssuePayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The new issue.\n  \"\"\"\n  issue: Issue\n}\n\n\"\"\"\nAutogenerated input type of CreateProject\n\"\"\"\ninput CreateProjectInput {\n  \"\"\"\n  The description of project.\n  \"\"\"\n  body: String\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The name of project.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The owner ID to create the project under.\n  \"\"\"\n  ownerId: ID!\n}\n\n\"\"\"\nAutogenerated return type of CreateProject\n\"\"\"\ntype CreateProjectPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The new project.\n  \"\"\"\n  project: Project\n}\n\n\"\"\"\nAutogenerated input type of CreatePullRequest\n\"\"\"\ninput CreatePullRequestInput @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  The name of the branch you want your changes pulled into. This should be an existing branch\n  on the current repository. You cannot update the base branch on a pull request to point\n  to another repository.\n  \"\"\"\n  baseRefName: String!\n\n  \"\"\"\n  The contents of the pull request.\n  \"\"\"\n  body: String\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The name of the branch where your changes are implemented. For cross-repository pull requests\n  in the same network, namespace `head_ref_name` with a user like this: `username:branch`.\n  \"\"\"\n  headRefName: String!\n\n  \"\"\"\n  Indicates whether maintainers can modify the pull request.\n  \"\"\"\n  maintainerCanModify: Boolean = true\n\n  \"\"\"\n  The Node ID of the repository.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n\n  \"\"\"\n  The title of the pull request.\n  \"\"\"\n  title: String!\n}\n\n\"\"\"\nAutogenerated return type of CreatePullRequest\n\"\"\"\ntype CreatePullRequestPayload @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The new pull request.\n  \"\"\"\n  pullRequest: PullRequest\n}\n\n\"\"\"\nAutogenerated input type of CreateTeamDiscussionComment\n\"\"\"\ninput CreateTeamDiscussionCommentInput @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  The content of the comment.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the discussion to which the comment belongs.\n  \"\"\"\n  discussionId: ID! @possibleTypes(concreteTypes: [\"TeamDiscussion\"])\n}\n\n\"\"\"\nAutogenerated return type of CreateTeamDiscussionComment\n\"\"\"\ntype CreateTeamDiscussionCommentPayload @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The new comment.\n  \"\"\"\n  teamDiscussionComment: TeamDiscussionComment\n}\n\n\"\"\"\nAutogenerated input type of CreateTeamDiscussion\n\"\"\"\ninput CreateTeamDiscussionInput @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  The content of the discussion.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  If true, restricts the visiblity of this discussion to team members and\n  organization admins. If false or not specified, allows any organization member\n  to view this discussion.\n  \"\"\"\n  private: Boolean\n\n  \"\"\"\n  The ID of the team to which the discussion belongs.\n  \"\"\"\n  teamId: ID! @possibleTypes(concreteTypes: [\"Team\"])\n\n  \"\"\"\n  The title of the discussion.\n  \"\"\"\n  title: String!\n}\n\n\"\"\"\nAutogenerated return type of CreateTeamDiscussion\n\"\"\"\ntype CreateTeamDiscussionPayload @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The new discussion.\n  \"\"\"\n  teamDiscussion: TeamDiscussion\n}\n\n\"\"\"\nRepresents the contribution a user made on GitHub by opening an issue.\n\"\"\"\ntype CreatedIssueContribution implements Contribution {\n  \"\"\"\n  Whether this contribution is associated with a record you do not have access to. For\n  example, your own 'first issue' contribution may have been made on a repository you can no\n  longer access.\n  \"\"\"\n  isRestricted: Boolean!\n\n  \"\"\"\n  The issue that was opened.\n  \"\"\"\n  issue: Issue!\n\n  \"\"\"\n  When this contribution was made.\n  \"\"\"\n  occurredAt: DateTime!\n\n  \"\"\"\n  The HTTP path for this contribution.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this contribution.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  The user who made this contribution.\n  \"\"\"\n  user: User!\n}\n\n\"\"\"\nThe connection type for CreatedIssueContribution.\n\"\"\"\ntype CreatedIssueContributionConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [CreatedIssueContributionEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [CreatedIssueContribution]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype CreatedIssueContributionEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: CreatedIssueContribution\n}\n\n\"\"\"\nRepresents either a issue the viewer can access or a restricted contribution.\n\"\"\"\nunion CreatedIssueOrRestrictedContribution = CreatedIssueContribution | RestrictedContribution\n\n\"\"\"\nRepresents the contribution a user made on GitHub by opening a pull request.\n\"\"\"\ntype CreatedPullRequestContribution implements Contribution {\n  \"\"\"\n  Whether this contribution is associated with a record you do not have access to. For\n  example, your own 'first issue' contribution may have been made on a repository you can no\n  longer access.\n  \"\"\"\n  isRestricted: Boolean!\n\n  \"\"\"\n  When this contribution was made.\n  \"\"\"\n  occurredAt: DateTime!\n\n  \"\"\"\n  The pull request that was opened.\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  The HTTP path for this contribution.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this contribution.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  The user who made this contribution.\n  \"\"\"\n  user: User!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype CreatedPullRequestContributionEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: CreatedPullRequestContribution\n}\n\n\"\"\"\nRepresents either a pull request the viewer can access or a restricted contribution.\n\"\"\"\nunion CreatedPullRequestOrRestrictedContribution = CreatedPullRequestContribution | RestrictedContribution\n\n\"\"\"\nRepresents a mention made by one issue or pull request to another.\n\"\"\"\ntype CrossReferencedEvent implements Node & UniformResourceLocatable {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Reference originated in a different repository.\n  \"\"\"\n  isCrossRepository: Boolean!\n\n  \"\"\"\n  Identifies when the reference was made.\n  \"\"\"\n  referencedAt: DateTime!\n\n  \"\"\"\n  The HTTP path for this pull request.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Issue or pull request that made the reference.\n  \"\"\"\n  source: ReferencedSubject!\n\n  \"\"\"\n  Issue or pull request to which the reference was made.\n  \"\"\"\n  target: ReferencedSubject!\n\n  \"\"\"\n  The HTTP URL for this pull request.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  Checks if the target will be closed when the source is merged.\n  \"\"\"\n  willCloseTarget: Boolean!\n}\n\n\"\"\"\nAn ISO-8601 encoded date string.\n\"\"\"\nscalar Date\n\n\"\"\"\nAn ISO-8601 encoded UTC date string.\n\"\"\"\nscalar DateTime\n\n\"\"\"\nAutogenerated input type of DeclineTopicSuggestion\n\"\"\"\ninput DeclineTopicSuggestionInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The name of the suggested topic.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The reason why the suggested topic is declined.\n  \"\"\"\n  reason: TopicSuggestionDeclineReason!\n\n  \"\"\"\n  The Node ID of the repository.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n}\n\n\"\"\"\nAutogenerated return type of DeclineTopicSuggestion\n\"\"\"\ntype DeclineTopicSuggestionPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The declined topic.\n  \"\"\"\n  topic: Topic\n}\n\n\"\"\"\nThe possible default permissions for repositories.\n\"\"\"\nenum DefaultRepositoryPermissionField {\n  \"\"\"\n  Can read, write, and administrate repos by default\n  \"\"\"\n  ADMIN\n\n  \"\"\"\n  No access\n  \"\"\"\n  NONE\n\n  \"\"\"\n  Can read repos by default\n  \"\"\"\n  READ\n\n  \"\"\"\n  Can read and write repos by default\n  \"\"\"\n  WRITE\n}\n\n\"\"\"\nEntities that can be deleted.\n\"\"\"\ninterface Deletable {\n  \"\"\"\n  Check if the current viewer can delete this object.\n  \"\"\"\n  viewerCanDelete: Boolean!\n}\n\n\"\"\"\nAutogenerated input type of DeleteBranchProtectionRule\n\"\"\"\ninput DeleteBranchProtectionRuleInput {\n  \"\"\"\n  The global relay id of the branch protection rule to be deleted.\n  \"\"\"\n  branchProtectionRuleId: ID! @possibleTypes(concreteTypes: [\"BranchProtectionRule\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated return type of DeleteBranchProtectionRule\n\"\"\"\ntype DeleteBranchProtectionRulePayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of DeleteIssueComment\n\"\"\"\ninput DeleteIssueCommentInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the comment to delete.\n  \"\"\"\n  id: ID! @possibleTypes(concreteTypes: [\"IssueComment\"])\n}\n\n\"\"\"\nAutogenerated return type of DeleteIssueComment\n\"\"\"\ntype DeleteIssueCommentPayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of DeleteIssue\n\"\"\"\ninput DeleteIssueInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the issue to delete.\n  \"\"\"\n  issueId: ID! @possibleTypes(concreteTypes: [\"Issue\"])\n}\n\n\"\"\"\nAutogenerated return type of DeleteIssue\n\"\"\"\ntype DeleteIssuePayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The repository the issue belonged to\n  \"\"\"\n  repository: Repository\n}\n\n\"\"\"\nAutogenerated input type of DeleteProjectCard\n\"\"\"\ninput DeleteProjectCardInput {\n  \"\"\"\n  The id of the card to delete.\n  \"\"\"\n  cardId: ID! @possibleTypes(concreteTypes: [\"ProjectCard\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated return type of DeleteProjectCard\n\"\"\"\ntype DeleteProjectCardPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The column the deleted card was in.\n  \"\"\"\n  column: ProjectColumn\n\n  \"\"\"\n  The deleted card ID.\n  \"\"\"\n  deletedCardId: ID\n}\n\n\"\"\"\nAutogenerated input type of DeleteProjectColumn\n\"\"\"\ninput DeleteProjectColumnInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The id of the column to delete.\n  \"\"\"\n  columnId: ID! @possibleTypes(concreteTypes: [\"ProjectColumn\"])\n}\n\n\"\"\"\nAutogenerated return type of DeleteProjectColumn\n\"\"\"\ntype DeleteProjectColumnPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The deleted column ID.\n  \"\"\"\n  deletedColumnId: ID\n\n  \"\"\"\n  The project the deleted column was in.\n  \"\"\"\n  project: Project\n}\n\n\"\"\"\nAutogenerated input type of DeleteProject\n\"\"\"\ninput DeleteProjectInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Project ID to update.\n  \"\"\"\n  projectId: ID! @possibleTypes(concreteTypes: [\"Project\"])\n}\n\n\"\"\"\nAutogenerated return type of DeleteProject\n\"\"\"\ntype DeleteProjectPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The repository or organization the project was removed from.\n  \"\"\"\n  owner: ProjectOwner\n}\n\n\"\"\"\nAutogenerated input type of DeletePullRequestReviewComment\n\"\"\"\ninput DeletePullRequestReviewCommentInput @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the comment to delete.\n  \"\"\"\n  id: ID! @possibleTypes(concreteTypes: [\"PullRequestReviewComment\"])\n}\n\n\"\"\"\nAutogenerated return type of DeletePullRequestReviewComment\n\"\"\"\ntype DeletePullRequestReviewCommentPayload @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The pull request review the deleted comment belonged to.\n  \"\"\"\n  pullRequestReview: PullRequestReview\n}\n\n\"\"\"\nAutogenerated input type of DeletePullRequestReview\n\"\"\"\ninput DeletePullRequestReviewInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the pull request review to delete.\n  \"\"\"\n  pullRequestReviewId: ID! @possibleTypes(concreteTypes: [\"PullRequestReview\"])\n}\n\n\"\"\"\nAutogenerated return type of DeletePullRequestReview\n\"\"\"\ntype DeletePullRequestReviewPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The deleted pull request review.\n  \"\"\"\n  pullRequestReview: PullRequestReview\n}\n\n\"\"\"\nAutogenerated input type of DeleteTeamDiscussionComment\n\"\"\"\ninput DeleteTeamDiscussionCommentInput @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the comment to delete.\n  \"\"\"\n  id: ID! @possibleTypes(concreteTypes: [\"TeamDiscussionComment\"])\n}\n\n\"\"\"\nAutogenerated return type of DeleteTeamDiscussionComment\n\"\"\"\ntype DeleteTeamDiscussionCommentPayload @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of DeleteTeamDiscussion\n\"\"\"\ninput DeleteTeamDiscussionInput @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The discussion ID to delete.\n  \"\"\"\n  id: ID! @possibleTypes(concreteTypes: [\"TeamDiscussion\"])\n}\n\n\"\"\"\nAutogenerated return type of DeleteTeamDiscussion\n\"\"\"\ntype DeleteTeamDiscussionPayload @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nRepresents a 'demilestoned' event on a given issue or pull request.\n\"\"\"\ntype DemilestonedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Identifies the milestone title associated with the 'demilestoned' event.\n  \"\"\"\n  milestoneTitle: String!\n\n  \"\"\"\n  Object referenced by event.\n  \"\"\"\n  subject: MilestoneItem!\n}\n\n\"\"\"\nA dependency manifest entry\n\"\"\"\ntype DependencyGraphDependency @preview(toggledBy: \"hawkgirl-preview\") {\n  \"\"\"\n  Does the dependency itself have dependencies?\n  \"\"\"\n  hasDependencies: Boolean!\n\n  \"\"\"\n  The dependency package manager\n  \"\"\"\n  packageManager: String\n\n  \"\"\"\n  The required package name\n  \"\"\"\n  packageName: String!\n\n  \"\"\"\n  The repository containing the package\n  \"\"\"\n  repository: Repository\n\n  \"\"\"\n  The dependency version requirements\n  \"\"\"\n  requirements: String!\n}\n\n\"\"\"\nThe connection type for DependencyGraphDependency.\n\"\"\"\ntype DependencyGraphDependencyConnection @preview(toggledBy: \"hawkgirl-preview\") {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [DependencyGraphDependencyEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [DependencyGraphDependency]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype DependencyGraphDependencyEdge @preview(toggledBy: \"hawkgirl-preview\") {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: DependencyGraphDependency\n}\n\n\"\"\"\nDependency manifest for a repository\n\"\"\"\ntype DependencyGraphManifest implements Node @preview(toggledBy: \"hawkgirl-preview\") {\n  \"\"\"\n  Path to view the manifest file blob\n  \"\"\"\n  blobPath: String!\n\n  \"\"\"\n  A list of manifest dependencies\n  \"\"\"\n  dependencies(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): DependencyGraphDependencyConnection\n\n  \"\"\"\n  The number of dependencies listed in the manifest\n  \"\"\"\n  dependenciesCount: Int\n\n  \"\"\"\n  Is the manifest too big to parse?\n  \"\"\"\n  exceedsMaxSize: Boolean!\n\n  \"\"\"\n  Fully qualified manifest filename\n  \"\"\"\n  filename: String!\n  id: ID!\n\n  \"\"\"\n  Were we able to parse the manifest?\n  \"\"\"\n  parseable: Boolean!\n\n  \"\"\"\n  The repository containing the manifest\n  \"\"\"\n  repository: Repository!\n}\n\n\"\"\"\nThe connection type for DependencyGraphManifest.\n\"\"\"\ntype DependencyGraphManifestConnection @preview(toggledBy: \"hawkgirl-preview\") {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [DependencyGraphManifestEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [DependencyGraphManifest]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype DependencyGraphManifestEdge @preview(toggledBy: \"hawkgirl-preview\") {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: DependencyGraphManifest\n}\n\n\"\"\"\nA repository deploy key.\n\"\"\"\ntype DeployKey implements Node {\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  The deploy key.\n  \"\"\"\n  key: String!\n\n  \"\"\"\n  Whether or not the deploy key is read only.\n  \"\"\"\n  readOnly: Boolean!\n\n  \"\"\"\n  The deploy key title.\n  \"\"\"\n  title: String!\n\n  \"\"\"\n  Whether or not the deploy key has been verified.\n  \"\"\"\n  verified: Boolean!\n}\n\n\"\"\"\nThe connection type for DeployKey.\n\"\"\"\ntype DeployKeyConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [DeployKeyEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [DeployKey]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype DeployKeyEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: DeployKey\n}\n\n\"\"\"\nRepresents a 'deployed' event on a given pull request.\n\"\"\"\ntype DeployedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The deployment associated with the 'deployed' event.\n  \"\"\"\n  deployment: Deployment!\n  id: ID!\n\n  \"\"\"\n  PullRequest referenced by event.\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  The ref associated with the 'deployed' event.\n  \"\"\"\n  ref: Ref\n}\n\n\"\"\"\nRepresents triggered deployment instance.\n\"\"\"\ntype Deployment implements Node {\n  \"\"\"\n  Identifies the commit sha of the deployment.\n  \"\"\"\n  commit: Commit\n\n  \"\"\"\n  Identifies the oid of the deployment commit, even if the commit has been deleted.\n  \"\"\"\n  commitOid: String!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the actor who triggered the deployment.\n  \"\"\"\n  creator: Actor\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The deployment description.\n  \"\"\"\n  description: String\n\n  \"\"\"\n  The environment to which this deployment was made.\n  \"\"\"\n  environment: String\n  id: ID!\n\n  \"\"\"\n  The latest status of this deployment.\n  \"\"\"\n  latestStatus: DeploymentStatus\n\n  \"\"\"\n  Extra information that a deployment system might need.\n  \"\"\"\n  payload: String\n\n  \"\"\"\n  Identifies the Ref of the deployment, if the deployment was created by ref.\n  \"\"\"\n  ref: Ref\n\n  \"\"\"\n  Identifies the repository associated with the deployment.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The current state of the deployment.\n  \"\"\"\n  state: DeploymentState\n\n  \"\"\"\n  A list of statuses associated with the deployment.\n  \"\"\"\n  statuses(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): DeploymentStatusConnection\n\n  \"\"\"\n  The deployment task.\n  \"\"\"\n  task: String\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n}\n\n\"\"\"\nThe connection type for Deployment.\n\"\"\"\ntype DeploymentConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [DeploymentEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Deployment]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype DeploymentEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Deployment\n}\n\n\"\"\"\nRepresents a 'deployment_environment_changed' event on a given pull request.\n\"\"\"\ntype DeploymentEnvironmentChangedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  The deployment status that updated the deployment environment.\n  \"\"\"\n  deploymentStatus: DeploymentStatus!\n  id: ID!\n\n  \"\"\"\n  PullRequest referenced by event.\n  \"\"\"\n  pullRequest: PullRequest!\n}\n\n\"\"\"\nOrdering options for deployment connections\n\"\"\"\ninput DeploymentOrder {\n  \"\"\"\n  The ordering direction.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field to order deployments by.\n  \"\"\"\n  field: DeploymentOrderField!\n}\n\n\"\"\"\nProperties by which deployment connections can be ordered.\n\"\"\"\nenum DeploymentOrderField {\n  \"\"\"\n  Order collection by creation time\n  \"\"\"\n  CREATED_AT\n}\n\n\"\"\"\nThe possible states in which a deployment can be.\n\"\"\"\nenum DeploymentState {\n  \"\"\"\n  The pending deployment was not updated after 30 minutes.\n  \"\"\"\n  ABANDONED\n\n  \"\"\"\n  The deployment is currently active.\n  \"\"\"\n  ACTIVE\n\n  \"\"\"\n  An inactive transient deployment.\n  \"\"\"\n  DESTROYED\n\n  \"\"\"\n  The deployment experienced an error.\n  \"\"\"\n  ERROR\n\n  \"\"\"\n  The deployment has failed.\n  \"\"\"\n  FAILURE\n\n  \"\"\"\n  The deployment is inactive.\n  \"\"\"\n  INACTIVE\n\n  \"\"\"\n  The deployment is in progress.\n  \"\"\"\n  IN_PROGRESS @preview(toggledBy: \"flash-preview\")\n\n  \"\"\"\n  The deployment is pending.\n  \"\"\"\n  PENDING\n\n  \"\"\"\n  The deployment has queued\n  \"\"\"\n  QUEUED @preview(toggledBy: \"flash-preview\")\n}\n\n\"\"\"\nDescribes the status of a given deployment attempt.\n\"\"\"\ntype DeploymentStatus implements Node {\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the actor who triggered the deployment.\n  \"\"\"\n  creator: Actor\n\n  \"\"\"\n  Identifies the deployment associated with status.\n  \"\"\"\n  deployment: Deployment!\n\n  \"\"\"\n  Identifies the description of the deployment.\n  \"\"\"\n  description: String\n\n  \"\"\"\n  Identifies the environment of the deployment at the time of this deployment status\n  \"\"\"\n  environment: String @preview(toggledBy: \"flash-preview\")\n\n  \"\"\"\n  Identifies the environment URL of the deployment.\n  \"\"\"\n  environmentUrl: URI\n  id: ID!\n\n  \"\"\"\n  Identifies the log URL of the deployment.\n  \"\"\"\n  logUrl: URI\n\n  \"\"\"\n  Identifies the current state of the deployment.\n  \"\"\"\n  state: DeploymentStatusState!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n}\n\n\"\"\"\nThe connection type for DeploymentStatus.\n\"\"\"\ntype DeploymentStatusConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [DeploymentStatusEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [DeploymentStatus]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype DeploymentStatusEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: DeploymentStatus\n}\n\n\"\"\"\nThe possible states for a deployment status.\n\"\"\"\nenum DeploymentStatusState {\n  \"\"\"\n  The deployment experienced an error.\n  \"\"\"\n  ERROR\n\n  \"\"\"\n  The deployment has failed.\n  \"\"\"\n  FAILURE\n\n  \"\"\"\n  The deployment is inactive.\n  \"\"\"\n  INACTIVE\n\n  \"\"\"\n  The deployment is in progress.\n  \"\"\"\n  IN_PROGRESS\n\n  \"\"\"\n  The deployment is pending.\n  \"\"\"\n  PENDING\n\n  \"\"\"\n  The deployment is queued\n  \"\"\"\n  QUEUED\n\n  \"\"\"\n  The deployment was successful.\n  \"\"\"\n  SUCCESS\n}\n\n\"\"\"\nAutogenerated input type of DismissPullRequestReview\n\"\"\"\ninput DismissPullRequestReviewInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The contents of the pull request review dismissal message.\n  \"\"\"\n  message: String!\n\n  \"\"\"\n  The Node ID of the pull request review to modify.\n  \"\"\"\n  pullRequestReviewId: ID! @possibleTypes(concreteTypes: [\"PullRequestReview\"])\n}\n\n\"\"\"\nAutogenerated return type of DismissPullRequestReview\n\"\"\"\ntype DismissPullRequestReviewPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The dismissed pull request review.\n  \"\"\"\n  pullRequestReview: PullRequestReview\n}\n\n\"\"\"\nSpecifies a review comment to be left with a Pull Request Review.\n\"\"\"\ninput DraftPullRequestReviewComment {\n  \"\"\"\n  Body of the comment to leave.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  Path to the file being commented on.\n  \"\"\"\n  path: String!\n\n  \"\"\"\n  Position in the file to leave a comment on.\n  \"\"\"\n  position: Int!\n}\n\n\"\"\"\nAn external identity provisioned by SAML SSO or SCIM.\n\"\"\"\ntype ExternalIdentity implements Node {\n  \"\"\"\n  The GUID for this identity\n  \"\"\"\n  guid: String!\n  id: ID!\n\n  \"\"\"\n  Organization invitation for this SCIM-provisioned external identity\n  \"\"\"\n  organizationInvitation: OrganizationInvitation\n\n  \"\"\"\n  SAML Identity attributes\n  \"\"\"\n  samlIdentity: ExternalIdentitySamlAttributes\n\n  \"\"\"\n  SCIM Identity attributes\n  \"\"\"\n  scimIdentity: ExternalIdentityScimAttributes\n\n  \"\"\"\n  User linked to this external identity. Will be NULL if this identity has not been claimed by an organization member.\n  \"\"\"\n  user: User\n}\n\n\"\"\"\nThe connection type for ExternalIdentity.\n\"\"\"\ntype ExternalIdentityConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [ExternalIdentityEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [ExternalIdentity]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype ExternalIdentityEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: ExternalIdentity\n}\n\n\"\"\"\nSAML attributes for the External Identity\n\"\"\"\ntype ExternalIdentitySamlAttributes {\n  \"\"\"\n  The NameID of the SAML identity\n  \"\"\"\n  nameId: String\n}\n\n\"\"\"\nSCIM attributes for the External Identity\n\"\"\"\ntype ExternalIdentityScimAttributes {\n  \"\"\"\n  The userName of the SCIM identity\n  \"\"\"\n  username: String\n}\n\n\"\"\"\nThe connection type for User.\n\"\"\"\ntype FollowerConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [UserEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [User]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nThe connection type for User.\n\"\"\"\ntype FollowingConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [UserEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [User]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nA generic hovercard context with a message and icon\n\"\"\"\ntype GenericHovercardContext implements HovercardContext @preview(toggledBy: \"hagar-preview\") {\n  \"\"\"\n  A string describing this context\n  \"\"\"\n  message: String!\n\n  \"\"\"\n  An octicon to accompany this context\n  \"\"\"\n  octicon: String!\n}\n\n\"\"\"\nA Gist.\n\"\"\"\ntype Gist implements Node & Starrable {\n  \"\"\"\n  A list of comments associated with the gist\n  \"\"\"\n  comments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): GistCommentConnection!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  The gist description.\n  \"\"\"\n  description: String\n  id: ID!\n\n  \"\"\"\n  Whether the gist is public or not.\n  \"\"\"\n  isPublic: Boolean!\n\n  \"\"\"\n  The gist name.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The gist owner.\n  \"\"\"\n  owner: RepositoryOwner\n\n  \"\"\"\n  Identifies when the gist was last pushed to.\n  \"\"\"\n  pushedAt: DateTime\n\n  \"\"\"\n  A list of users who have starred this starrable.\n  \"\"\"\n  stargazers(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Order for connection\n    \"\"\"\n    orderBy: StarOrder\n  ): StargazerConnection!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  Returns a boolean indicating whether the viewing user has starred this starrable.\n  \"\"\"\n  viewerHasStarred: Boolean!\n}\n\n\"\"\"\nRepresents a comment on an Gist.\n\"\"\"\ntype GistComment implements Comment & Deletable & Minimizable & Node & Updatable & UpdatableComment {\n  \"\"\"\n  The actor who authored the comment.\n  \"\"\"\n  author: Actor\n\n  \"\"\"\n  Author's association with the gist.\n  \"\"\"\n  authorAssociation: CommentAuthorAssociation!\n\n  \"\"\"\n  Identifies the comment body.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  The comment body rendered to HTML.\n  \"\"\"\n  bodyHTML: HTML!\n\n  \"\"\"\n  The body rendered to text.\n  \"\"\"\n  bodyText: String!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Check if this comment was created via an email reply.\n  \"\"\"\n  createdViaEmail: Boolean!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The actor who edited the comment.\n  \"\"\"\n  editor: Actor\n\n  \"\"\"\n  The associated gist.\n  \"\"\"\n  gist: Gist!\n  id: ID!\n\n  \"\"\"\n  Check if this comment was edited and includes an edit with the creation data\n  \"\"\"\n  includesCreatedEdit: Boolean!\n\n  \"\"\"\n  Returns whether or not a comment has been minimized.\n  \"\"\"\n  isMinimized: Boolean!\n\n  \"\"\"\n  The moment the editor made the last edit\n  \"\"\"\n  lastEditedAt: DateTime\n\n  \"\"\"\n  Returns why the comment was minimized.\n  \"\"\"\n  minimizedReason: String\n\n  \"\"\"\n  Identifies when the comment was published at.\n  \"\"\"\n  publishedAt: DateTime\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  A list of edits to this content.\n  \"\"\"\n  userContentEdits(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserContentEditConnection\n\n  \"\"\"\n  Check if the current viewer can delete this object.\n  \"\"\"\n  viewerCanDelete: Boolean!\n\n  \"\"\"\n  Check if the current viewer can minimize this object.\n  \"\"\"\n  viewerCanMinimize: Boolean!\n\n  \"\"\"\n  Check if the current viewer can update this object.\n  \"\"\"\n  viewerCanUpdate: Boolean!\n\n  \"\"\"\n  Reasons why the current viewer can not update this comment.\n  \"\"\"\n  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!\n\n  \"\"\"\n  Did the viewer author this comment.\n  \"\"\"\n  viewerDidAuthor: Boolean!\n}\n\n\"\"\"\nThe connection type for GistComment.\n\"\"\"\ntype GistCommentConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [GistCommentEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [GistComment]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype GistCommentEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: GistComment\n}\n\n\"\"\"\nThe connection type for Gist.\n\"\"\"\ntype GistConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [GistEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Gist]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype GistEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Gist\n}\n\n\"\"\"\nOrdering options for gist connections\n\"\"\"\ninput GistOrder {\n  \"\"\"\n  The ordering direction.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field to order repositories by.\n  \"\"\"\n  field: GistOrderField!\n}\n\n\"\"\"\nProperties by which gist connections can be ordered.\n\"\"\"\nenum GistOrderField {\n  \"\"\"\n  Order gists by creation time\n  \"\"\"\n  CREATED_AT\n\n  \"\"\"\n  Order gists by push time\n  \"\"\"\n  PUSHED_AT\n\n  \"\"\"\n  Order gists by update time\n  \"\"\"\n  UPDATED_AT\n}\n\n\"\"\"\nThe privacy of a Gist\n\"\"\"\nenum GistPrivacy {\n  \"\"\"\n  Gists that are public and secret\n  \"\"\"\n  ALL\n\n  \"\"\"\n  Public\n  \"\"\"\n  PUBLIC\n\n  \"\"\"\n  Secret\n  \"\"\"\n  SECRET\n}\n\n\"\"\"\nRepresents an actor in a Git commit (ie. an author or committer).\n\"\"\"\ntype GitActor {\n  \"\"\"\n  A URL pointing to the author's public avatar.\n  \"\"\"\n  avatarUrl(\n    \"\"\"\n    The size of the resulting square image.\n    \"\"\"\n    size: Int\n  ): URI!\n\n  \"\"\"\n  The timestamp of the Git action (authoring or committing).\n  \"\"\"\n  date: GitTimestamp\n\n  \"\"\"\n  The email in the Git commit.\n  \"\"\"\n  email: String\n\n  \"\"\"\n  The name in the Git commit.\n  \"\"\"\n  name: String\n\n  \"\"\"\n  The GitHub user corresponding to the email field. Null if no such user exists.\n  \"\"\"\n  user: User\n}\n\n\"\"\"\nRepresents information about the GitHub instance.\n\"\"\"\ntype GitHubMetadata {\n  \"\"\"\n  Returns a String that's a SHA of `github-services`\n  \"\"\"\n  gitHubServicesSha: GitObjectID!\n\n  \"\"\"\n  IP addresses that users connect to for git operations\n  \"\"\"\n  gitIpAddresses: [String!]\n\n  \"\"\"\n  IP addresses that service hooks are sent from\n  \"\"\"\n  hookIpAddresses: [String!]\n\n  \"\"\"\n  IP addresses that the importer connects from\n  \"\"\"\n  importerIpAddresses: [String!]\n\n  \"\"\"\n  Whether or not users are verified\n  \"\"\"\n  isPasswordAuthenticationVerifiable: Boolean!\n\n  \"\"\"\n  IP addresses for GitHub Pages' A records\n  \"\"\"\n  pagesIpAddresses: [String!]\n}\n\n\"\"\"\nRepresents a Git object.\n\"\"\"\ninterface GitObject {\n  \"\"\"\n  An abbreviated version of the Git object ID\n  \"\"\"\n  abbreviatedOid: String!\n\n  \"\"\"\n  The HTTP path for this Git object\n  \"\"\"\n  commitResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this Git object\n  \"\"\"\n  commitUrl: URI!\n  id: ID!\n\n  \"\"\"\n  The Git object ID\n  \"\"\"\n  oid: GitObjectID!\n\n  \"\"\"\n  The Repository the Git object belongs to\n  \"\"\"\n  repository: Repository!\n}\n\n\"\"\"\nA Git object ID.\n\"\"\"\nscalar GitObjectID\n\n\"\"\"\nGit SSH string\n\"\"\"\nscalar GitSSHRemote\n\n\"\"\"\nInformation about a signature (GPG or S/MIME) on a Commit or Tag.\n\"\"\"\ninterface GitSignature {\n  \"\"\"\n  Email used to sign this object.\n  \"\"\"\n  email: String!\n\n  \"\"\"\n  True if the signature is valid and verified by GitHub.\n  \"\"\"\n  isValid: Boolean!\n\n  \"\"\"\n  Payload for GPG signing object. Raw ODB object without the signature header.\n  \"\"\"\n  payload: String!\n\n  \"\"\"\n  ASCII-armored signature header from object.\n  \"\"\"\n  signature: String!\n\n  \"\"\"\n  GitHub user corresponding to the email signing this commit.\n  \"\"\"\n  signer: User\n\n  \"\"\"\n  The state of this signature. `VALID` if signature is valid and verified by\n  GitHub, otherwise represents reason why signature is considered invalid.\n  \"\"\"\n  state: GitSignatureState!\n\n  \"\"\"\n  True if the signature was made with GitHub's signing key.\n  \"\"\"\n  wasSignedByGitHub: Boolean!\n}\n\n\"\"\"\nThe state of a Git signature.\n\"\"\"\nenum GitSignatureState {\n  \"\"\"\n  The signing certificate or its chain could not be verified\n  \"\"\"\n  BAD_CERT\n\n  \"\"\"\n  Invalid email used for signing\n  \"\"\"\n  BAD_EMAIL\n\n  \"\"\"\n  Signing key expired\n  \"\"\"\n  EXPIRED_KEY\n\n  \"\"\"\n  Internal error - the GPG verification service misbehaved\n  \"\"\"\n  GPGVERIFY_ERROR\n\n  \"\"\"\n  Internal error - the GPG verification service is unavailable at the moment\n  \"\"\"\n  GPGVERIFY_UNAVAILABLE\n\n  \"\"\"\n  Invalid signature\n  \"\"\"\n  INVALID\n\n  \"\"\"\n  Malformed signature\n  \"\"\"\n  MALFORMED_SIG\n\n  \"\"\"\n  The usage flags for the key that signed this don't allow signing\n  \"\"\"\n  NOT_SIGNING_KEY\n\n  \"\"\"\n  Email used for signing not known to GitHub\n  \"\"\"\n  NO_USER\n\n  \"\"\"\n  Valid siganture, though certificate revocation check failed\n  \"\"\"\n  OCSP_ERROR\n\n  \"\"\"\n  Valid signature, pending certificate revocation checking\n  \"\"\"\n  OCSP_PENDING\n\n  \"\"\"\n  One or more certificates in chain has been revoked\n  \"\"\"\n  OCSP_REVOKED\n\n  \"\"\"\n  Key used for signing not known to GitHub\n  \"\"\"\n  UNKNOWN_KEY\n\n  \"\"\"\n  Unknown signature type\n  \"\"\"\n  UNKNOWN_SIG_TYPE\n\n  \"\"\"\n  Unsigned\n  \"\"\"\n  UNSIGNED\n\n  \"\"\"\n  Email used for signing unverified on GitHub\n  \"\"\"\n  UNVERIFIED_EMAIL\n\n  \"\"\"\n  Valid signature and verified by GitHub\n  \"\"\"\n  VALID\n}\n\n\"\"\"\nAn ISO-8601 encoded date string. Unlike the DateTime type, GitTimestamp is not converted in UTC.\n\"\"\"\nscalar GitTimestamp\n\n\"\"\"\nRepresents a GPG signature on a Commit or Tag.\n\"\"\"\ntype GpgSignature implements GitSignature {\n  \"\"\"\n  Email used to sign this object.\n  \"\"\"\n  email: String!\n\n  \"\"\"\n  True if the signature is valid and verified by GitHub.\n  \"\"\"\n  isValid: Boolean!\n\n  \"\"\"\n  Hex-encoded ID of the key that signed this object.\n  \"\"\"\n  keyId: String\n\n  \"\"\"\n  Payload for GPG signing object. Raw ODB object without the signature header.\n  \"\"\"\n  payload: String!\n\n  \"\"\"\n  ASCII-armored signature header from object.\n  \"\"\"\n  signature: String!\n\n  \"\"\"\n  GitHub user corresponding to the email signing this commit.\n  \"\"\"\n  signer: User\n\n  \"\"\"\n  The state of this signature. `VALID` if signature is valid and verified by\n  GitHub, otherwise represents reason why signature is considered invalid.\n  \"\"\"\n  state: GitSignatureState!\n\n  \"\"\"\n  True if the signature was made with GitHub's signing key.\n  \"\"\"\n  wasSignedByGitHub: Boolean!\n}\n\n\"\"\"\nA string containing HTML code.\n\"\"\"\nscalar HTML\n\n\"\"\"\nRepresents a 'head_ref_deleted' event on a given pull request.\n\"\"\"\ntype HeadRefDeletedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the Ref associated with the `head_ref_deleted` event.\n  \"\"\"\n  headRef: Ref\n\n  \"\"\"\n  Identifies the name of the Ref associated with the `head_ref_deleted` event.\n  \"\"\"\n  headRefName: String!\n  id: ID!\n\n  \"\"\"\n  PullRequest referenced by event.\n  \"\"\"\n  pullRequest: PullRequest!\n}\n\n\"\"\"\nRepresents a 'head_ref_force_pushed' event on a given pull request.\n\"\"\"\ntype HeadRefForcePushedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the after commit SHA for the 'head_ref_force_pushed' event.\n  \"\"\"\n  afterCommit: Commit\n\n  \"\"\"\n  Identifies the before commit SHA for the 'head_ref_force_pushed' event.\n  \"\"\"\n  beforeCommit: Commit\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  PullRequest referenced by event.\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  Identifies the fully qualified ref name for the 'head_ref_force_pushed' event.\n  \"\"\"\n  ref: Ref\n}\n\n\"\"\"\nRepresents a 'head_ref_restored' event on a given pull request.\n\"\"\"\ntype HeadRefRestoredEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  PullRequest referenced by event.\n  \"\"\"\n  pullRequest: PullRequest!\n}\n\n\"\"\"\nDetail needed to display a hovercard for a user\n\"\"\"\ntype Hovercard @preview(toggledBy: \"hagar-preview\") {\n  \"\"\"\n  Each of the contexts for this hovercard\n  \"\"\"\n  contexts: [HovercardContext!]!\n}\n\n\"\"\"\nAn individual line of a hovercard\n\"\"\"\ninterface HovercardContext @preview(toggledBy: \"hagar-preview\") {\n  \"\"\"\n  A string describing this context\n  \"\"\"\n  message: String!\n\n  \"\"\"\n  An octicon to accompany this context\n  \"\"\"\n  octicon: String!\n}\n\n\"\"\"\nAutogenerated input type of InviteBusinessAdmin\n\"\"\"\ninput InviteBusinessAdminInput {\n  \"\"\"\n  The ID of the business to which you want to invite an administrator.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The email of the person to invite as an administrator.\n  \"\"\"\n  email: String\n\n  \"\"\"\n  The login of a user to invite as an administrator.\n  \"\"\"\n  invitee: String\n}\n\n\"\"\"\nAutogenerated return type of InviteBusinessAdmin\n\"\"\"\ntype InviteBusinessAdminPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The created business administrator invitation\n  \"\"\"\n  invitation: BusinessMemberInvitation @preview(toggledBy: \"gwenpool-preview\")\n}\n\n\"\"\"\nAutogenerated input type of InviteBusinessBillingManager\n\"\"\"\ninput InviteBusinessBillingManagerInput {\n  \"\"\"\n  The ID of the business to which you want to invite a billing manager.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The email of the person to invite as a billing manager.\n  \"\"\"\n  email: String\n\n  \"\"\"\n  The login of a user to invite as a billing manager.\n  \"\"\"\n  invitee: String\n}\n\n\"\"\"\nAutogenerated return type of InviteBusinessBillingManager\n\"\"\"\ntype InviteBusinessBillingManagerPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The created business billing manager invitation\n  \"\"\"\n  invitation: BusinessMemberInvitation @preview(toggledBy: \"gwenpool-preview\")\n}\n\n\"\"\"\nAn Issue is a place to discuss ideas, enhancements, tasks, and bugs for a project.\n\"\"\"\ntype Issue implements Assignable & Closable & Comment & Labelable & Lockable & Node & Reactable & RepositoryNode & Subscribable & UniformResourceLocatable & Updatable & UpdatableComment {\n  \"\"\"\n  Reason that the conversation was locked.\n  \"\"\"\n  activeLockReason: LockReason\n\n  \"\"\"\n  A list of Users assigned to this object.\n  \"\"\"\n  assignees(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserConnection!\n\n  \"\"\"\n  The actor who authored the comment.\n  \"\"\"\n  author: Actor\n\n  \"\"\"\n  Author's association with the subject of the comment.\n  \"\"\"\n  authorAssociation: CommentAuthorAssociation!\n\n  \"\"\"\n  Identifies the body of the issue.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  Identifies the body of the issue rendered to HTML.\n  \"\"\"\n  bodyHTML: HTML!\n\n  \"\"\"\n  Identifies the body of the issue rendered to text.\n  \"\"\"\n  bodyText: String!\n\n  \"\"\"\n  `true` if the object is closed (definition of closed may depend on type)\n  \"\"\"\n  closed: Boolean!\n\n  \"\"\"\n  Identifies the date and time when the object was closed.\n  \"\"\"\n  closedAt: DateTime\n\n  \"\"\"\n  A list of comments associated with the Issue.\n  \"\"\"\n  comments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): IssueCommentConnection!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Check if this comment was created via an email reply.\n  \"\"\"\n  createdViaEmail: Boolean!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The actor who edited the comment.\n  \"\"\"\n  editor: Actor\n\n  \"\"\"\n  The hovercard information for this issue\n  \"\"\"\n  hovercard(\n    \"\"\"\n    Whether or not to include notification contexts\n    \"\"\"\n    includeNotificationContexts: Boolean = true\n  ): Hovercard! @preview(toggledBy: \"hagar-preview\")\n  id: ID!\n\n  \"\"\"\n  Check if this comment was edited and includes an edit with the creation data\n  \"\"\"\n  includesCreatedEdit: Boolean!\n\n  \"\"\"\n  A list of labels associated with the object.\n  \"\"\"\n  labels(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): LabelConnection\n\n  \"\"\"\n  The moment the editor made the last edit\n  \"\"\"\n  lastEditedAt: DateTime\n\n  \"\"\"\n  `true` if the object is locked\n  \"\"\"\n  locked: Boolean!\n\n  \"\"\"\n  Identifies the milestone associated with the issue.\n  \"\"\"\n  milestone: Milestone\n\n  \"\"\"\n  Identifies the issue number.\n  \"\"\"\n  number: Int!\n\n  \"\"\"\n  A list of Users that are participating in the Issue conversation.\n  \"\"\"\n  participants(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserConnection!\n\n  \"\"\"\n  List of project cards associated with this issue.\n  \"\"\"\n  projectCards(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    A list of archived states to filter the cards by\n    \"\"\"\n    archivedStates: [ProjectCardArchivedState] = [ARCHIVED, NOT_ARCHIVED]\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): ProjectCardConnection!\n\n  \"\"\"\n  Identifies when the comment was published at.\n  \"\"\"\n  publishedAt: DateTime\n\n  \"\"\"\n  A list of reactions grouped by content left on the subject.\n  \"\"\"\n  reactionGroups: [ReactionGroup!]\n\n  \"\"\"\n  A list of Reactions left on the Issue.\n  \"\"\"\n  reactions(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Allows filtering Reactions by emoji.\n    \"\"\"\n    content: ReactionContent\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Allows specifying the order in which reactions are returned.\n    \"\"\"\n    orderBy: ReactionOrder\n  ): ReactionConnection!\n\n  \"\"\"\n  The repository associated with this node.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The HTTP path for this issue\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Identifies the state of the issue.\n  \"\"\"\n  state: IssueState!\n\n  \"\"\"\n  A list of events, comments, commits, etc. associated with the issue.\n  \"\"\"\n  timeline(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Allows filtering timeline events by a `since` timestamp.\n    \"\"\"\n    since: DateTime\n  ): IssueTimelineConnection!\n\n  \"\"\"\n  A list of events, comments, commits, etc. associated with the issue.\n  \"\"\"\n  timelineItems(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Filter timeline items by type.\n    \"\"\"\n    itemTypes: [IssueTimelineItemsItemType!]\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Filter timeline items by a `since` timestamp.\n    \"\"\"\n    since: DateTime\n\n    \"\"\"\n    Skips the first _n_ elements in the list.\n    \"\"\"\n    skip: Int\n  ): IssueTimelineItemsConnection! @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Identifies the issue title.\n  \"\"\"\n  title: String!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this issue\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  A list of edits to this content.\n  \"\"\"\n  userContentEdits(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserContentEditConnection\n\n  \"\"\"\n  Can user react to this subject\n  \"\"\"\n  viewerCanReact: Boolean!\n\n  \"\"\"\n  Check if the viewer is able to change their subscription status for the repository.\n  \"\"\"\n  viewerCanSubscribe: Boolean!\n\n  \"\"\"\n  Check if the current viewer can update this object.\n  \"\"\"\n  viewerCanUpdate: Boolean!\n\n  \"\"\"\n  Reasons why the current viewer can not update this comment.\n  \"\"\"\n  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!\n\n  \"\"\"\n  Did the viewer author this comment.\n  \"\"\"\n  viewerDidAuthor: Boolean!\n\n  \"\"\"\n  Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.\n  \"\"\"\n  viewerSubscription: SubscriptionState\n}\n\n\"\"\"\nRepresents a comment on an Issue.\n\"\"\"\ntype IssueComment implements Comment & Deletable & Minimizable & Node & Reactable & RepositoryNode & Updatable & UpdatableComment {\n  \"\"\"\n  The actor who authored the comment.\n  \"\"\"\n  author: Actor\n\n  \"\"\"\n  Author's association with the subject of the comment.\n  \"\"\"\n  authorAssociation: CommentAuthorAssociation!\n\n  \"\"\"\n  The body as Markdown.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  The body rendered to HTML.\n  \"\"\"\n  bodyHTML: HTML!\n\n  \"\"\"\n  The body rendered to text.\n  \"\"\"\n  bodyText: String!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Check if this comment was created via an email reply.\n  \"\"\"\n  createdViaEmail: Boolean!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The actor who edited the comment.\n  \"\"\"\n  editor: Actor\n  id: ID!\n\n  \"\"\"\n  Check if this comment was edited and includes an edit with the creation data\n  \"\"\"\n  includesCreatedEdit: Boolean!\n\n  \"\"\"\n  Returns whether or not a comment has been minimized.\n  \"\"\"\n  isMinimized: Boolean!\n\n  \"\"\"\n  Identifies the issue associated with the comment.\n  \"\"\"\n  issue: Issue!\n\n  \"\"\"\n  The moment the editor made the last edit\n  \"\"\"\n  lastEditedAt: DateTime\n\n  \"\"\"\n  Returns why the comment was minimized.\n  \"\"\"\n  minimizedReason: String\n\n  \"\"\"\n  Identifies when the comment was published at.\n  \"\"\"\n  publishedAt: DateTime\n\n  \"\"\"\n  Returns the pull request associated with the comment, if this comment was made on a\n  pull request.\n  \"\"\"\n  pullRequest: PullRequest\n\n  \"\"\"\n  A list of reactions grouped by content left on the subject.\n  \"\"\"\n  reactionGroups: [ReactionGroup!]\n\n  \"\"\"\n  A list of Reactions left on the Issue.\n  \"\"\"\n  reactions(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Allows filtering Reactions by emoji.\n    \"\"\"\n    content: ReactionContent\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Allows specifying the order in which reactions are returned.\n    \"\"\"\n    orderBy: ReactionOrder\n  ): ReactionConnection!\n\n  \"\"\"\n  The repository associated with this node.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The HTTP path for this issue comment\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this issue comment\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  A list of edits to this content.\n  \"\"\"\n  userContentEdits(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserContentEditConnection\n\n  \"\"\"\n  Check if the current viewer can delete this object.\n  \"\"\"\n  viewerCanDelete: Boolean!\n\n  \"\"\"\n  Check if the current viewer can minimize this object.\n  \"\"\"\n  viewerCanMinimize: Boolean!\n\n  \"\"\"\n  Can user react to this subject\n  \"\"\"\n  viewerCanReact: Boolean!\n\n  \"\"\"\n  Check if the current viewer can update this object.\n  \"\"\"\n  viewerCanUpdate: Boolean!\n\n  \"\"\"\n  Reasons why the current viewer can not update this comment.\n  \"\"\"\n  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!\n\n  \"\"\"\n  Did the viewer author this comment.\n  \"\"\"\n  viewerDidAuthor: Boolean!\n}\n\n\"\"\"\nThe connection type for IssueComment.\n\"\"\"\ntype IssueCommentConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [IssueCommentEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [IssueComment]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype IssueCommentEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: IssueComment\n}\n\n\"\"\"\nThe connection type for Issue.\n\"\"\"\ntype IssueConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [IssueEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Issue]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype IssueEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Issue\n}\n\n\"\"\"\nWays in which to filter lists of issues.\n\"\"\"\ninput IssueFilters @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  List issues assigned to given name. Pass in `null` for issues with no assigned\n  user, and `*` for issues assigned to any user.\n  \"\"\"\n  assignee: String\n\n  \"\"\"\n  List issues created by given name.\n  \"\"\"\n  createdBy: String\n\n  \"\"\"\n  List issues where the list of label names exist on the issue.\n  \"\"\"\n  labels: [String!]\n\n  \"\"\"\n  List issues where the given name is mentioned in the issue.\n  \"\"\"\n  mentioned: String\n\n  \"\"\"\n  List issues by given milestone argument. If an string representation of an\n  integer is passed, it should refer to a milestone by its number field. Pass in\n  `null` for issues with no milestone, and `*` for issues that are assigned to any milestone.\n  \"\"\"\n  milestone: String\n\n  \"\"\"\n  List issues that have been updated at or after the given date.\n  \"\"\"\n  since: DateTime\n\n  \"\"\"\n  List issues filtered by the list of states given.\n  \"\"\"\n  states: [IssueState!]\n\n  \"\"\"\n  List issues subscribed to by viewer.\n  \"\"\"\n  viewerSubscribed: Boolean = false\n}\n\n\"\"\"\nUsed for return value of Repository.issueOrPullRequest.\n\"\"\"\nunion IssueOrPullRequest = Issue | PullRequest\n\n\"\"\"\nWays in which lists of issues can be ordered upon return.\n\"\"\"\ninput IssueOrder {\n  \"\"\"\n  The direction in which to order issues by the specified field.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field in which to order issues by.\n  \"\"\"\n  field: IssueOrderField!\n}\n\n\"\"\"\nProperties by which issue connections can be ordered.\n\"\"\"\nenum IssueOrderField {\n  \"\"\"\n  Order issues by comment count\n  \"\"\"\n  COMMENTS\n\n  \"\"\"\n  Order issues by creation time\n  \"\"\"\n  CREATED_AT\n\n  \"\"\"\n  Order issues by update time\n  \"\"\"\n  UPDATED_AT\n}\n\n\"\"\"\nThe possible states of an issue.\n\"\"\"\nenum IssueState {\n  \"\"\"\n  An issue that has been closed\n  \"\"\"\n  CLOSED\n\n  \"\"\"\n  An issue that is still open\n  \"\"\"\n  OPEN\n}\n\n\"\"\"\nThe connection type for IssueTimelineItem.\n\"\"\"\ntype IssueTimelineConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [IssueTimelineItemEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [IssueTimelineItem]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn item in an issue timeline\n\"\"\"\nunion IssueTimelineItem = AssignedEvent | ClosedEvent | Commit | CrossReferencedEvent | DemilestonedEvent | IssueComment | LabeledEvent | LockedEvent | MilestonedEvent | ReferencedEvent | RenamedTitleEvent | ReopenedEvent | SubscribedEvent | TransferredEvent | UnassignedEvent | UnlabeledEvent | UnlockedEvent | UnsubscribedEvent\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype IssueTimelineItemEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: IssueTimelineItem\n}\n\n\"\"\"\nAn item in an issue timeline\n\"\"\"\nunion IssueTimelineItems = AddedToProjectEvent | AssignedEvent | ClosedEvent | CommentDeletedEvent | ConvertedNoteToIssueEvent | CrossReferencedEvent | DemilestonedEvent | IssueComment | LabeledEvent | LockedEvent | MentionedEvent | MilestonedEvent | MovedColumnsInProjectEvent | PinnedEvent | ReferencedEvent | RemovedFromProjectEvent | RenamedTitleEvent | ReopenedEvent | SubscribedEvent | TransferredEvent | UnassignedEvent | UnlabeledEvent | UnlockedEvent | UnpinnedEvent | UnsubscribedEvent\n\n\"\"\"\nThe connection type for IssueTimelineItems.\n\"\"\"\ntype IssueTimelineItemsConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [IssueTimelineItemsEdge]\n\n  \"\"\"\n  Identifies the count of items after applying `before` and `after` filters.\n  \"\"\"\n  filteredCount: Int!\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [IssueTimelineItems]\n\n  \"\"\"\n  Identifies the count of items after applying `before`/`after` filters and `first`/`last`/`skip` slicing.\n  \"\"\"\n  pageCount: Int!\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n\n  \"\"\"\n  Identifies the date and time when the timeline was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype IssueTimelineItemsEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: IssueTimelineItems\n}\n\n\"\"\"\nThe possible item types found in a timeline.\n\"\"\"\nenum IssueTimelineItemsItemType {\n  \"\"\"\n  Represents a 'added_to_project' event on a given issue or pull request.\n  \"\"\"\n  ADDED_TO_PROJECT_EVENT\n\n  \"\"\"\n  Represents an 'assigned' event on any assignable object.\n  \"\"\"\n  ASSIGNED_EVENT\n\n  \"\"\"\n  Represents a 'closed' event on any `Closable`.\n  \"\"\"\n  CLOSED_EVENT\n\n  \"\"\"\n  Represents a 'comment_deleted' event on a given issue or pull request.\n  \"\"\"\n  COMMENT_DELETED_EVENT\n\n  \"\"\"\n  Represents a 'converted_note_to_issue' event on a given issue or pull request.\n  \"\"\"\n  CONVERTED_NOTE_TO_ISSUE_EVENT\n\n  \"\"\"\n  Represents a mention made by one issue or pull request to another.\n  \"\"\"\n  CROSS_REFERENCED_EVENT\n\n  \"\"\"\n  Represents a 'demilestoned' event on a given issue or pull request.\n  \"\"\"\n  DEMILESTONED_EVENT\n\n  \"\"\"\n  Represents a comment on an Issue.\n  \"\"\"\n  ISSUE_COMMENT\n\n  \"\"\"\n  Represents a 'labeled' event on a given issue or pull request.\n  \"\"\"\n  LABELED_EVENT\n\n  \"\"\"\n  Represents a 'locked' event on a given issue or pull request.\n  \"\"\"\n  LOCKED_EVENT\n\n  \"\"\"\n  Represents a 'mentioned' event on a given issue or pull request.\n  \"\"\"\n  MENTIONED_EVENT\n\n  \"\"\"\n  Represents a 'milestoned' event on a given issue or pull request.\n  \"\"\"\n  MILESTONED_EVENT\n\n  \"\"\"\n  Represents a 'moved_columns_in_project' event on a given issue or pull request.\n  \"\"\"\n  MOVED_COLUMNS_IN_PROJECT_EVENT\n\n  \"\"\"\n  Represents a 'pinned' event on a given issue or pull request.\n  \"\"\"\n  PINNED_EVENT\n\n  \"\"\"\n  Represents a 'referenced' event on a given `ReferencedSubject`.\n  \"\"\"\n  REFERENCED_EVENT\n\n  \"\"\"\n  Represents a 'removed_from_project' event on a given issue or pull request.\n  \"\"\"\n  REMOVED_FROM_PROJECT_EVENT\n\n  \"\"\"\n  Represents a 'renamed' event on a given issue or pull request\n  \"\"\"\n  RENAMED_TITLE_EVENT\n\n  \"\"\"\n  Represents a 'reopened' event on any `Closable`.\n  \"\"\"\n  REOPENED_EVENT\n\n  \"\"\"\n  Represents a 'subscribed' event on a given `Subscribable`.\n  \"\"\"\n  SUBSCRIBED_EVENT\n\n  \"\"\"\n  Represents a 'transferred' event on a given issue or pull request.\n  \"\"\"\n  TRANSFERRED_EVENT\n\n  \"\"\"\n  Represents an 'unassigned' event on any assignable object.\n  \"\"\"\n  UNASSIGNED_EVENT\n\n  \"\"\"\n  Represents an 'unlabeled' event on a given issue or pull request.\n  \"\"\"\n  UNLABELED_EVENT\n\n  \"\"\"\n  Represents an 'unlocked' event on a given issue or pull request.\n  \"\"\"\n  UNLOCKED_EVENT\n\n  \"\"\"\n  Represents an 'unpinned' event on a given issue or pull request.\n  \"\"\"\n  UNPINNED_EVENT\n\n  \"\"\"\n  Represents an 'unsubscribed' event on a given `Subscribable`.\n  \"\"\"\n  UNSUBSCRIBED_EVENT\n}\n\n\"\"\"\nRepresents a user signing up for a GitHub account.\n\"\"\"\ntype JoinedGitHubContribution implements Contribution {\n  \"\"\"\n  Whether this contribution is associated with a record you do not have access to. For\n  example, your own 'first issue' contribution may have been made on a repository you can no\n  longer access.\n  \"\"\"\n  isRestricted: Boolean!\n\n  \"\"\"\n  When this contribution was made.\n  \"\"\"\n  occurredAt: DateTime!\n\n  \"\"\"\n  The HTTP path for this contribution.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this contribution.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  The user who made this contribution.\n  \"\"\"\n  user: User!\n}\n\n\"\"\"\nA label for categorizing Issues or Milestones with a given Repository.\n\"\"\"\ntype Label implements Node {\n  \"\"\"\n  Identifies the label color.\n  \"\"\"\n  color: String!\n\n  \"\"\"\n  Identifies the date and time when the label was created.\n  \"\"\"\n  createdAt: DateTime\n\n  \"\"\"\n  A brief description of this label.\n  \"\"\"\n  description: String\n  id: ID!\n\n  \"\"\"\n  Indicates whether or not this is a default label.\n  \"\"\"\n  isDefault: Boolean!\n\n  \"\"\"\n  A list of issues associated with this label.\n  \"\"\"\n  issues(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Filtering options for issues returned from the connection.\n    \"\"\"\n    filterBy: IssueFilters @preview(toggledBy: \"starfire-preview\")\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    A list of label names to filter the pull requests by.\n    \"\"\"\n    labels: [String!]\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for issues returned from the connection.\n    \"\"\"\n    orderBy: IssueOrder\n\n    \"\"\"\n    A list of states to filter the issues by.\n    \"\"\"\n    states: [IssueState!]\n  ): IssueConnection!\n\n  \"\"\"\n  Identifies the label name.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  A list of pull requests associated with this label.\n  \"\"\"\n  pullRequests(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    The base ref name to filter the pull requests by.\n    \"\"\"\n    baseRefName: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    The head ref name to filter the pull requests by.\n    \"\"\"\n    headRefName: String\n\n    \"\"\"\n    A list of label names to filter the pull requests by.\n    \"\"\"\n    labels: [String!]\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for pull requests returned from the connection.\n    \"\"\"\n    orderBy: IssueOrder\n\n    \"\"\"\n    A list of states to filter the pull requests by.\n    \"\"\"\n    states: [PullRequestState!]\n  ): PullRequestConnection!\n\n  \"\"\"\n  The repository associated with this label.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The HTTP path for this label.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Identifies the date and time when the label was last updated.\n  \"\"\"\n  updatedAt: DateTime\n\n  \"\"\"\n  The HTTP URL for this label.\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nThe connection type for Label.\n\"\"\"\ntype LabelConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [LabelEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Label]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype LabelEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Label\n}\n\n\"\"\"\nAn object that can have labels assigned to it.\n\"\"\"\ninterface Labelable {\n  \"\"\"\n  A list of labels associated with the object.\n  \"\"\"\n  labels(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): LabelConnection\n}\n\n\"\"\"\nRepresents a 'labeled' event on a given issue or pull request.\n\"\"\"\ntype LabeledEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Identifies the label associated with the 'labeled' event.\n  \"\"\"\n  label: Label!\n\n  \"\"\"\n  Identifies the `Labelable` associated with the event.\n  \"\"\"\n  labelable: Labelable!\n}\n\n\"\"\"\nRepresents a given language found in repositories.\n\"\"\"\ntype Language implements Node {\n  \"\"\"\n  The color defined for the current language.\n  \"\"\"\n  color: String\n  id: ID!\n\n  \"\"\"\n  The name of the current language.\n  \"\"\"\n  name: String!\n}\n\n\"\"\"\nA list of languages associated with the parent.\n\"\"\"\ntype LanguageConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [LanguageEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Language]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n\n  \"\"\"\n  The total size in bytes of files written in that language.\n  \"\"\"\n  totalSize: Int!\n}\n\n\"\"\"\nRepresents the language of a repository.\n\"\"\"\ntype LanguageEdge {\n  cursor: String!\n  node: Language!\n\n  \"\"\"\n  The number of bytes of code written in the language.\n  \"\"\"\n  size: Int!\n}\n\n\"\"\"\nOrdering options for language connections.\n\"\"\"\ninput LanguageOrder {\n  \"\"\"\n  The ordering direction.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field to order languages by.\n  \"\"\"\n  field: LanguageOrderField!\n}\n\n\"\"\"\nProperties by which language connections can be ordered.\n\"\"\"\nenum LanguageOrderField {\n  \"\"\"\n  Order languages by the size of all files containing the language\n  \"\"\"\n  SIZE\n}\n\n\"\"\"\nA repository's open source license\n\"\"\"\ntype License implements Node {\n  \"\"\"\n  The full text of the license\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  The conditions set by the license\n  \"\"\"\n  conditions: [LicenseRule]!\n\n  \"\"\"\n  A human-readable description of the license\n  \"\"\"\n  description: String\n\n  \"\"\"\n  Whether the license should be featured\n  \"\"\"\n  featured: Boolean!\n\n  \"\"\"\n  Whether the license should be displayed in license pickers\n  \"\"\"\n  hidden: Boolean!\n  id: ID!\n\n  \"\"\"\n  Instructions on how to implement the license\n  \"\"\"\n  implementation: String\n\n  \"\"\"\n  The lowercased SPDX ID of the license\n  \"\"\"\n  key: String!\n\n  \"\"\"\n  The limitations set by the license\n  \"\"\"\n  limitations: [LicenseRule]!\n\n  \"\"\"\n  The license full name specified by <https://spdx.org/licenses>\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  Customary short name if applicable (e.g, GPLv3)\n  \"\"\"\n  nickname: String\n\n  \"\"\"\n  The permissions set by the license\n  \"\"\"\n  permissions: [LicenseRule]!\n\n  \"\"\"\n  Whether the license is a pseudo-license placeholder (e.g., other, no-license)\n  \"\"\"\n  pseudoLicense: Boolean!\n\n  \"\"\"\n  Short identifier specified by <https://spdx.org/licenses>\n  \"\"\"\n  spdxId: String\n\n  \"\"\"\n  URL to the license on <https://choosealicense.com>\n  \"\"\"\n  url: URI\n}\n\n\"\"\"\nDescribes a License's conditions, permissions, and limitations\n\"\"\"\ntype LicenseRule {\n  \"\"\"\n  A description of the rule\n  \"\"\"\n  description: String!\n\n  \"\"\"\n  The machine-readable rule key\n  \"\"\"\n  key: String!\n\n  \"\"\"\n  The human-readable rule label\n  \"\"\"\n  label: String!\n}\n\n\"\"\"\nAutogenerated input type of LockLockable\n\"\"\"\ninput LockLockableInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A reason for why the issue or pull request will be locked.\n  \"\"\"\n  lockReason: LockReason\n\n  \"\"\"\n  ID of the issue or pull request to be locked.\n  \"\"\"\n  lockableId: ID! @possibleTypes(concreteTypes: [\"Issue\", \"PullRequest\"], abstractType: \"Lockable\")\n}\n\n\"\"\"\nAutogenerated return type of LockLockable\n\"\"\"\ntype LockLockablePayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The item that was locked.\n  \"\"\"\n  lockedRecord: Lockable\n}\n\n\"\"\"\nThe possible reasons that an issue or pull request was locked.\n\"\"\"\nenum LockReason {\n  \"\"\"\n  The issue or pull request was locked because the conversation was off-topic.\n  \"\"\"\n  OFF_TOPIC\n\n  \"\"\"\n  The issue or pull request was locked because the conversation was resolved.\n  \"\"\"\n  RESOLVED\n\n  \"\"\"\n  The issue or pull request was locked because the conversation was spam.\n  \"\"\"\n  SPAM\n\n  \"\"\"\n  The issue or pull request was locked because the conversation was too heated.\n  \"\"\"\n  TOO_HEATED\n}\n\n\"\"\"\nAn object that can be locked.\n\"\"\"\ninterface Lockable {\n  \"\"\"\n  Reason that the conversation was locked.\n  \"\"\"\n  activeLockReason: LockReason\n\n  \"\"\"\n  `true` if the object is locked\n  \"\"\"\n  locked: Boolean!\n}\n\n\"\"\"\nRepresents a 'locked' event on a given issue or pull request.\n\"\"\"\ntype LockedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Reason that the conversation was locked (optional).\n  \"\"\"\n  lockReason: LockReason\n\n  \"\"\"\n  Object that was locked.\n  \"\"\"\n  lockable: Lockable!\n}\n\n\"\"\"\nA public description of a Marketplace category.\n\"\"\"\ntype MarketplaceCategory implements Node {\n  \"\"\"\n  The category's description.\n  \"\"\"\n  description: String\n\n  \"\"\"\n  The technical description of how apps listed in this category work with GitHub.\n  \"\"\"\n  howItWorks: String\n  id: ID!\n\n  \"\"\"\n  The category's name.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  How many Marketplace listings have this as their primary category.\n  \"\"\"\n  primaryListingCount: Int!\n\n  \"\"\"\n  The HTTP path for this Marketplace category.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  How many Marketplace listings have this as their secondary category.\n  \"\"\"\n  secondaryListingCount: Int!\n\n  \"\"\"\n  The short name of the category used in its URL.\n  \"\"\"\n  slug: String!\n\n  \"\"\"\n  The HTTP URL for this Marketplace category.\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nA listing in the GitHub integration marketplace.\n\"\"\"\ntype MarketplaceListing implements Node {\n  \"\"\"\n  The GitHub App this listing represents.\n  \"\"\"\n  app: App\n\n  \"\"\"\n  URL to the listing owner's company site.\n  \"\"\"\n  companyUrl: URI\n\n  \"\"\"\n  The HTTP path for configuring access to the listing's integration or OAuth app\n  \"\"\"\n  configurationResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for configuring access to the listing's integration or OAuth app\n  \"\"\"\n  configurationUrl: URI!\n\n  \"\"\"\n  URL to the listing's documentation.\n  \"\"\"\n  documentationUrl: URI\n\n  \"\"\"\n  The listing's detailed description.\n  \"\"\"\n  extendedDescription: String\n\n  \"\"\"\n  The listing's detailed description rendered to HTML.\n  \"\"\"\n  extendedDescriptionHTML: HTML!\n\n  \"\"\"\n  The listing's introductory description.\n  \"\"\"\n  fullDescription: String!\n\n  \"\"\"\n  The listing's introductory description rendered to HTML.\n  \"\"\"\n  fullDescriptionHTML: HTML!\n\n  \"\"\"\n  Whether this listing has been submitted for review from GitHub for approval to be displayed in the Marketplace.\n  \"\"\"\n  hasApprovalBeenRequested: Boolean!\n\n  \"\"\"\n  Does this listing have any plans with a free trial?\n  \"\"\"\n  hasPublishedFreeTrialPlans: Boolean!\n\n  \"\"\"\n  Does this listing have a terms of service link?\n  \"\"\"\n  hasTermsOfService: Boolean!\n\n  \"\"\"\n  A technical description of how this app works with GitHub.\n  \"\"\"\n  howItWorks: String\n\n  \"\"\"\n  The listing's technical description rendered to HTML.\n  \"\"\"\n  howItWorksHTML: HTML!\n  id: ID!\n\n  \"\"\"\n  URL to install the product to the viewer's account or organization.\n  \"\"\"\n  installationUrl: URI\n\n  \"\"\"\n  Whether this listing's app has been installed for the current viewer\n  \"\"\"\n  installedForViewer: Boolean!\n\n  \"\"\"\n  Whether this listing has been approved for display in the Marketplace.\n  \"\"\"\n  isApproved: Boolean!\n\n  \"\"\"\n  Whether this listing has been removed from the Marketplace.\n  \"\"\"\n  isDelisted: Boolean!\n\n  \"\"\"\n  Whether this listing is still an editable draft that has not been submitted\n  for review and is not publicly visible in the Marketplace.\n  \"\"\"\n  isDraft: Boolean!\n\n  \"\"\"\n  Whether the product this listing represents is available as part of a paid plan.\n  \"\"\"\n  isPaid: Boolean!\n\n  \"\"\"\n  Whether this listing has been rejected by GitHub for display in the Marketplace.\n  \"\"\"\n  isRejected: Boolean!\n\n  \"\"\"\n  The hex color code, without the leading '#', for the logo background.\n  \"\"\"\n  logoBackgroundColor: String!\n\n  \"\"\"\n  URL for the listing's logo image.\n  \"\"\"\n  logoUrl(\n    \"\"\"\n    The size in pixels of the resulting square image.\n    \"\"\"\n    size: Int = 400\n  ): URI\n\n  \"\"\"\n  The listing's full name.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The listing's very short description without a trailing period or ampersands.\n  \"\"\"\n  normalizedShortDescription: String!\n\n  \"\"\"\n  URL to the listing's detailed pricing.\n  \"\"\"\n  pricingUrl: URI\n\n  \"\"\"\n  The category that best describes the listing.\n  \"\"\"\n  primaryCategory: MarketplaceCategory!\n\n  \"\"\"\n  URL to the listing's privacy policy.\n  \"\"\"\n  privacyPolicyUrl: URI!\n\n  \"\"\"\n  The HTTP path for the Marketplace listing.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The URLs for the listing's screenshots.\n  \"\"\"\n  screenshotUrls: [String]!\n\n  \"\"\"\n  An alternate category that describes the listing.\n  \"\"\"\n  secondaryCategory: MarketplaceCategory\n\n  \"\"\"\n  The listing's very short description.\n  \"\"\"\n  shortDescription: String!\n\n  \"\"\"\n  The short name of the listing used in its URL.\n  \"\"\"\n  slug: String!\n\n  \"\"\"\n  URL to the listing's status page.\n  \"\"\"\n  statusUrl: URI\n\n  \"\"\"\n  An email address for support for this listing's app.\n  \"\"\"\n  supportEmail: String\n\n  \"\"\"\n  Either a URL or an email address for support for this listing's app.\n  \"\"\"\n  supportUrl: URI!\n\n  \"\"\"\n  URL to the listing's terms of service.\n  \"\"\"\n  termsOfServiceUrl: URI\n\n  \"\"\"\n  The HTTP URL for the Marketplace listing.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  Can the current viewer add plans for this Marketplace listing.\n  \"\"\"\n  viewerCanAddPlans: Boolean!\n\n  \"\"\"\n  Can the current viewer approve this Marketplace listing.\n  \"\"\"\n  viewerCanApprove: Boolean!\n\n  \"\"\"\n  Can the current viewer delist this Marketplace listing.\n  \"\"\"\n  viewerCanDelist: Boolean!\n\n  \"\"\"\n  Can the current viewer edit this Marketplace listing.\n  \"\"\"\n  viewerCanEdit: Boolean!\n\n  \"\"\"\n  Can the current viewer edit the primary and secondary category of this\n  Marketplace listing.\n  \"\"\"\n  viewerCanEditCategories: Boolean!\n\n  \"\"\"\n  Can the current viewer edit the plans for this Marketplace listing.\n  \"\"\"\n  viewerCanEditPlans: Boolean!\n\n  \"\"\"\n  Can the current viewer return this Marketplace listing to draft state\n  so it becomes editable again.\n  \"\"\"\n  viewerCanRedraft: Boolean!\n\n  \"\"\"\n  Can the current viewer reject this Marketplace listing by returning it to\n  an editable draft state or rejecting it entirely.\n  \"\"\"\n  viewerCanReject: Boolean!\n\n  \"\"\"\n  Can the current viewer request this listing be reviewed for display in\n  the Marketplace.\n  \"\"\"\n  viewerCanRequestApproval: Boolean!\n\n  \"\"\"\n  Indicates whether the current user has an active subscription to this Marketplace listing.\n  \"\"\"\n  viewerHasPurchased: Boolean!\n\n  \"\"\"\n  Indicates if the current user has purchased a subscription to this Marketplace listing\n  for all of the organizations the user owns.\n  \"\"\"\n  viewerHasPurchasedForAllOrganizations: Boolean!\n\n  \"\"\"\n  Does the current viewer role allow them to administer this Marketplace listing.\n  \"\"\"\n  viewerIsListingAdmin: Boolean!\n}\n\n\"\"\"\nLook up Marketplace Listings\n\"\"\"\ntype MarketplaceListingConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [MarketplaceListingEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [MarketplaceListing]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype MarketplaceListingEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: MarketplaceListing\n}\n\n\"\"\"\nRepresents a 'mentioned' event on a given issue or pull request.\n\"\"\"\ntype MentionedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n}\n\n\"\"\"\nAutogenerated input type of MergePullRequest\n\"\"\"\ninput MergePullRequestInput @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  Commit body to use for the merge commit; if omitted, a default message will be used\n  \"\"\"\n  commitBody: String\n\n  \"\"\"\n  Commit headline to use for the merge commit; if omitted, a default message will be used.\n  \"\"\"\n  commitHeadline: String\n\n  \"\"\"\n  OID that the pull request head ref must match to allow merge; if omitted, no check is performed.\n  \"\"\"\n  expectedHeadOid: GitObjectID\n\n  \"\"\"\n  ID of the pull request to be merged.\n  \"\"\"\n  pullRequestId: ID! @possibleTypes(concreteTypes: [\"PullRequest\"])\n}\n\n\"\"\"\nAutogenerated return type of MergePullRequest\n\"\"\"\ntype MergePullRequestPayload @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The pull request that was merged.\n  \"\"\"\n  pullRequest: PullRequest\n}\n\n\"\"\"\nDetailed status information about a pull request merge.\n\"\"\"\nenum MergeStateStatus {\n  \"\"\"\n  The head ref is out of date.\n  \"\"\"\n  BEHIND\n\n  \"\"\"\n  The merge is blocked.\n  \"\"\"\n  BLOCKED\n\n  \"\"\"\n  Mergeable and passing commit status.\n  \"\"\"\n  CLEAN\n\n  \"\"\"\n  The merge commit cannot be cleanly created.\n  \"\"\"\n  DIRTY\n\n  \"\"\"\n  Mergeable with passing commit status and pre-recieve hooks.\n  \"\"\"\n  HAS_HOOKS\n\n  \"\"\"\n  The state cannot currently be determined.\n  \"\"\"\n  UNKNOWN\n\n  \"\"\"\n  Mergeable with non-passing commit status.\n  \"\"\"\n  UNSTABLE\n}\n\n\"\"\"\nWhether or not a PullRequest can be merged.\n\"\"\"\nenum MergeableState {\n  \"\"\"\n  The pull request cannot be merged due to merge conflicts.\n  \"\"\"\n  CONFLICTING\n\n  \"\"\"\n  The pull request can be merged.\n  \"\"\"\n  MERGEABLE\n\n  \"\"\"\n  The mergeability of the pull request is still being calculated.\n  \"\"\"\n  UNKNOWN\n}\n\n\"\"\"\nRepresents a 'merged' event on a given pull request.\n\"\"\"\ntype MergedEvent implements Node & UniformResourceLocatable {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the commit associated with the `merge` event.\n  \"\"\"\n  commit: Commit\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Identifies the Ref associated with the `merge` event.\n  \"\"\"\n  mergeRef: Ref\n\n  \"\"\"\n  Identifies the name of the Ref associated with the `merge` event.\n  \"\"\"\n  mergeRefName: String!\n\n  \"\"\"\n  PullRequest referenced by event.\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  The HTTP path for this merged event.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this merged event.\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nRepresents a Milestone object on a given repository.\n\"\"\"\ntype Milestone implements Closable & Node & UniformResourceLocatable {\n  \"\"\"\n  `true` if the object is closed (definition of closed may depend on type)\n  \"\"\"\n  closed: Boolean!\n\n  \"\"\"\n  Identifies the date and time when the object was closed.\n  \"\"\"\n  closedAt: DateTime\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the actor who created the milestone.\n  \"\"\"\n  creator: Actor\n\n  \"\"\"\n  Identifies the description of the milestone.\n  \"\"\"\n  description: String\n\n  \"\"\"\n  Identifies the due date of the milestone.\n  \"\"\"\n  dueOn: DateTime\n  id: ID!\n\n  \"\"\"\n  A list of issues associated with the milestone.\n  \"\"\"\n  issues(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Filtering options for issues returned from the connection.\n    \"\"\"\n    filterBy: IssueFilters @preview(toggledBy: \"starfire-preview\")\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    A list of label names to filter the pull requests by.\n    \"\"\"\n    labels: [String!]\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for issues returned from the connection.\n    \"\"\"\n    orderBy: IssueOrder\n\n    \"\"\"\n    A list of states to filter the issues by.\n    \"\"\"\n    states: [IssueState!]\n  ): IssueConnection!\n\n  \"\"\"\n  Identifies the number of the milestone.\n  \"\"\"\n  number: Int!\n\n  \"\"\"\n  A list of pull requests associated with the milestone.\n  \"\"\"\n  pullRequests(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    The base ref name to filter the pull requests by.\n    \"\"\"\n    baseRefName: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    The head ref name to filter the pull requests by.\n    \"\"\"\n    headRefName: String\n\n    \"\"\"\n    A list of label names to filter the pull requests by.\n    \"\"\"\n    labels: [String!]\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for pull requests returned from the connection.\n    \"\"\"\n    orderBy: IssueOrder\n\n    \"\"\"\n    A list of states to filter the pull requests by.\n    \"\"\"\n    states: [PullRequestState!]\n  ): PullRequestConnection!\n\n  \"\"\"\n  The repository associated with this milestone.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The HTTP path for this milestone\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Identifies the state of the milestone.\n  \"\"\"\n  state: MilestoneState!\n\n  \"\"\"\n  Identifies the title of the milestone.\n  \"\"\"\n  title: String!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this milestone\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nThe connection type for Milestone.\n\"\"\"\ntype MilestoneConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [MilestoneEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Milestone]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype MilestoneEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Milestone\n}\n\n\"\"\"\nTypes that can be inside a Milestone.\n\"\"\"\nunion MilestoneItem = Issue | PullRequest\n\n\"\"\"\nOrdering options for milestone connections.\n\"\"\"\ninput MilestoneOrder {\n  \"\"\"\n  The ordering direction.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field to order milestones by.\n  \"\"\"\n  field: MilestoneOrderField!\n}\n\n\"\"\"\nProperties by which milestone connections can be ordered.\n\"\"\"\nenum MilestoneOrderField {\n  \"\"\"\n  Order milestones by when they were created.\n  \"\"\"\n  CREATED_AT\n\n  \"\"\"\n  Order milestones by when they are due.\n  \"\"\"\n  DUE_DATE\n\n  \"\"\"\n  Order milestones by their number.\n  \"\"\"\n  NUMBER\n\n  \"\"\"\n  Order milestones by when they were last updated.\n  \"\"\"\n  UPDATED_AT\n}\n\n\"\"\"\nThe possible states of a milestone.\n\"\"\"\nenum MilestoneState {\n  \"\"\"\n  A milestone that has been closed.\n  \"\"\"\n  CLOSED\n\n  \"\"\"\n  A milestone that is still open.\n  \"\"\"\n  OPEN\n}\n\n\"\"\"\nRepresents a 'milestoned' event on a given issue or pull request.\n\"\"\"\ntype MilestonedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Identifies the milestone title associated with the 'milestoned' event.\n  \"\"\"\n  milestoneTitle: String!\n\n  \"\"\"\n  Object referenced by event.\n  \"\"\"\n  subject: MilestoneItem!\n}\n\n\"\"\"\nEntities that can be minimized.\n\"\"\"\ninterface Minimizable @preview(toggledBy: \"queen-beryl-preview\") {\n  \"\"\"\n  Returns whether or not a comment has been minimized.\n  \"\"\"\n  isMinimized: Boolean!\n\n  \"\"\"\n  Returns why the comment was minimized.\n  \"\"\"\n  minimizedReason: String\n\n  \"\"\"\n  Check if the current viewer can minimize this object.\n  \"\"\"\n  viewerCanMinimize: Boolean!\n}\n\n\"\"\"\nAutogenerated input type of MinimizeComment\n\"\"\"\ninput MinimizeCommentInput {\n  \"\"\"\n  The classification of comment\n  \"\"\"\n  classifier: ReportedContentClassifiers!\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the subject to modify.\n  \"\"\"\n  subjectId: ID! @possibleTypes(concreteTypes: [\"CommitComment\", \"GistComment\", \"IssueComment\", \"PullRequestReviewComment\"], abstractType: \"Minimizable\")\n}\n\n\"\"\"\nAutogenerated return type of MinimizeComment\n\"\"\"\ntype MinimizeCommentPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The comment that was minimized.\n  \"\"\"\n  minimizedComment: Minimizable\n}\n\n\"\"\"\nAutogenerated input type of MoveProjectCard\n\"\"\"\ninput MoveProjectCardInput {\n  \"\"\"\n  Place the new card after the card with this id. Pass null to place it at the top.\n  \"\"\"\n  afterCardId: ID @possibleTypes(concreteTypes: [\"ProjectCard\"])\n\n  \"\"\"\n  The id of the card to move.\n  \"\"\"\n  cardId: ID! @possibleTypes(concreteTypes: [\"ProjectCard\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The id of the column to move it into.\n  \"\"\"\n  columnId: ID! @possibleTypes(concreteTypes: [\"ProjectColumn\"])\n}\n\n\"\"\"\nAutogenerated return type of MoveProjectCard\n\"\"\"\ntype MoveProjectCardPayload {\n  \"\"\"\n  The new edge of the moved card.\n  \"\"\"\n  cardEdge: ProjectCardEdge\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of MoveProjectColumn\n\"\"\"\ninput MoveProjectColumnInput {\n  \"\"\"\n  Place the new column after the column with this id. Pass null to place it at the front.\n  \"\"\"\n  afterColumnId: ID @possibleTypes(concreteTypes: [\"ProjectColumn\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The id of the column to move.\n  \"\"\"\n  columnId: ID! @possibleTypes(concreteTypes: [\"ProjectColumn\"])\n}\n\n\"\"\"\nAutogenerated return type of MoveProjectColumn\n\"\"\"\ntype MoveProjectColumnPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The new edge of the moved column.\n  \"\"\"\n  columnEdge: ProjectColumnEdge\n}\n\n\"\"\"\nRepresents a 'moved_columns_in_project' event on a given issue or pull request.\n\"\"\"\ntype MovedColumnsInProjectEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  Column name the issue or pull request was moved from.\n  \"\"\"\n  previousProjectColumnName: String! @preview(toggledBy: \"starfox-preview\")\n\n  \"\"\"\n  Project referenced by event.\n  \"\"\"\n  project: Project @preview(toggledBy: \"starfox-preview\")\n\n  \"\"\"\n  Project card referenced by this project event.\n  \"\"\"\n  projectCard: ProjectCard @preview(toggledBy: \"starfox-preview\")\n\n  \"\"\"\n  Column name the issue or pull request was moved to.\n  \"\"\"\n  projectColumnName: String! @preview(toggledBy: \"starfox-preview\")\n}\n\n\"\"\"\nThe root query for implementing GraphQL mutations.\n\"\"\"\ntype Mutation {\n  \"\"\"\n  Accepts a pending invitation for a user to join a business.\n  \"\"\"\n  acceptBusinessMemberInvitation(input: AcceptBusinessMemberInvitationInput!): AcceptBusinessMemberInvitationPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Applies a suggested topic to the repository.\n  \"\"\"\n  acceptTopicSuggestion(input: AcceptTopicSuggestionInput!): AcceptTopicSuggestionPayload\n\n  \"\"\"\n  Adds assignees to an assignable object.\n  \"\"\"\n  addAssigneesToAssignable(input: AddAssigneesToAssignableInput!): AddAssigneesToAssignablePayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Adds a comment to an Issue or Pull Request.\n  \"\"\"\n  addComment(input: AddCommentInput!): AddCommentPayload\n\n  \"\"\"\n  Adds labels to a labelable object.\n  \"\"\"\n  addLabelsToLabelable(input: AddLabelsToLabelableInput!): AddLabelsToLabelablePayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Adds a card to a ProjectColumn. Either `contentId` or `note` must be provided but **not** both.\n  \"\"\"\n  addProjectCard(input: AddProjectCardInput!): AddProjectCardPayload\n\n  \"\"\"\n  Adds a column to a Project.\n  \"\"\"\n  addProjectColumn(input: AddProjectColumnInput!): AddProjectColumnPayload\n\n  \"\"\"\n  Adds a review to a Pull Request.\n  \"\"\"\n  addPullRequestReview(input: AddPullRequestReviewInput!): AddPullRequestReviewPayload\n\n  \"\"\"\n  Adds a comment to a review.\n  \"\"\"\n  addPullRequestReviewComment(input: AddPullRequestReviewCommentInput!): AddPullRequestReviewCommentPayload\n\n  \"\"\"\n  Adds a reaction to a subject.\n  \"\"\"\n  addReaction(input: AddReactionInput!): AddReactionPayload\n\n  \"\"\"\n  Adds a star to a Starrable.\n  \"\"\"\n  addStar(input: AddStarInput!): AddStarPayload\n\n  \"\"\"\n  Cancels a pending invitation for an administrator to join a business.\n  \"\"\"\n  cancelBusinessAdminInvitation(input: CancelBusinessAdminInvitationInput!): CancelBusinessAdminInvitationPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Cancels a pending invitation for a billing manager to join a business.\n  \"\"\"\n  cancelBusinessBillingManagerInvitation(input: CancelBusinessBillingManagerInvitationInput!): CancelBusinessBillingManagerInvitationPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Clears all labels from a labelable object.\n  \"\"\"\n  clearLabelsFromLabelable(input: ClearLabelsFromLabelableInput!): ClearLabelsFromLabelablePayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Close an issue.\n  \"\"\"\n  closeIssue(input: CloseIssueInput!): CloseIssuePayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Close a pull request.\n  \"\"\"\n  closePullRequest(input: ClosePullRequestInput!): ClosePullRequestPayload @preview(toggledBy: \"ocelot-preview\")\n\n  \"\"\"\n  Convert a project note card to one associated with a newly created issue.\n  \"\"\"\n  convertProjectCardNoteToIssue(input: ConvertProjectCardNoteToIssueInput!): ConvertProjectCardNoteToIssuePayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Create a new branch protection rule\n  \"\"\"\n  createBranchProtectionRule(input: CreateBranchProtectionRuleInput!): CreateBranchProtectionRulePayload\n\n  \"\"\"\n  Create a check run.\n  \"\"\"\n  createCheckRun(input: CreateCheckRunInput!): CreateCheckRunPayload @preview(toggledBy: \"antiope-preview\")\n\n  \"\"\"\n  Create a check suite\n  \"\"\"\n  createCheckSuite(input: CreateCheckSuiteInput!): CreateCheckSuitePayload @preview(toggledBy: \"antiope-preview\")\n\n  \"\"\"\n  Create a content attachment.\n  \"\"\"\n  createContentAttachment(input: CreateContentAttachmentInput!): CreateContentAttachmentPayload @preview(toggledBy: \"corsair-preview\")\n\n  \"\"\"\n  Creates a new deployment event.\n  \"\"\"\n  createDeployment(input: CreateDeploymentInput!): CreateDeploymentPayload @preview(toggledBy: \"flash-preview\")\n\n  \"\"\"\n  Create a deployment status.\n  \"\"\"\n  createDeploymentStatus(input: CreateDeploymentStatusInput!): CreateDeploymentStatusPayload @preview(toggledBy: \"flash-preview\")\n\n  \"\"\"\n  Creates a new issue.\n  \"\"\"\n  createIssue(input: CreateIssueInput!): CreateIssuePayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Creates a new project.\n  \"\"\"\n  createProject(input: CreateProjectInput!): CreateProjectPayload\n\n  \"\"\"\n  Create a new pull request\n  \"\"\"\n  createPullRequest(input: CreatePullRequestInput!): CreatePullRequestPayload @preview(toggledBy: \"ocelot-preview\")\n\n  \"\"\"\n  Creates a new team discussion.\n  \"\"\"\n  createTeamDiscussion(input: CreateTeamDiscussionInput!): CreateTeamDiscussionPayload @preview(toggledBy: \"echo-preview\")\n\n  \"\"\"\n  Creates a new team discussion comment.\n  \"\"\"\n  createTeamDiscussionComment(input: CreateTeamDiscussionCommentInput!): CreateTeamDiscussionCommentPayload @preview(toggledBy: \"echo-preview\")\n\n  \"\"\"\n  Rejects a suggested topic for the repository.\n  \"\"\"\n  declineTopicSuggestion(input: DeclineTopicSuggestionInput!): DeclineTopicSuggestionPayload\n\n  \"\"\"\n  Delete a branch protection rule\n  \"\"\"\n  deleteBranchProtectionRule(input: DeleteBranchProtectionRuleInput!): DeleteBranchProtectionRulePayload\n\n  \"\"\"\n  Deletes an Issue object.\n  \"\"\"\n  deleteIssue(input: DeleteIssueInput!): DeleteIssuePayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Deletes an IssueComment object.\n  \"\"\"\n  deleteIssueComment(input: DeleteIssueCommentInput!): DeleteIssueCommentPayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Deletes a project.\n  \"\"\"\n  deleteProject(input: DeleteProjectInput!): DeleteProjectPayload\n\n  \"\"\"\n  Deletes a project card.\n  \"\"\"\n  deleteProjectCard(input: DeleteProjectCardInput!): DeleteProjectCardPayload\n\n  \"\"\"\n  Deletes a project column.\n  \"\"\"\n  deleteProjectColumn(input: DeleteProjectColumnInput!): DeleteProjectColumnPayload\n\n  \"\"\"\n  Deletes a pull request review.\n  \"\"\"\n  deletePullRequestReview(input: DeletePullRequestReviewInput!): DeletePullRequestReviewPayload\n\n  \"\"\"\n  Deletes a pull request review comment.\n  \"\"\"\n  deletePullRequestReviewComment(input: DeletePullRequestReviewCommentInput!): DeletePullRequestReviewCommentPayload @preview(toggledBy: \"ocelot-preview\")\n\n  \"\"\"\n  Deletes a team discussion.\n  \"\"\"\n  deleteTeamDiscussion(input: DeleteTeamDiscussionInput!): DeleteTeamDiscussionPayload @preview(toggledBy: \"echo-preview\")\n\n  \"\"\"\n  Deletes a team discussion comment.\n  \"\"\"\n  deleteTeamDiscussionComment(input: DeleteTeamDiscussionCommentInput!): DeleteTeamDiscussionCommentPayload @preview(toggledBy: \"echo-preview\")\n\n  \"\"\"\n  Dismisses an approved or rejected pull request review.\n  \"\"\"\n  dismissPullRequestReview(input: DismissPullRequestReviewInput!): DismissPullRequestReviewPayload\n\n  \"\"\"\n  Invite someone to become an administrator of the business\n  \"\"\"\n  inviteBusinessAdmin(input: InviteBusinessAdminInput!): InviteBusinessAdminPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Invite someone to become a billing manager of the business\n  \"\"\"\n  inviteBusinessBillingManager(input: InviteBusinessBillingManagerInput!): InviteBusinessBillingManagerPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Lock a lockable object\n  \"\"\"\n  lockLockable(input: LockLockableInput!): LockLockablePayload\n\n  \"\"\"\n  Merge a pull request.\n  \"\"\"\n  mergePullRequest(input: MergePullRequestInput!): MergePullRequestPayload @preview(toggledBy: \"ocelot-preview\")\n\n  \"\"\"\n  Minimizes a comment on an Issue, Commit, Pull Request, or Gist\n  \"\"\"\n  minimizeComment(input: MinimizeCommentInput!): MinimizeCommentPayload @preview(toggledBy: \"queen-beryl-preview\")\n\n  \"\"\"\n  Moves a project card to another place.\n  \"\"\"\n  moveProjectCard(input: MoveProjectCardInput!): MoveProjectCardPayload\n\n  \"\"\"\n  Moves a project column to another place.\n  \"\"\"\n  moveProjectColumn(input: MoveProjectColumnInput!): MoveProjectColumnPayload\n\n  \"\"\"\n  Pin an issue to a repository\n  \"\"\"\n  pinIssue(input: PinIssueInput!): PinIssuePayload @preview(toggledBy: \"elektra-preview\")\n\n  \"\"\"\n  Removes assignees from an assignable object.\n  \"\"\"\n  removeAssigneesFromAssignable(input: RemoveAssigneesFromAssignableInput!): RemoveAssigneesFromAssignablePayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Removes an admin from the business\n  \"\"\"\n  removeBusinessAdmin(input: RemoveBusinessAdminInput!): RemoveBusinessAdminPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Removes a billing manager from the business\n  \"\"\"\n  removeBusinessBillingManager(input: RemoveBusinessBillingManagerInput!): RemoveBusinessBillingManagerPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Removes labels from a Labelable object.\n  \"\"\"\n  removeLabelsFromLabelable(input: RemoveLabelsFromLabelableInput!): RemoveLabelsFromLabelablePayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Removes outside collaborator from all repositories in an organization.\n  \"\"\"\n  removeOutsideCollaborator(input: RemoveOutsideCollaboratorInput!): RemoveOutsideCollaboratorPayload\n\n  \"\"\"\n  Removes a reaction from a subject.\n  \"\"\"\n  removeReaction(input: RemoveReactionInput!): RemoveReactionPayload\n\n  \"\"\"\n  Removes a star from a Starrable.\n  \"\"\"\n  removeStar(input: RemoveStarInput!): RemoveStarPayload\n\n  \"\"\"\n  Reopen a issue.\n  \"\"\"\n  reopenIssue(input: ReopenIssueInput!): ReopenIssuePayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Reopen a pull request.\n  \"\"\"\n  reopenPullRequest(input: ReopenPullRequestInput!): ReopenPullRequestPayload @preview(toggledBy: \"ocelot-preview\")\n\n  \"\"\"\n  Set review requests on a pull request.\n  \"\"\"\n  requestReviews(input: RequestReviewsInput!): RequestReviewsPayload\n\n  \"\"\"\n  Rerequests an existing check suite.\n  \"\"\"\n  rerequestCheckSuite(input: RerequestCheckSuiteInput!): RerequestCheckSuitePayload @preview(toggledBy: \"antiope-preview\")\n\n  \"\"\"\n  Marks a review thread as resolved.\n  \"\"\"\n  resolveReviewThread(input: ResolveReviewThreadInput!): ResolveReviewThreadPayload @preview(toggledBy: \"cateye-preview\")\n\n  \"\"\"\n  Submits a pending pull request review.\n  \"\"\"\n  submitPullRequestReview(input: SubmitPullRequestReviewInput!): SubmitPullRequestReviewPayload\n\n  \"\"\"\n  Unlock a lockable object\n  \"\"\"\n  unlockLockable(input: UnlockLockableInput!): UnlockLockablePayload\n\n  \"\"\"\n  Unmark an issue as a duplicate of another issue.\n  \"\"\"\n  unmarkIssueAsDuplicate(input: UnmarkIssueAsDuplicateInput!): UnmarkIssueAsDuplicatePayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Unminimizes a comment on an Issue, Commit, Pull Request, or Gist\n  \"\"\"\n  unminimizeComment(input: UnminimizeCommentInput!): UnminimizeCommentPayload @preview(toggledBy: \"queen-beryl-preview\")\n\n  \"\"\"\n  Unpin a pinned issue from a repository\n  \"\"\"\n  unpinIssue(input: UnpinIssueInput!): UnpinIssuePayload @preview(toggledBy: \"elektra-preview\")\n\n  \"\"\"\n  Marks a review thread as unresolved.\n  \"\"\"\n  unresolveReviewThread(input: UnresolveReviewThreadInput!): UnresolveReviewThreadPayload @preview(toggledBy: \"cateye-preview\")\n\n  \"\"\"\n  Create a new branch protection rule\n  \"\"\"\n  updateBranchProtectionRule(input: UpdateBranchProtectionRuleInput!): UpdateBranchProtectionRulePayload\n\n  \"\"\"\n  Sets whether private repository forks are enabled for a business.\n  \"\"\"\n  updateBusinessAllowPrivateRepositoryForkingSetting(input: UpdateBusinessAllowPrivateRepositoryForkingSettingInput!): UpdateBusinessAllowPrivateRepositoryForkingSettingPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Sets the default repository permission for organizations in a business.\n  \"\"\"\n  updateBusinessDefaultRepositoryPermissionSetting(input: UpdateBusinessDefaultRepositoryPermissionSettingInput!): UpdateBusinessDefaultRepositoryPermissionSettingPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Sets whether organization members with admin permissions on a repository can change repository visibility.\n  \"\"\"\n  updateBusinessMembersCanChangeRepositoryVisibilitySetting(input: UpdateBusinessMembersCanChangeRepositoryVisibilitySettingInput!): UpdateBusinessMembersCanChangeRepositoryVisibilitySettingPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Sets the members can create repositories setting for a business.\n  \"\"\"\n  updateBusinessMembersCanCreateRepositoriesSetting(input: UpdateBusinessMembersCanCreateRepositoriesSettingInput!): UpdateBusinessMembersCanCreateRepositoriesSettingPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Sets the members can delete issues setting for a business.\n  \"\"\"\n  updateBusinessMembersCanDeleteIssuesSetting(input: UpdateBusinessMembersCanDeleteIssuesSettingInput!): UpdateBusinessMembersCanDeleteIssuesSettingPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Sets the members can delete repositories setting for a business.\n  \"\"\"\n  updateBusinessMembersCanDeleteRepositoriesSetting(input: UpdateBusinessMembersCanDeleteRepositoriesSettingInput!): UpdateBusinessMembersCanDeleteRepositoriesSettingPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Sets whether members can invite collaborators are enabled for a business.\n  \"\"\"\n  updateBusinessMembersCanInviteCollaboratorsSetting(input: UpdateBusinessMembersCanInviteCollaboratorsSettingInput!): UpdateBusinessMembersCanInviteCollaboratorsSettingPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Sets the members can update protected branches setting for a business.\n  \"\"\"\n  updateBusinessMembersCanUpdateProtectedBranchesSetting(input: UpdateBusinessMembersCanUpdateProtectedBranchesSettingInput!): UpdateBusinessMembersCanUpdateProtectedBranchesSettingPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Sets whether organization projects are enabled for a business.\n  \"\"\"\n  updateBusinessOrganizationProjectsSetting(input: UpdateBusinessOrganizationProjectsSettingInput!): UpdateBusinessOrganizationProjectsSettingPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Updates business's profile\n  \"\"\"\n  updateBusinessProfile(input: UpdateBusinessProfileInput!): UpdateBusinessProfilePayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Sets whether repository projects are enabled for a business.\n  \"\"\"\n  updateBusinessRepositoryProjectsSetting(input: UpdateBusinessRepositoryProjectsSettingInput!): UpdateBusinessRepositoryProjectsSettingPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Sets whether team discussions are enabled for a business.\n  \"\"\"\n  updateBusinessTeamDiscussionsSetting(input: UpdateBusinessTeamDiscussionsSettingInput!): UpdateBusinessTeamDiscussionsSettingPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Sets whether two factor authentication is required for all users in a business.\n  \"\"\"\n  updateBusinessTwoFactorAuthenticationRequiredSetting(input: UpdateBusinessTwoFactorAuthenticationRequiredSettingInput!): UpdateBusinessTwoFactorAuthenticationRequiredSettingPayload @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Update a check run\n  \"\"\"\n  updateCheckRun(input: UpdateCheckRunInput!): UpdateCheckRunPayload @preview(toggledBy: \"antiope-preview\")\n\n  \"\"\"\n  Modifies the settings of an existing check suite\n  \"\"\"\n  updateCheckSuitePreferences(input: UpdateCheckSuitePreferencesInput!): UpdateCheckSuitePreferencesPayload @preview(toggledBy: \"antiope-preview\")\n\n  \"\"\"\n  Updates an Issue.\n  \"\"\"\n  updateIssue(input: UpdateIssueInput!): UpdateIssuePayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Updates an IssueComment object.\n  \"\"\"\n  updateIssueComment(input: UpdateIssueCommentInput!): UpdateIssueCommentPayload @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Updates an existing project.\n  \"\"\"\n  updateProject(input: UpdateProjectInput!): UpdateProjectPayload\n\n  \"\"\"\n  Updates an existing project card.\n  \"\"\"\n  updateProjectCard(input: UpdateProjectCardInput!): UpdateProjectCardPayload\n\n  \"\"\"\n  Updates an existing project column.\n  \"\"\"\n  updateProjectColumn(input: UpdateProjectColumnInput!): UpdateProjectColumnPayload\n\n  \"\"\"\n  Update a pull request\n  \"\"\"\n  updatePullRequest(input: UpdatePullRequestInput!): UpdatePullRequestPayload @preview(toggledBy: \"ocelot-preview\")\n\n  \"\"\"\n  Updates the body of a pull request review.\n  \"\"\"\n  updatePullRequestReview(input: UpdatePullRequestReviewInput!): UpdatePullRequestReviewPayload\n\n  \"\"\"\n  Updates a pull request review comment.\n  \"\"\"\n  updatePullRequestReviewComment(input: UpdatePullRequestReviewCommentInput!): UpdatePullRequestReviewCommentPayload\n\n  \"\"\"\n  Updates the state for subscribable subjects.\n  \"\"\"\n  updateSubscription(input: UpdateSubscriptionInput!): UpdateSubscriptionPayload\n\n  \"\"\"\n  Updates a team discussion.\n  \"\"\"\n  updateTeamDiscussion(input: UpdateTeamDiscussionInput!): UpdateTeamDiscussionPayload @preview(toggledBy: \"echo-preview\")\n\n  \"\"\"\n  Updates a discussion comment.\n  \"\"\"\n  updateTeamDiscussionComment(input: UpdateTeamDiscussionCommentInput!): UpdateTeamDiscussionCommentPayload @preview(toggledBy: \"echo-preview\")\n\n  \"\"\"\n  Replaces the repository's topics with the given topics.\n  \"\"\"\n  updateTopics(input: UpdateTopicsInput!): UpdateTopicsPayload\n}\n\n\"\"\"\nAn object with an ID.\n\"\"\"\ninterface Node {\n  \"\"\"\n  ID of the object.\n  \"\"\"\n  id: ID!\n}\n\n\"\"\"\nPossible directions in which to order a list of items when provided an `orderBy` argument.\n\"\"\"\nenum OrderDirection {\n  \"\"\"\n  Specifies an ascending order for a given `orderBy` argument.\n  \"\"\"\n  ASC\n\n  \"\"\"\n  Specifies a descending order for a given `orderBy` argument.\n  \"\"\"\n  DESC\n}\n\n\"\"\"\nAn account on GitHub, with one or more owners, that has repositories, members and teams.\n\"\"\"\ntype Organization implements Actor & Node & ProjectOwner & RegistryPackageOwner & RegistryPackageSearch & RepositoryOwner & UniformResourceLocatable {\n  \"\"\"\n  A URL pointing to the organization's public avatar.\n  \"\"\"\n  avatarUrl(\n    \"\"\"\n    The size of the resulting square image.\n    \"\"\"\n    size: Int\n  ): URI!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The organization's public profile description.\n  \"\"\"\n  description: String\n\n  \"\"\"\n  The organization's public email.\n  \"\"\"\n  email: String\n  id: ID!\n\n  \"\"\"\n  Whether the organization has verified its profile email and website.\n  \"\"\"\n  isVerified: Boolean!\n\n  \"\"\"\n  The organization's public profile location.\n  \"\"\"\n  location: String\n\n  \"\"\"\n  The organization's login name.\n  \"\"\"\n  login: String!\n\n  \"\"\"\n  A list of users who are members of this organization.\n  \"\"\"\n  members(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserConnection! @deprecated(reason: \"The `members` field is deprecated and will be removed soon. Use `Organization.membersWithRole` instead. Removal on 2019-04-01 UTC.\")\n\n  \"\"\"\n  A list of users who are members of this organization.\n  \"\"\"\n  membersWithRole(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): OrganizationMemberConnection!\n\n  \"\"\"\n  The organization's public profile name.\n  \"\"\"\n  name: String\n\n  \"\"\"\n  The HTTP path creating a new team\n  \"\"\"\n  newTeamResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL creating a new team\n  \"\"\"\n  newTeamUrl: URI!\n\n  \"\"\"\n  The billing email for the organization.\n  \"\"\"\n  organizationBillingEmail: String\n\n  \"\"\"\n  A list of users who have been invited to join this organization.\n  \"\"\"\n  pendingMembers(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserConnection!\n\n  \"\"\"\n  A list of repositories this user has pinned to their profile\n  \"\"\"\n  pinnedRepositories(\n    \"\"\"\n    Array of viewer's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    current viewer owns.\n    \"\"\"\n    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    If non-null, filters repositories according to whether they have been locked\n    \"\"\"\n    isLocked: Boolean\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for repositories returned from the connection\n    \"\"\"\n    orderBy: RepositoryOrder\n\n    \"\"\"\n    Array of owner's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    organization or user being viewed owns.\n    \"\"\"\n    ownerAffiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    If non-null, filters repositories according to privacy\n    \"\"\"\n    privacy: RepositoryPrivacy\n  ): RepositoryConnection!\n\n  \"\"\"\n  Find project by number.\n  \"\"\"\n  project(\n    \"\"\"\n    The project number to find.\n    \"\"\"\n    number: Int!\n  ): Project\n\n  \"\"\"\n  A list of projects under the owner.\n  \"\"\"\n  projects(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for projects returned from the connection\n    \"\"\"\n    orderBy: ProjectOrder\n\n    \"\"\"\n    Query to search projects by, currently only searching by name.\n    \"\"\"\n    search: String\n\n    \"\"\"\n    A list of states to filter the projects by.\n    \"\"\"\n    states: [ProjectState!]\n  ): ProjectConnection!\n\n  \"\"\"\n  The HTTP path listing organization's projects\n  \"\"\"\n  projectsResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL listing organization's projects\n  \"\"\"\n  projectsUrl: URI!\n\n  \"\"\"\n  A list of repositories that the user owns.\n  \"\"\"\n  repositories(\n    \"\"\"\n    Array of viewer's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    current viewer owns.\n    \"\"\"\n    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    If non-null, filters repositories according to whether they are forks of another repository\n    \"\"\"\n    isFork: Boolean\n\n    \"\"\"\n    If non-null, filters repositories according to whether they have been locked\n    \"\"\"\n    isLocked: Boolean\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for repositories returned from the connection\n    \"\"\"\n    orderBy: RepositoryOrder\n\n    \"\"\"\n    Array of owner's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    organization or user being viewed owns.\n    \"\"\"\n    ownerAffiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    If non-null, filters repositories according to privacy\n    \"\"\"\n    privacy: RepositoryPrivacy\n  ): RepositoryConnection!\n\n  \"\"\"\n  Find Repository.\n  \"\"\"\n  repository(\n    \"\"\"\n    Name of Repository to find.\n    \"\"\"\n    name: String!\n  ): Repository\n\n  \"\"\"\n  When true the organization requires all members, billing managers, and outside\n  collaborators to enable two-factor authentication.\n  \"\"\"\n  requiresTwoFactorAuthentication: Boolean\n\n  \"\"\"\n  The HTTP path for this organization.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The Organization's SAML Identity Providers\n  \"\"\"\n  samlIdentityProvider: OrganizationIdentityProvider\n\n  \"\"\"\n  Find an organization's team by its slug.\n  \"\"\"\n  team(\n    \"\"\"\n    The name or slug of the team to find.\n    \"\"\"\n    slug: String!\n  ): Team\n\n  \"\"\"\n  A list of teams in this organization.\n  \"\"\"\n  teams(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    If true, filters teams that are mapped to an LDAP Group (Enterprise only)\n    \"\"\"\n    ldapMapped: Boolean\n\n    \"\"\"\n    Ordering options for teams returned from the connection\n    \"\"\"\n    orderBy: TeamOrder\n\n    \"\"\"\n    If non-null, filters teams according to privacy\n    \"\"\"\n    privacy: TeamPrivacy\n\n    \"\"\"\n    If non-null, filters teams with query on team name and team slug\n    \"\"\"\n    query: String\n\n    \"\"\"\n    If non-null, filters teams according to whether the viewer is an admin or member on team\n    \"\"\"\n    role: TeamRole\n\n    \"\"\"\n    If true, restrict to only root teams\n    \"\"\"\n    rootTeamsOnly: Boolean = false\n\n    \"\"\"\n    User logins to filter by\n    \"\"\"\n    userLogins: [String!]\n  ): TeamConnection!\n\n  \"\"\"\n  The HTTP path listing organization's teams\n  \"\"\"\n  teamsResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL listing organization's teams\n  \"\"\"\n  teamsUrl: URI!\n\n  \"\"\"\n  The HTTP URL for this organization.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  Organization is adminable by the viewer.\n  \"\"\"\n  viewerCanAdminister: Boolean!\n\n  \"\"\"\n  Can the current viewer create new projects on this owner.\n  \"\"\"\n  viewerCanCreateProjects: Boolean!\n\n  \"\"\"\n  Viewer can create repositories on this organization\n  \"\"\"\n  viewerCanCreateRepositories: Boolean!\n\n  \"\"\"\n  Viewer can create teams on this organization.\n  \"\"\"\n  viewerCanCreateTeams: Boolean!\n\n  \"\"\"\n  Viewer is an active member of this organization.\n  \"\"\"\n  viewerIsAMember: Boolean!\n\n  \"\"\"\n  The organization's public profile URL.\n  \"\"\"\n  websiteUrl: URI\n}\n\n\"\"\"\nThe connection type for Organization.\n\"\"\"\ntype OrganizationConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [OrganizationEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Organization]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype OrganizationEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Organization\n}\n\n\"\"\"\nAn Identity Provider configured to provision SAML and SCIM identities for Organizations\n\"\"\"\ntype OrganizationIdentityProvider implements Node {\n  \"\"\"\n  The digest algorithm used to sign SAML requests for the Identity Provider.\n  \"\"\"\n  digestMethod: URI\n\n  \"\"\"\n  External Identities provisioned by this Identity Provider\n  \"\"\"\n  externalIdentities(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): ExternalIdentityConnection!\n  id: ID!\n\n  \"\"\"\n  The x509 certificate used by the Identity Provder to sign assertions and responses.\n  \"\"\"\n  idpCertificate: X509Certificate\n\n  \"\"\"\n  The Issuer Entity ID for the SAML Identity Provider\n  \"\"\"\n  issuer: String\n\n  \"\"\"\n  Organization this Identity Provider belongs to\n  \"\"\"\n  organization: Organization\n\n  \"\"\"\n  The signature algorithm used to sign SAML requests for the Identity Provider.\n  \"\"\"\n  signatureMethod: URI\n\n  \"\"\"\n  The URL endpoint for the Identity Provider's SAML SSO.\n  \"\"\"\n  ssoUrl: URI\n}\n\n\"\"\"\nAn Invitation for a user to an organization.\n\"\"\"\ntype OrganizationInvitation implements Node {\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  The email address of the user invited to the organization.\n  \"\"\"\n  email: String\n  id: ID!\n\n  \"\"\"\n  The type of invitation that was sent (e.g. email, user).\n  \"\"\"\n  invitationType: OrganizationInvitationType!\n\n  \"\"\"\n  The user who was invited to the organization.\n  \"\"\"\n  invitee: User\n\n  \"\"\"\n  The user who created the invitation.\n  \"\"\"\n  inviter: User!\n\n  \"\"\"\n  The organization the invite is for\n  \"\"\"\n  organization: Organization!\n\n  \"\"\"\n  The user's pending role in the organization (e.g. member, owner).\n  \"\"\"\n  role: OrganizationInvitationRole!\n}\n\n\"\"\"\nThe connection type for OrganizationInvitation.\n\"\"\"\ntype OrganizationInvitationConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [OrganizationInvitationEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [OrganizationInvitation]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype OrganizationInvitationEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: OrganizationInvitation\n}\n\n\"\"\"\nThe possible organization invitation roles.\n\"\"\"\nenum OrganizationInvitationRole {\n  \"\"\"\n  The user is invited to be an admin of the organization.\n  \"\"\"\n  ADMIN\n\n  \"\"\"\n  The user is invited to be a billing manager of the organization.\n  \"\"\"\n  BILLING_MANAGER\n\n  \"\"\"\n  The user is invited to be a direct member of the organization.\n  \"\"\"\n  DIRECT_MEMBER\n\n  \"\"\"\n  The user's previous role will be reinstated.\n  \"\"\"\n  REINSTATE\n}\n\n\"\"\"\nThe possible organization invitation types.\n\"\"\"\nenum OrganizationInvitationType {\n  \"\"\"\n  The invitation was to an email address.\n  \"\"\"\n  EMAIL\n\n  \"\"\"\n  The invitation was to an existing user.\n  \"\"\"\n  USER\n}\n\n\"\"\"\nThe connection type for User.\n\"\"\"\ntype OrganizationMemberConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [OrganizationMemberEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [User]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nRepresents a user within an organization.\n\"\"\"\ntype OrganizationMemberEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: User\n\n  \"\"\"\n  The role this user has in the organization.\n  \"\"\"\n  role: OrganizationMemberRole\n}\n\n\"\"\"\nThe possible roles within an organization for its members.\n\"\"\"\nenum OrganizationMemberRole {\n  \"\"\"\n  The user is an administrator of the organization.\n  \"\"\"\n  ADMIN\n\n  \"\"\"\n  The user is a member of the organization.\n  \"\"\"\n  MEMBER\n}\n\n\"\"\"\nOrdering options for organization connections.\n\"\"\"\ninput OrganizationOrder @preview(toggledBy: \"gwenpool-preview\") {\n  \"\"\"\n  The ordering direction.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field to order organizations by.\n  \"\"\"\n  field: OrganizationOrderField!\n}\n\n\"\"\"\nProperties by which organization connections can be ordered.\n\"\"\"\nenum OrganizationOrderField @preview(toggledBy: \"gwenpool-preview\") {\n  \"\"\"\n  Order organizations by creation time\n  \"\"\"\n  CREATED_AT\n\n  \"\"\"\n  Order organizations by login\n  \"\"\"\n  LOGIN\n}\n\n\"\"\"\nAn organization teams hovercard context\n\"\"\"\ntype OrganizationTeamsHovercardContext implements HovercardContext @preview(toggledBy: \"hagar-preview\") {\n  \"\"\"\n  A string describing this context\n  \"\"\"\n  message: String!\n\n  \"\"\"\n  An octicon to accompany this context\n  \"\"\"\n  octicon: String!\n\n  \"\"\"\n  Teams in this organization the user is a member of that are relevant\n  \"\"\"\n  relevantTeams(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): TeamConnection!\n\n  \"\"\"\n  The path for the full team list for this user\n  \"\"\"\n  teamsResourcePath: URI!\n\n  \"\"\"\n  The URL for the full team list for this user\n  \"\"\"\n  teamsUrl: URI!\n\n  \"\"\"\n  The total number of teams the user is on in the organization\n  \"\"\"\n  totalTeamCount: Int!\n}\n\n\"\"\"\nAn organization list hovercard context\n\"\"\"\ntype OrganizationsHovercardContext implements HovercardContext @preview(toggledBy: \"hagar-preview\") {\n  \"\"\"\n  A string describing this context\n  \"\"\"\n  message: String!\n\n  \"\"\"\n  An octicon to accompany this context\n  \"\"\"\n  octicon: String!\n\n  \"\"\"\n  Organizations this user is a member of that are relevant\n  \"\"\"\n  relevantOrganizations(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): OrganizationConnection!\n\n  \"\"\"\n  The total number of organizations this user is in\n  \"\"\"\n  totalOrganizationCount: Int!\n}\n\n\"\"\"\nInformation about pagination in a connection.\n\"\"\"\ntype PageInfo {\n  \"\"\"\n  When paginating forwards, the cursor to continue.\n  \"\"\"\n  endCursor: String\n\n  \"\"\"\n  When paginating forwards, are there more items?\n  \"\"\"\n  hasNextPage: Boolean!\n\n  \"\"\"\n  When paginating backwards, are there more items?\n  \"\"\"\n  hasPreviousPage: Boolean!\n\n  \"\"\"\n  When paginating backwards, the cursor to continue.\n  \"\"\"\n  startCursor: String\n}\n\n\"\"\"\nAutogenerated input type of PinIssue\n\"\"\"\ninput PinIssueInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the issue to be pinned\n  \"\"\"\n  issueId: ID! @possibleTypes(concreteTypes: [\"Issue\"])\n}\n\n\"\"\"\nAutogenerated return type of PinIssue\n\"\"\"\ntype PinIssuePayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The issue that was pinned\n  \"\"\"\n  issue: Issue\n}\n\n\"\"\"\nRepresents a 'pinned' event on a given issue or pull request.\n\"\"\"\ntype PinnedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Identifies the issue associated with the event.\n  \"\"\"\n  issue: Issue!\n}\n\n\"\"\"\nA Pinned Issue is a issue pinned to a repository's index page.\n\"\"\"\ntype PinnedIssue implements Node @preview(toggledBy: \"elektra-preview\") {\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  The issue that was pinned.\n  \"\"\"\n  issue: Issue!\n\n  \"\"\"\n  The actor that pinned this issue.\n  \"\"\"\n  pinnedBy: Actor!\n\n  \"\"\"\n  The repository that this issue was pinned to.\n  \"\"\"\n  repository: Repository!\n}\n\n\"\"\"\nThe connection type for PinnedIssue.\n\"\"\"\ntype PinnedIssueConnection @preview(toggledBy: \"elektra-preview\") {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [PinnedIssueEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [PinnedIssue]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype PinnedIssueEdge @preview(toggledBy: \"elektra-preview\") {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: PinnedIssue\n}\n\n\"\"\"\nProjects manage issues, pull requests and notes within a project owner.\n\"\"\"\ntype Project implements Closable & Node & Updatable {\n  \"\"\"\n  The project's description body.\n  \"\"\"\n  body: String\n\n  \"\"\"\n  The projects description body rendered to HTML.\n  \"\"\"\n  bodyHTML: HTML!\n\n  \"\"\"\n  `true` if the object is closed (definition of closed may depend on type)\n  \"\"\"\n  closed: Boolean!\n\n  \"\"\"\n  Identifies the date and time when the object was closed.\n  \"\"\"\n  closedAt: DateTime\n\n  \"\"\"\n  List of columns in the project\n  \"\"\"\n  columns(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): ProjectColumnConnection!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  The actor who originally created the project.\n  \"\"\"\n  creator: Actor\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  The project's name.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The project's number.\n  \"\"\"\n  number: Int!\n\n  \"\"\"\n  The project's owner. Currently limited to repositories and organizations.\n  \"\"\"\n  owner: ProjectOwner!\n\n  \"\"\"\n  List of pending cards in this project\n  \"\"\"\n  pendingCards(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    A list of archived states to filter the cards by\n    \"\"\"\n    archivedStates: [ProjectCardArchivedState] = [ARCHIVED, NOT_ARCHIVED]\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): ProjectCardConnection!\n\n  \"\"\"\n  The HTTP path for this project\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Whether the project is open or closed.\n  \"\"\"\n  state: ProjectState!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this project\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  Check if the current viewer can update this object.\n  \"\"\"\n  viewerCanUpdate: Boolean!\n}\n\n\"\"\"\nA card in a project.\n\"\"\"\ntype ProjectCard implements Node {\n  \"\"\"\n  The project column this card is associated under. A card may only belong to one\n  project column at a time. The column field will be null if the card is created\n  in a pending state and has yet to be associated with a column. Once cards are\n  associated with a column, they will not become pending in the future.\n  \"\"\"\n  column: ProjectColumn\n\n  \"\"\"\n  The card content item\n  \"\"\"\n  content: ProjectCardItem\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  The actor who created this card\n  \"\"\"\n  creator: Actor\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  Whether the card is archived\n  \"\"\"\n  isArchived: Boolean!\n\n  \"\"\"\n  The card note\n  \"\"\"\n  note: String\n\n  \"\"\"\n  The project that contains this card.\n  \"\"\"\n  project: Project!\n\n  \"\"\"\n  The HTTP path for this card\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The state of ProjectCard\n  \"\"\"\n  state: ProjectCardState\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this card\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nThe possible archived states of a project card.\n\"\"\"\nenum ProjectCardArchivedState {\n  \"\"\"\n  A project card that is archived\n  \"\"\"\n  ARCHIVED\n\n  \"\"\"\n  A project card that is not archived\n  \"\"\"\n  NOT_ARCHIVED\n}\n\n\"\"\"\nThe connection type for ProjectCard.\n\"\"\"\ntype ProjectCardConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [ProjectCardEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [ProjectCard]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype ProjectCardEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: ProjectCard\n}\n\n\"\"\"\nTypes that can be inside Project Cards.\n\"\"\"\nunion ProjectCardItem = Issue | PullRequest\n\n\"\"\"\nVarious content states of a ProjectCard\n\"\"\"\nenum ProjectCardState {\n  \"\"\"\n  The card has content only.\n  \"\"\"\n  CONTENT_ONLY\n\n  \"\"\"\n  The card has a note only.\n  \"\"\"\n  NOTE_ONLY\n\n  \"\"\"\n  The card is redacted.\n  \"\"\"\n  REDACTED\n}\n\n\"\"\"\nA column inside a project.\n\"\"\"\ntype ProjectColumn implements Node {\n  \"\"\"\n  List of cards in the column\n  \"\"\"\n  cards(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    A list of archived states to filter the cards by\n    \"\"\"\n    archivedStates: [ProjectCardArchivedState] = [ARCHIVED, NOT_ARCHIVED]\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): ProjectCardConnection!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  The project column's name.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The project that contains this column.\n  \"\"\"\n  project: Project!\n\n  \"\"\"\n  The semantic purpose of the column\n  \"\"\"\n  purpose: ProjectColumnPurpose\n\n  \"\"\"\n  The HTTP path for this project column\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this project column\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nThe connection type for ProjectColumn.\n\"\"\"\ntype ProjectColumnConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [ProjectColumnEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [ProjectColumn]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype ProjectColumnEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: ProjectColumn\n}\n\n\"\"\"\nThe semantic purpose of the column - todo, in progress, or done.\n\"\"\"\nenum ProjectColumnPurpose {\n  \"\"\"\n  The column contains cards which are complete\n  \"\"\"\n  DONE\n\n  \"\"\"\n  The column contains cards which are currently being worked on\n  \"\"\"\n  IN_PROGRESS\n\n  \"\"\"\n  The column contains cards still to be worked on\n  \"\"\"\n  TODO\n}\n\n\"\"\"\nA list of projects associated with the owner.\n\"\"\"\ntype ProjectConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [ProjectEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Project]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype ProjectEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Project\n}\n\n\"\"\"\nWays in which lists of projects can be ordered upon return.\n\"\"\"\ninput ProjectOrder {\n  \"\"\"\n  The direction in which to order projects by the specified field.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field in which to order projects by.\n  \"\"\"\n  field: ProjectOrderField!\n}\n\n\"\"\"\nProperties by which project connections can be ordered.\n\"\"\"\nenum ProjectOrderField {\n  \"\"\"\n  Order projects by creation time\n  \"\"\"\n  CREATED_AT\n\n  \"\"\"\n  Order projects by name\n  \"\"\"\n  NAME\n\n  \"\"\"\n  Order projects by update time\n  \"\"\"\n  UPDATED_AT\n}\n\n\"\"\"\nRepresents an owner of a Project.\n\"\"\"\ninterface ProjectOwner {\n  id: ID!\n\n  \"\"\"\n  Find project by number.\n  \"\"\"\n  project(\n    \"\"\"\n    The project number to find.\n    \"\"\"\n    number: Int!\n  ): Project\n\n  \"\"\"\n  A list of projects under the owner.\n  \"\"\"\n  projects(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for projects returned from the connection\n    \"\"\"\n    orderBy: ProjectOrder\n\n    \"\"\"\n    Query to search projects by, currently only searching by name.\n    \"\"\"\n    search: String\n\n    \"\"\"\n    A list of states to filter the projects by.\n    \"\"\"\n    states: [ProjectState!]\n  ): ProjectConnection!\n\n  \"\"\"\n  The HTTP path listing owners projects\n  \"\"\"\n  projectsResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL listing owners projects\n  \"\"\"\n  projectsUrl: URI!\n\n  \"\"\"\n  Can the current viewer create new projects on this owner.\n  \"\"\"\n  viewerCanCreateProjects: Boolean!\n}\n\n\"\"\"\nState of the project; either 'open' or 'closed'\n\"\"\"\nenum ProjectState {\n  \"\"\"\n  The project is closed.\n  \"\"\"\n  CLOSED\n\n  \"\"\"\n  The project is open.\n  \"\"\"\n  OPEN\n}\n\n\"\"\"\nA repository protected branch.\n\"\"\"\ntype ProtectedBranch implements Node {\n  \"\"\"\n  The actor who created this protected branch.\n  \"\"\"\n  creator: Actor\n\n  \"\"\"\n  Will new commits pushed to this branch dismiss pull request review approvals.\n  \"\"\"\n  hasDismissableStaleReviews: Boolean!\n\n  \"\"\"\n  Are reviews required to update this branch.\n  \"\"\"\n  hasRequiredReviews: Boolean!\n\n  \"\"\"\n  Are commits required to be signed.\n  \"\"\"\n  hasRequiredSignatures: Boolean! @preview(toggledBy: \"zzzax-preview\")\n\n  \"\"\"\n  Are status checks required to update this branch.\n  \"\"\"\n  hasRequiredStatusChecks: Boolean!\n\n  \"\"\"\n  Is pushing to this branch restricted.\n  \"\"\"\n  hasRestrictedPushes: Boolean!\n\n  \"\"\"\n  Is dismissal of pull request reviews restricted.\n  \"\"\"\n  hasRestrictedReviewDismissals: Boolean!\n\n  \"\"\"\n  Are branches required to be up to date before merging.\n  \"\"\"\n  hasStrictRequiredStatusChecks: Boolean!\n  id: ID!\n\n  \"\"\"\n  Can admins overwrite branch protection.\n  \"\"\"\n  isAdminEnforced: Boolean!\n\n  \"\"\"\n  The name of the protected branch rule.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  A list push allowances for this protected branch.\n  \"\"\"\n  pushAllowances(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): PushAllowanceConnection!\n\n  \"\"\"\n  The repository associated with this protected branch.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  Number of approving reviews required to update this branch.\n  \"\"\"\n  requiredApprovingReviewCount: Int @preview(toggledBy: \"luke-cage-preview\")\n\n  \"\"\"\n  List of required status check contexts that must pass for commits to be accepted to this branch.\n  \"\"\"\n  requiredStatusCheckContexts: [String]\n\n  \"\"\"\n  A list review dismissal allowances for this protected branch.\n  \"\"\"\n  reviewDismissalAllowances(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): ReviewDismissalAllowanceConnection!\n}\n\n\"\"\"\nThe connection type for ProtectedBranch.\n\"\"\"\ntype ProtectedBranchConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [ProtectedBranchEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [ProtectedBranch]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype ProtectedBranchEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: ProtectedBranch\n}\n\n\"\"\"\nA user's public key.\n\"\"\"\ntype PublicKey implements Node {\n  id: ID!\n\n  \"\"\"\n  The public key string\n  \"\"\"\n  key: String!\n}\n\n\"\"\"\nThe connection type for PublicKey.\n\"\"\"\ntype PublicKeyConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [PublicKeyEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [PublicKey]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype PublicKeyEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: PublicKey\n}\n\n\"\"\"\nA repository pull request.\n\"\"\"\ntype PullRequest implements Assignable & Closable & Comment & Labelable & Lockable & Node & Reactable & RepositoryNode & Subscribable & UniformResourceLocatable & Updatable & UpdatableComment {\n  \"\"\"\n  Reason that the conversation was locked.\n  \"\"\"\n  activeLockReason: LockReason\n\n  \"\"\"\n  The number of additions in this pull request.\n  \"\"\"\n  additions: Int!\n\n  \"\"\"\n  A list of Users assigned to this object.\n  \"\"\"\n  assignees(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserConnection!\n\n  \"\"\"\n  The actor who authored the comment.\n  \"\"\"\n  author: Actor\n\n  \"\"\"\n  Author's association with the subject of the comment.\n  \"\"\"\n  authorAssociation: CommentAuthorAssociation!\n\n  \"\"\"\n  Identifies the base Ref associated with the pull request.\n  \"\"\"\n  baseRef: Ref\n\n  \"\"\"\n  Identifies the name of the base Ref associated with the pull request, even if the ref has been deleted.\n  \"\"\"\n  baseRefName: String!\n\n  \"\"\"\n  Identifies the oid of the base ref associated with the pull request, even if the ref has been deleted.\n  \"\"\"\n  baseRefOid: GitObjectID!\n\n  \"\"\"\n  The body as Markdown.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  The body rendered to HTML.\n  \"\"\"\n  bodyHTML: HTML!\n\n  \"\"\"\n  The body rendered to text.\n  \"\"\"\n  bodyText: String!\n\n  \"\"\"\n  Whether or not the pull request is rebaseable.\n  \"\"\"\n  canBeRebased: Boolean! @preview(toggledBy: \"merge-info-preview\")\n\n  \"\"\"\n  The number of changed files in this pull request.\n  \"\"\"\n  changedFiles: Int!\n\n  \"\"\"\n  `true` if the pull request is closed\n  \"\"\"\n  closed: Boolean!\n\n  \"\"\"\n  Identifies the date and time when the object was closed.\n  \"\"\"\n  closedAt: DateTime\n\n  \"\"\"\n  A list of comments associated with the pull request.\n  \"\"\"\n  comments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): IssueCommentConnection!\n\n  \"\"\"\n  A list of commits present in this pull request's head branch not present in the base branch.\n  \"\"\"\n  commits(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): PullRequestCommitConnection!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Check if this comment was created via an email reply.\n  \"\"\"\n  createdViaEmail: Boolean!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The number of deletions in this pull request.\n  \"\"\"\n  deletions: Int!\n\n  \"\"\"\n  The actor who edited this pull request's body.\n  \"\"\"\n  editor: Actor\n\n  \"\"\"\n  Lists the files changed within this pull request.\n  \"\"\"\n  files(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): PullRequestChangedFileConnection @preview(toggledBy: \"ocelot-preview\")\n\n  \"\"\"\n  Identifies the head Ref associated with the pull request.\n  \"\"\"\n  headRef: Ref\n\n  \"\"\"\n  Identifies the name of the head Ref associated with the pull request, even if the ref has been deleted.\n  \"\"\"\n  headRefName: String!\n\n  \"\"\"\n  Identifies the oid of the head ref associated with the pull request, even if the ref has been deleted.\n  \"\"\"\n  headRefOid: GitObjectID!\n\n  \"\"\"\n  The repository associated with this pull request's head Ref.\n  \"\"\"\n  headRepository: Repository\n\n  \"\"\"\n  The owner of the repository associated with this pull request's head Ref.\n  \"\"\"\n  headRepositoryOwner: RepositoryOwner\n\n  \"\"\"\n  The hovercard information for this issue\n  \"\"\"\n  hovercard(\n    \"\"\"\n    Whether or not to include notification contexts\n    \"\"\"\n    includeNotificationContexts: Boolean = true\n  ): Hovercard! @preview(toggledBy: \"hagar-preview\")\n  id: ID!\n\n  \"\"\"\n  Check if this comment was edited and includes an edit with the creation data\n  \"\"\"\n  includesCreatedEdit: Boolean!\n\n  \"\"\"\n  The head and base repositories are different.\n  \"\"\"\n  isCrossRepository: Boolean!\n\n  \"\"\"\n  A list of labels associated with the object.\n  \"\"\"\n  labels(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): LabelConnection\n\n  \"\"\"\n  The moment the editor made the last edit\n  \"\"\"\n  lastEditedAt: DateTime\n\n  \"\"\"\n  `true` if the pull request is locked\n  \"\"\"\n  locked: Boolean!\n\n  \"\"\"\n  Indicates whether maintainers can modify the pull request.\n  \"\"\"\n  maintainerCanModify: Boolean!\n\n  \"\"\"\n  The commit that was created when this pull request was merged.\n  \"\"\"\n  mergeCommit: Commit\n\n  \"\"\"\n  Detailed information about the current pull request merge state status.\n  \"\"\"\n  mergeStateStatus: MergeStateStatus! @preview(toggledBy: \"merge-info-preview\")\n\n  \"\"\"\n  Whether or not the pull request can be merged based on the existence of merge conflicts.\n  \"\"\"\n  mergeable: MergeableState!\n\n  \"\"\"\n  Whether or not the pull request was merged.\n  \"\"\"\n  merged: Boolean!\n\n  \"\"\"\n  The date and time that the pull request was merged.\n  \"\"\"\n  mergedAt: DateTime\n\n  \"\"\"\n  The actor who merged the pull request.\n  \"\"\"\n  mergedBy: Actor\n\n  \"\"\"\n  Identifies the milestone associated with the pull request.\n  \"\"\"\n  milestone: Milestone\n\n  \"\"\"\n  Identifies the pull request number.\n  \"\"\"\n  number: Int!\n\n  \"\"\"\n  A list of Users that are participating in the Pull Request conversation.\n  \"\"\"\n  participants(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserConnection!\n\n  \"\"\"\n  The permalink to the pull request.\n  \"\"\"\n  permalink: URI!\n\n  \"\"\"\n  The commit that GitHub automatically generated to test if this pull request\n  could be merged. This field will not return a value if the pull request is\n  merged, or if the test merge commit is still being generated. See the\n  `mergeable` field for more details on the mergeability of the pull request.\n  \"\"\"\n  potentialMergeCommit: Commit\n\n  \"\"\"\n  List of project cards associated with this pull request.\n  \"\"\"\n  projectCards(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    A list of archived states to filter the cards by\n    \"\"\"\n    archivedStates: [ProjectCardArchivedState] = [ARCHIVED, NOT_ARCHIVED]\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): ProjectCardConnection!\n\n  \"\"\"\n  Identifies when the comment was published at.\n  \"\"\"\n  publishedAt: DateTime\n\n  \"\"\"\n  A list of reactions grouped by content left on the subject.\n  \"\"\"\n  reactionGroups: [ReactionGroup!]\n\n  \"\"\"\n  A list of Reactions left on the Issue.\n  \"\"\"\n  reactions(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Allows filtering Reactions by emoji.\n    \"\"\"\n    content: ReactionContent\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Allows specifying the order in which reactions are returned.\n    \"\"\"\n    orderBy: ReactionOrder\n  ): ReactionConnection!\n\n  \"\"\"\n  The repository associated with this node.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The HTTP path for this pull request.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The HTTP path for reverting this pull request.\n  \"\"\"\n  revertResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for reverting this pull request.\n  \"\"\"\n  revertUrl: URI!\n\n  \"\"\"\n  A list of review requests associated with the pull request.\n  \"\"\"\n  reviewRequests(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): ReviewRequestConnection\n\n  \"\"\"\n  The list of all review threads for this pull request.\n  \"\"\"\n  reviewThreads(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): PullRequestReviewThreadConnection! @preview(toggledBy: \"ocelot-preview\")\n\n  \"\"\"\n  A list of reviews associated with the pull request.\n  \"\"\"\n  reviews(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Filter by author of the review.\n    \"\"\"\n    author: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    A list of states to filter the reviews.\n    \"\"\"\n    states: [PullRequestReviewState!]\n  ): PullRequestReviewConnection\n\n  \"\"\"\n  Identifies the state of the pull request.\n  \"\"\"\n  state: PullRequestState!\n\n  \"\"\"\n  A list of reviewer suggestions based on commit history and past review comments.\n  \"\"\"\n  suggestedReviewers: [SuggestedReviewer]!\n\n  \"\"\"\n  A list of events, comments, commits, etc. associated with the pull request.\n  \"\"\"\n  timeline(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Allows filtering timeline events by a `since` timestamp.\n    \"\"\"\n    since: DateTime\n  ): PullRequestTimelineConnection!\n\n  \"\"\"\n  A list of events, comments, commits, etc. associated with the pull request.\n  \"\"\"\n  timelineItems(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Filter timeline items by type.\n    \"\"\"\n    itemTypes: [PullRequestTimelineItemsItemType!]\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Filter timeline items by a `since` timestamp.\n    \"\"\"\n    since: DateTime\n\n    \"\"\"\n    Skips the first _n_ elements in the list.\n    \"\"\"\n    skip: Int\n  ): PullRequestTimelineItemsConnection! @preview(toggledBy: \"starfire-preview\")\n\n  \"\"\"\n  Identifies the pull request title.\n  \"\"\"\n  title: String!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this pull request.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  A list of edits to this content.\n  \"\"\"\n  userContentEdits(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserContentEditConnection\n\n  \"\"\"\n  Whether or not the viewer can apply suggestion.\n  \"\"\"\n  viewerCanApplySuggestion: Boolean!\n\n  \"\"\"\n  Can user react to this subject\n  \"\"\"\n  viewerCanReact: Boolean!\n\n  \"\"\"\n  Check if the viewer is able to change their subscription status for the repository.\n  \"\"\"\n  viewerCanSubscribe: Boolean!\n\n  \"\"\"\n  Check if the current viewer can update this object.\n  \"\"\"\n  viewerCanUpdate: Boolean!\n\n  \"\"\"\n  Reasons why the current viewer can not update this comment.\n  \"\"\"\n  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!\n\n  \"\"\"\n  Did the viewer author this comment.\n  \"\"\"\n  viewerDidAuthor: Boolean!\n\n  \"\"\"\n  Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.\n  \"\"\"\n  viewerSubscription: SubscriptionState\n}\n\n\"\"\"\nA file changed in a pull request.\n\"\"\"\ntype PullRequestChangedFile @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  The number of additions to the file.\n  \"\"\"\n  additions: Int!\n\n  \"\"\"\n  The number of deletions to the file.\n  \"\"\"\n  deletions: Int!\n\n  \"\"\"\n  The path of the file.\n  \"\"\"\n  path: String!\n}\n\n\"\"\"\nThe connection type for PullRequestChangedFile.\n\"\"\"\ntype PullRequestChangedFileConnection @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [PullRequestChangedFileEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [PullRequestChangedFile]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype PullRequestChangedFileEdge @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: PullRequestChangedFile\n}\n\n\"\"\"\nRepresents a Git commit part of a pull request.\n\"\"\"\ntype PullRequestCommit implements Node & UniformResourceLocatable {\n  \"\"\"\n  The Git commit object\n  \"\"\"\n  commit: Commit!\n  id: ID!\n\n  \"\"\"\n  The pull request this commit belongs to\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  The HTTP path for this pull request commit\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this pull request commit\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nRepresents a commit comment thread part of a pull request.\n\"\"\"\ntype PullRequestCommitCommentThread implements Node & RepositoryNode @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  The comments that exist in this thread.\n  \"\"\"\n  comments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): CommitCommentConnection!\n\n  \"\"\"\n  The commit the comments were made on.\n  \"\"\"\n  commit: Commit!\n  id: ID!\n\n  \"\"\"\n  The file the comments were made on.\n  \"\"\"\n  path: String\n\n  \"\"\"\n  The position in the diff for the commit that the comment was made on.\n  \"\"\"\n  position: Int\n\n  \"\"\"\n  The pull request this commit comment thread belongs to\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  The repository associated with this node.\n  \"\"\"\n  repository: Repository!\n}\n\n\"\"\"\nThe connection type for PullRequestCommit.\n\"\"\"\ntype PullRequestCommitConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [PullRequestCommitEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [PullRequestCommit]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype PullRequestCommitEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: PullRequestCommit\n}\n\n\"\"\"\nThe connection type for PullRequest.\n\"\"\"\ntype PullRequestConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [PullRequestEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [PullRequest]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype PullRequestEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: PullRequest\n}\n\n\"\"\"\nProperties by which pull_requests connections can be ordered.\n\"\"\"\nenum PullRequestOrderField {\n  \"\"\"\n  Order pull_requests by creation time\n  \"\"\"\n  CREATED_AT\n\n  \"\"\"\n  Order pull_requests by update time\n  \"\"\"\n  UPDATED_AT\n}\n\n\"\"\"\nA review object for a given pull request.\n\"\"\"\ntype PullRequestReview implements Comment & Deletable & Node & Reactable & RepositoryNode & Updatable & UpdatableComment {\n  \"\"\"\n  The actor who authored the comment.\n  \"\"\"\n  author: Actor\n\n  \"\"\"\n  Author's association with the subject of the comment.\n  \"\"\"\n  authorAssociation: CommentAuthorAssociation!\n\n  \"\"\"\n  Identifies the pull request review body.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  The body of this review rendered to HTML.\n  \"\"\"\n  bodyHTML: HTML!\n\n  \"\"\"\n  The body of this review rendered as plain text.\n  \"\"\"\n  bodyText: String!\n\n  \"\"\"\n  A list of review comments for the current pull request review.\n  \"\"\"\n  comments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): PullRequestReviewCommentConnection!\n\n  \"\"\"\n  Identifies the commit associated with this pull request review.\n  \"\"\"\n  commit: Commit\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Check if this comment was created via an email reply.\n  \"\"\"\n  createdViaEmail: Boolean!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The actor who edited the comment.\n  \"\"\"\n  editor: Actor\n  id: ID!\n\n  \"\"\"\n  Check if this comment was edited and includes an edit with the creation data\n  \"\"\"\n  includesCreatedEdit: Boolean!\n\n  \"\"\"\n  The moment the editor made the last edit\n  \"\"\"\n  lastEditedAt: DateTime\n\n  \"\"\"\n  A list of teams that this review was made on behalf of.\n  \"\"\"\n  onBehalfOf(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): TeamConnection!\n\n  \"\"\"\n  Identifies when the comment was published at.\n  \"\"\"\n  publishedAt: DateTime\n\n  \"\"\"\n  Identifies the pull request associated with this pull request review.\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  A list of reactions grouped by content left on the subject.\n  \"\"\"\n  reactionGroups: [ReactionGroup!]\n\n  \"\"\"\n  A list of Reactions left on the Issue.\n  \"\"\"\n  reactions(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Allows filtering Reactions by emoji.\n    \"\"\"\n    content: ReactionContent\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Allows specifying the order in which reactions are returned.\n    \"\"\"\n    orderBy: ReactionOrder\n  ): ReactionConnection!\n\n  \"\"\"\n  The repository associated with this node.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The HTTP path permalink for this PullRequestReview.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Identifies the current state of the pull request review.\n  \"\"\"\n  state: PullRequestReviewState!\n\n  \"\"\"\n  Identifies when the Pull Request Review was submitted\n  \"\"\"\n  submittedAt: DateTime\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL permalink for this PullRequestReview.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  A list of edits to this content.\n  \"\"\"\n  userContentEdits(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserContentEditConnection\n\n  \"\"\"\n  Check if the current viewer can delete this object.\n  \"\"\"\n  viewerCanDelete: Boolean!\n\n  \"\"\"\n  Can user react to this subject\n  \"\"\"\n  viewerCanReact: Boolean!\n\n  \"\"\"\n  Check if the current viewer can update this object.\n  \"\"\"\n  viewerCanUpdate: Boolean!\n\n  \"\"\"\n  Reasons why the current viewer can not update this comment.\n  \"\"\"\n  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!\n\n  \"\"\"\n  Did the viewer author this comment.\n  \"\"\"\n  viewerDidAuthor: Boolean!\n}\n\n\"\"\"\nA review comment associated with a given repository pull request.\n\"\"\"\ntype PullRequestReviewComment implements Comment & Deletable & Minimizable & Node & Reactable & RepositoryNode & Updatable & UpdatableComment {\n  \"\"\"\n  The actor who authored the comment.\n  \"\"\"\n  author: Actor\n\n  \"\"\"\n  Author's association with the subject of the comment.\n  \"\"\"\n  authorAssociation: CommentAuthorAssociation!\n\n  \"\"\"\n  The comment body of this review comment.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  The comment body of this review comment rendered to HTML.\n  \"\"\"\n  bodyHTML: HTML!\n\n  \"\"\"\n  The comment body of this review comment rendered as plain text.\n  \"\"\"\n  bodyText: String!\n\n  \"\"\"\n  Identifies the commit associated with the comment.\n  \"\"\"\n  commit: Commit!\n\n  \"\"\"\n  Identifies when the comment was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Check if this comment was created via an email reply.\n  \"\"\"\n  createdViaEmail: Boolean!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The diff hunk to which the comment applies.\n  \"\"\"\n  diffHunk: String!\n\n  \"\"\"\n  Identifies when the comment was created in a draft state.\n  \"\"\"\n  draftedAt: DateTime!\n\n  \"\"\"\n  The actor who edited the comment.\n  \"\"\"\n  editor: Actor\n  id: ID!\n\n  \"\"\"\n  Check if this comment was edited and includes an edit with the creation data\n  \"\"\"\n  includesCreatedEdit: Boolean!\n\n  \"\"\"\n  Returns whether or not a comment has been minimized.\n  \"\"\"\n  isMinimized: Boolean!\n\n  \"\"\"\n  The moment the editor made the last edit\n  \"\"\"\n  lastEditedAt: DateTime\n\n  \"\"\"\n  Returns why the comment was minimized.\n  \"\"\"\n  minimizedReason: String\n\n  \"\"\"\n  Identifies the original commit associated with the comment.\n  \"\"\"\n  originalCommit: Commit\n\n  \"\"\"\n  The original line index in the diff to which the comment applies.\n  \"\"\"\n  originalPosition: Int!\n\n  \"\"\"\n  Identifies when the comment body is outdated\n  \"\"\"\n  outdated: Boolean!\n\n  \"\"\"\n  The path to which the comment applies.\n  \"\"\"\n  path: String!\n\n  \"\"\"\n  The line index in the diff to which the comment applies.\n  \"\"\"\n  position: Int\n\n  \"\"\"\n  Identifies when the comment was published at.\n  \"\"\"\n  publishedAt: DateTime\n\n  \"\"\"\n  The pull request associated with this review comment.\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  The pull request review associated with this review comment.\n  \"\"\"\n  pullRequestReview: PullRequestReview\n\n  \"\"\"\n  A list of reactions grouped by content left on the subject.\n  \"\"\"\n  reactionGroups: [ReactionGroup!]\n\n  \"\"\"\n  A list of Reactions left on the Issue.\n  \"\"\"\n  reactions(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Allows filtering Reactions by emoji.\n    \"\"\"\n    content: ReactionContent\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Allows specifying the order in which reactions are returned.\n    \"\"\"\n    orderBy: ReactionOrder\n  ): ReactionConnection!\n\n  \"\"\"\n  The comment this is a reply to.\n  \"\"\"\n  replyTo: PullRequestReviewComment\n\n  \"\"\"\n  The repository associated with this node.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The HTTP path permalink for this review comment.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Identifies the state of the comment.\n  \"\"\"\n  state: PullRequestReviewCommentState!\n\n  \"\"\"\n  Identifies when the comment was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL permalink for this review comment.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  A list of edits to this content.\n  \"\"\"\n  userContentEdits(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserContentEditConnection\n\n  \"\"\"\n  Check if the current viewer can delete this object.\n  \"\"\"\n  viewerCanDelete: Boolean!\n\n  \"\"\"\n  Check if the current viewer can minimize this object.\n  \"\"\"\n  viewerCanMinimize: Boolean!\n\n  \"\"\"\n  Can user react to this subject\n  \"\"\"\n  viewerCanReact: Boolean!\n\n  \"\"\"\n  Check if the current viewer can update this object.\n  \"\"\"\n  viewerCanUpdate: Boolean!\n\n  \"\"\"\n  Reasons why the current viewer can not update this comment.\n  \"\"\"\n  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!\n\n  \"\"\"\n  Did the viewer author this comment.\n  \"\"\"\n  viewerDidAuthor: Boolean!\n}\n\n\"\"\"\nThe connection type for PullRequestReviewComment.\n\"\"\"\ntype PullRequestReviewCommentConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [PullRequestReviewCommentEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [PullRequestReviewComment]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype PullRequestReviewCommentEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: PullRequestReviewComment\n}\n\n\"\"\"\nThe possible states of a pull request review comment.\n\"\"\"\nenum PullRequestReviewCommentState {\n  \"\"\"\n  A comment that is part of a pending review\n  \"\"\"\n  PENDING\n\n  \"\"\"\n  A comment that is part of a submitted review\n  \"\"\"\n  SUBMITTED\n}\n\n\"\"\"\nThe connection type for PullRequestReview.\n\"\"\"\ntype PullRequestReviewConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [PullRequestReviewEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [PullRequestReview]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype PullRequestReviewEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: PullRequestReview\n}\n\n\"\"\"\nThe possible events to perform on a pull request review.\n\"\"\"\nenum PullRequestReviewEvent {\n  \"\"\"\n  Submit feedback and approve merging these changes.\n  \"\"\"\n  APPROVE\n\n  \"\"\"\n  Submit general feedback without explicit approval.\n  \"\"\"\n  COMMENT\n\n  \"\"\"\n  Dismiss review so it now longer effects merging.\n  \"\"\"\n  DISMISS\n\n  \"\"\"\n  Submit feedback that must be addressed before merging.\n  \"\"\"\n  REQUEST_CHANGES\n}\n\n\"\"\"\nThe possible states of a pull request review.\n\"\"\"\nenum PullRequestReviewState {\n  \"\"\"\n  A review allowing the pull request to merge.\n  \"\"\"\n  APPROVED\n\n  \"\"\"\n  A review blocking the pull request from merging.\n  \"\"\"\n  CHANGES_REQUESTED\n\n  \"\"\"\n  An informational review.\n  \"\"\"\n  COMMENTED\n\n  \"\"\"\n  A review that has been dismissed.\n  \"\"\"\n  DISMISSED\n\n  \"\"\"\n  A review that has not yet been submitted.\n  \"\"\"\n  PENDING\n}\n\n\"\"\"\nA threaded list of comments for a given pull request.\n\"\"\"\ntype PullRequestReviewThread implements Node {\n  \"\"\"\n  A list of pull request comments associated with the thread.\n  \"\"\"\n  comments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): PullRequestReviewCommentConnection!\n  id: ID!\n\n  \"\"\"\n  Whether this thread has been resolved\n  \"\"\"\n  isResolved: Boolean! @preview(toggledBy: \"cateye-preview\")\n\n  \"\"\"\n  Identifies the pull request associated with this thread.\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  Identifies the repository associated with this thread.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The user who resolved this thread\n  \"\"\"\n  resolvedBy: User @preview(toggledBy: \"cateye-preview\")\n\n  \"\"\"\n  Whether or not the viewer can resolve this thread\n  \"\"\"\n  viewerCanResolve: Boolean! @preview(toggledBy: \"cateye-preview\")\n\n  \"\"\"\n  Whether or not the viewer can unresolve this thread\n  \"\"\"\n  viewerCanUnresolve: Boolean! @preview(toggledBy: \"cateye-preview\")\n}\n\n\"\"\"\nReview comment threads for a pull request review.\n\"\"\"\ntype PullRequestReviewThreadConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [PullRequestReviewThreadEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [PullRequestReviewThread]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype PullRequestReviewThreadEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: PullRequestReviewThread\n}\n\n\"\"\"\nRepresents the latest point in the pull request timeline for which the viewer has seen the pull request's commits.\n\"\"\"\ntype PullRequestRevisionMarker @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  The last commit the viewer has seen.\n  \"\"\"\n  lastSeenCommit: Commit!\n\n  \"\"\"\n  The pull request to which the marker belongs.\n  \"\"\"\n  pullRequest: PullRequest!\n}\n\n\"\"\"\nThe possible states of a pull request.\n\"\"\"\nenum PullRequestState {\n  \"\"\"\n  A pull request that has been closed without being merged.\n  \"\"\"\n  CLOSED\n\n  \"\"\"\n  A pull request that has been closed by being merged.\n  \"\"\"\n  MERGED\n\n  \"\"\"\n  A pull request that is still open.\n  \"\"\"\n  OPEN\n}\n\n\"\"\"\nThe connection type for PullRequestTimelineItem.\n\"\"\"\ntype PullRequestTimelineConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [PullRequestTimelineItemEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [PullRequestTimelineItem]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn item in an pull request timeline\n\"\"\"\nunion PullRequestTimelineItem = AssignedEvent | BaseRefForcePushedEvent | ClosedEvent | Commit | CommitCommentThread | CrossReferencedEvent | DemilestonedEvent | DeployedEvent | DeploymentEnvironmentChangedEvent | HeadRefDeletedEvent | HeadRefForcePushedEvent | HeadRefRestoredEvent | IssueComment | LabeledEvent | LockedEvent | MergedEvent | MilestonedEvent | PullRequestReview | PullRequestReviewComment | PullRequestReviewThread | ReferencedEvent | RenamedTitleEvent | ReopenedEvent | ReviewDismissedEvent | ReviewRequestRemovedEvent | ReviewRequestedEvent | SubscribedEvent | UnassignedEvent | UnlabeledEvent | UnlockedEvent | UnsubscribedEvent\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype PullRequestTimelineItemEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: PullRequestTimelineItem\n}\n\n\"\"\"\nAn item in a pull request timeline\n\"\"\"\nunion PullRequestTimelineItems = AddedToProjectEvent | AssignedEvent | BaseRefChangedEvent | BaseRefForcePushedEvent | ClosedEvent | CommentDeletedEvent | ConvertedNoteToIssueEvent | CrossReferencedEvent | DemilestonedEvent | DeployedEvent | DeploymentEnvironmentChangedEvent | HeadRefDeletedEvent | HeadRefForcePushedEvent | HeadRefRestoredEvent | IssueComment | LabeledEvent | LockedEvent | MentionedEvent | MergedEvent | MilestonedEvent | MovedColumnsInProjectEvent | PinnedEvent | PullRequestCommit | PullRequestCommitCommentThread | PullRequestReview | PullRequestReviewThread | PullRequestRevisionMarker | ReferencedEvent | RemovedFromProjectEvent | RenamedTitleEvent | ReopenedEvent | ReviewDismissedEvent | ReviewRequestRemovedEvent | ReviewRequestedEvent | SubscribedEvent | TransferredEvent | UnassignedEvent | UnlabeledEvent | UnlockedEvent | UnpinnedEvent | UnsubscribedEvent\n\n\"\"\"\nThe connection type for PullRequestTimelineItems.\n\"\"\"\ntype PullRequestTimelineItemsConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [PullRequestTimelineItemsEdge]\n\n  \"\"\"\n  Identifies the count of items after applying `before` and `after` filters.\n  \"\"\"\n  filteredCount: Int!\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [PullRequestTimelineItems]\n\n  \"\"\"\n  Identifies the count of items after applying `before`/`after` filters and `first`/`last`/`skip` slicing.\n  \"\"\"\n  pageCount: Int!\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n\n  \"\"\"\n  Identifies the date and time when the timeline was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype PullRequestTimelineItemsEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: PullRequestTimelineItems\n}\n\n\"\"\"\nThe possible item types found in a timeline.\n\"\"\"\nenum PullRequestTimelineItemsItemType {\n  \"\"\"\n  Represents a 'added_to_project' event on a given issue or pull request.\n  \"\"\"\n  ADDED_TO_PROJECT_EVENT\n\n  \"\"\"\n  Represents an 'assigned' event on any assignable object.\n  \"\"\"\n  ASSIGNED_EVENT\n\n  \"\"\"\n  Represents a 'base_ref_changed' event on a given issue or pull request.\n  \"\"\"\n  BASE_REF_CHANGED_EVENT\n\n  \"\"\"\n  Represents a 'base_ref_force_pushed' event on a given pull request.\n  \"\"\"\n  BASE_REF_FORCE_PUSHED_EVENT\n\n  \"\"\"\n  Represents a 'closed' event on any `Closable`.\n  \"\"\"\n  CLOSED_EVENT\n\n  \"\"\"\n  Represents a 'comment_deleted' event on a given issue or pull request.\n  \"\"\"\n  COMMENT_DELETED_EVENT\n\n  \"\"\"\n  Represents a 'converted_note_to_issue' event on a given issue or pull request.\n  \"\"\"\n  CONVERTED_NOTE_TO_ISSUE_EVENT\n\n  \"\"\"\n  Represents a mention made by one issue or pull request to another.\n  \"\"\"\n  CROSS_REFERENCED_EVENT\n\n  \"\"\"\n  Represents a 'demilestoned' event on a given issue or pull request.\n  \"\"\"\n  DEMILESTONED_EVENT\n\n  \"\"\"\n  Represents a 'deployed' event on a given pull request.\n  \"\"\"\n  DEPLOYED_EVENT\n\n  \"\"\"\n  Represents a 'deployment_environment_changed' event on a given pull request.\n  \"\"\"\n  DEPLOYMENT_ENVIRONMENT_CHANGED_EVENT\n\n  \"\"\"\n  Represents a 'head_ref_deleted' event on a given pull request.\n  \"\"\"\n  HEAD_REF_DELETED_EVENT\n\n  \"\"\"\n  Represents a 'head_ref_force_pushed' event on a given pull request.\n  \"\"\"\n  HEAD_REF_FORCE_PUSHED_EVENT\n\n  \"\"\"\n  Represents a 'head_ref_restored' event on a given pull request.\n  \"\"\"\n  HEAD_REF_RESTORED_EVENT\n\n  \"\"\"\n  Represents a comment on an Issue.\n  \"\"\"\n  ISSUE_COMMENT\n\n  \"\"\"\n  Represents a 'labeled' event on a given issue or pull request.\n  \"\"\"\n  LABELED_EVENT\n\n  \"\"\"\n  Represents a 'locked' event on a given issue or pull request.\n  \"\"\"\n  LOCKED_EVENT\n\n  \"\"\"\n  Represents a 'mentioned' event on a given issue or pull request.\n  \"\"\"\n  MENTIONED_EVENT\n\n  \"\"\"\n  Represents a 'merged' event on a given pull request.\n  \"\"\"\n  MERGED_EVENT\n\n  \"\"\"\n  Represents a 'milestoned' event on a given issue or pull request.\n  \"\"\"\n  MILESTONED_EVENT\n\n  \"\"\"\n  Represents a 'moved_columns_in_project' event on a given issue or pull request.\n  \"\"\"\n  MOVED_COLUMNS_IN_PROJECT_EVENT\n\n  \"\"\"\n  Represents a 'pinned' event on a given issue or pull request.\n  \"\"\"\n  PINNED_EVENT\n\n  \"\"\"\n  Represents a Git commit part of a pull request.\n  \"\"\"\n  PULL_REQUEST_COMMIT\n\n  \"\"\"\n  Represents a commit comment thread part of a pull request.\n  \"\"\"\n  PULL_REQUEST_COMMIT_COMMENT_THREAD\n\n  \"\"\"\n  A review object for a given pull request.\n  \"\"\"\n  PULL_REQUEST_REVIEW\n\n  \"\"\"\n  A threaded list of comments for a given pull request.\n  \"\"\"\n  PULL_REQUEST_REVIEW_THREAD\n\n  \"\"\"\n  Represents the latest point in the pull request timeline for which the viewer has seen the pull request's commits.\n  \"\"\"\n  PULL_REQUEST_REVISION_MARKER\n\n  \"\"\"\n  Represents a 'referenced' event on a given `ReferencedSubject`.\n  \"\"\"\n  REFERENCED_EVENT\n\n  \"\"\"\n  Represents a 'removed_from_project' event on a given issue or pull request.\n  \"\"\"\n  REMOVED_FROM_PROJECT_EVENT\n\n  \"\"\"\n  Represents a 'renamed' event on a given issue or pull request\n  \"\"\"\n  RENAMED_TITLE_EVENT\n\n  \"\"\"\n  Represents a 'reopened' event on any `Closable`.\n  \"\"\"\n  REOPENED_EVENT\n\n  \"\"\"\n  Represents a 'review_dismissed' event on a given issue or pull request.\n  \"\"\"\n  REVIEW_DISMISSED_EVENT\n\n  \"\"\"\n  Represents an 'review_requested' event on a given pull request.\n  \"\"\"\n  REVIEW_REQUESTED_EVENT\n\n  \"\"\"\n  Represents an 'review_request_removed' event on a given pull request.\n  \"\"\"\n  REVIEW_REQUEST_REMOVED_EVENT\n\n  \"\"\"\n  Represents a 'subscribed' event on a given `Subscribable`.\n  \"\"\"\n  SUBSCRIBED_EVENT\n\n  \"\"\"\n  Represents a 'transferred' event on a given issue or pull request.\n  \"\"\"\n  TRANSFERRED_EVENT\n\n  \"\"\"\n  Represents an 'unassigned' event on any assignable object.\n  \"\"\"\n  UNASSIGNED_EVENT\n\n  \"\"\"\n  Represents an 'unlabeled' event on a given issue or pull request.\n  \"\"\"\n  UNLABELED_EVENT\n\n  \"\"\"\n  Represents an 'unlocked' event on a given issue or pull request.\n  \"\"\"\n  UNLOCKED_EVENT\n\n  \"\"\"\n  Represents an 'unpinned' event on a given issue or pull request.\n  \"\"\"\n  UNPINNED_EVENT\n\n  \"\"\"\n  Represents an 'unsubscribed' event on a given `Subscribable`.\n  \"\"\"\n  UNSUBSCRIBED_EVENT\n}\n\n\"\"\"\nA Git push.\n\"\"\"\ntype Push implements Node @preview(toggledBy: \"antiope-preview\") {\n  id: ID!\n\n  \"\"\"\n  The SHA after the push\n  \"\"\"\n  nextSha: GitObjectID\n\n  \"\"\"\n  The permalink for this push.\n  \"\"\"\n  permalink: URI!\n\n  \"\"\"\n  The SHA before the push\n  \"\"\"\n  previousSha: GitObjectID\n\n  \"\"\"\n  The user who pushed\n  \"\"\"\n  pusher: User!\n\n  \"\"\"\n  The repository that was pushed to\n  \"\"\"\n  repository: Repository!\n}\n\n\"\"\"\nA team or user who has the ability to push to a protected branch.\n\"\"\"\ntype PushAllowance implements Node {\n  \"\"\"\n  The actor that can push.\n  \"\"\"\n  actor: PushAllowanceActor\n\n  \"\"\"\n  Identifies the branch protection rule associated with the allowed user or team.\n  \"\"\"\n  branchProtectionRule: BranchProtectionRule\n  id: ID!\n}\n\n\"\"\"\nTypes that can be an actor.\n\"\"\"\nunion PushAllowanceActor = Team | User\n\n\"\"\"\nThe connection type for PushAllowance.\n\"\"\"\ntype PushAllowanceConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [PushAllowanceEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [PushAllowance]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype PushAllowanceEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: PushAllowance\n}\n\n\"\"\"\nThe query root of GitHub's GraphQL interface.\n\"\"\"\ntype Query {\n  \"\"\"\n  Look up a business by URL slug.\n  \"\"\"\n  business(\n    \"\"\"\n    The business invitation token\n    \"\"\"\n    invitationToken: String\n\n    \"\"\"\n    The business URL slug.\n    \"\"\"\n    slug: String!\n  ): Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Look up a pending business member invitation by invitee, business and role.\n  \"\"\"\n  businessMemberInvitation(\n    \"\"\"\n    The slug of the business the user was invited to join\n    \"\"\"\n    businessSlug: String!\n\n    \"\"\"\n    The role for the business member invitation.\n    \"\"\"\n    role: BusinessMemberInvitationRole!\n\n    \"\"\"\n    The login of the user invited to join the business\n    \"\"\"\n    userLogin: String!\n  ): BusinessMemberInvitation @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Look up a pending business member invitation by invitation token\n  \"\"\"\n  businessMemberInvitationByToken(\n    \"\"\"\n    The invitation token sent with the invitation email.\n    \"\"\"\n    invitationToken: String!\n  ): BusinessMemberInvitation @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  Look up a code of conduct by its key\n  \"\"\"\n  codeOfConduct(\n    \"\"\"\n    The code of conduct's key\n    \"\"\"\n    key: String!\n  ): CodeOfConduct\n\n  \"\"\"\n  Look up a code of conduct by its key\n  \"\"\"\n  codesOfConduct: [CodeOfConduct]\n\n  \"\"\"\n  Look up an open source license by its key\n  \"\"\"\n  license(\n    \"\"\"\n    The license's downcased SPDX ID\n    \"\"\"\n    key: String!\n  ): License\n\n  \"\"\"\n  Return a list of known open source licenses\n  \"\"\"\n  licenses: [License]!\n\n  \"\"\"\n  Get alphabetically sorted list of Marketplace categories\n  \"\"\"\n  marketplaceCategories(\n    \"\"\"\n    Exclude categories with no listings.\n    \"\"\"\n    excludeEmpty: Boolean\n\n    \"\"\"\n    Returns top level categories only, excluding any subcategories.\n    \"\"\"\n    excludeSubcategories: Boolean\n\n    \"\"\"\n    Return only the specified categories.\n    \"\"\"\n    includeCategories: [String!]\n  ): [MarketplaceCategory!]!\n\n  \"\"\"\n  Look up a Marketplace category by its slug.\n  \"\"\"\n  marketplaceCategory(\n    \"\"\"\n    The URL slug of the category.\n    \"\"\"\n    slug: String!\n\n    \"\"\"\n    Also check topic aliases for the category slug\n    \"\"\"\n    useTopicAliases: Boolean\n  ): MarketplaceCategory\n\n  \"\"\"\n  Look up a single Marketplace listing\n  \"\"\"\n  marketplaceListing(\n    \"\"\"\n    Select the listing that matches this slug. It's the short name of the listing used in its URL.\n    \"\"\"\n    slug: String!\n  ): MarketplaceListing\n\n  \"\"\"\n  Look up Marketplace listings\n  \"\"\"\n  marketplaceListings(\n    \"\"\"\n    Select listings that can be administered by the specified user.\n    \"\"\"\n    adminId: ID\n\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Select listings visible to the viewer even if they are not approved. If omitted or\n    false, only approved listings will be returned.\n    \"\"\"\n    allStates: Boolean\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Select only listings with the given category.\n    \"\"\"\n    categorySlug: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Select listings for products owned by the specified organization.\n    \"\"\"\n    organizationId: ID\n\n    \"\"\"\n    Select only listings where the primary category matches the given category slug.\n    \"\"\"\n    primaryCategoryOnly: Boolean = false\n\n    \"\"\"\n    Select the listings with these slugs, if they are visible to the viewer.\n    \"\"\"\n    slugs: [String]\n\n    \"\"\"\n    Also check topic aliases for the category slug\n    \"\"\"\n    useTopicAliases: Boolean\n\n    \"\"\"\n    Select listings to which user has admin access. If omitted, listings visible to the\n    viewer are returned.\n    \"\"\"\n    viewerCanAdmin: Boolean\n\n    \"\"\"\n    Select only listings that offer a free trial.\n    \"\"\"\n    withFreeTrialsOnly: Boolean = false\n  ): MarketplaceListingConnection!\n\n  \"\"\"\n  Return information about the GitHub instance\n  \"\"\"\n  meta: GitHubMetadata!\n\n  \"\"\"\n  Fetches an object given its ID.\n  \"\"\"\n  node(\n    \"\"\"\n    ID of the object.\n    \"\"\"\n    id: ID!\n  ): Node\n\n  \"\"\"\n  Lookup nodes by a list of IDs.\n  \"\"\"\n  nodes(\n    \"\"\"\n    The list of node IDs.\n    \"\"\"\n    ids: [ID!]!\n  ): [Node]!\n\n  \"\"\"\n  Lookup a organization by login.\n  \"\"\"\n  organization(\n    \"\"\"\n    The organization's login.\n    \"\"\"\n    login: String!\n  ): Organization\n\n  \"\"\"\n  The client's rate limit information.\n  \"\"\"\n  rateLimit(\n    \"\"\"\n    If true, calculate the cost for the query without evaluating it\n    \"\"\"\n    dryRun: Boolean = false\n  ): RateLimit\n\n  \"\"\"\n  Hack to workaround https://github.com/facebook/relay/issues/112 re-exposing the root query object\n  \"\"\"\n  relay: Query!\n\n  \"\"\"\n  Lookup a given repository by the owner and repository name.\n  \"\"\"\n  repository(\n    \"\"\"\n    The name of the repository\n    \"\"\"\n    name: String!\n\n    \"\"\"\n    The login field of a user or organization\n    \"\"\"\n    owner: String!\n  ): Repository\n\n  \"\"\"\n  Lookup a repository owner (ie. either a User or an Organization) by login.\n  \"\"\"\n  repositoryOwner(\n    \"\"\"\n    The username to lookup the owner by.\n    \"\"\"\n    login: String!\n  ): RepositoryOwner\n\n  \"\"\"\n  Lookup resource by a URL.\n  \"\"\"\n  resource(\n    \"\"\"\n    The URL.\n    \"\"\"\n    url: URI!\n  ): UniformResourceLocatable\n\n  \"\"\"\n  Perform a search across resources.\n  \"\"\"\n  search(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    The search string to look for.\n    \"\"\"\n    query: String!\n\n    \"\"\"\n    The types of search items to search within.\n    \"\"\"\n    type: SearchType!\n  ): SearchResultItemConnection!\n\n  \"\"\"\n  GitHub Security Advisories\n  \"\"\"\n  securityAdvisories(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Filter advisories by identifier, e.g. GHSA or CVE.\n    \"\"\"\n    identifier: SecurityAdvisoryIdentifierFilter\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for the returned topics.\n    \"\"\"\n    orderBy: SecurityAdvisoryOrder = {field: UPDATED_AT, direction: DESC}\n\n    \"\"\"\n    Filter advisories to those published since a time in the past.\n    \"\"\"\n    publishedSince: DateTime\n\n    \"\"\"\n    Filter advisories to those updated since a time in the past.\n    \"\"\"\n    updatedSince: DateTime\n  ): SecurityAdvisoryConnection!\n\n  \"\"\"\n  Fetch a Security Advisory by its GHSA ID\n  \"\"\"\n  securityAdvisory(\n    \"\"\"\n    GitHub Security Advisory ID.\n    \"\"\"\n    ghsaId: String!\n  ): SecurityAdvisory\n\n  \"\"\"\n  Software Vulnerabilities documented by GitHub Security Advisories\n  \"\"\"\n  securityVulnerabilities(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    An ecosystem to filter vulnerabilities by.\n    \"\"\"\n    ecosystem: SecurityAdvisoryEcosystem\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for the returned topics.\n    \"\"\"\n    orderBy: SecurityVulnerabilityOrder = {field: UPDATED_AT, direction: DESC}\n\n    \"\"\"\n    A package name to filter vulnerabilities by.\n    \"\"\"\n    package: String\n\n    \"\"\"\n    A list of severities to filter vulnerabilities by.\n    \"\"\"\n    severities: [SecurityAdvisorySeverity!]\n  ): SecurityVulnerabilityConnection!\n\n  \"\"\"\n  Look up a topic by name.\n  \"\"\"\n  topic(\n    \"\"\"\n    The topic's name.\n    \"\"\"\n    name: String!\n  ): Topic\n\n  \"\"\"\n  Lookup a user by login.\n  \"\"\"\n  user(\n    \"\"\"\n    The user's login.\n    \"\"\"\n    login: String!\n  ): User\n\n  \"\"\"\n  The currently authenticated user.\n  \"\"\"\n  viewer: User!\n}\n\n\"\"\"\nRepresents the client's rate limit.\n\"\"\"\ntype RateLimit {\n  \"\"\"\n  The point cost for the current query counting against the rate limit.\n  \"\"\"\n  cost: Int!\n\n  \"\"\"\n  The maximum number of points the client is permitted to consume in a 60 minute window.\n  \"\"\"\n  limit: Int!\n\n  \"\"\"\n  The maximum number of nodes this query may return\n  \"\"\"\n  nodeCount: Int!\n\n  \"\"\"\n  The number of points remaining in the current rate limit window.\n  \"\"\"\n  remaining: Int!\n\n  \"\"\"\n  The time at which the current rate limit window resets in UTC epoch seconds.\n  \"\"\"\n  resetAt: DateTime!\n}\n\n\"\"\"\nRepresents a subject that can be reacted on.\n\"\"\"\ninterface Reactable {\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  A list of reactions grouped by content left on the subject.\n  \"\"\"\n  reactionGroups: [ReactionGroup!]\n\n  \"\"\"\n  A list of Reactions left on the Issue.\n  \"\"\"\n  reactions(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Allows filtering Reactions by emoji.\n    \"\"\"\n    content: ReactionContent\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Allows specifying the order in which reactions are returned.\n    \"\"\"\n    orderBy: ReactionOrder\n  ): ReactionConnection!\n\n  \"\"\"\n  Can user react to this subject\n  \"\"\"\n  viewerCanReact: Boolean!\n}\n\n\"\"\"\nThe connection type for User.\n\"\"\"\ntype ReactingUserConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [ReactingUserEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [User]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nRepresents a user that's made a reaction.\n\"\"\"\ntype ReactingUserEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n  node: User!\n\n  \"\"\"\n  The moment when the user made the reaction.\n  \"\"\"\n  reactedAt: DateTime!\n}\n\n\"\"\"\nAn emoji reaction to a particular piece of content.\n\"\"\"\ntype Reaction implements Node {\n  \"\"\"\n  Identifies the emoji reaction.\n  \"\"\"\n  content: ReactionContent!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  The reactable piece of content\n  \"\"\"\n  reactable: Reactable!\n\n  \"\"\"\n  Identifies the user who created this reaction.\n  \"\"\"\n  user: User\n}\n\n\"\"\"\nA list of reactions that have been left on the subject.\n\"\"\"\ntype ReactionConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [ReactionEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Reaction]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n\n  \"\"\"\n  Whether or not the authenticated user has left a reaction on the subject.\n  \"\"\"\n  viewerHasReacted: Boolean!\n}\n\n\"\"\"\nEmojis that can be attached to Issues, Pull Requests and Comments.\n\"\"\"\nenum ReactionContent {\n  \"\"\"\n  Represents the 😕 emoji.\n  \"\"\"\n  CONFUSED\n\n  \"\"\"\n  Represents the 👀 emoji.\n  \"\"\"\n  EYES\n\n  \"\"\"\n  Represents the ❤️ emoji.\n  \"\"\"\n  HEART\n\n  \"\"\"\n  Represents the 🎉 emoji.\n  \"\"\"\n  HOORAY\n\n  \"\"\"\n  Represents the 😄 emoji.\n  \"\"\"\n  LAUGH\n\n  \"\"\"\n  Represents the 🚀 emoji.\n  \"\"\"\n  ROCKET\n\n  \"\"\"\n  Represents the 👎 emoji.\n  \"\"\"\n  THUMBS_DOWN\n\n  \"\"\"\n  Represents the 👍 emoji.\n  \"\"\"\n  THUMBS_UP\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype ReactionEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Reaction\n}\n\n\"\"\"\nA group of emoji reactions to a particular piece of content.\n\"\"\"\ntype ReactionGroup {\n  \"\"\"\n  Identifies the emoji reaction.\n  \"\"\"\n  content: ReactionContent!\n\n  \"\"\"\n  Identifies when the reaction was created.\n  \"\"\"\n  createdAt: DateTime\n\n  \"\"\"\n  The subject that was reacted to.\n  \"\"\"\n  subject: Reactable!\n\n  \"\"\"\n  Users who have reacted to the reaction subject with the emotion represented by this reaction group\n  \"\"\"\n  users(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): ReactingUserConnection!\n\n  \"\"\"\n  Whether or not the authenticated user has left a reaction on the subject.\n  \"\"\"\n  viewerHasReacted: Boolean!\n}\n\n\"\"\"\nWays in which lists of reactions can be ordered upon return.\n\"\"\"\ninput ReactionOrder {\n  \"\"\"\n  The direction in which to order reactions by the specified field.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field in which to order reactions by.\n  \"\"\"\n  field: ReactionOrderField!\n}\n\n\"\"\"\nA list of fields that reactions can be ordered by.\n\"\"\"\nenum ReactionOrderField {\n  \"\"\"\n  Allows ordering a list of reactions by when they were created.\n  \"\"\"\n  CREATED_AT\n}\n\n\"\"\"\nRepresents a Git reference.\n\"\"\"\ntype Ref implements Node {\n  \"\"\"\n  A list of pull requests with this ref as the head ref.\n  \"\"\"\n  associatedPullRequests(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    The base ref name to filter the pull requests by.\n    \"\"\"\n    baseRefName: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    The head ref name to filter the pull requests by.\n    \"\"\"\n    headRefName: String\n\n    \"\"\"\n    A list of label names to filter the pull requests by.\n    \"\"\"\n    labels: [String!]\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for pull requests returned from the connection.\n    \"\"\"\n    orderBy: IssueOrder\n\n    \"\"\"\n    A list of states to filter the pull requests by.\n    \"\"\"\n    states: [PullRequestState!]\n  ): PullRequestConnection!\n  id: ID!\n\n  \"\"\"\n  The ref name.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The ref's prefix, such as `refs/heads/` or `refs/tags/`.\n  \"\"\"\n  prefix: String!\n\n  \"\"\"\n  The repository the ref belongs to.\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The object the ref points to.\n  \"\"\"\n  target: GitObject!\n}\n\n\"\"\"\nThe connection type for Ref.\n\"\"\"\ntype RefConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [RefEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Ref]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype RefEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Ref\n}\n\n\"\"\"\nWays in which lists of git refs can be ordered upon return.\n\"\"\"\ninput RefOrder {\n  \"\"\"\n  The direction in which to order refs by the specified field.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field in which to order refs by.\n  \"\"\"\n  field: RefOrderField!\n}\n\n\"\"\"\nProperties by which ref connections can be ordered.\n\"\"\"\nenum RefOrderField {\n  \"\"\"\n  Order refs by their alphanumeric name\n  \"\"\"\n  ALPHABETICAL\n\n  \"\"\"\n  Order refs by underlying commit date if the ref prefix is refs/tags/\n  \"\"\"\n  TAG_COMMIT_DATE\n}\n\n\"\"\"\nRepresents a 'referenced' event on a given `ReferencedSubject`.\n\"\"\"\ntype ReferencedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the commit associated with the 'referenced' event.\n  \"\"\"\n  commit: Commit\n\n  \"\"\"\n  Identifies the repository associated with the 'referenced' event.\n  \"\"\"\n  commitRepository: Repository!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Reference originated in a different repository.\n  \"\"\"\n  isCrossRepository: Boolean!\n\n  \"\"\"\n  Checks if the commit message itself references the subject. Can be false in the case of a commit comment reference.\n  \"\"\"\n  isDirectReference: Boolean!\n\n  \"\"\"\n  Object referenced by event.\n  \"\"\"\n  subject: ReferencedSubject!\n}\n\n\"\"\"\nAny referencable object\n\"\"\"\nunion ReferencedSubject = Issue | PullRequest\n\n\"\"\"\nRepresents an owner of a registry package.\n\"\"\"\ninterface RegistryPackageOwner {\n  id: ID!\n}\n\n\"\"\"\nRepresents an interface to search packages on an object.\n\"\"\"\ninterface RegistryPackageSearch {\n  id: ID!\n}\n\n\"\"\"\nA release contains the content for a release.\n\"\"\"\ntype Release implements Node & UniformResourceLocatable {\n  \"\"\"\n  The author of the release\n  \"\"\"\n  author: User\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the description of the release.\n  \"\"\"\n  description: String\n  id: ID!\n\n  \"\"\"\n  Whether or not the release is a draft\n  \"\"\"\n  isDraft: Boolean!\n\n  \"\"\"\n  Whether or not the release is a prerelease\n  \"\"\"\n  isPrerelease: Boolean!\n\n  \"\"\"\n  Identifies the title of the release.\n  \"\"\"\n  name: String\n\n  \"\"\"\n  Identifies the date and time when the release was created.\n  \"\"\"\n  publishedAt: DateTime\n\n  \"\"\"\n  List of releases assets which are dependent on this release.\n  \"\"\"\n  releaseAssets(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    A list of names to filter the assets by.\n    \"\"\"\n    name: String\n  ): ReleaseAssetConnection!\n\n  \"\"\"\n  The HTTP path for this issue\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The Git tag the release points to\n  \"\"\"\n  tag: Ref\n\n  \"\"\"\n  The name of the release's Git tag\n  \"\"\"\n  tagName: String!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this issue\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nA release asset contains the content for a release asset.\n\"\"\"\ntype ReleaseAsset implements Node {\n  \"\"\"\n  The asset's content-type\n  \"\"\"\n  contentType: String!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  The number of times this asset was downloaded\n  \"\"\"\n  downloadCount: Int!\n\n  \"\"\"\n  Identifies the URL where you can download the release asset via the browser.\n  \"\"\"\n  downloadUrl: URI!\n  id: ID!\n\n  \"\"\"\n  Identifies the title of the release asset.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  Release that the asset is associated with\n  \"\"\"\n  release: Release\n\n  \"\"\"\n  The size (in bytes) of the asset\n  \"\"\"\n  size: Int!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The user that performed the upload\n  \"\"\"\n  uploadedBy: User!\n\n  \"\"\"\n  Identifies the URL of the release asset.\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nThe connection type for ReleaseAsset.\n\"\"\"\ntype ReleaseAssetConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [ReleaseAssetEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [ReleaseAsset]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype ReleaseAssetEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: ReleaseAsset\n}\n\n\"\"\"\nThe connection type for Release.\n\"\"\"\ntype ReleaseConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [ReleaseEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Release]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype ReleaseEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Release\n}\n\n\"\"\"\nWays in which lists of releases can be ordered upon return.\n\"\"\"\ninput ReleaseOrder {\n  \"\"\"\n  The direction in which to order releases by the specified field.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field in which to order releases by.\n  \"\"\"\n  field: ReleaseOrderField!\n}\n\n\"\"\"\nProperties by which release connections can be ordered.\n\"\"\"\nenum ReleaseOrderField {\n  \"\"\"\n  Order releases by creation time\n  \"\"\"\n  CREATED_AT\n\n  \"\"\"\n  Order releases alphabetically by name\n  \"\"\"\n  NAME\n}\n\n\"\"\"\nAutogenerated input type of RemoveAssigneesFromAssignable\n\"\"\"\ninput RemoveAssigneesFromAssignableInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  The id of the assignable object to remove assignees from.\n  \"\"\"\n  assignableId: ID! @possibleTypes(concreteTypes: [\"Issue\", \"PullRequest\"], abstractType: \"Assignable\")\n\n  \"\"\"\n  The id of users to remove as assignees.\n  \"\"\"\n  assigneeIds: [ID!]! @possibleTypes(concreteTypes: [\"User\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated return type of RemoveAssigneesFromAssignable\n\"\"\"\ntype RemoveAssigneesFromAssignablePayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  The item that was unassigned.\n  \"\"\"\n  assignable: Assignable\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of RemoveBusinessAdmin\n\"\"\"\ninput RemoveBusinessAdminInput {\n  \"\"\"\n  The Business ID to update.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The login of the user to add as an admin.\n  \"\"\"\n  login: String!\n}\n\n\"\"\"\nAutogenerated return type of RemoveBusinessAdmin\n\"\"\"\ntype RemoveBusinessAdminPayload {\n  \"\"\"\n  The user who was added as an admin.\n  \"\"\"\n  admin: User\n\n  \"\"\"\n  The updated business.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The viewer performing the mutation.\n  \"\"\"\n  viewer: User\n}\n\n\"\"\"\nAutogenerated input type of RemoveBusinessBillingManager\n\"\"\"\ninput RemoveBusinessBillingManagerInput {\n  \"\"\"\n  The Business ID to update.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The login of the user to add as a billing manager.\n  \"\"\"\n  login: String!\n}\n\n\"\"\"\nAutogenerated return type of RemoveBusinessBillingManager\n\"\"\"\ntype RemoveBusinessBillingManagerPayload {\n  \"\"\"\n  The user who was added as a billing manager.\n  \"\"\"\n  billingManager: User\n\n  \"\"\"\n  The updated business.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The viewer performing the mutation.\n  \"\"\"\n  viewer: User\n}\n\n\"\"\"\nAutogenerated input type of RemoveLabelsFromLabelable\n\"\"\"\ninput RemoveLabelsFromLabelableInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ids of labels to remove.\n  \"\"\"\n  labelIds: [ID!]! @possibleTypes(concreteTypes: [\"Label\"])\n\n  \"\"\"\n  The id of the Labelable to remove labels from.\n  \"\"\"\n  labelableId: ID! @possibleTypes(concreteTypes: [\"Issue\", \"PullRequest\"], abstractType: \"Labelable\")\n}\n\n\"\"\"\nAutogenerated return type of RemoveLabelsFromLabelable\n\"\"\"\ntype RemoveLabelsFromLabelablePayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Labelable the labels were removed from.\n  \"\"\"\n  labelable: Labelable\n}\n\n\"\"\"\nAutogenerated input type of RemoveOutsideCollaborator\n\"\"\"\ninput RemoveOutsideCollaboratorInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the organization to remove the outside collaborator from.\n  \"\"\"\n  organizationId: ID! @possibleTypes(concreteTypes: [\"Organization\"])\n\n  \"\"\"\n  The ID of the outside collaborator to remove.\n  \"\"\"\n  userId: ID! @possibleTypes(concreteTypes: [\"User\"])\n}\n\n\"\"\"\nAutogenerated return type of RemoveOutsideCollaborator\n\"\"\"\ntype RemoveOutsideCollaboratorPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The user that was removed as an outside collaborator.\n  \"\"\"\n  removedUser: User\n}\n\n\"\"\"\nAutogenerated input type of RemoveReaction\n\"\"\"\ninput RemoveReactionInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The name of the emoji reaction to remove.\n  \"\"\"\n  content: ReactionContent!\n\n  \"\"\"\n  The Node ID of the subject to modify.\n  \"\"\"\n  subjectId: ID! @possibleTypes(concreteTypes: [\"CommitComment\", \"Issue\", \"IssueComment\", \"PullRequest\", \"PullRequestReview\", \"PullRequestReviewComment\", \"TeamDiscussion\", \"TeamDiscussionComment\"], abstractType: \"Reactable\")\n}\n\n\"\"\"\nAutogenerated return type of RemoveReaction\n\"\"\"\ntype RemoveReactionPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The reaction object.\n  \"\"\"\n  reaction: Reaction\n\n  \"\"\"\n  The reactable subject.\n  \"\"\"\n  subject: Reactable\n}\n\n\"\"\"\nAutogenerated input type of RemoveStar\n\"\"\"\ninput RemoveStarInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Starrable ID to unstar.\n  \"\"\"\n  starrableId: ID! @possibleTypes(concreteTypes: [\"Gist\", \"Repository\", \"Topic\"], abstractType: \"Starrable\")\n}\n\n\"\"\"\nAutogenerated return type of RemoveStar\n\"\"\"\ntype RemoveStarPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The starrable.\n  \"\"\"\n  starrable: Starrable\n}\n\n\"\"\"\nRepresents a 'removed_from_project' event on a given issue or pull request.\n\"\"\"\ntype RemovedFromProjectEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  Project referenced by event.\n  \"\"\"\n  project: Project @preview(toggledBy: \"starfox-preview\")\n\n  \"\"\"\n  Column name referenced by this project event.\n  \"\"\"\n  projectColumnName: String! @preview(toggledBy: \"starfox-preview\")\n}\n\n\"\"\"\nRepresents a 'renamed' event on a given issue or pull request\n\"\"\"\ntype RenamedTitleEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the current title of the issue or pull request.\n  \"\"\"\n  currentTitle: String!\n  id: ID!\n\n  \"\"\"\n  Identifies the previous title of the issue or pull request.\n  \"\"\"\n  previousTitle: String!\n\n  \"\"\"\n  Subject that was renamed.\n  \"\"\"\n  subject: RenamedTitleSubject!\n}\n\n\"\"\"\nAn object which has a renamable title\n\"\"\"\nunion RenamedTitleSubject = Issue | PullRequest\n\n\"\"\"\nAutogenerated input type of ReopenIssue\n\"\"\"\ninput ReopenIssueInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  ID of the issue to be opened.\n  \"\"\"\n  issueId: ID! @possibleTypes(concreteTypes: [\"Issue\"])\n}\n\n\"\"\"\nAutogenerated return type of ReopenIssue\n\"\"\"\ntype ReopenIssuePayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The issue that was opened.\n  \"\"\"\n  issue: Issue\n}\n\n\"\"\"\nAutogenerated input type of ReopenPullRequest\n\"\"\"\ninput ReopenPullRequestInput @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  ID of the pull request to be reopened.\n  \"\"\"\n  pullRequestId: ID! @possibleTypes(concreteTypes: [\"PullRequest\"])\n}\n\n\"\"\"\nAutogenerated return type of ReopenPullRequest\n\"\"\"\ntype ReopenPullRequestPayload @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The pull request that was reopened.\n  \"\"\"\n  pullRequest: PullRequest\n}\n\n\"\"\"\nRepresents a 'reopened' event on any `Closable`.\n\"\"\"\ntype ReopenedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Object that was reopened.\n  \"\"\"\n  closable: Closable!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n}\n\n\"\"\"\nThe reasons a piece of content can be reported or minimized.\n\"\"\"\nenum ReportedContentClassifiers {\n  \"\"\"\n  An abusive or harassing piece of content\n  \"\"\"\n  ABUSE\n\n  \"\"\"\n  An irrelevant piece of content\n  \"\"\"\n  OFF_TOPIC\n\n  \"\"\"\n  An outdated piece of content\n  \"\"\"\n  OUTDATED\n\n  \"\"\"\n  The content has been resolved\n  \"\"\"\n  RESOLVED\n\n  \"\"\"\n  A spammy piece of content\n  \"\"\"\n  SPAM\n}\n\n\"\"\"\nA repository contains the content for a project.\n\"\"\"\ntype Repository implements Node & ProjectOwner & RegistryPackageOwner & RepositoryInfo & Starrable & Subscribable & UniformResourceLocatable {\n  \"\"\"\n  A list of users that can be assigned to issues in this repository.\n  \"\"\"\n  assignableUsers(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserConnection!\n\n  \"\"\"\n  A list of branch protection rules for this repository.\n  \"\"\"\n  branchProtectionRules(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): BranchProtectionRuleConnection!\n\n  \"\"\"\n  Returns the code of conduct for this repository\n  \"\"\"\n  codeOfConduct: CodeOfConduct\n\n  \"\"\"\n  A list of collaborators associated with the repository.\n  \"\"\"\n  collaborators(\n    \"\"\"\n    Collaborators affiliation level with a repository.\n    \"\"\"\n    affiliation: CollaboratorAffiliation\n\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): RepositoryCollaboratorConnection\n\n  \"\"\"\n  A list of commit comments associated with the repository.\n  \"\"\"\n  commitComments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): CommitCommentConnection!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The Ref associated with the repository's default branch.\n  \"\"\"\n  defaultBranchRef: Ref\n\n  \"\"\"\n  A list of dependency manifests contained in the repository\n  \"\"\"\n  dependencyGraphManifests(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Cursor to paginate dependencies\n    \"\"\"\n    dependenciesAfter: String\n\n    \"\"\"\n    Number of dependencies to fetch\n    \"\"\"\n    dependenciesFirst: Int\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Flag to scope to only manifests with dependencies\n    \"\"\"\n    withDependencies: Boolean\n  ): DependencyGraphManifestConnection @preview(toggledBy: \"hawkgirl-preview\")\n\n  \"\"\"\n  A list of deploy keys that are on this repository.\n  \"\"\"\n  deployKeys(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): DeployKeyConnection!\n\n  \"\"\"\n  Deployments associated with the repository\n  \"\"\"\n  deployments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Environments to list deployments for\n    \"\"\"\n    environments: [String!]\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for deployments returned from the connection.\n    \"\"\"\n    orderBy: DeploymentOrder = {field: CREATED_AT, direction: ASC}\n  ): DeploymentConnection!\n\n  \"\"\"\n  The description of the repository.\n  \"\"\"\n  description: String\n\n  \"\"\"\n  The description of the repository rendered to HTML.\n  \"\"\"\n  descriptionHTML: HTML!\n\n  \"\"\"\n  The number of kilobytes this repository occupies on disk.\n  \"\"\"\n  diskUsage: Int\n\n  \"\"\"\n  Returns how many forks there are of this repository in the whole network.\n  \"\"\"\n  forkCount: Int!\n\n  \"\"\"\n  A list of direct forked repositories.\n  \"\"\"\n  forks(\n    \"\"\"\n    Array of viewer's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    current viewer owns.\n    \"\"\"\n    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    If non-null, filters repositories according to whether they have been locked\n    \"\"\"\n    isLocked: Boolean\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for repositories returned from the connection\n    \"\"\"\n    orderBy: RepositoryOrder\n\n    \"\"\"\n    Array of owner's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    organization or user being viewed owns.\n    \"\"\"\n    ownerAffiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    If non-null, filters repositories according to privacy\n    \"\"\"\n    privacy: RepositoryPrivacy\n  ): RepositoryConnection!\n\n  \"\"\"\n  Indicates if the repository has issues feature enabled.\n  \"\"\"\n  hasIssuesEnabled: Boolean!\n\n  \"\"\"\n  Indicates if the repository has wiki feature enabled.\n  \"\"\"\n  hasWikiEnabled: Boolean!\n\n  \"\"\"\n  The repository's URL.\n  \"\"\"\n  homepageUrl: URI\n  id: ID!\n\n  \"\"\"\n  Indicates if the repository is unmaintained.\n  \"\"\"\n  isArchived: Boolean!\n\n  \"\"\"\n  Identifies if the repository is a fork.\n  \"\"\"\n  isFork: Boolean!\n\n  \"\"\"\n  Indicates if the repository has been locked or not.\n  \"\"\"\n  isLocked: Boolean!\n\n  \"\"\"\n  Identifies if the repository is a mirror.\n  \"\"\"\n  isMirror: Boolean!\n\n  \"\"\"\n  Identifies if the repository is private.\n  \"\"\"\n  isPrivate: Boolean!\n\n  \"\"\"\n  Returns a single issue from the current repository by number.\n  \"\"\"\n  issue(\n    \"\"\"\n    The number for the issue to be returned.\n    \"\"\"\n    number: Int!\n  ): Issue\n\n  \"\"\"\n  Returns a single issue-like object from the current repository by number.\n  \"\"\"\n  issueOrPullRequest(\n    \"\"\"\n    The number for the issue to be returned.\n    \"\"\"\n    number: Int!\n  ): IssueOrPullRequest\n\n  \"\"\"\n  A list of issues that have been opened in the repository.\n  \"\"\"\n  issues(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Filtering options for issues returned from the connection.\n    \"\"\"\n    filterBy: IssueFilters @preview(toggledBy: \"starfire-preview\")\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    A list of label names to filter the pull requests by.\n    \"\"\"\n    labels: [String!]\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for issues returned from the connection.\n    \"\"\"\n    orderBy: IssueOrder\n\n    \"\"\"\n    A list of states to filter the issues by.\n    \"\"\"\n    states: [IssueState!]\n  ): IssueConnection!\n\n  \"\"\"\n  Returns a single label by name\n  \"\"\"\n  label(\n    \"\"\"\n    Label name\n    \"\"\"\n    name: String!\n  ): Label\n\n  \"\"\"\n  A list of labels associated with the repository.\n  \"\"\"\n  labels(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    If provided, searches labels by name and description.\n    \"\"\"\n    query: String\n  ): LabelConnection\n\n  \"\"\"\n  A list containing a breakdown of the language composition of the repository.\n  \"\"\"\n  languages(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Order for connection\n    \"\"\"\n    orderBy: LanguageOrder\n  ): LanguageConnection\n\n  \"\"\"\n  The license associated with the repository\n  \"\"\"\n  licenseInfo: License\n\n  \"\"\"\n  The reason the repository has been locked.\n  \"\"\"\n  lockReason: RepositoryLockReason\n\n  \"\"\"\n  A list of Users that can be mentioned in the context of the repository.\n  \"\"\"\n  mentionableUsers(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserConnection!\n\n  \"\"\"\n  Whether or not PRs are merged with a merge commit on this repository.\n  \"\"\"\n  mergeCommitAllowed: Boolean!\n\n  \"\"\"\n  Returns a single milestone from the current repository by number.\n  \"\"\"\n  milestone(\n    \"\"\"\n    The number for the milestone to be returned.\n    \"\"\"\n    number: Int!\n  ): Milestone\n\n  \"\"\"\n  A list of milestones associated with the repository.\n  \"\"\"\n  milestones(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for milestones.\n    \"\"\"\n    orderBy: MilestoneOrder\n\n    \"\"\"\n    Filter by the state of the milestones.\n    \"\"\"\n    states: [MilestoneState!]\n  ): MilestoneConnection\n\n  \"\"\"\n  The repository's original mirror URL.\n  \"\"\"\n  mirrorUrl: URI\n\n  \"\"\"\n  The name of the repository.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The repository's name with owner.\n  \"\"\"\n  nameWithOwner: String!\n\n  \"\"\"\n  A Git object in the repository\n  \"\"\"\n  object(\n    \"\"\"\n    A Git revision expression suitable for rev-parse\n    \"\"\"\n    expression: String\n\n    \"\"\"\n    The Git object ID\n    \"\"\"\n    oid: GitObjectID\n  ): GitObject\n\n  \"\"\"\n  The User owner of the repository.\n  \"\"\"\n  owner: RepositoryOwner!\n\n  \"\"\"\n  The repository parent, if this is a fork.\n  \"\"\"\n  parent: Repository\n\n  \"\"\"\n  A list of pinned issues for this repository.\n  \"\"\"\n  pinnedIssues(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): PinnedIssueConnection @preview(toggledBy: \"elektra-preview\")\n\n  \"\"\"\n  The primary language of the repository's code.\n  \"\"\"\n  primaryLanguage: Language\n\n  \"\"\"\n  Find project by number.\n  \"\"\"\n  project(\n    \"\"\"\n    The project number to find.\n    \"\"\"\n    number: Int!\n  ): Project\n\n  \"\"\"\n  A list of projects under the owner.\n  \"\"\"\n  projects(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for projects returned from the connection\n    \"\"\"\n    orderBy: ProjectOrder\n\n    \"\"\"\n    Query to search projects by, currently only searching by name.\n    \"\"\"\n    search: String\n\n    \"\"\"\n    A list of states to filter the projects by.\n    \"\"\"\n    states: [ProjectState!]\n  ): ProjectConnection!\n\n  \"\"\"\n  The HTTP path listing the repository's projects\n  \"\"\"\n  projectsResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL listing the repository's projects\n  \"\"\"\n  projectsUrl: URI!\n\n  \"\"\"\n  A list of protected branches that are on this repository.\n  \"\"\"\n  protectedBranches(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): ProtectedBranchConnection! @deprecated(reason: \"The `ProtectedBranch` type is deprecated and will be removed soon. Use `Repository.branchProtectionRules` instead. Removal on 2019-01-01 UTC.\")\n\n  \"\"\"\n  Returns a single pull request from the current repository by number.\n  \"\"\"\n  pullRequest(\n    \"\"\"\n    The number for the pull request to be returned.\n    \"\"\"\n    number: Int!\n  ): PullRequest\n\n  \"\"\"\n  A list of pull requests that have been opened in the repository.\n  \"\"\"\n  pullRequests(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    The base ref name to filter the pull requests by.\n    \"\"\"\n    baseRefName: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    The head ref name to filter the pull requests by.\n    \"\"\"\n    headRefName: String\n\n    \"\"\"\n    A list of label names to filter the pull requests by.\n    \"\"\"\n    labels: [String!]\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for pull requests returned from the connection.\n    \"\"\"\n    orderBy: IssueOrder\n\n    \"\"\"\n    A list of states to filter the pull requests by.\n    \"\"\"\n    states: [PullRequestState!]\n  ): PullRequestConnection!\n\n  \"\"\"\n  Identifies when the repository was last pushed to.\n  \"\"\"\n  pushedAt: DateTime\n\n  \"\"\"\n  Whether or not rebase-merging is enabled on this repository.\n  \"\"\"\n  rebaseMergeAllowed: Boolean!\n\n  \"\"\"\n  Fetch a given ref from the repository\n  \"\"\"\n  ref(\n    \"\"\"\n    The ref to retrieve. Fully qualified matches are checked in order\n    (`refs/heads/master`) before falling back onto checks for short name matches (`master`).\n    \"\"\"\n    qualifiedName: String!\n  ): Ref\n\n  \"\"\"\n  Fetch a list of refs from the repository\n  \"\"\"\n  refs(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    DEPRECATED: use orderBy. The ordering direction.\n    \"\"\"\n    direction: OrderDirection\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for refs returned from the connection.\n    \"\"\"\n    orderBy: RefOrder\n\n    \"\"\"\n    A ref name prefix like `refs/heads/`, `refs/tags/`, etc.\n    \"\"\"\n    refPrefix: String!\n  ): RefConnection\n\n  \"\"\"\n  Lookup a single release given various criteria.\n  \"\"\"\n  release(\n    \"\"\"\n    The name of the Tag the Release was created from\n    \"\"\"\n    tagName: String!\n  ): Release\n\n  \"\"\"\n  List of releases which are dependent on this repository.\n  \"\"\"\n  releases(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Order for connection\n    \"\"\"\n    orderBy: ReleaseOrder\n  ): ReleaseConnection!\n\n  \"\"\"\n  A list of applied repository-topic associations for this repository.\n  \"\"\"\n  repositoryTopics(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): RepositoryTopicConnection!\n\n  \"\"\"\n  The HTTP path for this repository\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  A description of the repository, rendered to HTML without any links in it.\n  \"\"\"\n  shortDescriptionHTML(\n    \"\"\"\n    How many characters to return.\n    \"\"\"\n    limit: Int = 200\n  ): HTML!\n\n  \"\"\"\n  Whether or not squash-merging is enabled on this repository.\n  \"\"\"\n  squashMergeAllowed: Boolean!\n\n  \"\"\"\n  The SSH URL to clone this repository\n  \"\"\"\n  sshUrl: GitSSHRemote!\n\n  \"\"\"\n  A list of users who have starred this starrable.\n  \"\"\"\n  stargazers(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Order for connection\n    \"\"\"\n    orderBy: StarOrder\n  ): StargazerConnection!\n\n  \"\"\"\n  Temporary authentication token for cloning this repository.\n  \"\"\"\n  tempCloneToken: String @preview(toggledBy: \"daredevil-preview\")\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this repository\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  Indicates whether the viewer has admin permissions on this repository.\n  \"\"\"\n  viewerCanAdminister: Boolean!\n\n  \"\"\"\n  Can the current viewer create new projects on this owner.\n  \"\"\"\n  viewerCanCreateProjects: Boolean!\n\n  \"\"\"\n  Check if the viewer is able to change their subscription status for the repository.\n  \"\"\"\n  viewerCanSubscribe: Boolean!\n\n  \"\"\"\n  Indicates whether the viewer can update the topics of this repository.\n  \"\"\"\n  viewerCanUpdateTopics: Boolean!\n\n  \"\"\"\n  Returns a boolean indicating whether the viewing user has starred this starrable.\n  \"\"\"\n  viewerHasStarred: Boolean!\n\n  \"\"\"\n  The users permission level on the repository. Will return null if authenticated as an GitHub App.\n  \"\"\"\n  viewerPermission: RepositoryPermission\n\n  \"\"\"\n  Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.\n  \"\"\"\n  viewerSubscription: SubscriptionState\n\n  \"\"\"\n  A list of vulnerability alerts that are on this repository.\n  \"\"\"\n  vulnerabilityAlerts(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): RepositoryVulnerabilityAlertConnection @preview(toggledBy: \"vixen-preview\")\n\n  \"\"\"\n  A list of users watching the repository.\n  \"\"\"\n  watchers(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserConnection!\n}\n\n\"\"\"\nThe affiliation of a user to a repository\n\"\"\"\nenum RepositoryAffiliation {\n  \"\"\"\n  Repositories that the user has been added to as a collaborator.\n  \"\"\"\n  COLLABORATOR\n\n  \"\"\"\n  Repositories that the user has access to through being a member of an\n  organization. This includes every repository on every team that the user is on.\n  \"\"\"\n  ORGANIZATION_MEMBER\n\n  \"\"\"\n  Repositories that are owned by the authenticated user.\n  \"\"\"\n  OWNER\n}\n\n\"\"\"\nThe connection type for User.\n\"\"\"\ntype RepositoryCollaboratorConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [RepositoryCollaboratorEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [User]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nRepresents a user who is a collaborator of a repository.\n\"\"\"\ntype RepositoryCollaboratorEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n  node: User!\n\n  \"\"\"\n  The permission the user has on the repository.\n  \"\"\"\n  permission: RepositoryPermission!\n}\n\n\"\"\"\nA list of repositories owned by the subject.\n\"\"\"\ntype RepositoryConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [RepositoryEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Repository]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n\n  \"\"\"\n  The total size in kilobytes of all repositories in the connection.\n  \"\"\"\n  totalDiskUsage: Int!\n}\n\n\"\"\"\nThe reason a repository is listed as 'contributed'.\n\"\"\"\nenum RepositoryContributionType {\n  \"\"\"\n  Created a commit\n  \"\"\"\n  COMMIT\n\n  \"\"\"\n  Created an issue\n  \"\"\"\n  ISSUE\n\n  \"\"\"\n  Created a pull request\n  \"\"\"\n  PULL_REQUEST\n\n  \"\"\"\n  Reviewed a pull request\n  \"\"\"\n  PULL_REQUEST_REVIEW\n\n  \"\"\"\n  Created the repository\n  \"\"\"\n  REPOSITORY\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype RepositoryEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Repository\n}\n\n\"\"\"\nA subset of repository info.\n\"\"\"\ninterface RepositoryInfo {\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  The description of the repository.\n  \"\"\"\n  description: String\n\n  \"\"\"\n  The description of the repository rendered to HTML.\n  \"\"\"\n  descriptionHTML: HTML!\n\n  \"\"\"\n  Returns how many forks there are of this repository in the whole network.\n  \"\"\"\n  forkCount: Int!\n\n  \"\"\"\n  Indicates if the repository has issues feature enabled.\n  \"\"\"\n  hasIssuesEnabled: Boolean!\n\n  \"\"\"\n  Indicates if the repository has wiki feature enabled.\n  \"\"\"\n  hasWikiEnabled: Boolean!\n\n  \"\"\"\n  The repository's URL.\n  \"\"\"\n  homepageUrl: URI\n\n  \"\"\"\n  Indicates if the repository is unmaintained.\n  \"\"\"\n  isArchived: Boolean!\n\n  \"\"\"\n  Identifies if the repository is a fork.\n  \"\"\"\n  isFork: Boolean!\n\n  \"\"\"\n  Indicates if the repository has been locked or not.\n  \"\"\"\n  isLocked: Boolean!\n\n  \"\"\"\n  Identifies if the repository is a mirror.\n  \"\"\"\n  isMirror: Boolean!\n\n  \"\"\"\n  Identifies if the repository is private.\n  \"\"\"\n  isPrivate: Boolean!\n\n  \"\"\"\n  The license associated with the repository\n  \"\"\"\n  licenseInfo: License\n\n  \"\"\"\n  The reason the repository has been locked.\n  \"\"\"\n  lockReason: RepositoryLockReason\n\n  \"\"\"\n  The repository's original mirror URL.\n  \"\"\"\n  mirrorUrl: URI\n\n  \"\"\"\n  The name of the repository.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The repository's name with owner.\n  \"\"\"\n  nameWithOwner: String!\n\n  \"\"\"\n  The User owner of the repository.\n  \"\"\"\n  owner: RepositoryOwner!\n\n  \"\"\"\n  Identifies when the repository was last pushed to.\n  \"\"\"\n  pushedAt: DateTime\n\n  \"\"\"\n  The HTTP path for this repository\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  A description of the repository, rendered to HTML without any links in it.\n  \"\"\"\n  shortDescriptionHTML(\n    \"\"\"\n    How many characters to return.\n    \"\"\"\n    limit: Int = 200\n  ): HTML!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this repository\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nAn invitation for a user to be added to a repository.\n\"\"\"\ntype RepositoryInvitation implements Node {\n  id: ID!\n\n  \"\"\"\n  The user who received the invitation.\n  \"\"\"\n  invitee: User!\n\n  \"\"\"\n  The user who created the invitation.\n  \"\"\"\n  inviter: User!\n\n  \"\"\"\n  The permission granted on this repository by this invitation.\n  \"\"\"\n  permission: RepositoryPermission!\n\n  \"\"\"\n  The Repository the user is invited to.\n  \"\"\"\n  repository: RepositoryInfo\n}\n\n\"\"\"\nThe possible reasons a given repository could be in a locked state.\n\"\"\"\nenum RepositoryLockReason {\n  \"\"\"\n  The repository is locked due to a billing related reason.\n  \"\"\"\n  BILLING\n\n  \"\"\"\n  The repository is locked due to a migration.\n  \"\"\"\n  MIGRATING\n\n  \"\"\"\n  The repository is locked due to a move.\n  \"\"\"\n  MOVING\n\n  \"\"\"\n  The repository is locked due to a rename.\n  \"\"\"\n  RENAME\n}\n\n\"\"\"\nRepresents a object that belongs to a repository.\n\"\"\"\ninterface RepositoryNode {\n  \"\"\"\n  The repository associated with this node.\n  \"\"\"\n  repository: Repository!\n}\n\n\"\"\"\nOrdering options for repository connections\n\"\"\"\ninput RepositoryOrder {\n  \"\"\"\n  The ordering direction.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field to order repositories by.\n  \"\"\"\n  field: RepositoryOrderField!\n}\n\n\"\"\"\nProperties by which repository connections can be ordered.\n\"\"\"\nenum RepositoryOrderField {\n  \"\"\"\n  Order repositories by creation time\n  \"\"\"\n  CREATED_AT\n\n  \"\"\"\n  Order repositories by name\n  \"\"\"\n  NAME\n\n  \"\"\"\n  Order repositories by push time\n  \"\"\"\n  PUSHED_AT\n\n  \"\"\"\n  Order repositories by number of stargazers\n  \"\"\"\n  STARGAZERS\n\n  \"\"\"\n  Order repositories by update time\n  \"\"\"\n  UPDATED_AT\n}\n\n\"\"\"\nRepresents an owner of a Repository.\n\"\"\"\ninterface RepositoryOwner {\n  \"\"\"\n  A URL pointing to the owner's public avatar.\n  \"\"\"\n  avatarUrl(\n    \"\"\"\n    The size of the resulting square image.\n    \"\"\"\n    size: Int\n  ): URI!\n  id: ID!\n\n  \"\"\"\n  The username used to login.\n  \"\"\"\n  login: String!\n\n  \"\"\"\n  A list of repositories this user has pinned to their profile\n  \"\"\"\n  pinnedRepositories(\n    \"\"\"\n    Array of viewer's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    current viewer owns.\n    \"\"\"\n    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    If non-null, filters repositories according to whether they have been locked\n    \"\"\"\n    isLocked: Boolean\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for repositories returned from the connection\n    \"\"\"\n    orderBy: RepositoryOrder\n\n    \"\"\"\n    Array of owner's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    organization or user being viewed owns.\n    \"\"\"\n    ownerAffiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    If non-null, filters repositories according to privacy\n    \"\"\"\n    privacy: RepositoryPrivacy\n  ): RepositoryConnection!\n\n  \"\"\"\n  A list of repositories that the user owns.\n  \"\"\"\n  repositories(\n    \"\"\"\n    Array of viewer's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    current viewer owns.\n    \"\"\"\n    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    If non-null, filters repositories according to whether they are forks of another repository\n    \"\"\"\n    isFork: Boolean\n\n    \"\"\"\n    If non-null, filters repositories according to whether they have been locked\n    \"\"\"\n    isLocked: Boolean\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for repositories returned from the connection\n    \"\"\"\n    orderBy: RepositoryOrder\n\n    \"\"\"\n    Array of owner's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    organization or user being viewed owns.\n    \"\"\"\n    ownerAffiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    If non-null, filters repositories according to privacy\n    \"\"\"\n    privacy: RepositoryPrivacy\n  ): RepositoryConnection!\n\n  \"\"\"\n  Find Repository.\n  \"\"\"\n  repository(\n    \"\"\"\n    Name of Repository to find.\n    \"\"\"\n    name: String!\n  ): Repository\n\n  \"\"\"\n  The HTTP URL for the owner.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for the owner.\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nThe access level to a repository\n\"\"\"\nenum RepositoryPermission {\n  \"\"\"\n  Can read, clone, push, and add collaborators\n  \"\"\"\n  ADMIN\n\n  \"\"\"\n  Can read and clone\n  \"\"\"\n  READ\n\n  \"\"\"\n  Can read, clone and push\n  \"\"\"\n  WRITE\n}\n\n\"\"\"\nThe privacy of a repository\n\"\"\"\nenum RepositoryPrivacy {\n  \"\"\"\n  Private\n  \"\"\"\n  PRIVATE\n\n  \"\"\"\n  Public\n  \"\"\"\n  PUBLIC\n}\n\n\"\"\"\nA repository-topic connects a repository to a topic.\n\"\"\"\ntype RepositoryTopic implements Node & UniformResourceLocatable {\n  id: ID!\n\n  \"\"\"\n  The HTTP path for this repository-topic.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The topic.\n  \"\"\"\n  topic: Topic!\n\n  \"\"\"\n  The HTTP URL for this repository-topic.\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nThe connection type for RepositoryTopic.\n\"\"\"\ntype RepositoryTopicConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [RepositoryTopicEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [RepositoryTopic]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype RepositoryTopicEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: RepositoryTopic\n}\n\n\"\"\"\nA alert for a repository with an affected vulnerability.\n\"\"\"\ntype RepositoryVulnerabilityAlert implements Node & RepositoryNode @preview(toggledBy: \"vixen-preview\") {\n  \"\"\"\n  The affected version\n  \"\"\"\n  affectedRange: String! @deprecated(reason: \"advisory specific fields are being removed from repositoryVulnerabilityAlert objects Use `securityVulnerability.vulnerableVersionRange` instead. Removal on 2019-07-01 UTC.\")\n\n  \"\"\"\n  The reason the alert was dismissed\n  \"\"\"\n  dismissReason: String\n\n  \"\"\"\n  When was the alert dimissed?\n  \"\"\"\n  dismissedAt: DateTime\n\n  \"\"\"\n  The user who dismissed the alert\n  \"\"\"\n  dismisser: User\n\n  \"\"\"\n  The external identifier for the vulnerability\n  \"\"\"\n  externalIdentifier: String @deprecated(reason: \"advisory specific fields are being removed from repositoryVulnerabilityAlert objects Use `securityAdvisory.identifiers` instead. Removal on 2019-07-01 UTC.\")\n\n  \"\"\"\n  The external reference for the vulnerability\n  \"\"\"\n  externalReference: String! @deprecated(reason: \"advisory specific fields are being removed from repositoryVulnerabilityAlert objects Use `securityAdvisory.references` instead. Removal on 2019-07-01 UTC.\")\n\n  \"\"\"\n  The fixed version\n  \"\"\"\n  fixedIn: String @deprecated(reason: \"advisory specific fields are being removed from repositoryVulnerabilityAlert objects Use `securityVulnerability.firstPatchedVersion` instead. Removal on 2019-07-01 UTC.\")\n  id: ID!\n\n  \"\"\"\n  The affected package\n  \"\"\"\n  packageName: String! @deprecated(reason: \"advisory specific fields are being removed from repositoryVulnerabilityAlert objects Use `securityVulnerability.package` instead. Removal on 2019-07-01 UTC.\")\n\n  \"\"\"\n  The associated repository\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  The associated security advisory\n  \"\"\"\n  securityAdvisory: SecurityAdvisory\n\n  \"\"\"\n  The associated security vulnerablity\n  \"\"\"\n  securityVulnerability: SecurityVulnerability\n\n  \"\"\"\n  The vulnerable manifest filename\n  \"\"\"\n  vulnerableManifestFilename: String!\n\n  \"\"\"\n  The vulnerable manifest path\n  \"\"\"\n  vulnerableManifestPath: String!\n\n  \"\"\"\n  The vulnerable requirements\n  \"\"\"\n  vulnerableRequirements: String\n}\n\n\"\"\"\nThe connection type for RepositoryVulnerabilityAlert.\n\"\"\"\ntype RepositoryVulnerabilityAlertConnection @preview(toggledBy: \"vixen-preview\") {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [RepositoryVulnerabilityAlertEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [RepositoryVulnerabilityAlert]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype RepositoryVulnerabilityAlertEdge @preview(toggledBy: \"vixen-preview\") {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: RepositoryVulnerabilityAlert\n}\n\n\"\"\"\nAutogenerated input type of RequestReviews\n\"\"\"\ninput RequestReviewsInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the pull request to modify.\n  \"\"\"\n  pullRequestId: ID! @possibleTypes(concreteTypes: [\"PullRequest\"])\n\n  \"\"\"\n  The Node IDs of the team to request.\n  \"\"\"\n  teamIds: [ID!] @possibleTypes(concreteTypes: [\"Team\"])\n\n  \"\"\"\n  Add users to the set rather than replace.\n  \"\"\"\n  union: Boolean\n\n  \"\"\"\n  The Node IDs of the user to request.\n  \"\"\"\n  userIds: [ID!] @possibleTypes(concreteTypes: [\"User\"])\n}\n\n\"\"\"\nAutogenerated return type of RequestReviews\n\"\"\"\ntype RequestReviewsPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The pull request that is getting requests.\n  \"\"\"\n  pullRequest: PullRequest\n\n  \"\"\"\n  The edge from the pull request to the requested reviewers.\n  \"\"\"\n  requestedReviewersEdge: UserEdge\n}\n\n\"\"\"\nThe possible states that can be requested when creating a check run.\n\"\"\"\nenum RequestableCheckStatusState @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The check suite or run has been completed.\n  \"\"\"\n  COMPLETED\n\n  \"\"\"\n  The check suite or run is in progress.\n  \"\"\"\n  IN_PROGRESS\n\n  \"\"\"\n  The check suite or run has been queued.\n  \"\"\"\n  QUEUED\n}\n\n\"\"\"\nTypes that can be requested reviewers.\n\"\"\"\nunion RequestedReviewer = Team | User\n\n\"\"\"\nAutogenerated input type of RerequestCheckSuite\n\"\"\"\ninput RerequestCheckSuiteInput @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The Node ID of the check suite.\n  \"\"\"\n  checkSuiteId: ID! @possibleTypes(concreteTypes: [\"CheckSuite\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the repository.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n}\n\n\"\"\"\nAutogenerated return type of RerequestCheckSuite\n\"\"\"\ntype RerequestCheckSuitePayload @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The requested check suite.\n  \"\"\"\n  checkSuite: CheckSuite\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of ResolveReviewThread\n\"\"\"\ninput ResolveReviewThreadInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the thread to resolve\n  \"\"\"\n  threadId: ID! @possibleTypes(concreteTypes: [\"PullRequestReviewThread\"])\n}\n\n\"\"\"\nAutogenerated return type of ResolveReviewThread\n\"\"\"\ntype ResolveReviewThreadPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The thread to resolve.\n  \"\"\"\n  thread: PullRequestReviewThread\n}\n\n\"\"\"\nRepresents a private contribution a user made on GitHub.\n\"\"\"\ntype RestrictedContribution implements Contribution {\n  \"\"\"\n  Whether this contribution is associated with a record you do not have access to. For\n  example, your own 'first issue' contribution may have been made on a repository you can no\n  longer access.\n  \"\"\"\n  isRestricted: Boolean!\n\n  \"\"\"\n  When this contribution was made.\n  \"\"\"\n  occurredAt: DateTime!\n\n  \"\"\"\n  The HTTP path for this contribution.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this contribution.\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  The user who made this contribution.\n  \"\"\"\n  user: User!\n}\n\n\"\"\"\nA team or user who has the ability to dismiss a review on a protected branch.\n\"\"\"\ntype ReviewDismissalAllowance implements Node {\n  \"\"\"\n  The actor that can dismiss.\n  \"\"\"\n  actor: ReviewDismissalAllowanceActor\n\n  \"\"\"\n  Identifies the branch protection rule associated with the allowed user or team.\n  \"\"\"\n  branchProtectionRule: BranchProtectionRule\n  id: ID!\n}\n\n\"\"\"\nTypes that can be an actor.\n\"\"\"\nunion ReviewDismissalAllowanceActor = Team | User\n\n\"\"\"\nThe connection type for ReviewDismissalAllowance.\n\"\"\"\ntype ReviewDismissalAllowanceConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [ReviewDismissalAllowanceEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [ReviewDismissalAllowance]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype ReviewDismissalAllowanceEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: ReviewDismissalAllowance\n}\n\n\"\"\"\nRepresents a 'review_dismissed' event on a given issue or pull request.\n\"\"\"\ntype ReviewDismissedEvent implements Node & UniformResourceLocatable {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  Identifies the optional message associated with the 'review_dismissed' event.\n  \"\"\"\n  dismissalMessage: String\n\n  \"\"\"\n  Identifies the optional message associated with the event, rendered to HTML.\n  \"\"\"\n  dismissalMessageHTML: String\n  id: ID!\n\n  \"\"\"\n  Identifies the message associated with the 'review_dismissed' event.\n  \"\"\"\n  message: String! @deprecated(reason: \"`message` is being removed because it not nullable, whereas the underlying field is optional. Use `dismissalMessage` instead. Removal on 2019-07-01 UTC.\")\n\n  \"\"\"\n  The message associated with the event, rendered to HTML.\n  \"\"\"\n  messageHtml: HTML! @deprecated(reason: \"`messageHtml` is being removed because it not nullable, whereas the underlying field is optional. Use `dismissalMessageHTML` instead. Removal on 2019-07-01 UTC.\")\n\n  \"\"\"\n  Identifies the previous state of the review with the 'review_dismissed' event.\n  \"\"\"\n  previousReviewState: PullRequestReviewState!\n\n  \"\"\"\n  PullRequest referenced by event.\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  Identifies the commit which caused the review to become stale.\n  \"\"\"\n  pullRequestCommit: PullRequestCommit\n\n  \"\"\"\n  The HTTP path for this review dismissed event.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Identifies the review associated with the 'review_dismissed' event.\n  \"\"\"\n  review: PullRequestReview\n\n  \"\"\"\n  The HTTP URL for this review dismissed event.\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nA request for a user to review a pull request.\n\"\"\"\ntype ReviewRequest implements Node {\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n  id: ID!\n\n  \"\"\"\n  Identifies the pull request associated with this review request.\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  The reviewer that is requested.\n  \"\"\"\n  requestedReviewer: RequestedReviewer\n}\n\n\"\"\"\nThe connection type for ReviewRequest.\n\"\"\"\ntype ReviewRequestConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [ReviewRequestEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [ReviewRequest]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype ReviewRequestEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: ReviewRequest\n}\n\n\"\"\"\nRepresents an 'review_request_removed' event on a given pull request.\n\"\"\"\ntype ReviewRequestRemovedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  PullRequest referenced by event.\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  Identifies the reviewer whose review request was removed.\n  \"\"\"\n  requestedReviewer: RequestedReviewer\n}\n\n\"\"\"\nRepresents an 'review_requested' event on a given pull request.\n\"\"\"\ntype ReviewRequestedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  PullRequest referenced by event.\n  \"\"\"\n  pullRequest: PullRequest!\n\n  \"\"\"\n  Identifies the reviewer whose review was requested.\n  \"\"\"\n  requestedReviewer: RequestedReviewer\n}\n\n\"\"\"\nA hovercard context with a message describing the current code review state of the pull\nrequest.\n\"\"\"\ntype ReviewStatusHovercardContext implements HovercardContext @preview(toggledBy: \"hagar-preview\") {\n  \"\"\"\n  A string describing this context\n  \"\"\"\n  message: String!\n\n  \"\"\"\n  An octicon to accompany this context\n  \"\"\"\n  octicon: String!\n}\n\n\"\"\"\nThe results of a search.\n\"\"\"\nunion SearchResultItem = Issue | MarketplaceListing | Organization | PullRequest | Repository | User\n\n\"\"\"\nA list of results that matched against a search query.\n\"\"\"\ntype SearchResultItemConnection {\n  \"\"\"\n  The number of pieces of code that matched the search query.\n  \"\"\"\n  codeCount: Int!\n\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [SearchResultItemEdge]\n\n  \"\"\"\n  The number of issues that matched the search query.\n  \"\"\"\n  issueCount: Int!\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [SearchResultItem]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  The number of repositories that matched the search query.\n  \"\"\"\n  repositoryCount: Int!\n\n  \"\"\"\n  The number of users that matched the search query.\n  \"\"\"\n  userCount: Int!\n\n  \"\"\"\n  The number of wiki pages that matched the search query.\n  \"\"\"\n  wikiCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype SearchResultItemEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: SearchResultItem\n\n  \"\"\"\n  Text matches on the result found.\n  \"\"\"\n  textMatches: [TextMatch]\n}\n\n\"\"\"\nRepresents the individual results of a search.\n\"\"\"\nenum SearchType {\n  \"\"\"\n  Returns results matching issues in repositories.\n  \"\"\"\n  ISSUE\n\n  \"\"\"\n  Returns results matching repositories.\n  \"\"\"\n  REPOSITORY\n\n  \"\"\"\n  Returns results matching users and organizations on GitHub.\n  \"\"\"\n  USER\n}\n\n\"\"\"\nA GitHub Security Advisory\n\"\"\"\ntype SecurityAdvisory implements Node {\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  This is a long plaintext description of the advisory\n  \"\"\"\n  description: String!\n\n  \"\"\"\n  The GitHub Security Advisory ID\n  \"\"\"\n  ghsaId: String!\n  id: ID!\n\n  \"\"\"\n  A list of identifiers for this advisory\n  \"\"\"\n  identifiers: [SecurityAdvisoryIdentifier!]!\n\n  \"\"\"\n  When the advisory was published\n  \"\"\"\n  publishedAt: DateTime!\n\n  \"\"\"\n  A list of references for this advisory\n  \"\"\"\n  references: [SecurityAdvisoryReference!]!\n\n  \"\"\"\n  The severity of the advisory\n  \"\"\"\n  severity: SecurityAdvisorySeverity!\n\n  \"\"\"\n  A short plaintext summary of the advisory\n  \"\"\"\n  summary: String!\n\n  \"\"\"\n  When the advisory was last updated\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  Vulnerabilities associated with this Advisory\n  \"\"\"\n  vulnerabilities(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    An ecosystem to filter vulnerabilities by.\n    \"\"\"\n    ecosystem: SecurityAdvisoryEcosystem\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for the returned topics.\n    \"\"\"\n    orderBy: SecurityVulnerabilityOrder = {field: UPDATED_AT, direction: DESC}\n\n    \"\"\"\n    A package name to filter vulnerabilities by.\n    \"\"\"\n    package: String\n\n    \"\"\"\n    A list of severities to filter vulnerabilities by.\n    \"\"\"\n    severities: [SecurityAdvisorySeverity!]\n  ): SecurityVulnerabilityConnection!\n\n  \"\"\"\n  When the advisory was withdrawn, if it has been withdrawn\n  \"\"\"\n  withdrawnAt: DateTime\n}\n\n\"\"\"\nThe connection type for SecurityAdvisory.\n\"\"\"\ntype SecurityAdvisoryConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [SecurityAdvisoryEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [SecurityAdvisory]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nThe possible ecosystems of a security vulnerability's package.\n\"\"\"\nenum SecurityAdvisoryEcosystem {\n  \"\"\"\n  Java artifacts hosted at the Maven central repository\n  \"\"\"\n  MAVEN\n\n  \"\"\"\n  JavaScript packages hosted at npmjs.com\n  \"\"\"\n  NPM\n\n  \"\"\"\n  .NET packages hosted at the NuGet Gallery\n  \"\"\"\n  NUGET\n\n  \"\"\"\n  Python packages hosted at PyPI.org\n  \"\"\"\n  PIP\n\n  \"\"\"\n  Ruby gems hosted at RubyGems.org\n  \"\"\"\n  RUBYGEMS\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype SecurityAdvisoryEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: SecurityAdvisory\n}\n\n\"\"\"\nA GitHub Security Advisory Identifier\n\"\"\"\ntype SecurityAdvisoryIdentifier {\n  \"\"\"\n  The identifier type, e.g. GHSA, CVE\n  \"\"\"\n  type: String!\n\n  \"\"\"\n  The identifier\n  \"\"\"\n  value: String!\n}\n\n\"\"\"\nAn advisory identifier to filter results on.\n\"\"\"\ninput SecurityAdvisoryIdentifierFilter {\n  \"\"\"\n  The identifier type.\n  \"\"\"\n  type: SecurityAdvisoryIdentifierType!\n\n  \"\"\"\n  The identifier string. Supports exact or partial matching.\n  \"\"\"\n  value: String!\n}\n\n\"\"\"\nIdentifier formats available for advisories.\n\"\"\"\nenum SecurityAdvisoryIdentifierType {\n  \"\"\"\n  Common Vulnerabilities and Exposures Identifier.\n  \"\"\"\n  CVE\n\n  \"\"\"\n  GitHub Security Advisory ID.\n  \"\"\"\n  GHSA\n}\n\n\"\"\"\nOrdering options for security advisory connections\n\"\"\"\ninput SecurityAdvisoryOrder {\n  \"\"\"\n  The ordering direction.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field to order security advisories by.\n  \"\"\"\n  field: SecurityAdvisoryOrderField!\n}\n\n\"\"\"\nProperties by which security advisory connections can be ordered.\n\"\"\"\nenum SecurityAdvisoryOrderField {\n  \"\"\"\n  Order advisories by publication time\n  \"\"\"\n  PUBLISHED_AT\n\n  \"\"\"\n  Order advisories by update time\n  \"\"\"\n  UPDATED_AT\n}\n\n\"\"\"\nAn individual package\n\"\"\"\ntype SecurityAdvisoryPackage {\n  \"\"\"\n  The ecosystem the package belongs to, e.g. RUBYGEMS, NPM\n  \"\"\"\n  ecosystem: SecurityAdvisoryEcosystem!\n\n  \"\"\"\n  The package name\n  \"\"\"\n  name: String!\n}\n\n\"\"\"\nAn individual package version\n\"\"\"\ntype SecurityAdvisoryPackageVersion {\n  \"\"\"\n  The package name or version\n  \"\"\"\n  identifier: String!\n}\n\n\"\"\"\nA GitHub Security Advisory Reference\n\"\"\"\ntype SecurityAdvisoryReference {\n  \"\"\"\n  A publicly accessible reference\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nSeverity of the vulnerability.\n\"\"\"\nenum SecurityAdvisorySeverity {\n  \"\"\"\n  Critical.\n  \"\"\"\n  CRITICAL\n\n  \"\"\"\n  High.\n  \"\"\"\n  HIGH\n\n  \"\"\"\n  Low.\n  \"\"\"\n  LOW\n\n  \"\"\"\n  Moderate.\n  \"\"\"\n  MODERATE\n}\n\n\"\"\"\nAn individual vulnerability within an Advisory\n\"\"\"\ntype SecurityVulnerability {\n  \"\"\"\n  The Advisory associated with this Vulnerability\n  \"\"\"\n  advisory: SecurityAdvisory!\n\n  \"\"\"\n  The first version containing a fix for the vulnerability\n  \"\"\"\n  firstPatchedVersion: SecurityAdvisoryPackageVersion\n\n  \"\"\"\n  A description of the vulnerable package\n  \"\"\"\n  package: SecurityAdvisoryPackage!\n\n  \"\"\"\n  The severity of the vulnerability within this package\n  \"\"\"\n  severity: SecurityAdvisorySeverity!\n\n  \"\"\"\n  When the vulnerability was last updated\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  A string that describes the vulnerable package versions.\n  This string follows a basic syntax with a few forms.\n  + `= 0.2.0` denotes a single vulnerable version.\n  + `<= 1.0.8` denotes a version range up to and including the specified version\n  + `< 0.1.11` denotes a version range up to, but excluding, the specified version\n  + `>= 4.3.0, < 4.3.5` denotes a version range with a known minimum and maximum version.\n  + `>= 0.0.1` denotes a version range with a known minimum, but no known maximum\n  \"\"\"\n  vulnerableVersionRange: String!\n}\n\n\"\"\"\nThe connection type for SecurityVulnerability.\n\"\"\"\ntype SecurityVulnerabilityConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [SecurityVulnerabilityEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [SecurityVulnerability]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype SecurityVulnerabilityEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: SecurityVulnerability\n}\n\n\"\"\"\nOrdering options for security vulnerability connections\n\"\"\"\ninput SecurityVulnerabilityOrder {\n  \"\"\"\n  The ordering direction.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field to order security vulnerabilities by.\n  \"\"\"\n  field: SecurityVulnerabilityOrderField!\n}\n\n\"\"\"\nProperties by which security vulnerability connections can be ordered.\n\"\"\"\nenum SecurityVulnerabilityOrderField {\n  \"\"\"\n  Order vulnerability by update time\n  \"\"\"\n  UPDATED_AT\n}\n\n\"\"\"\nRepresents an S/MIME signature on a Commit or Tag.\n\"\"\"\ntype SmimeSignature implements GitSignature {\n  \"\"\"\n  Email used to sign this object.\n  \"\"\"\n  email: String!\n\n  \"\"\"\n  True if the signature is valid and verified by GitHub.\n  \"\"\"\n  isValid: Boolean!\n\n  \"\"\"\n  Payload for GPG signing object. Raw ODB object without the signature header.\n  \"\"\"\n  payload: String!\n\n  \"\"\"\n  ASCII-armored signature header from object.\n  \"\"\"\n  signature: String!\n\n  \"\"\"\n  GitHub user corresponding to the email signing this commit.\n  \"\"\"\n  signer: User\n\n  \"\"\"\n  The state of this signature. `VALID` if signature is valid and verified by\n  GitHub, otherwise represents reason why signature is considered invalid.\n  \"\"\"\n  state: GitSignatureState!\n\n  \"\"\"\n  True if the signature was made with GitHub's signing key.\n  \"\"\"\n  wasSignedByGitHub: Boolean!\n}\n\n\"\"\"\nWays in which star connections can be ordered.\n\"\"\"\ninput StarOrder {\n  \"\"\"\n  The direction in which to order nodes.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field in which to order nodes by.\n  \"\"\"\n  field: StarOrderField!\n}\n\n\"\"\"\nProperties by which star connections can be ordered.\n\"\"\"\nenum StarOrderField {\n  \"\"\"\n  Allows ordering a list of stars by when they were created.\n  \"\"\"\n  STARRED_AT\n}\n\n\"\"\"\nThe connection type for User.\n\"\"\"\ntype StargazerConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [StargazerEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [User]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nRepresents a user that's starred a repository.\n\"\"\"\ntype StargazerEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n  node: User!\n\n  \"\"\"\n  Identifies when the item was starred.\n  \"\"\"\n  starredAt: DateTime!\n}\n\n\"\"\"\nThings that can be starred.\n\"\"\"\ninterface Starrable {\n  id: ID!\n\n  \"\"\"\n  A list of users who have starred this starrable.\n  \"\"\"\n  stargazers(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Order for connection\n    \"\"\"\n    orderBy: StarOrder\n  ): StargazerConnection!\n\n  \"\"\"\n  Returns a boolean indicating whether the viewing user has starred this starrable.\n  \"\"\"\n  viewerHasStarred: Boolean!\n}\n\n\"\"\"\nThe connection type for Repository.\n\"\"\"\ntype StarredRepositoryConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [StarredRepositoryEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Repository]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nRepresents a starred repository.\n\"\"\"\ntype StarredRepositoryEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n  node: Repository!\n\n  \"\"\"\n  Identifies when the item was starred.\n  \"\"\"\n  starredAt: DateTime!\n}\n\n\"\"\"\nRepresents a commit status.\n\"\"\"\ntype Status implements Node {\n  \"\"\"\n  The commit this status is attached to.\n  \"\"\"\n  commit: Commit\n\n  \"\"\"\n  Looks up an individual status context by context name.\n  \"\"\"\n  context(\n    \"\"\"\n    The context name.\n    \"\"\"\n    name: String!\n  ): StatusContext\n\n  \"\"\"\n  The individual status contexts for this commit.\n  \"\"\"\n  contexts: [StatusContext!]!\n  id: ID!\n\n  \"\"\"\n  The combined commit status.\n  \"\"\"\n  state: StatusState!\n}\n\n\"\"\"\nRepresents an individual commit status context\n\"\"\"\ntype StatusContext implements Node {\n  \"\"\"\n  This commit this status context is attached to.\n  \"\"\"\n  commit: Commit\n\n  \"\"\"\n  The name of this status context.\n  \"\"\"\n  context: String!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  The actor who created this status context.\n  \"\"\"\n  creator: Actor\n\n  \"\"\"\n  The description for this status context.\n  \"\"\"\n  description: String\n  id: ID!\n\n  \"\"\"\n  The state of this status context.\n  \"\"\"\n  state: StatusState!\n\n  \"\"\"\n  The URL for this status context.\n  \"\"\"\n  targetUrl: URI\n}\n\n\"\"\"\nThe possible commit status states.\n\"\"\"\nenum StatusState {\n  \"\"\"\n  Status is errored.\n  \"\"\"\n  ERROR\n\n  \"\"\"\n  Status is expected.\n  \"\"\"\n  EXPECTED\n\n  \"\"\"\n  Status is failing.\n  \"\"\"\n  FAILURE\n\n  \"\"\"\n  Status is pending.\n  \"\"\"\n  PENDING\n\n  \"\"\"\n  Status is successful.\n  \"\"\"\n  SUCCESS\n}\n\n\"\"\"\nAutogenerated input type of SubmitPullRequestReview\n\"\"\"\ninput SubmitPullRequestReviewInput {\n  \"\"\"\n  The text field to set on the Pull Request Review.\n  \"\"\"\n  body: String\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The event to send to the Pull Request Review.\n  \"\"\"\n  event: PullRequestReviewEvent!\n\n  \"\"\"\n  The Pull Request Review ID to submit.\n  \"\"\"\n  pullRequestReviewId: ID! @possibleTypes(concreteTypes: [\"PullRequestReview\"])\n}\n\n\"\"\"\nAutogenerated return type of SubmitPullRequestReview\n\"\"\"\ntype SubmitPullRequestReviewPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The submitted pull request review.\n  \"\"\"\n  pullRequestReview: PullRequestReview\n}\n\n\"\"\"\nEntities that can be subscribed to for web and email notifications.\n\"\"\"\ninterface Subscribable {\n  id: ID!\n\n  \"\"\"\n  Check if the viewer is able to change their subscription status for the repository.\n  \"\"\"\n  viewerCanSubscribe: Boolean!\n\n  \"\"\"\n  Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.\n  \"\"\"\n  viewerSubscription: SubscriptionState\n}\n\n\"\"\"\nRepresents a 'subscribed' event on a given `Subscribable`.\n\"\"\"\ntype SubscribedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Object referenced by event.\n  \"\"\"\n  subscribable: Subscribable!\n}\n\n\"\"\"\nThe possible states of a subscription.\n\"\"\"\nenum SubscriptionState {\n  \"\"\"\n  The User is never notified.\n  \"\"\"\n  IGNORED\n\n  \"\"\"\n  The User is notified of all conversations.\n  \"\"\"\n  SUBSCRIBED\n\n  \"\"\"\n  The User is only notified when participating or @mentioned.\n  \"\"\"\n  UNSUBSCRIBED\n}\n\n\"\"\"\nA suggestion to review a pull request based on a user's commit history and review comments.\n\"\"\"\ntype SuggestedReviewer {\n  \"\"\"\n  Is this suggestion based on past commits?\n  \"\"\"\n  isAuthor: Boolean!\n\n  \"\"\"\n  Is this suggestion based on past review comments?\n  \"\"\"\n  isCommenter: Boolean!\n\n  \"\"\"\n  Identifies the user suggested to review the pull request.\n  \"\"\"\n  reviewer: User!\n}\n\n\"\"\"\nRepresents a Git tag.\n\"\"\"\ntype Tag implements GitObject & Node {\n  \"\"\"\n  An abbreviated version of the Git object ID\n  \"\"\"\n  abbreviatedOid: String!\n\n  \"\"\"\n  The HTTP path for this Git object\n  \"\"\"\n  commitResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this Git object\n  \"\"\"\n  commitUrl: URI!\n  id: ID!\n\n  \"\"\"\n  The Git tag message.\n  \"\"\"\n  message: String\n\n  \"\"\"\n  The Git tag name.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The Git object ID\n  \"\"\"\n  oid: GitObjectID!\n\n  \"\"\"\n  The Repository the Git object belongs to\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  Details about the tag author.\n  \"\"\"\n  tagger: GitActor\n\n  \"\"\"\n  The Git object the tag points to.\n  \"\"\"\n  target: GitObject!\n}\n\n\"\"\"\nA team of users in an organization.\n\"\"\"\ntype Team implements Node & Subscribable {\n  \"\"\"\n  A list of teams that are ancestors of this team.\n  \"\"\"\n  ancestors(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): TeamConnection!\n\n  \"\"\"\n  A URL pointing to the team's avatar.\n  \"\"\"\n  avatarUrl(\n    \"\"\"\n    The size in pixels of the resulting square image.\n    \"\"\"\n    size: Int = 400\n  ): URI\n\n  \"\"\"\n  List of child teams belonging to this team\n  \"\"\"\n  childTeams(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Whether to list immediate child teams or all descendant child teams.\n    \"\"\"\n    immediateOnly: Boolean = true\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Order for connection\n    \"\"\"\n    orderBy: TeamOrder\n\n    \"\"\"\n    User logins to filter by\n    \"\"\"\n    userLogins: [String!]\n  ): TeamConnection!\n\n  \"\"\"\n  The slug corresponding to the organization and team.\n  \"\"\"\n  combinedSlug: String!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  The description of the team.\n  \"\"\"\n  description: String\n\n  \"\"\"\n  Find a team discussion by its number.\n  \"\"\"\n  discussion(\n    \"\"\"\n    The sequence number of the discussion to find.\n    \"\"\"\n    number: Int!\n  ): TeamDiscussion @preview(toggledBy: \"echo-preview\")\n\n  \"\"\"\n  A list of team discussions.\n  \"\"\"\n  discussions(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    If provided, filters discussions according to whether or not they are pinned.\n    \"\"\"\n    isPinned: Boolean\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Order for connection\n    \"\"\"\n    orderBy: TeamDiscussionOrder\n  ): TeamDiscussionConnection! @preview(toggledBy: \"echo-preview\")\n\n  \"\"\"\n  The HTTP path for team discussions\n  \"\"\"\n  discussionsResourcePath: URI! @preview(toggledBy: \"echo-preview\")\n\n  \"\"\"\n  The HTTP URL for team discussions\n  \"\"\"\n  discussionsUrl: URI! @preview(toggledBy: \"echo-preview\")\n\n  \"\"\"\n  The HTTP path for editing this team\n  \"\"\"\n  editTeamResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for editing this team\n  \"\"\"\n  editTeamUrl: URI!\n  id: ID!\n\n  \"\"\"\n  A list of pending invitations for users to this team\n  \"\"\"\n  invitations(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): OrganizationInvitationConnection\n\n  \"\"\"\n  A list of users who are members of this team.\n  \"\"\"\n  members(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Filter by membership type\n    \"\"\"\n    membership: TeamMembershipType = ALL\n\n    \"\"\"\n    Order for the connection.\n    \"\"\"\n    orderBy: TeamMemberOrder\n\n    \"\"\"\n    The search string to look for.\n    \"\"\"\n    query: String\n\n    \"\"\"\n    Filter by team member role\n    \"\"\"\n    role: TeamMemberRole\n  ): TeamMemberConnection!\n\n  \"\"\"\n  The HTTP path for the team' members\n  \"\"\"\n  membersResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for the team' members\n  \"\"\"\n  membersUrl: URI!\n\n  \"\"\"\n  The name of the team.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The HTTP path creating a new team\n  \"\"\"\n  newTeamResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL creating a new team\n  \"\"\"\n  newTeamUrl: URI!\n\n  \"\"\"\n  The organization that owns this team.\n  \"\"\"\n  organization: Organization!\n\n  \"\"\"\n  The parent team of the team.\n  \"\"\"\n  parentTeam: Team\n\n  \"\"\"\n  The level of privacy the team has.\n  \"\"\"\n  privacy: TeamPrivacy!\n\n  \"\"\"\n  A list of repositories this team has access to.\n  \"\"\"\n  repositories(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Order for the connection.\n    \"\"\"\n    orderBy: TeamRepositoryOrder\n\n    \"\"\"\n    The search string to look for.\n    \"\"\"\n    query: String\n  ): TeamRepositoryConnection!\n\n  \"\"\"\n  The HTTP path for this team's repositories\n  \"\"\"\n  repositoriesResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this team's repositories\n  \"\"\"\n  repositoriesUrl: URI!\n\n  \"\"\"\n  The HTTP path for this team\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The slug corresponding to the team.\n  \"\"\"\n  slug: String!\n\n  \"\"\"\n  The HTTP path for this team's teams\n  \"\"\"\n  teamsResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this team's teams\n  \"\"\"\n  teamsUrl: URI!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this team\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  Team is adminable by the viewer.\n  \"\"\"\n  viewerCanAdminister: Boolean!\n\n  \"\"\"\n  Check if the viewer is able to change their subscription status for the repository.\n  \"\"\"\n  viewerCanSubscribe: Boolean!\n\n  \"\"\"\n  Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.\n  \"\"\"\n  viewerSubscription: SubscriptionState\n}\n\n\"\"\"\nThe connection type for Team.\n\"\"\"\ntype TeamConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [TeamEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Team]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nA team discussion.\n\"\"\"\ntype TeamDiscussion implements Comment & Deletable & Node & Reactable & Subscribable & UniformResourceLocatable & Updatable & UpdatableComment @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  The actor who authored the comment.\n  \"\"\"\n  author: Actor\n\n  \"\"\"\n  Author's association with the discussion's team.\n  \"\"\"\n  authorAssociation: CommentAuthorAssociation!\n\n  \"\"\"\n  The body as Markdown.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  The discussion body rendered to HTML.\n  \"\"\"\n  bodyHTML: HTML!\n\n  \"\"\"\n  The body rendered to text.\n  \"\"\"\n  bodyText: String!\n\n  \"\"\"\n  Identifies the discussion body hash.\n  \"\"\"\n  bodyVersion: String!\n\n  \"\"\"\n  A list of comments on this discussion.\n  \"\"\"\n  comments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    When provided, filters the connection such that results begin with the comment with this number.\n    \"\"\"\n    fromComment: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Order for connection\n    \"\"\"\n    orderBy: TeamDiscussionCommentOrder\n  ): TeamDiscussionCommentConnection!\n\n  \"\"\"\n  The HTTP path for discussion comments\n  \"\"\"\n  commentsResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for discussion comments\n  \"\"\"\n  commentsUrl: URI!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Check if this comment was created via an email reply.\n  \"\"\"\n  createdViaEmail: Boolean!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The actor who edited the comment.\n  \"\"\"\n  editor: Actor\n  id: ID!\n\n  \"\"\"\n  Check if this comment was edited and includes an edit with the creation data\n  \"\"\"\n  includesCreatedEdit: Boolean!\n\n  \"\"\"\n  Whether or not the discussion is pinned.\n  \"\"\"\n  isPinned: Boolean!\n\n  \"\"\"\n  Whether or not the discussion is only visible to team members and org admins.\n  \"\"\"\n  isPrivate: Boolean!\n\n  \"\"\"\n  The moment the editor made the last edit\n  \"\"\"\n  lastEditedAt: DateTime\n\n  \"\"\"\n  Identifies the discussion within its team.\n  \"\"\"\n  number: Int!\n\n  \"\"\"\n  Identifies when the comment was published at.\n  \"\"\"\n  publishedAt: DateTime\n\n  \"\"\"\n  A list of reactions grouped by content left on the subject.\n  \"\"\"\n  reactionGroups: [ReactionGroup!]\n\n  \"\"\"\n  A list of Reactions left on the Issue.\n  \"\"\"\n  reactions(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Allows filtering Reactions by emoji.\n    \"\"\"\n    content: ReactionContent\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Allows specifying the order in which reactions are returned.\n    \"\"\"\n    orderBy: ReactionOrder\n  ): ReactionConnection!\n\n  \"\"\"\n  The HTTP path for this discussion\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The team that defines the context of this discussion.\n  \"\"\"\n  team: Team!\n\n  \"\"\"\n  The title of the discussion\n  \"\"\"\n  title: String!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this discussion\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  A list of edits to this content.\n  \"\"\"\n  userContentEdits(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserContentEditConnection\n\n  \"\"\"\n  Check if the current viewer can delete this object.\n  \"\"\"\n  viewerCanDelete: Boolean!\n\n  \"\"\"\n  Whether or not the current viewer can pin this discussion.\n  \"\"\"\n  viewerCanPin: Boolean!\n\n  \"\"\"\n  Can user react to this subject\n  \"\"\"\n  viewerCanReact: Boolean!\n\n  \"\"\"\n  Check if the viewer is able to change their subscription status for the repository.\n  \"\"\"\n  viewerCanSubscribe: Boolean!\n\n  \"\"\"\n  Check if the current viewer can update this object.\n  \"\"\"\n  viewerCanUpdate: Boolean!\n\n  \"\"\"\n  Reasons why the current viewer can not update this comment.\n  \"\"\"\n  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!\n\n  \"\"\"\n  Did the viewer author this comment.\n  \"\"\"\n  viewerDidAuthor: Boolean!\n\n  \"\"\"\n  Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.\n  \"\"\"\n  viewerSubscription: SubscriptionState\n}\n\n\"\"\"\nA comment on a team discussion.\n\"\"\"\ntype TeamDiscussionComment implements Comment & Deletable & Node & Reactable & UniformResourceLocatable & Updatable & UpdatableComment @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  The actor who authored the comment.\n  \"\"\"\n  author: Actor\n\n  \"\"\"\n  Author's association with the comment's team.\n  \"\"\"\n  authorAssociation: CommentAuthorAssociation!\n\n  \"\"\"\n  The body as Markdown.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  The comment body rendered to HTML.\n  \"\"\"\n  bodyHTML: HTML!\n\n  \"\"\"\n  The body rendered to text.\n  \"\"\"\n  bodyText: String!\n\n  \"\"\"\n  The current version of the body content.\n  \"\"\"\n  bodyVersion: String!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Check if this comment was created via an email reply.\n  \"\"\"\n  createdViaEmail: Boolean!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The discussion this comment is about.\n  \"\"\"\n  discussion: TeamDiscussion!\n\n  \"\"\"\n  The actor who edited the comment.\n  \"\"\"\n  editor: Actor\n  id: ID!\n\n  \"\"\"\n  Check if this comment was edited and includes an edit with the creation data\n  \"\"\"\n  includesCreatedEdit: Boolean!\n\n  \"\"\"\n  The moment the editor made the last edit\n  \"\"\"\n  lastEditedAt: DateTime\n\n  \"\"\"\n  Identifies the comment number.\n  \"\"\"\n  number: Int!\n\n  \"\"\"\n  Identifies when the comment was published at.\n  \"\"\"\n  publishedAt: DateTime\n\n  \"\"\"\n  A list of reactions grouped by content left on the subject.\n  \"\"\"\n  reactionGroups: [ReactionGroup!]\n\n  \"\"\"\n  A list of Reactions left on the Issue.\n  \"\"\"\n  reactions(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Allows filtering Reactions by emoji.\n    \"\"\"\n    content: ReactionContent\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Allows specifying the order in which reactions are returned.\n    \"\"\"\n    orderBy: ReactionOrder\n  ): ReactionConnection!\n\n  \"\"\"\n  The HTTP path for this comment\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this comment\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  A list of edits to this content.\n  \"\"\"\n  userContentEdits(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): UserContentEditConnection\n\n  \"\"\"\n  Check if the current viewer can delete this object.\n  \"\"\"\n  viewerCanDelete: Boolean!\n\n  \"\"\"\n  Can user react to this subject\n  \"\"\"\n  viewerCanReact: Boolean!\n\n  \"\"\"\n  Check if the current viewer can update this object.\n  \"\"\"\n  viewerCanUpdate: Boolean!\n\n  \"\"\"\n  Reasons why the current viewer can not update this comment.\n  \"\"\"\n  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!\n\n  \"\"\"\n  Did the viewer author this comment.\n  \"\"\"\n  viewerDidAuthor: Boolean!\n}\n\n\"\"\"\nThe connection type for TeamDiscussionComment.\n\"\"\"\ntype TeamDiscussionCommentConnection @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [TeamDiscussionCommentEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [TeamDiscussionComment]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype TeamDiscussionCommentEdge @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: TeamDiscussionComment\n}\n\n\"\"\"\nWays in which team discussion comment connections can be ordered.\n\"\"\"\ninput TeamDiscussionCommentOrder @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  The direction in which to order nodes.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field by which to order nodes.\n  \"\"\"\n  field: TeamDiscussionCommentOrderField!\n}\n\n\"\"\"\nProperties by which team discussion comment connections can be ordered.\n\"\"\"\nenum TeamDiscussionCommentOrderField @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  Allows sequential ordering of team discussion comments (which is equivalent to chronological ordering).\n  \"\"\"\n  NUMBER\n}\n\n\"\"\"\nThe connection type for TeamDiscussion.\n\"\"\"\ntype TeamDiscussionConnection @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [TeamDiscussionEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [TeamDiscussion]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype TeamDiscussionEdge @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: TeamDiscussion\n}\n\n\"\"\"\nWays in which team discussion connections can be ordered.\n\"\"\"\ninput TeamDiscussionOrder @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  The direction in which to order nodes.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field by which to order nodes.\n  \"\"\"\n  field: TeamDiscussionOrderField!\n}\n\n\"\"\"\nProperties by which team discussion connections can be ordered.\n\"\"\"\nenum TeamDiscussionOrderField @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  Allows chronological ordering of team discussions.\n  \"\"\"\n  CREATED_AT\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype TeamEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Team\n}\n\n\"\"\"\nThe connection type for User.\n\"\"\"\ntype TeamMemberConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [TeamMemberEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [User]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nRepresents a user who is a member of a team.\n\"\"\"\ntype TeamMemberEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The HTTP path to the organization's member access page.\n  \"\"\"\n  memberAccessResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL to the organization's member access page.\n  \"\"\"\n  memberAccessUrl: URI!\n  node: User!\n\n  \"\"\"\n  The role the member has on the team.\n  \"\"\"\n  role: TeamMemberRole!\n}\n\n\"\"\"\nOrdering options for team member connections\n\"\"\"\ninput TeamMemberOrder {\n  \"\"\"\n  The ordering direction.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field to order team members by.\n  \"\"\"\n  field: TeamMemberOrderField!\n}\n\n\"\"\"\nProperties by which team member connections can be ordered.\n\"\"\"\nenum TeamMemberOrderField {\n  \"\"\"\n  Order team members by creation time\n  \"\"\"\n  CREATED_AT\n\n  \"\"\"\n  Order team members by login\n  \"\"\"\n  LOGIN\n}\n\n\"\"\"\nThe possible team member roles; either 'maintainer' or 'member'.\n\"\"\"\nenum TeamMemberRole {\n  \"\"\"\n  A team maintainer has permission to add and remove team members.\n  \"\"\"\n  MAINTAINER\n\n  \"\"\"\n  A team member has no administrative permissions on the team.\n  \"\"\"\n  MEMBER\n}\n\n\"\"\"\nDefines which types of team members are included in the returned list. Can be one of IMMEDIATE, CHILD_TEAM or ALL.\n\"\"\"\nenum TeamMembershipType {\n  \"\"\"\n  Includes immediate and child team members for the team.\n  \"\"\"\n  ALL\n\n  \"\"\"\n  Includes only child team members for the team.\n  \"\"\"\n  CHILD_TEAM\n\n  \"\"\"\n  Includes only immediate members of the team.\n  \"\"\"\n  IMMEDIATE\n}\n\n\"\"\"\nWays in which team connections can be ordered.\n\"\"\"\ninput TeamOrder {\n  \"\"\"\n  The direction in which to order nodes.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field in which to order nodes by.\n  \"\"\"\n  field: TeamOrderField!\n}\n\n\"\"\"\nProperties by which team connections can be ordered.\n\"\"\"\nenum TeamOrderField {\n  \"\"\"\n  Allows ordering a list of teams by name.\n  \"\"\"\n  NAME\n}\n\n\"\"\"\nThe possible team privacy values.\n\"\"\"\nenum TeamPrivacy {\n  \"\"\"\n  A secret team can only be seen by its members.\n  \"\"\"\n  SECRET\n\n  \"\"\"\n  A visible team can be seen and @mentioned by every member of the organization.\n  \"\"\"\n  VISIBLE\n}\n\n\"\"\"\nThe connection type for Repository.\n\"\"\"\ntype TeamRepositoryConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [TeamRepositoryEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Repository]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nRepresents a team repository.\n\"\"\"\ntype TeamRepositoryEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n  node: Repository!\n\n  \"\"\"\n  The permission level the team has on the repository\n  \"\"\"\n  permission: RepositoryPermission!\n}\n\n\"\"\"\nOrdering options for team repository connections\n\"\"\"\ninput TeamRepositoryOrder {\n  \"\"\"\n  The ordering direction.\n  \"\"\"\n  direction: OrderDirection!\n\n  \"\"\"\n  The field to order repositories by.\n  \"\"\"\n  field: TeamRepositoryOrderField!\n}\n\n\"\"\"\nProperties by which team repository connections can be ordered.\n\"\"\"\nenum TeamRepositoryOrderField {\n  \"\"\"\n  Order repositories by creation time\n  \"\"\"\n  CREATED_AT\n\n  \"\"\"\n  Order repositories by name\n  \"\"\"\n  NAME\n\n  \"\"\"\n  Order repositories by permission\n  \"\"\"\n  PERMISSION\n\n  \"\"\"\n  Order repositories by push time\n  \"\"\"\n  PUSHED_AT\n\n  \"\"\"\n  Order repositories by number of stargazers\n  \"\"\"\n  STARGAZERS\n\n  \"\"\"\n  Order repositories by update time\n  \"\"\"\n  UPDATED_AT\n}\n\n\"\"\"\nThe role of a user on a team.\n\"\"\"\nenum TeamRole {\n  \"\"\"\n  User has admin rights on the team.\n  \"\"\"\n  ADMIN\n\n  \"\"\"\n  User is a member of the team.\n  \"\"\"\n  MEMBER\n}\n\n\"\"\"\nA text match within a search result.\n\"\"\"\ntype TextMatch {\n  \"\"\"\n  The specific text fragment within the property matched on.\n  \"\"\"\n  fragment: String!\n\n  \"\"\"\n  Highlights within the matched fragment.\n  \"\"\"\n  highlights: [TextMatchHighlight!]!\n\n  \"\"\"\n  The property matched on.\n  \"\"\"\n  property: String!\n}\n\n\"\"\"\nRepresents a single highlight in a search result match.\n\"\"\"\ntype TextMatchHighlight {\n  \"\"\"\n  The indice in the fragment where the matched text begins.\n  \"\"\"\n  beginIndice: Int!\n\n  \"\"\"\n  The indice in the fragment where the matched text ends.\n  \"\"\"\n  endIndice: Int!\n\n  \"\"\"\n  The text matched.\n  \"\"\"\n  text: String!\n}\n\n\"\"\"\nA topic aggregates entities that are related to a subject.\n\"\"\"\ntype Topic implements Node & Starrable {\n  id: ID!\n\n  \"\"\"\n  The topic's name.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  A list of related topics, including aliases of this topic, sorted with the most relevant\n  first. Returns up to 10 Topics.\n  \"\"\"\n  relatedTopics(\n    \"\"\"\n    How many topics to return.\n    \"\"\"\n    first: Int = 3\n  ): [Topic!]!\n\n  \"\"\"\n  A list of users who have starred this starrable.\n  \"\"\"\n  stargazers(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Order for connection\n    \"\"\"\n    orderBy: StarOrder\n  ): StargazerConnection!\n\n  \"\"\"\n  Returns a boolean indicating whether the viewing user has starred this starrable.\n  \"\"\"\n  viewerHasStarred: Boolean!\n}\n\n\"\"\"\nThe connection type for Topic.\n\"\"\"\ntype TopicConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [TopicEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [Topic]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype TopicEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: Topic\n}\n\n\"\"\"\nReason that the suggested topic is declined.\n\"\"\"\nenum TopicSuggestionDeclineReason {\n  \"\"\"\n  The suggested topic is not relevant to the repository.\n  \"\"\"\n  NOT_RELEVANT\n\n  \"\"\"\n  The viewer does not like the suggested topic.\n  \"\"\"\n  PERSONAL_PREFERENCE\n\n  \"\"\"\n  The suggested topic is too general for the repository.\n  \"\"\"\n  TOO_GENERAL\n\n  \"\"\"\n  The suggested topic is too specific for the repository (e.g. #ruby-on-rails-version-4-2-1).\n  \"\"\"\n  TOO_SPECIFIC\n}\n\n\"\"\"\nRepresents a 'transferred' event on a given issue or pull request.\n\"\"\"\ntype TransferredEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  The repository this came from\n  \"\"\"\n  fromRepository: Repository\n  id: ID!\n\n  \"\"\"\n  Identifies the issue associated with the event.\n  \"\"\"\n  issue: Issue!\n}\n\n\"\"\"\nRepresents a Git tree.\n\"\"\"\ntype Tree implements GitObject & Node {\n  \"\"\"\n  An abbreviated version of the Git object ID\n  \"\"\"\n  abbreviatedOid: String!\n\n  \"\"\"\n  The HTTP path for this Git object\n  \"\"\"\n  commitResourcePath: URI!\n\n  \"\"\"\n  The HTTP URL for this Git object\n  \"\"\"\n  commitUrl: URI!\n\n  \"\"\"\n  A list of tree entries.\n  \"\"\"\n  entries: [TreeEntry!]\n  id: ID!\n\n  \"\"\"\n  The Git object ID\n  \"\"\"\n  oid: GitObjectID!\n\n  \"\"\"\n  The Repository the Git object belongs to\n  \"\"\"\n  repository: Repository!\n}\n\n\"\"\"\nRepresents a Git tree entry.\n\"\"\"\ntype TreeEntry {\n  \"\"\"\n  Entry file mode.\n  \"\"\"\n  mode: Int!\n\n  \"\"\"\n  Entry file name.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  Entry file object.\n  \"\"\"\n  object: GitObject\n\n  \"\"\"\n  Entry file Git object ID.\n  \"\"\"\n  oid: GitObjectID!\n\n  \"\"\"\n  The Repository the tree entry belongs to\n  \"\"\"\n  repository: Repository!\n\n  \"\"\"\n  Entry file type.\n  \"\"\"\n  type: String!\n}\n\n\"\"\"\nAn RFC 3986, RFC 3987, and RFC 6570 (level 4) compliant URI string.\n\"\"\"\nscalar URI\n\n\"\"\"\nRepresents an 'unassigned' event on any assignable object.\n\"\"\"\ntype UnassignedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the assignable associated with the event.\n  \"\"\"\n  assignable: Assignable!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Identifies the subject (user) who was unassigned.\n  \"\"\"\n  user: User\n}\n\n\"\"\"\nRepresents a type that can be retrieved by a URL.\n\"\"\"\ninterface UniformResourceLocatable {\n  \"\"\"\n  The HTML path to this resource.\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  The URL to this resource.\n  \"\"\"\n  url: URI!\n}\n\n\"\"\"\nRepresents an unknown signature on a Commit or Tag.\n\"\"\"\ntype UnknownSignature implements GitSignature {\n  \"\"\"\n  Email used to sign this object.\n  \"\"\"\n  email: String!\n\n  \"\"\"\n  True if the signature is valid and verified by GitHub.\n  \"\"\"\n  isValid: Boolean!\n\n  \"\"\"\n  Payload for GPG signing object. Raw ODB object without the signature header.\n  \"\"\"\n  payload: String!\n\n  \"\"\"\n  ASCII-armored signature header from object.\n  \"\"\"\n  signature: String!\n\n  \"\"\"\n  GitHub user corresponding to the email signing this commit.\n  \"\"\"\n  signer: User\n\n  \"\"\"\n  The state of this signature. `VALID` if signature is valid and verified by\n  GitHub, otherwise represents reason why signature is considered invalid.\n  \"\"\"\n  state: GitSignatureState!\n\n  \"\"\"\n  True if the signature was made with GitHub's signing key.\n  \"\"\"\n  wasSignedByGitHub: Boolean!\n}\n\n\"\"\"\nRepresents an 'unlabeled' event on a given issue or pull request.\n\"\"\"\ntype UnlabeledEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Identifies the label associated with the 'unlabeled' event.\n  \"\"\"\n  label: Label!\n\n  \"\"\"\n  Identifies the `Labelable` associated with the event.\n  \"\"\"\n  labelable: Labelable!\n}\n\n\"\"\"\nAutogenerated input type of UnlockLockable\n\"\"\"\ninput UnlockLockableInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  ID of the issue or pull request to be unlocked.\n  \"\"\"\n  lockableId: ID! @possibleTypes(concreteTypes: [\"Issue\", \"PullRequest\"], abstractType: \"Lockable\")\n}\n\n\"\"\"\nAutogenerated return type of UnlockLockable\n\"\"\"\ntype UnlockLockablePayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The item that was unlocked.\n  \"\"\"\n  unlockedRecord: Lockable\n}\n\n\"\"\"\nRepresents an 'unlocked' event on a given issue or pull request.\n\"\"\"\ntype UnlockedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Object that was unlocked.\n  \"\"\"\n  lockable: Lockable!\n}\n\n\"\"\"\nAutogenerated input type of UnmarkIssueAsDuplicate\n\"\"\"\ninput UnmarkIssueAsDuplicateInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  ID of the issue or pull request currently considered canonical/authoritative/original.\n  \"\"\"\n  canonicalId: ID! @possibleTypes(concreteTypes: [\"Issue\", \"PullRequest\"], abstractType: \"IssueOrPullRequest\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  ID of the issue or pull request currently marked as a duplicate.\n  \"\"\"\n  duplicateId: ID! @possibleTypes(concreteTypes: [\"Issue\", \"PullRequest\"], abstractType: \"IssueOrPullRequest\")\n}\n\n\"\"\"\nAutogenerated return type of UnmarkIssueAsDuplicate\n\"\"\"\ntype UnmarkIssueAsDuplicatePayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The issue or pull request that was marked as a duplicate.\n  \"\"\"\n  duplicate: IssueOrPullRequest\n}\n\n\"\"\"\nAutogenerated input type of UnminimizeComment\n\"\"\"\ninput UnminimizeCommentInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the subject to modify.\n  \"\"\"\n  subjectId: ID! @possibleTypes(concreteTypes: [\"CommitComment\", \"GistComment\", \"IssueComment\", \"PullRequestReviewComment\"], abstractType: \"Minimizable\")\n}\n\n\"\"\"\nAutogenerated return type of UnminimizeComment\n\"\"\"\ntype UnminimizeCommentPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The comment that was unminimized.\n  \"\"\"\n  unminimizedComment: Minimizable\n}\n\n\"\"\"\nAutogenerated input type of UnpinIssue\n\"\"\"\ninput UnpinIssueInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the issue to be unpinned\n  \"\"\"\n  issueId: ID! @possibleTypes(concreteTypes: [\"Issue\"])\n}\n\n\"\"\"\nAutogenerated return type of UnpinIssue\n\"\"\"\ntype UnpinIssuePayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The issue that was unpinned\n  \"\"\"\n  issue: Issue\n}\n\n\"\"\"\nRepresents an 'unpinned' event on a given issue or pull request.\n\"\"\"\ntype UnpinnedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Identifies the issue associated with the event.\n  \"\"\"\n  issue: Issue!\n}\n\n\"\"\"\nAutogenerated input type of UnresolveReviewThread\n\"\"\"\ninput UnresolveReviewThreadInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the thread to unresolve\n  \"\"\"\n  threadId: ID! @possibleTypes(concreteTypes: [\"PullRequestReviewThread\"])\n}\n\n\"\"\"\nAutogenerated return type of UnresolveReviewThread\n\"\"\"\ntype UnresolveReviewThreadPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The thread to resolve.\n  \"\"\"\n  thread: PullRequestReviewThread\n}\n\n\"\"\"\nRepresents an 'unsubscribed' event on a given `Subscribable`.\n\"\"\"\ntype UnsubscribedEvent implements Node {\n  \"\"\"\n  Identifies the actor who performed the event.\n  \"\"\"\n  actor: Actor\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n  id: ID!\n\n  \"\"\"\n  Object referenced by event.\n  \"\"\"\n  subscribable: Subscribable!\n}\n\n\"\"\"\nEntities that can be updated.\n\"\"\"\ninterface Updatable {\n  \"\"\"\n  Check if the current viewer can update this object.\n  \"\"\"\n  viewerCanUpdate: Boolean!\n}\n\n\"\"\"\nComments that can be updated.\n\"\"\"\ninterface UpdatableComment {\n  \"\"\"\n  Reasons why the current viewer can not update this comment.\n  \"\"\"\n  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!\n}\n\n\"\"\"\nAutogenerated input type of UpdateBranchProtectionRule\n\"\"\"\ninput UpdateBranchProtectionRuleInput {\n  \"\"\"\n  The global relay id of the branch protection rule to be updated.\n  \"\"\"\n  branchProtectionRuleId: ID! @possibleTypes(concreteTypes: [\"BranchProtectionRule\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  Will new commits pushed to matching branches dismiss pull request review approvals.\n  \"\"\"\n  dismissesStaleReviews: Boolean\n\n  \"\"\"\n  Can admins overwrite branch protection.\n  \"\"\"\n  isAdminEnforced: Boolean\n\n  \"\"\"\n  The glob-like pattern used to determine matching branches.\n  \"\"\"\n  pattern: String\n\n  \"\"\"\n  A list of User or Team IDs allowed to push to matching branches.\n  \"\"\"\n  pushActorIds: [ID!]\n\n  \"\"\"\n  Number of approving reviews required to update matching branches.\n  \"\"\"\n  requiredApprovingReviewCount: Int\n\n  \"\"\"\n  List of required status check contexts that must pass for commits to be accepted to matching branches.\n  \"\"\"\n  requiredStatusCheckContexts: [String!]\n\n  \"\"\"\n  Are approving reviews required to update matching branches.\n  \"\"\"\n  requiresApprovingReviews: Boolean\n\n  \"\"\"\n  Are reviews from code owners required to update matching branches.\n  \"\"\"\n  requiresCodeOwnerReviews: Boolean\n\n  \"\"\"\n  Are commits required to be signed.\n  \"\"\"\n  requiresCommitSignatures: Boolean\n\n  \"\"\"\n  Are status checks required to update matching branches.\n  \"\"\"\n  requiresStatusChecks: Boolean\n\n  \"\"\"\n  Are branches required to be up to date before merging.\n  \"\"\"\n  requiresStrictStatusChecks: Boolean\n\n  \"\"\"\n  Is pushing to matching branches restricted.\n  \"\"\"\n  restrictsPushes: Boolean\n\n  \"\"\"\n  Is dismissal of pull request reviews restricted.\n  \"\"\"\n  restrictsReviewDismissals: Boolean\n\n  \"\"\"\n  A list of User or Team IDs allowed to dismiss reviews on pull requests targeting matching branches.\n  \"\"\"\n  reviewDismissalActorIds: [ID!]\n}\n\n\"\"\"\nAutogenerated return type of UpdateBranchProtectionRule\n\"\"\"\ntype UpdateBranchProtectionRulePayload {\n  \"\"\"\n  The newly created BranchProtectionRule.\n  \"\"\"\n  branchProtectionRule: BranchProtectionRule\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessAllowPrivateRepositoryForkingSetting\n\"\"\"\ninput UpdateBusinessAllowPrivateRepositoryForkingSettingInput {\n  \"\"\"\n  The ID of the business on which to set the allow private repository forking setting.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The value for the allow private repository forking setting on the business.\n  \"\"\"\n  settingValue: BusinessEnabledDisabledSettingValue!\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessAllowPrivateRepositoryForkingSetting\n\"\"\"\ntype UpdateBusinessAllowPrivateRepositoryForkingSettingPayload {\n  \"\"\"\n  The business with the updated allow private repository forking setting.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A message confirming the result of updating the allow private repository forking setting.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessDefaultRepositoryPermissionSetting\n\"\"\"\ninput UpdateBusinessDefaultRepositoryPermissionSettingInput {\n  \"\"\"\n  The ID of the business on which to set the default repository permission setting.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The value for the default repository permission setting on the business.\n  \"\"\"\n  settingValue: BusinessDefaultRepositoryPermissionSettingValue!\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessDefaultRepositoryPermissionSetting\n\"\"\"\ntype UpdateBusinessDefaultRepositoryPermissionSettingPayload {\n  \"\"\"\n  The business with the updated default repository permission setting.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A message confirming the result of updating the default repository permission setting.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessMembersCanChangeRepositoryVisibilitySetting\n\"\"\"\ninput UpdateBusinessMembersCanChangeRepositoryVisibilitySettingInput {\n  \"\"\"\n  The ID of the business on which to set the members can change repository visibility setting.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The value for the members can change repository visibility setting on the business.\n  \"\"\"\n  settingValue: BusinessEnabledDisabledSettingValue!\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessMembersCanChangeRepositoryVisibilitySetting\n\"\"\"\ntype UpdateBusinessMembersCanChangeRepositoryVisibilitySettingPayload {\n  \"\"\"\n  The business with the updated members can change repository visibility setting.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A message confirming the result of updating the members can change repository visibility setting.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessMembersCanCreateRepositoriesSetting\n\"\"\"\ninput UpdateBusinessMembersCanCreateRepositoriesSettingInput {\n  \"\"\"\n  The ID of the business on which to set the members can create repositories setting.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The value for the members can create repositories setting on the business.\n  \"\"\"\n  settingValue: BusinessMembersCanCreateRepositoriesSettingValue!\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessMembersCanCreateRepositoriesSetting\n\"\"\"\ntype UpdateBusinessMembersCanCreateRepositoriesSettingPayload {\n  \"\"\"\n  The business with the updated members can create repositories setting.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A message confirming the result of updating the members can create repositories setting.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessMembersCanDeleteIssuesSetting\n\"\"\"\ninput UpdateBusinessMembersCanDeleteIssuesSettingInput {\n  \"\"\"\n  The ID of the business on which to set the members can delete issues setting.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The value for the members can delete issues setting on the business.\n  \"\"\"\n  settingValue: BusinessEnabledDisabledSettingValue!\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessMembersCanDeleteIssuesSetting\n\"\"\"\ntype UpdateBusinessMembersCanDeleteIssuesSettingPayload {\n  \"\"\"\n  The business with the updated members can delete issues setting.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A message confirming the result of updating the members can delete issues setting.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessMembersCanDeleteRepositoriesSetting\n\"\"\"\ninput UpdateBusinessMembersCanDeleteRepositoriesSettingInput {\n  \"\"\"\n  The ID of the business on which to set the members can delete repositories setting.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The value for the members can delete repositories setting on the business.\n  \"\"\"\n  settingValue: BusinessEnabledDisabledSettingValue!\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessMembersCanDeleteRepositoriesSetting\n\"\"\"\ntype UpdateBusinessMembersCanDeleteRepositoriesSettingPayload {\n  \"\"\"\n  The business with the updated members can delete repositories setting.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A message confirming the result of updating the members can delete repositories setting.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessMembersCanInviteCollaboratorsSetting\n\"\"\"\ninput UpdateBusinessMembersCanInviteCollaboratorsSettingInput {\n  \"\"\"\n  The ID of the business on which to set the members can invite collaborators setting.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The value for the members can invite collaborators setting on the business.\n  \"\"\"\n  settingValue: BusinessEnabledDisabledSettingValue!\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessMembersCanInviteCollaboratorsSetting\n\"\"\"\ntype UpdateBusinessMembersCanInviteCollaboratorsSettingPayload {\n  \"\"\"\n  The business with the updated members can invite collaborators setting.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A message confirming the result of updating the members can invite collaborators setting.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessMembersCanUpdateProtectedBranchesSetting\n\"\"\"\ninput UpdateBusinessMembersCanUpdateProtectedBranchesSettingInput {\n  \"\"\"\n  The ID of the business on which to set the members can update protected branches setting.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The value for the members can update protected branches setting on the business.\n  \"\"\"\n  settingValue: BusinessEnabledDisabledSettingValue!\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessMembersCanUpdateProtectedBranchesSetting\n\"\"\"\ntype UpdateBusinessMembersCanUpdateProtectedBranchesSettingPayload {\n  \"\"\"\n  The business with the updated members can update protected branches setting.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A message confirming the result of updating the members can update protected branches setting.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessOrganizationProjectsSetting\n\"\"\"\ninput UpdateBusinessOrganizationProjectsSettingInput {\n  \"\"\"\n  The ID of the business on which to set the organization projects setting.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The value for the organization projects setting on the business.\n  \"\"\"\n  settingValue: BusinessEnabledDisabledSettingValue!\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessOrganizationProjectsSetting\n\"\"\"\ntype UpdateBusinessOrganizationProjectsSettingPayload {\n  \"\"\"\n  The business with the updated organization projects setting.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A message confirming the result of updating the organization projects setting.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessProfile\n\"\"\"\ninput UpdateBusinessProfileInput {\n  \"\"\"\n  The Business ID to update.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The description of the business.\n  \"\"\"\n  description: String\n\n  \"\"\"\n  The location of the business\n  \"\"\"\n  location: String\n\n  \"\"\"\n  The name of business.\n  \"\"\"\n  name: String\n\n  \"\"\"\n  The URL of the business's website\n  \"\"\"\n  websiteUrl: String\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessProfile\n\"\"\"\ntype UpdateBusinessProfilePayload {\n  \"\"\"\n  The updated business.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessRepositoryProjectsSetting\n\"\"\"\ninput UpdateBusinessRepositoryProjectsSettingInput {\n  \"\"\"\n  The ID of the business on which to set the repository projects setting.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The value for the repository projects setting on the business.\n  \"\"\"\n  settingValue: BusinessEnabledDisabledSettingValue!\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessRepositoryProjectsSetting\n\"\"\"\ntype UpdateBusinessRepositoryProjectsSettingPayload {\n  \"\"\"\n  The business with the updated repository projects setting.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A message confirming the result of updating the repository projects setting.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessTeamDiscussionsSetting\n\"\"\"\ninput UpdateBusinessTeamDiscussionsSettingInput {\n  \"\"\"\n  The ID of the business on which to set the team discussions setting.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The value for the team discussions setting on the business.\n  \"\"\"\n  settingValue: BusinessEnabledDisabledSettingValue!\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessTeamDiscussionsSetting\n\"\"\"\ntype UpdateBusinessTeamDiscussionsSettingPayload {\n  \"\"\"\n  The business with the updated team discussions setting.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A message confirming the result of updating the team discussions setting.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateBusinessTwoFactorAuthenticationRequiredSetting\n\"\"\"\ninput UpdateBusinessTwoFactorAuthenticationRequiredSettingInput {\n  \"\"\"\n  The ID of the business on which to set the two factor authentication required setting.\n  \"\"\"\n  businessId: ID! @possibleTypes(concreteTypes: [\"Business\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The value for the two factor authentication required setting on the business.\n  \"\"\"\n  settingValue: BusinessEnabledSettingValue!\n}\n\n\"\"\"\nAutogenerated return type of UpdateBusinessTwoFactorAuthenticationRequiredSetting\n\"\"\"\ntype UpdateBusinessTwoFactorAuthenticationRequiredSettingPayload {\n  \"\"\"\n  The business with the updated two factor authentication required setting.\n  \"\"\"\n  business: Business @preview(toggledBy: \"gwenpool-preview\")\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  A message confirming the result of updating the two factor authentication required setting.\n  \"\"\"\n  message: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateCheckRun\n\"\"\"\ninput UpdateCheckRunInput @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  Possible further actions the integrator can perform, which a user may trigger.\n  \"\"\"\n  actions: [CheckRunAction!]\n\n  \"\"\"\n  The node of the check.\n  \"\"\"\n  checkRunId: ID! @possibleTypes(concreteTypes: [\"CheckRun\"])\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The time that the check run finished.\n  \"\"\"\n  completedAt: DateTime\n\n  \"\"\"\n  The final conclusion of the check.\n  \"\"\"\n  conclusion: CheckConclusionState\n\n  \"\"\"\n  The URL of the integrator's site that has the full details of the check.\n  \"\"\"\n  detailsUrl: URI\n\n  \"\"\"\n  A reference for the run on the integrator's system.\n  \"\"\"\n  externalId: String\n\n  \"\"\"\n  The name of the check.\n  \"\"\"\n  name: String\n\n  \"\"\"\n  Descriptive details about the run.\n  \"\"\"\n  output: CheckRunOutput\n\n  \"\"\"\n  The node ID of the repository.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n\n  \"\"\"\n  The time that the check run began.\n  \"\"\"\n  startedAt: DateTime\n\n  \"\"\"\n  The current status.\n  \"\"\"\n  status: RequestableCheckStatusState\n}\n\n\"\"\"\nAutogenerated return type of UpdateCheckRun\n\"\"\"\ntype UpdateCheckRunPayload @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The updated check run.\n  \"\"\"\n  checkRun: CheckRun\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n}\n\n\"\"\"\nAutogenerated input type of UpdateCheckSuitePreferences\n\"\"\"\ninput UpdateCheckSuitePreferencesInput @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  The check suite preferences to modify.\n  \"\"\"\n  autoTriggerPreferences: [CheckSuiteAutoTriggerPreference!]!\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the repository.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n}\n\n\"\"\"\nAutogenerated return type of UpdateCheckSuitePreferences\n\"\"\"\ntype UpdateCheckSuitePreferencesPayload @preview(toggledBy: \"antiope-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The updated repository.\n  \"\"\"\n  repository: Repository\n}\n\n\"\"\"\nAutogenerated input type of UpdateIssueComment\n\"\"\"\ninput UpdateIssueCommentInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  The updated text of the comment.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the IssueComment to modify.\n  \"\"\"\n  id: ID! @possibleTypes(concreteTypes: [\"IssueComment\"])\n}\n\n\"\"\"\nAutogenerated return type of UpdateIssueComment\n\"\"\"\ntype UpdateIssueCommentPayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The updated comment.\n  \"\"\"\n  issueComment: IssueComment\n}\n\n\"\"\"\nAutogenerated input type of UpdateIssue\n\"\"\"\ninput UpdateIssueInput @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  An array of Node IDs of users for this issue.\n  \"\"\"\n  assigneeIds: [ID!] @possibleTypes(concreteTypes: [\"User\"])\n\n  \"\"\"\n  The body for the issue description.\n  \"\"\"\n  body: String\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the Issue to modify.\n  \"\"\"\n  id: ID! @possibleTypes(concreteTypes: [\"Issue\"])\n\n  \"\"\"\n  An array of Node IDs of labels for this issue.\n  \"\"\"\n  labelIds: [ID!] @possibleTypes(concreteTypes: [\"Label\"])\n\n  \"\"\"\n  The Node ID of the milestone for this issue.\n  \"\"\"\n  milestoneId: ID @possibleTypes(concreteTypes: [\"Milestone\"])\n\n  \"\"\"\n  An array of Node IDs for projects associated with this issue.\n  \"\"\"\n  projectIds: [ID!]\n\n  \"\"\"\n  The desired issue state.\n  \"\"\"\n  state: IssueState\n\n  \"\"\"\n  The title for the issue.\n  \"\"\"\n  title: String\n}\n\n\"\"\"\nAutogenerated return type of UpdateIssue\n\"\"\"\ntype UpdateIssuePayload @preview(toggledBy: \"starfire-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The issue.\n  \"\"\"\n  issue: Issue\n}\n\n\"\"\"\nAutogenerated input type of UpdateProjectCard\n\"\"\"\ninput UpdateProjectCardInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  Whether or not the ProjectCard should be archived\n  \"\"\"\n  isArchived: Boolean\n\n  \"\"\"\n  The note of ProjectCard.\n  \"\"\"\n  note: String\n\n  \"\"\"\n  The ProjectCard ID to update.\n  \"\"\"\n  projectCardId: ID! @possibleTypes(concreteTypes: [\"ProjectCard\"])\n}\n\n\"\"\"\nAutogenerated return type of UpdateProjectCard\n\"\"\"\ntype UpdateProjectCardPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The updated ProjectCard.\n  \"\"\"\n  projectCard: ProjectCard\n}\n\n\"\"\"\nAutogenerated input type of UpdateProjectColumn\n\"\"\"\ninput UpdateProjectColumnInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The name of project column.\n  \"\"\"\n  name: String!\n\n  \"\"\"\n  The ProjectColumn ID to update.\n  \"\"\"\n  projectColumnId: ID! @possibleTypes(concreteTypes: [\"ProjectColumn\"])\n}\n\n\"\"\"\nAutogenerated return type of UpdateProjectColumn\n\"\"\"\ntype UpdateProjectColumnPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The updated project column.\n  \"\"\"\n  projectColumn: ProjectColumn\n}\n\n\"\"\"\nAutogenerated input type of UpdateProject\n\"\"\"\ninput UpdateProjectInput {\n  \"\"\"\n  The description of project.\n  \"\"\"\n  body: String\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The name of project.\n  \"\"\"\n  name: String\n\n  \"\"\"\n  The Project ID to update.\n  \"\"\"\n  projectId: ID! @possibleTypes(concreteTypes: [\"Project\"])\n\n  \"\"\"\n  Whether the project is public or not.\n  \"\"\"\n  public: Boolean\n\n  \"\"\"\n  Whether the project is open or closed.\n  \"\"\"\n  state: ProjectState\n}\n\n\"\"\"\nAutogenerated return type of UpdateProject\n\"\"\"\ntype UpdateProjectPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The updated project.\n  \"\"\"\n  project: Project\n}\n\n\"\"\"\nAutogenerated input type of UpdatePullRequest\n\"\"\"\ninput UpdatePullRequestInput @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  The name of the branch you want your changes pulled into. This should be an existing branch\n  on the current repository.\n  \"\"\"\n  baseRefName: String\n\n  \"\"\"\n  The contents of the pull request.\n  \"\"\"\n  body: String\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  Indicates whether maintainers can modify the pull request.\n  \"\"\"\n  maintainerCanModify: Boolean\n\n  \"\"\"\n  The Node ID of the pull request.\n  \"\"\"\n  pullRequestId: ID! @possibleTypes(concreteTypes: [\"PullRequest\"])\n\n  \"\"\"\n  The title of the pull request.\n  \"\"\"\n  title: String\n}\n\n\"\"\"\nAutogenerated return type of UpdatePullRequest\n\"\"\"\ntype UpdatePullRequestPayload @preview(toggledBy: \"ocelot-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The updated pull request.\n  \"\"\"\n  pullRequest: PullRequest\n}\n\n\"\"\"\nAutogenerated input type of UpdatePullRequestReviewComment\n\"\"\"\ninput UpdatePullRequestReviewCommentInput {\n  \"\"\"\n  The text of the comment.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the comment to modify.\n  \"\"\"\n  pullRequestReviewCommentId: ID! @possibleTypes(concreteTypes: [\"PullRequestReviewComment\"])\n}\n\n\"\"\"\nAutogenerated return type of UpdatePullRequestReviewComment\n\"\"\"\ntype UpdatePullRequestReviewCommentPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The updated comment.\n  \"\"\"\n  pullRequestReviewComment: PullRequestReviewComment\n}\n\n\"\"\"\nAutogenerated input type of UpdatePullRequestReview\n\"\"\"\ninput UpdatePullRequestReviewInput {\n  \"\"\"\n  The contents of the pull request review body.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the pull request review to modify.\n  \"\"\"\n  pullRequestReviewId: ID! @possibleTypes(concreteTypes: [\"PullRequestReview\"])\n}\n\n\"\"\"\nAutogenerated return type of UpdatePullRequestReview\n\"\"\"\ntype UpdatePullRequestReviewPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The updated pull request review.\n  \"\"\"\n  pullRequestReview: PullRequestReview\n}\n\n\"\"\"\nAutogenerated input type of UpdateSubscription\n\"\"\"\ninput UpdateSubscriptionInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The new state of the subscription.\n  \"\"\"\n  state: SubscriptionState!\n\n  \"\"\"\n  The Node ID of the subscribable object to modify.\n  \"\"\"\n  subscribableId: ID! @possibleTypes(concreteTypes: [\"Commit\", \"Issue\", \"PullRequest\", \"Repository\", \"Team\", \"TeamDiscussion\"], abstractType: \"Subscribable\")\n}\n\n\"\"\"\nAutogenerated return type of UpdateSubscription\n\"\"\"\ntype UpdateSubscriptionPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The input subscribable entity.\n  \"\"\"\n  subscribable: Subscribable\n}\n\n\"\"\"\nAutogenerated input type of UpdateTeamDiscussionComment\n\"\"\"\ninput UpdateTeamDiscussionCommentInput @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  The updated text of the comment.\n  \"\"\"\n  body: String!\n\n  \"\"\"\n  The current version of the body content.\n  \"\"\"\n  bodyVersion: String\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The ID of the comment to modify.\n  \"\"\"\n  id: ID! @possibleTypes(concreteTypes: [\"TeamDiscussionComment\"])\n}\n\n\"\"\"\nAutogenerated return type of UpdateTeamDiscussionComment\n\"\"\"\ntype UpdateTeamDiscussionCommentPayload @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The updated comment.\n  \"\"\"\n  teamDiscussionComment: TeamDiscussionComment\n}\n\n\"\"\"\nAutogenerated input type of UpdateTeamDiscussion\n\"\"\"\ninput UpdateTeamDiscussionInput @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  The updated text of the discussion.\n  \"\"\"\n  body: String\n\n  \"\"\"\n  The current version of the body content. If provided, this update operation\n  will be rejected if the given version does not match the latest version on the server.\n  \"\"\"\n  bodyVersion: String\n\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the discussion to modify.\n  \"\"\"\n  id: ID! @possibleTypes(concreteTypes: [\"TeamDiscussion\"])\n\n  \"\"\"\n  If provided, sets the pinned state of the updated discussion.\n  \"\"\"\n  pinned: Boolean\n\n  \"\"\"\n  The updated title of the discussion.\n  \"\"\"\n  title: String\n}\n\n\"\"\"\nAutogenerated return type of UpdateTeamDiscussion\n\"\"\"\ntype UpdateTeamDiscussionPayload @preview(toggledBy: \"echo-preview\") {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The updated discussion.\n  \"\"\"\n  teamDiscussion: TeamDiscussion\n}\n\n\"\"\"\nAutogenerated input type of UpdateTopics\n\"\"\"\ninput UpdateTopicsInput {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  The Node ID of the repository.\n  \"\"\"\n  repositoryId: ID! @possibleTypes(concreteTypes: [\"Repository\"])\n\n  \"\"\"\n  An array of topic names.\n  \"\"\"\n  topicNames: [String!]!\n}\n\n\"\"\"\nAutogenerated return type of UpdateTopics\n\"\"\"\ntype UpdateTopicsPayload {\n  \"\"\"\n  A unique identifier for the client performing the mutation.\n  \"\"\"\n  clientMutationId: String\n\n  \"\"\"\n  Names of the provided topics that are not valid.\n  \"\"\"\n  invalidTopicNames: [String!]\n\n  \"\"\"\n  The updated repository.\n  \"\"\"\n  repository: Repository\n}\n\n\"\"\"\nA user is an individual's account on GitHub that owns repositories and can make new content.\n\"\"\"\ntype User implements Actor & Node & RegistryPackageOwner & RegistryPackageSearch & RepositoryOwner & UniformResourceLocatable {\n  \"\"\"\n  A URL pointing to the user's public avatar.\n  \"\"\"\n  avatarUrl(\n    \"\"\"\n    The size of the resulting square image.\n    \"\"\"\n    size: Int\n  ): URI!\n\n  \"\"\"\n  The user's public profile bio.\n  \"\"\"\n  bio: String\n\n  \"\"\"\n  The user's public profile bio as HTML.\n  \"\"\"\n  bioHTML: HTML!\n\n  \"\"\"\n  A list of commit comments made by this user.\n  \"\"\"\n  commitComments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): CommitCommentConnection!\n\n  \"\"\"\n  The user's public profile company.\n  \"\"\"\n  company: String\n\n  \"\"\"\n  The user's public profile company as HTML.\n  \"\"\"\n  companyHTML: HTML!\n\n  \"\"\"\n  The collection of contributions this user has made to different repositories.\n  \"\"\"\n  contributionsCollection(\n    \"\"\"\n    Only contributions made at this time or later will be counted. If omitted, defaults to a year ago.\n    \"\"\"\n    from: DateTime\n\n    \"\"\"\n    The ID of the organization used to filter contributions.\n    \"\"\"\n    organizationID: ID\n\n    \"\"\"\n    Only contributions made before and up to and including this time will be\n    counted. If omitted, defaults to the current time.\n    \"\"\"\n    to: DateTime\n  ): ContributionsCollection!\n\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the primary key from the database.\n  \"\"\"\n  databaseId: Int\n\n  \"\"\"\n  The user's publicly visible profile email.\n  \"\"\"\n  email: String!\n\n  \"\"\"\n  A list of users the given user is followed by.\n  \"\"\"\n  followers(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): FollowerConnection!\n\n  \"\"\"\n  A list of users the given user is following.\n  \"\"\"\n  following(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): FollowingConnection!\n\n  \"\"\"\n  Find gist by repo name.\n  \"\"\"\n  gist(\n    \"\"\"\n    The gist name to find.\n    \"\"\"\n    name: String!\n  ): Gist\n\n  \"\"\"\n  A list of gist comments made by this user.\n  \"\"\"\n  gistComments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): GistCommentConnection!\n\n  \"\"\"\n  A list of the Gists the user has created.\n  \"\"\"\n  gists(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for gists returned from the connection\n    \"\"\"\n    orderBy: GistOrder\n\n    \"\"\"\n    Filters Gists according to privacy.\n    \"\"\"\n    privacy: GistPrivacy\n  ): GistConnection!\n\n  \"\"\"\n  The hovercard information for this user in a given context\n  \"\"\"\n  hovercard(\n    \"\"\"\n    The ID of the subject to get the hovercard in the context of\n    \"\"\"\n    primarySubjectId: ID\n  ): Hovercard! @preview(toggledBy: \"hagar-preview\")\n  id: ID!\n\n  \"\"\"\n  Whether or not this user is a participant in the GitHub Security Bug Bounty.\n  \"\"\"\n  isBountyHunter: Boolean!\n\n  \"\"\"\n  Whether or not this user is a participant in the GitHub Campus Experts Program.\n  \"\"\"\n  isCampusExpert: Boolean!\n\n  \"\"\"\n  Whether or not this user is a GitHub Developer Program member.\n  \"\"\"\n  isDeveloperProgramMember: Boolean!\n\n  \"\"\"\n  Whether or not this user is a GitHub employee.\n  \"\"\"\n  isEmployee: Boolean!\n\n  \"\"\"\n  Whether or not the user has marked themselves as for hire.\n  \"\"\"\n  isHireable: Boolean!\n\n  \"\"\"\n  Whether or not this user is a site administrator.\n  \"\"\"\n  isSiteAdmin: Boolean!\n\n  \"\"\"\n  Whether or not this user is the viewing user.\n  \"\"\"\n  isViewer: Boolean!\n\n  \"\"\"\n  A list of issue comments made by this user.\n  \"\"\"\n  issueComments(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): IssueCommentConnection!\n\n  \"\"\"\n  A list of issues associated with this user.\n  \"\"\"\n  issues(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Filtering options for issues returned from the connection.\n    \"\"\"\n    filterBy: IssueFilters @preview(toggledBy: \"starfire-preview\")\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    A list of label names to filter the pull requests by.\n    \"\"\"\n    labels: [String!]\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for issues returned from the connection.\n    \"\"\"\n    orderBy: IssueOrder\n\n    \"\"\"\n    A list of states to filter the issues by.\n    \"\"\"\n    states: [IssueState!]\n  ): IssueConnection!\n\n  \"\"\"\n  The user's public profile location.\n  \"\"\"\n  location: String\n\n  \"\"\"\n  The username used to login.\n  \"\"\"\n  login: String!\n\n  \"\"\"\n  The user's public profile name.\n  \"\"\"\n  name: String\n\n  \"\"\"\n  Find an organization by its login that the user belongs to.\n  \"\"\"\n  organization(\n    \"\"\"\n    The login of the organization to find.\n    \"\"\"\n    login: String!\n  ): Organization\n\n  \"\"\"\n  A list of organizations the user belongs to.\n  \"\"\"\n  organizations(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): OrganizationConnection!\n\n  \"\"\"\n  A list of repositories this user has pinned to their profile\n  \"\"\"\n  pinnedRepositories(\n    \"\"\"\n    Array of viewer's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    current viewer owns.\n    \"\"\"\n    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    If non-null, filters repositories according to whether they have been locked\n    \"\"\"\n    isLocked: Boolean\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for repositories returned from the connection\n    \"\"\"\n    orderBy: RepositoryOrder\n\n    \"\"\"\n    Array of owner's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    organization or user being viewed owns.\n    \"\"\"\n    ownerAffiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    If non-null, filters repositories according to privacy\n    \"\"\"\n    privacy: RepositoryPrivacy\n  ): RepositoryConnection!\n\n  \"\"\"\n  A list of public keys associated with this user.\n  \"\"\"\n  publicKeys(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n  ): PublicKeyConnection!\n\n  \"\"\"\n  A list of pull requests associated with this user.\n  \"\"\"\n  pullRequests(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    The base ref name to filter the pull requests by.\n    \"\"\"\n    baseRefName: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    The head ref name to filter the pull requests by.\n    \"\"\"\n    headRefName: String\n\n    \"\"\"\n    A list of label names to filter the pull requests by.\n    \"\"\"\n    labels: [String!]\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for pull requests returned from the connection.\n    \"\"\"\n    orderBy: IssueOrder\n\n    \"\"\"\n    A list of states to filter the pull requests by.\n    \"\"\"\n    states: [PullRequestState!]\n  ): PullRequestConnection!\n\n  \"\"\"\n  A list of repositories that the user owns.\n  \"\"\"\n  repositories(\n    \"\"\"\n    Array of viewer's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    current viewer owns.\n    \"\"\"\n    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    If non-null, filters repositories according to whether they are forks of another repository\n    \"\"\"\n    isFork: Boolean\n\n    \"\"\"\n    If non-null, filters repositories according to whether they have been locked\n    \"\"\"\n    isLocked: Boolean\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for repositories returned from the connection\n    \"\"\"\n    orderBy: RepositoryOrder\n\n    \"\"\"\n    Array of owner's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    organization or user being viewed owns.\n    \"\"\"\n    ownerAffiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    If non-null, filters repositories according to privacy\n    \"\"\"\n    privacy: RepositoryPrivacy\n  ): RepositoryConnection!\n\n  \"\"\"\n  A list of repositories that the user recently contributed to.\n  \"\"\"\n  repositoriesContributedTo(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    If non-null, include only the specified types of contributions. The\n    GitHub.com UI uses [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]\n    \"\"\"\n    contributionTypes: [RepositoryContributionType]\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    If true, include user repositories\n    \"\"\"\n    includeUserRepositories: Boolean\n\n    \"\"\"\n    If non-null, filters repositories according to whether they have been locked\n    \"\"\"\n    isLocked: Boolean\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for repositories returned from the connection\n    \"\"\"\n    orderBy: RepositoryOrder\n\n    \"\"\"\n    If non-null, filters repositories according to privacy\n    \"\"\"\n    privacy: RepositoryPrivacy\n  ): RepositoryConnection!\n\n  \"\"\"\n  Find Repository.\n  \"\"\"\n  repository(\n    \"\"\"\n    Name of Repository to find.\n    \"\"\"\n    name: String!\n  ): Repository\n\n  \"\"\"\n  The HTTP path for this user\n  \"\"\"\n  resourcePath: URI!\n\n  \"\"\"\n  Repositories the user has starred.\n  \"\"\"\n  starredRepositories(\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Order for connection\n    \"\"\"\n    orderBy: StarOrder\n\n    \"\"\"\n    Filters starred repositories to only return repositories owned by the viewer.\n    \"\"\"\n    ownedByViewer: Boolean\n  ): StarredRepositoryConnection!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n\n  \"\"\"\n  The HTTP URL for this user\n  \"\"\"\n  url: URI!\n\n  \"\"\"\n  Whether or not the viewer is able to follow the user.\n  \"\"\"\n  viewerCanFollow: Boolean!\n\n  \"\"\"\n  Whether or not this user is followed by the viewer.\n  \"\"\"\n  viewerIsFollowing: Boolean!\n\n  \"\"\"\n  A list of repositories the given user is watching.\n  \"\"\"\n  watching(\n    \"\"\"\n    Affiliation options for repositories returned from the connection\n    \"\"\"\n    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR, ORGANIZATION_MEMBER]\n\n    \"\"\"\n    Returns the elements in the list that come after the specified cursor.\n    \"\"\"\n    after: String\n\n    \"\"\"\n    Returns the elements in the list that come before the specified cursor.\n    \"\"\"\n    before: String\n\n    \"\"\"\n    Returns the first _n_ elements from the list.\n    \"\"\"\n    first: Int\n\n    \"\"\"\n    If non-null, filters repositories according to whether they have been locked\n    \"\"\"\n    isLocked: Boolean\n\n    \"\"\"\n    Returns the last _n_ elements from the list.\n    \"\"\"\n    last: Int\n\n    \"\"\"\n    Ordering options for repositories returned from the connection\n    \"\"\"\n    orderBy: RepositoryOrder\n\n    \"\"\"\n    Array of owner's affiliation options for repositories returned from the\n    connection. For example, OWNER will include only repositories that the\n    organization or user being viewed owns.\n    \"\"\"\n    ownerAffiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]\n\n    \"\"\"\n    If non-null, filters repositories according to privacy\n    \"\"\"\n    privacy: RepositoryPrivacy\n  ): RepositoryConnection!\n\n  \"\"\"\n  A URL pointing to the user's public website/blog.\n  \"\"\"\n  websiteUrl: URI\n}\n\n\"\"\"\nThe connection type for User.\n\"\"\"\ntype UserConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [UserEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [User]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edit on user content\n\"\"\"\ntype UserContentEdit implements Node {\n  \"\"\"\n  Identifies the date and time when the object was created.\n  \"\"\"\n  createdAt: DateTime!\n\n  \"\"\"\n  Identifies the date and time when the object was deleted.\n  \"\"\"\n  deletedAt: DateTime\n\n  \"\"\"\n  The actor who deleted this content\n  \"\"\"\n  deletedBy: Actor\n\n  \"\"\"\n  A summary of the changes for this edit\n  \"\"\"\n  diff: String\n\n  \"\"\"\n  When this content was edited\n  \"\"\"\n  editedAt: DateTime!\n\n  \"\"\"\n  The actor who edited this content\n  \"\"\"\n  editor: Actor\n  id: ID!\n\n  \"\"\"\n  Identifies the date and time when the object was last updated.\n  \"\"\"\n  updatedAt: DateTime!\n}\n\n\"\"\"\nA list of edits to content.\n\"\"\"\ntype UserContentEditConnection {\n  \"\"\"\n  A list of edges.\n  \"\"\"\n  edges: [UserContentEditEdge]\n\n  \"\"\"\n  A list of nodes.\n  \"\"\"\n  nodes: [UserContentEdit]\n\n  \"\"\"\n  Information to aid in pagination.\n  \"\"\"\n  pageInfo: PageInfo!\n\n  \"\"\"\n  Identifies the total count of items in the connection.\n  \"\"\"\n  totalCount: Int!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype UserContentEditEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: UserContentEdit\n}\n\n\"\"\"\nRepresents a user.\n\"\"\"\ntype UserEdge {\n  \"\"\"\n  A cursor for use in pagination.\n  \"\"\"\n  cursor: String!\n\n  \"\"\"\n  The item at the end of the edge.\n  \"\"\"\n  node: User\n}\n\n\"\"\"\nA hovercard context with a message describing how the viewer is related.\n\"\"\"\ntype ViewerHovercardContext implements HovercardContext @preview(toggledBy: \"hagar-preview\") {\n  \"\"\"\n  A string describing this context\n  \"\"\"\n  message: String!\n\n  \"\"\"\n  An octicon to accompany this context\n  \"\"\"\n  octicon: String!\n\n  \"\"\"\n  Identifies the user who is related to this context.\n  \"\"\"\n  viewer: User!\n}\n\n\"\"\"\nA valid x509 certificate string\n\"\"\"\nscalar X509Certificate"
  },
  {
    "path": "4-api/4_swagger/docs/docs.go",
    "content": "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n// This file was generated by swaggo/swag at\n// 2019-09-25 15:54:20.870705 +0300 MSK m=+0.021560440\n\npackage docs\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"strings\"\n\n\t\"github.com/alecthomas/template\"\n\t\"github.com/swaggo/swag\"\n)\n\nvar doc = `{\n    \"schemes\": {{ marshal .Schemes }},\n    \"swagger\": \"2.0\",\n    \"info\": {\n        \"description\": \"{{.Description}}\",\n        \"title\": \"{{.Title}}\",\n        \"termsOfService\": \"http://swagger.io/terms/\",\n        \"contact\": {\n            \"name\": \"API Support\",\n            \"url\": \"http://www.swagger.io/support\",\n            \"email\": \"support@swagger.io\"\n        },\n        \"license\": {\n            \"name\": \"Apache 2.0\",\n            \"url\": \"http://www.apache.org/licenses/LICENSE-2.0.html\"\n        },\n        \"version\": \"{{.Version}}\"\n    },\n    \"host\": \"{{.Host}}\",\n    \"basePath\": \"{{.BasePath}}\",\n    \"paths\": {\n        \"/user/{id}\": {\n            \"get\": {\n                \"description\": \"get user by ID\",\n                \"consumes\": [\n                    \"application/json\"\n                ],\n                \"produces\": [\n                    \"application/json\"\n                ],\n                \"summary\": \"Show a account\",\n                \"operationId\": \"get-user-by-int\",\n                \"parameters\": [\n                    {\n                        \"type\": \"integer\",\n                        \"description\": \"User ID\",\n                        \"name\": \"id\",\n                        \"in\": \"path\",\n                        \"required\": true\n                    }\n                ],\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"OK\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/model.User\"\n                        }\n                    },\n                    \"400\": {\n                        \"description\": \"Bad Request\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/model.Error\"\n                        }\n                    },\n                    \"404\": {\n                        \"description\": \"Not Found\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/model.Error\"\n                        }\n                    },\n                    \"500\": {\n                        \"description\": \"Internal Server Error\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/main.myError\"\n                        }\n                    }\n                }\n            }\n        }\n    },\n    \"definitions\": {\n        \"main.myError\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"error\": {\n                    \"type\": \"string\"\n                },\n                \"status\": {\n                    \"type\": \"integer\"\n                }\n            }\n        },\n        \"model.Error\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"message\": {\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"model.User\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"email\": {\n                    \"type\": \"string\"\n                },\n                \"id\": {\n                    \"type\": \"integer\"\n                },\n                \"name\": {\n                    \"type\": \"string\"\n                }\n            }\n        }\n    }\n}`\n\ntype swaggerInfo struct {\n\tVersion     string\n\tHost        string\n\tBasePath    string\n\tSchemes     []string\n\tTitle       string\n\tDescription string\n}\n\n// SwaggerInfo holds exported Swagger Info so clients can modify it\nvar SwaggerInfo = swaggerInfo{\n\tVersion:     \"1.0\",\n\tHost:        \"petstore.swagger.io\",\n\tBasePath:    \"/api/v1\",\n\tSchemes:     []string{},\n\tTitle:       \"Sample Project API\",\n\tDescription: \"This is a sample server Petstore server.\",\n}\n\ntype s struct{}\n\nfunc (s *s) ReadDoc() string {\n\tsInfo := SwaggerInfo\n\tsInfo.Description = strings.Replace(sInfo.Description, \"\\n\", \"\\\\n\", -1)\n\n\tt, err := template.New(\"swagger_info\").Funcs(template.FuncMap{\n\t\t\"marshal\": func(v interface{}) string {\n\t\t\ta, _ := json.Marshal(v)\n\t\t\treturn string(a)\n\t\t},\n\t}).Parse(doc)\n\tif err != nil {\n\t\treturn doc\n\t}\n\n\tvar tpl bytes.Buffer\n\tif err := t.Execute(&tpl, sInfo); err != nil {\n\t\treturn doc\n\t}\n\n\treturn tpl.String()\n}\n\nfunc init() {\n\tswag.Register(swag.Name, &s{})\n}\n"
  },
  {
    "path": "4-api/4_swagger/docs/swagger/swagger.json",
    "content": "{\n    \"swagger\": \"2.0\",\n    \"info\": {\n        \"description\": \"This is a sample server Petstore server.\",\n        \"title\": \"Sample Project API\",\n        \"termsOfService\": \"http://swagger.io/terms/\",\n        \"contact\": {\n            \"name\": \"API Support\",\n            \"url\": \"http://www.swagger.io/support\",\n            \"email\": \"support@swagger.io\"\n        },\n        \"license\": {\n            \"name\": \"Apache 2.0\",\n            \"url\": \"http://www.apache.org/licenses/LICENSE-2.0.html\"\n        },\n        \"version\": \"1.0\"\n    },\n    \"host\": \"petstore.swagger.io\",\n    \"basePath\": \"/api/v1\",\n    \"paths\": {\n        \"/user/{id}\": {\n            \"get\": {\n                \"description\": \"get user by ID\",\n                \"consumes\": [\n                    \"application/json\"\n                ],\n                \"produces\": [\n                    \"application/json\"\n                ],\n                \"summary\": \"Show a account\",\n                \"operationId\": \"get-user-by-int\",\n                \"parameters\": [\n                    {\n                        \"type\": \"integer\",\n                        \"description\": \"User ID\",\n                        \"name\": \"id\",\n                        \"in\": \"path\",\n                        \"required\": true\n                    }\n                ],\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"OK\",\n                        \"schema\": {\n                            \"type\": \"object\",\n                            \"$ref\": \"#/definitions/model.User\"\n                        }\n                    },\n                    \"400\": {\n                        \"description\": \"Bad Request\",\n                        \"schema\": {\n                            \"type\": \"object\",\n                            \"$ref\": \"#/definitions/model.Error\"\n                        }\n                    },\n                    \"404\": {\n                        \"description\": \"Not Found\",\n                        \"schema\": {\n                            \"type\": \"object\",\n                            \"$ref\": \"#/definitions/model.Error\"\n                        }\n                    },\n                    \"500\": {\n                        \"description\": \"Internal Server Error\",\n                        \"schema\": {\n                            \"type\": \"object\",\n                            \"$ref\": \"#/definitions/model.Error\"\n                        }\n                    }\n                }\n            }\n        }\n    },\n    \"definitions\": {\n        \"model.Error\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"message\": {\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"model.User\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"email\": {\n                    \"type\": \"string\"\n                },\n                \"id\": {\n                    \"type\": \"integer\"\n                },\n                \"name\": {\n                    \"type\": \"string\"\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "4-api/4_swagger/docs/swagger/swagger.yaml",
    "content": "basePath: /api/v1\ndefinitions:\n  model.Error:\n    properties:\n      message:\n        type: string\n    type: object\n  model.User:\n    properties:\n      email:\n        type: string\n      id:\n        type: integer\n      name:\n        type: string\n    type: object\nhost: petstore.swagger.io\ninfo:\n  contact:\n    email: support@swagger.io\n    name: API Support\n    url: http://www.swagger.io/support\n  description: This is a sample server Petstore server.\n  license:\n    name: Apache 2.0\n    url: http://www.apache.org/licenses/LICENSE-2.0.html\n  termsOfService: http://swagger.io/terms/\n  title: Sample Project API\n  version: \"1.0\"\npaths:\n  /user/{id}:\n    get:\n      consumes:\n      - application/json\n      description: get user by ID\n      operationId: get-user-by-int\n      parameters:\n      - description: User ID\n        in: path\n        name: id\n        required: true\n        type: integer\n      produces:\n      - application/json\n      responses:\n        \"200\":\n          description: OK\n          schema:\n            $ref: '#/definitions/model.User'\n            type: object\n        \"400\":\n          description: Bad Request\n          schema:\n            $ref: '#/definitions/model.Error'\n            type: object\n        \"404\":\n          description: Not Found\n          schema:\n            $ref: '#/definitions/model.Error'\n            type: object\n        \"500\":\n          description: Internal Server Error\n          schema:\n            $ref: '#/definitions/model.Error'\n            type: object\n      summary: Show a account\nswagger: \"2.0\"\n"
  },
  {
    "path": "4-api/4_swagger/docs/swagger.json",
    "content": "{\n    \"swagger\": \"2.0\",\n    \"info\": {\n        \"description\": \"This is a sample server Petstore server.\",\n        \"title\": \"Sample Project API\",\n        \"termsOfService\": \"http://swagger.io/terms/\",\n        \"contact\": {\n            \"name\": \"API Support\",\n            \"url\": \"http://www.swagger.io/support\",\n            \"email\": \"support@swagger.io\"\n        },\n        \"license\": {\n            \"name\": \"Apache 2.0\",\n            \"url\": \"http://www.apache.org/licenses/LICENSE-2.0.html\"\n        },\n        \"version\": \"1.0\"\n    },\n    \"host\": \"petstore.swagger.io\",\n    \"basePath\": \"/api/v1\",\n    \"paths\": {\n        \"/user/{id}\": {\n            \"get\": {\n                \"description\": \"get user by ID\",\n                \"consumes\": [\n                    \"application/json\"\n                ],\n                \"produces\": [\n                    \"application/json\"\n                ],\n                \"summary\": \"Show a account\",\n                \"operationId\": \"get-user-by-int\",\n                \"parameters\": [\n                    {\n                        \"type\": \"integer\",\n                        \"description\": \"User ID\",\n                        \"name\": \"id\",\n                        \"in\": \"path\",\n                        \"required\": true\n                    }\n                ],\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"OK\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/model.User\"\n                        }\n                    },\n                    \"400\": {\n                        \"description\": \"Bad Request\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/model.Error\"\n                        }\n                    },\n                    \"404\": {\n                        \"description\": \"Not Found\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/model.Error\"\n                        }\n                    },\n                    \"500\": {\n                        \"description\": \"Internal Server Error\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/main.myError\"\n                        }\n                    }\n                }\n            }\n        }\n    },\n    \"definitions\": {\n        \"main.myError\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"error\": {\n                    \"type\": \"string\"\n                },\n                \"status\": {\n                    \"type\": \"integer\"\n                }\n            }\n        },\n        \"model.Error\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"message\": {\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"model.User\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"email\": {\n                    \"type\": \"string\"\n                },\n                \"id\": {\n                    \"type\": \"integer\"\n                },\n                \"name\": {\n                    \"type\": \"string\"\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "4-api/4_swagger/docs/swagger.yaml",
    "content": "basePath: /api/v1\ndefinitions:\n  main.myError:\n    properties:\n      error:\n        type: string\n      status:\n        type: integer\n    type: object\n  model.Error:\n    properties:\n      message:\n        type: string\n    type: object\n  model.User:\n    properties:\n      email:\n        type: string\n      id:\n        type: integer\n      name:\n        type: string\n    type: object\nhost: petstore.swagger.io\ninfo:\n  contact:\n    email: support@swagger.io\n    name: API Support\n    url: http://www.swagger.io/support\n  description: This is a sample server Petstore server.\n  license:\n    name: Apache 2.0\n    url: http://www.apache.org/licenses/LICENSE-2.0.html\n  termsOfService: http://swagger.io/terms/\n  title: Sample Project API\n  version: \"1.0\"\npaths:\n  /user/{id}:\n    get:\n      consumes:\n      - application/json\n      description: get user by ID\n      operationId: get-user-by-int\n      parameters:\n      - description: User ID\n        in: path\n        name: id\n        required: true\n        type: integer\n      produces:\n      - application/json\n      responses:\n        \"200\":\n          description: OK\n          schema:\n            $ref: '#/definitions/model.User'\n        \"400\":\n          description: Bad Request\n          schema:\n            $ref: '#/definitions/model.Error'\n        \"404\":\n          description: Not Found\n          schema:\n            $ref: '#/definitions/model.Error'\n        \"500\":\n          description: Internal Server Error\n          schema:\n            $ref: '#/definitions/main.myError'\n      summary: Show a account\nswagger: \"2.0\"\n"
  },
  {
    "path": "4-api/4_swagger/main.go",
    "content": "package main\n\nimport (\n\t\"net/http\"\n\n\t_ \"github.com/go-park-mail-ru/lectures/4-api/4_swagger/docs\"\n\n\thttpSwagger \"github.com/swaggo/http-swagger\"\n)\n\n// swag init\n\ntype myError struct {\n\tStatus int\n\tError  string\n}\n\n// ShowAccount godoc\n// @Summary Show a account\n// @Description get user by ID\n// @ID get-user-by-int\n// @Accept  json\n// @Produce  json\n// @Param id path int true \"User ID\"\n// @Success 200 {object} model.User\n// @Failure 400 {object} model.Error\n// @Failure 404 {object} model.Error\n// @Failure 500 {object} myError\n// @Router /user/{id} [get]\nfunc handleUsers(w http.ResponseWriter, r *http.Request) {\n\tw.Write([]byte(`{\"status\": \"ok\"}`))\n}\n\n// @title Sample Project API\n// @version 1.0\n// @description This is a sample server Petstore server.\n// @termsOfService http://swagger.io/terms/\n\n// @contact.name API Support\n// @contact.url http://www.swagger.io/support\n// @contact.email support@swagger.io\n\n// @license.name Apache 2.0\n// @license.url http://www.apache.org/licenses/LICENSE-2.0.html\n\n// @host petstore.swagger.io\n// @BasePath /api/v1\nfunc main() {\n\n\thttp.HandleFunc(\"/docs/\", httpSwagger.WrapHandler)\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tw.Write([]byte(\"url: \" + r.URL.String()))\n\t})\n\n\thttp.ListenAndServe(\":8080\", nil)\n\n}\n"
  },
  {
    "path": "4-api/4_swagger/model/user.go",
    "content": "package model\n\ntype User struct {\n\tID    int\n\tName  string\n\tEmail string\n}\n\ntype Error struct {\n\tMessage string\n}\n"
  },
  {
    "path": "4-api/5_sessions/main.go",
    "content": "package main\n\nimport (\n\t\"math/rand\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/gorilla/mux\"\n)\n\ntype User struct {\n\tID       uint   `json:\"id\"`\n\tUsername string `json:\"username\"`\n\tPassword string `json:\"password\"`\n}\n\nvar (\n\tletterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n)\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n\ntype MyHandler struct {\n\tsessions map[string]uint\n\tusers    map[string]*User\n}\n\nfunc NewMyHandler() *MyHandler {\n\treturn &MyHandler{\n\t\tsessions: make(map[string]uint, 10),\n\t\tusers: map[string]*User{\n\t\t\t\"rvasily\": {1, \"rvasily\", \"love\"},\n\t\t},\n\t}\n}\n\n// http://127.0.0.1:8080/login?login=rvsily&password=love\n\nfunc (api *MyHandler) Login(w http.ResponseWriter, r *http.Request) {\n\n\tuser, ok := api.users[r.FormValue(\"login\")]\n\tif !ok {\n\t\thttp.Error(w, `no user`, 404)\n\t\treturn\n\t}\n\n\tif user.Password != r.FormValue(\"password\") {\n\t\thttp.Error(w, `bad pass`, 400)\n\t\treturn\n\t}\n\n\tSID := RandStringRunes(32)\n\n\tapi.sessions[SID] = user.ID\n\n\tcookie := &http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   SID,\n\t\tExpires: time.Now().Add(10 * time.Hour),\n\t}\n\thttp.SetCookie(w, cookie)\n\tw.Write([]byte(SID))\n\n}\n\nfunc (api *MyHandler) Logout(w http.ResponseWriter, r *http.Request) {\n\n\tsession, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\thttp.Error(w, `no sess`, 401)\n\t\treturn\n\t}\n\n\tif _, ok := api.sessions[session.Value]; !ok {\n\t\thttp.Error(w, `no sess`, 401)\n\t\treturn\n\t}\n\n\tdelete(api.sessions, session.Value)\n\n\tsession.Expires = time.Now().AddDate(0, 0, -1)\n\thttp.SetCookie(w, session)\n}\n\nfunc (api *MyHandler) Root(w http.ResponseWriter, r *http.Request) {\n\tauthorized := false\n\tsession, err := r.Cookie(\"session_id\")\n\tif err == nil && session != nil {\n\t\t_, authorized = api.sessions[session.Value]\n\t}\n\n\tif authorized {\n\t\tw.Write([]byte(\"autrorized\"))\n\t} else {\n\t\tw.Write([]byte(\"not autrorized\"))\n\t}\n}\n\nfunc main() {\n\tr := mux.NewRouter()\n\n\tapi := NewMyHandler()\n\tr.HandleFunc(\"/\", api.Root)\n\tr.HandleFunc(\"/login\", api.Login)\n\tr.HandleFunc(\"/logout\", api.Logout)\n\n\thttp.ListenAndServe(\":8080\", r)\n}\n"
  },
  {
    "path": "4-api/6_jwt/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\tjwt \"github.com/dgrijalva/jwt-go\"\n)\n\nvar SECRET = []byte(\"myawesomesecret\")\n\n// http://127.0.0.1:8080/login?username=rvasily\n\nfunc main() {\n\thttp.HandleFunc(\"/login\", func(w http.ResponseWriter, r *http.Request) {\n\n\t\t// if r.Method != http.MethodPost {\n\t\t// \tw.WriteHeader(http.StatusBadRequest)\n\t\t// \treturn\n\t\t// }\n\n\t\ttoken := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{\n\t\t\t\"username\": r.FormValue(\"username\"),\n\t\t})\n\n\t\tstr, err := token.SignedString(SECRET)\n\t\tif err != nil {\n\t\t\tw.Write([]byte(\"=(\" + err.Error()))\n\t\t\treturn\n\t\t}\n\n\t\tcookie := &http.Cookie{\n\t\t\tName:  \"session_id\",\n\t\t\tValue: str,\n\t\t}\n\n\t\thttp.SetCookie(w, cookie)\n\t\tw.Write([]byte(str))\n\t})\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tcookie, err := r.Cookie(\"session_id\")\n\t\tif err != nil {\n\t\t\tw.Write([]byte(\"=(\"))\n\t\t\treturn\n\t\t}\n\t\ttoken, err := jwt.Parse(cookie.Value, func(token *jwt.Token) (interface{}, error) {\n\t\t\tif _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"Unexpected signing method: %v\", token.Header[\"alg\"])\n\t\t\t}\n\n\t\t\treturn SECRET, nil\n\t\t})\n\n\t\tif claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {\n\t\t\tw.Write([]byte(\"hello \" + claims[\"username\"].(string)))\n\t\t\treturn\n\t\t}\n\t\tw.Write([]byte(\"not authorized\"))\n\t\tfmt.Println(err)\n\t})\n\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "4-api/7_oauth/main.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"net/http\"\n\n\t\"golang.org/x/oauth2\"\n\t\"golang.org/x/oauth2/vk\"\n)\n\nconst (\n\tAPP_ID     = \"7065390\"\n\tAPP_KEY    = \"cQZe3Vvo4mHotmetUdXK\"\n\tAPP_SECRET = \"1bbf49951bbf49951bbf49953b1bd486bb11bbf1bbf4995468b3d76e2cb2114610654e0\"\n\tAPI_URL    = \"https://api.vk.com/method/users.get?fields=email,photo_50&access_token=%s&v=5.131\"\n)\n\ntype Response struct {\n\tResponse []struct {\n\t\tFirstName string `json:\"first_name\"`\n\t\tPhoto     string `json:\"photo_50\"`\n\t}\n}\n\n// https://oauth.vk.com/authorize?client_id=7065390&redirect_uri=http://localhost:8080/&response_type=code&scope=email\n\nfunc main() {\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tctx := r.Context()\n\t\tcode := r.FormValue(\"code\")\n\t\tconf := oauth2.Config{\n\t\t\tClientID:     APP_ID,\n\t\t\tClientSecret: APP_KEY,\n\t\t\tRedirectURL:  \"http://localhost:8080/\",\n\t\t\tEndpoint:     vk.Endpoint,\n\t\t}\n\n\t\ttoken, err := conf.Exchange(ctx, code)\n\t\tif err != nil {\n\t\t\tlog.Println(\"cannot exchange\", err)\n\t\t\tw.Write([]byte(\"=(\"))\n\t\t\treturn\n\t\t}\n\n\t\tclient := conf.Client(ctx, token)\n\t\tresp, err := client.Get(fmt.Sprintf(API_URL, token.AccessToken))\n\t\tif err != nil {\n\t\t\tlog.Println(\"cannot request data\", err)\n\t\t\tw.Write([]byte(\"=(\"))\n\t\t\treturn\n\t\t}\n\n\t\tdefer resp.Body.Close()\n\n\t\tbody, err := ioutil.ReadAll(resp.Body)\n\t\tif err != nil {\n\t\t\tlog.Println(\"cannot read buffer\", err)\n\t\t\tw.Write([]byte(\"=(\"))\n\t\t\treturn\n\t\t}\n\n\t\tdata := &Response{}\n\t\tjson.Unmarshal(body, data)\n\n\t\tw.Write([]byte(`\n\t\t<div>\n\t\t\t<img src=\"` + data.Response[0].Photo + `\"/>\n\t\t\t` + data.Response[0].FirstName + `\n\t\t</div>\n\t\t`))\n\t})\n\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "5-architecture/0_bad_example/api.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"math/rand\"\n\t\"net/http\"\n)\n\ntype User struct {\n\tLogin    string `json:\"login\"`\n\tPassword string `json:\"password\"`\n}\n\ntype TODO struct {\n\tText string `json:\"text\"`\n}\n\nvar (\n\tuserDB = map[string]User{\n\t\t\"predefined\": {\n\t\t\tLogin:    \"predefined\",\n\t\t\tPassword: \"123\",\n\t\t},\n\t}\n\tsessionDB = map[string]string{\n\t\t\"predefined\": \"predefined\",\n\t}\n\ttodoDB = map[string][]TODO{\n\t\t\"predefined\": {{Text: \"first thing\"}, {Text: \"second thing\"}},\n\t}\n)\n\nfunc genRequestID() string {\n\treturn fmt.Sprintf(\"%016x\", rand.Int())[:10]\n}\n\nfunc createUserHandler(w http.ResponseWriter, r *http.Request) {\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\tlog.Printf(\"panic during request: %s\", err)\n\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\tw.Write([]byte(\"internal error\"))\n\t\t}\n\t}()\n\n\trequestID := genRequestID()\n\tlog.Printf(\"incoming request [rid=%s] %s %q\", requestID, r.Method, r.URL)\n\n\tswitch r.Method {\n\t// curl 'http://127.0.0.1:8080/user' --cookie \"session=78629a0f5f3f164f\"\n\tcase http.MethodGet:\n\t\tsessionCookie, err := r.Cookie(\"session\")\n\t\tif err != nil {\n\t\t\tw.WriteHeader(http.StatusUnauthorized)\n\t\t\tw.Write([]byte(\"unauthorized\"))\n\t\t\treturn\n\t\t}\n\n\t\tusername := sessionDB[sessionCookie.Value]\n\t\tuser, ok := userDB[username]\n\t\tif !ok {\n\t\t\tpanic(\"user not exists\")\n\t\t}\n\n\t\tres, _ := json.Marshal(user)\n\n\t\tw.WriteHeader(http.StatusOK)\n\t\tw.Write(res)\n\n\t// curl 'http://127.0.0.1:8080/user' -X POST -v -d '{\"login\": \"user\", \"password\": \"123\"}'\n\tcase http.MethodPost:\n\t\tbody, err := ioutil.ReadAll(r.Body)\n\t\tif err != nil {\n\t\t\tpanic(\"request body read failure\")\n\t\t}\n\n\t\tvar user User\n\t\terr = json.Unmarshal(body, &user)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"[rid=%s] unmarshal failure: %s\", requestID, err)\n\t\t\tw.WriteHeader(http.StatusBadRequest)\n\t\t\tw.Write([]byte(\"bad body\"))\n\t\t\treturn\n\t\t}\n\n\t\tuserDB[user.Login] = user\n\n\t\tsessionID := fmt.Sprintf(\"%016x\", rand.Int())\n\t\tsessionDB[sessionID] = user.Login\n\n\t\thttp.SetCookie(w, &http.Cookie{\n\t\t\tName:  \"session\",\n\t\t\tValue: sessionID,\n\t\t\tPath:  \"/\",\n\t\t})\n\t\tw.WriteHeader(200)\n\n\tdefault:\n\t\tw.WriteHeader(http.StatusNotFound)\n\t}\n}\n\nfunc allUsersHandler(w http.ResponseWriter, r *http.Request) {\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\tlog.Printf(\"panic during request: %s\", err)\n\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\tw.Write([]byte(\"internal error\"))\n\t\t}\n\t}()\n\n\trequestID := genRequestID()\n\tlog.Printf(\"incoming request [rid=%s] %s %q\", requestID, r.Method, r.URL)\n\n\tswitch r.Method {\n\tcase http.MethodGet:\n\t\tresponse, err := json.Marshal(userDB)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\n\t\tw.WriteHeader(200)\n\t\tw.Write(response)\n\n\tdefault:\n\t\tw.WriteHeader(http.StatusNotFound)\n\t}\n}\n\nfunc todoHandler(w http.ResponseWriter, r *http.Request) {\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\tlog.Printf(\"panic during request: %s\", err)\n\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\tw.Write([]byte(\"internal error\"))\n\t\t}\n\t}()\n\n\trequestID := genRequestID()\n\tlog.Printf(\"incoming request [rid=%s] %s %q\", requestID, r.Method, r.URL)\n\n\tsessionCookie, err := r.Cookie(\"session\")\n\tif err != nil {\n\t\tw.WriteHeader(http.StatusUnauthorized)\n\t\tw.Write([]byte(\"unauthorized\"))\n\t\treturn\n\t}\n\n\tusername := sessionDB[sessionCookie.Value]\n\n\tswitch r.Method {\n\tcase http.MethodGet:\n\t\ttodos, _ := json.Marshal(todoDB[username])\n\t\tw.WriteHeader(http.StatusOK)\n\t\tw.Write(todos)\n\n\tcase http.MethodPost:\n\t\tbody, err := ioutil.ReadAll(r.Body)\n\t\tif err != nil {\n\t\t\tpanic(\"request body read failure\")\n\t\t}\n\n\t\tvar todo TODO\n\t\tjson.Unmarshal(body, &todo)\n\t\ttodoDB[username] = append(todoDB[username], todo)\n\n\t\tw.WriteHeader(200)\n\t\tw.Write([]byte(\"ok\"))\n\n\tdefault:\n\t\tw.WriteHeader(404)\n\t\tw.Write([]byte(\"not exists\"))\n\t}\n}\n\nfunc main() {\n\tuserMux := http.NewServeMux()\n\n\tuserMux.HandleFunc(\"/user\", createUserHandler)\n\tuserMux.HandleFunc(\"/users\", allUsersHandler)\n\tuserMux.HandleFunc(\"/todo\", todoHandler)\n\n\tlog.Println(\"listening on 127.0.0.1:8080\")\n\tlog.Fatal(http.ListenAndServe(\"127.0.0.1:8080\", userMux))\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/cmd/crudapp/main.go",
    "content": "package main\n\nimport (\n\t\"html/template\"\n\t\"net/http\"\n\n\t\"crudapp/internal/crudapp/middleware\"\n\titems_delivery \"crudapp/internal/pkg/items/delivery\"\n\titems_repo \"crudapp/internal/pkg/items/repository\"\n\t\"crudapp/internal/pkg/session\"\n\tuser_delivery \"crudapp/internal/pkg/user/delivery\"\n\tuser_repo \"crudapp/internal/pkg/user/repository\"\n\n\t\"github.com/gorilla/mux\"\n\t\"go.uber.org/zap\"\n)\n\nfunc main() {\n\ttemplates := template.Must(template.ParseGlob(\"./templates/*\"))\n\n\tsm := session.NewSessionsMem()\n\tzapLogger, _ := zap.NewProduction()\n\tdefer zapLogger.Sync() // flushes buffer, if any\n\tlogger := zapLogger.Sugar()\n\n\tuserRepo := user_repo.NewUserRepo()\n\titemsRepo := items_repo.NewRepo()\n\n\tuserHandler := &user_delivery.UserHandler{\n\t\tTmpl:     templates,\n\t\tUserRepo: userRepo,\n\t\tLogger:   logger,\n\t\tSessions: sm,\n\t}\n\n\thandlers := &items_delivery.ItemsHandler{\n\t\tTmpl:      templates,\n\t\tLogger:    logger,\n\t\tItemsRepo: itemsRepo,\n\t}\n\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/\", userHandler.Index).Methods(\"GET\")\n\tr.HandleFunc(\"/login\", userHandler.Login).Methods(\"POST\")\n\tr.HandleFunc(\"/logout\", userHandler.Logout).Methods(\"POST\")\n\n\tr.HandleFunc(\"/items\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.AddForm).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.Add).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Edit).Methods(\"GET\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Update).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Delete).Methods(\"DELETE\")\n\n\tmux := middleware.Auth(sm, r)\n\tmux = middleware.AccessLog(logger, mux)\n\tmux = middleware.Panic(mux)\n\n\taddr := \":8080\"\n\tlogger.Infow(\"starting server\",\n\t\t\"type\", \"START\",\n\t\t\"addr\", addr,\n\t)\n\thttp.ListenAndServe(addr, mux)\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/file_tree.txt",
    "content": "? tree\n.\n├── bin\n    crudapp_auth\n    crudapp\n├── cmd\n│   └── crudapp\n│       └── main.go\n├── go.mod\n├── go.sum\n├── pkg\n│   ├── handlers\n│   │   ├── items.go\n│   │   └── user.go\n│   ├── items\n│   │   ├── item.go\n│   │   └── repo.go\n│   ├── middleware\n│   │   ├── accesslog.go\n│   │   ├── auth.go\n│   │   └── panic.go\n│   ├── session\n│   │   ├── manager.go\n│   │   └── session.go\n│   └── user\n│       ├── user.go\n│       └── repo.go\n├── readme.md\n└── templates\n    ├── create.html\n    ├── edit.html\n    ├── index.html\n    └── login.html\n\n10 directories, 18 files"
  },
  {
    "path": "5-architecture/10_crudapp/go.mod",
    "content": "module crudapp\n\ngo 1.13\n\nrequire (\n\tgithub.com/golang/mock v1.4.4\n\tgithub.com/gorilla/mux v1.7.3\n\tgithub.com/gorilla/schema v1.1.0\n\tgithub.com/stretchr/testify v1.4.0\n\tgo.uber.org/zap v1.12.0\n)\n"
  },
  {
    "path": "5-architecture/10_crudapp/go.sum",
    "content": "github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=\ngithub.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=\ngithub.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=\ngithub.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngo.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=\ngo.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=\ngo.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=\ngo.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\nhonnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/crudapp/middleware/accesslog.go",
    "content": "package middleware\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"go.uber.org/zap\"\n)\n\nfunc AccessLog(logger *zap.SugaredLogger, next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tfmt.Println(\"access log middleware\")\n\t\tstart := time.Now()\n\t\tnext.ServeHTTP(w, r)\n\t\tlogger.Infow(\"New request\",\n\t\t\t\"method\", r.Method,\n\t\t\t\"remote_addr\", r.RemoteAddr,\n\t\t\t\"url\", r.URL.Path,\n\t\t\t\"time\", time.Since(start),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/crudapp/middleware/auth.go",
    "content": "package middleware\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"crudapp/internal/pkg/models\"\n\t\"crudapp/internal/pkg/session\"\n)\n\nvar (\n\tnoAuthUrls = map[string]struct{}{\n\t\t\"/login\": struct{}{},\n\t}\n\tnoSessUrls = map[string]struct{}{\n\t\t\"/\": struct{}{},\n\t}\n)\n\nfunc Auth(sm *session.SessionsManager, next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tfmt.Println(\"auth middleware\")\n\t\tif _, ok := noAuthUrls[r.URL.Path]; ok {\n\t\t\tnext.ServeHTTP(w, r)\n\t\t\treturn\n\t\t}\n\t\tsess, err := sm.Check(r)\n\t\t_, canbeWithouthSess := noSessUrls[r.URL.Path]\n\t\tif err != nil && !canbeWithouthSess {\n\t\t\tfmt.Println(\"no auth\")\n\t\t\thttp.Redirect(w, r, \"/\", 302)\n\t\t\treturn\n\t\t}\n\t\tctx := context.WithValue(r.Context(), models.SessionKey, sess)\n\t\tnext.ServeHTTP(w, r.WithContext(ctx))\n\t})\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/crudapp/middleware/panic.go",
    "content": "package middleware\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc Panic(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tfmt.Println(\"panicMiddleware\", r.URL.Path)\n\t\tdefer func() {\n\t\t\tif err := recover(); err != nil {\n\t\t\t\tfmt.Println(\"recovered\", err)\n\t\t\t\thttp.Error(w, \"Internal server error\", 500)\n\t\t\t}\n\t\t}()\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/pkg/items/delivery/items.go",
    "content": "package delivery\n\nimport (\n\t\"crudapp/internal/pkg/items\"\n\t\"encoding/json\"\n\t\"html/template\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"crudapp/internal/pkg/models\"\n\n\t\"github.com/gorilla/mux\"\n\t\"github.com/gorilla/schema\"\n\t\"go.uber.org/zap\"\n)\n\ntype ItemsHandler struct {\n\tTmpl      *template.Template\n\tItemsRepo items.Repository\n\tLogger    *zap.SugaredLogger\n}\n\nfunc (h *ItemsHandler) List(w http.ResponseWriter, r *http.Request) {\n\telems, err := h.ItemsRepo.GetAll()\n\tif err != nil {\n\t\thttp.Error(w, `DB err`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"index.html\", struct {\n\t\tItems []*models.Item\n\t}{\n\t\tItems: elems,\n\t})\n\tif err != nil {\n\t\thttp.Error(w, `Template errror`, http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *ItemsHandler) AddForm(w http.ResponseWriter, r *http.Request) {\n\terr := h.Tmpl.ExecuteTemplate(w, \"create.html\", nil)\n\tif err != nil {\n\t\thttp.Error(w, `Template errror`, http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *ItemsHandler) Add(w http.ResponseWriter, r *http.Request) {\n\tr.ParseForm()\n\titem := new(models.Item)\n\tdecoder := schema.NewDecoder()\n\tdecoder.IgnoreUnknownKeys(true)\n\terr := decoder.Decode(item, r.PostForm)\n\tif err != nil {\n\t\thttp.Error(w, `Bad form`, http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tsess, _ := models.SessionFromContext(r.Context())\n\titem.CreatedBy = sess.UserID\n\n\tlastID, err := h.ItemsRepo.Add(item)\n\tif err != nil {\n\t\thttp.Error(w, `DB err`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\th.Logger.Infof(\"Insert with id LastInsertId: %v\", lastID)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *ItemsHandler) Edit(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tif err != nil {\n\t\thttp.Error(w, `{\"error\": \"bad id\"}`, http.StatusBadGateway)\n\t\treturn\n\t}\n\n\titem, err := h.ItemsRepo.GetByID(uint32(id))\n\tif err != nil {\n\t\thttp.Error(w, `DB err`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif item == nil {\n\t\thttp.Error(w, `no item`, http.StatusNotFound)\n\t\treturn\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"edit.html\", item)\n\tif err != nil {\n\t\thttp.Error(w, `Template errror`, http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *ItemsHandler) Update(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tif err != nil {\n\t\thttp.Error(w, `Bad id`, http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tr.ParseForm()\n\titem := new(models.Item)\n\tdecoder := schema.NewDecoder()\n\tdecoder.IgnoreUnknownKeys(true)\n\terr = decoder.Decode(item, r.PostForm)\n\tif err != nil {\n\t\thttp.Error(w, `Bad form`, http.StatusBadRequest)\n\t\treturn\n\t}\n\titem.ID = uint32(id)\n\n\tok, err := h.ItemsRepo.Update(item)\n\tif err != nil {\n\t\thttp.Error(w, `db error`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\th.Logger.Infof(\"update: %v %v\", item, ok)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *ItemsHandler) Delete(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tif err != nil {\n\t\thttp.Error(w, `{\"error\": \"bad id\"}`, http.StatusBadGateway)\n\t\treturn\n\t}\n\n\tok, err := h.ItemsRepo.Delete(uint32(id))\n\tif err != nil {\n\t\thttp.Error(w, `{\"error\": \"db error\"}`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-type\", \"application/json\")\n\trespJSON, _ := json.Marshal(map[string]bool{\n\t\t\"success\": ok,\n\t})\n\tw.Write(respJSON)\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/pkg/items/items.go",
    "content": "package items\n\nimport \"crudapp/internal/pkg/models\"\n\ntype Repository interface {\n\tGetAll() ([]*models.Item, error)\n\tGetByID(id uint32) (*models.Item, error)\n\tAdd(item *models.Item) (uint32, error)\n\tUpdate(newItem *models.Item) (bool, error)\n\tDelete(id uint32) (bool, error)\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/pkg/items/repository/repo.go",
    "content": "package repository\n\nimport \"crudapp/internal/pkg/models\"\n\n// WARNING! completly unsafe in multi-goroutine use, need add mutexes\n\ntype itemsRepo struct {\n\tlastID uint32\n\tdata   []*models.Item\n}\n\nfunc NewRepo() *itemsRepo {\n\treturn &itemsRepo{\n\t\tdata: make([]*models.Item, 0, 10),\n\t}\n}\n\nfunc (repo *itemsRepo) GetAll() ([]*models.Item, error) {\n\treturn repo.data, nil\n}\n\nfunc (repo *itemsRepo) GetByID(id uint32) (*models.Item, error) {\n\tfor _, item := range repo.data {\n\t\tif item.ID == id {\n\t\t\treturn item, nil\n\t\t}\n\t}\n\treturn nil, nil\n}\n\nfunc (repo *itemsRepo) Add(item *models.Item) (uint32, error) {\n\trepo.lastID++\n\titem.ID = repo.lastID\n\trepo.data = append(repo.data, item)\n\treturn repo.lastID, nil\n}\n\nfunc (repo *itemsRepo) Update(newItem *models.Item) (bool, error) {\n\tfor _, item := range repo.data {\n\t\tif item.ID != newItem.ID {\n\t\t\tcontinue\n\t\t}\n\t\titem.Title = newItem.Title\n\t\titem.Description = newItem.Description\n\t\treturn true, nil\n\t}\n\treturn false, nil\n}\n\nfunc (repo *itemsRepo) Delete(id uint32) (bool, error) {\n\ti := -1\n\tfor idx, item := range repo.data {\n\t\tif item.ID != id {\n\t\t\tcontinue\n\t\t}\n\t\ti = idx\n\t}\n\tif i < 0 {\n\t\treturn false, nil\n\t}\n\n\tif i < len(repo.data)-1 {\n\t\tcopy(repo.data[i:], repo.data[i+1:])\n\t}\n\trepo.data[len(repo.data)-1] = nil // or the zero value of T\n\trepo.data = repo.data[:len(repo.data)-1]\n\n\treturn true, nil\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/pkg/models/item.go",
    "content": "package models\n\ntype Item struct {\n\tID          uint32 `schema:\"-\"`\n\tTitle       string `schema:\"title,required\"`\n\tDescription string `schema:\"description,required\"`\n\tCreatedBy   uint32 `schema:\"-\"`\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/pkg/models/session.go",
    "content": "package models\n\nimport (\n\t\"context\"\n\t\"crypto/rand\"\n\t\"errors\"\n\t\"fmt\"\n)\n\ntype Session struct {\n\tID     string\n\tUserID uint32\n}\n\nfunc NewSession(userID uint32) *Session {\n\t// лучше генерировать из заданного алфавита, но так писать меньше и для учебного примера ОК\n\trandID := make([]byte, 16)\n\trand.Read(randID)\n\n\treturn &Session{\n\t\tID:     fmt.Sprintf(\"%x\", randID),\n\t\tUserID: userID,\n\t}\n}\n\nvar (\n\tErrNoAuth = errors.New(\"No session found\")\n)\n\ntype sessKey string\n\nvar SessionKey sessKey = \"sessionKey\"\n\nfunc SessionFromContext(ctx context.Context) (*Session, error) {\n\tsess, ok := ctx.Value(SessionKey).(*Session)\n\tif !ok || sess == nil {\n\t\treturn nil, ErrNoAuth\n\t}\n\treturn sess, nil\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/pkg/models/user.go",
    "content": "package models\n\nimport \"errors\"\n\ntype User struct {\n\tID       uint32\n\tLogin    string\n\tPassword string\n}\n\nvar (\n\tErrNoUser  = errors.New(\"no user found\")\n\tErrBadPass = errors.New(\"invalid password\")\n)\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/pkg/session/manager.go",
    "content": "package session\n\nimport (\n\t\"crudapp/internal/pkg/models\"\n\t\"net/http\"\n\t\"sync\"\n\t\"time\"\n)\n\ntype SessionsManager struct {\n\tdata map[string]*models.Session\n\tmu   *sync.RWMutex\n}\n\nfunc NewSessionsMem() *SessionsManager {\n\treturn &SessionsManager{\n\t\tdata: make(map[string]*models.Session, 10),\n\t\tmu:   &sync.RWMutex{},\n\t}\n}\n\nfunc (sm *SessionsManager) Check(r *http.Request) (*models.Session, error) {\n\tsessionCookie, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\treturn nil, models.ErrNoAuth\n\t}\n\n\tsm.mu.RLock()\n\tsess, ok := sm.data[sessionCookie.Value]\n\tsm.mu.RUnlock()\n\n\tif !ok {\n\t\treturn nil, models.ErrNoAuth\n\t}\n\n\treturn sess, nil\n}\n\nfunc (sm *SessionsManager) Create(w http.ResponseWriter, userID uint32) (*models.Session, error) {\n\tsess := models.NewSession(userID)\n\n\tsm.mu.Lock()\n\tsm.data[sess.ID] = sess\n\tsm.mu.Unlock()\n\n\tcookie := &http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   sess.ID,\n\t\tExpires: time.Now().Add(90 * 24 * time.Hour),\n\t\tPath:    \"/\",\n\t}\n\thttp.SetCookie(w, cookie)\n\treturn sess, nil\n}\n\nfunc (sm *SessionsManager) DestroyCurrent(w http.ResponseWriter, r *http.Request) error {\n\tsess, err := models.SessionFromContext(r.Context())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tsm.mu.Lock()\n\tdelete(sm.data, sess.ID)\n\tsm.mu.Unlock()\n\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tExpires: time.Now().AddDate(0, 0, -1),\n\t\tPath:    \"/\",\n\t}\n\thttp.SetCookie(w, &cookie)\n\treturn nil\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/pkg/user/delivery/user.go",
    "content": "package delivery\n\nimport (\n\t\"crudapp/internal/pkg/models\"\n\t\"crudapp/internal/pkg/user\"\n\t\"errors\"\n\t\"html/template\"\n\t\"net/http\"\n\n\t\"crudapp/internal/pkg/session\"\n\n\t\"go.uber.org/zap\"\n)\n\ntype UserHandler struct {\n\tTmpl     *template.Template\n\tLogger   *zap.SugaredLogger\n\tUserRepo user.Repository\n\tSessions *session.SessionsManager\n}\n\nfunc (h *UserHandler) Index(w http.ResponseWriter, r *http.Request) {\n\t_, err := models.SessionFromContext(r.Context())\n\tif err == nil {\n\t\thttp.Redirect(w, r, \"/items\", 302)\n\t\treturn\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"login.html\", nil)\n\tif err != nil {\n\t\thttp.Error(w, `Template errror`, http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *UserHandler) Login(w http.ResponseWriter, r *http.Request) {\n\tu, err := h.UserRepo.Authorize(r.FormValue(\"login\"), r.FormValue(\"password\"))\n\tif err == models.ErrNoUser {\n\t\thttp.Error(w, `no user`, http.StatusBadRequest)\n\t\treturn\n\t}\n\tif err == models.ErrBadPass {\n\t\thttp.Error(w, `bad pass`, http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tsess, _ := h.Sessions.Create(w, u.ID)\n\th.Logger.Infof(\"created session for %v\", sess.UserID)\n\thttp.Redirect(w, r, \"/\", 302)\n}\n\nfunc (h *UserHandler) Logout(w http.ResponseWriter, r *http.Request) {\n\th.Sessions.DestroyCurrent(w, r)\n\thttp.Redirect(w, r, \"/\", 302)\n}\n\nfunc (h *UserHandler) GetUserByID(login string) (*models.User, error) {\n\tif login == \"\" {\n\t\treturn nil, errors.New(\"login is empty\")\n\t}\n\n\treturn h.UserRepo.GetByLogin(login)\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/pkg/user/delivery/user_test.go",
    "content": "package delivery\n\nimport (\n\t\"crudapp/internal/pkg/models\"\n\t\"crudapp/internal/pkg/user/mock\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/golang/mock/gomock\"\n)\n\nfunc TestGetByID(t *testing.T) {\n\tlogin := \"somelogin\"\n\tretModel := &models.User{\n\t\tID:       0,\n\t\tLogin:    login,\n\t\tPassword: \"password\",\n\t}\n\n\tctrl := gomock.NewController(t)\n\tdefer ctrl.Finish()\n\n\tmock := mock.NewMockRepository(ctrl)\n\tmock.EXPECT().GetByLogin(login).Times(1).Return(retModel, nil)\n\n\tuh := UserHandler{\n\t\tUserRepo: mock,\n\t}\n\n\tmodels, err := uh.GetUserByID(login)\n\n\trequire.NoError(t, err)\n\trequire.Equal(t, models, retModel)\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/pkg/user/mock/mock_repo.go",
    "content": "// Code generated by MockGen. DO NOT EDIT.\n// Source: crudapp/internal/pkg/user (interfaces: Repository)\n\n// Package mock is a generated GoMock package.\npackage mock\n\nimport (\n\tmodels \"crudapp/internal/pkg/models\"\n\tgomock \"github.com/golang/mock/gomock\"\n\treflect \"reflect\"\n)\n\n// MockRepository is a mock of Repository interface\ntype MockRepository struct {\n\tctrl     *gomock.Controller\n\trecorder *MockRepositoryMockRecorder\n}\n\n// MockRepositoryMockRecorder is the mock recorder for MockRepository\ntype MockRepositoryMockRecorder struct {\n\tmock *MockRepository\n}\n\n// NewMockRepository creates a new mock instance\nfunc NewMockRepository(ctrl *gomock.Controller) *MockRepository {\n\tmock := &MockRepository{ctrl: ctrl}\n\tmock.recorder = &MockRepositoryMockRecorder{mock}\n\treturn mock\n}\n\n// EXPECT returns an object that allows the caller to indicate expected use\nfunc (m *MockRepository) EXPECT() *MockRepositoryMockRecorder {\n\treturn m.recorder\n}\n\n// Authorize mocks base method\nfunc (m *MockRepository) Authorize(arg0, arg1 string) (*models.User, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"Authorize\", arg0, arg1)\n\tret0, _ := ret[0].(*models.User)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// Authorize indicates an expected call of Authorize\nfunc (mr *MockRepositoryMockRecorder) Authorize(arg0, arg1 interface{}) *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"Authorize\", reflect.TypeOf((*MockRepository)(nil).Authorize), arg0, arg1)\n}\n\n// GetByLogin mocks base method\nfunc (m *MockRepository) GetByLogin(arg0 string) (*models.User, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"GetByLogin\", arg0)\n\tret0, _ := ret[0].(*models.User)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// GetByLogin indicates an expected call of GetByLogin\nfunc (mr *MockRepositoryMockRecorder) GetByLogin(arg0 interface{}) *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"GetByLogin\", reflect.TypeOf((*MockRepository)(nil).GetByLogin), arg0)\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/pkg/user/repository/user.go",
    "content": "package repository\n\nimport (\n\t\"crudapp/internal/pkg/models\"\n)\n\ntype UserRepo struct {\n\tdata map[string]*models.User\n}\n\nfunc NewUserRepo() *UserRepo {\n\treturn &UserRepo{\n\t\tdata: map[string]*models.User{\n\t\t\t\"rvasily\": {\n\t\t\t\tID:       1,\n\t\t\t\tLogin:    \"rvasily\",\n\t\t\t\tPassword: \"love\",\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc (repo *UserRepo) Authorize(login, pass string) (*models.User, error) {\n\tu, ok := repo.data[login]\n\tif !ok {\n\t\treturn nil, models.ErrNoUser\n\t}\n\n\t// dont do this un production :)\n\tif u.Password != pass {\n\t\treturn nil, models.ErrBadPass\n\t}\n\n\treturn u, nil\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/internal/pkg/user/user.go",
    "content": "package user\n\nimport \"crudapp/internal/pkg/models\"\n\n//go:generate mockgen -destination=./mock/mock_repo.go -package=mock crudapp/internal/pkg/user Repository\n\ntype Repository interface {\n\tGetByLogin(login string) (*models.User, error)\n\tAuthorize(login, pass string) (*models.User, error)\n}\n"
  },
  {
    "path": "5-architecture/10_crudapp/readme.md",
    "content": "``` bash\ngo mod init crudapp\n# go mod init github.com/rvasily/crudapp\ngo build\ngo mod download\ngo mod verify\ngo mod tidy\n\ngo build  -o ./bin/crudapp ./cmd/crudapp\ngo test -v -coverpkg=./... ./...\n\ngo mod vendor\ngo build -mod=vendor -o ./bin/myapp ./cmd/myapp\ngo test -v -mod=vendor -coverpkg=./... ./...\n```\n"
  },
  {
    "path": "5-architecture/10_crudapp/templates/create.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/new\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "5-architecture/10_crudapp/templates/edit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/{{.ID}}\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "5-architecture/10_crudapp/templates/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\t<div class=\"container\">\n    <h1>Posts</h1>\n    <table class=\"table\">\n    <thead>\n      <tr>\n        <th>#</th>\n        <th>Title</th>\n        <th style=\"width:140px;\"><a href=\"/items/new\" class=\"btn btn-success\">New</a></th>\n      </tr>\n    </thead>\n    <tbody>\n    {{range .Items}}\n      <tr>\n        <td>{{.ID}}</td>\n        <td>{{.Title}}</td>\n        <td>\n          <a href=\"/items/{{.ID}}\" class=\"btn btn-primary\">Edit</a>\n          <span data-id=\"{{.ID}}\" class=\"do-delete btn btn-danger\">Del</span>\n        </td>\n      </tr>\n\t\t{{end}}\n    </tbody>\n  </div>\n  \n  <script src=\"https://code.jquery.com/jquery-3.2.1.min.js\" crossorigin=\"anonymous\"></script>\n\n  <script type=\"text/javascript\">\n  $('.do-delete').click(function() {\n    if(!confirm(\"Are you sure?\")) {\n      return\n    }\n    $elem = $(this)\n    $.ajax({\n      url: '/items/' + $elem.data(\"id\"),\n      type: 'DELETE',\n      data: {},\n      success: function(resp) {\n        if(resp.success) {\n          $elem.parent().parent().remove()\n        }\n      },\n    });\n  })\n  </script>\n  \n  </body>\n</html>\n"
  },
  {
    "path": "5-architecture/10_crudapp/templates/login.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\t<div class=\"container\">\n        <h1>CrudAPP login</h1>\n        <form method=\"POST\" action=\"/login\">\n            <div class=\"form-group\">\n                <label for=\"login\">Login</label>\n                <input type=\"text\" class=\"form-control\" name=\"login\" id=\"login\" value=\"rvasily\">\n            </div>\n            <div class=\"form-group\">\n                <label for=\"password\">Password</label>\n                <input type=\"password\" class=\"form-control\" name=\"password\" id=\"password\" value=\"love\">\n            </div>\n            <button type=\"submit\" class=\"btn btn-primary\">Login</button>\n        </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "5-architecture/1_routers/0_httprouter/0_httprouter.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\n\t\"github.com/julienschmidt/httprouter\"\n)\n\nfunc List(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {\n\tfmt.Fprint(w, \"You see user list\\n\")\n}\n\nfunc Get(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {\n\tfmt.Fprintf(w, \"you try to see user %s\\n\", ps.ByName(\"id\"))\n}\n\n/*\ncurl -v -X PUT -H \"Content-Type: application/json\" -d '{\"login\":\"rvasily\"}' http://localhost:8080/users\n*/\n\nfunc Create(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {\n\tfmt.Fprintf(w, \"you try to create new user\\n\")\n}\n\n/*\ncurl -v -X POST -H \"Content-Type: application/json\" -d '{\"name\":\"Vasily Romanov\"}' http://localhost:8080/users/rvasily\n*/\n\nfunc Update(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {\n\tfmt.Fprintf(w, \"you try to update %s\\n\", ps.ByName(\"login\"))\n}\n\nfunc main() {\n\trouter := httprouter.New()\n\trouter.GET(\"/\", List)\n\trouter.GET(\"/users\", List)\n\trouter.PUT(\"/users\", Create)\n\trouter.GET(\"/users/:id\", Get)\n\trouter.POST(\"/users/:login\", Update)\n\n\tfmt.Println(\"starting server at :8080\")\n\tlog.Fatal(http.ListenAndServe(\":8080\", router))\n}\n"
  },
  {
    "path": "5-architecture/1_routers/1_fasthttp/1_fasthttp.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/buaazp/fasthttprouter\"\n\t\"github.com/valyala/fasthttp\"\n)\n\nfunc Index(ctx *fasthttp.RequestCtx) {\n\n\tctx.SetContentType(\"application/json\")\n\tctx.SetStatusCode(fasthttp.StatusOK)\n\n\tusers := []string{\"rvasily\"}\n\tbody, _ := json.Marshal(users)\n\n\tctx.SetBody(body)\n}\n\nfunc GetUser(ctx *fasthttp.RequestCtx) {\n\tfmt.Fprintf(ctx, \"you try to see user %s\\n\", ctx.UserValue(\"id\"))\n}\n\nfunc main() {\n\trouter := fasthttprouter.New()\n\trouter.GET(\"/\", Index)\n\t// /users/123\n\trouter.GET(\"/users/:id\", GetUser)\n\n\tfmt.Println(\"starting server at :8080\")\n\tlog.Fatal(fasthttp.ListenAndServe(\":8080\", router.Handler))\n}\n"
  },
  {
    "path": "5-architecture/1_routers/2_gorilla/2_gorilla.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\n\t\"github.com/gorilla/mux\"\n)\n\nfunc List(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprint(w, \"You see user list\\n\")\n}\n\nfunc Get(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tfmt.Fprintf(w, \"you try to see user %s\\n\", vars[\"id\"])\n}\n\n/*\ncurl -v -X PUT -H \"Content-Type: application/json\" -d '{\"login\":\"rvasily\"}' http://localhost:8080/users\n*/\n\nfunc Create(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintf(w, \"you try to create new user\\n\")\n}\n\n/*\ncurl -v -X POST -H \"Content-Type: application/json\"  -H \"X-Auth: test\" -d '{\"name\":\"Vasily Romanov\"}' http://localhost:8080/users/rvasily\n*/\n\nfunc Update(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tfmt.Fprintf(w, \"you try to update %s\\n\", vars[\"login\"])\n}\n\nfunc main() {\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/\", List)\n\n\tr.HandleFunc(\"/users\", List).\n\t\tHost(\"localhost\")\n\n\tr.HandleFunc(\"/users\", Update).\n\t\tMethods(\"PUT\")\n\n\tr.HandleFunc(\"/users/{id:[0-9]+}\", Get)\n\n\tr.HandleFunc(\"/users/{login}\", Create).\n\t\tMethods(\"POST\").\n\t\tHeaders(\"X-Auth\", \"test\")\n\n\tfmt.Println(\"starting server at :8080\")\n\tlog.Fatal(http.ListenAndServe(\":8080\", r))\n}\n"
  },
  {
    "path": "5-architecture/1_routers/3_multiple/3_multiple.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\n\t\"github.com/gorilla/mux\"\n\t\"github.com/julienschmidt/httprouter\"\n)\n\nfunc RegularRequest(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprint(w, \"Request with averange amout of logic\\n\")\n}\n\nfunc FastRequest(w http.ResponseWriter, r *http.Request, params httprouter.Params) {\n\tfmt.Fprint(w, \"Request with high hitrate\\n\")\n}\n\nfunc ComplexRequest(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprint(w, \"Request with complex routing logic\\n\")\n}\n\nfunc main() {\n\tfastApiHandler := httprouter.New()\n\tfastApiHandler.GET(\"/fast/:id\", FastRequest)\n\n\tcomplexApiHandler := mux.NewRouter()\n\tcomplexApiHandler.HandleFunc(\"/complex/\", ComplexRequest).\n\t\tHeaders(\"X-Requested-With\", \"XMLHttpRequest\") // ajax\n\n\tstdApiHandler := http.NewServeMux()\n\tstdApiHandler.HandleFunc(\"/std/\", RegularRequest)\n\n\tsiteMux := http.NewServeMux()\n\tsiteMux.Handle(\"/fast/\", fastApiHandler)\n\tsiteMux.Handle(\"/complex/\", complexApiHandler)\n\tsiteMux.Handle(\"/std/\", stdApiHandler)\n\n\tfmt.Println(\"starting server at :8080\")\n\tlog.Fatal(http.ListenAndServe(\":8080\", siteMux))\n}\n"
  },
  {
    "path": "5-architecture/2_middleware/1_middleware/1_middleware.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n)\n\nfunc mainPage(w http.ResponseWriter, r *http.Request) {\n\tsession, err := r.Cookie(\"session_id\")\n\t// учебный пример! это не проверка авторизации!\n\tloggedIn := (err != http.ErrNoCookie)\n\n\tif loggedIn {\n\t\tfmt.Fprintln(w, `<a href=\"/logout\">logout</a>`)\n\t\tfmt.Fprintln(w, \"Welcome, \"+session.Value)\n\t} else {\n\t\tfmt.Fprintln(w, `<a href=\"/login\">login</a>`)\n\t\tfmt.Fprintln(w, \"You need to login\")\n\t}\n}\n\nfunc loginPage(w http.ResponseWriter, r *http.Request) {\n\texpiration := time.Now().Add(10 * time.Hour)\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   \"Dmitry\",\n\t\tExpires: expiration,\n\t}\n\thttp.SetCookie(w, &cookie)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc logoutPage(w http.ResponseWriter, r *http.Request) {\n\tsession, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t\treturn\n\t}\n\tsession.Expires = time.Now().AddDate(0, 0, -1)\n\thttp.SetCookie(w, session)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\n// -----------\n\nfunc adminIndex(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintln(w, `<a href=\"/\">site index</a>`)\n\tfmt.Fprintln(w, \"Admin main page\")\n}\n\nfunc panicPage(w http.ResponseWriter, r *http.Request) {\n\tpanic(\"this must me recovered\")\n}\n\n// -----------\n\nfunc pageWithAllChecks(w http.ResponseWriter, r *http.Request) {\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\tfmt.Println(\"recovered\", err)\n\t\t\thttp.Error(w, \"Internal server error\", 500)\n\t\t}\n\t}()\n\tdefer func(start time.Time) {\n\t\tfmt.Printf(\"[%s] %s, %s %s\\n\",\n\t\t\tr.Method, r.RemoteAddr, r.URL.Path, time.Since(start))\n\t}(time.Now())\n\n\t_, err := r.Cookie(\"session_id\")\n\t// учебный пример! это не проверка авторизации!\n\tif err != nil {\n\t\tfmt.Println(\"no auth at\", r.URL.Path)\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t\treturn\n\t}\n\n\t// your logic\n}\n\n// -----------\n\nfunc adminAuthMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tfmt.Println(\"adminAuthMiddleware\", r.URL.Path)\n\t\t_, err := r.Cookie(\"session_id\")\n\t\t// учебный пример! это не проверка авторизации!\n\t\tif err != nil {\n\t\t\tfmt.Println(\"no auth at\", r.URL.Path)\n\t\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t\t\treturn\n\t\t}\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n\nfunc accessLogMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tfmt.Println(\"accessLogMiddleware\", r.URL.Path)\n\t\tstart := time.Now()\n\t\tnext.ServeHTTP(w, r)\n\t\tfmt.Printf(\"[%s] %s, %s %s\\n\",\n\t\t\tr.Method, r.RemoteAddr, r.URL.Path, time.Since(start))\n\t})\n}\n\nfunc panicMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tfmt.Println(\"panicMiddleware\", r.URL.Path)\n\t\tdefer func() {\n\t\t\tif err := recover(); err != nil {\n\t\t\t\tfmt.Println(\"recovered\", err)\n\t\t\t\thttp.Error(w, \"Internal server error\", 500)\n\t\t\t}\n\t\t}()\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n\n// -----------\n\nfunc main() {\n\tadminMux := http.NewServeMux()\n\tadminMux.HandleFunc(\"/admin/\", adminIndex)\n\tadminMux.HandleFunc(\"/admin/panic\", panicPage)\n\n\t// set middleware\n\tadminHandler := adminAuthMiddleware(adminMux)\n\n\tsiteMux := http.NewServeMux()\n\tsiteMux.Handle(\"/admin/\", adminHandler)\n\tsiteMux.HandleFunc(\"/login\", loginPage)\n\tsiteMux.HandleFunc(\"/logout\", logoutPage)\n\tsiteMux.HandleFunc(\"/\", mainPage)\n\n\t// set middleware\n\tsiteHandler := accessLogMiddleware(siteMux)\n\tsiteHandler = panicMiddleware(siteHandler)\n\n\tfmt.Println(\"starting server at http://127.0.0.1:8080\")\n\thttp.ListenAndServe(\":8080\", siteHandler)\n}\n"
  },
  {
    "path": "5-architecture/2_middleware/2_context_value/2_context_value.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"net/http\"\n\t\"sync\"\n\t\"time\"\n)\n\n// сколько в среднем спим при эмуляции работы\nconst AvgSleep = 50\n\nfunc trackContextTimings(ctx context.Context, metricName string, start time.Time) {\n\t// получаем тайминги из контекста\n\t// поскольку там пустой интерфейс, то нам надо преобразовать к нужному типу\n\ttimings, ok := ctx.Value(timingsKey).(*ctxTimings)\n\tif !ok {\n\t\treturn\n\t}\n\telapsed := time.Since(start)\n\t// лочимся на случай конкурентной записи в мапку\n\ttimings.Lock()\n\tdefer timings.Unlock()\n\t// если меткри ещё нет - мы её создадим, если есть - допишем в существующую\n\tif metric, metricExist := timings.Data[metricName]; !metricExist {\n\t\ttimings.Data[metricName] = &Timing{\n\t\t\tCount:    1,\n\t\t\tDuration: elapsed,\n\t\t}\n\t} else {\n\t\tmetric.Count++\n\t\tmetric.Duration += elapsed\n\t}\n}\n\ntype Timing struct {\n\tCount    int\n\tDuration time.Duration\n}\n\ntype ctxTimings struct {\n\tsync.Mutex\n\tData map[string]*Timing\n}\n\n// линтер ругается если используем базовые типы в Value контекста\n// типа так безопаснее разграничивать\ntype key int\n\nconst timingsKey key = 1\n\nfunc logContextTimings(ctx context.Context, path string, start time.Time) {\n\t// получаем тайминги из контекста\n\t// поскольку там пустой интерфейс, то нам надо преобразовать к нужному типу\n\ttimings, ok := ctx.Value(timingsKey).(*ctxTimings)\n\tif !ok {\n\t\treturn\n\t}\n\ttotalReal := time.Since(start)\n\tbuf := bytes.NewBufferString(path)\n\tvar total time.Duration\n\tfor timing, value := range timings.Data {\n\t\ttotal += value.Duration\n\t\tbuf.WriteString(fmt.Sprintf(\"\\n\\t%s(%d): %s\", timing, value.Count, value.Duration))\n\t}\n\tbuf.WriteString(fmt.Sprintf(\"\\n\\ttotal: %s\", totalReal))\n\tbuf.WriteString(fmt.Sprintf(\"\\n\\ttracked: %s\", total))\n\tbuf.WriteString(fmt.Sprintf(\"\\n\\tunkn: %s\", totalReal-total))\n\n\tfmt.Println(buf.String())\n}\n\nfunc timingMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tctx := r.Context()\n\t\tctx = context.WithValue(ctx,\n\t\t\ttimingsKey,\n\t\t\t&ctxTimings{\n\t\t\t\tData: make(map[string]*Timing),\n\t\t\t})\n\t\tdefer logContextTimings(ctx, r.URL.Path, time.Now())\n\t\tnext.ServeHTTP(w, r.WithContext(ctx))\n\t})\n}\n\nfunc emulateWork(ctx context.Context, workName string) {\n\tdefer trackContextTimings(ctx, workName, time.Now())\n\n\trnd := time.Duration(rand.Intn(AvgSleep))\n\ttime.Sleep(time.Millisecond * rnd)\n}\n\nfunc loadPostsHandle(w http.ResponseWriter, req *http.Request) {\n\tctx := req.Context()\n\n\temulateWork(ctx, \"checkCache\")\n\temulateWork(ctx, \"loadPosts\")\n\temulateWork(ctx, \"loadPosts\")\n\temulateWork(ctx, \"loadPosts\")\n\ttime.Sleep(10 * time.Millisecond)\n\temulateWork(ctx, \"loadSidebar\")\n\temulateWork(ctx, \"loadComments\")\n\n\tfmt.Fprintln(w, \"Request done\")\n}\n\nfunc main() {\n\trand.Seed(time.Now().UTC().UnixNano())\n\n\tsiteMux := http.NewServeMux()\n\tsiteMux.HandleFunc(\"/\", loadPostsHandle)\n\n\tsiteHandler := timingMiddleware(siteMux)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", siteHandler)\n}\n"
  },
  {
    "path": "5-architecture/3_errors/1_basic_err/1_basic_err.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n)\n\nvar (\n\tclient = http.Client{Timeout: time.Duration(time.Millisecond)}\n)\n\nfunc getRemoteResource() error {\n\turl := \"http://127.0.0.1:9999/pages?id=123\"\n\t_, err := client.Get(url)\n\tif err != nil {\n\t\t// вернётся `timed out`. и что?\n\t\t// return err\n\n\t\t// будет `res error: time out`. а где?\n\t\t// return fmt.Errof(\"getRemoteResource: %+v\", err)\n\n\t\treturn fmt.Errorf(\"getRemoteResource: %s at %s\", err, url)\n\t}\n\treturn nil\n}\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\terr := getRemoteResource()\n\n\tif err != nil {\n\t\tfmt.Printf(\"error happend: %+v\\n\", err)\n\t\thttp.Error(w, \"internal error\", 500)\n\t\treturn\n\t}\n\n\tw.Write([]byte(\"all is OK\"))\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handler)\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "5-architecture/3_errors/2_named_err/2_named_err.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n)\n\nvar (\n\tclient = http.Client{Timeout: time.Duration(time.Millisecond)}\n\n\tErrResource = errors.New(\"resource error\")\n)\n\nfunc getRemoteResource() error {\n\turl := \"http://127.0.0.1:9999/pages?id=123\"\n\t_, err := client.Get(url)\n\tif err != nil {\n\t\treturn ErrResource\n\t}\n\treturn nil\n}\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\terr := getRemoteResource()\n\tif err != nil {\n\t\tfmt.Printf(\"error happend: %+v\\n\", err)\n\t\tswitch err {\n\t\tcase ErrResource:\n\t\t\thttp.Error(w, \"remote resource error\", 500)\n\t\tdefault:\n\t\t\thttp.Error(w, \"internal error\", 500)\n\t\t}\n\t\treturn\n\t}\n\tw.Write([]byte(\"all is OK\"))\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handler)\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "5-architecture/3_errors/3_pkg_err/3_pkg_err.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n)\n\nvar (\n\tclient = http.Client{Timeout: time.Duration(time.Millisecond)}\n)\n\nfunc getRemoteResource() error {\n\turl := \"http://127.0.0.1:9999/pages?id=123\"\n\t_, err := client.Get(url)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"resource error\")\n\t\t// resource error: timeout\n\t}\n\treturn nil\n}\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\terr := getRemoteResource()\n\tif err != nil {\n\t\tfmt.Printf(\"full err: %+v\\n\", err)\n\t\tswitch err := errors.Cause(err).(type) {\n\t\tcase *url.Error:\n\t\t\tfmt.Printf(\"resource %s err: %+v\\n\", err.URL, err.Err)\n\t\t\thttp.Error(w, \"remote resource error\", 422)\n\t\tdefault:\n\t\t\tfmt.Printf(\"%+v\\n\", err)\n\t\t\thttp.Error(w, \"parsing error\", 500)\n\t\t}\n\t\treturn\n\t}\n\tw.Write([]byte(\"all is OK\"))\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handler)\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "5-architecture/3_errors/4_own_err/4_own_err.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n)\n\nvar (\n\tclient = http.Client{Timeout: time.Duration(time.Millisecond)}\n)\n\ntype HTTPError struct {\n\tCode int\n}\n\nvar e error = &ResourceError{}\n\ntype ResourceError struct {\n\tURL  string\n\tErr  error\n\tCode int\n}\n\nfunc (re *ResourceError) Error() string {\n\treturn fmt.Sprintf(\n\t\t\"Resource error: URL: %s, err: %v\",\n\t\tre.URL,\n\t\tre.Err,\n\t)\n}\n\nfunc getRemoteResource() error {\n\turl := \"http://127.0.0.1:9999/pages?id=123\"\n\t_, err := client.Get(url)\n\tif err != nil {\n\t\treturn &ResourceError{URL: url, Err: err}\n\t}\n\treturn nil\n}\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\terr := getRemoteResource()\n\tif err != nil {\n\t\tswitch err.(type) {\n\t\tcase *ResourceError:\n\t\t\terr := err.(*ResourceError)\n\t\t\tfmt.Printf(\"resource %s err: %s\\n\", err.URL, err.Err)\n\t\t\thttp.Error(w, \"remote resource error\", 500)\n\t\tdefault:\n\t\t\tfmt.Printf(\"internal error: %+v\\n\", err)\n\t\t\thttp.Error(w, \"internal error\", 500)\n\t\t}\n\t\treturn\n\t}\n\tw.Write([]byte(\"all is OK\"))\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handler)\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "5-architecture/3_errors/5_new_errors/5_new_errors.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n)\n\ntype MyOwnError struct {\n\tReason string\n\tCode   int\n}\n\nfunc (e MyOwnError) Error() string {\n\treturn fmt.Sprintf(\"error with code %d happened: %s\", e.Code, e.Reason)\n}\n\nvar (\n\townError1 error = MyOwnError{\n\t\tReason: \"really bad things happened\",\n\t\tCode:   42,\n\t}\n)\n\nfunc someJob() error {\n\tif rand.Intn(100) > 50 {\n\t\treturn ownError1\n\t}\n\n\tif randomInt := rand.Intn(100); randomInt > 50 {\n\t\treturn MyOwnError{\n\t\t\tReason: \"random was above 50\",\n\t\t\tCode:   randomInt,\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc jobWrapper() error {\n\terr := someJob()\n\treturn errors.Wrap(err, \"failed to do some job\")\n}\n\nfunc main() {\n\trand.Seed(time.Now().UnixNano())\n\n\terr := someJob()\n\t// if err == ownError1 // WRONG\n\tif errors.Is(err, ownError1) {\n\t\tlog.Println(\"found ownError1\")\n\t\treturn\n\t}\n\n\tvar myOwnError MyOwnError\n\tif ok := errors.As(err, &myOwnError); ok {\n\t\tlog.Println(\"found my own error sturct\")\n\t\treturn\n\t}\n\n\tif err != nil {\n\t\tlog.Println(\"well, that was unexpected\")\n\t\treturn\n\t}\n\n\tlog.Println(\"error is nil\")\n}\n"
  },
  {
    "path": "5-architecture/4_validation/validation.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\t// валидатор\n\t\"github.com/asaskevich/govalidator\"\n\n\t// парсинг параметров в структуру\n\t\"github.com/gorilla/schema\"\n)\n\n// http://127.0.0.1:8080/?to=v.romanov@corp.mail.ru&priority=low&subject=Hello!&inner=ignored&id=12&flag=23\n\ntype SendMessage struct {\n\tId        int    `valid:\",optional\"`\n\tPriority  string `valid:\"in(low|normal|high)\"`\n\tRecipient string `schema:\"to\" valid:\"email\"`\n\tSubject   string `valid:\"msgSubject\"`\n\tInner     string `schema:\"-\" valid:\"-\"`\n\tflag      int\n}\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\tw.Write([]byte(\"request \" + r.URL.String() + \"\\n\\n\"))\n\n\tmsg := &SendMessage{}\n\n\tdecoder := schema.NewDecoder()\n\tdecoder.IgnoreUnknownKeys(true)\n\terr := decoder.Decode(msg, r.URL.Query())\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\thttp.Error(w, \"internal\", 500)\n\t\treturn\n\t}\n\tw.Write([]byte(fmt.Sprintf(\"Msg: %#v\\n\\n\", msg)))\n\n\t_, err = govalidator.ValidateStruct(msg)\n\tif err != nil {\n\t\tif allErrs, ok := err.(govalidator.Errors); ok {\n\t\t\tfor _, fld := range allErrs.Errors() {\n\t\t\t\tdata := []byte(fmt.Sprintf(\"field: %#v\\n\\n\", fld))\n\t\t\t\tw.Write(data)\n\t\t\t}\n\t\t}\n\n\t\tw.Write([]byte(fmt.Sprintf(\"error: %s\\n\\n\", err)))\n\t} else {\n\t\tw.Write([]byte(fmt.Sprintf(\"msg is correct\\n\\n\")))\n\t}\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handler)\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\nfunc init() {\n\tgovalidator.CustomTypeTagMap.Set(\n\t\t\"msgSubject\",\n\t\tgovalidator.CustomTypeValidator(func(i interface{}, o interface{}) bool {\n\t\t\tsubject, ok := i.(string)\n\t\t\tif !ok {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif len(subject) == 0 || len(subject) > 10 {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t}),\n\t)\n}\n"
  },
  {
    "path": "5-architecture/5_logging/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/sirupsen/logrus\"\n\t\"go.uber.org/zap\"\n)\n\nfunc mainPage(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintln(w, \"hello world\")\n}\n\ntype AccessLogger struct {\n\tStdLogger    *log.Logger\n\tZapLogger    *zap.SugaredLogger\n\tLogrusLogger *logrus.Entry\n}\n\nfunc (ac *AccessLogger) accessLogMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tstart := time.Now()\n\t\tnext.ServeHTTP(w, r)\n\n\t\tfmt.Printf(\"FMT [%s] %s, %s %s\\n\",\n\t\t\tr.Method, r.RemoteAddr, r.URL.Path, time.Since(start))\n\n\t\tlog.Printf(\"LOG [%s] %s, %s %s\\n\",\n\t\t\tr.Method, r.RemoteAddr, r.URL.Path, time.Since(start))\n\n\t\tac.StdLogger.Printf(\"[%s] %s, %s %s\\n\",\n\t\t\tr.Method, r.RemoteAddr, r.URL.Path, time.Since(start))\n\n\t\tac.ZapLogger.Info(r.URL.Path,\n\t\t\tzap.String(\"method\", r.Method),\n\t\t\tzap.String(\"remote_addr\", r.RemoteAddr),\n\t\t\tzap.String(\"url\", r.URL.Path),\n\t\t\tzap.Duration(\"work_time\", time.Since(start)),\n\t\t)\n\n\t\tac.LogrusLogger.WithFields(logrus.Fields{\n\t\t\t\"method\":      r.Method,\n\t\t\t\"remote_addr\": r.RemoteAddr,\n\t\t\t\"work_time\":   time.Since(start),\n\t\t}).Info(r.URL.Path)\n\t})\n}\n\n// -----------\n\nfunc main() {\n\n\taddr := \"localhost\"\n\tport := 8080\n\n\t// std\n\tfmt.Printf(\"STD starting server at %s:%d\\n\", addr, port)\n\n\t// std\n\tlog.Printf(\"STD starting server at %s:%d\\n\", addr, port)\n\n\t// zap\n\t// у zap-а нет логгера по-умолчанию\n\tzapLogger, _ := zap.NewProduction()\n\tdefer zapLogger.Sync()\n\tzapLogger.Info(\"starting server\",\n\t\tzap.String(\"logger\", \"ZAP\"),\n\t\tzap.String(\"host\", addr),\n\t\tzap.Int(\"port\", port),\n\t)\n\n\t// logrus\n\tlogrus.SetFormatter(&logrus.TextFormatter{DisableColors: true})\n\tlogrus.WithFields(logrus.Fields{\n\t\t\"logger\": \"LOGRUS\",\n\t\t\"host\":   addr,\n\t\t\"port\":   port,\n\t}).Info(\"Starting server\")\n\n\tAccessLogOut := new(AccessLogger)\n\n\t// std\n\tAccessLogOut.StdLogger = log.New(os.Stdout, \"STD \", log.LUTC|log.Lshortfile)\n\n\t// zap\n\tsugar := zapLogger.Sugar().With(\n\t\tzap.String(\"mode\", \"[access_log]\"),\n\t\tzap.String(\"logger\", \"ZAP\"),\n\t)\n\tAccessLogOut.ZapLogger = sugar\n\n\t// logrus\n\tcontextLogger := logrus.WithFields(logrus.Fields{\n\t\t\"mode\":   \"[access_log]\",\n\t\t\"logger\": \"LOGRUS\",\n\t})\n\tlogrus.SetFormatter(&logrus.JSONFormatter{})\n\tAccessLogOut.LogrusLogger = contextLogger\n\n\t// server stuff\n\tsiteMux := http.NewServeMux()\n\tsiteMux.HandleFunc(\"/\", mainPage)\n\tsiteHandler := AccessLogOut.accessLogMiddleware(siteMux)\n\thttp.ListenAndServe(\":8080\", siteHandler)\n}\n"
  },
  {
    "path": "5-architecture/6_websockets/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <!-- Required meta tags -->\n        <meta charset=\"utf-8\">\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n        <title>Inbox</title>\n\n        <!-- Bootstrap CSS -->\n        <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n        <style>\n            .row { margin: 10px; border: 1px solid silver;}\n        </style>\n    </head>\n<body>\n<div class=\"container\" id=\"\">\n        <h1>Messages</h1>\n</div>\n\n<div class=\"container\" id=\"messages\">\n    <div class=\"row\"></div>\n</div>\n<script>\n\n    function newMessage(msg) {\n        // msg = {email: \"vasily@mail.ru\", subject: \"testing testing\", name: \"rvasily\"}\n\n        // dont do this!\n        // completly insecure to XSS\n        msgNode = `\n            <div class=\"col-sm\">\n                ${msg.name}&laquo;${msg.email}&raquo;\n            </div>\n            <div class=\"col-sm\">\n                ${msg.subject}\n            </div>\n        `;\n\n        var node = document.createElement(\"div\");\n        node.className = \"row\";\n        node.innerHTML = msgNode;\n\n        msgs = document.getElementById(\"messages\")\n        msgs.insertBefore(node, msgs.childNodes[0]);\n    }\n\n    conn = new WebSocket(\"ws://localhost:8080/notifications\");\n    conn.onmessage = function (event) {\n        newMessage(JSON.parse(event.data));\n    };\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "5-architecture/6_websockets/main.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/gorilla/websocket\"\n\t\"github.com/icrowley/fake\"\n)\n\nvar upgrader = websocket.Upgrader{\n\tReadBufferSize:  1024,\n\tWriteBufferSize: 1024,\n\tCheckOrigin: func(r *http.Request) bool {\n\t\treturn true\n\t},\n}\n\nfunc sendNewMsgNotifications(client *websocket.Conn) {\n\tticker := time.NewTicker(3 * time.Second)\n\tfor {\n\t\tw, err := client.NextWriter(websocket.TextMessage)\n\t\tif err != nil {\n\t\t\tticker.Stop()\n\t\t\tbreak\n\t\t}\n\n\t\tmsg := newMessage()\n\t\tw.Write(msg)\n\t\tw.Close()\n\n\t\t<-ticker.C\n\t}\n}\n\nfunc main() {\n\ttmpl := template.Must(template.ParseFiles(\"index.html\"))\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\ttmpl.Execute(w, nil)\n\t})\n\n\thttp.HandleFunc(\"/notifications\", func(w http.ResponseWriter, r *http.Request) {\n\t\tlog.Println(\"ws upgrade\")\n\t\tws, err := upgrader.Upgrade(w, r, nil)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tgo sendNewMsgNotifications(ws)\n\t})\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\nfunc newMessage() []byte {\n\tdata, _ := json.Marshal(map[string]string{\n\t\t\"email\":   fake.EmailAddress(),\n\t\t\"name\":    fake.FirstName() + \" \" + fake.LastName(),\n\t\t\"subject\": fake.Product() + \" \" + fake.Model(),\n\t})\n\treturn data\n}\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/main.go",
    "content": "package main\n\nimport (\n\t\"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/middleware\"\n\tuserhttp \"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/user/delivery/http\"\n\t\"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/user/repository\"\n\t\"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/user/usecase\"\n\n\t\"github.com/labstack/echo\"\n\techomiddleware \"github.com/labstack/echo/middleware\"\n)\n\nconst listenAddr = \"127.0.0.1:8080\"\n\nfunc main() {\n\te := echo.New()\n\n\te.Use(middleware.RequestIDMiddleware)\n\te.Use(echomiddleware.Logger())\n\te.Use(middleware.PanicMiddleware)\n\n\te.HTTPErrorHandler = middleware.ErrorHandler\n\n\tuserhttp.NewUserHandler(e, usecase.NewUserUsecase(repository.NewUserMemoryRepository()))\n\n\te.Logger.Warnf(\"start listening on %s\", listenAddr)\n\terr := e.Start(\"127.0.0.1:8080\")\n\tif err != nil {\n\t\te.Logger.Errorf(\"server error: %s\", err)\n\t}\n\n\te.Logger.Warnf(\"shutdown\")\n}\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/middleware/error.go",
    "content": "package middleware\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/labstack/echo\"\n)\n\nfunc ErrorHandler(err error, ctx echo.Context) {\n\tctx.Logger().Errorf(\"error happened while processing request: %s\", err)\n\n\tswitch err := errors.Cause(err); err.(type) {\n\tcase *echo.HTTPError:\n\t\tctx.JSON(err.(*echo.HTTPError).Code, struct {\n\t\t\tBody string\n\t\t}{Body: \"internal\"})\n\tdefault:\n\t\tctx.JSON(500, struct {\n\t\t\tBody string\n\t\t}{Body: \"internal\"})\n\t}\n\n\terr = ctx.HTML(http.StatusInternalServerError, \"internal\")\n\tif err != nil {\n\t\tctx.Logger().Errorf(\"failed to write 500 internal after error: %s\", err)\n\t}\n}\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/middleware/panic.go",
    "content": "package middleware\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/labstack/echo\"\n)\n\nfunc PanicMiddleware(next echo.HandlerFunc) echo.HandlerFunc {\n\treturn func(ctx echo.Context) error {\n\t\tdefer func() {\n\t\t\tif err := recover(); err != nil {\n\t\t\t\tctx.Error(fmt.Errorf(\"%s\", err))\n\t\t\t}\n\t\t}()\n\n\t\treturn next(ctx)\n\t}\n}\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/middleware/request_id.go",
    "content": "package middleware\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\n\t\"github.com/labstack/echo\"\n)\n\nfunc RequestIDMiddleware(next echo.HandlerFunc) echo.HandlerFunc {\n\treturn func(ctx echo.Context) error {\n\t\trequestID := fmt.Sprintf(\"%016x\", rand.Int())[:10]\n\n\t\tctx.Logger().SetPrefix(fmt.Sprintf(\"%s rid=%s\", ctx.Logger().Prefix(), requestID))\n\t\treturn next(ctx)\n\t}\n}\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/middleware/session.go",
    "content": "package middleware\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/model/user.go",
    "content": "package model\n\ntype User struct {\n\tUsername string\n\tPassword string `json:\"-\"`\n}\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/user/delivery/http/hander_test.go",
    "content": "package http\n\nimport (\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/model\"\n\t\"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/user\"\n\t\"github.com/golang/mock/gomock\"\n\t\"github.com/labstack/echo\"\n)\n\nfunc TestGetUser(t *testing.T) {\n\tctrl := gomock.NewController(t)\n\tdefer ctrl.Finish()\n\n\tusecase := user.NewMockUsecase(ctrl)\n\n\tusecase.EXPECT().GetUser(gomock.Eq(\"ivan\")).Return(model.User{\n\t\tUsername: \"Ivan\",\n\t}, nil)\n\n\thandler := userHandler{usecase: usecase}\n\te := echo.New()\n\n\treq := httptest.NewRequest(http.MethodGet, \"/user/ivan\", nil)\n\trec := httptest.NewRecorder()\n\n\tc := e.NewContext(req, rec)\n\tc.SetPath(\"/user/:username\")\n\tc.SetParamNames(\"username\")\n\tc.SetParamValues(\"ivan\")\n\n\terr := handler.GetUser(c)\n\n\tif err != nil {\n\t\tt.Errorf(\"err is not nil: %s\", err)\n\t}\n\n\tbody, _ := ioutil.ReadAll(rec.Body)\n\n\tif strings.Trim(string(body), \"\\n\") != `{\"Username\":\"Ivan\"}` {\n\t\tt.Errorf(\"Expected: %s, got: %s\", `{\"Username\":\"Ivan\"}`, string(body))\n\t}\n\n}\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/user/delivery/http/handler.go",
    "content": "package http\n\nimport (\n\t\"errors\"\n\n\t\"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/middleware\"\n\t\"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/user\"\n\t\"github.com/labstack/echo\"\n)\n\ntype userHandler struct {\n\tusecase user.Usecase\n}\n\nfunc NewUserHandler(e *echo.Echo, us user.Usecase) {\n\thandler := userHandler{usecase: us}\n\n\te.GET(\"/user\", handler.GetUser, middleware.PanicMiddleware)\n\te.POST(\"/user\", handler.CreateUser)\n\n\te.GET(\"/users\", handler.GetAllUsers)\n}\n\nfunc (h *userHandler) GetUser(ctx echo.Context) error {\n\tctx.Error(errors.New(\"some error\"))\n}\n\nfunc (h *userHandler) GetAllUsers(ctx echo.Context) error {\n\treturn nil\n}\n\nfunc (h *userHandler) CreateUser(ctx echo.Context) error {\n\treturn nil\n}\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/user/repository/memory.go",
    "content": "package repository\n\nimport (\n\t\"sync\"\n\n\t\"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/model\"\n\t\"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/user\"\n)\n\nfunc NewUserMemoryRepository() user.Repository {\n\treturn &UserMemoryRepository{\n\t\tstorage: map[string]model.User{},\n\t}\n}\n\ntype UserMemoryRepository struct {\n\tmu      sync.RWMutex\n\tstorage map[string]model.User\n}\n\nfunc (db *UserMemoryRepository) GetUser(username string) (model.User, error) {\n\tpanic(\"implement me\")\n}\n\nfunc (db *UserMemoryRepository) GetAllUsers() ([]model.User, error) {\n\tdb.mu.RLock()\n\tdefer db.mu.RUnlock()\n\n\tret := make([]model.User, 0, len(db.storage))\n\n\tfor _, u := range db.storage {\n\t\tret = append(ret, u)\n\t}\n\n\treturn ret, nil\n}\n\nfunc (db *UserMemoryRepository) InsertUser(u model.User) error {\n\tdb.mu.Lock()\n\tdefer db.mu.Unlock()\n\n\tif _, ok := db.storage[u.Username]; ok {\n\t\treturn user.ErrUserExists\n\t}\n\n\tdb.storage[u.Username] = u\n\n\treturn nil\n}\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/user/repository.go",
    "content": "package user\n\nimport (\n\t\"errors\"\n\n\t\"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/model\"\n)\n\nvar ErrUserExists = errors.New(\"user exists\")\n\ntype Repository interface {\n\tGetUser(username string) (model.User, error)\n\tGetAllUsers() ([]model.User, error)\n\n\tInsertUser(user model.User) error\n}\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/user/usecase/usecase.go",
    "content": "package usecase\n\nimport (\n\t\"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/model\"\n\t\"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/user\"\n)\n\nfunc NewUserUsecase(userRepo user.Repository) user.Usecase {\n\treturn userUsecase{repo: userRepo}\n}\n\ntype userUsecase struct {\n\trepo user.Repository\n}\n\nfunc (u userUsecase) GetUser(username string) (model.User, error) {\n\treturn u.repo.GetUser(username)\n}\n\nfunc (u userUsecase) GetAllUsers() ([]model.User, error) {\n\treturn u.repo.GetAllUsers()\n}\n\nfunc (u userUsecase) CreateUser(user model.User) error {\n\treturn u.repo.InsertUser(user)\n}\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/user/usecase.go",
    "content": "package user\n\nimport \"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/model\"\n\ntype Usecase interface {\n\tGetUser(username string) (model.User, error)\n\tGetAllUsers() ([]model.User, error)\n\n\tCreateUser(user model.User) error\n}\n"
  },
  {
    "path": "5-architecture/7_frameworks/echo/user/usecase_mock.go",
    "content": "// Code generated by MockGen. DO NOT EDIT.\n// Source: user/usecase.go\n\n// Package user is a generated GoMock package.\npackage user\n\nimport (\n\tmodel \"github.com/go-park-mail-ru/lectures/5-architecture/7_frameworks/echo/model\"\n\tgomock \"github.com/golang/mock/gomock\"\n\treflect \"reflect\"\n)\n\n// MockUsecase is a mock of Usecase interface\ntype MockUsecase struct {\n\tctrl     *gomock.Controller\n\trecorder *MockUsecaseMockRecorder\n}\n\n// MockUsecaseMockRecorder is the mock recorder for MockUsecase\ntype MockUsecaseMockRecorder struct {\n\tmock *MockUsecase\n}\n\n// NewMockUsecase creates a new mock instance\nfunc NewMockUsecase(ctrl *gomock.Controller) *MockUsecase {\n\tmock := &MockUsecase{ctrl: ctrl}\n\tmock.recorder = &MockUsecaseMockRecorder{mock}\n\treturn mock\n}\n\n// EXPECT returns an object that allows the caller to indicate expected use\nfunc (m *MockUsecase) EXPECT() *MockUsecaseMockRecorder {\n\treturn m.recorder\n}\n\n// GetUser mocks base method\nfunc (m *MockUsecase) GetUser(username string) (model.User, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"GetUser\", username)\n\tret0, _ := ret[0].(model.User)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// GetUser indicates an expected call of GetUser\nfunc (mr *MockUsecaseMockRecorder) GetUser(username interface{}) *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"GetUser\", reflect.TypeOf((*MockUsecase)(nil).GetUser), username)\n}\n\n// GetAllUsers mocks base method\nfunc (m *MockUsecase) GetAllUsers() ([]model.User, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"GetAllUsers\")\n\tret0, _ := ret[0].([]model.User)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// GetAllUsers indicates an expected call of GetAllUsers\nfunc (mr *MockUsecaseMockRecorder) GetAllUsers() *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"GetAllUsers\", reflect.TypeOf((*MockUsecase)(nil).GetAllUsers))\n}\n\n// CreateUser mocks base method\nfunc (m *MockUsecase) CreateUser(user model.User) error {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"CreateUser\", user)\n\tret0, _ := ret[0].(error)\n\treturn ret0\n}\n\n// CreateUser indicates an expected call of CreateUser\nfunc (mr *MockUsecaseMockRecorder) CreateUser(user interface{}) *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"CreateUser\", reflect.TypeOf((*MockUsecase)(nil).CreateUser), user)\n}\n"
  },
  {
    "path": "5-architecture/readings_5.md",
    "content": "# Репозиторий, архитектура, либы\n\nLayout'ы репозиториев:\n\n* https://github.com/golang-standards/project-layout - стандартный layout репозитория сервиса на гошке\n* https://github.com/bxcodec/go-clean-arch - layout репозитория с чистой архитектурой\n\nОсновная и самая важная ссылка, касательно компонентов:\n\n* https://github.com/avelino/awesome-go\n\nШаблоны:\n\n* https://github.com/SlinSo/goTemplateBenchmark\n\nРоутеры:\n\n* https://github.com/gorilla/mux - один из компонентов gorillatoolkit, из которых можно собрать себе полноценный фреймворк\n* https://github.com/julienschmidt/httprouter\n* https://github.com/valyala/fasthttp\n* https://github.com/julienschmidt/go-http-routing-benchmark\n\nФреймворки:\n\n* https://github.com/labstack/echo\n* https://github.com/gin-gonic/gin\n* https://github.com/gramework/gramework - быстрый веб-ферймворк на основе fasthttp\n\nЛогирование:\n\n* https://github.com/uber-go/zap\n* https://github.com/sirupsen/logrus\n* https://www.youtube.com/watch?v=c_MPDg2C9tg - видео по структурному логирования\n* https://habrahabr.ru/company/badoo/blog/328722/\n\nВеб-сокеты:\n\n* https://github.com/gorilla/websocket\n* https://github.com/gobwas/ws - библиотека для низкоуровневой работы в веб-сокетами от Mail.ru, которая позволяет существенно сэкономить на памяти сервера\n* https://github.com/olahol/melody\n\nБезопасность:\n\n* https://github.com/Checkmarx/Go-SCP\n"
  },
  {
    "path": "6-databases/00_databases/_kafka/setup.sh",
    "content": "#!/bin/sh\n\n/opt/bitnami/kafka/bin/kafka-topics.sh --create --topic cool_topic --bootstrap-server localhost:9092\n/opt/bitnami/kafka/bin/kafka-topics.sh --describe --topic cool_topic --bootstrap-server localhost:9092\n"
  },
  {
    "path": "6-databases/00_databases/_mysql/injection_db.sql",
    "content": "DROP TABLE IF EXISTS `users`;\nCREATE TABLE `users` (\n  `id` int(11) NOT NULL,\n  `login` varchar(200) NOT NULL,\n  `name` varchar(200) NOT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nINSERT INTO `users` (`id`, `login`, `name`) VALUES\n(1,\t'user',\t''),\n(2,\t'admin',\t'');\n"
  },
  {
    "path": "6-databases/00_databases/_mysql/items.sql",
    "content": "SET NAMES utf8;\nSET time_zone = '+00:00';\nSET foreign_key_checks = 0;\nSET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';\n\nDROP TABLE IF EXISTS `items`;\nCREATE TABLE `items` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `title` varchar(255) NOT NULL,\n  `description` text NOT NULL,\n  `updated` varchar(255) DEFAULT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nINSERT INTO `items` (`id`, `title`, `description`, `updated`) VALUES\n(1,\t'database/sql',\t'Рассказать про базы данных',\t'rvasily'),\n(2,\t'memcache',\t'Рассказать про мемкеш с примером использования',\tNULL);\n"
  },
  {
    "path": "6-databases/00_databases/_postgres/items.sql",
    "content": "SET TIME ZONE '+00:00';\n\nDROP TABLE IF EXISTS items;\n\nCREATE TABLE items (\n    id SERIAL PRIMARY KEY,\n    title VARCHAR(255) NOT NULL,\n    description TEXT NOT NULL,\n    updated VARCHAR(255)\n);\n\nINSERT INTO items (id, title, description, updated) VALUES\n    (1,\t'database/sql',\t'Рассказать про базы данных',\t'rvasily'),\n    (2,\t'memcache',\t'Рассказать про мемкеш с примером использования',\tNULL);\n\nSELECT setval(pg_get_serial_sequence('items', 'id'), MAX(id)) FROM items;\n"
  },
  {
    "path": "6-databases/00_databases/docker-compose.yml",
    "content": "version: '3'\n\n# docker-compose up -d\n# docker-compose down\n# docker rm $(docker ps -a -q) && docker volume prune -f\n\nservices:\n  mysql:\n    image: mysql:8\n    command: --mysql-native-password=ON\n    environment:\n      MYSQL_ROOT_PASSWORD: \"love\"\n      MYSQL_DATABASE: golang\n    ports:\n      - '3306:3306'\n    volumes:\n      - './_mysql/:/docker-entrypoint-initdb.d/'\n\n  postgres:\n    image: postgres:13.2\n    restart: always\n    environment:\n      POSTGRES_USER: postgres_user\n      POSTGRES_PASSWORD: postgres_password\n      POSTGRES_DB: golang\n    ports:\n      - '5432:5432'\n    volumes:\n      - './_postgres/:/docker-entrypoint-initdb.d/'\n\n  mongodb:\n    image: mongo:5\n    environment:\n      - MONGO_INITDB_DATABASE=vkbmstu\n    ports:\n      - '27017-27019:27017-27019'\n\n  adminer:\n    image: adminer\n    restart: always\n    links:\n        - \"mysql:mysql\"\n        - \"postgres:postgres\"\n    ports:\n      - '8090:8080'\n\n  memcached:\n    image: 'memcached:latest'\n    ports:\n      - '11211:11211'\n  \n  redis:\n    image: 'redis'\n    ports:\n      - '6379:6379'\n\n  rabbitmq:\n    image: 'rabbitmq'\n    ports:\n      - '5672:5672'\n\n  kafka:\n    image: bitnami/kafka:3.2.1\n    ports:\n      - '9092:9092'\n    environment:\n      KAFKA_ENABLE_KRAFT: yes\n      KAFKA_CFG_PROCESS_ROLES: broker,controller\n      KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER\n      KAFKA_CFG_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093\n      KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT\n      KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://127.0.0.1:9092\n      KAFKA_BROKER_ID: 1\n      KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 1@127.0.0.1:9093\n      ALLOW_PLAINTEXT_LISTENER: yes\n    volumes:\n      - ./_kafka:/scripts\n\n  tarantool:\n    build: ../13_tarantool_simple\n    restart: always\n    ports:\n      - '3301:3301'\n\n"
  },
  {
    "path": "6-databases/01_mysql/main.go",
    "content": "package main\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/gorilla/mux\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n)\n\ntype Item struct {\n\tId          int\n\tTitle       string\n\tDescription string\n\tUpdated     sql.NullString\n}\n\ntype Handler struct {\n\tDB   *sql.DB\n\tTmpl *template.Template\n}\n\nfunc (h *Handler) List(w http.ResponseWriter, r *http.Request) {\n\n\titems := []*Item{}\n\t// Не надо так: SELECT * FROM items\n\trows, err := h.DB.QueryContext(r.Context(), \"SELECT id, title, updated FROM items\")\n\tpanicOnErr(err)\n\t// Надо закрывать соединение, иначе будет течь\n\tdefer rows.Close()\n\n\tfor rows.Next() {\n\t\tpost := &Item{}\n\t\terr = rows.Scan(&post.Id, &post.Title, &post.Updated)\n\t\tpanicOnErr(err)\n\t\titems = append(items, post)\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"index.html\", struct {\n\t\tItems []*Item\n\t}{\n\t\tItems: items,\n\t})\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) AddForm(w http.ResponseWriter, r *http.Request) {\n\terr := h.Tmpl.ExecuteTemplate(w, \"create.html\", nil)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) Add(w http.ResponseWriter, r *http.Request) {\n\t// В целях упрощения примера пропущена валидация\n\tresult, err := h.DB.Exec(\n\t\t\"INSERT INTO items (`title`, `description`) VALUES (?, ?)\",\n\t\tr.FormValue(\"title\"),\n\t\tr.FormValue(\"description\"),\n\t)\n\tpanicOnErr(err)\n\n\taffected, err := result.RowsAffected()\n\tpanicOnErr(err)\n\tlastID, err := result.LastInsertId()\n\tpanicOnErr(err)\n\n\tfmt.Println(\"Insert - RowsAffected\", affected, \"LastInsertId: \", lastID)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *Handler) Edit(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tpanicOnErr(err)\n\n\tpost := &Item{}\n\n\trow := h.DB.QueryRow(\"SELECT id, title, updated, description FROM items WHERE id = ?\", id)\n\n\t// Scan сам закрывает коннект\n\terr = row.Scan(&post.Id, &post.Title, &post.Updated, &post.Description)\n\tpanicOnErr(err)\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"edit.html\", post)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) Update(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tpanicOnErr(err)\n\n\t// В целях упрощения примера пропущена валидация\n\tresult, err := h.DB.Exec(\n\t\t\"UPDATE items SET `title` = ?, `description` = ?, `updated` = ? WHERE id = ?\",\n\t\tr.FormValue(\"title\"), r.FormValue(\"description\"), \"user\", id,\n\t)\n\tpanicOnErr(err)\n\n\taffected, err := result.RowsAffected()\n\tpanicOnErr(err)\n\n\tfmt.Println(\"Update - RowsAffected\", affected)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tpanicOnErr(err)\n\n\tresult, err := h.DB.Exec(\n\t\t\"DELETE FROM items WHERE id = ?\",\n\t\tid,\n\t)\n\tpanicOnErr(err)\n\n\taffected, err := result.RowsAffected()\n\tpanicOnErr(err)\n\n\tfmt.Println(\"Delete - RowsAffected\", affected)\n\n\tw.Header().Set(\"Content-type\", \"application/json\")\n\tresp := `{\"affected\": ` + strconv.Itoa(int(affected)) + `}`\n\tw.Write([]byte(resp))\n}\n\nfunc main() {\n\n\t// основные настройки к базе\n\tdsn := \"root:love@tcp(localhost:3306)/golang?\"\n\t// указываем кодировку\n\tdsn += \"&charset=utf8\"\n\t// отказываемся от prepared statements\n\t// параметры подставляются сразу\n\tdsn += \"&interpolateParams=true\"\n\n\tdb, err := sql.Open(\"mysql\", dsn)\n\tpanicOnErr(err)\n\n\tdb.SetMaxOpenConns(10)\n\n\terr = db.Ping() // Тут будет первое подключение к базе\n\tpanicOnErr(err)\n\n\thandlers := &Handler{\n\t\tDB:   db,\n\t\tTmpl: template.Must(template.ParseGlob(\"templates/*\")),\n\t}\n\n\t// В целях упрощения примера пропущена авторизация и csrf\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.AddForm).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.Add).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Edit).Methods(\"GET\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Update).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Delete).Methods(\"DELETE\")\n\n\tfmt.Println(\"starting server at :8080\")\n\tfmt.Println(http.ListenAndServe(\":8080\", r))\n}\n\n// Не используйте такой код в продакшене\n// Ошибка должна всегда явно обрабатываться\nfunc panicOnErr(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n"
  },
  {
    "path": "6-databases/01_mysql/templates/create.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/new\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/01_mysql/templates/edit.html",
    "content": "<!DOCTYPE html>\r\n<html lang=\"en\">\r\n  <head>\r\n    <!-- Required meta tags -->\r\n    <meta charset=\"utf-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\r\n\r\n    <!-- Bootstrap CSS -->\r\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\r\n  </head>\r\n  <body>\r\n\r\n    <div class=\"container\">\r\n      <h1>Edit item</h1>\r\n\r\n      <form method=\"post\" action=\"/items/{{.Id}}\">\r\n        <div class=\"form-group\">\r\n          <label for=\"title\">Title</label>\r\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\r\n        </div>\r\n        <div class=\"form-group\">\r\n          <label for=\"description\">Description</label>\r\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\r\n        </div>\r\n        {{if .Updated.Valid}}\r\n        <div class=\"form-group\">\r\n          <label>{{.Updated.String}}</label>\r\n        </div>\r\n        {{end}}\r\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\r\n      </form>\r\n    </div>\r\n  </body>\r\n</html>\r\n"
  },
  {
    "path": "6-databases/01_mysql/templates/index.html",
    "content": "<!DOCTYPE html>\r\n<html lang=\"en\">\r\n  <head>\r\n    <!-- Required meta tags -->\r\n    <meta charset=\"utf-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\r\n\r\n    <!-- Bootstrap CSS -->\r\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\r\n  </head>\r\n  <body>\r\n\t<div class=\"container\">\r\n    <h1>Posts</h1>\r\n    <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th>#</th>\r\n        <th>Title</th>\r\n        <th style=\"width:60px;\">Edited</th>\r\n        <th style=\"width:140px;\"><a href=\"/items/new\" class=\"btn btn-success\">New</a></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n    {{range .Items}}\r\n      <tr>\r\n        <td>{{.Id}}</td>\r\n        <td>{{.Title}}</td>\r\n        <td>{{if .Updated.Valid}}{{.Updated.String}}{{end}}</td>\r\n        <td>\r\n          <a href=\"/items/{{.Id}}\" class=\"btn btn-primary\">Edit</a>\r\n          <span data-id=\"{{.Id}}\" class=\"do-delete btn btn-danger\">Del</span>\r\n        </td>\r\n      </tr>\r\n\t\t{{end}}\r\n    </tbody>\r\n  </div>\r\n  \r\n  <script src=\"https://code.jquery.com/jquery-3.2.1.min.js\" crossorigin=\"anonymous\"></script>\r\n\r\n  <script type=\"text/javascript\">\r\n  $('.do-delete').click(function() {\r\n    if(!confirm(\"Are you sure?\")) {\r\n      return\r\n    }\r\n    $elem = $(this)\r\n    $.ajax({\r\n      url: '/items/' + $elem.data(\"id\"),\r\n      type: 'DELETE',\r\n      data: {},\r\n      success: function(resp) {\r\n        if(resp.affected > 0 ) {\r\n          $elem.parent().parent().remove()\r\n        }\r\n      },\r\n    });\r\n  })\r\n  </script>\r\n  \r\n  </body>\r\n</html>\r\n"
  },
  {
    "path": "6-databases/02_postgresql/main.go",
    "content": "package main\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/gorilla/mux\"\n\n\t_ \"github.com/jackc/pgx/v5/stdlib\"\n)\n\ntype Item struct {\n\tId          int\n\tTitle       string\n\tDescription string\n\tUpdated     sql.NullString\n}\n\ntype Handler struct {\n\tDB   *sql.DB\n\tTmpl *template.Template\n}\n\nfunc (h *Handler) List(w http.ResponseWriter, r *http.Request) {\n\n\titems := []*Item{}\n\t// Не надо так: SELECT * FROM items\n\trows, err := h.DB.QueryContext(r.Context(), \"SELECT id, title, updated FROM items\")\n\tpanicOnErr(err)\n\n\t// Надо закрывать соединение, иначе будет течь\n\tdefer rows.Close()\n\n\tfor rows.Next() {\n\t\tpost := &Item{}\n\t\terr = rows.Scan(&post.Id, &post.Title, &post.Updated)\n\t\tpanicOnErr(err)\n\t\titems = append(items, post)\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"index.html\", struct {\n\t\tItems []*Item\n\t}{\n\t\tItems: items,\n\t})\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) AddForm(w http.ResponseWriter, r *http.Request) {\n\terr := h.Tmpl.ExecuteTemplate(w, \"create.html\", nil)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) Add(w http.ResponseWriter, r *http.Request) {\n\t// В целях упрощения примера пропущена валидация\n\tvar insertedID int\n\terr := h.DB.QueryRow(\n\t\t\"INSERT INTO items (title, description) VALUES ($1, $2) RETURNING id\",\n\t\tr.FormValue(\"title\"),\n\t\tr.FormValue(\"description\"),\n\t).Scan(&insertedID)\n\tpanicOnErr(err)\n\n\tfmt.Println(\"Insert - InsertedId: \", insertedID)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *Handler) Edit(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tpanicOnErr(err)\n\n\tpost := &Item{}\n\trow := h.DB.QueryRow(\"SELECT id, title, updated, description FROM items WHERE id = $1\", id)\n\n\t// Scan сам закрывает коннект\n\terr = row.Scan(&post.Id, &post.Title, &post.Updated, &post.Description)\n\tpanicOnErr(err)\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"edit.html\", post)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) Update(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tpanicOnErr(err)\n\n\t// В целях упрощения примера пропущена валидация\n\tresult, err := h.DB.Exec(\n\t\t\"UPDATE items SET title = $1, description = $2, updated = $3 WHERE id = $4\",\n\t\tr.FormValue(\"title\"), r.FormValue(\"description\"), \"user\", id,\n\t)\n\tpanicOnErr(err)\n\n\taffected, err := result.RowsAffected()\n\tpanicOnErr(err)\n\n\tfmt.Println(\"Update - RowsAffected\", affected)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tpanicOnErr(err)\n\n\tresult, err := h.DB.Exec(\n\t\t\"DELETE FROM items WHERE id = $1\",\n\t\tid,\n\t)\n\tpanicOnErr(err)\n\n\taffected, err := result.RowsAffected()\n\tpanicOnErr(err)\n\n\tfmt.Println(\"Delete - RowsAffected\", affected)\n\n\tw.Header().Set(\"Content-type\", \"application/json\")\n\tresp := `{\"affected\": ` + strconv.Itoa(int(affected)) + `}`\n\tw.Write([]byte(resp))\n}\n\nfunc main() {\n\n\t// Основные настройки подключения к базе\n\tdsn := \"postgres://postgres_user:postgres_password@localhost:5432/golang?\"\n\t// Отключаем использование SSL\n\tdsn += \"sslmode=disable\"\n\n\tdb, err := sql.Open(\"pgx\", dsn)\n\tpanicOnErr(err)\n\n\tdb.SetMaxOpenConns(10)\n\n\terr = db.Ping() // Тут будет первое подключение к базе\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\thandlers := &Handler{\n\t\tDB:   db,\n\t\tTmpl: template.Must(template.ParseGlob(\"templates/*\")),\n\t}\n\n\t// В целях упрощения примера пропущена авторизация и csrf\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.AddForm).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.Add).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Edit).Methods(\"GET\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Update).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Delete).Methods(\"DELETE\")\n\n\tfmt.Println(\"starting server at :8080\")\n\tfmt.Println(http.ListenAndServe(\":8080\", r))\n}\n\n// Не используйте такой код в продакшене\n// Ошибка должна всегда явно обрабатываться\nfunc panicOnErr(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n"
  },
  {
    "path": "6-databases/02_postgresql/templates/create.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/new\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/02_postgresql/templates/edit.html",
    "content": "<!DOCTYPE html>\r\n<html lang=\"en\">\r\n  <head>\r\n    <!-- Required meta tags -->\r\n    <meta charset=\"utf-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\r\n\r\n    <!-- Bootstrap CSS -->\r\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\r\n  </head>\r\n  <body>\r\n\r\n    <div class=\"container\">\r\n      <h1>Edit item</h1>\r\n\r\n      <form method=\"post\" action=\"/items/{{.Id}}\">\r\n        <div class=\"form-group\">\r\n          <label for=\"title\">Title</label>\r\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\r\n        </div>\r\n        <div class=\"form-group\">\r\n          <label for=\"description\">Description</label>\r\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\r\n        </div>\r\n        {{if .Updated.Valid}}\r\n        <div class=\"form-group\">\r\n          <label>{{.Updated.String}}</label>\r\n        </div>\r\n        {{end}}\r\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\r\n      </form>\r\n    </div>\r\n  </body>\r\n</html>\r\n"
  },
  {
    "path": "6-databases/02_postgresql/templates/index.html",
    "content": "<!DOCTYPE html>\r\n<html lang=\"en\">\r\n  <head>\r\n    <!-- Required meta tags -->\r\n    <meta charset=\"utf-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\r\n\r\n    <!-- Bootstrap CSS -->\r\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\r\n  </head>\r\n  <body>\r\n\t<div class=\"container\">\r\n    <h1>Posts</h1>\r\n    <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th>#</th>\r\n        <th>Title</th>\r\n        <th style=\"width:60px;\">Edited</th>\r\n        <th style=\"width:140px;\"><a href=\"/items/new\" class=\"btn btn-success\">New</a></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n    {{range .Items}}\r\n      <tr>\r\n        <td>{{.Id}}</td>\r\n        <td>{{.Title}}</td>\r\n        <td>{{if .Updated.Valid}}{{.Updated.String}}{{end}}</td>\r\n        <td>\r\n          <a href=\"/items/{{.Id}}\" class=\"btn btn-primary\">Edit</a>\r\n          <span data-id=\"{{.Id}}\" class=\"do-delete btn btn-danger\">Del</span>\r\n        </td>\r\n      </tr>\r\n\t\t{{end}}\r\n    </tbody>\r\n  </div>\r\n  \r\n  <script src=\"https://code.jquery.com/jquery-3.2.1.min.js\" crossorigin=\"anonymous\"></script>\r\n\r\n  <script type=\"text/javascript\">\r\n  $('.do-delete').click(function() {\r\n    if(!confirm(\"Are you sure?\")) {\r\n      return\r\n    }\r\n    $elem = $(this)\r\n    $.ajax({\r\n      url: '/items/' + $elem.data(\"id\"),\r\n      type: 'DELETE',\r\n      data: {},\r\n      success: function(resp) {\r\n        if(resp.affected > 0 ) {\r\n          $elem.parent().parent().remove()\r\n        }\r\n      },\r\n    });\r\n  })\r\n  </script>\r\n  \r\n  </body>\r\n</html>\r\n"
  },
  {
    "path": "6-databases/03_mysql_sql_injection/main.go",
    "content": "package main\n\nimport (\n\t\"database/sql\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n)\n\nvar loginFormTmpl = `\n<html>\n\t<body>\n\t<form action=\"/login\" method=\"post\">\n\t\tLogin: <input type=\"text\" name=\"login\">\n\t\tPassword: <input type=\"password\" name=\"password\">\n\t\t<input type=\"submit\" value=\"Login\">\n\t</form>\n\t</body>\n</html>\n`\n\nfunc main() {\n\n\t// Основные настройки подключения к базе\n\tdsn := \"root:love@tcp(localhost:3306)/golang?\"\n\t// Указываем кодировку\n\tdsn += \"&charset=utf8\"\n\t// Отказываемся от prepared statements\n\t// Параметры подставляются сразу\n\tdsn += \"&interpolateParams=true\"\n\n\tvar err error\n\t// Создаём структуру базы\n\t// Но соединение происходит только при первом запросе\n\tdb, err := sql.Open(\"mysql\", dsn)\n\tPanicOnErr(err)\n\n\terr = db.Ping() // Тут будет первое подключение к базе\n\tPanicOnErr(err)\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tw.Write([]byte(loginFormTmpl))\n\t})\n\n\thttp.HandleFunc(\"/login\", func(w http.ResponseWriter, r *http.Request) {\n\t\tvar (\n\t\t\tid          int\n\t\t\tlogin, body string\n\t\t)\n\n\t\tinputLogin := r.FormValue(\"login\")\n\t\tbody += fmt.Sprintln(\"inputLogin:\", inputLogin)\n\n\t\t// ПЛОХО! НЕ ДЕЛАЙТЕ ТАК!\n\t\t// Параметры не экранированы должным образом\n\t\t// Мы подставляем в запрос параметр как есть\n\t\tquery := fmt.Sprintf(\"SELECT id, login FROM users WHERE login = '%s' LIMIT 1\", inputLogin) // SELECT id, login FROM users WHERE login = '' OR '1'<>'2' LIMIT 1\n\t\t//query := fmt.Sprintf(\"SELECT id, login FROM users WHERE (login = '%s' AND login <> 'admin') LIMIT 1\", inputLogin) // SELECT id, login FROM users WHERE (login = 'admin') #' AND login <> 'admin') LIMIT 1\n\n\t\tbody += fmt.Sprintln(\"Sprint query:\", query)\n\n\t\trow := db.QueryRow(query)\n\t\terr := row.Scan(&id, &login)\n\n\t\tif errors.Is(err, sql.ErrNoRows) {\n\t\t\tbody += fmt.Sprintln(\"Sprint case: NOT FOUND\")\n\t\t} else {\n\t\t\tPanicOnErr(err)\n\t\t\tbody += fmt.Sprintln(\"Sprint case: id:\", id, \"login:\", login)\n\t\t}\n\n\t\t// ПРАВИЛЬНО\n\t\t// Мы используем плейсхолдеры, там параметры будет экранирован должным образом\n\t\trow = db.QueryRow(\"SELECT id, login FROM users WHERE login = ? LIMIT 1\", inputLogin)\n\t\terr = row.Scan(&id, &login)\n\t\tif errors.Is(err, sql.ErrNoRows) {\n\t\t\tbody += fmt.Sprintln(\"Placeholders case: NOT FOUND\")\n\t\t} else {\n\t\t\tPanicOnErr(err)\n\t\t\tbody += fmt.Sprintln(\"Placeholders id:\", id, \"login:\", login)\n\t\t}\n\n\t\tw.Write([]byte(body))\n\t})\n\n\tfmt.Println(\"starting server at :8080\")\n\tPanicOnErr(http.ListenAndServe(\":8080\", nil))\n}\n\n// PanicOnErr panics on error\nfunc PanicOnErr(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n"
  },
  {
    "path": "6-databases/04_mysql_sqlmock/item_repo.go",
    "content": "package main\n\nimport (\n\t\"database/sql\"\n)\n\ntype Item struct {\n\tID          int64\n\tTitle       string\n\tDescription string\n\tUpdated     sql.NullString\n}\n\ntype ItemRepository struct {\n\tDB *sql.DB\n}\n\nfunc (repo *ItemRepository) ListAll() ([]*Item, error) {\n\titems := []*Item{}\n\trows, err := repo.DB.Query(\"SELECT id, title, updated FROM items\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer rows.Close() // надо закрывать соединение, иначе будет течь\n\tfor rows.Next() {\n\t\tpost := &Item{}\n\t\terr = rows.Scan(&post.ID, &post.Title, &post.Updated)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\titems = append(items, post)\n\t}\n\treturn items, nil\n}\n\nfunc (repo *ItemRepository) SelectByID(id int64) (*Item, error) {\n\tpost := &Item{}\n\t// QueryRow сам закрывает коннект\n\terr := repo.DB.\n\t\tQueryRow(\"SELECT id, title, updated, description FROM items WHERE id = ?\", id).\n\t\tScan(&post.ID, &post.Title, &post.Updated, &post.Description)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn post, nil\n}\n\nfunc (repo *ItemRepository) Create(elem *Item) (int64, error) {\n\tresult, err := repo.DB.Exec(\n\t\t\"INSERT INTO items (`title`, `description`) VALUES (?, ?)\",\n\t\telem.Title,\n\t\telem.Description,\n\t)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn result.LastInsertId()\n}\n\nfunc (repo *ItemRepository) Update(elem *Item) (int64, error) {\n\tresult, err := repo.DB.Exec(\n\t\t\"UPDATE items SET\"+\n\t\t\t\"`title` = ?\"+\n\t\t\t\",`description` = ?\"+\n\t\t\t\",`updated` = ?\"+\n\t\t\t\"WHERE id = ?\",\n\t\telem.Title,\n\t\telem.Description,\n\t\t\"rvasily\",\n\t\telem.ID,\n\t)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn result.RowsAffected()\n}\n\nfunc (repo *ItemRepository) Delete(id int64) (int64, error) {\n\tresult, err := repo.DB.Exec(\n\t\t\"DELETE FROM items WHERE id = ?\",\n\t\tid,\n\t)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn result.RowsAffected()\n}\n"
  },
  {
    "path": "6-databases/04_mysql_sqlmock/item_repo_test.go",
    "content": "package main\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/DATA-DOG/go-sqlmock\"\n\t\"github.com/stretchr/testify/require\"\n)\n\n// go test -coverprofile=cover.out && go tool cover -html=cover.out -o cover.html\n\nfunc TestSelectByID(t *testing.T) {\n\tdb, mock, err := sqlmock.New()\n\tif err != nil {\n\t\tt.Fatalf(\"cant create mock: %s\", err)\n\t}\n\tdefer db.Close()\n\n\tvar elemID int64 = 1\n\n\t// good query\n\trows := sqlmock.\n\t\tNewRows([]string{\"id\", \"title\", \"updated\", \"description\"})\n\texpect := []*Item{\n\t\t{elemID, \"title\", \"desct\", sql.NullString{}},\n\t}\n\tfor _, item := range expect {\n\t\trows = rows.AddRow(item.ID, item.Title, nil, item.Description)\n\t}\n\n\tmock.\n\t\tExpectQuery(\"SELECT id, title, updated, description FROM items WHERE\").\n\t\tWithArgs(elemID).\n\t\tWillReturnRows(rows)\n\n\trepo := &ItemRepository{\n\t\tDB: db,\n\t}\n\titem, err := repo.SelectByID(elemID)\n\tif err != nil {\n\t\tt.Errorf(\"unexpected err: %s\", err)\n\t\treturn\n\t}\n\tif err := mock.ExpectationsWereMet(); err != nil {\n\t\tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t\treturn\n\t}\n\n\trequire.Equalf(t, item, expect[0], \"results not match, want %v, have %v\", expect[0], item)\n\n\t// query error\n\tmock.\n\t\tExpectQuery(\"SELECT id, title, updated, description FROM items WHERE\").\n\t\tWithArgs(elemID).\n\t\tWillReturnError(fmt.Errorf(\"db_error\"))\n\n\t_, err = repo.SelectByID(elemID)\n\tif err := mock.ExpectationsWereMet(); err != nil {\n\t\tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t\treturn\n\t}\n\tif err == nil {\n\t\tt.Errorf(\"expected error, got nil\")\n\t\treturn\n\t}\n\n\t// row scan error\n\trows = sqlmock.NewRows([]string{\"id\", \"title\"}).\n\t\tAddRow(1, \"title\")\n\n\tmock.\n\t\tExpectQuery(\"SELECT id, title, updated, description FROM items WHERE\").\n\t\tWithArgs(elemID).\n\t\tWillReturnRows(rows)\n\n\t_, err = repo.SelectByID(elemID)\n\tif err := mock.ExpectationsWereMet(); err != nil {\n\t\tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t\treturn\n\t}\n\tif err == nil {\n\t\tt.Errorf(\"expected error, got nil\")\n\t\treturn\n\t}\n\n}\n\nfunc TestCreate(t *testing.T) {\n\tdb, mock, err := sqlmock.New()\n\tif err != nil {\n\t\tt.Fatalf(\"cant create mock: %s\", err)\n\t}\n\tdefer db.Close()\n\n\trepo := &ItemRepository{\n\t\tDB: db,\n\t}\n\n\ttitle := \"title\"\n\tdescr := \"description\"\n\ttestItem := &Item{\n\t\tTitle:       title,\n\t\tDescription: descr,\n\t}\n\n\t//ok query\n\tmock.\n\t\tExpectExec(`INSERT INTO items`).\n\t\tWithArgs(title, descr).\n\t\tWillReturnResult(sqlmock.NewResult(1, 1))\n\n\tid, err := repo.Create(testItem)\n\tif err != nil {\n\t\tt.Errorf(\"unexpected err: %s\", err)\n\t\treturn\n\t}\n\tif id != 1 {\n\t\tt.Errorf(\"bad id: want %v, have %v\", id, 1)\n\t\treturn\n\t}\n\n\tif err := mock.ExpectationsWereMet(); err != nil {\n\t\tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t}\n\n\t// query error\n\tmock.\n\t\tExpectExec(`INSERT INTO items`).\n\t\tWithArgs(title, descr).\n\t\tWillReturnError(fmt.Errorf(\"bad query\"))\n\n\t_, err = repo.Create(testItem)\n\tif err == nil {\n\t\tt.Errorf(\"expected error, got nil\")\n\t\treturn\n\t}\n\tif err := mock.ExpectationsWereMet(); err != nil {\n\t\tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t}\n\n\t// result error\n\tmock.\n\t\tExpectExec(`INSERT INTO items`).\n\t\tWithArgs(title, descr).\n\t\tWillReturnResult(sqlmock.NewErrorResult(fmt.Errorf(\"bad_result\")))\n\n\t_, err = repo.Create(testItem)\n\tif err == nil {\n\t\tt.Errorf(\"expected error, got nil\")\n\t\treturn\n\t}\n\tif err := mock.ExpectationsWereMet(); err != nil {\n\t\tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t}\n\n\t// // last id error\n\t// mock.\n\t// \tExpectExec(`INSERT INTO items`).\n\t// \tWithArgs(title, descr).\n\t// \tWillReturnResult(sqlmock.NewResult(0, 0))\n\n\t// _, err = repo.Create(testItem)\n\t// if err == nil {\n\t// \tt.Errorf(\"expected error, got nil\")\n\t// \treturn\n\t// }\n\t// if err := mock.ExpectationsWereMet(); err != nil {\n\t// \tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t// }\n\n}\n"
  },
  {
    "path": "6-databases/04_mysql_sqlmock/main.go",
    "content": "package main\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"log\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/gorilla/mux\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n)\n\ntype ItemCRUD interface {\n\tListAll() ([]*Item, error)\n\tSelectByID(int64) (*Item, error)\n\tCreate(*Item) (int64, error)\n\tUpdate(*Item) (int64, error)\n\tDelete(int64) (int64, error)\n}\n\ntype Handler struct {\n\tItems ItemCRUD\n\tTmpl  *template.Template\n}\n\nfunc (h *Handler) List(w http.ResponseWriter, r *http.Request) {\n\titems, err := h.Items.ListAll()\n\tif err != nil {\n\t\tlog.Println(\"Items.ListAll err:\", err)\n\t\thttp.Error(w, \"db err\", 500)\n\t\treturn\n\t}\n\terr = h.Tmpl.ExecuteTemplate(w, \"index.html\", struct {\n\t\tItems []*Item\n\t}{\n\t\tItems: items,\n\t})\n\tif err != nil {\n\t\tlog.Println(\"Tmpl.ExecuteTemplate err:\", err)\n\t\thttp.Error(w, \"template expand err\", 500)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) AddForm(w http.ResponseWriter, r *http.Request) {\n\terr := h.Tmpl.ExecuteTemplate(w, \"create.html\", nil)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) Add(w http.ResponseWriter, r *http.Request) {\n\telem := &Item{\n\t\tTitle:       r.FormValue(\"title\"),\n\t\tDescription: r.FormValue(\"description\"),\n\t}\n\tlastID, err := h.Items.Create(elem)\n\tif err != nil {\n\t\tlog.Println(\"Items.Create err:\", err)\n\t\thttp.Error(w, \"db err\", 500)\n\t\treturn\n\t}\n\n\tfmt.Println(\"LastInsertId: \", lastID)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *Handler) Edit(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tif err != nil || id == 0 {\n\t\tlog.Println(\"bad id:\", id, err)\n\t\thttp.Error(w, \"bad request\", 400)\n\t\treturn\n\t}\n\n\tpost, err := h.Items.SelectByID(int64(id))\n\tif err != nil {\n\t\tlog.Println(\"Items.SelectByID err:\", err)\n\t\thttp.Error(w, \"db err\", 500)\n\t\treturn\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"edit.html\", post)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) Update(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tpanicOnErr(err)\n\n\telem := &Item{\n\t\tID:          int64(id),\n\t\tTitle:       r.FormValue(\"title\"),\n\t\tDescription: r.FormValue(\"description\"),\n\t}\n\taffected, err := h.Items.Update(elem)\n\tif err != nil {\n\t\tlog.Println(\"Items.Update err:\", err)\n\t\thttp.Error(w, \"db err\", 500)\n\t\treturn\n\t}\n\n\tfmt.Println(\"Update - RowsAffected\", affected)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tpanicOnErr(err)\n\n\taffected, err := h.Items.Delete(int64(id))\n\tfmt.Println(\"Delete - RowsAffected\", affected, err)\n\n\tw.Header().Set(\"Content-type\", \"application/json\")\n\tresp := `{\"affected\": ` + strconv.Itoa(int(affected)) + `}`\n\tw.Write([]byte(resp))\n}\n\nfunc main() {\n\t// основные настройки к базе\n\tdsn := \"root:love@tcp(localhost:3306)/golang?\"\n\t// указываем кодировку\n\tdsn += \"&charset=utf8\"\n\t// отказываемся от prapared statements\n\t// параметры подставляются сразу\n\tdsn += \"&interpolateParams=true\"\n\n\tdb, err := sql.Open(\"mysql\", dsn)\n\tpanicOnErr(err)\n\n\tdb.SetMaxOpenConns(10)\n\n\terr = db.Ping() // Тут будет первое подключение к базе\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\titemsRepo := &ItemRepository{\n\t\tDB: db,\n\t}\n\n\thandlers := &Handler{\n\t\tItems: itemsRepo,\n\t\tTmpl:  template.Must(template.ParseGlob(\"./templates/*\")),\n\t}\n\n\t// В целях упрощения примера пропущена авторизация и csrf\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.AddForm).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.Add).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Edit).Methods(\"GET\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Update).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Delete).Methods(\"DELETE\")\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", r)\n}\n\n// Не используйте такой код в продакшене.\n// Ошибка должна всегда явно обрабатываться\nfunc panicOnErr(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n"
  },
  {
    "path": "6-databases/04_mysql_sqlmock/templates/create.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/new\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/04_mysql_sqlmock/templates/edit.html",
    "content": "<!DOCTYPE html>\r\n<html lang=\"en\">\r\n  <head>\r\n    <!-- Required meta tags -->\r\n    <meta charset=\"utf-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\r\n\r\n    <!-- Bootstrap CSS -->\r\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\r\n  </head>\r\n  <body>\r\n\r\n    <div class=\"container\">\r\n      <h1>Edit item</h1>\r\n\r\n      <form method=\"post\" action=\"/items/{{.Id}}\">\r\n        <div class=\"form-group\">\r\n          <label for=\"title\">Title</label>\r\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\r\n        </div>\r\n        <div class=\"form-group\">\r\n          <label for=\"description\">Description</label>\r\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\r\n        </div>\r\n        {{if .Updated.Valid}}\r\n        <div class=\"form-group\">\r\n          <label>{{.Updated.String}}</label>\r\n        </div>\r\n        {{end}}\r\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\r\n      </form>\r\n    </div>\r\n  </body>\r\n</html>\r\n"
  },
  {
    "path": "6-databases/04_mysql_sqlmock/templates/index.html",
    "content": "<!DOCTYPE html>\r\n<html lang=\"en\">\r\n  <head>\r\n    <!-- Required meta tags -->\r\n    <meta charset=\"utf-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\r\n\r\n    <!-- Bootstrap CSS -->\r\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\r\n  </head>\r\n  <body>\r\n\t<div class=\"container\">\r\n    <h1>Posts</h1>\r\n    <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th>#</th>\r\n        <th>Title</th>\r\n        <th style=\"width:60px;\">Edited</th>\r\n        <th style=\"width:140px;\"><a href=\"/items/new\" class=\"btn btn-success\">New</a></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n    {{range .Items}}\r\n      <tr>\r\n        <td>{{.Id}}</td>\r\n        <td>{{.Title}}</td>\r\n        <td>{{if .Updated.Valid}}{{.Updated.String}}{{end}}</td>\r\n        <td>\r\n          <a href=\"/items/{{.Id}}\" class=\"btn btn-primary\">Edit</a>\r\n          <span data-id=\"{{.Id}}\" class=\"do-delete btn btn-danger\">Del</span>\r\n        </td>\r\n      </tr>\r\n\t\t{{end}}\r\n    </tbody>\r\n  </div>\r\n  \r\n  <script src=\"https://code.jquery.com/jquery-3.2.1.min.js\" crossorigin=\"anonymous\"></script>\r\n\r\n  <script type=\"text/javascript\">\r\n  $('.do-delete').click(function() {\r\n    if(!confirm(\"Are you sure?\")) {\r\n      return\r\n    }\r\n    $elem = $(this)\r\n    $.ajax({\r\n      url: '/items/' + $elem.data(\"id\"),\r\n      type: 'DELETE',\r\n      data: {},\r\n      success: function(resp) {\r\n        if(resp.affected > 0 ) {\r\n          $elem.parent().parent().remove()\r\n        }\r\n      },\r\n    });\r\n  })\r\n  </script>\r\n  \r\n  </body>\r\n</html>\r\n"
  },
  {
    "path": "6-databases/05_gorm/main.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/gorilla/mux\"\n\t\"github.com/jinzhu/gorm\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n)\n\ntype Item struct {\n\tId          int `sql:\"AUTO_INCREMENT\" gorm:\"primary_key\"`\n\tTitle       string\n\tDescription string\n\tUpdated     string `sql:\"null\"`\n}\n\nfunc (Item) TableName() string {\n\treturn \"items\"\n}\n\nfunc (Item) BeforeSave() (err error) {\n\tfmt.Println(\"trigger on before save\")\n\treturn\n}\n\n// see also https://github.com/doug-martin/goqu\ntype Handler struct {\n\tDB   *gorm.DB\n\tTmpl *template.Template\n}\n\nfunc (h *Handler) List(w http.ResponseWriter, r *http.Request) {\n\n\titems := []*Item{}\n\n\tdb := h.DB.Find(&items)\n\terr := db.Error\n\t__err_panic(err)\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"index.html\", struct {\n\t\tItems []*Item\n\t}{\n\t\tItems: items,\n\t})\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) AddForm(w http.ResponseWriter, r *http.Request) {\n\terr := h.Tmpl.ExecuteTemplate(w, \"create.html\", nil)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) Add(w http.ResponseWriter, r *http.Request) {\n\n\tnewItem := &Item{\n\t\tTitle:       r.FormValue(\"title\"),\n\t\tDescription: r.FormValue(\"description\"),\n\t}\n\tdb := h.DB.Create(&newItem)\n\terr := db.Error\n\t__err_panic(err)\n\taffected := db.RowsAffected\n\n\tfmt.Println(\"Insert - RowsAffected\", affected, \"LastInsertId: \", newItem.Id)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *Handler) Edit(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\t__err_panic(err)\n\n\tpost := &Item{\n\t\tId: id,\n\t}\n\n\tdb := h.DB.Find(post)\n\terr = db.Error\n\tif errors.Is(err, gorm.ErrRecordNotFound) {\n\t\tfmt.Println(\"Record not found\", id)\n\t} else {\n\t\t__err_panic(err)\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"edit.html\", post)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) Update(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\t__err_panic(err)\n\n\tpost := &Item{}\n\th.DB.Find(post, id)\n\n\tpost.Title = r.FormValue(\"title\")\n\tpost.Description = r.FormValue(\"description\")\n\tpost.Updated = \"rvasily\"\n\n\tdb := h.DB.Save(post)\n\terr = db.Error\n\t__err_panic(err)\n\taffected := db.RowsAffected\n\n\tfmt.Println(\"Update - RowsAffected\", affected)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\t__err_panic(err)\n\n\tdb := h.DB.Delete(&Item{Id: id})\n\terr = db.Error\n\t__err_panic(err)\n\taffected := db.RowsAffected\n\n\tfmt.Println(\"Delete - RowsAffected\", affected)\n\n\tw.Header().Set(\"Content-type\", \"application/json\")\n\tresp := `{\"affected\": ` + strconv.Itoa(int(affected)) + `}`\n\tw.Write([]byte(resp))\n}\n\nfunc main() {\n\n\t// основные настройки к базе\n\tdsn := \"root:love@tcp(localhost:3306)/golang?\"\n\t// указываем кодировку\n\tdsn += \"&charset=utf8\"\n\t// отказываемся от prapared statements\n\t// параметры подставляются сразу\n\tdsn += \"&interpolateParams=true\"\n\n\tdb, err := gorm.Open(\"mysql\", dsn)\n\tdb.DB()\n\tdb.DB().Ping()\n\t__err_panic(err)\n\n\thandlers := &Handler{\n\t\tDB:   db,\n\t\tTmpl: template.Must(template.ParseGlob(\"templates/*\")),\n\t}\n\n\t// в целям упрощения примера пропущена авторизация и csrf\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.AddForm).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.Add).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Edit).Methods(\"GET\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Update).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Delete).Methods(\"DELETE\")\n\n\tfmt.Println(\"starting server at :8080\")\n\tfmt.Println(http.ListenAndServe(\":8080\", r))\n}\n\n// не используйте такой код в прошакшене\n// ошибка должна всегда явно обрабатываться\nfunc __err_panic(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n"
  },
  {
    "path": "6-databases/05_gorm/templates/create.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/new\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/05_gorm/templates/edit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/{{.Id}}\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n        <div class=\"form-group\">\n          <label>{{.Updated}}</label>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/05_gorm/templates/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\t<div class=\"container\">\n    <h1>Posts</h1>\n    <table class=\"table\">\n    <thead>\n      <tr>\n        <th>#</th>\n        <th>Title</th>\n        <th style=\"width:60px;\">Edited</th>\n        <th style=\"width:140px;\"><a href=\"/items/new\" class=\"btn btn-success\">New</a></th>\n      </tr>\n    </thead>\n    <tbody>\n    {{range .Items}}\n      <tr>\n        <td>{{.Id}}</td>\n        <td>{{.Title}}</td>\n        <td>{{.Updated}}</td>\n        <td>\n          <a href=\"/items/{{.Id}}\" class=\"btn btn-primary\">Edit</a>\n          <span data-id=\"{{.Id}}\" class=\"do-delete btn btn-danger\">Del</span>\n        </td>\n      </tr>\n\t\t{{end}}\n    </tbody>\n  </div>\n  \n  <script src=\"https://code.jquery.com/jquery-3.2.1.min.js\" crossorigin=\"anonymous\"></script>\n\n  <script type=\"text/javascript\">\n  $('.do-delete').click(function() {\n    if(!confirm(\"Are you sure?\")) {\n      return\n    }\n    $elem = $(this)\n    $.ajax({\n      url: '/items/' + $elem.data(\"id\"),\n      type: 'DELETE',\n      data: {},\n      success: function(resp) {\n        if(resp.affected > 0 ) {\n          $elem.parent().parent().remove()\n        }\n      },\n    });\n  })\n  </script>\n  \n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/cmd/crudapp/main.go",
    "content": "package main\n\nimport (\n\t\"database/sql\"\n\t\"html/template\"\n\t\"log\"\n\t\"net/http\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n\t_ \"github.com/jackc/pgx/stdlib\"\n\t\"github.com/jmoiron/sqlx\"\n\t\"gorm.io/driver/mysql\"\n\t\"gorm.io/gorm\"\n\n\t\"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/handlers\"\n\t\"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/items\"\n\t\"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/middleware\"\n\t\"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/session\"\n\t\"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/user\"\n\n\t\"github.com/gorilla/mux\"\n\t\"go.uber.org/zap\"\n)\n\nfunc getMysql() *sql.DB {\n\tdsn := \"root:love@tcp(localhost:3306)/golang?&charset=utf8&interpolateParams=true\"\n\tdb, err := sql.Open(\"mysql\", dsn)\n\terr = db.Ping() // вот тут будет первое подключение к базе\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\tdb.SetMaxOpenConns(10)\n\treturn db\n}\n\nfunc getPostgres() *sql.DB {\n\tdsn := \"user=postgres_user dbname=golang password=postgres_password host=127.0.0.1 port=5432 sslmode=disable\"\n\tdb, err := sql.Open(\"pgx\", dsn)\n\tif err != nil {\n\t\tlog.Fatalln(\"cant parse config\", err)\n\t}\n\terr = db.Ping() // вот тут будет первое подключение к базе\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\tdb.SetMaxOpenConns(10)\n\treturn db\n}\n\n// http://jmoiron.github.io/sqlx/\nfunc getSqlx() *sqlx.DB {\n\treturn sqlx.NewDb(getMysql(), \"mysql\")\n}\n\n// https://gorm.io/\nfunc getGorm() *gorm.DB {\n\tdb, err := gorm.Open(mysql.New(mysql.Config{\n\t\tConn: getMysql(),\n\t}), &gorm.Config{})\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\treturn db\n}\n\nfunc main() {\n\n\t// -----\n\n\ttemplates := template.Must(template.ParseGlob(\"./templates/*\"))\n\n\tsm := session.NewSessionsMem()\n\tzapLogger, _ := zap.NewProduction()\n\tdefer zapLogger.Sync() // flushes buffer, if any\n\tlogger := zapLogger.Sugar()\n\n\t// dbMSSQL := sql.Open(...)\n\n\tuserRepo := user.NewUserRepo()\n\t// itemsRepo := items.NewMysqlRepository(getMysql())\n\t// itemsRepo := items.NewSqlxRepository(getSqlx())\n\titemsRepo := items.NewGormRepository(getGorm())\n\t// itemsRepo := items.NewPgxRepository(getPostgres())\n\n\tuserHandler := &handlers.UserHandler{\n\t\tTmpl:     templates,\n\t\tUserRepo: userRepo,\n\t\tLogger:   logger,\n\t\tSessions: sm,\n\t}\n\n\thandlers := &handlers.ItemsHandler{\n\t\tTmpl:      templates,\n\t\tLogger:    logger,\n\t\tItemsRepo: itemsRepo,\n\t}\n\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/\", userHandler.Index).Methods(\"GET\")\n\tr.HandleFunc(\"/login\", userHandler.Login).Methods(\"POST\")\n\tr.HandleFunc(\"/logout\", userHandler.Logout).Methods(\"POST\")\n\n\tr.HandleFunc(\"/items\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.AddForm).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.Add).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Edit).Methods(\"GET\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Update).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Delete).Methods(\"DELETE\")\n\n\tmux := middleware.Auth(sm, r)\n\tmux = middleware.AccessLog(logger, mux)\n\tmux = middleware.Panic(mux)\n\n\taddr := \":8080\"\n\tlogger.Infow(\"starting server\",\n\t\t\"type\", \"START\",\n\t\t\"addr\", addr,\n\t)\n\thttp.ListenAndServe(addr, mux)\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/handlers/handler.html",
    "content": "\n<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n\t\t<title>handlers: Go Coverage Report</title>\n\t\t<style>\n\t\t\tbody {\n\t\t\t\tbackground: black;\n\t\t\t\tcolor: rgb(80, 80, 80);\n\t\t\t}\n\t\t\tbody, pre, #legend span {\n\t\t\t\tfont-family: Menlo, monospace;\n\t\t\t\tfont-weight: bold;\n\t\t\t}\n\t\t\t#topbar {\n\t\t\t\tbackground: black;\n\t\t\t\tposition: fixed;\n\t\t\t\ttop: 0; left: 0; right: 0;\n\t\t\t\theight: 42px;\n\t\t\t\tborder-bottom: 1px solid rgb(80, 80, 80);\n\t\t\t}\n\t\t\t#content {\n\t\t\t\tmargin-top: 50px;\n\t\t\t}\n\t\t\t#nav, #legend {\n\t\t\t\tfloat: left;\n\t\t\t\tmargin-left: 10px;\n\t\t\t}\n\t\t\t#legend {\n\t\t\t\tmargin-top: 12px;\n\t\t\t}\n\t\t\t#nav {\n\t\t\t\tmargin-top: 10px;\n\t\t\t}\n\t\t\t#legend span {\n\t\t\t\tmargin: 0 5px;\n\t\t\t}\n\t\t\t.cov0 { color: rgb(192, 0, 0) }\n.cov1 { color: rgb(128, 128, 128) }\n.cov2 { color: rgb(116, 140, 131) }\n.cov3 { color: rgb(104, 152, 134) }\n.cov4 { color: rgb(92, 164, 137) }\n.cov5 { color: rgb(80, 176, 140) }\n.cov6 { color: rgb(68, 188, 143) }\n.cov7 { color: rgb(56, 200, 146) }\n.cov8 { color: rgb(44, 212, 149) }\n.cov9 { color: rgb(32, 224, 152) }\n.cov10 { color: rgb(20, 236, 155) }\n\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<div id=\"topbar\">\n\t\t\t<div id=\"nav\">\n\t\t\t\t<select id=\"files\">\n\t\t\t\t\n\t\t\t\t<option value=\"file0\">github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/handlers/items.go (11.5%)</option>\n\t\t\t\t\n\t\t\t\t<option value=\"file1\">github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/handlers/items_mock.go (28.2%)</option>\n\t\t\t\t\n\t\t\t\t<option value=\"file2\">github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/handlers/user.go (0.0%)</option>\n\t\t\t\t\n\t\t\t\t</select>\n\t\t\t</div>\n\t\t\t<div id=\"legend\">\n\t\t\t\t<span>not tracked</span>\n\t\t\t\n\t\t\t\t<span class=\"cov0\">not covered</span>\n\t\t\t\t<span class=\"cov8\">covered</span>\n\t\t\t\n\t\t\t</div>\n\t\t</div>\n\t\t<div id=\"content\">\n\t\t\n\t\t<pre class=\"file\" id=\"file0\" style=\"display: none\">package handlers\n\nimport (\n        \"encoding/json\"\n        \"html/template\"\n        \"net/http\"\n        \"strconv\"\n\n        \"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/items\"\n        \"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/session\"\n\n        \"github.com/gorilla/mux\"\n        \"github.com/gorilla/schema\"\n        \"go.uber.org/zap\"\n)\n\n//go:generate mockgen -source=items.go -destination=items_mock.go -package=handlers ItemRepositoryInterface\ntype ItemRepositoryInterface interface {\n        GetAll() ([]*items.Item, error)\n        GetByID(int64) (*items.Item, error)\n        Add(*items.Item) (int64, error)\n        Update(*items.Item) (int64, error)\n        Delete(int64) (int64, error)\n}\n\ntype ItemsHandler struct {\n        Tmpl      *template.Template\n        ItemsRepo ItemRepositoryInterface\n        Logger    *zap.SugaredLogger\n}\n\nfunc (h *ItemsHandler) List(w http.ResponseWriter, r *http.Request) <span class=\"cov8\" title=\"1\">{\n        elems, err := h.ItemsRepo.GetAll()\n        if err != nil </span><span class=\"cov8\" title=\"1\">{\n                h.Logger.Error(\"GetAll err\", err)\n                http.Error(w, `DB err`, http.StatusInternalServerError)\n                return\n        }</span>\n\n        <span class=\"cov8\" title=\"1\">err = h.Tmpl.ExecuteTemplate(w, \"index.html\", struct {\n                Items []*items.Item\n        }{\n                Items: elems,\n        })\n        if err != nil </span><span class=\"cov8\" title=\"1\">{\n                h.Logger.Error(\"ExecuteTemplate err\", err)\n                http.Error(w, `Template errror`, http.StatusInternalServerError)\n                return\n        }</span>\n}\n\nfunc (h *ItemsHandler) AddForm(w http.ResponseWriter, r *http.Request) <span class=\"cov0\" title=\"0\">{\n        err := h.Tmpl.ExecuteTemplate(w, \"create.html\", nil)\n        if err != nil </span><span class=\"cov0\" title=\"0\">{\n                h.Logger.Error(\"ExecuteTemplate err\", err)\n                http.Error(w, `Template errror`, http.StatusInternalServerError)\n                return\n        }</span>\n}\n\n// type ItemsAddInput struct {\n\n// }\n\nfunc (h *ItemsHandler) Add(w http.ResponseWriter, r *http.Request) <span class=\"cov0\" title=\"0\">{\n        r.ParseForm()\n        item := new(items.Item)\n        decoder := schema.NewDecoder()\n        decoder.IgnoreUnknownKeys(true)\n        err := decoder.Decode(item, r.PostForm)\n        if err != nil </span><span class=\"cov0\" title=\"0\">{\n                h.Logger.Error(\"Form err\", err)\n                http.Error(w, `Bad form`, http.StatusBadRequest)\n                return\n        }</span>\n\n        <span class=\"cov0\" title=\"0\">sess, _ := session.SessionFromContext(r.Context())\n        // item.UserID = sess.UserID\n\n        lastID, err := h.ItemsRepo.Add(item)\n        if err != nil </span><span class=\"cov0\" title=\"0\">{\n                h.Logger.Error(\"Db err\", err)\n                http.Error(w, `DB err`, http.StatusInternalServerError)\n                return\n        }</span>\n        <span class=\"cov0\" title=\"0\">h.Logger.Infof(\"Insert with id LastInsertId: %v %v\", lastID, sess)\n        http.Redirect(w, r, \"/\", http.StatusFound)</span>\n}\n\nfunc (h *ItemsHandler) Edit(w http.ResponseWriter, r *http.Request) <span class=\"cov0\" title=\"0\">{\n        vars := mux.Vars(r)\n        id, err := strconv.Atoi(vars[\"id\"])\n        if err != nil </span><span class=\"cov0\" title=\"0\">{\n                http.Error(w, `{\"error\": \"bad id\"}`, http.StatusBadGateway)\n                return\n        }</span>\n\n        <span class=\"cov0\" title=\"0\">item, err := h.ItemsRepo.GetByID(int64(id))\n        if err != nil </span><span class=\"cov0\" title=\"0\">{\n                h.Logger.Error(\"Db err\", err)\n                http.Error(w, `DB err`, http.StatusInternalServerError)\n                return\n        }</span>\n        <span class=\"cov0\" title=\"0\">if item == nil </span><span class=\"cov0\" title=\"0\">{\n                http.Error(w, `no item`, http.StatusNotFound)\n                return\n        }</span>\n\n        <span class=\"cov0\" title=\"0\">err = h.Tmpl.ExecuteTemplate(w, \"edit.html\", item)\n        if err != nil </span><span class=\"cov0\" title=\"0\">{\n                h.Logger.Error(\"ExecuteTemplate err\", err)\n                http.Error(w, `Template errror`, http.StatusInternalServerError)\n                return\n        }</span>\n}\n\nfunc (h *ItemsHandler) Update(w http.ResponseWriter, r *http.Request) <span class=\"cov0\" title=\"0\">{\n        vars := mux.Vars(r)\n        id, err := strconv.Atoi(vars[\"id\"])\n        if err != nil </span><span class=\"cov0\" title=\"0\">{\n                http.Error(w, `Bad id`, http.StatusBadRequest)\n                return\n        }</span>\n\n        <span class=\"cov0\" title=\"0\">r.ParseForm()\n        item := new(items.Item)\n        decoder := schema.NewDecoder()\n        decoder.IgnoreUnknownKeys(true)\n        err = decoder.Decode(item, r.PostForm)\n        if err != nil </span><span class=\"cov0\" title=\"0\">{\n                h.Logger.Error(\"Form err\", err)\n                http.Error(w, `Bad form`, http.StatusBadRequest)\n                return\n        }</span>\n        <span class=\"cov0\" title=\"0\">item.ID = uint32(id)\n\n        sess, _ := session.SessionFromContext(r.Context())\n        item.SetUpdated(sess.UserID)\n\n        ok, err := h.ItemsRepo.Update(item)\n        if err != nil </span><span class=\"cov0\" title=\"0\">{\n                h.Logger.Error(\"Db err\", err)\n                http.Error(w, `db error`, http.StatusInternalServerError)\n                return\n        }</span>\n\n        <span class=\"cov0\" title=\"0\">h.Logger.Infof(\"update: %v %v\", item, ok)\n\n        http.Redirect(w, r, \"/\", http.StatusFound)</span>\n}\n\nfunc (h *ItemsHandler) Delete(w http.ResponseWriter, r *http.Request) <span class=\"cov0\" title=\"0\">{\n        vars := mux.Vars(r)\n        id, err := strconv.Atoi(vars[\"id\"])\n        if err != nil </span><span class=\"cov0\" title=\"0\">{\n                http.Error(w, `{\"error\": \"bad id\"}`, http.StatusBadGateway)\n                return\n        }</span>\n\n        <span class=\"cov0\" title=\"0\">affected, err := h.ItemsRepo.Delete(int64(id))\n        if err != nil </span><span class=\"cov0\" title=\"0\">{\n                h.Logger.Error(\"Db err\", err)\n                http.Error(w, `{\"error\": \"db error\"}`, http.StatusInternalServerError)\n                return\n        }</span>\n\n        <span class=\"cov0\" title=\"0\">w.Header().Set(\"Content-type\", \"application/json\")\n        respJSON, _ := json.Marshal(map[string]int64{\n                \"updated\": affected,\n        })\n        w.Write(respJSON)</span>\n}\n</pre>\n\t\t\n\t\t<pre class=\"file\" id=\"file1\" style=\"display: none\">// Code generated by MockGen. DO NOT EDIT.\n// Source: items.go\n//\n// Generated by this command:\n//\n//        mockgen -source=items.go -destination=items_mock.go -package=handlers ItemRepositoryInterface\n//\n\n// Package handlers is a generated GoMock package.\npackage handlers\n\nimport (\n        reflect \"reflect\"\n\n        items \"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/items\"\n        gomock \"go.uber.org/mock/gomock\"\n)\n\n// MockItemRepositoryInterface is a mock of ItemRepositoryInterface interface.\ntype MockItemRepositoryInterface struct {\n        ctrl     *gomock.Controller\n        recorder *MockItemRepositoryInterfaceMockRecorder\n        isgomock struct{}\n}\n\n// MockItemRepositoryInterfaceMockRecorder is the mock recorder for MockItemRepositoryInterface.\ntype MockItemRepositoryInterfaceMockRecorder struct {\n        mock *MockItemRepositoryInterface\n}\n\n// NewMockItemRepositoryInterface creates a new mock instance.\nfunc NewMockItemRepositoryInterface(ctrl *gomock.Controller) *MockItemRepositoryInterface <span class=\"cov8\" title=\"1\">{\n        mock := &amp;MockItemRepositoryInterface{ctrl: ctrl}\n        mock.recorder = &amp;MockItemRepositoryInterfaceMockRecorder{mock}\n        return mock\n}</span>\n\n// EXPECT returns an object that allows the caller to indicate expected use.\nfunc (m *MockItemRepositoryInterface) EXPECT() *MockItemRepositoryInterfaceMockRecorder <span class=\"cov8\" title=\"1\">{\n        return m.recorder\n}</span>\n\n// Add mocks base method.\nfunc (m *MockItemRepositoryInterface) Add(arg0 *items.Item) (int64, error) <span class=\"cov0\" title=\"0\">{\n        m.ctrl.T.Helper()\n        ret := m.ctrl.Call(m, \"Add\", arg0)\n        ret0, _ := ret[0].(int64)\n        ret1, _ := ret[1].(error)\n        return ret0, ret1\n}</span>\n\n// Add indicates an expected call of Add.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) Add(arg0 any) *gomock.Call <span class=\"cov0\" title=\"0\">{\n        mr.mock.ctrl.T.Helper()\n        return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"Add\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).Add), arg0)\n}</span>\n\n// Delete mocks base method.\nfunc (m *MockItemRepositoryInterface) Delete(arg0 int64) (int64, error) <span class=\"cov0\" title=\"0\">{\n        m.ctrl.T.Helper()\n        ret := m.ctrl.Call(m, \"Delete\", arg0)\n        ret0, _ := ret[0].(int64)\n        ret1, _ := ret[1].(error)\n        return ret0, ret1\n}</span>\n\n// Delete indicates an expected call of Delete.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) Delete(arg0 any) *gomock.Call <span class=\"cov0\" title=\"0\">{\n        mr.mock.ctrl.T.Helper()\n        return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"Delete\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).Delete), arg0)\n}</span>\n\n// GetAll mocks base method.\nfunc (m *MockItemRepositoryInterface) GetAll() ([]*items.Item, error) <span class=\"cov8\" title=\"1\">{\n        m.ctrl.T.Helper()\n        ret := m.ctrl.Call(m, \"GetAll\")\n        ret0, _ := ret[0].([]*items.Item)\n        ret1, _ := ret[1].(error)\n        return ret0, ret1\n}</span>\n\n// GetAll indicates an expected call of GetAll.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) GetAll() *gomock.Call <span class=\"cov8\" title=\"1\">{\n        mr.mock.ctrl.T.Helper()\n        return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"GetAll\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).GetAll))\n}</span>\n\n// GetByID mocks base method.\nfunc (m *MockItemRepositoryInterface) GetByID(arg0 int64) (*items.Item, error) <span class=\"cov0\" title=\"0\">{\n        m.ctrl.T.Helper()\n        ret := m.ctrl.Call(m, \"GetByID\", arg0)\n        ret0, _ := ret[0].(*items.Item)\n        ret1, _ := ret[1].(error)\n        return ret0, ret1\n}</span>\n\n// GetByID indicates an expected call of GetByID.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) GetByID(arg0 any) *gomock.Call <span class=\"cov0\" title=\"0\">{\n        mr.mock.ctrl.T.Helper()\n        return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"GetByID\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).GetByID), arg0)\n}</span>\n\n// Update mocks base method.\nfunc (m *MockItemRepositoryInterface) Update(arg0 *items.Item) (int64, error) <span class=\"cov0\" title=\"0\">{\n        m.ctrl.T.Helper()\n        ret := m.ctrl.Call(m, \"Update\", arg0)\n        ret0, _ := ret[0].(int64)\n        ret1, _ := ret[1].(error)\n        return ret0, ret1\n}</span>\n\n// Update indicates an expected call of Update.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) Update(arg0 any) *gomock.Call <span class=\"cov0\" title=\"0\">{\n        mr.mock.ctrl.T.Helper()\n        return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"Update\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).Update), arg0)\n}</span>\n</pre>\n\t\t\n\t\t<pre class=\"file\" id=\"file2\" style=\"display: none\">package handlers\n\nimport (\n        \"html/template\"\n        \"net/http\"\n\n        \"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/session\"\n        \"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/user\"\n\n        \"go.uber.org/zap\"\n)\n\ntype UserHandler struct {\n        Tmpl     *template.Template\n        Logger   *zap.SugaredLogger\n        UserRepo *user.UserRepo\n        Sessions *session.SessionsManager\n}\n\nfunc (h *UserHandler) Index(w http.ResponseWriter, r *http.Request) <span class=\"cov0\" title=\"0\">{\n        _, err := session.SessionFromContext(r.Context())\n        if err == nil </span><span class=\"cov0\" title=\"0\">{\n                http.Redirect(w, r, \"/items\", 302)\n                return\n        }</span>\n\n        <span class=\"cov0\" title=\"0\">err = h.Tmpl.ExecuteTemplate(w, \"login.html\", nil)\n        if err != nil </span><span class=\"cov0\" title=\"0\">{\n                http.Error(w, `Template errror`, http.StatusInternalServerError)\n                return\n        }</span>\n}\n\nfunc (h *UserHandler) Login(w http.ResponseWriter, r *http.Request) <span class=\"cov0\" title=\"0\">{\n        u, err := h.UserRepo.Authorize(r.FormValue(\"login\"), r.FormValue(\"password\"))\n        if err == user.ErrNoUser </span><span class=\"cov0\" title=\"0\">{\n                http.Error(w, `no user`, http.StatusBadRequest)\n                return\n        }</span>\n        <span class=\"cov0\" title=\"0\">if err == user.ErrBadPass </span><span class=\"cov0\" title=\"0\">{\n                http.Error(w, `bad pass`, http.StatusBadRequest)\n                return\n        }</span>\n\n        <span class=\"cov0\" title=\"0\">sess, _ := h.Sessions.Create(w, u.ID)\n        h.Logger.Infof(\"created session for %v\", sess.UserID)\n        http.Redirect(w, r, \"/\", 302)</span>\n}\n\nfunc (h *UserHandler) Logout(w http.ResponseWriter, r *http.Request) <span class=\"cov0\" title=\"0\">{\n        h.Sessions.DestroyCurrent(w, r)\n        http.Redirect(w, r, \"/\", 302)\n}</span>\n</pre>\n\t\t\n\t\t</div>\n\t</body>\n\t<script>\n\t(function() {\n\t\tvar files = document.getElementById('files');\n\t\tvar visible;\n\t\tfiles.addEventListener('change', onChange, false);\n\t\tfunction select(part) {\n\t\t\tif (visible)\n\t\t\t\tvisible.style.display = 'none';\n\t\t\tvisible = document.getElementById(part);\n\t\t\tif (!visible)\n\t\t\t\treturn;\n\t\t\tfiles.value = part;\n\t\t\tvisible.style.display = 'block';\n\t\t\tlocation.hash = part;\n\t\t}\n\t\tfunction onChange() {\n\t\t\tselect(files.value);\n\t\t\twindow.scrollTo(0, 0);\n\t\t}\n\t\tif (location.hash != \"\") {\n\t\t\tselect(location.hash.substr(1));\n\t\t}\n\t\tif (!visible) {\n\t\t\tselect(\"file0\");\n\t\t}\n\t})();\n\t</script>\n</html>\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/handlers/items.go",
    "content": "package handlers\n\nimport (\n\t\"encoding/json\"\n\t\"html/template\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/items\"\n\t\"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/session\"\n\n\t\"github.com/gorilla/mux\"\n\t\"github.com/gorilla/schema\"\n\t\"go.uber.org/zap\"\n)\n\n//go:generate mockgen -source=items.go -destination=items_mock.go -package=handlers ItemRepositoryInterface\ntype ItemRepositoryInterface interface {\n\tGetAll() ([]*items.Item, error)\n\tGetByID(int64) (*items.Item, error)\n\tAdd(*items.Item) (int64, error)\n\tUpdate(*items.Item) (int64, error)\n\tDelete(int64) (int64, error)\n}\n\ntype ItemsHandler struct {\n\tTmpl      *template.Template\n\tItemsRepo ItemRepositoryInterface\n\tLogger    *zap.SugaredLogger\n}\n\nfunc (h *ItemsHandler) List(w http.ResponseWriter, r *http.Request) {\n\telems, err := h.ItemsRepo.GetAll()\n\tif err != nil {\n\t\th.Logger.Error(\"GetAll err\", err)\n\t\thttp.Error(w, `DB err`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"index.html\", struct {\n\t\tItems []*items.Item\n\t}{\n\t\tItems: elems,\n\t})\n\tif err != nil {\n\t\th.Logger.Error(\"ExecuteTemplate err\", err)\n\t\thttp.Error(w, `Template errror`, http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *ItemsHandler) AddForm(w http.ResponseWriter, r *http.Request) {\n\terr := h.Tmpl.ExecuteTemplate(w, \"create.html\", nil)\n\tif err != nil {\n\t\th.Logger.Error(\"ExecuteTemplate err\", err)\n\t\thttp.Error(w, `Template errror`, http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\n// type ItemsAddInput struct {\n\n// }\n\nfunc (h *ItemsHandler) Add(w http.ResponseWriter, r *http.Request) {\n\tr.ParseForm()\n\titem := new(items.Item)\n\tdecoder := schema.NewDecoder()\n\tdecoder.IgnoreUnknownKeys(true)\n\terr := decoder.Decode(item, r.PostForm)\n\tif err != nil {\n\t\th.Logger.Error(\"Form err\", err)\n\t\thttp.Error(w, `Bad form`, http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tsess, _ := session.SessionFromContext(r.Context())\n\t// item.UserID = sess.UserID\n\n\tlastID, err := h.ItemsRepo.Add(item)\n\tif err != nil {\n\t\th.Logger.Error(\"Db err\", err)\n\t\thttp.Error(w, `DB err`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\th.Logger.Infof(\"Insert with id LastInsertId: %v %v\", lastID, sess)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *ItemsHandler) Edit(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tif err != nil {\n\t\thttp.Error(w, `{\"error\": \"bad id\"}`, http.StatusBadGateway)\n\t\treturn\n\t}\n\n\titem, err := h.ItemsRepo.GetByID(int64(id))\n\tif err != nil {\n\t\th.Logger.Error(\"Db err\", err)\n\t\thttp.Error(w, `DB err`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif item == nil {\n\t\thttp.Error(w, `no item`, http.StatusNotFound)\n\t\treturn\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"edit.html\", item)\n\tif err != nil {\n\t\th.Logger.Error(\"ExecuteTemplate err\", err)\n\t\thttp.Error(w, `Template errror`, http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *ItemsHandler) Update(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tif err != nil {\n\t\thttp.Error(w, `Bad id`, http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tr.ParseForm()\n\titem := new(items.Item)\n\tdecoder := schema.NewDecoder()\n\tdecoder.IgnoreUnknownKeys(true)\n\terr = decoder.Decode(item, r.PostForm)\n\tif err != nil {\n\t\th.Logger.Error(\"Form err\", err)\n\t\thttp.Error(w, `Bad form`, http.StatusBadRequest)\n\t\treturn\n\t}\n\titem.ID = uint32(id)\n\n\tsess, _ := session.SessionFromContext(r.Context())\n\titem.SetUpdated(sess.UserID)\n\n\tok, err := h.ItemsRepo.Update(item)\n\tif err != nil {\n\t\th.Logger.Error(\"Db err\", err)\n\t\thttp.Error(w, `db error`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\th.Logger.Infof(\"update: %v %v\", item, ok)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *ItemsHandler) Delete(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := strconv.Atoi(vars[\"id\"])\n\tif err != nil {\n\t\thttp.Error(w, `{\"error\": \"bad id\"}`, http.StatusBadGateway)\n\t\treturn\n\t}\n\n\taffected, err := h.ItemsRepo.Delete(int64(id))\n\tif err != nil {\n\t\th.Logger.Error(\"Db err\", err)\n\t\thttp.Error(w, `{\"error\": \"db error\"}`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-type\", \"application/json\")\n\trespJSON, _ := json.Marshal(map[string]int64{\n\t\t\"updated\": affected,\n\t})\n\tw.Write(respJSON)\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/handlers/items_mock.go",
    "content": "// Code generated by MockGen. DO NOT EDIT.\n// Source: items.go\n//\n// Generated by this command:\n//\n//\tmockgen -source=items.go -destination=items_mock.go -package=handlers ItemRepositoryInterface\n//\n\n// Package handlers is a generated GoMock package.\npackage handlers\n\nimport (\n\treflect \"reflect\"\n\n\titems \"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/items\"\n\tgomock \"go.uber.org/mock/gomock\"\n)\n\n// MockItemRepositoryInterface is a mock of ItemRepositoryInterface interface.\ntype MockItemRepositoryInterface struct {\n\tctrl     *gomock.Controller\n\trecorder *MockItemRepositoryInterfaceMockRecorder\n\tisgomock struct{}\n}\n\n// MockItemRepositoryInterfaceMockRecorder is the mock recorder for MockItemRepositoryInterface.\ntype MockItemRepositoryInterfaceMockRecorder struct {\n\tmock *MockItemRepositoryInterface\n}\n\n// NewMockItemRepositoryInterface creates a new mock instance.\nfunc NewMockItemRepositoryInterface(ctrl *gomock.Controller) *MockItemRepositoryInterface {\n\tmock := &MockItemRepositoryInterface{ctrl: ctrl}\n\tmock.recorder = &MockItemRepositoryInterfaceMockRecorder{mock}\n\treturn mock\n}\n\n// EXPECT returns an object that allows the caller to indicate expected use.\nfunc (m *MockItemRepositoryInterface) EXPECT() *MockItemRepositoryInterfaceMockRecorder {\n\treturn m.recorder\n}\n\n// Add mocks base method.\nfunc (m *MockItemRepositoryInterface) Add(arg0 *items.Item) (int64, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"Add\", arg0)\n\tret0, _ := ret[0].(int64)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// Add indicates an expected call of Add.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) Add(arg0 any) *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"Add\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).Add), arg0)\n}\n\n// Delete mocks base method.\nfunc (m *MockItemRepositoryInterface) Delete(arg0 int64) (int64, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"Delete\", arg0)\n\tret0, _ := ret[0].(int64)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// Delete indicates an expected call of Delete.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) Delete(arg0 any) *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"Delete\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).Delete), arg0)\n}\n\n// GetAll mocks base method.\nfunc (m *MockItemRepositoryInterface) GetAll() ([]*items.Item, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"GetAll\")\n\tret0, _ := ret[0].([]*items.Item)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// GetAll indicates an expected call of GetAll.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) GetAll() *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"GetAll\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).GetAll))\n}\n\n// GetByID mocks base method.\nfunc (m *MockItemRepositoryInterface) GetByID(arg0 int64) (*items.Item, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"GetByID\", arg0)\n\tret0, _ := ret[0].(*items.Item)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// GetByID indicates an expected call of GetByID.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) GetByID(arg0 any) *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"GetByID\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).GetByID), arg0)\n}\n\n// Update mocks base method.\nfunc (m *MockItemRepositoryInterface) Update(arg0 *items.Item) (int64, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"Update\", arg0)\n\tret0, _ := ret[0].(int64)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// Update indicates an expected call of Update.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) Update(arg0 any) *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"Update\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).Update), arg0)\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/handlers/items_test.go",
    "content": "package handlers\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"io/ioutil\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\n\t\"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/items\"\n\n\t\"go.uber.org/mock/gomock\"\n\t\"go.uber.org/zap\"\n)\n\n/*\n\nrepo\n\tdb -> mock\n\nhandler\n\trepo -> mock\n\n\n*/\n\nfunc TestItemsHandlerList(t *testing.T) {\n\n\t// мы передаём t сюда, это надо чтобы получить корректное сообщение если тесты не пройдут\n\tctrl := gomock.NewController(t)\n\n\t// Finish сравнит последовательсноть вызовов и выведет ошибку если последовательность другая\n\tdefer ctrl.Finish()\n\n\tst := NewMockItemRepositoryInterface(ctrl)\n\tservice := &ItemsHandler{\n\t\tItemsRepo: st,\n\t\tLogger:    zap.NewNop().Sugar(), // не пишет логи\n\t\tTmpl:      template.Must(template.ParseGlob(\"../../templates/*\")),\n\t}\n\n\tresultItems := []*items.Item{\n\t\t{ID: 1, Title: \"database/sql\"},\n\t}\n\n\t// тут мы записываем последовтаельность вызовов и результат\n\tst.EXPECT().GetAll().Return(resultItems, nil)\n\n\treq := httptest.NewRequest(\"GET\", \"/\", nil)\n\tw := httptest.NewRecorder()\n\n\tservice.List(w, req)\n\n\tresp := w.Result()\n\tbody, _ := ioutil.ReadAll(resp.Body)\n\n\timg := `database/sql`\n\tif !bytes.Contains(body, []byte(img)) {\n\t\tt.Errorf(\"no text found\")\n\t\treturn\n\t}\n\n\t// GetPhotos error\n\t// тут мы записываем последовтаельность вызовов и результат\n\tst.EXPECT().GetAll().Return(nil, fmt.Errorf(\"no results\"))\n\n\treq = httptest.NewRequest(\"GET\", \"/\", nil)\n\tw = httptest.NewRecorder()\n\n\tservice.List(w, req)\n\n\tresp = w.Result()\n\tif resp.StatusCode != 500 {\n\t\tt.Errorf(\"expected resp status 500, got %d\", resp.StatusCode)\n\t\treturn\n\t}\n\n\t// template expand error\n\tservice.Tmpl, _ = template.New(\"tmplError\").Parse(\"{{.NotExist}}\")\n\n\tst.EXPECT().GetAll().Return(resultItems, nil)\n\n\treq = httptest.NewRequest(\"GET\", \"/\", nil)\n\tw = httptest.NewRecorder()\n\n\tservice.List(w, req)\n\n\tresp = w.Result()\n\tif resp.StatusCode != 500 {\n\t\tt.Errorf(\"expected resp status 500, got %d\", resp.StatusCode)\n\t\treturn\n\t}\n\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/handlers/user.go",
    "content": "package handlers\n\nimport (\n\t\"html/template\"\n\t\"net/http\"\n\n\t\"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/session\"\n\t\"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/user\"\n\n\t\"go.uber.org/zap\"\n)\n\ntype UserHandler struct {\n\tTmpl     *template.Template\n\tLogger   *zap.SugaredLogger\n\tUserRepo *user.UserRepo\n\tSessions *session.SessionsManager\n}\n\nfunc (h *UserHandler) Index(w http.ResponseWriter, r *http.Request) {\n\t_, err := session.SessionFromContext(r.Context())\n\tif err == nil {\n\t\thttp.Redirect(w, r, \"/items\", 302)\n\t\treturn\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"login.html\", nil)\n\tif err != nil {\n\t\thttp.Error(w, `Template errror`, http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *UserHandler) Login(w http.ResponseWriter, r *http.Request) {\n\tu, err := h.UserRepo.Authorize(r.FormValue(\"login\"), r.FormValue(\"password\"))\n\tif err == user.ErrNoUser {\n\t\thttp.Error(w, `no user`, http.StatusBadRequest)\n\t\treturn\n\t}\n\tif err == user.ErrBadPass {\n\t\thttp.Error(w, `bad pass`, http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tsess, _ := h.Sessions.Create(w, u.ID)\n\th.Logger.Infof(\"created session for %v\", sess.UserID)\n\thttp.Redirect(w, r, \"/\", 302)\n}\n\nfunc (h *UserHandler) Logout(w http.ResponseWriter, r *http.Request) {\n\th.Sessions.DestroyCurrent(w, r)\n\thttp.Redirect(w, r, \"/\", 302)\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/items/item.go",
    "content": "package items\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"gorm.io/gorm\"\n)\n\ntype ItemZero struct {\n\tID          uint32\n\tTitle       string\n\tDescription string\n\tUpdated     sql.NullString\n}\n\ntype Item struct {\n\tID          uint32 `sql:\"AUTO_INCREMENT\" gorm:\"primary_key\"`\n\tTitle       string\n\tDescription string\n\tUpdated     sql.NullString `sql:\"null\"`\n}\n\n// позволяет items handlers не импортировать sql\nfunc (it *Item) SetUpdated(val uint32) {\n\tit.Updated = sql.NullString{String: strconv.Itoa(int(val))}\n}\n\n/*\nhttps://gorm.io/docs/models.html\n*/\n\nfunc (i *Item) TableName() string {\n\treturn \"items\"\n}\n\nfunc (i *Item) BeforeSave(*gorm.DB) (err error) {\n\tfmt.Println(\"trigger on before save\")\n\treturn\n}\n\ntype Item0 struct {\n\tgorm.Model\n\tID          uint32 `sql:\"AUTO_INCREMENT\" gorm:\"primary_key\"`\n\tTitle       string\n\tDescription string\n\tUpdated     string `sql:\"null\"`\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/items/item_repo_test.go",
    "content": "package items\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"testing\"\n\n\tsqlmock \"github.com/DATA-DOG/go-sqlmock\"\n)\n\n// go test -coverprofile=cover.out && go tool cover -html=cover.out -o cover.html\n\n/*\nhandlers\n\trepo -> mock\n\nrepo\n\tdb -> mock\n\n*/\n\nfunc TestGetByID(t *testing.T) {\n\tdb, mock, err := sqlmock.New()\n\tif err != nil {\n\t\tt.Fatalf(\"cant create mock: %s\", err)\n\t}\n\tdefer db.Close()\n\n\trepo := &RepoMysql{\n\t\tDB: db,\n\t}\n\n\tvar elemID int64 = 1\n\n\t// good query\n\trows := sqlmock.\n\t\tNewRows([]string{\"id\", \"title\", \"updated\", \"description\"})\n\texpect := []*Item{\n\t\t{uint32(elemID), \"title\", \"desct\", sql.NullString{}},\n\t}\n\tfor _, item := range expect {\n\t\trows = rows.AddRow(item.ID, item.Title, nil, item.Description)\n\t}\n\n\tmock.\n\t\tExpectQuery(\"SELECT id, title, updated, description\").\n\t\tWithArgs(elemID).\n\t\tWillReturnRows(rows)\n\n\titem, err := repo.GetByID(elemID)\n\tif err != nil {\n\t\tt.Errorf(\"unexpected err: %s\", err)\n\t\treturn\n\t}\n\tif err := mock.ExpectationsWereMet(); err != nil {\n\t\tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t\treturn\n\t}\n\tif !reflect.DeepEqual(item, expect[0]) {\n\t\tt.Errorf(\"results not match, want %v, have %v\", expect[0], item)\n\t\treturn\n\t}\n\n\t// query error\n\tmock.\n\t\tExpectQuery(\"SELECT id, title, updated, description FROM items WHERE\").\n\t\tWithArgs(elemID).\n\t\tWillReturnError(fmt.Errorf(\"db_error\"))\n\n\t_, err = repo.GetByID(elemID)\n\tif err := mock.ExpectationsWereMet(); err != nil {\n\t\tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t\treturn\n\t}\n\tif err == nil {\n\t\tt.Errorf(\"expected error, got nil\")\n\t\treturn\n\t}\n\n\t// row scan error\n\trows = sqlmock.NewRows([]string{\"id\", \"title\"}).\n\t\tAddRow(1, \"title\")\n\n\tmock.\n\t\tExpectQuery(\"SELECT id, title, updated, description FROM items WHERE\").\n\t\tWithArgs(elemID).\n\t\tWillReturnRows(rows)\n\n\t_, err = repo.GetByID(elemID)\n\tif err := mock.ExpectationsWereMet(); err != nil {\n\t\tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t\treturn\n\t}\n\tif err == nil {\n\t\tt.Errorf(\"expected error, got nil\")\n\t\treturn\n\t}\n\n}\n\nfunc TestCreate(t *testing.T) {\n\tdb, mock, err := sqlmock.New()\n\tif err != nil {\n\t\tt.Fatalf(\"cant create mock: %s\", err)\n\t}\n\tdefer db.Close()\n\n\trepo := &RepoMysql{\n\t\tDB: db,\n\t}\n\n\ttitle := \"title\"\n\tdescr := \"description\"\n\ttestItem := &Item{\n\t\tTitle:       title,\n\t\tDescription: descr,\n\t}\n\n\t//ok query\n\tmock.\n\t\tExpectExec(`INSERT INTO items`).\n\t\tWithArgs(title, descr).\n\t\tWillReturnResult(sqlmock.NewResult(1, 1))\n\n\tid, err := repo.Add(testItem)\n\tif err != nil {\n\t\tt.Errorf(\"unexpected err: %s\", err)\n\t\treturn\n\t}\n\tif id != 1 {\n\t\tt.Errorf(\"bad id: want %v, have %v\", id, 1)\n\t\treturn\n\t}\n\n\tif err := mock.ExpectationsWereMet(); err != nil {\n\t\tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t}\n\n\t// query error\n\tmock.\n\t\tExpectExec(`INSERT INTO items`).\n\t\tWithArgs(title, descr).\n\t\tWillReturnError(fmt.Errorf(\"bad query\"))\n\n\t// mock.ExpectClose()\n\n\t_, err = repo.Add(testItem)\n\tif err == nil {\n\t\tt.Errorf(\"expected error, got nil\")\n\t\treturn\n\t}\n\tif err := mock.ExpectationsWereMet(); err != nil {\n\t\tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t}\n\n\t// result error\n\tmock.\n\t\tExpectExec(`INSERT INTO items`).\n\t\tWithArgs(title, descr).\n\t\tWillReturnResult(sqlmock.NewErrorResult(fmt.Errorf(\"bad_result\")))\n\n\t_, err = repo.Add(testItem)\n\tif err == nil {\n\t\tt.Errorf(\"expected error, got nil\")\n\t\treturn\n\t}\n\tif err := mock.ExpectationsWereMet(); err != nil {\n\t\tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t}\n\n\t// // last id error\n\t// mock.\n\t// \tExpectExec(`INSERT INTO items`).\n\t// \tWithArgs(title, descr).\n\t// \tWillReturnResult(sqlmock.NewResult(0, 0))\n\n\t// _, err = repo.Add(testItem)\n\t// if err == nil {\n\t// \tt.Errorf(\"expected error, got nil\")\n\t// \treturn\n\t// }\n\t// if err := mock.ExpectationsWereMet(); err != nil {\n\t// \tt.Errorf(\"there were unfulfilled expectations: %s\", err)\n\t// }\n\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/items/repo_gorm.go",
    "content": "package items\n\nimport (\n\t\"log\"\n\n\t\"gorm.io/gorm\"\n)\n\ntype RepoGorm struct {\n\tDB *gorm.DB\n}\n\nfunc NewGormRepository(db *gorm.DB) *RepoGorm {\n\treturn &RepoGorm{DB: db}\n}\n\nfunc (repo *RepoGorm) GetAll() ([]*Item, error) {\n\t// https://gorm.io/docs/query.html\n\titems := make([]*Item, 0, 10)\n\terr := repo.DB.Find(&items).Error\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn items, nil\n}\n\nfunc (repo *RepoGorm) GetByID(id int64) (*Item, error) {\n\tpost := &Item{}\n\terr := repo.DB.First(&post, \"id = ?\", id).Error\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn post, nil\n}\n\nfunc (repo *RepoGorm) Add(elem *Item) (int64, error) {\n\terr := repo.DB.Create(elem).Error\n\tlog.Println(\"created elem id:\", elem.ID)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn int64(elem.ID), nil\n}\n\nfunc (repo *RepoGorm) Update(elem *Item) (int64, error) {\n\tres := repo.DB.Model(&elem).Updates(map[string]interface{}{\n\t\t\"title\":       elem.Title,\n\t\t\"description\": elem.Description,\n\t\t\"updated\":     \"rvasily\",\n\t})\n\tif res.Error != nil {\n\t\treturn 0, res.Error\n\t}\n\treturn res.RowsAffected, nil\n}\n\nfunc (repo *RepoGorm) Delete(id int64) (int64, error) {\n\tres := repo.DB.Delete(&Item{}, id)\n\tif res.Error != nil {\n\t\treturn 0, res.Error\n\t}\n\treturn res.RowsAffected, nil\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/items/repo_mysql.go",
    "content": "package items\n\nimport (\n\t\"database/sql\"\n)\n\ntype RepoMysql struct {\n\tDB *sql.DB\n}\n\nfunc NewMysqlRepository(db *sql.DB) *RepoMysql {\n\treturn &RepoMysql{DB: db}\n}\n\nfunc (repo *RepoMysql) GetAll(limit int) ([]*Item, error) {\n\titems := make([]*Item, 0, limit)\n\trows, err := repo.DB.Query(\"SELECT id, title, updated FROM items\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer rows.Close() // надо закрывать соединение, иначе будет течь\n\tfor rows.Next() {\n\t\tpost := &Item{}\n\t\terr = rows.Scan(&post.ID, &post.Title, &post.Updated)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\titems = append(items, post)\n\t}\n\treturn items, nil\n}\n\n/*\n\n\tdsn += \"&interpolateParams=false\" (или нет параметра)\n\tQueryRow(\"SELECT * FROM items WHERE id = ?\", id).\n\t->\n\tsmtp := db.PrepareStatement(\"SELECT * FROM items WHERE id = ?\")\n\trow := smtp.Execute(smtp, 1)\n\n\n\n\tdsn += \"&interpolateParams=true\"\n\tsmtp := db.QueryRaw(\"SELECT * FROM items WHERE id = 1\")\n\n\n\n\tparams := make([]string, 0, len(manyIds))\n\tvalues := make([]interface{}, 0, len(manyIds))\n\tfor _, val := manyIds {\n\t\tparams = append(params, \"?\")\n\t\tvalues = append(values, val)\n\t}\n\n\tq := fmt.Sprintf(`where id in(%s)`, string.Join(params, `,`))\n\tdb.Query(q, values...)\n\n*/\n\nfunc (repo *RepoMysql) GetByID(id int64) (*Item, error) {\n\tpost := &Item{}\n\t// QueryRow сам закрывает коннект\n\terr := repo.DB.\n\t\tQueryRow(`SELECT id, title, updated, description FROM items WHERE id = ?`, id).\n\t\tScan(&post.ID, &post.Title, &post.Updated, &post.Description)\n\t// если запись не найден - вернется sql.ErrNoRows\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn post, nil\n}\n\nfunc (repo *RepoMysql) Add(elem *Item) (int64, error) {\n\tresult, err := repo.DB.Exec(\n\t\t\"INSERT INTO items (`title`, `description`) VALUES (?, ?)\",\n\t\telem.Title,\n\t\telem.Description,\n\t)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn result.LastInsertId()\n}\n\nfunc (repo *RepoMysql) Update(elem *Item) (int64, error) {\n\tresult, err := repo.DB.Exec(\n\t\t\"UPDATE items SET\"+\n\t\t\t\"`title` = ?\"+\n\t\t\t\",`description` = ?\"+\n\t\t\t\",`updated` = ?\"+\n\t\t\t\"WHERE id = ?\",\n\t\telem.Title,\n\t\telem.Description,\n\t\t\"rvasily\",\n\t\telem.ID,\n\t)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn result.RowsAffected()\n}\n\nfunc (repo *RepoMysql) Delete(id int64) (int64, error) {\n\tresult, err := repo.DB.Exec(\n\t\t\"DELETE FROM items WHERE id = ?\",\n\t\tid,\n\t)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn result.RowsAffected()\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/items/repo_pgx.go",
    "content": "package items\n\nimport (\n\t\"database/sql\"\n)\n\ntype RepoPgx struct {\n\tDB *sql.DB\n}\n\nfunc NewPgxRepository(db *sql.DB) *RepoPgx {\n\treturn &RepoPgx{DB: db}\n}\n\nfunc (repo *RepoPgx) GetAll() ([]*Item, error) {\n\titems := []*Item{}\n\trows, err := repo.DB.Query(\"SELECT id, title, updated FROM items\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer rows.Close() // надо закрывать соединение, иначе будет течь\n\tfor rows.Next() {\n\t\tpost := &Item{}\n\t\terr = rows.Scan(&post.ID, &post.Title, &post.Updated)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\titems = append(items, post)\n\t}\n\t/*\n\t\tfunc tx(db *sq.DB, fb func(tx *sql.Tx) error) error {\n\t\t\ttx := repo.DB.Begin()\n\t\t\terr := fb(tx)\n\t\t\tif err != nil {\n\t\t\t\ttx.Rollback()\n\t\t\t\treturn err\n\t\t\t}\n\t\t\ttx.Commit()\n\t\t\treturn nil\n\t\t}\n\n\t\ttx(repo.DB, func(tx *sql.Tx) error {\n\t\t\ttx.Query(\"select\")\n\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\ttx.Exec(\"update\")\n\n\t\t\treturn nil\n\t\t})\n\t*/\n\n\treturn items, nil\n}\n\nfunc (repo *RepoPgx) GetByID(id int64) (*Item, error) {\n\tpost := &Item{}\n\t// QueryRow сам закрывает коннект\n\terr := repo.DB.\n\t\tQueryRow(`SELECT id, title, updated, description FROM items WHERE id = $1`, id).\n\t\tScan(&post.ID, &post.Title, &post.Updated, &post.Description)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn post, nil\n}\n\nfunc (repo *RepoPgx) Add(elem *Item) (int64, error) {\n\tvar lastInsertId int64\n\terr := repo.DB.QueryRow(\n\t\t`INSERT INTO items (\"title\", \"description\") VALUES ($1, $2) RETURNING id`,\n\t\telem.Title,\n\t\telem.Description,\n\t).Scan(&lastInsertId)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn lastInsertId, nil\n}\n\nfunc (repo *RepoPgx) Update(elem *Item) (int64, error) {\n\tresult, err := repo.DB.Exec(\n\t\t`UPDATE items SET \"title\" = $1`+\n\t\t\t`,\"description\" = $2`+\n\t\t\t`,\"updated\" = $3`+\n\t\t\t`WHERE id = $4`,\n\t\telem.Title,\n\t\telem.Description,\n\t\t\"rvasily\",\n\t\telem.ID,\n\t)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn result.RowsAffected()\n}\n\nfunc (repo *RepoPgx) Delete(id int64) (int64, error) {\n\tresult, err := repo.DB.Exec(\n\t\t\"DELETE FROM items WHERE id = $1\",\n\t\tid,\n\t)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn result.RowsAffected()\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/items/repo_sqlx.go",
    "content": "package items\n\nimport (\n\t// \"database/sql\"\n\t\"github.com/jmoiron/sqlx\"\n)\n\ntype RepoSqlx struct {\n\tDB *sqlx.DB\n}\n\nfunc NewSqlxRepository(db *sqlx.DB) *RepoSqlx {\n\treturn &RepoSqlx{DB: db}\n}\n\nfunc (repo *RepoSqlx) GetAll() ([]*Item, error) {\n\titems := make([]*Item, 0, 10)\n\terr := repo.DB.Select(&items, \"SELECT id, title, updated FROM items\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn items, nil\n}\n\nfunc (repo *RepoSqlx) GetAll_0() ([]*Item, error) {\n\titems := make([]*Item, 0, 10)\n\trows, err := repo.DB.Queryx(\"SELECT id, title, updated FROM items\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor rows.Next() {\n\t\titem := &Item{}\n\t\t// MapScan, SliceScan\n\t\terr := rows.StructScan(&item)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\titems = append(items, item)\n\t}\n\treturn items, nil\n}\n\nfunc (repo *RepoSqlx) GetByID(id int64) (*Item, error) {\n\tpost := &Item{}\n\terr := repo.DB.Get(post, `SELECT id, title, updated, description FROM items WHERE id = ?`, id)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn post, nil\n}\n\nfunc (repo *RepoSqlx) Add(elem *Item) (int64, error) {\n\tresult, err := repo.DB.NamedExec(\n\t\t`INSERT INTO person (first_name,last_name,email) VALUES (:title, :description)`,\n\t\tmap[string]interface{}{\n\t\t\t\"title\":       elem.Title,\n\t\t\t\"description\": elem.Description,\n\t\t})\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn result.LastInsertId()\n}\n\nfunc (repo *RepoSqlx) Update(elem *Item) (int64, error) {\n\tresult, err := repo.DB.Exec(\n\t\t\"UPDATE items SET\"+\n\t\t\t\"`title` = ?\"+\n\t\t\t\",`description` = ?\"+\n\t\t\t\",`updated` = ?\"+\n\t\t\t\"WHERE id = ?\",\n\t\telem.Title,\n\t\telem.Description,\n\t\t\"rvasily\",\n\t\telem.ID,\n\t)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn result.RowsAffected()\n}\n\nfunc (repo *RepoSqlx) Delete(id int64) (int64, error) {\n\tresult, err := repo.DB.Exec(\n\t\t\"DELETE FROM items WHERE id = ?\",\n\t\tid,\n\t)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn result.RowsAffected()\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/middleware/accesslog.go",
    "content": "package middleware\n\nimport (\n\t// \"fmt\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"go.uber.org/zap\"\n)\n\nfunc AccessLog(logger *zap.SugaredLogger, next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t// fmt.Println(\"access log middleware\")\n\t\tstart := time.Now()\n\t\tnext.ServeHTTP(w, r)\n\t\tlogger.Infow(\"New request\",\n\t\t\t\"method\", r.Method,\n\t\t\t\"remote_addr\", r.RemoteAddr,\n\t\t\t\"url\", r.URL.Path,\n\t\t\t\"time\", time.Since(start),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/middleware/auth.go",
    "content": "package middleware\n\nimport (\n\t\"context\"\n\t// \"fmt\"\n\t\"net/http\"\n\n\t\"github.com/go-park-mail-ru/lectures/6-databases/06_crudapp_db_tests/pkg/session\"\n)\n\nvar (\n\tnoAuthUrls = map[string]struct{}{\n\t\t\"/login\": struct{}{},\n\t}\n\tnoSessUrls = map[string]struct{}{\n\t\t\"/\": struct{}{},\n\t}\n)\n\nfunc Auth(sm *session.SessionsManager, next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t// fmt.Println(\"auth middleware\")\n\t\tif _, ok := noAuthUrls[r.URL.Path]; ok {\n\t\t\tnext.ServeHTTP(w, r)\n\t\t\treturn\n\t\t}\n\t\tsess, err := sm.Check(r)\n\t\t_, canbeWithouthSess := noSessUrls[r.URL.Path]\n\t\tif err != nil && !canbeWithouthSess {\n\t\t\t// fmt.Println(\"no auth\")\n\t\t\thttp.Redirect(w, r, \"/\", 302)\n\t\t\treturn\n\t\t}\n\t\tctx := context.WithValue(r.Context(), session.SessionKey, sess)\n\t\tnext.ServeHTTP(w, r.WithContext(ctx))\n\t})\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/middleware/panic.go",
    "content": "package middleware\n\nimport (\n\t\"net/http\"\n)\n\nfunc Panic(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t// fmt.Println(\"panicMiddleware\", r.URL.Path)\n\t\tdefer func() {\n\t\t\tif err := recover(); err != nil {\n\t\t\t\t// fmt.Println(\"recovered\", err)\n\t\t\t\thttp.Error(w, \"Internal server error\", 500)\n\t\t\t}\n\t\t}()\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/session/manager.go",
    "content": "package session\n\nimport (\n\t\"net/http\"\n\t\"sync\"\n\t\"time\"\n)\n\ntype SessionsManager struct {\n\tdata map[string]*Session\n\tmu   *sync.RWMutex\n}\n\nfunc NewSessionsMem() *SessionsManager {\n\treturn &SessionsManager{\n\t\tdata: make(map[string]*Session, 10),\n\t\tmu:   &sync.RWMutex{},\n\t}\n}\n\nfunc (sm *SessionsManager) Check(r *http.Request) (*Session, error) {\n\tsessionCookie, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\treturn nil, ErrNoAuth\n\t}\n\n\tsm.mu.RLock()\n\tsess, ok := sm.data[sessionCookie.Value]\n\tsm.mu.RUnlock()\n\n\tif !ok {\n\t\treturn nil, ErrNoAuth\n\t}\n\n\treturn sess, nil\n}\n\nfunc (sm *SessionsManager) Create(w http.ResponseWriter, userID uint32) (*Session, error) {\n\tsess := NewSession(userID)\n\n\tsm.mu.Lock()\n\tsm.data[sess.ID] = sess\n\tsm.mu.Unlock()\n\n\tcookie := &http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   sess.ID,\n\t\tExpires: time.Now().Add(90 * 24 * time.Hour),\n\t\tPath:    \"/\",\n\t}\n\thttp.SetCookie(w, cookie)\n\treturn sess, nil\n}\n\nfunc (sm *SessionsManager) DestroyCurrent(w http.ResponseWriter, r *http.Request) error {\n\tsess, err := SessionFromContext(r.Context())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tsm.mu.Lock()\n\tdelete(sm.data, sess.ID)\n\tsm.mu.Unlock()\n\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tExpires: time.Now().AddDate(0, 0, -1),\n\t\tPath:    \"/\",\n\t}\n\thttp.SetCookie(w, &cookie)\n\treturn nil\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/session/session.go",
    "content": "package session\n\nimport (\n\t\"context\"\n\t\"crypto/rand\"\n\t\"errors\"\n\t\"fmt\"\n)\n\ntype Session struct {\n\tID     string\n\tUserID uint32\n}\n\nfunc NewSession(userID uint32) *Session {\n\t// лучше генерировать из заданного алфавита, но так писать меньше и для учебного примера ОК\n\trandID := make([]byte, 16)\n\trand.Read(randID)\n\n\treturn &Session{\n\t\tID:     fmt.Sprintf(\"%x\", randID),\n\t\tUserID: userID,\n\t}\n}\n\nvar (\n\tErrNoAuth = errors.New(\"No session found\")\n)\n\ntype sessKey string\n\nvar SessionKey sessKey = \"sessionKey\"\n\nfunc SessionFromContext(ctx context.Context) (*Session, error) {\n\tsess, ok := ctx.Value(SessionKey).(*Session)\n\tif !ok || sess == nil {\n\t\treturn nil, ErrNoAuth\n\t}\n\treturn sess, nil\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/pkg/user/user.go",
    "content": "package user\n\nimport \"errors\"\n\ntype User struct {\n\tID       uint32\n\tLogin    string\n\tpassword string\n}\n\ntype UserRepo struct {\n\tdata map[string]*User\n}\n\nfunc NewUserRepo() *UserRepo {\n\treturn &UserRepo{\n\t\tdata: map[string]*User{\n\t\t\t\"rvasily\": &User{\n\t\t\t\tID:       1,\n\t\t\t\tLogin:    \"rvasily\",\n\t\t\t\tpassword: \"love\",\n\t\t\t},\n\t\t},\n\t}\n}\n\nvar (\n\tErrNoUser  = errors.New(\"No user found\")\n\tErrBadPass = errors.New(\"Invald password\")\n)\n\nfunc (repo *UserRepo) Authorize(login, pass string) (*User, error) {\n\tu, ok := repo.data[login]\n\tif !ok {\n\t\treturn nil, ErrNoUser\n\t}\n\n\t// dont do this un production :)\n\tif u.password != pass {\n\t\treturn nil, ErrBadPass\n\t}\n\n\treturn u, nil\n}\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/readme.md",
    "content": "go mod init crudapp\n# go mod init github.com/rvasily/crudapp\ngo build\ngo mod download\ngo mod verify\ngo mod tidy\n\ngo build  -o ./bin/crudapp ./cmd/crudapp\ngo test -v -coverpkg=./... ./...\n\ngo mod vendor\ngo build -mod=vendor -o ./bin/myapp ./cmd/myapp\ngo test -v -mod=vendor -coverpkg=./... ./...\n\n----\n\ndocker-compose up\n\ngo test -v -coverprofile=cover.out -coverpkg=./... ./...\ngo tool cover -html=cover.out -o cover.html\n\n-----\n\nнаходять в папке pkg/handlers\nmockgen -source=items.go -destination=items_mock.go -package=handlers ItemRepositoryInterface\n\ngo test -v -run Handler -coverprofile=handler.out && go tool cover -html=handler.out -o handler.html && rm handler.out\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/templates/create.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/new\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/templates/edit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/{{.ID}}\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n        {{if .Updated.Valid}}\n        <div class=\"form-group\">\n          <label>{{.Updated.String}}</label>\n        </div>\n        {{end}}\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/templates/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\t<div class=\"container\">\n    <h1>Posts</h1>\n    <table class=\"table\">\n    <thead>\n      <tr>\n        <th>#</th>\n        <th>Title</th>\n        <th style=\"width:60px;\">Updated</th>\n        <th style=\"width:140px;\"><a href=\"/items/new\" class=\"btn btn-success\">New</a></th>\n      </tr>\n    </thead>\n    <tbody>\n    {{range .Items}}\n      <tr>\n        <td>{{.ID}}</td>\n        <td>{{.Title}}</td>\n        <td>{{if .Updated.Valid}}{{.Updated.String}}{{end}}</td>\n        <td>\n          <a href=\"/items/{{.ID}}\" class=\"btn btn-primary\">Edit</a>\n          <span data-id=\"{{.ID}}\" class=\"do-delete btn btn-danger\">Del</span>\n        </td>\n      </tr>\n\t\t{{end}}\n    </tbody>\n  </div>\n  \n  <script src=\"https://code.jquery.com/jquery-3.2.1.min.js\" crossorigin=\"anonymous\"></script>\n\n  <script type=\"text/javascript\">\n  $('.do-delete').click(function() {\n    if(!confirm(\"Are you sure?\")) {\n      return\n    }\n    $elem = $(this)\n    $.ajax({\n      url: '/items/' + $elem.data(\"id\"),\n      type: 'DELETE',\n      data: {},\n      success: function(resp) {\n        if(resp.updated) {\n          $elem.parent().parent().remove()\n        }\n      },\n    });\n  })\n  </script>\n  \n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/06_crudapp_db_tests/templates/login.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\t<div class=\"container\">\n        <h1>CrudAPP login</h1>\n        <form method=\"POST\" action=\"/login\">\n            <div class=\"form-group\">\n                <label for=\"login\">Login</label>\n                <input type=\"text\" class=\"form-control\" name=\"login\" id=\"login\" value=\"rvasily\">\n            </div>\n            <div class=\"form-group\">\n                <label for=\"password\">Password</label>\n                <input type=\"password\" class=\"form-control\" name=\"password\" id=\"password\" value=\"love\">\n            </div>\n            <button type=\"submit\" class=\"btn btn-primary\">Login</button>\n        </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/07_mongodb/main.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t// https://www.mongodb.com/blog/post/quick-start-golang--mongodb--modeling-documents-with-go-data-structures\n\t\"github.com/gorilla/mux\"\n\t\"go.mongodb.org/mongo-driver/bson\"\n\t\"go.mongodb.org/mongo-driver/bson/primitive\"\n\t\"go.mongodb.org/mongo-driver/mongo\"\n\t\"go.mongodb.org/mongo-driver/mongo/options\"\n)\n\ntype Item struct {\n\tId          primitive.ObjectID `json:\"id\" bson:\"_id\"`\n\tTitle       string             `json:\"title\" bson:\"title\"`\n\tDescription string             `json:\"description\" bson:\"description\"`\n\tUpdated     string             `json:\"updated\" bson:\"updated\"`\n}\n\ntype Handler struct {\n\tSess  *mongo.Client\n\tItems *mongo.Collection\n\tTmpl  *template.Template\n}\n\nfunc (h *Handler) List(w http.ResponseWriter, r *http.Request) {\n\n\titems := []*Item{}\n\n\t// bson.M{} - это типа условия для поиска\n\tc, err := h.Items.Find(r.Context(), bson.M{})\n\tpanicOnError(err)\n\terr = c.All(r.Context(), &items)\n\tpanicOnError(err)\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"index.html\", struct {\n\t\tItems []*Item\n\t}{\n\t\tItems: items,\n\t})\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) AddForm(w http.ResponseWriter, r *http.Request) {\n\terr := h.Tmpl.ExecuteTemplate(w, \"create.html\", nil)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) Add(w http.ResponseWriter, r *http.Request) {\n\n\tnewItem := bson.M{\n\t\t\"_id\":         primitive.NewObjectID(),\n\t\t\"title\":       r.FormValue(\"title\"),\n\t\t\"description\": r.FormValue(\"description\"),\n\t\t\"some_filed\":  123,\n\t}\n\t_, err := h.Items.InsertOne(r.Context(), newItem)\n\tpanicOnError(err)\n\n\tfmt.Println(\"Insert - LastInsertId:\", newItem[\"_id\"])\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *Handler) Edit(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tif !primitive.IsValidObjectID(vars[\"id\"]) {\n\t\thttp.Error(w, \"bad id\", 500)\n\t\treturn\n\t}\n\tid, err := primitive.ObjectIDFromHex(vars[\"id\"])\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), 500)\n\t\treturn\n\t}\n\n\tpost := &Item{}\n\terr = h.Items.FindOne(r.Context(), bson.M{\"_id\": id}).Decode(post)\n\tpanicOnError(err)\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"edit.html\", post)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *Handler) Update(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tif !primitive.IsValidObjectID(vars[\"id\"]) {\n\t\thttp.Error(w, \"bad id\", 500)\n\t\treturn\n\t}\n\tid, err := primitive.ObjectIDFromHex(vars[\"id\"])\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), 500)\n\t\treturn\n\t}\n\n\tpost := &Item{}\n\terr = h.Items.FindOne(r.Context(), bson.M{\"_id\": id}).Decode(&post)\n\tpanicOnError(err)\n\n\tpost.Title = r.FormValue(\"title\")\n\tpost.Description = r.FormValue(\"description\")\n\tpost.Updated = \"rvasily\"\n\n\tres, err := h.Items.UpdateOne(\n\t\tr.Context(),\n\t\tbson.M{\"_id\": id},\n\t\t// про другие операторы помимо $set можно почитать тут\n\t\t// https://www.mongodb.com/docs/manual/reference/operator/update/\n\t\tbson.M{\"$set\": bson.M{\n\t\t\t\"title\":       r.FormValue(\"title\"),\n\t\t\t\"description\": r.FormValue(\"description\"),\n\t\t\t\"updated\":     \"rvasily\",\n\t\t\t\"newField\":    123,\n\t\t}},\n\t)\n\taffected := 1\n\tif err != nil {\n\t\tpanicOnError(err)\n\t} else if res.ModifiedCount == 0 {\n\t\taffected = 0\n\t}\n\n\tfmt.Println(\"Update - RowsAffected\", affected)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tif !primitive.IsValidObjectID(vars[\"id\"]) {\n\t\thttp.Error(w, \"bad id\", 500)\n\t\treturn\n\t}\n\tid, err := primitive.ObjectIDFromHex(vars[\"id\"])\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), 500)\n\t\treturn\n\t}\n\n\tres, err := h.Items.DeleteOne(r.Context(), bson.M{\"_id\": id})\n\taffected := 1\n\tif err != nil {\n\t\tpanicOnError(err)\n\t} else if res.DeletedCount == 0 {\n\t\taffected = 0\n\t}\n\n\tw.Header().Set(\"Content-type\", \"application/json\")\n\tresp := `{\"affected\": ` + strconv.Itoa(int(affected)) + `}`\n\tw.Write([]byte(resp))\n}\n\nfunc main() {\n\tctx := context.Background()\n\tsess, err := mongo.Connect(ctx, options.Client().ApplyURI(\"mongodb://localhost\"))\n\tpanicOnError(err)\n\n\tcollection := sess.Database(\"golang\").Collection(\"items\")\n\n\t// если коллекции не будет, то она создасться автоматически\n\t// для монги нет такого красивого дампа SQL, так что я вставляю демо-запись если коллекция пуста\n\tif n, _ := collection.CountDocuments(ctx, bson.M{}); n == 0 {\n\t\tcollection.InsertOne(ctx, &Item{\n\t\t\tId:          primitive.NewObjectID(),\n\t\t\tTitle:       \"mongodb\",\n\t\t\tDescription: \"Рассказать про монгу\",\n\t\t\tUpdated:     \"\",\n\t\t})\n\t\tcollection.InsertOne(ctx, &Item{\n\t\t\tId:          primitive.NewObjectID(),\n\t\t\tTitle:       \"redis\",\n\t\t\tDescription: \"Рассказать про redis\",\n\t\t\tUpdated:     \"rvasily\",\n\t\t})\n\t}\n\n\thandlers := &Handler{\n\t\tItems: collection,\n\t\tTmpl:  template.Must(template.ParseGlob(\"./templates/*\")),\n\t}\n\n\t// В целях упрощения примера пропущена авторизация и csrf\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.AddForm).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.Add).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Edit).Methods(\"GET\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Update).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Delete).Methods(\"DELETE\")\n\n\tfmt.Println(\"starting server at :8080\")\n\terr = http.ListenAndServe(\":8080\", r)\n\tpanicOnError(err)\n}\n\n// Не используйте такой код в продакшене.\n// Ошибка должна всегда явно обрабатываться\nfunc panicOnError(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n"
  },
  {
    "path": "6-databases/07_mongodb/templates/create.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/new\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/07_mongodb/templates/edit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/{{.Id.Hex}}\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n        <div class=\"form-group\">\n          <label>{{.Updated}}</label>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/07_mongodb/templates/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\t<div class=\"container\">\n    <h1>Posts</h1>\n    <table class=\"table\">\n    <thead>\n      <tr>\n        <th>#</th>\n        <th>Title</th>\n        <th style=\"width:60px;\">Edited</th>\n        <th style=\"width:140px;\"><a href=\"/items/new\" class=\"btn btn-success\">New</a></th>\n      </tr>\n    </thead>\n    <tbody>\n    {{range .Items}}\n      <tr>\n        <td>{{.Id.Hex}}</td>\n        <td>{{.Title}}</td>\n        <td>{{.Updated}}</td>\n        <td>\n          <a href=\"/items/{{.Id.Hex}}\" class=\"btn btn-primary\">Edit</a>\n          <span data-id=\"{{.Id.Hex}}\" class=\"do-delete btn btn-danger\">Del</span>\n        </td>\n      </tr>\n\t\t{{end}}\n    </tbody>\n  </div>\n  \n  <script src=\"https://code.jquery.com/jquery-3.2.1.min.js\" crossorigin=\"anonymous\"></script>\n\n  <script type=\"text/javascript\">\n  $('.do-delete').click(function() {\n    if(!confirm(\"Are you sure?\")) {\n      return\n    }\n    $elem = $(this)\n    $.ajax({\n      url: '/items/' + $elem.data(\"id\"),\n      type: 'DELETE',\n      data: {},\n      success: function(resp) {\n        if(resp.affected > 0 ) {\n          $elem.parent().parent().remove()\n        }\n      },\n    });\n  })\n  </script>\n  \n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/08_memcache/memcache.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/bradfitz/gomemcache/memcache\"\n)\n\nfunc main() {\n\tMemcachedAddresses := []string{\"127.0.0.1:11211\"}\n\tmemcacheClient := memcache.New(MemcachedAddresses...)\n\n\tmkey := \"tech\"\n\n\tmemcacheClient.Set(&memcache.Item{\n\t\tKey:        mkey,\n\t\tValue:      []byte(\"1\"),\n\t\tExpiration: 3,\n\t})\n\n\tmemcacheClient.Increment(\"habrTag\", 1)\n\n\titem, err := memcacheClient.Get(mkey)\n\tif err != nil && !errors.Is(err, memcache.ErrCacheMiss) {\n\t\tfmt.Println(\"MC error\", err)\n\t}\n\n\tfmt.Printf(\"mc value %#v\\n\", item)\n\n\tmemcacheClient.Delete(mkey)\n\n\titem, err = memcacheClient.Get(mkey)\n\tif errors.Is(err, memcache.ErrCacheMiss) {\n\t\tfmt.Println(\"record not found in MC\")\n\t}\n\n}\n"
  },
  {
    "path": "6-databases/09_redis_simple/cmds.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/gomodule/redigo/redis\"\n)\n\nvar (\n\tc redis.Conn\n)\n\nfunc getRecord(mkey string) (string, error) {\n\tprintln(\"get\", mkey)\n\t// получает запись, https://redis.io/commands/get\n\tdata, err := c.Do(\"GET\", mkey)\n\titem, err := redis.String(data, err)\n\t// если записи нет, то для этого есть специальная ошибка, её надо обрабатывать отдеьно, это почти штатная ситуация, а не что-то страшное\n\tif errors.Is(err, redis.ErrNil) {\n\t\tfmt.Println(\"Record not found in redis (return value is nil)\")\n\t\treturn \"\", redis.ErrNil\n\t} else if err != nil {\n\t\treturn \"\", err\n\t}\n\treturn item, nil\n}\n\nfunc main() {\n\tvar err error\n\t// соединение\n\tc, err = redis.DialURL(\"redis://user:@localhost:6379/0\")\n\t// c, err = redis.DialURL(os.Getenv(\"REDIS_URL\"))\n\tPanicOnErr(err)\n\tdefer c.Close()\n\n\tmkey := \"record_21\"\n\n\titem, err := getRecord(mkey)\n\tfmt.Printf(\"first get %+v\\n\", item)\n\n\tttl := 5\n\t// добавляет запись, https://redis.io/commands/set\n\tresult, err := redis.String(c.Do(\"SET\", mkey, 1, \"EX\", ttl))\n\tPanicOnErr(err)\n\tif result != \"OK\" {\n\t\tpanic(\"result not ok: \" + result)\n\t}\n\n\ttime.Sleep(time.Microsecond)\n\t// time.Sleep(7 * time.Second)\n\n\titem, err = getRecord(mkey)\n\tif err != nil {\n\t\tPanicOnErr(err)\n\t}\n\tfmt.Printf(\"second get %+v\\n\", item)\n\n\t// https://redis.io/commands/incrby\n\t// https://redis.io/commands/incr - тут хорошо описан рейтилимитер\n\tn, _ := redis.Int(c.Do(\"INCRBY\", mkey, 2))\n\tfmt.Println(\"INCRBY by 2 \", mkey, \"is\", n)\n\n\t// https://redis.io/commands/decrby\n\tn, _ = redis.Int(c.Do(\"DECRBY\", mkey, 1))\n\tfmt.Println(\"DECRY by 1 \", mkey, \"is\", n)\n\n\t// если записи не было - редис создаст\n\tn, err = redis.Int(c.Do(\"INCR\", mkey+\"_not_exist\"))\n\tfmt.Println(\"INCR (default by 1) \", mkey+\"_not_exist\", \"is\", n)\n\tPanicOnErr(err)\n\n\tkeys := []interface{}{mkey, mkey + \"_not_exist\", \"sure_not_exist\"}\n\n\t// https://redis.io/commands/mget\n\treply, err := redis.Strings(c.Do(\"MGET\", keys...))\n\tPanicOnErr(err)\n\tfmt.Println(reply)\n}\n\n// PanicOnErr panics on error\nfunc PanicOnErr(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n"
  },
  {
    "path": "6-databases/10_redis/main.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/gomodule/redigo/redis\"\n)\n\nvar (\n\tredisAddr = flag.String(\"addr\", \"redis://user:@localhost:6379/0\", \"redis addr\")\n\n\tsessManager *SessionManager\n\n\tusers = map[string]string{\n\t\t\"dmitrydorofeev\": \"test\",\n\t\t\"romanov.vasily\": \"100500\",\n\t}\n)\n\nfunc checkSession(r *http.Request) (*Session, error) {\n\tcookieSessionID, err := r.Cookie(\"session_id\")\n\tif errors.Is(err, http.ErrNoCookie) {\n\t\treturn nil, nil\n\t} else if err != nil {\n\t\treturn nil, err\n\t}\n\n\tsess := sessManager.Check(&SessionID{\n\t\tID: cookieSessionID.Value,\n\t})\n\treturn sess, nil\n}\n\nfunc innerPage(w http.ResponseWriter, r *http.Request) {\n\tsess, err := checkSession(r)\n\tif err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif sess == nil {\n\t\tw.Write(loginFormTmpl)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"text/html\")\n\tfmt.Fprintln(w, \"Welcome, \"+sess.Login+\" <br />\")\n\tfmt.Fprintln(w, \"Session ua: \"+sess.Useragent+\" <br />\")\n\tfmt.Fprintln(w, `<a href=\"/logout\">logout</a>`)\n}\n\nfunc loginPage(w http.ResponseWriter, r *http.Request) {\n\tinputLogin := r.FormValue(\"login\")\n\tinputPass := r.FormValue(\"password\")\n\texpiration := time.Now().Add(24 * time.Hour)\n\n\tpass, exist := users[inputLogin]\n\tif !exist || pass != inputPass {\n\t\tw.WriteHeader(http.StatusUnauthorized)\n\t\treturn\n\t}\n\n\tsess, err := sessManager.Create(&Session{\n\t\tLogin:     inputLogin,\n\t\tUseragent: r.UserAgent(),\n\t})\n\tif err != nil {\n\t\tlog.Println(\"cant create session:\", err)\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   sess.ID,\n\t\tExpires: expiration,\n\t}\n\thttp.SetCookie(w, &cookie)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc main() {\n\tflag.Parse()\n\n\tvar err error\n\tredisConn, err := redis.DialURL(*redisAddr)\n\tif err != nil {\n\t\tlog.Fatalf(\"cant connect to redis\")\n\t}\n\n\tsessManager = NewSessionManager(redisConn)\n\n\thttp.HandleFunc(\"/\", innerPage)\n\thttp.HandleFunc(\"/login\", loginPage)\n\thttp.HandleFunc(\"/logout\", logoutPage)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\nfunc logoutPage(w http.ResponseWriter, r *http.Request) {\n\tsession, err := r.Cookie(\"session_id\")\n\tif errors.Is(err, http.ErrNoCookie) {\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t\treturn\n\t} else if err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tsessManager.Delete(&SessionID{\n\t\tID: session.Value,\n\t})\n\n\tsession.Expires = time.Now().AddDate(0, 0, -1)\n\thttp.SetCookie(w, session)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nvar loginFormTmpl = []byte(`\n\t<html>\n\t\t<body>\n\t\t<form action=\"/login\" method=\"post\">\n\t\t\tLogin: <input type=\"text\" name=\"login\">\n\t\t\tPassword: <input type=\"password\" name=\"password\">\n\t\t\t<input type=\"submit\" value=\"Login\">\n\t\t</form>\n\t\t</body>\n\t</html>\n\t`)\n"
  },
  {
    "path": "6-databases/10_redis/session.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\n\t\"github.com/gomodule/redigo/redis\"\n)\n\ntype Session struct {\n\tLogin     string\n\tUseragent string\n}\n\ntype SessionID struct {\n\tID string\n}\n\nconst sessKeyLen = 10\n\ntype SessionManager struct {\n\tredisConn redis.Conn\n}\n\nfunc NewSessionManager(conn redis.Conn) *SessionManager {\n\treturn &SessionManager{\n\t\tredisConn: conn,\n\t}\n}\n\nfunc (sm *SessionManager) Create(in *Session) (*SessionID, error) {\n\tid := SessionID{RandStringRunes(sessKeyLen)}\n\tdataSerialized, _ := json.Marshal(in)\n\tmkey := \"sessions:\" + id.ID\n\tresult, err := redis.String(sm.redisConn.Do(\"SET\", mkey, dataSerialized, \"EX\", 86400))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif result != \"OK\" {\n\t\treturn nil, fmt.Errorf(\"result not OK\")\n\t}\n\treturn &id, nil\n}\n\nfunc (sm *SessionManager) Check(in *SessionID) *Session {\n\tmkey := \"sessions:\" + in.ID\n\tdata, err := redis.Bytes(sm.redisConn.Do(\"GET\", mkey))\n\tif err != nil {\n\t\tlog.Println(\"cant get data:\", err)\n\t\treturn nil\n\t}\n\tsess := &Session{}\n\terr = json.Unmarshal(data, sess)\n\tif err != nil {\n\t\tlog.Println(\"cant unpack session data:\", err)\n\t\treturn nil\n\t}\n\treturn sess\n}\n\nfunc (sm *SessionManager) Delete(in *SessionID) {\n\tmkey := \"sessions:\" + in.ID\n\t_, err := redis.Int(sm.redisConn.Do(\"DEL\", mkey))\n\tif err != nil {\n\t\tlog.Println(\"redis error:\", err)\n\t}\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "6-databases/11_rabbit/form/form.go",
    "content": "package main\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"math/rand\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/streadway/amqp\"\n)\n\nvar uploadFormTmpl = []byte(`\n<html>\n\t<body>\n\t<form action=\"/upload\" method=\"post\" enctype=\"multipart/form-data\">\n\t\tImage: <input type=\"file\" name=\"my_file\">\n\t\t<input type=\"submit\" value=\"Upload\">\n\t</form>\n\t</body>\n</html>\n`)\n\ntype ImgResizeTask struct {\n\tName string\n\tMD5  string\n}\n\nfunc mainPage(w http.ResponseWriter, r *http.Request) {\n\tw.Write(uploadFormTmpl)\n}\n\nfunc uploadPage(w http.ResponseWriter, r *http.Request) {\n\tuploadData, handler, err := r.FormFile(\"my_file\")\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\treturn\n\t}\n\tdefer uploadData.Close()\n\n\tfmt.Fprintf(w, \"handler.Filename %v\\n\", handler.Filename)\n\tfmt.Fprintf(w, \"handler.Header %#v\\n\", handler.Header)\n\n\ttmpName := RandStringRunes(32)\n\n\ttmpFile := \"./images/\" + tmpName + \".jpg\"\n\tnewFile, err := os.Create(tmpFile)\n\tif err != nil {\n\t\thttp.Error(w, \"cant open file: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\thasher := md5.New()\n\twrittenBytes, err := io.Copy(newFile, io.TeeReader(uploadData, hasher))\n\tif err != nil {\n\t\thttp.Error(w, \"cant save file: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\tnewFile.Sync()\n\tnewFile.Close()\n\n\tmd5Sum := hex.EncodeToString(hasher.Sum(nil))\n\n\trealFile := \"./images/\" + md5Sum + \".jpg\"\n\terr = os.Rename(tmpFile, realFile)\n\tif err != nil {\n\t\thttp.Error(w, \"cant rename file: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tdata, _ := json.Marshal(ImgResizeTask{handler.Filename, md5Sum})\n\n\tfmt.Println(\"put task \", string(data))\n\n\terr = rabbitChan.Publish(\n\t\t\"\",                   // exchange\n\t\tImageResizeQueueName, // routing key\n\t\tfalse,                // mandatory\n\t\tfalse,                // immediate\n\t\tamqp.Publishing{\n\t\t\tDeliveryMode: amqp.Persistent,\n\t\t\tContentType:  \"text/plain\",\n\t\t\tBody:         data,\n\t\t},\n\t)\n\tpanicOnError(\"cant publish task\", err)\n\n\tfmt.Fprintf(w, \"Upload %d bytes successful\\n\", writtenBytes)\n}\n\nconst (\n\tImageResizeQueueName = \"image_resize\"\n)\n\nvar (\n\trabbitAddr = flag.String(\"addr\", \"amqp://guest:guest@127.0.0.1:5672/\", \"rabbit addr\")\n\n\trabbitConn *amqp.Connection\n\n\trabbitChan *amqp.Channel\n)\n\nfunc main() {\n\terr := os.Mkdir(\"./images\", 0777)\n\tif err != nil && !os.IsExist(err) {\n\t\tfmt.Println(err)\n\t\treturn\n\t}\n\n\tflag.Parse()\n\n\trabbitConn, err = amqp.Dial(*rabbitAddr)\n\tpanicOnError(\"cant connect to rabbit\", err)\n\n\trabbitChan, err = rabbitConn.Channel()\n\tpanicOnError(\"cant open chan\", err)\n\tdefer rabbitChan.Close()\n\n\tq, err := rabbitChan.QueueDeclare(\n\t\tImageResizeQueueName, // name\n\t\ttrue,                 // durable\n\t\tfalse,                // delete when unused\n\t\tfalse,                // exclusive\n\t\tfalse,                // no-wait\n\t\tnil,                  // arguments\n\t)\n\tpanicOnError(\"cant init queue\", err)\n\n\tfmt.Printf(\"queue %s have %d msg and %d consumers\\n\",\n\t\tq.Name, q.Messages, q.Consumers)\n\n\thttp.HandleFunc(\"/\", mainPage)\n\thttp.HandleFunc(\"/upload\", uploadPage)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\n// Никогда так не делайте!\nfunc panicOnError(msg string, err error) {\n\tif err != nil {\n\t\tpanic(msg + \" \" + err.Error())\n\t}\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "6-databases/11_rabbit/resizer/resize_worker.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"image/jpeg\"\n\t\"os\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/nfnt/resize\"\n\t\"github.com/streadway/amqp\"\n)\n\ntype ImgResizeTask struct {\n\tName string\n\tMD5  string\n}\n\nconst (\n\tImageResizeQueueName = \"image_resize\"\n)\n\nvar (\n\trabbitAddr = flag.String(\"addr\", \"amqp://guest:guest@127.0.0.1:5672/\", \"rabbit addr\")\n\n\trabbitConn *amqp.Connection\n\n\trabbitChan *amqp.Channel\n)\n\nfunc main() {\n\tflag.Parse()\n\tvar err error\n\trabbitConn, err = amqp.Dial(*rabbitAddr)\n\tpanicOnError(\"cant connect to rabbit\", err)\n\n\trabbitChan, err = rabbitConn.Channel()\n\tpanicOnError(\"cant open chan\", err)\n\tdefer rabbitChan.Close()\n\n\t_, err = rabbitChan.QueueDeclare(\n\t\tImageResizeQueueName, // name\n\t\ttrue,                 // durable\n\t\tfalse,                // delete when unused\n\t\tfalse,                // exclusive\n\t\tfalse,                // no-wait\n\t\tnil,                  // arguments\n\t)\n\tpanicOnError(\"cant init queue\", err)\n\n\terr = rabbitChan.Qos(\n\t\t1,     // prefetch count\n\t\t0,     // prefetch size\n\t\tfalse, // global\n\t)\n\tpanicOnError(\"cant set QoS\", err)\n\n\ttasks, err := rabbitChan.Consume(\n\t\tImageResizeQueueName, // queue\n\t\t\"\",                   // consumer\n\t\tfalse,                // auto-ack\n\t\tfalse,                // exclusive\n\t\tfalse,                // no-local\n\t\tfalse,                // no-wait\n\t\tnil,                  // args\n\t)\n\tpanicOnError(\"cant register consumer\", err)\n\n\twg := &sync.WaitGroup{}\n\twg.Add(1)\n\n\tgo ResizeWorker(tasks)\n\n\tfmt.Println(\"worker started\")\n\twg.Wait()\n}\n\nvar (\n\tsizes = []uint{80, 160, 320}\n)\n\nfunc ResizeWorker(tasks <-chan amqp.Delivery) {\n\tfor taskItem := range tasks {\n\t\tfmt.Printf(\"incoming task %+v\\n\", taskItem)\n\n\t\ttask := &ImgResizeTask{}\n\t\terr := json.Unmarshal(taskItem.Body, task)\n\t\tif err != nil {\n\t\t\tfmt.Println(\"cant unpack json\", err)\n\t\t\ttaskItem.Ack(false)\n\t\t\tcontinue\n\t\t}\n\n\t\toriginalPath := fmt.Sprintf(\"./images/%s.jpg\", task.MD5)\n\t\tfor _, size := range sizes {\n\t\t\tresizedPath := fmt.Sprintf(\"./images/%s_%d.jpg\", task.MD5, size)\n\t\t\terr := ResizeImage(originalPath, resizedPath, size)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Println(\"resize failed\", err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfmt.Println(\"resize success\")\n\t\t\ttime.Sleep(3 * time.Second)\n\t\t}\n\n\t\ttaskItem.Ack(false)\n\t}\n}\n\nfunc ResizeImage(originalPath string, resizedPath string, size uint) error {\n\tfile, err := os.Open(originalPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cant open file %s: %s\", originalPath, err)\n\t}\n\n\timg, err := jpeg.Decode(file)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cant jpeg decode file %s\", err)\n\t}\n\tfile.Close()\n\n\tresizeImage := resize.Resize(size, 0, img, resize.Lanczos3)\n\n\tout, err := os.Create(resizedPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cant create file %s: %s\", resizedPath, err)\n\t}\n\tdefer out.Close()\n\n\tjpeg.Encode(out, resizeImage, nil)\n\n\treturn nil\n}\n\n// Никогда так не делайте!\nfunc panicOnError(msg string, err error) {\n\tif err != nil {\n\t\tpanic(msg + \" \" + err.Error())\n\t}\n}\n"
  },
  {
    "path": "6-databases/12_kafka/form/form.go",
    "content": "package main\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"math/rand\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/IBM/sarama\"\n)\n\nvar uploadFormTmpl = []byte(`\n<html>\n\t<body>\n\t<form action=\"/upload\" method=\"post\" enctype=\"multipart/form-data\">\n\t\tImage: <input type=\"file\" name=\"my_file\">\n\t\t<input type=\"submit\" value=\"Upload\">\n\t</form>\n\t</body>\n</html>\n`)\n\ntype ImgResizeTask struct {\n\tName string\n\tMD5  string\n}\n\nfunc mainPage(w http.ResponseWriter, r *http.Request) {\n\tw.Write(uploadFormTmpl)\n}\n\nfunc uploadPage(w http.ResponseWriter, r *http.Request) {\n\tuploadData, handler, err := r.FormFile(\"my_file\")\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\treturn\n\t}\n\tdefer uploadData.Close()\n\n\tfmt.Fprintf(w, \"handler.Filename %v\\n\", handler.Filename)\n\tfmt.Fprintf(w, \"handler.Header %#v\\n\", handler.Header)\n\n\ttmpName := RandStringRunes(32)\n\n\ttmpFile := \"./images/\" + tmpName + \".jpg\"\n\tnewFile, err := os.Create(tmpFile)\n\tif err != nil {\n\t\thttp.Error(w, \"cant open file: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\thasher := md5.New()\n\twrittenBytes, err := io.Copy(newFile, io.TeeReader(uploadData, hasher))\n\tif err != nil {\n\t\thttp.Error(w, \"cant save file: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\tnewFile.Sync()\n\tnewFile.Close()\n\n\tmd5Sum := hex.EncodeToString(hasher.Sum(nil))\n\n\trealFile := \"./images/\" + md5Sum + \".jpg\"\n\terr = os.Rename(tmpFile, realFile)\n\tif err != nil {\n\t\thttp.Error(w, \"cant rename file: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tdata, _ := json.Marshal(ImgResizeTask{handler.Filename, md5Sum})\n\n\tfmt.Println(\"put task \", string(data))\n\n\t// Kafka publish via sarama\n\tmsg := &sarama.ProducerMessage{\n\t\tTopic: ImageResizeTopicName,\n\t\tKey:   sarama.StringEncoder(md5Sum),\n\t\tValue: sarama.ByteEncoder(data),\n\t}\n\tkafkaAsyncP.Input() <- msg\n\n\tfmt.Fprintf(w, \"Upload %d bytes successful\\n\", writtenBytes)\n}\n\nconst (\n\tImageResizeTopicName = \"cool_topic\"\n)\n\nvar (\n\tkafkaAddr   = flag.String(\"addr\", \"localhost:9092\", \"kafka broker address\")\n\tkafkaAsyncP sarama.AsyncProducer\n)\n\nfunc main() {\n\terr := os.Mkdir(\"./images\", 0777)\n\tif err != nil && !os.IsExist(err) {\n\t\tfmt.Println(err)\n\t\treturn\n\t}\n\n\tflag.Parse()\n\n\tconfig := sarama.NewConfig()\n\tconfig.Producer.Return.Successes = false\n\tconfig.Producer.Return.Errors = true\n\n\tkafkaAsyncP, err = sarama.NewAsyncProducer([]string{*kafkaAddr}, config)\n\tpanicOnError(\"cant create kafka producer\", err)\n\tdefer kafkaAsyncP.Close()\n\n\t// Отдельная горутина для ошибок продюсера\n\tgo func() {\n\t\tfor err := range kafkaAsyncP.Errors() {\n\t\t\tfmt.Println(\"Failed to produce message\", err)\n\t\t}\n\t}()\n\n\thttp.HandleFunc(\"/\", mainPage)\n\thttp.HandleFunc(\"/upload\", uploadPage)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\n// Никогда так не делайте!\nfunc panicOnError(msg string, err error) {\n\tif err != nil {\n\t\tpanic(msg + \" \" + err.Error())\n\t}\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "6-databases/12_kafka/resizer/resize_worker.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"image/jpeg\"\n\t\"os\"\n\t\"os/signal\"\n\t\"sync\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/IBM/sarama\"\n\t\"github.com/nfnt/resize\"\n)\n\ntype ImgResizeTask struct {\n\tName string\n\tMD5  string\n}\n\nconst (\n\tImageResizeTopicName = \"cool_topic\"\n)\n\nvar (\n\tkafkaAddr = flag.String(\"addr\", \"localhost:9092\", \"kafka broker address\")\n\tgroupID   = flag.String(\"group\", \"resizer-group\", \"kafka consumer group\")\n)\n\nvar (\n\tsizes = []uint{80, 160, 320}\n)\n\ntype Consumer struct {\n\tready chan bool\n}\n\nfunc (c *Consumer) Setup(sarama.ConsumerGroupSession) error {\n\tclose(c.ready)\n\treturn nil\n}\nfunc (c *Consumer) Cleanup(sarama.ConsumerGroupSession) error { return nil }\n\nfunc (c *Consumer) ConsumeClaim(sess sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error {\n\tfor msg := range claim.Messages() {\n\t\tfmt.Printf(\"incoming task %s\\n\", string(msg.Value))\n\n\t\ttask := &ImgResizeTask{}\n\t\terr := json.Unmarshal(msg.Value, task)\n\t\tif err != nil {\n\t\t\tfmt.Println(\"cant unpack json\", err)\n\t\t\tsess.MarkMessage(msg, \"\")\n\t\t\tcontinue\n\t\t}\n\n\t\toriginalPath := fmt.Sprintf(\"./images/%s.jpg\", task.MD5)\n\t\tfor _, size := range sizes {\n\t\t\tresizedPath := fmt.Sprintf(\"./images/%s_%d.jpg\", task.MD5, size)\n\t\t\terr := ResizeImage(originalPath, resizedPath, size)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Println(\"resize failed\", err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfmt.Println(\"resize success\")\n\t\t\ttime.Sleep(3 * time.Second)\n\t\t}\n\t\tsess.MarkMessage(msg, \"\")\n\t}\n\treturn nil\n}\n\nfunc main() {\n\tflag.Parse()\n\n\tconfig := sarama.NewConfig()\n\tconfig.Version = sarama.V2_1_0_0\n\tconfig.Consumer.Return.Errors = true\n\tconfig.Consumer.Offsets.Initial = sarama.OffsetOldest\n\n\tconsumer := Consumer{\n\t\tready: make(chan bool),\n\t}\n\n\tclient, err := sarama.NewConsumerGroup([]string{*kafkaAddr}, *groupID, config)\n\tpanicOnError(\"cant create consumer group\", err)\n\tdefer client.Close()\n\n\tc := make(chan os.Signal, 1)\n\tsignal.Notify(c, syscall.SIGINT, syscall.SIGTERM)\n\n\twg := &sync.WaitGroup{}\n\twg.Add(1)\n\n\tctx, cancel := context.WithCancel(context.Background())\n\n\tgo func() {\n\t\t<-c\n\t\tcancel()\n\t}()\n\n\tgo func() {\n\t\tdefer wg.Done()\n\n\t\tfor {\n\t\t\tif err := client.Consume(ctx, []string{ImageResizeTopicName}, &consumer); err != nil {\n\t\t\t\tfmt.Println(\"Error from consumer:\", err)\n\t\t\t\ttime.Sleep(time.Second)\n\t\t\t}\n\n\t\t\tconsumer.ready = make(chan bool)\n\n\t\t\t// Check if context was cancelled, signaling that the consumer should stop\n\t\t\tselect {\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn\n\t\t\tdefault:\n\t\t\t}\n\t\t}\n\t}()\n\n\t<-consumer.ready\n\tfmt.Println(\"worker started\")\n\t<-ctx.Done()\n\tfmt.Println(\"worker stopped\")\n\twg.Wait()\n}\n\nfunc ResizeImage(originalPath string, resizedPath string, size uint) error {\n\tfile, err := os.Open(originalPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cant open file %s: %s\", originalPath, err)\n\t}\n\tdefer file.Close()\n\n\timg, err := jpeg.Decode(file)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cant jpeg decode file %s\", err)\n\t}\n\n\tresizeImage := resize.Resize(size, 0, img, resize.Lanczos3)\n\n\tout, err := os.Create(resizedPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cant create file %s: %s\", resizedPath, err)\n\t}\n\tdefer out.Close()\n\n\tjpeg.Encode(out, resizeImage, nil)\n\n\treturn nil\n}\n\n// Никогда так не делайте!\nfunc panicOnError(msg string, err error) {\n\tif err != nil {\n\t\tpanic(msg + \" \" + err.Error())\n\t}\n}\n"
  },
  {
    "path": "6-databases/13_tarantool_simple/Dockerfile",
    "content": "FROM tarantool/tarantool:2.10.8\nCOPY app.lua /opt/tarantool\nCMD [\"tarantool\", \"/opt/tarantool/app.lua\"]\n"
  },
  {
    "path": "6-databases/13_tarantool_simple/app.lua",
    "content": "#!/usr/bin/env tarantool\n\n-- Настроить базу данных\nbox.cfg {\n    listen = 3301\n}\n\n-- При поднятии БД создаем спейсы и индексы\nbox.once('init', function()\n    box.schema.space.create('users')\n    box.space.users:create_index('primary',\n        { type = 'TREE', parts = {1, 'unsigned'}})\n\n    box.schema.space.create('sessions')\n    box.space.sessions:create_index('primary',\n        { type = 'HASH', parts = {1, 'string'}})\n\n     print('Hello, world!')\nend)\n\n-- Можем определять свои функции и вызывать их из кода\nfunction test()\n    print('test')\n    return 'test'\nend\n\n-- Например ID сессии генерируется здесь\nfunction new_session(user_data)\n    print('received data', user_data)\n    local random_number\n    local session_id\n    session_id = \"\"\n    for x = 1,64,1 do\n        random_number = math.random(65, 90)\n        session_id = session_id .. string.char(random_number)\n    end\n\n    box.space.sessions:insert{session_id, user_data}\n\n    return session_id\nend\n\nfunction check_session(session_id)\n    local session_id = box.space.sessions:select{session_id}[1]\n    print('found session', session_id)\n    return session_id\nend\n"
  },
  {
    "path": "6-databases/13_tarantool_simple/main.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"math/rand\"\n\n\t\"github.com/tarantool/go-tarantool/v2\"\n)\n\n/*\n\ts = box.schema.space.create('users')\n\ts:format({{name = 'id', type = 'unsigned'},{name = 'name', type = 'string'},{name = 'age', type = 'unsigned'}})\n\ts:create_index('primary', {type = 'hash', parts = {'id'}})\n*/\n\nfunc main() {\n\tctx := context.Background()\n\n\tdialer := tarantool.NetDialer{Address: \"127.0.0.1:3301\", User: \"guest\"}\n\n\tconn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{})\n\tif err != nil {\n\t\tfmt.Println(\"baa: Connection refused:\", err)\n\t\treturn\n\t}\n\n\tresp, err := conn.Do(\n\t\ttarantool.NewInsertRequest(\"users\").Tuple([]any{rand.Int(), fmt.Sprintf(\"user%d\", rand.Int()), 2019}),\n\t).Get()\n\tif err != nil {\n\t\tfmt.Println(\"Error\", err)\n\t}\n\n\titems := make([]any, 0)\n\terr = conn.Do(\n\t\ttarantool.NewSelectRequest(\"users\").Index(\"primary\").Offset(0).Limit(100).Iterator(tarantool.IterAll).Key([]any{uint(1)}),\n\t).GetTyped(&items)\n\tif err != nil {\n\t\tfmt.Println(\"Error\", err)\n\t\treturn\n\t}\n\n\tfor _, item := range items {\n\t\tfmt.Println(item)\n\t}\n\n\tresp, err = conn.Do(\n\t\ttarantool.NewEvalRequest(\"return test()\"),\n\t).Get()\n\tif err != nil {\n\t\tfmt.Println(\"Error\", err)\n\t\treturn\n\t}\n\n\tfmt.Println(resp)\n}\n"
  },
  {
    "path": "6-databases/14_tarantool/main.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/tarantool/go-tarantool/v2\"\n)\n\nvar (\n\ttarantoolAddr = flag.String(\"addr\", \"127.0.0.1:3301\", \"tarantool addr\")\n\n\tsessManager *SessionManager\n\n\tusers = map[string]string{\n\t\t\"a.sulaev\":       \"golang\",\n\t\t\"dmitrydorofeev\": \"test\",\n\t\t\"romanov.vasily\": \"100500\",\n\t\t\"anton.chumakov\": \"amogus\",\n\t}\n)\n\nfunc checkSession(r *http.Request) (*Session, error) {\n\tcookieSessionID, err := r.Cookie(\"session_id\")\n\tif errors.Is(err, http.ErrNoCookie) {\n\t\treturn nil, nil\n\t} else if err != nil {\n\t\treturn nil, err\n\t}\n\n\tsess, err := sessManager.Check(&SessionID{\n\t\tID: cookieSessionID.Value,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn sess, nil\n}\n\nfunc innerPage(w http.ResponseWriter, r *http.Request) {\n\tsess, err := checkSession(r)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif sess == nil {\n\t\tw.Write(loginFormTmpl)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"text/html\")\n\tfmt.Fprintln(w, \"Welcome, \"+sess.Login+\" <br />\")\n\tfmt.Fprintln(w, \"Session ua: \"+sess.Useragent+\" <br />\")\n\tfmt.Fprintln(w, `<a href=\"/logout\">logout</a>`)\n}\n\nfunc loginPage(w http.ResponseWriter, r *http.Request) {\n\tinputLogin := r.FormValue(\"login\")\n\tinputPass := r.FormValue(\"password\")\n\texpiration := time.Now().Add(24 * time.Hour)\n\n\tpass, exist := users[inputLogin]\n\tif !exist || pass != inputPass {\n\t\tw.WriteHeader(http.StatusUnauthorized)\n\t\tw.Write([]byte(\"wrong credentials\"))\n\t\treturn\n\t}\n\n\tsess, err := sessManager.Create(&Session{\n\t\tLogin:     inputLogin,\n\t\tUseragent: r.UserAgent(),\n\t})\n\tif err != nil {\n\t\tlog.Printf(\"cannot create session: %s\", err)\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   sess.ID,\n\t\tExpires: expiration,\n\t}\n\thttp.SetCookie(w, &cookie)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc main() {\n\tflag.Parse()\n\n\tvar err error\n\n\tctx := context.Background()\n\tdialer := tarantool.NetDialer{Address: *tarantoolAddr, User: \"guest\"}\n\n\ttConn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{})\n\tif err != nil {\n\t\tlog.Fatalf(\"cant connect to tarantool: %s\\n\", err)\n\t}\n\n\tsessManager = NewSessionManager(tConn)\n\n\thttp.HandleFunc(\"/\", innerPage)\n\thttp.HandleFunc(\"/login\", loginPage)\n\thttp.HandleFunc(\"/logout\", logoutPage)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\nfunc logoutPage(w http.ResponseWriter, r *http.Request) {\n\tsession, err := r.Cookie(\"session_id\")\n\tif errors.Is(err, http.ErrNoCookie) {\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t\treturn\n\t} else if err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tsessManager.Delete(&SessionID{\n\t\tID: session.Value,\n\t})\n\n\tsession.Expires = time.Now().AddDate(0, 0, -1)\n\thttp.SetCookie(w, session)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nvar loginFormTmpl = []byte(`\n\t<html>\n\t\t<body>\n\t\t<form action=\"/login\" method=\"post\">\n\t\t\tLogin: <input type=\"text\" name=\"login\">\n\t\t\tPassword: <input type=\"password\" name=\"password\">\n\t\t\t<input type=\"submit\" value=\"Login\">\n\t\t</form>\n\t\t</body>\n\t</html>\n\t`)\n"
  },
  {
    "path": "6-databases/14_tarantool/session.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/tarantool/go-tarantool/v2\"\n)\n\ntype Session struct {\n\tLogin     string\n\tUseragent string\n}\n\ntype SessionID struct {\n\tID string\n}\n\ntype SessionManager struct {\n\ttConn *tarantool.Connection\n}\n\nfunc NewSessionManager(conn *tarantool.Connection) *SessionManager {\n\treturn &SessionManager{\n\t\ttConn: conn,\n\t}\n}\n\nfunc (sm *SessionManager) Create(in *Session) (*SessionID, error) {\n\tdataSerialized, err := json.Marshal(in)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"data serialization failed: %s\", err)\n\t}\n\n\tdataStr := string(dataSerialized)\n\tlog.Printf(\"try to save data: %s\", dataStr)\n\n\tresp, err := sm.tConn.Do(\n\t\ttarantool.NewEvalRequest(\"return new_session(...)\").Args([]interface{}{dataStr}),\n\t).Get()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error while calling function: %s\", err)\n\t}\n\n\tdata := resp[0]\n\tif id, ok := data.(string); ok {\n\t\treturn &SessionID{id}, nil\n\t}\n\n\treturn nil, fmt.Errorf(\"cannot cast into int\")\n}\n\nfunc (sm *SessionManager) Check(in *SessionID) (*Session, error) {\n\tresp, err := sm.tConn.Do(\n\t\ttarantool.NewCallRequest(\"check_session\").Args([]interface{}{in.ID}),\n\t).Get()\n\tif err != nil {\n\t\tfmt.Println(\"cannot check session\", err)\n\t\treturn nil, err\n\t}\n\n\tdata := resp[0]\n\tif data == nil {\n\t\treturn &Session{}, nil\n\t}\n\tsessionDataSlice, ok := data.([]interface{})\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"cannot cast data: %v\", sessionDataSlice)\n\t}\n\n\tif sessionDataSlice[1] == nil {\n\t\treturn nil, nil\n\t}\n\n\tsessionData, ok := sessionDataSlice[1].(string)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"cannot cast data: %v\", sessionDataSlice[1])\n\t}\n\n\tsess := &Session{}\n\terr = json.Unmarshal([]byte(sessionData), sess)\n\tif err != nil {\n\t\tlog.Printf(\"cant unpack session data(%s): %v\\n\", sessionData, err)\n\t\treturn nil, nil\n\t}\n\treturn sess, nil\n}\n\nfunc (sm *SessionManager) Delete(in *SessionID) {\n\t// mkey := \"sessions:\" + in.ID\n\t// _, err := redis.Int(sm.redisConn.Do(\"DEL\", mkey))\n\t// if err != nil {\n\t// \tlog.Println(\"redis error:\", err)\n\t// }\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/cmd/crudapp/main.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"html/template\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/go-park-mail-ru/lectures/6-databases/crudapp_mongo/pkg/handlers\"\n\t\"github.com/go-park-mail-ru/lectures/6-databases/crudapp_mongo/pkg/items\"\n\t\"github.com/go-park-mail-ru/lectures/6-databases/crudapp_mongo/pkg/middleware\"\n\t\"github.com/go-park-mail-ru/lectures/6-databases/crudapp_mongo/pkg/session\"\n\t\"github.com/go-park-mail-ru/lectures/6-databases/crudapp_mongo/pkg/user\"\n\n\t\"github.com/gorilla/mux\"\n\t\"go.mongodb.org/mongo-driver/mongo\"\n\t\"go.mongodb.org/mongo-driver/mongo/options\"\n\t\"go.mongodb.org/mongo-driver/mongo/readpref\"\n\t\"go.uber.org/zap\"\n)\n\nfunc getMongo(cfg string) *mongo.Client {\n\tctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\n\tdefer cancel()\n\tclient, err := mongo.Connect(ctx, options.Client().ApplyURI(cfg))\n\tif err != nil {\n\t\tlog.Fatalln(\"cant connect to mongo\", err)\n\t}\n\terr = client.Ping(ctx, readpref.Primary())\n\tif err != nil {\n\t\tlog.Fatalln(\"cant ping mongo\", err)\n\t}\n\treturn client\n}\n\nfunc main() {\n\n\t// -----\n\n\ttemplates := template.Must(template.ParseGlob(\"./templates/*\"))\n\n\tsm := session.NewSessionsMem()\n\tzapLogger, _ := zap.NewProduction()\n\tdefer zapLogger.Sync() // flushes buffer, if any\n\tlogger := zapLogger.Sugar()\n\n\t// dbMSSQL := sql.Open(...)\n\n\tuserRepo := user.NewUserRepo()\n\n\tmongoClient := getMongo(\"mongodb://localhost:27017\")\n\titemsRepo := items.NewMongoRepository(mongoClient.Database(\"vkbmstu\").Collection(\"items\"))\n\n\tuserHandler := &handlers.UserHandler{\n\t\tTmpl:     templates,\n\t\tUserRepo: userRepo,\n\t\tLogger:   logger,\n\t\tSessions: sm,\n\t}\n\n\thandlers := &handlers.ItemsHandler{\n\t\tTmpl:      templates,\n\t\tLogger:    logger,\n\t\tItemsRepo: itemsRepo,\n\t}\n\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/\", userHandler.Index).Methods(\"GET\")\n\tr.HandleFunc(\"/login\", userHandler.Login).Methods(\"POST\")\n\tr.HandleFunc(\"/logout\", userHandler.Logout).Methods(\"POST\")\n\n\tr.HandleFunc(\"/items\", handlers.List).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.AddForm).Methods(\"GET\")\n\tr.HandleFunc(\"/items/new\", handlers.Add).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Edit).Methods(\"GET\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Update).Methods(\"POST\")\n\tr.HandleFunc(\"/items/{id}\", handlers.Delete).Methods(\"DELETE\")\n\n\tmux := middleware.Auth(sm, r)\n\tmux = middleware.AccessLog(logger, mux)\n\tmux = middleware.Panic(mux)\n\n\taddr := \":8080\"\n\tlogger.Infow(\"starting server\",\n\t\t\"type\", \"START\",\n\t\t\"addr\", addr,\n\t)\n\thttp.ListenAndServe(addr, mux)\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/file_tree.txt",
    "content": ".\n├── bin\n├── cmd\n│   └── crudapp\n│       └── main.go\n├── cover.html\n├── cover.out\n├── file_tree.txt\n├── go.mod\n├── go.sum\n├── pkg\n│   ├── handlers\n│   │   ├── cover.out\n│   │   ├── handler.html\n│   │   ├── items.go\n│   │   ├── items_mock.go\n│   │   ├── items_test.go\n│   │   └── user.go\n│   ├── items\n│   │   ├── item.go\n│   │   ├── item_repo_test.go\n│   │   ├── repo_gorm.go\n│   │   ├── repo_mysql.go\n│   │   ├── repo_pgx.go\n│   │   └── repo_sqlx.go\n│   ├── middleware\n│   │   ├── accesslog.go\n│   │   ├── auth.go\n│   │   └── panic.go\n│   ├── session\n│   │   ├── manager.go\n│   │   └── session.go\n│   └── user\n│       └── user.go\n├── readme.md\n└── templates\n    ├── create.html\n    ├── edit.html\n    ├── index.html\n    └── login.html\n\n10 directories, 29 files\n"
  },
  {
    "path": "6-databases/crudapp_mongo/pkg/handlers/items.go",
    "content": "package handlers\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"html/template\"\n\t\"net/http\"\n\n\t\"github.com/go-park-mail-ru/lectures/6-databases/crudapp_mongo/pkg/items\"\n\t\"github.com/go-park-mail-ru/lectures/6-databases/crudapp_mongo/pkg/session\"\n\n\t\"github.com/gorilla/mux\"\n\t\"github.com/gorilla/schema\"\n\t\"go.mongodb.org/mongo-driver/bson/primitive\"\n\t\"go.uber.org/zap\"\n)\n\ntype ItemRepositoryInterface interface {\n\tGetAll() ([]*items.Item, error)\n\tGetByID(string) (*items.Item, error)\n\tAdd(context.Context, *items.Item) (string, error)\n\tUpdate(*items.Item) (int64, error)\n\tDelete(string) (int64, error)\n}\n\ntype ItemsHandler struct {\n\tTmpl      *template.Template\n\tItemsRepo ItemRepositoryInterface\n\tLogger    *zap.SugaredLogger\n}\n\nfunc (h *ItemsHandler) List(w http.ResponseWriter, r *http.Request) {\n\telems, err := h.ItemsRepo.GetAll()\n\tif err != nil {\n\t\th.Logger.Error(\"GetAll err\", err)\n\t\thttp.Error(w, `DB err`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"index.html\", struct {\n\t\tItems []*items.Item\n\t}{\n\t\tItems: elems,\n\t})\n\tif err != nil {\n\t\th.Logger.Error(\"ExecuteTemplate err\", err)\n\t\thttp.Error(w, `Template errror`, http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *ItemsHandler) AddForm(w http.ResponseWriter, r *http.Request) {\n\terr := h.Tmpl.ExecuteTemplate(w, \"create.html\", nil)\n\tif err != nil {\n\t\th.Logger.Error(\"ExecuteTemplate err\", err)\n\t\thttp.Error(w, `Template errror`, http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\n// type ItemsAddInput struct {\n\n// }\n\nfunc (h *ItemsHandler) Add(w http.ResponseWriter, r *http.Request) {\n\tr.ParseForm()\n\titem := new(items.Item)\n\tdecoder := schema.NewDecoder()\n\tdecoder.IgnoreUnknownKeys(true)\n\terr := decoder.Decode(item, r.PostForm)\n\tif err != nil {\n\t\th.Logger.Error(\"Form err\", err)\n\t\thttp.Error(w, `Bad form`, http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tctx := r.Context()\n\tsess, _ := session.SessionFromContext(ctx)\n\t// item.UserID = sess.UserID\n\n\tlastID, err := h.ItemsRepo.Add(ctx, item)\n\tif err != nil {\n\t\th.Logger.Error(\"Db err\", err)\n\t\thttp.Error(w, `DB err`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\th.Logger.Infof(\"Insert with id LastInsertId: %v %v\", lastID, sess)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *ItemsHandler) Edit(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid := vars[\"id\"]\n\tif _, err := primitive.ObjectIDFromHex(id); err != nil {\n\t\thttp.Error(w, `{\"error\": \"bad id\"}`, http.StatusBadGateway)\n\t\treturn\n\t}\n\n\titem, err := h.ItemsRepo.GetByID(id)\n\tif err != nil {\n\t\th.Logger.Error(\"Db err\", err)\n\t\thttp.Error(w, `DB err`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif item == nil {\n\t\thttp.Error(w, `no item`, http.StatusNotFound)\n\t\treturn\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"edit.html\", item)\n\tif err != nil {\n\t\th.Logger.Error(\"ExecuteTemplate err\", err)\n\t\thttp.Error(w, `Template errror`, http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *ItemsHandler) Update(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid, err := primitive.ObjectIDFromHex(vars[\"id\"])\n\tif err != nil {\n\t\thttp.Error(w, `{\"error\": \"bad id\"}`, http.StatusBadGateway)\n\t\treturn\n\t}\n\n\tr.ParseForm()\n\titem := new(items.Item)\n\tdecoder := schema.NewDecoder()\n\tdecoder.IgnoreUnknownKeys(true)\n\terr = decoder.Decode(item, r.PostForm)\n\tif err != nil {\n\t\th.Logger.Error(\"Form err\", err)\n\t\thttp.Error(w, `Bad form`, http.StatusBadRequest)\n\t\treturn\n\t}\n\titem.ID = id\n\n\tsess, _ := session.SessionFromContext(r.Context())\n\titem.SetUpdated(sess.UserID)\n\n\tok, err := h.ItemsRepo.Update(item)\n\tif err != nil {\n\t\th.Logger.Error(\"Db err\", err)\n\t\thttp.Error(w, `db error`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\th.Logger.Infof(\"update: %v %v\", item, ok)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc (h *ItemsHandler) Delete(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\tid := vars[\"id\"]\n\tif _, err := primitive.ObjectIDFromHex(id); err != nil {\n\t\thttp.Error(w, `{\"error\": \"bad id\"}`, http.StatusBadGateway)\n\t\treturn\n\t}\n\n\taffected, err := h.ItemsRepo.Delete(id)\n\tif err != nil {\n\t\th.Logger.Error(\"Db err\", err)\n\t\thttp.Error(w, `{\"error\": \"db error\"}`, http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-type\", \"application/json\")\n\trespJSON, _ := json.Marshal(map[string]int64{\n\t\t\"updated\": affected,\n\t})\n\tw.Write(respJSON)\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/pkg/handlers/items_mock.go",
    "content": "// Code generated by MockGen. DO NOT EDIT.\n// Source: items.go\n\n// Package handlers is a generated GoMock package.\npackage handlers\n\nimport (\n\tcontext \"context\"\n\treflect \"reflect\"\n\n\titems \"github.com/go-park-mail-ru/lectures/6-databases/crudapp_mongo/pkg/items\"\n\tgomock \"github.com/golang/mock/gomock\"\n)\n\n// MockItemRepositoryInterface is a mock of ItemRepositoryInterface interface.\ntype MockItemRepositoryInterface struct {\n\tctrl     *gomock.Controller\n\trecorder *MockItemRepositoryInterfaceMockRecorder\n}\n\n// MockItemRepositoryInterfaceMockRecorder is the mock recorder for MockItemRepositoryInterface.\ntype MockItemRepositoryInterfaceMockRecorder struct {\n\tmock *MockItemRepositoryInterface\n}\n\n// NewMockItemRepositoryInterface creates a new mock instance.\nfunc NewMockItemRepositoryInterface(ctrl *gomock.Controller) *MockItemRepositoryInterface {\n\tmock := &MockItemRepositoryInterface{ctrl: ctrl}\n\tmock.recorder = &MockItemRepositoryInterfaceMockRecorder{mock}\n\treturn mock\n}\n\n// EXPECT returns an object that allows the caller to indicate expected use.\nfunc (m *MockItemRepositoryInterface) EXPECT() *MockItemRepositoryInterfaceMockRecorder {\n\treturn m.recorder\n}\n\n// Add mocks base method.\nfunc (m *MockItemRepositoryInterface) Add(arg0 context.Context, arg1 *items.Item) (string, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"Add\", arg0, arg1)\n\tret0, _ := ret[0].(string)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// Add indicates an expected call of Add.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) Add(arg0, arg1 interface{}) *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"Add\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).Add), arg0, arg1)\n}\n\n// Delete mocks base method.\nfunc (m *MockItemRepositoryInterface) Delete(arg0 string) (int64, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"Delete\", arg0)\n\tret0, _ := ret[0].(int64)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// Delete indicates an expected call of Delete.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) Delete(arg0 interface{}) *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"Delete\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).Delete), arg0)\n}\n\n// GetAll mocks base method.\nfunc (m *MockItemRepositoryInterface) GetAll() ([]*items.Item, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"GetAll\")\n\tret0, _ := ret[0].([]*items.Item)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// GetAll indicates an expected call of GetAll.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) GetAll() *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"GetAll\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).GetAll))\n}\n\n// GetByID mocks base method.\nfunc (m *MockItemRepositoryInterface) GetByID(arg0 string) (*items.Item, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"GetByID\", arg0)\n\tret0, _ := ret[0].(*items.Item)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// GetByID indicates an expected call of GetByID.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) GetByID(arg0 interface{}) *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"GetByID\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).GetByID), arg0)\n}\n\n// Update mocks base method.\nfunc (m *MockItemRepositoryInterface) Update(arg0 *items.Item) (int64, error) {\n\tm.ctrl.T.Helper()\n\tret := m.ctrl.Call(m, \"Update\", arg0)\n\tret0, _ := ret[0].(int64)\n\tret1, _ := ret[1].(error)\n\treturn ret0, ret1\n}\n\n// Update indicates an expected call of Update.\nfunc (mr *MockItemRepositoryInterfaceMockRecorder) Update(arg0 interface{}) *gomock.Call {\n\tmr.mock.ctrl.T.Helper()\n\treturn mr.mock.ctrl.RecordCallWithMethodType(mr.mock, \"Update\", reflect.TypeOf((*MockItemRepositoryInterface)(nil).Update), arg0)\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/pkg/handlers/items_test.go",
    "content": "package handlers\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"io/ioutil\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\n\t\"github.com/go-park-mail-ru/lectures/6-databases/crudapp_mongo/pkg/items\"\n\t\"go.mongodb.org/mongo-driver/bson/primitive\"\n\n\t\"github.com/golang/mock/gomock\"\n\t\"go.uber.org/zap\"\n)\n\n/*\n\nrepo\n\tdb -> mock\n\nhandler\n\trepo -> mock\n\n\n*/\n\nfunc TestItemsHandlerList(t *testing.T) {\n\n\t// мы передаём t сюда, это надо чтобы получить корректное сообщение если тесты не пройдут\n\tctrl := gomock.NewController(t)\n\n\t// Finish сравнит последовательсноть вызовов и выведет ошибку если последовательность другая\n\tdefer ctrl.Finish()\n\n\tst := NewMockItemRepositoryInterface(ctrl)\n\tservice := &ItemsHandler{\n\t\tItemsRepo: st,\n\t\tLogger:    zap.NewNop().Sugar(), // не пишет логи\n\t\tTmpl:      template.Must(template.ParseGlob(\"../../templates/*\")),\n\t}\n\n\tresultItems := []*items.Item{\n\t\t{ID: primitive.NewObjectID(), Title: \"database/sql\"},\n\t}\n\n\t// тут мы записываем последовтаельность вызовов и результат\n\tst.EXPECT().GetAll().Return(resultItems, nil)\n\n\treq := httptest.NewRequest(\"GET\", \"/\", nil)\n\tw := httptest.NewRecorder()\n\n\tservice.List(w, req)\n\n\tresp := w.Result()\n\tbody, _ := ioutil.ReadAll(resp.Body)\n\n\timg := `database/sql`\n\tif !bytes.Contains(body, []byte(img)) {\n\t\tt.Errorf(\"no text found\")\n\t\treturn\n\t}\n\n\t// GetPhotos error\n\t// тут мы записываем последовтаельность вызовов и результат\n\tst.EXPECT().GetAll().Return(nil, fmt.Errorf(\"no results\"))\n\n\treq = httptest.NewRequest(\"GET\", \"/\", nil)\n\tw = httptest.NewRecorder()\n\n\tservice.List(w, req)\n\n\tresp = w.Result()\n\tif resp.StatusCode != 500 {\n\t\tt.Errorf(\"expected resp status 500, got %d\", resp.StatusCode)\n\t\treturn\n\t}\n\n\t// template expand error\n\tservice.Tmpl, _ = template.New(\"tmplError\").Parse(\"{{.NotExist}}\")\n\n\tst.EXPECT().GetAll().Return(resultItems, nil)\n\n\treq = httptest.NewRequest(\"GET\", \"/\", nil)\n\tw = httptest.NewRecorder()\n\n\tservice.List(w, req)\n\n\tresp = w.Result()\n\tif resp.StatusCode != 500 {\n\t\tt.Errorf(\"expected resp status 500, got %d\", resp.StatusCode)\n\t\treturn\n\t}\n\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/pkg/handlers/user.go",
    "content": "package handlers\n\nimport (\n\t\"html/template\"\n\t\"net/http\"\n\n\t\"github.com/go-park-mail-ru/lectures/6-databases/crudapp_mongo/pkg/session\"\n\t\"github.com/go-park-mail-ru/lectures/6-databases/crudapp_mongo/pkg/user\"\n\n\t\"go.uber.org/zap\"\n)\n\ntype UserHandler struct {\n\tTmpl     *template.Template\n\tLogger   *zap.SugaredLogger\n\tUserRepo *user.UserRepo\n\tSessions *session.SessionsManager\n}\n\nfunc (h *UserHandler) Index(w http.ResponseWriter, r *http.Request) {\n\t_, err := session.SessionFromContext(r.Context())\n\tif err == nil {\n\t\thttp.Redirect(w, r, \"/items\", 302)\n\t\treturn\n\t}\n\n\terr = h.Tmpl.ExecuteTemplate(w, \"login.html\", nil)\n\tif err != nil {\n\t\thttp.Error(w, `Template errror`, http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (h *UserHandler) Login(w http.ResponseWriter, r *http.Request) {\n\tu, err := h.UserRepo.Authorize(r.FormValue(\"login\"), r.FormValue(\"password\"))\n\tif err == user.ErrNoUser {\n\t\thttp.Error(w, `no user`, http.StatusBadRequest)\n\t\treturn\n\t}\n\tif err == user.ErrBadPass {\n\t\thttp.Error(w, `bad pass`, http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tsess, _ := h.Sessions.Create(w, u.ID)\n\th.Logger.Infof(\"created session for %v\", sess.UserID)\n\thttp.Redirect(w, r, \"/\", 302)\n}\n\nfunc (h *UserHandler) Logout(w http.ResponseWriter, r *http.Request) {\n\th.Sessions.DestroyCurrent(w, r)\n\thttp.Redirect(w, r, \"/\", 302)\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/pkg/items/item.go",
    "content": "package items\n\nimport (\n\t\"strconv\"\n\n\t\"go.mongodb.org/mongo-driver/bson/primitive\"\n)\n\ntype Item struct {\n\tID          primitive.ObjectID `json:\"id\" bson:\"_id\"`\n\tTitle       string             `json:\"title\" bson:\"title\"`\n\tDescription string             `json:\"description\" bson:\"description\"`\n\tUpdated     string             `json:\"updated\" bson:\"updated\"`\n}\n\n// позволяет items handlers не импортировать sql\nfunc (it *Item) SetUpdated(val uint32) {\n\tit.Updated = strconv.Itoa(int(val))\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/pkg/items/repo_mongo.go",
    "content": "package items\n\nimport (\n\t\"context\"\n\n\t\"go.mongodb.org/mongo-driver/bson\"\n\t\"go.mongodb.org/mongo-driver/bson/primitive\"\n\t\"go.mongodb.org/mongo-driver/mongo\"\n)\n\ntype RepoMongo struct {\n\tColl *mongo.Collection\n}\n\nfunc NewMongoRepository(coll *mongo.Collection) *RepoMongo {\n\treturn &RepoMongo{Coll: coll}\n}\n\nfunc (repo *RepoMongo) GetAll() ([]*Item, error) {\n\titems := make([]*Item, 0, 10)\n\tres, err := repo.Coll.Find(context.Background(), bson.M{})\n\terr = res.All(context.Background(), &items)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn items, nil\n}\n\nfunc (repo *RepoMongo) GetByID(id string) (*Item, error) {\n\tpost := &Item{}\n\toid, _ := primitive.ObjectIDFromHex(id)\n\terr := repo.Coll.FindOne(context.Background(), bson.M{\"_id\": oid}).Decode(&post)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn post, nil\n}\n\nfunc (repo *RepoMongo) Add(ctx context.Context, elem *Item) (string, error) {\n\telem.ID = primitive.NewObjectID()\n\t_, err := repo.Coll.InsertOne(ctx, elem)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\t// log.Println(res, elem)\n\treturn elem.ID.Hex(), nil\n}\n\nfunc (repo *RepoMongo) Update(elem *Item) (int64, error) {\n\n\tres, err := repo.Coll.UpdateOne(context.Background(),\n\t\tbson.M{\"_id\": elem.ID},\n\t\tbson.M{\n\t\t\t\"$set\": bson.M{\n\t\t\t\t\"title\":       elem.Title,\n\t\t\t\t\"description\": elem.Description,\n\t\t\t\t\"updated\":     \"rvasily\",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn res.ModifiedCount, nil\n}\n\nfunc (repo *RepoMongo) Delete(id string) (int64, error) {\n\toid, _ := primitive.ObjectIDFromHex(id)\n\tres, err := repo.Coll.DeleteOne(context.Background(), bson.M{\"_id\": oid})\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn res.DeletedCount, nil\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/pkg/middleware/accesslog.go",
    "content": "package middleware\n\nimport (\n\t// \"fmt\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"go.uber.org/zap\"\n)\n\nfunc AccessLog(logger *zap.SugaredLogger, next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t// fmt.Println(\"access log middleware\")\n\t\tstart := time.Now()\n\t\tnext.ServeHTTP(w, r)\n\t\tlogger.Infow(\"New request\",\n\t\t\t\"method\", r.Method,\n\t\t\t\"remote_addr\", r.RemoteAddr,\n\t\t\t\"url\", r.URL.Path,\n\t\t\t\"time\", time.Since(start),\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/pkg/middleware/auth.go",
    "content": "package middleware\n\nimport (\n\t\"context\"\n\t// \"fmt\"\n\t\"net/http\"\n\n\t\"github.com/go-park-mail-ru/lectures/6-databases/crudapp_mongo/pkg/session\"\n)\n\nvar (\n\tnoAuthUrls = map[string]struct{}{\n\t\t\"/login\": struct{}{},\n\t}\n\tnoSessUrls = map[string]struct{}{\n\t\t\"/\": struct{}{},\n\t}\n)\n\nfunc Auth(sm *session.SessionsManager, next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t// fmt.Println(\"auth middleware\")\n\t\tif _, ok := noAuthUrls[r.URL.Path]; ok {\n\t\t\tnext.ServeHTTP(w, r)\n\t\t\treturn\n\t\t}\n\t\tsess, err := sm.Check(r)\n\t\t_, canbeWithouthSess := noSessUrls[r.URL.Path]\n\t\tif err != nil && !canbeWithouthSess {\n\t\t\t// fmt.Println(\"no auth\")\n\t\t\thttp.Redirect(w, r, \"/\", 302)\n\t\t\treturn\n\t\t}\n\t\tctx := context.WithValue(r.Context(), session.SessionKey, sess)\n\t\tnext.ServeHTTP(w, r.WithContext(ctx))\n\t})\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/pkg/middleware/panic.go",
    "content": "package middleware\n\nimport (\n\t\"net/http\"\n)\n\nfunc Panic(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t// fmt.Println(\"panicMiddleware\", r.URL.Path)\n\t\tdefer func() {\n\t\t\tif err := recover(); err != nil {\n\t\t\t\t// fmt.Println(\"recovered\", err)\n\t\t\t\thttp.Error(w, \"Internal server error\", 500)\n\t\t\t}\n\t\t}()\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/pkg/session/manager.go",
    "content": "package session\n\nimport (\n\t\"net/http\"\n\t\"sync\"\n\t\"time\"\n)\n\ntype SessionsManager struct {\n\tdata map[string]*Session\n\tmu   *sync.RWMutex\n}\n\nfunc NewSessionsMem() *SessionsManager {\n\treturn &SessionsManager{\n\t\tdata: make(map[string]*Session, 10),\n\t\tmu:   &sync.RWMutex{},\n\t}\n}\n\nfunc (sm *SessionsManager) Check(r *http.Request) (*Session, error) {\n\tsessionCookie, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\treturn nil, ErrNoAuth\n\t}\n\n\tsm.mu.RLock()\n\tsess, ok := sm.data[sessionCookie.Value]\n\tsm.mu.RUnlock()\n\n\tif !ok {\n\t\treturn nil, ErrNoAuth\n\t}\n\n\treturn sess, nil\n}\n\nfunc (sm *SessionsManager) Create(w http.ResponseWriter, userID uint32) (*Session, error) {\n\tsess := NewSession(userID)\n\n\tsm.mu.Lock()\n\tsm.data[sess.ID] = sess\n\tsm.mu.Unlock()\n\n\tcookie := &http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   sess.ID,\n\t\tExpires: time.Now().Add(90 * 24 * time.Hour),\n\t\tPath:    \"/\",\n\t}\n\thttp.SetCookie(w, cookie)\n\treturn sess, nil\n}\n\nfunc (sm *SessionsManager) DestroyCurrent(w http.ResponseWriter, r *http.Request) error {\n\tsess, err := SessionFromContext(r.Context())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tsm.mu.Lock()\n\tdelete(sm.data, sess.ID)\n\tsm.mu.Unlock()\n\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tExpires: time.Now().AddDate(0, 0, -1),\n\t\tPath:    \"/\",\n\t}\n\thttp.SetCookie(w, &cookie)\n\treturn nil\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/pkg/session/session.go",
    "content": "package session\n\nimport (\n\t\"context\"\n\t\"crypto/rand\"\n\t\"errors\"\n\t\"fmt\"\n)\n\ntype Session struct {\n\tID     string\n\tUserID uint32\n}\n\nfunc NewSession(userID uint32) *Session {\n\t// лучше генерировать из заданного алфавита, но так писать меньше и для учебного примера ОК\n\trandID := make([]byte, 16)\n\trand.Read(randID)\n\n\treturn &Session{\n\t\tID:     fmt.Sprintf(\"%x\", randID),\n\t\tUserID: userID,\n\t}\n}\n\nvar (\n\tErrNoAuth = errors.New(\"No session found\")\n)\n\ntype sessKey string\n\nvar SessionKey sessKey = \"sessionKey\"\n\nfunc SessionFromContext(ctx context.Context) (*Session, error) {\n\tsess, ok := ctx.Value(SessionKey).(*Session)\n\tif !ok || sess == nil {\n\t\treturn nil, ErrNoAuth\n\t}\n\treturn sess, nil\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/pkg/user/user.go",
    "content": "package user\n\nimport \"errors\"\n\ntype User struct {\n\tID       uint32\n\tLogin    string\n\tpassword string\n}\n\ntype UserRepo struct {\n\tdata map[string]*User\n}\n\nfunc NewUserRepo() *UserRepo {\n\treturn &UserRepo{\n\t\tdata: map[string]*User{\n\t\t\t\"rvasily\": &User{\n\t\t\t\tID:       1,\n\t\t\t\tLogin:    \"rvasily\",\n\t\t\t\tpassword: \"love\",\n\t\t\t},\n\t\t},\n\t}\n}\n\nvar (\n\tErrNoUser  = errors.New(\"No user found\")\n\tErrBadPass = errors.New(\"Invald password\")\n)\n\nfunc (repo *UserRepo) Authorize(login, pass string) (*User, error) {\n\tu, ok := repo.data[login]\n\tif !ok {\n\t\treturn nil, ErrNoUser\n\t}\n\n\t// dont do this un production :)\n\tif u.password != pass {\n\t\treturn nil, ErrBadPass\n\t}\n\n\treturn u, nil\n}\n"
  },
  {
    "path": "6-databases/crudapp_mongo/readme.md",
    "content": "go mod init crudapp\n# go mod init github.com/rvasily/crudapp\ngo build\ngo mod download\ngo mod verify\ngo mod tidy\n\ngo build  -o ./bin/crudapp ./cmd/crudapp\ngo test -v -coverpkg=./... ./...\n\ngo mod vendor\ngo build -mod=vendor -o ./bin/myapp ./cmd/myapp\ngo test -v -mod=vendor -coverpkg=./... ./...\n\n----\n\ndocker-compose up\n\ngo test -v -coverprofile=cover.out -coverpkg=./... ./...\ngo tool cover -html=cover.out -o cover.html\n\n-----\n\nнаходять в папке pkg/handlers\nmockgen -source=items.go -destination=items_mock.go -package=handlers ItemRepositoryInterface\n\ngo test -v -run Handler -coverprofile=handler.out && go tool cover -html=handler.out -o handler.html && rm handler.out\n"
  },
  {
    "path": "6-databases/crudapp_mongo/templates/create.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/new\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/crudapp_mongo/templates/edit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\n    <div class=\"container\">\n      <h1>Edit item</h1>\n\n      <form method=\"post\" action=\"/items/{{.ID.Hex}}\">\n        <div class=\"form-group\">\n          <label for=\"title\">Title</label>\n          <input type=\"text\" class=\"form-control\" name=\"title\" id=\"title\" value=\"{{.Title}}\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"description\">Description</label>\n          <textarea class=\"form-control\" name=\"description\" id=\"description\" rows=\"3\">{{.Description}}</textarea>\n        </div>\n\n        <div class=\"form-group\">\n          <label>{{.Updated}}</label>\n        </div>\n\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/crudapp_mongo/templates/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\t<div class=\"container\">\n    <h1>Posts</h1>\n    <table class=\"table\">\n    <thead>\n      <tr>\n        <th>#</th>\n        <th>Title</th>\n        <th style=\"width:60px;\">Updated</th>\n        <th style=\"width:140px;\"><a href=\"/items/new\" class=\"btn btn-success\">New</a></th>\n      </tr>\n    </thead>\n    <tbody>\n    {{range .Items}}\n      <tr>\n        <td>{{.ID.Hex}}</td>\n        <td>{{.Title}}</td>\n        <td>{{.Updated}}</td>\n        <td>\n          <a href=\"/items/{{.ID.Hex}}\" class=\"btn btn-primary\">Edit</a>\n          <span data-id=\"{{.ID.Hex}}\" class=\"do-delete btn btn-danger\">Del</span>\n        </td>\n      </tr>\n\t\t{{end}}\n    </tbody>\n  </div>\n  \n  <script src=\"https://code.jquery.com/jquery-3.2.1.min.js\" crossorigin=\"anonymous\"></script>\n\n  <script type=\"text/javascript\">\n  $('.do-delete').click(function() {\n    if(!confirm(\"Are you sure?\")) {\n      return\n    }\n    $elem = $(this)\n    $.ajax({\n      url: '/items/' + $elem.data(\"id\"),\n      type: 'DELETE',\n      data: {},\n      success: function(resp) {\n        if(resp.updated) {\n          $elem.parent().parent().remove()\n        }\n      },\n    });\n  })\n  </script>\n  \n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/crudapp_mongo/templates/login.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Required meta tags -->\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n\n    <!-- Bootstrap CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n  </head>\n  <body>\n\t<div class=\"container\">\n        <h1>CrudAPP login</h1>\n        <form method=\"POST\" action=\"/login\">\n            <div class=\"form-group\">\n                <label for=\"login\">Login</label>\n                <input type=\"text\" class=\"form-control\" name=\"login\" id=\"login\" value=\"rvasily\">\n            </div>\n            <div class=\"form-group\">\n                <label for=\"password\">Password</label>\n                <input type=\"password\" class=\"form-control\" name=\"password\" id=\"password\" value=\"love\">\n            </div>\n            <button type=\"submit\" class=\"btn btn-primary\">Login</button>\n        </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "6-databases/readings_6.md",
    "content": "* http://www.vividcortex.com/hubfs/eBooks/The_Ultimate_Guide_To_Building_Database-Driven_Apps_with_Go.pdf - в удобной форме информация по основным аспектам работы с database/sql\n* https://golang.org/pkg/database/sql/ - собственно сам интерфейс к базе\n* https://github.com/golang/go/wiki/SQLDrivers - список поддерживаемых баз\n* https://github.com/golang/go/wiki/SQLInterface\n* https://github.com/DATA-DOG/go-sqlmock\n* http://www.alexedwards.net/blog/configuring-sqldb\n* http://go-database-sql.org/\n* https://astaxie.gitbooks.io/build-web-application-with-golang/\n* https://github.com/thewhitetulip/web-dev-golang-anti-textbook/\n* https://codegangsta.gitbooks.io/building-web-apps-with-go/content/\n* https://godoc.org/github.com/go-sql-driver/mysql\n* https://godoc.org/github.com/lib/pq\n* https://godoc.org/github.com/bradfitz/gomemcache/memcache\n* https://godoc.org/github.com/garyburd/redigo/redis\n* https://godoc.org/gopkg.in/mgo.v2\n* http://goinbigdata.com/how-to-build-microservice-with-mongodb-in-golang/\n* http://gorm.io/\n* http://motion-express.com/blog/gorm:-a-simple-guide-on-crud\n* https://godoc.org/github.com/jinzhu/gorm\n* https://habrahabr.ru/company/mailru/blog/266811/ - архи-полезная статья про устройство базы внутри\n* https://hackernoon.com/communicating-go-applications-through-redis-pub-sub-messaging-paradigm-df7317897b13\n* https://medium.com/@shijuvar/introducing-nats-to-go-developers-3cfcb98c21d0\n* https://medium.com/@shijuvar/building-distributed-systems-and-microservices-in-go-with-nats-streaming-d8b4baa633a2\n"
  },
  {
    "path": "6-databases/readme.md",
    "content": "docker run -p 3306:3306 --name some-mysql -e MYSQL_ROOT_PASSWORD=1234 -d mysql:5\ndocker run -p 6379:6379 --name some-redis -d redis\ndocker run -p 11211:11211 --name my-memcache -d memcached\ndocker run -p 5672:5672 -d --hostname my-rabbit --name some-rabbit rabbitmq:3\ndocker run -p 27017:27017 --name some-mongo -d mongo\n\ndocker build --tag=mytnt .\ndocker run --name mytnt-inst -p 3301:3301 -d mytnt\ndocker exec -t -i mytnt-inst console"
  },
  {
    "path": "6-databases/tcache/cache.go",
    "content": "package main\r\n\r\nimport (\r\n\t\"encoding/json\"\r\n\t\"fmt\"\r\n\t\"reflect\"\r\n\t\"strconv\"\r\n\t\"time\"\r\n\r\n\t\"github.com/bradfitz/gomemcache/memcache\"\r\n)\r\n\r\ntype CacheItem struct {\r\n\tData json.RawMessage\r\n\tTags map[string]int\r\n}\r\n\r\ntype CacheItemStore struct {\r\n\tData interface{}\r\n\tTags map[string]int\r\n}\r\n\r\ntype RebuildFunc func() (interface{}, []string, error)\r\n\r\ntype TCache struct {\r\n\t*memcache.Client\r\n}\r\n\r\nfunc (tc *TCache) TGet(\r\n\tmkey string,\r\n\tttl int32,\r\n\tin interface{},\r\n\trebuildCb RebuildFunc,\r\n) (err error) {\r\n\tinKind := reflect.ValueOf(in).Kind()\r\n\tif inKind != reflect.Ptr {\r\n\t\treturn fmt.Errorf(\"in must be ptr, got %s\", inKind)\r\n\t}\r\n\r\n\ttc.checkLock(mkey)\r\n\r\n\titemRaw, err := tc.Get(mkey)\r\n\tif err == memcache.ErrCacheMiss {\r\n\t\tfmt.Println(\"Record not found in memcache\")\r\n\t\treturn tc.rebuild(mkey, ttl, in, rebuildCb)\r\n\t} else if err != nil {\r\n\t\treturn err\r\n\t}\r\n\r\n\titem := &CacheItem{}\r\n\terr = json.Unmarshal(itemRaw.Value, &item)\r\n\tif err != nil {\r\n\t\treturn err\r\n\t}\r\n\r\n\ttagsValid, err := tc.isTagsValid(item.Tags)\r\n\tif err != nil {\r\n\t\treturn fmt.Errorf(\"isTagsValid error %s\", err)\r\n\t}\r\n\r\n\tif tagsValid {\r\n\t\terr = json.Unmarshal(item.Data, &in)\r\n\t\treturn err\r\n\t}\r\n\r\n\treturn tc.rebuild(mkey, ttl, in, rebuildCb)\r\n}\r\n\r\nfunc (tc *TCache) isTagsValid(itemTags map[string]int) (bool, error) {\r\n\ttags := make([]string, 0, len(itemTags))\r\n\tfor tagKey := range itemTags {\r\n\t\ttags = append(tags, tagKey)\r\n\t}\r\n\r\n\tcurr, err := tc.GetMulti(tags)\r\n\tif err != nil {\r\n\t\treturn false, err\r\n\t}\r\n\tcurrentTagsMap := make(map[string]int, len(curr))\r\n\tfor tagKey, tagItem := range curr {\r\n\t\ti, err := strconv.Atoi(string(tagItem.Value))\r\n\t\tif err != nil {\r\n\t\t\treturn false, err\r\n\t\t}\r\n\t\tcurrentTagsMap[tagKey] = i\r\n\t}\r\n\treturn reflect.DeepEqual(itemTags, currentTagsMap), nil\r\n}\r\n\r\nfunc (tc *TCache) rebuild(\r\n\tmkey string,\r\n\tttl int32,\r\n\tin interface{},\r\n\trebuildCb RebuildFunc,\r\n) error {\r\n\ttc.lockRebuild(mkey)\r\n\tdefer tc.unlockRebuild(mkey)\r\n\r\n\tresult, tags, err := rebuildCb()\r\n\r\n\t// ожидаем и возвращаем одинаковые типы\r\n\tif reflect.TypeOf(result) != reflect.TypeOf(in) {\r\n\t\treturn fmt.Errorf(\r\n\t\t\t\"data type mismatch, expected %s, got %s\", reflect.TypeOf(in),\r\n\t\t\treflect.TypeOf(result),\r\n\t\t)\r\n\t}\r\n\r\n\tcurrTags, err := tc.getCurrentItemTags(tags, ttl)\r\n\tif err != nil {\r\n\t\treturn err\r\n\t}\r\n\r\n\tcacheData := CacheItemStore{result, currTags}\r\n\trawData, err := json.Marshal(cacheData)\r\n\tif err != nil {\r\n\t\treturn err\r\n\t}\r\n\r\n\terr = tc.Set(&memcache.Item{\r\n\t\tKey:        mkey,\r\n\t\tValue:      rawData,\r\n\t\tExpiration: int32(ttl),\r\n\t})\r\n\r\n\tinVal := reflect.ValueOf(in)\r\n\tresultVal := reflect.ValueOf(result)\r\n\trv := reflect.Indirect(inVal)\r\n\trvpresult := reflect.Indirect(resultVal)\r\n\trv.Set(rvpresult) // *in = *result\r\n\r\n\treturn nil\r\n}\r\n\r\nfunc (tc *TCache) checkLock(mkey string) error {\r\n\tfor i := 0; i < 4; i++ {\r\n\t\t_, err := tc.Get(\"lock_\" + mkey)\r\n\t\tif err == memcache.ErrCacheMiss {\r\n\t\t\treturn nil\r\n\t\t}\r\n\t\tif err != nil {\r\n\t\t\treturn err\r\n\t\t}\r\n\t\ttime.Sleep(10 * time.Millisecond)\r\n\t}\r\n\treturn nil\r\n}\r\n\r\nfunc (tc *TCache) lockRebuild(mkey string) (bool, error) {\r\n\t// пытаемся взять лок на перестроение кеша\r\n\t// чтобы все не ломанулись его перестраивать\r\n\t// параметры надо тюнить\r\n\tlockKey := \"lock_\" + mkey\r\n\tlockAccuired := false\r\n\tfor i := 0; i < 4; i++ {\r\n\t\t// add добавляет запись если её ещё нету\r\n\t\terr := tc.Add(&memcache.Item{\r\n\t\t\tKey:        lockKey,\r\n\t\t\tValue:      []byte(\"1\"),\r\n\t\t\tExpiration: int32(3),\r\n\t\t})\r\n\r\n\t\tif err == memcache.ErrNotStored {\r\n\t\t\tfmt.Println(\"get lock try\", i)\r\n\t\t\ttime.Sleep(time.Millisecond * 10)\r\n\t\t\tcontinue\r\n\t\t} else if err != nil {\r\n\t\t\treturn false, err\r\n\t\t}\r\n\t\tlockAccuired = true\r\n\t\tbreak\r\n\t}\r\n\tif !lockAccuired {\r\n\t\treturn false, fmt.Errorf(\"Can't get lock\")\r\n\t}\r\n\treturn true, nil\r\n}\r\n\r\nfunc (tc *TCache) unlockRebuild(mkey string) {\r\n\ttc.Delete(\"lock_\" + mkey)\r\n}\r\n\r\nfunc (tc *TCache) getCurrentItemTags(tags []string, ttl int32) (map[string]int, error) {\r\n\tcurrTags, err := tc.GetMulti(tags)\r\n\tif err != nil {\r\n\t\treturn nil, err\r\n\t}\r\n\tresultTags := make(map[string]int, len(tags))\r\n\tnow := int(time.Now().Unix())\r\n\tnowBytes := []byte(fmt.Sprint(now))\r\n\r\n\tfor _, tagKey := range tags {\r\n\t\ttagItem, tagExist := currTags[tagKey]\r\n\t\tif !tagExist {\r\n\t\t\terr := tc.Set(&memcache.Item{\r\n\t\t\t\tKey:        tagKey,\r\n\t\t\t\tValue:      nowBytes,\r\n\t\t\t\tExpiration: int32(ttl),\r\n\t\t\t})\r\n\t\t\tif err != nil {\r\n\t\t\t\treturn nil, err\r\n\t\t\t}\r\n\t\t\tresultTags[tagKey] = now\r\n\t\t} else {\r\n\t\t\ti, err := strconv.Atoi(string(tagItem.Value))\r\n\t\t\tif err != nil {\r\n\t\t\t\treturn nil, err\r\n\t\t\t}\r\n\t\t\tresultTags[tagKey] = i\r\n\t\t}\r\n\t}\r\n\treturn resultTags, nil\r\n}\r\n"
  },
  {
    "path": "6-databases/tcache/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/bradfitz/gomemcache/memcache\"\n)\n\n/*\ntype TCache struct {\n\t*memcache.Client\n}\n*/\n\nfunc main() {\n\tMemcachedAddresses := []string{\"127.0.0.1:11211\"}\n\tmemcacheClient := memcache.New(MemcachedAddresses...)\n\n\ttc := &TCache{memcacheClient}\n\n\tmkey := \"habrposts\"\n\ttc.Delete(mkey)\n\n\trebuild := func() (interface{}, []string, error) {\n\t\thabrPosts, err := GetHabrPosts()\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\treturn habrPosts, []string{\"habrTag\", \"geektimes\"}, nil\n\t}\n\n\tfmt.Println(\"\\nTGet call #1\")\n\tposts := RSS{}\n\terr := tc.TGet(mkey, 30, &posts, rebuild)\n\tfmt.Println(\"#1\", len(posts.Items), \"err:\", err)\n\n\tfmt.Println(\"\\nTGet call #2\")\n\tposts = RSS{}\n\terr = tc.TGet(mkey, 30, &posts, rebuild)\n\tfmt.Println(\"#2\", len(posts.Items), \"err:\", err)\n\n\tfmt.Println(\"\\ninc tag habrTag\")\n\ttc.Increment(\"habrTag\", 1)\n\n\tgo func() {\n\t\t// time.Sleep(time.Millisecond)\n\t\tfmt.Println(\"\\nTGet call #async\")\n\t\tposts = RSS{}\n\t\terr = tc.TGet(mkey, 30, &posts, rebuild)\n\t\tfmt.Println(\"#async\", len(posts.Items), \"err:\", err)\n\t}()\n\n\tfmt.Println(\"\\nTGet call #3\")\n\tposts = RSS{}\n\terr = tc.TGet(mkey, 30, &posts, rebuild)\n\tfmt.Println(\"#3\", len(posts.Items), \"err:\", err)\n}\n"
  },
  {
    "path": "6-databases/tcache/posts.go",
    "content": "package main\n\nimport (\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net/http\"\n)\n\ntype RSS struct {\n\tItems []Item `xml:\"channel>item\"`\n}\n\ntype Item struct {\n\tURL   string `xml:\"guid\"`\n\tTitle string `xml:\"title\"`\n}\n\nfunc GetHabrPosts() (*RSS, error) {\n\tfmt.Println(\"fetching https://habrahabr.ru/rss/best/\")\n\tresp, err := http.Get(\"https://habrahabr.ru/rss/best/\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdefer resp.Body.Close()\n\tbody, _ := ioutil.ReadAll(resp.Body)\n\n\trss := new(RSS)\n\terr = xml.Unmarshal(body, rss)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn rss, nil\n}\n"
  },
  {
    "path": "7-security/1_passwords/0_password.txt",
    "content": "john 1234\nbob 12345\n\njohn 81dc9bdb52d04dc20036dbd8313ed055\nbob 827ccb0eea8a706c4c34a16891f84e7b\nalice 81dc9bdb52d04dc20036dbd8313ed055\n\njohn 123_ad90103a6daa2d46f6ca32753f5bd8cd\nbob 234_876b13777d05743fca744018f8c82ef7\nalice 789_0c01c17a759578ba5a956a18acd54c9b\n\n\nmd5(salt + _ + password)\n\n-> reg password\n    -> md5(salt + _ + password)\n        -> db\n\n-> login password\n    -> md5(salt + _ + password)\n    <- db hash + salt\n    ? ==\n\n\n\nemail - pass:\nk.kitsuragi@mail.ru - e10adc3949ba59abbe56e057f20f883e\nh.dubois@mail.ru - d8578edf8458ce06fbc5bb76a58c5ca4\n...\n<https://crackstation.net>\n<https://hashcat.net/hashcat/>"
  },
  {
    "path": "7-security/1_passwords/1_salt.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"crypto/rand\"\n\t\"fmt\"\n\n\t\"golang.org/x/crypto/argon2\"\n)\n\nfunc hashPass(salt []byte, plainPassword string) []byte {\n\thashedPass := argon2.IDKey([]byte(plainPassword), []byte(salt), 1, 64*1024, 4, 32)\n\treturn append(salt, hashedPass...)\n\t// [salt] + [pass_hash]\n}\n\nfunc checkPass(passHash []byte, plainPassword string) bool {\n\tsalt := make([]byte, 8)\n\tcopy(salt, passHash[:8])\n\tuserPassHash := hashPass(salt, plainPassword)\n\treturn bytes.Equal(userPassHash, passHash)\n}\n\nfunc passExample() {\n\tpass := \"love\"\n\n\t// reg\n\tsalt := make([]byte, 8)\n\trand.Read(salt)\n\tfmt.Printf(\"salt: %x\\n\", salt)\n\n\thashedPass := hashPass(salt, pass)\n\tfmt.Printf(\"hashedPass: %x\\n\", hashedPass)\n\n\t// login\n\tpassValid := checkPass(hashedPass, pass)\n\tfmt.Printf(\"passValid: %v\\n\", passValid)\n}\n\n// func main() {\n// \tfor i := 0; i < 3; i++ {\n// \t\tfmt.Println(\"\\titeration\", i)\n// \t\tpassExample()\n// \t}\n// }\n"
  },
  {
    "path": "7-security/1_passwords/2_pass.go",
    "content": "package main\n\nimport (\n\t\"crypto/md5\"\n\t\"crypto/sha1\"\n\t\"fmt\"\n\n\t\"golang.org/x/crypto/argon2\"\n\t\"golang.org/x/crypto/bcrypt\"\n\t\"golang.org/x/crypto/pbkdf2\"\n\t\"golang.org/x/crypto/scrypt\"\n)\n\nvar (\n\tplainPassword = []byte(\"qwerty123456\")\n\n\t// соль должна быть для каждого юзера своя, не используте в таком виде\n\tsalt = []byte{0xd7, 0xc2, 0xf2, 0x51, 0xaa, 0x6a, 0x4e, 0x7b}\n)\n\n// md5 - плохой вариант, подвержен брутфорс-атаке\nfunc PasswordMD5(plainPassword []byte) []byte {\n\treturn md5.New().Sum(plainPassword)\n}\n\n// bcrypt where PBKDF2 or scrypt support is not available.\nfunc PasswordBcrypt(plainPassword []byte) []byte {\n\tpassBcrypt, _ := bcrypt.GenerateFromPassword(plainPassword, 7)\n\treturn passBcrypt\n}\n\n// PBKDF2 when FIPS certification or enterprise support on many platforms is required;\nfunc PasswordPBKDF2(plainPassword []byte) []byte {\n\treturn pbkdf2.Key(plainPassword, salt, 4096, 32, sha1.New)\n}\n\n// scrypt where resisting any/all hardware accelerated attacks is necessary but support isn’t.\nfunc PasswordScrypt(plainPassword []byte) []byte {\n\tpassScrypt, _ := scrypt.Key(plainPassword, salt, 1<<15, 8, 1, 32)\n\treturn passScrypt\n}\n\n// Argon2 is the winner of the password hashing competition and should be considered as your first choice for new applications;\nfunc PasswordArgon2(plainPassword []byte) []byte {\n\treturn argon2.IDKey(plainPassword, salt, 1, 64*1024, 4, 32)\n}\n\n// https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Password_Storage_Cheat_Sheet.md\n// https://cheatsheetseries.owasp.org\nfunc main() {\n\tfmt.Printf(\"PasswordMD5: %x\\n\", PasswordMD5(plainPassword))\n\tfmt.Printf(\"PasswordBcrypt: %x\\n\", PasswordBcrypt(plainPassword))\n\tfmt.Printf(\"PasswordBcrypt2: %x\\n\", PasswordBcrypt(plainPassword))\n\tfmt.Printf(\"PasswordPBKDF2: %x\\n\", PasswordPBKDF2(plainPassword))\n\tfmt.Printf(\"PasswordScrypt: %x\\n\", PasswordScrypt(plainPassword))\n\tfmt.Printf(\"PasswordArgon2: %x\\n\", PasswordArgon2(plainPassword))\n}\n"
  },
  {
    "path": "7-security/1_passwords/2_pass_bench_test.go",
    "content": "package main\n\nimport (\n\t\"testing\"\n)\n\n// go test -bench . -benchmem pass.go pass_bench_test.go\n\nfunc BenchmarkMD5(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\tPasswordMD5(plainPassword)\n\t}\n}\n\nfunc BenchmarkBcrypt(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\tPasswordBcrypt(plainPassword)\n\t}\n}\n\nfunc BenchmarkPBKDF2(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\tPasswordPBKDF2(plainPassword)\n\t}\n}\n\nfunc BenchmarkScrypt(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\tPasswordScrypt(plainPassword)\n\t}\n}\n\nfunc BenchmarkArgon2(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\tPasswordArgon2(plainPassword)\n\t}\n}\n"
  },
  {
    "path": "7-security/2_csrf/csrf.go",
    "content": "// CSRF - это выполнение какие-то действий на сайте от имени другого пользователя\n\n// данный пример ИСКУССТВЕННЫЙ, чтобы показать как проявляется CSRF\n// используйте пакет html/template\n// он автоматичски экранирует все входящие данные с учетом контекста\n// подрбонее https://golang.org/pkg/html/template/\n\npackage main\n\nimport (\n\t\"net/http\"\n\t// \"html/template\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"strconv\"\n\t\"text/template\" // надо заменить text/template на html/template чтобы по-умоллчанию было правильное экранирование\n\t\"time\"\n)\n\nvar sessions = map[string]string{}\nvar cnt = 1\n\ntype Msg struct {\n\tID      int\n\tMessage string\n\tRating  int\n}\n\nvar messages = map[int]*Msg{}\n\nvar loginFormTmplRaw = `<html><body>\n\t<form action=\"/login\" method=\"post\">\n\t\tLogin: <input type=\"text\" name=\"login\" value=\"DefaultUserName\">\n\t\tPassword: <input type=\"password\" name=\"password\" value=\"anypass\">\n\t\t<input type=\"submit\" value=\"Login\">\n\t</form>\n</body></html>`\n\nvar messagesTmpl = `<html>\n<head>\n<script>\n\tfunction rateComment(id, vote) {\n\t\tvar request = new XMLHttpRequest();\n\t\trequest.open('POST', '/rate?id='+id+\"&vote=\"+(vote > 0 ? \"up\" : \"down\"), true);\n\n\t\trequest.onload = function() {\n\t\t    var resp = JSON.parse(request.responseText);\n\t\t\tconsole.log(resp, resp.id)\n\t\t\tconsole.log('#rating-'+resp.id)\n\t\t\tconsole.log(document.querySelector('#rating-'+resp.id))\n\t\t\tdocument.querySelector('#rating-'+resp.id).innerHTML = resp.rating;\n\t\t};\n\t\trequest.send();\n\t}\n</script>\n</head>\n<body>\n\t&lt;img src=&quot;/rate?id=1&amp;vote=up&quot;&gt;\n\t<br />\n\t<br />\n\n\t<form action=\"/comment\" method=\"post\">\n\t\t<textarea name=\"comment\"></textarea><br />\n\t\t<input type=\"submit\" value=\"Comment\">\n\t</form>\n\t<br />\n\t\n    {{range $idx, $var := .Messages}}\n\t\t<div style=\"border: 1px solid black; padding: 5px; margin: 5px;\">\n\t\t\t<button onclick=\"rateComment({{$var.ID}}, 1)\">&uarr;</button>\n\t\t\t<span id=\"rating-{{$var.ID}}\">{{$var.Rating}}</span>\n\t\t\t<button onclick=\"rateComment({{$var.ID}}, -1)\">&darr;</button>\n\t\t\t&nbsp;\n\n\t\t\t<!-- text/template по-умолчанию ничего не экранируется --> \n\t\t\t<!-- html/template по-умолчанию будет экранировать --> \n\t\t\t{{$var.Message}}\n\t\t</div>\n    {{end}}\n</body></html>`\n\n// https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html\nfunc main() {\n\n\ttmpl := template.New(\"main\")\n\ttmpl, _ = tmpl.Parse(messagesTmpl)\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tif !checkSession(r) {\n\t\t\tw.Write([]byte(loginFormTmplRaw))\n\t\t\treturn\n\t\t}\n\t\t//выводим комментарии + форму отправки\n\t\ttmpl.Execute(w, struct {\n\t\t\tMessages map[int]*Msg\n\t\t}{\n\t\t\tMessages: messages,\n\t\t})\n\t})\n\n\t// добавление комментария\n\t// добавим комментарий c текстом\n\t/*\n\t\t<img src=\"/rate?id=1&vote=up\">\n\t*/\n\t// это выведет на экран куки сайта. дальше с ними можно сделать всё что угодно - например отправить ан внешний сервис, который с сессией этого юзера будет слать спам пока может\n\thttp.HandleFunc(\"/comment\", func(w http.ResponseWriter, r *http.Request) {\n\t\tr.ParseForm()\n\t\tcommentText := r.FormValue(\"comment\")\n\t\tid := cnt\n\t\tmessages[id] = &Msg{\n\t\t\tID:      id,\n\t\t\tMessage: commentText,\n\t\t\tRating:  0,\n\t\t}\n\t\tcnt++\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t})\n\n\t// функция для изменения рейтинга\n\t// тут происхрдит CSRF т.к. <img который мы вставили в комменте выше вызывается каждым пользователем который его видит без его ведома\n\thttp.HandleFunc(\"/rate\", func(w http.ResponseWriter, r *http.Request) {\n\t\tw.Header().Set(\"Content-Type\", \"application/json\")\n\n\t\temptyResponse := []byte(`{\"id\":0, \"rating\":0}`)\n\t\tif !checkSession(r) || r.Method == http.MethodGet {\n\t\t\t// if !checkSession(r) {\n\t\t\tw.Write([]byte(emptyResponse))\n\t\t\treturn\n\t\t}\n\n\t\tid, _ := strconv.Atoi(r.URL.Query().Get(\"id\"))\n\t\tvote := r.URL.Query().Get(\"vote\")\n\n\t\tif msg, ok := messages[id]; ok {\n\t\t\tif vote == \"up\" {\n\t\t\t\tmsg.Rating++\n\t\t\t} else if vote == \"down\" {\n\t\t\t\tmsg.Rating--\n\t\t\t}\n\t\t\tw.Write([]byte(fmt.Sprintf(`{\"id\":%d, \"rating\":%d}`, msg.ID, msg.Rating)))\n\t\t} else {\n\t\t\tw.Write([]byte(emptyResponse))\n\t\t}\n\t})\n\n\t// сервисный метод для очистки комментариев\n\thttp.HandleFunc(\"/clear_comments\", func(w http.ResponseWriter, r *http.Request) {\n\t\tif !checkSession(r) {\n\t\t\tw.Write([]byte(loginFormTmplRaw))\n\t\t\treturn\n\t\t}\n\t\tmessages = map[int]*Msg{}\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t})\n\n\t// создаём сессию\n\t// не используйте эитот подход в продакшене\n\thttp.HandleFunc(\"/login\", loginHandler)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\nfunc loginHandler(w http.ResponseWriter, r *http.Request) {\n\tr.ParseForm()\n\tinputLogin := r.Form[\"login\"][0]\n\texpiration := time.Now().Add(365 * 24 * time.Hour)\n\n\tsessionID := RandStringRunes(32)\n\tsessions[sessionID] = inputLogin\n\n\tcookie := http.Cookie{Name: \"session_id\", Value: sessionID, Expires: expiration}\n\thttp.SetCookie(w, &cookie)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc checkSession(r *http.Request) bool {\n\t// обработка сессии\n\t// не используйте эитот подход в продакшене\n\tsessionID, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\treturn false\n\t} else if err != nil {\n\t\tPanicOnErr(err)\n\t}\n\t_, ok := sessions[sessionID.Value]\n\tif !ok {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// PanicOnErr panics on error\nfunc PanicOnErr(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "7-security/2_csrf/csrf.txt",
    "content": "front -> api.myproj.com/csrf\n    -> referrer? -> jwt token\n\nfront -> POST api.myproj.com/pay + token\n\n\n\n//--\n\nfront -> GET api.myproj.com/api/user\n    -> Set-Cookie: csrf=kldjflckdhsfbilehroiw4hrkj34btf domain=.myproj.com expires=in 15 min\n    -> POST api.myproj.com/pay X-CSRF-Token: getCookie('csrf')\n        header == cookie"
  },
  {
    "path": "7-security/3_csrf_token/csrf.go",
    "content": "// CSRF - это выполнение какие-то действий на сайте от имени другого пользователя\n\n// данный пример ИСКУССТВЕННЫЙ, чтобы показать как проявляется CSRF\n// используйте пакет html/template\n// он автоматичски экранирует все входящие данные с учетом контекста\n// подрбонее https://golang.org/pkg/html/template/\n\npackage main\n\nimport (\n\t\"net/http\"\n\t// \"html/template\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"strconv\"\n\t\"text/template\" // надо заменить text/template на html/template чтобы по-умоллчанию было правильное экранирование\n\t\"time\"\n)\n\nvar sessions = map[string]*Session{}\nvar cnt = 1\n\ntype Msg struct {\n\tID      int\n\tMessage string\n\tRating  int\n}\n\ntype Session struct {\n\tUserID uint32\n\tID     string\n}\n\nvar messages = map[int]*Msg{}\n\nvar loginFormTmplRaw = `<html><body>\n\t<form action=\"/login\" method=\"post\">\n\t\tLogin: <input type=\"text\" name=\"login\" value=\"DefaultUserName\">\n\t\tPassword: <input type=\"password\" name=\"password\" value=\"anypass\">\n\t\t<input type=\"submit\" value=\"Login\">\n\t</form>\n</body></html>`\n\nvar messagesTmpl = `<html>\n<head>\n<script>\n\tfunction rateComment(id, vote) {\n\t\tvar request = new XMLHttpRequest();\n\t\trequest.open('POST', '/rate?id='+id+\"&vote=\"+(vote > 0 ? \"up\" : \"down\"), true);\n\t\trequest.setRequestHeader(\"csrf-token\", \"{{.CSRFToken}}\");\n\t\trequest.onload = function() {\n\t\t    var resp = JSON.parse(request.responseText);\n\t\t\tconsole.log(resp, resp.id)\n\t\t\tconsole.log('#rating-'+resp.id)\n\t\t\tconsole.log(document.querySelector('#rating-'+resp.id))\n\t\t\tdocument.querySelector('#rating-'+resp.id).innerHTML = resp.rating;\n\t\t};\n\t\trequest.send();\n\t}\n</script>\n</head>\n<body>\n\t&lt;img src=&quot;/rate?id=1&amp;vote=up&quot;&gt;\n\t<br />\n\t<br />\n\n\t<form action=\"/comment\" method=\"post\">\n\t\t<input type=\"hidden\" value=\"{{.CSRFToken}}\" name=\"csrf-token\" />\n\t\t<textarea name=\"comment\"></textarea><br />\n\t\t<input type=\"submit\" value=\"Comment\">\n\t</form>\n\t<br />\n\t\n    {{range $idx, $var := .Messages}}\n\t\t<div style=\"border: 1px solid black; padding: 5px; margin: 5px;\">\n\t\t\t<button onclick=\"rateComment({{$var.ID}}, 1)\">&uarr;</button>\n\t\t\t<span id=\"rating-{{$var.ID}}\">{{$var.Rating}}</span>\n\t\t\t<button onclick=\"rateComment({{$var.ID}}, -1)\">&darr;</button>\n\t\t\t&nbsp;\n\n\t\t\t<!-- text/template по-умолчанию ничего не экранируется --> \n\t\t\t<!-- html/template по-умолчанию будет экранировать --> \n\t\t\t{{$var.Message}}\n\t\t</div>\n    {{end}}\n</body></html>`\n\nfunc main() {\n\n\ttmpl := template.New(\"main\")\n\ttmpl, _ = tmpl.Parse(messagesTmpl)\n\n\t// tokens, _ := NewHMACHashToken(\"golangcourse\") //только хеш фиксированных данных\n\t// tokens, _ := NewAesCryptHashToken(\"qsRY2e4hcM5T7X984E9WQ5uZ8Nty7fxB\") // можно еще че-то хранить и шифровать. без расшифровки не видно\n\ttokens, _ := NewJwtToken(\"qsRY2e4hcM5T7X984E9WQ5uZ8Nty7fxB\") // можно так же че-то хранить и подписывать. видно, но нельзя подделать\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tsess, err := checkSession(r)\n\t\tif err != nil {\n\t\t\tw.Write([]byte(loginFormTmplRaw))\n\t\t\treturn\n\t\t}\n\n\t\ttoken, err := tokens.Create(sess, time.Now().Add(24*time.Hour).Unix())\n\t\tif err != nil {\n\t\t\tlog.Println(\"csrf token creation error:\", err)\n\t\t\thttp.Error(w, \"internal error\", http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\t//выводим комментарии + форму отправки\n\t\ttmpl.Execute(w, struct {\n\t\t\tMessages  map[int]*Msg\n\t\t\tCSRFToken string\n\t\t}{\n\t\t\tMessages:  messages,\n\t\t\tCSRFToken: token,\n\t\t})\n\t})\n\n\t// добавление комментария\n\t// добавим комментарий c текстом\n\t/*\n\t\t<img src=\"/rate?id=1&vote=up\">\n\t*/\n\t// это выведет на экран куки сайта. дальше с ними можно сделать всё что угодно - например отправить ан внешний сервис, который с сессией этого юзера будет слать спам пока может\n\thttp.HandleFunc(\"/comment\", func(w http.ResponseWriter, r *http.Request) {\n\t\tr.ParseForm()\n\n\t\tsess, err := checkSession(r)\n\t\tif err != nil || r.Method == http.MethodGet {\n\t\t\tw.Write([]byte(loginFormTmplRaw))\n\t\t\treturn\n\t\t}\n\n\t\tCSRFToken := r.FormValue(\"csrf-token\")\n\t\t_, err = tokens.Check(sess, CSRFToken)\n\t\tif err != nil {\n\t\t\tw.Write([]byte(\"{}\"))\n\t\t\treturn\n\t\t}\n\n\t\tcommentText := r.FormValue(\"comment\")\n\t\tid := cnt\n\t\tmessages[id] = &Msg{\n\t\t\tID:      id,\n\t\t\tMessage: commentText,\n\t\t\tRating:  0,\n\t\t}\n\t\tcnt++\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t})\n\n\t// функция для изменения рейтинга\n\t// тут происхрдит CSRF т.к. <img который мы вставили в комменте выше вызывается каждым пользователем который его видит без его ведома\n\thttp.HandleFunc(\"/rate\", func(w http.ResponseWriter, r *http.Request) {\n\t\tw.Header().Set(\"Content-Type\", \"application/json\")\n\n\t\temptyResponse := []byte(`{\"id\":0, \"rating\":0}`)\n\t\tsess, err := checkSession(r)\n\t\t// if err != nil || r.Method == http.MethodGet {\n\t\tif err != nil {\n\t\t\tw.Write([]byte(emptyResponse))\n\t\t\treturn\n\t\t}\n\n\t\tCSRFToken := r.Header.Get(\"csrf-token\")\n\t\t_, err = tokens.Check(sess, CSRFToken)\n\t\tif err != nil {\n\t\t\tw.Write([]byte(emptyResponse))\n\t\t\treturn\n\t\t}\n\n\t\tid, _ := strconv.Atoi(r.URL.Query().Get(\"id\"))\n\t\tvote := r.URL.Query().Get(\"vote\")\n\n\t\tif msg, ok := messages[id]; ok {\n\t\t\tif vote == \"up\" {\n\t\t\t\tmsg.Rating++\n\t\t\t} else if vote == \"down\" {\n\t\t\t\tmsg.Rating--\n\t\t\t}\n\t\t\tw.Write([]byte(fmt.Sprintf(`{\"id\":%d, \"rating\":%d}`, msg.ID, msg.Rating)))\n\t\t} else {\n\t\t\tw.Write([]byte(emptyResponse))\n\t\t}\n\t})\n\n\t// сервисный метод для очистки комментариев\n\thttp.HandleFunc(\"/clear_comments\", func(w http.ResponseWriter, r *http.Request) {\n\t\t_, err := checkSession(r)\n\t\tif err != nil {\n\t\t\tw.Write([]byte(loginFormTmplRaw))\n\t\t\treturn\n\t\t}\n\t\tmessages = map[int]*Msg{}\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t})\n\n\t// создаём сессию\n\t// не используйте эитот подход в продакшене\n\thttp.HandleFunc(\"/login\", loginHandler)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\nfunc loginHandler(w http.ResponseWriter, r *http.Request) {\n\tr.ParseForm()\n\t// inputLogin := r.Form[\"login\"][0]\n\texpiration := time.Now().Add(365 * 24 * time.Hour)\n\n\tsessionID := RandStringRunes(32)\n\tsessions[sessionID] = &Session{ID: sessionID, UserID: 123}\n\n\tcookie := http.Cookie{Name: \"session_id\", Value: sessionID, Expires: expiration}\n\thttp.SetCookie(w, &cookie)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc checkSession(r *http.Request) (*Session, error) {\n\t// обработка сессии\n\t// не используйте эитот подход в продакшене\n\tsessionID, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\treturn nil, fmt.Errorf(\"no cookie\")\n\t} else if err != nil {\n\t\treturn nil, err\n\t}\n\tsess, ok := sessions[sessionID.Value]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no session\")\n\t}\n\treturn sess, nil\n}\n\n// PanicOnErr panics on error\nfunc PanicOnErr(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "7-security/3_csrf_token/token_crypt.go",
    "content": "package main\n\nimport (\n\t\"crypto/aes\"\n\t\"crypto/cipher\"\n\t\"crypto/rand\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\n\t// \"strings\"\n\t\"time\"\n)\n\ntype CryptToken struct {\n\tSecret []byte\n}\n\ntype TokenData struct {\n\tSessionID string\n\tUserID    uint32\n\tExp       int64\n}\n\nfunc NewAesCryptHashToken(secret string) (*CryptToken, error) {\n\tkey := []byte(secret)\n\t_, err := aes.NewCipher(key)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cypher problem %v\", err)\n\t}\n\treturn &CryptToken{Secret: key}, nil\n}\n\nfunc (tk *CryptToken) Create(s *Session, tokenExpTime int64) (string, error) {\n\tblock, err := aes.NewCipher(tk.Secret)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\taesgcm, err := cipher.NewGCM(block)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tnonce := make([]byte, aesgcm.NonceSize())\n\tif _, err := io.ReadFull(rand.Reader, nonce); err != nil {\n\t\treturn \"\", err\n\t}\n\n\ttd := &TokenData{SessionID: s.ID, UserID: s.UserID, Exp: tokenExpTime}\n\tdata, _ := json.Marshal(td)\n\tciphertext := aesgcm.Seal(nil, nonce, data, nil)\n\n\tres := append([]byte(nil), nonce...)\n\tres = append(res, ciphertext...)\n\n\ttoken := base64.StdEncoding.EncodeToString(res)\n\treturn token, nil\n}\n\nfunc (tk *CryptToken) Check(s *Session, inputToken string) (bool, error) {\n\tblock, err := aes.NewCipher(tk.Secret)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\taesgcm, err := cipher.NewGCM(block)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tciphertext, err := base64.StdEncoding.DecodeString(inputToken)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tnonceSize := aesgcm.NonceSize()\n\tif len(ciphertext) < nonceSize {\n\t\treturn false, fmt.Errorf(\"ciphertext too short\")\n\t}\n\n\tnonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]\n\tplaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"decrypt fail: %v\", err)\n\t}\n\n\ttd := TokenData{}\n\terr = json.Unmarshal(plaintext, &td)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"bad json: %v\", err)\n\t}\n\n\tif td.Exp < time.Now().Unix() {\n\t\treturn false, fmt.Errorf(\"token expired\")\n\t}\n\n\treturn s.ID == td.SessionID && s.UserID == td.UserID, nil\n}\n"
  },
  {
    "path": "7-security/3_csrf_token/token_jwt.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\tjwt \"github.com/dgrijalva/jwt-go\"\n)\n\ntype JwtToken struct {\n\tSecret []byte\n}\n\nfunc NewJwtToken(secret string) (*JwtToken, error) {\n\treturn &JwtToken{Secret: []byte(secret)}, nil\n}\n\ntype JwtCsrfClaims struct {\n\tSessionID string `json:\"sid\"`\n\tUserID    uint32 `json:\"uid\"`\n\tjwt.StandardClaims\n}\n\nfunc (tk *JwtToken) Create(s *Session, tokenExpTime int64) (string, error) {\n\tdata := JwtCsrfClaims{\n\t\tSessionID: s.ID,\n\t\tUserID:    s.UserID,\n\t\tStandardClaims: jwt.StandardClaims{\n\t\t\tExpiresAt: tokenExpTime,\n\t\t\tIssuedAt:  time.Now().Unix(),\n\t\t},\n\t}\n\ttoken := jwt.NewWithClaims(jwt.SigningMethodHS256, data)\n\treturn token.SignedString(tk.Secret)\n}\n\nfunc (tk *JwtToken) parseSecretGetter(token *jwt.Token) (interface{}, error) {\n\tmethod, ok := token.Method.(*jwt.SigningMethodHMAC)\n\tif !ok || method.Alg() != \"HS256\" {\n\t\treturn nil, fmt.Errorf(\"bad sign method\")\n\t}\n\treturn tk.Secret, nil\n}\n\nfunc (tk *JwtToken) Check(s *Session, inputToken string) (bool, error) {\n\tpayload := &JwtCsrfClaims{}\n\t_, err := jwt.ParseWithClaims(inputToken, payload, tk.parseSecretGetter)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"cant parse jwt token: %v\", err)\n\t}\n\tif payload.Valid() != nil {\n\t\treturn false, fmt.Errorf(\"invalid jwt token: %v\", err)\n\t}\n\treturn payload.SessionID == s.ID && payload.UserID == s.UserID, nil\n}\n\n/*\nfunc (tk *JwtToken) parseSecretGetterMultiKeys(token *jwt.Token) (interface{}, error) {\n\tmethod, ok := token.Method.(*jwt.SigningMethodHMAC)\n\tif !ok || method.Alg() != \"HS256\" {\n\t\treturn nil, fmt.Errorf(\"bad sign method\")\n\t}\n\n\tkeys := []*Key{\n\t\t&Key{Exp: 10, Secret: 1},\n\t\t&Key{Exp: 20, Secret: 2},\n\t\t&Key{Exp: 30, Secret: 3},\n\t}\n\n\tpayload, ok := token.Claims.(*JwtCsrfClaims)\n\tif !ok {\n\t\treturn nil, err\n\t}\n\tsecret := \"\"\n\tfor _, key := range keys {\n\t\tif Key.Exp > payload.Exp {\n\t\t\tsecret = key.Secret\n\t\t\tbreak\n\t\t}\n\t}\n\tif secret == \"\" {\n\t\treturn nil, fmt.Errrof(\"no secret found\")\n\t}\n\n\treturn secret, nil\n}\n*/\n\n// https://specialistoff.net/page/902\n"
  },
  {
    "path": "7-security/3_csrf_token/tokjen_hash.go",
    "content": "package main\n\nimport (\n\t\"crypto/hmac\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\n// fbc1fd86ab53d52c3ffeb6529aea9676e14bc52b792414c32f5612b4eb2c9745:1567618546\n// JSv5M7FZ5iPHnHiLXR1QbhnMcdoY/wvEae4a76KrGBxeHruFb1S90d4GkwsoQQU4R1zqEdSa0KMGflriF2dHj5XWm4Zp6OBxLp6BJFUhqpQxEBEr5yl4sxEHadgssvVWfWtDKe0bENU=\n// JSv5M7FZ5iPHnHiLXR1QbhnMcDAU/wvEae4a76KrGBxeHruFb1S90d4GkwsoQQU4R1zqEdSa0KMGflriF2dHj5XWm4Zp6OBxLp6BJFUhqpQxEBEr5yl4sxEHadgssvVWfWtDKe0bENU=\n// JSv5M7FZ5iPHnHiLXR1QbhnMcNEF/wvEae4a76KrGBxeHruFb1S90d4GkwsoQQU4R1zqEdSa0KMGflriF2dHj5XWm4Zp6OBxLp6BJFUhqpQxEBEr5yl4sxEHadgssvVWfWtDKe0bENU=\n\ntype HashToken struct {\n\tSecret []byte\n}\n\nfunc NewHMACHashToken(secret string) (*HashToken, error) {\n\treturn &HashToken{Secret: []byte(secret)}, nil\n}\n\nfunc (tk *HashToken) Create(s *Session, tokenExpTime int64) (string, error) {\n\th := hmac.New(sha256.New, []byte(tk.Secret))\n\tdata := fmt.Sprintf(\"%s:%d:%d\", s.ID, s.UserID, tokenExpTime)\n\th.Write([]byte(data))\n\ttoken := hex.EncodeToString(h.Sum(nil)) + \":\" + strconv.FormatInt(tokenExpTime, 10)\n\treturn token, nil\n}\n\nfunc (tk *HashToken) Check(s *Session, inputToken string) (bool, error) {\n\ttokenData := strings.Split(inputToken, \":\")\n\tif len(tokenData) != 2 {\n\t\treturn false, fmt.Errorf(\"bad token data\")\n\t}\n\n\ttokenExp, err := strconv.ParseInt(tokenData[1], 10, 64)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"bad token time\")\n\t}\n\n\tif tokenExp < time.Now().Unix() {\n\t\treturn false, fmt.Errorf(\"token expired\")\n\t}\n\n\th := hmac.New(sha256.New, []byte(tk.Secret))\n\tdata := fmt.Sprintf(\"%s:%d:%d\", s.ID, s.UserID, tokenExp)\n\th.Write([]byte(data))\n\texpectedMAC := h.Sum(nil)\n\tmessageMAC, err := hex.DecodeString(tokenData[0])\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"cand hex decode token\")\n\t}\n\n\treturn hmac.Equal(messageMAC, expectedMAC), nil\n}\n"
  },
  {
    "path": "7-security/4_xss/xss.go",
    "content": "// XSS - это внедрение вредоносного кода там где мы не ожидаем\n// например в комменте пишем JS, который будет выполняться для всех пользователей, читающих его\n// опасность заключается в том, что злоумышленник может вызывать от имени юзера какие-то методы\n// например отправка спама от его имени или кража сессии\n// лечится правильным экранированием всех внешних входных данных по отношению к сайту (в первую очередь - пользовательского ввода)\n\n// данный пример ИСКУССТВЕННЫЙ, чтобы показать как проявляется XSS\n// используйте пакет html/template\n// он автоматичски экранирует все входящие данные с учетом контекста\n// подрбонее https://golang.org/pkg/html/template/\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"html/template\"\n\t\"math/rand\"\n\t\"net/http\"\n\t// \"text/template\"\n\t\"time\"\n)\n\nvar sessions = map[string]string{}\nvar messages = []string{\"Hello World\"}\n\nvar loginFormTmplRaw = `<html><body>\n\t<form action=\"/login\" method=\"post\">\n\t\tLogin: <input type=\"text\" name=\"login\" value=\"DefaultUserName\">\n\t\tPassword: <input type=\"password\" name=\"password\" value=\"anypass\">\n\t\t<input type=\"submit\" value=\"Login\">\n\t</form>\n</body></html>`\n\nvar messagesTmpl = `<html><body>\n\n\t&lt;script&gt;alert(document.cookie)&lt;/script&gt;\n\n\t<br />\n\t<br />\n\n\t<form action=\"/comment\" method=\"post\">\n\t\t<textarea name=\"comment\"></textarea><br />\n\t\t<input type=\"submit\" value=\"Comment\">\n\t</form>\n\n\t<br />\n\n    {{range .Messages}}\n\t\t<div style=\"border: 1px solid black; padding: 5px; margin: 5px;\">\n\t\t\t<!-- text/template по-умолч ничего не экранируется, надо указать | html --> \n\t\t\t<!-- html/template по-умолч будет экранировать --> \n\n\t\t\t{{.}}\n\t\t</div>\n    {{end}}\n</body></html>`\n\nfunc checkSession(r *http.Request) bool {\n\t// обработка сессии\n\t// не используйте этот подход в продакшене\n\tsessionID, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\treturn false\n\t} else if err != nil {\n\t\tPanicOnErr(err)\n\t}\n\t_, ok := sessions[sessionID.Value]\n\tif !ok {\n\t\treturn false\n\t}\n\treturn true\n}\n\nfunc main() {\n\n\ttmpl := template.New(\"main\")\n\ttmpl, _ = tmpl.Parse(messagesTmpl)\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tif !checkSession(r) {\n\t\t\tw.Write([]byte(loginFormTmplRaw))\n\t\t\treturn\n\t\t}\n\n\t\t// для отключения экранирования в html/template\n\t\tnewMsgs := []template.HTML{}\n\t\tfor _, v := range messages {\n\t\t\tnewMsgs = append(newMsgs, template.HTML(v))\n\t\t}\n\n\t\t//выводим комментарии + форму отправки\n\t\ttmpl.Execute(w, struct {\n\t\t\tMessages []template.HTML\n\t\t}{\n\t\t\tMessages: newMsgs,\n\t\t})\n\t})\n\n\t// добавление комментария\n\t// добавим комментарий c текстом\n\t/*\n\t\t<script>alert(document.cookie)</script>\n\t*/\n\t// это выведет на экран куки сайта. дальше с ними можно сделать всё что угодно - например отправить на внешний сервис, который с сессией этого юзера будет слать спам пока может\n\thttp.HandleFunc(\"/comment\", func(w http.ResponseWriter, r *http.Request) {\n\t\tif !checkSession(r) {\n\t\t\tw.Write([]byte(loginFormTmplRaw))\n\t\t\treturn\n\t\t}\n\t\tr.ParseForm()\n\t\tcommentText := r.FormValue(\"comment\")\n\t\tmessages = append(messages, commentText)\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t})\n\n\t// сервисный метод для очистки комментариев\n\thttp.HandleFunc(\"/clear_comments\", func(w http.ResponseWriter, r *http.Request) {\n\t\tif !checkSession(r) {\n\t\t\tw.Write([]byte(loginFormTmplRaw))\n\t\t\treturn\n\t\t}\n\n\t\tmessages = []string{}\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t})\n\n\t// создаём сессию\n\t// не используйте этот подход в продакшене\n\thttp.HandleFunc(\"/login\", func(w http.ResponseWriter, r *http.Request) {\n\t\tr.ParseForm()\n\t\tinputLogin := r.Form[\"login\"][0]\n\t\texpiration := time.Now().Add(365 * 24 * time.Hour)\n\n\t\tsessionID := RandStringRunes(32)\n\t\tsessions[sessionID] = inputLogin\n\n\t\tcookie := http.Cookie{Name: \"session_id\", Value: sessionID, Expires: expiration}\n\t\thttp.SetCookie(w, &cookie)\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t})\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\n//PanicOnErr panics on error\nfunc PanicOnErr(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "7-security/5_xss_clean/login.txt",
    "content": "Здравствуйте, ,\n\nспасибо за регу\n\n-> Регаете в сервисе юзера с email d.dorofeev@corp.mail.ru, ставите имя скачайте бесплатно и без смс <a href....>\n\n"
  },
  {
    "path": "7-security/5_xss_clean/xss_clean.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"github.com/microcosm-cc/bluemonday\"\n\t\"net/http\"\n)\n\n// для санитайзинга на сторое фронта используйте https://github.com/cure53/DOMPurify\n\nfunc main() {\n\tsanitizer := bluemonday.UGCPolicy()\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tcomment := `<a onblur=\"alert(document.сookie)\" href=\"javascript:alert(document.сookie)\">Mail.ru</a>`\n\t\tcomment = sanitizer.Sanitize(comment)\n\t\tresp, _ := json.Marshal(map[string]interface{}{\n\t\t\t\"comment\": comment,\n\t\t})\n\t\tw.Write(resp)\n\t})\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "7-security/6_acl/acl_rbac.txt",
    "content": "ACL:\nAccess Control List\n\nкто что и что делает?\nalice /menu write\nbob /menu read\n\n/admin/user/edit\n    userid=1\n    userid=2\n    userid=3\n/admin/user/moderate\n    userid=1\n\n-------\n\nuserid=1\n    /admin/user/edit\n    /admin/user/moderate\n\nuserid=2\n    /admin/user/edit\n\nuserid=3\n    /admin/user/edit\n\n\n-------------------------------\n\nRBAC:\nRole Based Access Control\n\nclient\n    /menu read\n    /order write\nowner\n    /menu read\n    /menu write\n    /orders read\n\nuser_id; role\n1; user\n2; moderator\n3; admin\n\n\n\n/admin/user/edit\n    moderator\n    admin\n/admin/user/moderate\n    admin\n\n-------\n\nadmin\n    /admin/user/edit\n    /admin/user/moderate\n\n\n\n------\n\nhttps://github.com/casbin/casbin\n\n\ntype Session struct {\n    ID string\n    UserID string\n    Role string\n}"
  },
  {
    "path": "7-security/6_acl/casbin/basic_model.conf",
    "content": "[request_definition]\nr = sub, obj, act\n\n[policy_definition]\np = sub, obj, act\n\n[policy_effect]\ne = some(where (p.eft == allow))\n\n[matchers]\nm = r.sub == p.sub && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == \"*\")"
  },
  {
    "path": "7-security/6_acl/casbin/basic_policy.csv",
    "content": "p, admin, /*, *\n\np, anonymous, /, *\np, anonymous, /login, POST\n\np, member, /, *\np, member, /member/*, *\np, member, /logout, *"
  },
  {
    "path": "7-security/6_acl/casbin/rbac.go",
    "content": "package main\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/casbin/casbin\"\n)\n\n// https://casbin.org/en/editor\nfunc main() {\n\tur := &UsersRepo{\n\t\tdb: map[string]*User{\n\t\t\t\"admin@mail.ru\": {1, \"admin\", \"555\"},\n\t\t\t\"user@mail.ru\":  {2, \"member\", \"123\"},\n\t\t},\n\t}\n\te, err := casbin.NewEnforcerSafe(\"basic_model.conf\", \"basic_policy.csv\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tr := http.NewServeMux()\n\tr.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(\"root page\")) })\n\tr.HandleFunc(\"/login\", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(\"you just logged int\")) })\n\tr.HandleFunc(\"/logout\", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(\"you just logged out\")) })\n\n\tr.HandleFunc(\"/member/profile\", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(\"here is your profile\")) })\n\tr.HandleFunc(\"/member/profiles\", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(\"here is your profile\")) })\n\n\tr.HandleFunc(\"/admin/user\", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(\"user edditing\")) })\n\tr.HandleFunc(\"/admin/users\", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(\"users list\")) })\n\n\tmux := PermissionsMiddleware(e, ur, r)\n\n\thttp.ListenAndServe(\":8080\", mux)\n}\n\nfunc PermissionsMiddleware(e *casbin.Enforcer, ur *UsersRepo, next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tv, _ := url.ParseQuery(r.URL.RawQuery)\n\t\temail := v.Get(\"email\")\n\t\t// check auth and cookie/token ...\n\n\t\trole := \"anonymous\"\n\t\tuser := ur.GetUser(email)\n\t\tif user != nil {\n\t\t\trole = user.Role\n\t\t}\n\n\t\tres, _ := e.EnforceSafe(role, r.URL.Path, r.Method)\n\t\tlog.Printf(\"path=%s role=%s access=%v\", r.URL.Path, role, res)\n\t\tif res {\n\t\t\tnext.ServeHTTP(w, r)\n\t\t} else {\n\t\t\thttp.Error(w, \"forbidden\", http.StatusForbidden)\n\t\t\treturn\n\t\t}\n\t})\n\n}\n\ntype User struct {\n\tUserID   int\n\tRole     string\n\tPassword string\n}\ntype UsersRepo struct {\n\tdb map[string]*User\n}\n\nfunc (ur *UsersRepo) GetUser(email string) *User {\n\treturn ur.db[email]\n}\n"
  },
  {
    "path": "7-security/7_docker/.dockerignore",
    "content": "*.exe\n.git\n.DS_Store\n.gitignore\n\n"
  },
  {
    "path": "7-security/7_docker/Dockerfile",
    "content": "FROM golang:1.19-alpine\nCOPY ./code /go/src/my_super_app\nWORKDIR /go/src/my_super_app\nRUN go install .\n\nEXPOSE 8080/tcp\n\nCMD [ \"my_super_app\" ]"
  },
  {
    "path": "7-security/7_docker/Dockerfile.Multistage",
    "content": "# 1 шаг - сборки\nFROM golang:1.19-alpine AS build_stage\nCOPY ./code /go/src/my_super_app\nWORKDIR /go/src/my_super_app\nRUN go install .\n\n# 2 шаг\nFROM alpine AS run_stage\nWORKDIR /app_binary\nCOPY --from=build_stage /go/bin/my_super_app /app_binary/\nRUN chmod +x ./my_super_app\nEXPOSE 8080/tcp\nENTRYPOINT ./my_super_app"
  },
  {
    "path": "7-security/7_docker/code/go.mod",
    "content": "module my_super_app\n\ngo 1.19\n"
  },
  {
    "path": "7-security/7_docker/code/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nvar privateAlbums = map[string]struct{}{\n\t\"selfies\": struct{}{},\n\t\"nudes\":   struct{}{},\n}\n\nvar privateAlbumsACL = map[string]map[int]struct{}{\n\t\"selfies\": map[int]struct{}{\n\t\t1: struct{}{},\n\t\t2: struct{}{},\n\t\t3: struct{}{},\n\t},\n\t\"nudes\": map[int]struct{}{\n\t\t2: struct{}{},\n\t},\n}\n\nfunc checkACL(albumName string, uid int) bool {\n\tif _, ok := privateAlbums[albumName]; !ok {\n\t\treturn true\n\t}\n\tallowedUsers, ok := privateAlbumsACL[albumName]\n\tif !ok {\n\t\treturn true\n\t}\n\t_, ok = allowedUsers[uid]\n\treturn ok\n}\n\nfunc getSession(r string) int {\n\tuid, _ := strconv.Atoi(r)\n\treturn uid\n}\n\nfunc main() {\n\n\thttp.HandleFunc(\"/auth\", func(w http.ResponseWriter, r *http.Request) {\n\t\tfmt.Println(\"AUTH request\", r)\n\n\t\t// fmt.Println(\"X-Original-URI\", r.Header.Get(\"X-Original-URI\"))\n\t\treq, _ := url.Parse(r.Header.Get(\"X-Original-URI\"))\n\t\t// fmt.Println(\"X-User-ID\", req, err)\n\t\t// fmt.Println(\"Req Data\", req.Path, \" -- \", req.Query().Get(\"user_id\"))\n\n\t\tuid := getSession(req.Query().Get(\"user_id\"))\n\n\t\tstr := req.Path\n\t\talbumName := strings.ReplaceAll(str, \"/albums/\", \"\")\n\t\tfmt.Println(\"PARAMS\", albumName, uid)\n\n\t\tif !checkACL(albumName, uid) {\n\t\t\tfmt.Println(\"ACL failed\", albumName, uid)\n\t\t\thttp.Error(w, \"\", 403)\n\t\t}\n\n\t\tw.Header().Set(\"WWW-Authenticate\", req.Query().Get(\"user_id\"))\n\t\tfmt.Println(\"ACL OK\", albumName, uid)\n\t\thttp.Error(w, \"\", 200)\n\t})\n\n\thttp.HandleFunc(\"/albums/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tfmt.Println(\"incoming request\", r)\n\t\tfmt.Fprintln(w, \"hi\", r.Header.Get(\"WWW-Authenticate\"))\n\t})\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tfmt.Println(\"ROOT incoming request\", r)\n\t\tfmt.Fprintln(w, \"hi\", r.Header.Get(\"WWW-Authenticate\"))\n\t})\n\n\tfmt.Println(\"start server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "7-security/7_docker/docker-compose.yml",
    "content": "version: '3'\n\nservices:\n  dockergo:\n    image: docker-golang-image:latest\n\n  nginx:\n    image: nginx:1.15.3\n    links:\n      - dockergo:dockergo\n    volumes:\n      - ./nginx:/etc/nginx/conf.d\n    ports:\n      - 8080:80\n\n"
  },
  {
    "path": "7-security/7_docker/nginx/nginx.conf",
    "content": "server {\n  listen 80;\n\n  location / {\n    proxy_pass http://dockergo:8080/;\n  }\n\n  location /albums/ {\n      auth_request /auth;\n      proxy_pass http://dockergo:8080/;\n  }\n\n  location = /auth {\n      proxy_pass http://dockergo:8080/auth;\n      proxy_pass_request_body off;\n      proxy_set_header Content-Length \"\";\n      # proxy_set_header X-User-ID $arg_user_id;\n      proxy_set_header X-Original-URI $request_uri;\n  }\n}\n"
  },
  {
    "path": "7-security/7_docker/readme.md",
    "content": "docker build -f Dockerfile -t docker-golang-image .\ndocker build -f Dockerfile.Multistage -t docker-golang-image .\ndocker-compose up\n\ndocker run --rm -p 8080:8080 docker-golang-image\n\n<http://127.0.0.1:8080/>\n<http://127.0.0.1:8080/images/sad.jpeg>\n<http://127.0.0.1:8080/albums/selfies?user_id=10>\n"
  },
  {
    "path": "8-microservices/0_service/1_step/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n)\n\nvar loginFormTmpl = []byte(`\n<html>\n\t<body>\n\t<form action=\"/login\" method=\"post\">\n\t\tLogin: <input type=\"text\" name=\"login\">\n\t\tPassword: <input type=\"password\" name=\"password\">\n\t\t<input type=\"submit\" value=\"Login\">\n\t</form>\n\t</body>\n</html>\n`)\n\nfunc checkSession(r *http.Request) (*Session, error) {\n\tcookieSessionID, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\treturn nil, nil\n\t} else if err != nil {\n\t\treturn nil, err\n\t}\n\n\tsess := AuthCheckSession(&SessionID{\n\t\tID: cookieSessionID.Value,\n\t})\n\treturn sess, nil\n}\n\nfunc innerPage(w http.ResponseWriter, r *http.Request) {\n\tsess, err := checkSession(r)\n\tif err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif sess == nil {\n\t\tw.Write(loginFormTmpl)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"text/html\")\n\tfmt.Fprintln(w, \"Welcome, \"+sess.Login+\" <br />\")\n\tfmt.Fprintln(w, \"Session ua: \"+sess.Useragent+\" <br />\")\n\tfmt.Fprintln(w, `<a href=\"/logout\">logout</a>`)\n}\n\nfunc loginPage(w http.ResponseWriter, r *http.Request) {\n\tinputLogin := r.FormValue(\"login\")\n\texpiration := time.Now().Add(365 * 24 * time.Hour)\n\n\tsess, err := AuthCreateSession(&Session{\n\t\tLogin:     inputLogin,\n\t\tUseragent: r.UserAgent(),\n\t})\n\tif err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   sess.ID,\n\t\tExpires: expiration,\n\t}\n\thttp.SetCookie(w, &cookie)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc logoutPage(w http.ResponseWriter, r *http.Request) {\n\tsession, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t\treturn\n\t} else if err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tAuthSessionDelete(&SessionID{\n\t\tID: session.Value,\n\t})\n\n\tsession.Expires = time.Now().AddDate(0, 0, -1)\n\thttp.SetCookie(w, session)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", innerPage)\n\thttp.HandleFunc(\"/login\", loginPage)\n\thttp.HandleFunc(\"/logout\", logoutPage)\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "8-microservices/0_service/1_step/run_test.go",
    "content": "package main\n\nimport (\n\t\"testing\"\n)\n\nfunc TestExample(t *testing.T) {\n\t// создаем сессию\n\tsessId, err := AuthCreateSession(\n\t\t&Session{\n\t\t\tLogin:     \"anton\",\n\t\t\tUseragent: \"safari\",\n\t\t})\n\tt.Log(\"sessId\", sessId, err)\n\n\t// проеряем сессию\n\tsess := AuthCheckSession(\n\t\t&SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\tt.Log(\"sess\", sess)\n\n\t// удаляем сессию\n\tAuthSessionDelete(\n\t\t&SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\n\t// проверяем еще раз\n\tsess = AuthCheckSession(\n\t\t&SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\tt.Log(\"sess\", sess)\n\tt.Fail()\n}\n"
  },
  {
    "path": "8-microservices/0_service/1_step/session.go",
    "content": "package main\n\nimport (\n\t\"math/rand\"\n\t\"sync\"\n)\n\ntype Session struct {\n\tLogin     string\n\tUseragent string\n}\n\ntype SessionID struct {\n\tID string\n}\n\nconst sessKeyLen = 10\n\nvar (\n\tsessions = map[SessionID]*Session{}\n\tmu       = &sync.RWMutex{}\n)\n\nfunc AuthCreateSession(in *Session) (*SessionID, error) {\n\tmu.Lock()\n\tid := SessionID{RandStringRunes(sessKeyLen)}\n\tmu.Unlock()\n\tsessions[id] = in\n\treturn &id, nil\n}\n\nfunc AuthCheckSession(in *SessionID) *Session {\n\tmu.RLock()\n\tdefer mu.RUnlock()\n\tif sess, ok := sessions[*in]; ok {\n\t\treturn sess\n\t}\n\treturn nil\n}\n\nfunc AuthSessionDelete(in *SessionID) {\n\tmu.Lock()\n\tdefer mu.Unlock()\n\tdelete(sessions, *in)\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "8-microservices/0_service/2_step/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n)\n\nvar loginFormTmpl = []byte(`\n<html>\n\t<body>\n\t<form action=\"/login\" method=\"post\">\n\t\tLogin: <input type=\"text\" name=\"login\">\n\t\tPassword: <input type=\"password\" name=\"password\">\n\t\t<input type=\"submit\" value=\"Login\">\n\t</form>\n\t</body>\n</html>\n`)\n\nvar (\n\tsessManager SessionManagerInterface\n)\n\nfunc checkSession(r *http.Request) (*Session, error) {\n\tcookieSessionID, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\treturn nil, nil\n\t} else if err != nil {\n\t\treturn nil, err\n\t}\n\n\tsess := sessManager.Check(&SessionID{\n\t\tID: cookieSessionID.Value,\n\t})\n\treturn sess, nil\n}\n\nfunc innerPage(w http.ResponseWriter, r *http.Request) {\n\tsess, err := checkSession(r)\n\tif err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif sess == nil {\n\t\tw.Write(loginFormTmpl)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"text/html\")\n\tfmt.Fprintln(w, \"Welcome, \"+sess.Login+\" <br />\")\n\tfmt.Fprintln(w, \"Session ua: \"+sess.Useragent+\" <br />\")\n\tfmt.Fprintln(w, `<a href=\"/logout\">logout</a>`)\n}\n\nfunc loginPage(w http.ResponseWriter, r *http.Request) {\n\tinputLogin := r.FormValue(\"login\")\n\texpiration := time.Now().Add(365 * 24 * time.Hour)\n\n\tsess, err := sessManager.Create(&Session{\n\t\tLogin:     inputLogin,\n\t\tUseragent: r.UserAgent(),\n\t})\n\tif err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   sess.ID,\n\t\tExpires: expiration,\n\t}\n\thttp.SetCookie(w, &cookie)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc main() {\n\n\tsessManager = NewSessionManager()\n\n\thttp.HandleFunc(\"/\", innerPage)\n\thttp.HandleFunc(\"/login\", loginPage)\n\thttp.HandleFunc(\"/logout\", logoutPage)\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\nfunc logoutPage(w http.ResponseWriter, r *http.Request) {\n\tsession, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t\treturn\n\t} else if err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tsessManager.Delete(&SessionID{\n\t\tID: session.Value,\n\t})\n\n\tsession.Expires = time.Now().AddDate(0, 0, -1)\n\thttp.SetCookie(w, session)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n"
  },
  {
    "path": "8-microservices/0_service/2_step/run_test.go",
    "content": "package main\n\nimport (\n\t\"testing\"\n)\n\nfunc TestExample(t *testing.T) {\n\tsessManager = NewSessionManager()\n\n\t// создаем сессию\n\tsessId, err := sessManager.Create(\n\t\t&Session{\n\t\t\tLogin:     \"anton\",\n\t\t\tUseragent: \"safari\",\n\t\t})\n\tt.Log(\"sessId\", sessId, err)\n\n\t// проеряем сессию\n\tsess := sessManager.Check(\n\t\t&SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\tt.Log(\"sess\", sess)\n\n\t// удаляем сессию\n\tsessManager.Delete(\n\t\t&SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\n\t// проверяем еще раз\n\tsess = sessManager.Check(\n\t\t&SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\tt.Log(\"sess\", sess)\n\tt.Fail()\n}\n"
  },
  {
    "path": "8-microservices/0_service/2_step/session.go",
    "content": "package main\n\nimport (\n\t\"math/rand\"\n\t\"sync\"\n)\n\ntype Session struct {\n\tLogin     string\n\tUseragent string\n}\n\ntype SessionID struct {\n\tID string\n}\n\nconst sessKeyLen = 10\n\ntype SessionManagerInterface interface {\n\tCreate(in *Session) (*SessionID, error)\n\tCheck(in *SessionID) *Session\n\tDelete(in *SessionID)\n}\n\ntype SessionManager struct {\n\tmu       sync.RWMutex\n\tsessions map[SessionID]*Session\n}\n\nfunc NewSessionManager() *SessionManager {\n\treturn &SessionManager{\n\t\tmu:       sync.RWMutex{},\n\t\tsessions: map[SessionID]*Session{},\n\t}\n}\n\nfunc (sm *SessionManager) Create(in *Session) (*SessionID, error) {\n\tsm.mu.Lock()\n\tid := SessionID{RandStringRunes(sessKeyLen)}\n\tsm.mu.Unlock()\n\tsm.sessions[id] = in\n\treturn &id, nil\n}\n\nfunc (sm *SessionManager) Check(in *SessionID) *Session {\n\tsm.mu.RLock()\n\tdefer sm.mu.RUnlock()\n\tif sess, ok := sm.sessions[*in]; ok {\n\t\treturn sess\n\t}\n\treturn nil\n}\n\nfunc (sm *SessionManager) Delete(in *SessionID) {\n\tsm.mu.Lock()\n\tdefer sm.mu.Unlock()\n\tdelete(sm.sessions, *in)\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "8-microservices/1_net-rpc/client/client.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n)\n\nvar loginFormTmpl = []byte(`\n<html>\n\t<body>\n\t<form action=\"/login\" method=\"post\">\n\t\tLogin: <input type=\"text\" name=\"login\">\n\t\tPassword: <input type=\"password\" name=\"password\">\n\t\t<input type=\"submit\" value=\"Login\">\n\t</form>\n\t</body>\n</html>\n`)\n\nvar (\n\tsessManager *SessionManager\n)\n\nfunc checkSession(r *http.Request) (*Session, error) {\n\tcookieSessionID, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\treturn nil, nil\n\t} else if err != nil {\n\t\treturn nil, err\n\t}\n\n\tsess := sessManager.Check(&SessionID{\n\t\tID: cookieSessionID.Value,\n\t})\n\treturn sess, nil\n}\n\nfunc innerPage(w http.ResponseWriter, r *http.Request) {\n\tsess, err := checkSession(r)\n\tif err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif sess == nil {\n\t\tw.Write(loginFormTmpl)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"text/html\")\n\tfmt.Fprintln(w, \"Welcome, \"+sess.Login+\" <br />\")\n\tfmt.Fprintln(w, \"Session ua: \"+sess.Useragent+\" <br />\")\n\tfmt.Fprintln(w, `<a href=\"/logout\">logout</a>`)\n}\n\nfunc loginPage(w http.ResponseWriter, r *http.Request) {\n\tinputLogin := r.FormValue(\"login\")\n\texpiration := time.Now().Add(365 * 24 * time.Hour)\n\n\tsess, err := sessManager.Create(&Session{\n\t\tLogin:     inputLogin,\n\t\tUseragent: r.UserAgent(),\n\t})\n\tif err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   sess.ID,\n\t\tExpires: expiration,\n\t}\n\thttp.SetCookie(w, &cookie)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc main() {\n\n\tsessManager = NewSessionManager()\n\n\thttp.HandleFunc(\"/\", innerPage)\n\thttp.HandleFunc(\"/login\", loginPage)\n\thttp.HandleFunc(\"/logout\", logoutPage)\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\nfunc logoutPage(w http.ResponseWriter, r *http.Request) {\n\tsession, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t\treturn\n\t} else if err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tsessManager.Delete(&SessionID{\n\t\tID: session.Value,\n\t})\n\n\tsession.Expires = time.Now().AddDate(0, 0, -1)\n\thttp.SetCookie(w, session)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n"
  },
  {
    "path": "8-microservices/1_net-rpc/client/run_test.go",
    "content": "package main\n\nimport (\n\t\"testing\"\n)\n\nfunc TestRun(t *testing.T) {\n\n\tsessManager = NewSessionManager()\n\n\t// создаем сессию\n\tsessId, err := sessManager.Create(\n\t\t&Session{\n\t\t\tLogin:     \"anton\",\n\t\t\tUseragent: \"safari\",\n\t\t})\n\tt.Log(\"sessId\", sessId, err)\n\n\t// проеряем сессию\n\tsess := sessManager.Check(\n\t\t&SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\tt.Log(\"sess\", sess)\n\n\t// удаляем сессию\n\tsessManager.Delete(\n\t\t&SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\n\t// проверяем еще раз\n\tsess = sessManager.Check(\n\t\t&SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\tt.Log(\"sess\", sess)\n\tt.Fail()\n}\n"
  },
  {
    "path": "8-microservices/1_net-rpc/client/session.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/rpc\"\n)\n\ntype Session struct {\n\tLogin     string\n\tUseragent string\n}\n\ntype SessionID struct {\n\tID string\n}\n\ntype SessionManagerI interface {\n\tCreate(*Session) (*SessionID, error)\n\tCheck(*SessionID) *Session\n\tDelete(*SessionID)\n}\n\ntype SessionManager struct {\n\tclient *rpc.Client\n}\n\nfunc NewSessionManager() *SessionManager {\n\tclient, err := rpc.DialHTTP(\"tcp\", \"localhost:8081\")\n\tif err != nil {\n\t\tlog.Fatal(\"dialing:\", err)\n\t}\n\n\treturn &SessionManager{\n\t\tclient: client,\n\t}\n}\n\nfunc (sm *SessionManager) Create(in *Session) (*SessionID, error) {\n\tid := new(SessionID)\n\terr := sm.client.Call(\"SessionManager.Create\", in, id)\n\tif err != nil {\n\t\tfmt.Println(\"SessionManager.Create error:\", err)\n\t\treturn nil, nil\n\t}\n\treturn id, nil\n}\n\nfunc (sm *SessionManager) Check(in *SessionID) *Session {\n\tsess := new(Session)\n\terr := sm.client.Call(\"SessionManager.Check\", in, sess)\n\tif err != nil {\n\t\tfmt.Println(\"SessionManager.Check error:\", err)\n\t\treturn nil\n\t}\n\treturn sess\n}\n\nfunc (sm *SessionManager) Delete(in *SessionID) {\n\tvar reply int\n\terr := sm.client.Call(\"SessionManager.Delete\", in, &reply)\n\tif err != nil {\n\t\tfmt.Println(\"SessionManager.Delete error:\", err)\n\t}\n}\n"
  },
  {
    "path": "8-microservices/1_net-rpc/server/server.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/rpc\"\n)\n\nfunc main() {\n\tsessManager := NewSessManager()\n\n\trpc.Register(sessManager)\n\trpc.HandleHTTP()\n\n\tl, e := net.Listen(\"tcp\", \":8081\")\n\tif e != nil {\n\t\tlog.Fatal(\"listen error:\", e)\n\t}\n\n\tfmt.Println(\"starting server at :8081\")\n\thttp.Serve(l, nil)\n}\n"
  },
  {
    "path": "8-microservices/1_net-rpc/server/session.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"sync\"\n)\n\ntype Session struct {\n\tLogin     string\n\tUseragent string\n}\n\ntype SessionID struct {\n\tID string\n}\n\nconst sessKeyLen = 10\n\ntype SessionManager struct {\n\tmu       sync.RWMutex\n\tsessions map[SessionID]*Session\n}\n\nfunc NewSessManager() *SessionManager {\n\treturn &SessionManager{\n\t\tmu:       sync.RWMutex{},\n\t\tsessions: map[SessionID]*Session{},\n\t}\n}\n\n// func (sm *SessionManager) Create(in *Session) (*SessionID, error) {\n\nfunc (sm *SessionManager) Create(in *Session, out *SessionID) error {\n\tfmt.Println(\"call Create\", in)\n\tid := &SessionID{RandStringRunes(sessKeyLen)}\n\tsm.mu.Lock()\n\tsm.sessions[*id] = in\n\tsm.mu.Unlock()\n\t*out = *id\n\treturn nil\n}\n\nfunc (sm *SessionManager) Check(in *SessionID, out *Session) error {\n\tfmt.Println(\"call Check\", in)\n\tsm.mu.RLock()\n\tdefer sm.mu.RUnlock()\n\tif sess, ok := sm.sessions[*in]; ok {\n\t\t*out = *sess\n\t}\n\treturn nil\n}\n\nfunc (sm *SessionManager) Delete(in *SessionID, out *int) error {\n\tfmt.Println(\"call Delete\", in)\n\tsm.mu.Lock()\n\tdefer sm.mu.Unlock()\n\tdelete(sm.sessions, *in)\n\t*out = 1\n\treturn nil\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "8-microservices/2_json-rpc/client/client.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n)\n\nvar loginFormTmpl = []byte(`\n<html>\n\t<body>\n\t<form action=\"/login\" method=\"post\">\n\t\tLogin: <input type=\"text\" name=\"login\">\n\t\tPassword: <input type=\"password\" name=\"password\">\n\t\t<input type=\"submit\" value=\"Login\">\n\t</form>\n\t</body>\n</html>\n`)\n\nvar (\n\tsessManager *SessionManager\n)\n\nfunc checkSession(r *http.Request) (*Session, error) {\n\tcookieSessionID, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\treturn nil, nil\n\t} else if err != nil {\n\t\treturn nil, err\n\t}\n\n\tsess := sessManager.Check(&SessionID{\n\t\tID: cookieSessionID.Value,\n\t})\n\treturn sess, nil\n}\n\nfunc innerPage(w http.ResponseWriter, r *http.Request) {\n\tsess, err := checkSession(r)\n\tif err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif sess == nil {\n\t\tw.Write(loginFormTmpl)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"text/html\")\n\tfmt.Fprintln(w, \"Welcome, \"+sess.Login+\" <br />\")\n\tfmt.Fprintln(w, \"Session ua: \"+sess.Useragent+\" <br />\")\n\tfmt.Fprintln(w, `<a href=\"/logout\">logout</a>`)\n}\n\nfunc loginPage(w http.ResponseWriter, r *http.Request) {\n\tinputLogin := r.FormValue(\"login\")\n\texpiration := time.Now().Add(365 * 24 * time.Hour)\n\n\tsess, err := sessManager.Create(&Session{\n\t\tLogin:     inputLogin,\n\t\tUseragent: r.UserAgent(),\n\t})\n\tif err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   sess.ID,\n\t\tExpires: expiration,\n\t}\n\thttp.SetCookie(w, &cookie)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc main() {\n\n\tsessManager = NewSessionManager()\n\n\thttp.HandleFunc(\"/\", innerPage)\n\thttp.HandleFunc(\"/login\", loginPage)\n\thttp.HandleFunc(\"/logout\", logoutPage)\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\nfunc logoutPage(w http.ResponseWriter, r *http.Request) {\n\tsession, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t\treturn\n\t} else if err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tsessManager.Delete(&SessionID{\n\t\tID: session.Value,\n\t})\n\n\tsession.Expires = time.Now().AddDate(0, 0, -1)\n\thttp.SetCookie(w, session)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n"
  },
  {
    "path": "8-microservices/2_json-rpc/client/run_test.go",
    "content": "package main\n\nimport (\n\t\"testing\"\n)\n\nfunc TestRun(t *testing.T) {\n\n\tsessManager = NewSessionManager()\n\n\t// создаем сессию\n\tsessId, err := sessManager.Create(\n\t\t&Session{\n\t\t\tLogin:     \"anton\",\n\t\t\tUseragent: \"safari\",\n\t\t})\n\tt.Log(\"sessId\", sessId, err)\n\n\t// проеряем сессию\n\tsess := sessManager.Check(\n\t\t&SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\tt.Log(\"sess\", sess)\n\n\t// удаляем сессию\n\tsessManager.Delete(\n\t\t&SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\n\t// проверяем еще раз\n\tsess = sessManager.Check(\n\t\t&SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\tt.Log(\"sess\", sess)\n\tt.Fail()\n}\n"
  },
  {
    "path": "8-microservices/2_json-rpc/client/session.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\n\tjsonrpc \"github.com/ybbus/jsonrpc/v2\"\n)\n\ntype Session struct {\n\tLogin     string\n\tUseragent string\n}\n\ntype SessionID struct {\n\tID string\n}\n\ntype SessionManagerI interface {\n\tCreate(*Session) (*SessionID, error)\n\tCheck(*SessionID) *Session\n\tDelete(*SessionID)\n}\n\ntype SessionManager struct {\n\tclient jsonrpc.RPCClient\n}\n\nfunc NewSessionManager() *SessionManager {\n\tclient := jsonrpc.NewClient(\"http://localhost:8081/rpc\")\n\n\treturn &SessionManager{\n\t\tclient: client,\n\t}\n}\n\nfunc (sm *SessionManager) Create(in *Session) (*SessionID, error) {\n\tid := new(SessionID)\n\t_, err := sm.client.Call(\"SessionManager.Create\", in, id)\n\tif err != nil {\n\t\tfmt.Println(\"SessionManager.Create error:\", err)\n\t\treturn nil, nil\n\t}\n\treturn id, nil\n}\n\nfunc (sm *SessionManager) Check(in *SessionID) *Session {\n\tsess := new(Session)\n\t_, err := sm.client.Call(\"SessionManager.Check\", in, sess)\n\tif err != nil {\n\t\tfmt.Println(\"SessionManager.Check error:\", err)\n\t\treturn nil\n\t}\n\treturn sess\n}\n\nfunc (sm *SessionManager) Delete(in *SessionID) {\n\tvar reply int\n\t_, err := sm.client.Call(\"SessionManager.Delete\", in, &reply)\n\tif err != nil {\n\t\tfmt.Println(\"SessionManager.Delete error:\", err)\n\t}\n}\n"
  },
  {
    "path": "8-microservices/2_json-rpc/server/server.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"net/rpc\"\n\t\"net/rpc/jsonrpc\"\n)\n\ntype HttpConn struct {\n\tin  io.Reader\n\tout io.Writer\n}\n\nfunc (c *HttpConn) Read(p []byte) (n int, err error)  { return c.in.Read(p) }\nfunc (c *HttpConn) Write(d []byte) (n int, err error) { return c.out.Write(d) }\nfunc (c *HttpConn) Close() error                      { return nil }\n\n/*\n{\n   \"jsonrpc\":\"2.0\",\n   \"id\":1,\n   \"method\":\"SessionManager.Create\",\n   \"params\":[\n      {\n         \"login\":\"rvasily\",\n         \"useragent\":\"chrome\"\n      }\n   ]\n}\n*/\n\n/*\n\ncurl -v -X POST -H \"Content-Type: application/json\" -H \"X-Auth: 123\" -d '{\"jsonrpc\":\"2.0\", \"id\": 1, \"method\": \"SessionManager.Create\", \"params\": [{\"login\":\"rvasily\", \"useragent\": \"chrome\"}]}' http://localhost:8081/rpc\n\ncurl -v -X POST -H \"Content-Type: application/json\" -H \"X-Auth: 123\" -d '{\"jsonrpc\":\"2.0\", \"id\": 2, \"method\": \"SessionManager.Check\", \"params\": [{\"id\":\"XVlBzgbaiC\"}]}' http://localhost:8081/rpc\n\n*/\n\ntype Handler struct {\n\trpcServer *rpc.Server\n}\n\nfunc (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n\tfmt.Println(\"rpc auth: \", r.Header.Get(\"X-Auth\"))\n\n\tserverCodec := jsonrpc.NewServerCodec(&HttpConn{\n\t\tin:  r.Body,\n\t\tout: w,\n\t})\n\tw.Header().Set(\"Content-type\", \"application/json\")\n\terr := h.rpcServer.ServeRequest(serverCodec)\n\tif err != nil {\n\t\tlog.Printf(\"Error while serving JSON request: %v\", err)\n\t\thttp.Error(w, `{\"error\":\"cant serve request\"}`, 500)\n\t} else {\n\t\tw.WriteHeader(200)\n\t}\n}\n\nfunc main() {\n\tsessManager := NewSessManager()\n\n\tserver := rpc.NewServer()\n\tserver.Register(sessManager)\n\n\tsessionHandler := &Handler{\n\t\trpcServer: server,\n\t}\n\thttp.Handle(\"/rpc\", sessionHandler)\n\n\tfmt.Println(\"starting server at :8081\")\n\thttp.ListenAndServe(\":8081\", nil)\n\n}\n"
  },
  {
    "path": "8-microservices/2_json-rpc/server/session.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"sync\"\n)\n\ntype Session struct {\n\tLogin     string\n\tUseragent string\n}\n\ntype SessionID struct {\n\tID string\n}\n\nconst sessKeyLen = 10\n\ntype SessionManager struct {\n\tmu       sync.RWMutex\n\tsessions map[SessionID]*Session\n}\n\nfunc NewSessManager() *SessionManager {\n\treturn &SessionManager{\n\t\tmu:       sync.RWMutex{},\n\t\tsessions: map[SessionID]*Session{},\n\t}\n}\n\nfunc (sm *SessionManager) Create(in *Session, out *SessionID) error {\n\tfmt.Println(\"call Create\", in)\n\tid := &SessionID{RandStringRunes(sessKeyLen)}\n\tsm.mu.Lock()\n\tsm.sessions[*id] = in\n\tsm.mu.Unlock()\n\t*out = *id\n\treturn nil\n}\n\nfunc (sm *SessionManager) Check(in *SessionID, out *Session) error {\n\tfmt.Println(\"call Check\", in)\n\tsm.mu.RLock()\n\tdefer sm.mu.RUnlock()\n\tif sess, ok := sm.sessions[*in]; ok {\n\t\t*out = *sess\n\t}\n\treturn nil\n}\n\nfunc (sm *SessionManager) Delete(in *SessionID, out *int) error {\n\tfmt.Println(\"call Delete\", in)\n\tsm.mu.Lock()\n\tdefer sm.mu.Unlock()\n\tdelete(sm.sessions, *in)\n\t*out = 1\n\treturn nil\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "8-microservices/3_protobuf/main.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"github.com/golang/protobuf/proto\"\n\t\"gopkg.in/vmihailenco/msgpack.v2\"\n)\n\n// protoc --go_out=. *.proto\n\nfunc main() {\n\tsess := &Session{\n\t\tLogin:     \"vasiliy\",\n\t\tUseragent: \"Chrome\",\n\t}\n\n\tdataJson, _ := json.Marshal(sess)\n\n\tfmt.Printf(\"dataJson: %s\\n\", string(dataJson))\n\tfmt.Printf(\"dataJson\\nlen %d\\n%v\\n\", len(dataJson), dataJson)\n\n\t/*\n\t\t39 байт\n\t\t{\"login\":\"dmitry\",\"useragent\":\"Chrome\"}\n\t*/\n\n\tdataPb, _ := proto.Marshal(sess)\n\tfmt.Printf(\"dataPb\\nlen %d\\n%v\\n\", len(dataPb), dataPb)\n\n\t/*\n\t\t17 байт\n\t\t[10 7 114 118 97 115 105 108 121 18 6 67 104 114 111 109 101]\n\n\t\t\t10 // номер поля + тип\n\t\t\t7  // длина данных\n\t\t\t\t114 118 97 115 105 108 121\n\n\t\t\t18 // номер поля + тип\n\t\t\t6  // длина данных\n\t\t\t\t67 104 114 111 109 101\n\t*/\n\n\tdataMsgPack, _ := msgpack.Marshal(sess)\n\tfmt.Printf(\"dataMsgPack\\nlen %d\\n%v\\n\", len(dataMsgPack), dataMsgPack)\n}\n"
  },
  {
    "path": "8-microservices/3_protobuf/session.pb.go",
    "content": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.26.0\n// \tprotoc        v3.17.3\n// source: session.proto\n\npackage main\n\nimport (\n\tprotoreflect \"google.golang.org/protobuf/reflect/protoreflect\"\n\tprotoimpl \"google.golang.org/protobuf/runtime/protoimpl\"\n\treflect \"reflect\"\n\tsync \"sync\"\n)\n\nconst (\n\t// Verify that this generated code is sufficiently up-to-date.\n\t_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)\n\t// Verify that runtime/protoimpl is sufficiently up-to-date.\n\t_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)\n)\n\ntype SessionID struct {\n\tstate         protoimpl.MessageState\n\tsizeCache     protoimpl.SizeCache\n\tunknownFields protoimpl.UnknownFields\n\n\tID string `protobuf:\"bytes,1,opt,name=ID,proto3\" json:\"ID,omitempty\"`\n}\n\nfunc (x *SessionID) Reset() {\n\t*x = SessionID{}\n\tif protoimpl.UnsafeEnabled {\n\t\tmi := &file_session_proto_msgTypes[0]\n\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n\t\tms.StoreMessageInfo(mi)\n\t}\n}\n\nfunc (x *SessionID) String() string {\n\treturn protoimpl.X.MessageStringOf(x)\n}\n\nfunc (*SessionID) ProtoMessage() {}\n\nfunc (x *SessionID) ProtoReflect() protoreflect.Message {\n\tmi := &file_session_proto_msgTypes[0]\n\tif protoimpl.UnsafeEnabled && x != nil {\n\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n\t\tif ms.LoadMessageInfo() == nil {\n\t\t\tms.StoreMessageInfo(mi)\n\t\t}\n\t\treturn ms\n\t}\n\treturn mi.MessageOf(x)\n}\n\n// Deprecated: Use SessionID.ProtoReflect.Descriptor instead.\nfunc (*SessionID) Descriptor() ([]byte, []int) {\n\treturn file_session_proto_rawDescGZIP(), []int{0}\n}\n\nfunc (x *SessionID) GetID() string {\n\tif x != nil {\n\t\treturn x.ID\n\t}\n\treturn \"\"\n}\n\ntype Session struct {\n\tstate         protoimpl.MessageState\n\tsizeCache     protoimpl.SizeCache\n\tunknownFields protoimpl.UnknownFields\n\n\tLogin     string `protobuf:\"bytes,1,opt,name=login,proto3\" json:\"login,omitempty\"`\n\tUseragent string `protobuf:\"bytes,2,opt,name=useragent,proto3\" json:\"useragent,omitempty\"`\n}\n\nfunc (x *Session) Reset() {\n\t*x = Session{}\n\tif protoimpl.UnsafeEnabled {\n\t\tmi := &file_session_proto_msgTypes[1]\n\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n\t\tms.StoreMessageInfo(mi)\n\t}\n}\n\nfunc (x *Session) String() string {\n\treturn protoimpl.X.MessageStringOf(x)\n}\n\nfunc (*Session) ProtoMessage() {}\n\nfunc (x *Session) ProtoReflect() protoreflect.Message {\n\tmi := &file_session_proto_msgTypes[1]\n\tif protoimpl.UnsafeEnabled && x != nil {\n\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n\t\tif ms.LoadMessageInfo() == nil {\n\t\t\tms.StoreMessageInfo(mi)\n\t\t}\n\t\treturn ms\n\t}\n\treturn mi.MessageOf(x)\n}\n\n// Deprecated: Use Session.ProtoReflect.Descriptor instead.\nfunc (*Session) Descriptor() ([]byte, []int) {\n\treturn file_session_proto_rawDescGZIP(), []int{1}\n}\n\nfunc (x *Session) GetLogin() string {\n\tif x != nil {\n\t\treturn x.Login\n\t}\n\treturn \"\"\n}\n\nfunc (x *Session) GetUseragent() string {\n\tif x != nil {\n\t\treturn x.Useragent\n\t}\n\treturn \"\"\n}\n\nvar File_session_proto protoreflect.FileDescriptor\n\nvar file_session_proto_rawDesc = []byte{\n\t0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,\n\t0x04, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x1b, 0x0a, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,\n\t0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,\n\t0x49, 0x44, 0x22, 0x3d, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a,\n\t0x05, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x6f,\n\t0x67, 0x69, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x61, 0x67, 0x65, 0x6e, 0x74,\n\t0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x61, 0x67, 0x65, 0x6e,\n\t0x74, 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x2f, 0x3b, 0x6d, 0x61, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72,\n\t0x6f, 0x74, 0x6f, 0x33,\n}\n\nvar (\n\tfile_session_proto_rawDescOnce sync.Once\n\tfile_session_proto_rawDescData = file_session_proto_rawDesc\n)\n\nfunc file_session_proto_rawDescGZIP() []byte {\n\tfile_session_proto_rawDescOnce.Do(func() {\n\t\tfile_session_proto_rawDescData = protoimpl.X.CompressGZIP(file_session_proto_rawDescData)\n\t})\n\treturn file_session_proto_rawDescData\n}\n\nvar file_session_proto_msgTypes = make([]protoimpl.MessageInfo, 2)\nvar file_session_proto_goTypes = []interface{}{\n\t(*SessionID)(nil), // 0: main.SessionID\n\t(*Session)(nil),   // 1: main.Session\n}\nvar file_session_proto_depIdxs = []int32{\n\t0, // [0:0] is the sub-list for method output_type\n\t0, // [0:0] is the sub-list for method input_type\n\t0, // [0:0] is the sub-list for extension type_name\n\t0, // [0:0] is the sub-list for extension extendee\n\t0, // [0:0] is the sub-list for field type_name\n}\n\nfunc init() { file_session_proto_init() }\nfunc file_session_proto_init() {\n\tif File_session_proto != nil {\n\t\treturn\n\t}\n\tif !protoimpl.UnsafeEnabled {\n\t\tfile_session_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {\n\t\t\tswitch v := v.(*SessionID); i {\n\t\t\tcase 0:\n\t\t\t\treturn &v.state\n\t\t\tcase 1:\n\t\t\t\treturn &v.sizeCache\n\t\t\tcase 2:\n\t\t\t\treturn &v.unknownFields\n\t\t\tdefault:\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t\tfile_session_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {\n\t\t\tswitch v := v.(*Session); i {\n\t\t\tcase 0:\n\t\t\t\treturn &v.state\n\t\t\tcase 1:\n\t\t\t\treturn &v.sizeCache\n\t\t\tcase 2:\n\t\t\t\treturn &v.unknownFields\n\t\t\tdefault:\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t}\n\ttype x struct{}\n\tout := protoimpl.TypeBuilder{\n\t\tFile: protoimpl.DescBuilder{\n\t\t\tGoPackagePath: reflect.TypeOf(x{}).PkgPath(),\n\t\t\tRawDescriptor: file_session_proto_rawDesc,\n\t\t\tNumEnums:      0,\n\t\t\tNumMessages:   2,\n\t\t\tNumExtensions: 0,\n\t\t\tNumServices:   0,\n\t\t},\n\t\tGoTypes:           file_session_proto_goTypes,\n\t\tDependencyIndexes: file_session_proto_depIdxs,\n\t\tMessageInfos:      file_session_proto_msgTypes,\n\t}.Build()\n\tFile_session_proto = out.File\n\tfile_session_proto_rawDesc = nil\n\tfile_session_proto_goTypes = nil\n\tfile_session_proto_depIdxs = nil\n}\n"
  },
  {
    "path": "8-microservices/3_protobuf/session.proto",
    "content": "syntax = \"proto3\";\n\noption go_package = \"./;main\";\n// protoc --go_out=. *.proto\n\npackage main;\n\nmessage SessionID {\n  string ID = 1;\n}\n\nmessage Session {\n  string login = 1;\n  string useragent = 2;\n}\n"
  },
  {
    "path": "8-microservices/4_grpc/client/main.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"google.golang.org/grpc\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/4_grpc/session\"\n)\n\nvar loginFormTmpl = []byte(`\n<html>\n\t<body>\n\t<form action=\"/login\" method=\"post\">\n\t\tLogin: <input type=\"text\" name=\"login\">\n\t\tPassword: <input type=\"password\" name=\"password\">\n\t\t<input type=\"submit\" value=\"Login\">\n\t</form>\n\t</body>\n</html>\n`)\n\nvar (\n\tsessManager session.AuthCheckerClient\n)\n\nfunc checkSession(r *http.Request) (*session.Session, error) {\n\tcookieSessionID, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\treturn nil, nil\n\t} else if err != nil {\n\t\treturn nil, err\n\t}\n\n\tsess, err := sessManager.Check(\n\t\tcontext.Background(),\n\t\t&session.SessionID{\n\t\t\tID: cookieSessionID.Value,\n\t\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn sess, nil\n}\n\nfunc innerPage(w http.ResponseWriter, r *http.Request) {\n\tsess, err := checkSession(r)\n\tif err != nil {\n\t\tw.Write(loginFormTmpl)\n\t\treturn\n\t}\n\tif sess == nil {\n\t\tw.Write(loginFormTmpl)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"text/html\")\n\tfmt.Fprintln(w, \"Welcome, \"+sess.Login+\" <br />\")\n\tfmt.Fprintln(w, \"Session ua: \"+sess.Useragent+\" <br />\")\n\tfmt.Fprintln(w, `<a href=\"/logout\">logout</a>`)\n}\n\nfunc loginPage(w http.ResponseWriter, r *http.Request) {\n\tinputLogin := r.FormValue(\"login\")\n\texpiration := time.Now().Add(365 * 24 * time.Hour)\n\n\tsess, err := sessManager.Create(\n\t\tcontext.Background(),\n\t\t&session.Session{\n\t\t\tLogin:     inputLogin,\n\t\t\tUseragent: r.UserAgent(),\n\t\t})\n\tif err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   sess.ID,\n\t\tExpires: expiration,\n\t}\n\thttp.SetCookie(w, &cookie)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc main() {\n\n\tgrcpConn, err := grpc.Dial(\n\t\t\"127.0.0.1:8081\",\n\t\tgrpc.WithInsecure(),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"cant connect to grpc\")\n\t}\n\tdefer grcpConn.Close()\n\n\tsessManager = session.NewAuthCheckerClient(grcpConn)\n\n\thttp.HandleFunc(\"/\", innerPage)\n\thttp.HandleFunc(\"/login\", loginPage)\n\thttp.HandleFunc(\"/logout\", logoutPage)\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\nfunc logoutPage(w http.ResponseWriter, r *http.Request) {\n\tcookieSessionID, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t\treturn\n\t} else if err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tsessManager.Delete(\n\t\tcontext.Background(),\n\t\t&session.SessionID{\n\t\t\tID: cookieSessionID.Value,\n\t\t})\n\n\tcookieSessionID.Expires = time.Now().AddDate(0, 0, -1)\n\thttp.SetCookie(w, cookieSessionID)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n"
  },
  {
    "path": "8-microservices/4_grpc/client/run_test.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"testing\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/4_grpc/session\"\n\t\"google.golang.org/grpc\"\n)\n\nfunc TestRun(t *testing.T) {\n\n\tgrcpConn, err := grpc.Dial(\n\t\t\"127.0.0.1:8081\",\n\t\tgrpc.WithInsecure(),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"cant connect to grpc\")\n\t}\n\tdefer grcpConn.Close()\n\n\tsessManager := session.NewAuthCheckerClient(grcpConn)\n\n\tctx := context.Background()\n\n\t// создаем сессию\n\tsessId, err := sessManager.Create(ctx,\n\t\t&session.Session{\n\t\t\tLogin:     \"rvasily\",\n\t\t\tUseragent: \"chrome\",\n\t\t})\n\tlog.Println(\"sessId\", sessId, err)\n\n\t// проеряем сессию\n\tsess, err := sessManager.Check(ctx,\n\t\t&session.SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\tlog.Println(\"sess\", sess, err)\n\n\t// удаляем сессию\n\t_, err = sessManager.Delete(ctx,\n\t\t&session.SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\n\t// проверяем еще раз\n\tsess, err = sessManager.Check(ctx,\n\t\t&session.SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\tlog.Println(\"sess\", sess, err)\n\tt.Fail()\n}\n"
  },
  {
    "path": "8-microservices/4_grpc/readme.md",
    "content": "пример с микросервисом авторизации\n\nсмысл:\n\n* проверяем авторизацию в 1 месте из разных сервисов, можем горизонатльно масштабироваться (увеличивать количество серверов)\n* скрываем детали реализации хранения - теперь это может быть мапка в памяти, мемкеш, таранутл, файлы, база, libastral\n\n# 1 старый способ генерации. он deprecated, но может еще работать\n\n1. надо скачать protoc (<https://github.com/google/protobuf/releases>)\n2. go get -u github.com/golang/protobuf/{proto,protoc-gen-go}\n3. go get -u google.golang.org/grpc\n4. go get -u golang.org/x/net/context\n\nГенерация кода:\n\n* находясь в папке session сгенерируем код для го `protoc --go_out=plugins=grpc:. *.proto`\n* подобной командой так же генерируется нужная обвязка для других поддерживаемых языков\n* go_out означает что мы хотим сгенерировать код в этой папке для языка go\n* plugins=grpc созначает что мы хотим использовать ещё плагин для генерации grpc-сервиса\n\nдополнительная документация\n\n* <https://developers.google.com/protocol-buffers/docs/gotutorial>\n* <https://github.com/grpc/grpc-go/tree/master/examples>\n* <https://habrahabr.ru/company/infopulse/blog/265805/>\n\nwindows:\nDownload protoc-win32.zip from <https://developers.google.com/protocol-buffers/docs/downloads>\nUnzip and add location of the protoc.exe to your PATH environment variable\nRun `protoc --version` from command prompt to verify\nVerify the your GOPATH environment variable is set\nRun `go get -u github.com/golang/protobuf/protoc-gen-go` from command prompt. This should install the binary to %GOPATH%/bin\nAdd `%GOPATH%/bin` to your PATH environment variable\nOpen a new command prompt, navigate to your .proto file, run `protoc --go_out=. *.proto`\n\nесли ругается - надо читобы были доступны protoc.exe и protoc-gen-go.exe - прописать в PATH путь до них\n\n# 2 способ генерации. лучше им и пользоваться\n\n* ставим тулзу для генерации - protoc (это можно нагуглить)\n* ставим модуль go для protoc `go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26`\n* ставим модуль grpc для protoc `go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1`\n* генерим (на выходе получаем 2 файла. это ок): `protoc --go_out=. --go-grpc_out=. --go-grpc_opt=paths=source_relative --go_opt=paths=source_relative *.proto`\n"
  },
  {
    "path": "8-microservices/4_grpc/server/server.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/4_grpc/session\"\n\n\t\"google.golang.org/grpc\"\n)\n\nfunc main() {\n\tlis, err := net.Listen(\"tcp\", \":8081\")\n\tif err != nil {\n\t\tlog.Fatalln(\"cant listet port\", err)\n\t}\n\n\tserver := grpc.NewServer()\n\n\tsession.RegisterAuthCheckerServer(server, NewSessionManager())\n\n\tfmt.Println(\"starting server at :8081\")\n\tserver.Serve(lis)\n}\n"
  },
  {
    "path": "8-microservices/4_grpc/server/session.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"sync\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/4_grpc/session\"\n\n\t\"google.golang.org/grpc\"\n\t\"google.golang.org/grpc/codes\"\n\n\t\"context\"\n)\n\nconst sessKeyLen = 10\n\ntype SessionManager struct {\n\tsession.UnimplementedAuthCheckerServer\n\n\tmu       sync.RWMutex\n\tsessions map[string]*session.Session\n}\n\nfunc NewSessionManager() *SessionManager {\n\treturn &SessionManager{\n\t\tmu:       sync.RWMutex{},\n\t\tsessions: map[string]*session.Session{},\n\t}\n}\n\nfunc (sm *SessionManager) Create(ctx context.Context, in *session.Session) (*session.SessionID, error) {\n\tfmt.Println(\"call Create\", in)\n\tid := &session.SessionID{\n\t\tID: RandStringRunes(sessKeyLen),\n\t}\n\tsm.mu.Lock()\n\tsm.sessions[id.ID] = in\n\tsm.mu.Unlock()\n\treturn id, nil\n}\n\nfunc (sm *SessionManager) Check(ctx context.Context, in *session.SessionID) (*session.Session, error) {\n\tfmt.Println(\"call Check\", in)\n\tsm.mu.RLock()\n\tdefer sm.mu.RUnlock()\n\tif sess, ok := sm.sessions[in.ID]; ok {\n\t\treturn sess, nil\n\t}\n\treturn nil, grpc.Errorf(codes.NotFound, \"session not found\")\n}\n\nfunc (sm *SessionManager) Delete(ctx context.Context, in *session.SessionID) (*session.Nothing, error) {\n\tfmt.Println(\"call Delete\", in)\n\tsm.mu.Lock()\n\tdefer sm.mu.Unlock()\n\tdelete(sm.sessions, in.ID)\n\treturn &session.Nothing{Dummy: true}, nil\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "8-microservices/4_grpc/session/session.pb.go",
    "content": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.26.0\n// \tprotoc        v3.17.3\n// source: session.proto\n\npackage session\n\nimport (\n\tprotoreflect \"google.golang.org/protobuf/reflect/protoreflect\"\n\tprotoimpl \"google.golang.org/protobuf/runtime/protoimpl\"\n\treflect \"reflect\"\n\tsync \"sync\"\n)\n\nconst (\n\t// Verify that this generated code is sufficiently up-to-date.\n\t_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)\n\t// Verify that runtime/protoimpl is sufficiently up-to-date.\n\t_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)\n)\n\ntype SessionID struct {\n\tstate         protoimpl.MessageState\n\tsizeCache     protoimpl.SizeCache\n\tunknownFields protoimpl.UnknownFields\n\n\tID string `protobuf:\"bytes,1,opt,name=ID,proto3\" json:\"ID,omitempty\"`\n}\n\nfunc (x *SessionID) Reset() {\n\t*x = SessionID{}\n\tif protoimpl.UnsafeEnabled {\n\t\tmi := &file_session_proto_msgTypes[0]\n\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n\t\tms.StoreMessageInfo(mi)\n\t}\n}\n\nfunc (x *SessionID) String() string {\n\treturn protoimpl.X.MessageStringOf(x)\n}\n\nfunc (*SessionID) ProtoMessage() {}\n\nfunc (x *SessionID) ProtoReflect() protoreflect.Message {\n\tmi := &file_session_proto_msgTypes[0]\n\tif protoimpl.UnsafeEnabled && x != nil {\n\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n\t\tif ms.LoadMessageInfo() == nil {\n\t\t\tms.StoreMessageInfo(mi)\n\t\t}\n\t\treturn ms\n\t}\n\treturn mi.MessageOf(x)\n}\n\n// Deprecated: Use SessionID.ProtoReflect.Descriptor instead.\nfunc (*SessionID) Descriptor() ([]byte, []int) {\n\treturn file_session_proto_rawDescGZIP(), []int{0}\n}\n\nfunc (x *SessionID) GetID() string {\n\tif x != nil {\n\t\treturn x.ID\n\t}\n\treturn \"\"\n}\n\ntype Session struct {\n\tstate         protoimpl.MessageState\n\tsizeCache     protoimpl.SizeCache\n\tunknownFields protoimpl.UnknownFields\n\n\tLogin     string `protobuf:\"bytes,1,opt,name=login,proto3\" json:\"login,omitempty\"`\n\tUseragent string `protobuf:\"bytes,2,opt,name=useragent,proto3\" json:\"useragent,omitempty\"`\n}\n\nfunc (x *Session) Reset() {\n\t*x = Session{}\n\tif protoimpl.UnsafeEnabled {\n\t\tmi := &file_session_proto_msgTypes[1]\n\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n\t\tms.StoreMessageInfo(mi)\n\t}\n}\n\nfunc (x *Session) String() string {\n\treturn protoimpl.X.MessageStringOf(x)\n}\n\nfunc (*Session) ProtoMessage() {}\n\nfunc (x *Session) ProtoReflect() protoreflect.Message {\n\tmi := &file_session_proto_msgTypes[1]\n\tif protoimpl.UnsafeEnabled && x != nil {\n\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n\t\tif ms.LoadMessageInfo() == nil {\n\t\t\tms.StoreMessageInfo(mi)\n\t\t}\n\t\treturn ms\n\t}\n\treturn mi.MessageOf(x)\n}\n\n// Deprecated: Use Session.ProtoReflect.Descriptor instead.\nfunc (*Session) Descriptor() ([]byte, []int) {\n\treturn file_session_proto_rawDescGZIP(), []int{1}\n}\n\nfunc (x *Session) GetLogin() string {\n\tif x != nil {\n\t\treturn x.Login\n\t}\n\treturn \"\"\n}\n\nfunc (x *Session) GetUseragent() string {\n\tif x != nil {\n\t\treturn x.Useragent\n\t}\n\treturn \"\"\n}\n\ntype Nothing struct {\n\tstate         protoimpl.MessageState\n\tsizeCache     protoimpl.SizeCache\n\tunknownFields protoimpl.UnknownFields\n\n\tDummy bool `protobuf:\"varint,1,opt,name=dummy,proto3\" json:\"dummy,omitempty\"`\n}\n\nfunc (x *Nothing) Reset() {\n\t*x = Nothing{}\n\tif protoimpl.UnsafeEnabled {\n\t\tmi := &file_session_proto_msgTypes[2]\n\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n\t\tms.StoreMessageInfo(mi)\n\t}\n}\n\nfunc (x *Nothing) String() string {\n\treturn protoimpl.X.MessageStringOf(x)\n}\n\nfunc (*Nothing) ProtoMessage() {}\n\nfunc (x *Nothing) ProtoReflect() protoreflect.Message {\n\tmi := &file_session_proto_msgTypes[2]\n\tif protoimpl.UnsafeEnabled && x != nil {\n\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n\t\tif ms.LoadMessageInfo() == nil {\n\t\t\tms.StoreMessageInfo(mi)\n\t\t}\n\t\treturn ms\n\t}\n\treturn mi.MessageOf(x)\n}\n\n// Deprecated: Use Nothing.ProtoReflect.Descriptor instead.\nfunc (*Nothing) Descriptor() ([]byte, []int) {\n\treturn file_session_proto_rawDescGZIP(), []int{2}\n}\n\nfunc (x *Nothing) GetDummy() bool {\n\tif x != nil {\n\t\treturn x.Dummy\n\t}\n\treturn false\n}\n\nvar File_session_proto protoreflect.FileDescriptor\n\nvar file_session_proto_rawDesc = []byte{\n\t0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,\n\t0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x1b, 0x0a, 0x09, 0x53, 0x65, 0x73, 0x73,\n\t0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28,\n\t0x09, 0x52, 0x02, 0x49, 0x44, 0x22, 0x3d, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,\n\t0x12, 0x14, 0x0a, 0x05, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,\n\t0x05, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x61, 0x67,\n\t0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x61,\n\t0x67, 0x65, 0x6e, 0x74, 0x22, 0x1f, 0x0a, 0x07, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x12,\n\t0x14, 0x0a, 0x05, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05,\n\t0x64, 0x75, 0x6d, 0x6d, 0x79, 0x32, 0xa2, 0x01, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x68, 0x43, 0x68,\n\t0x65, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x30, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12,\n\t0x10, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,\n\t0x6e, 0x1a, 0x12, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x73, 0x73,\n\t0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b,\n\t0x12, 0x12, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69,\n\t0x6f, 0x6e, 0x49, 0x44, 0x1a, 0x10, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53,\n\t0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x30, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65,\n\t0x74, 0x65, 0x12, 0x12, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x73,\n\t0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x1a, 0x10, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,\n\t0x2e, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x22, 0x00, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f,\n\t0x3b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,\n}\n\nvar (\n\tfile_session_proto_rawDescOnce sync.Once\n\tfile_session_proto_rawDescData = file_session_proto_rawDesc\n)\n\nfunc file_session_proto_rawDescGZIP() []byte {\n\tfile_session_proto_rawDescOnce.Do(func() {\n\t\tfile_session_proto_rawDescData = protoimpl.X.CompressGZIP(file_session_proto_rawDescData)\n\t})\n\treturn file_session_proto_rawDescData\n}\n\nvar file_session_proto_msgTypes = make([]protoimpl.MessageInfo, 3)\nvar file_session_proto_goTypes = []interface{}{\n\t(*SessionID)(nil), // 0: session.SessionID\n\t(*Session)(nil),   // 1: session.Session\n\t(*Nothing)(nil),   // 2: session.Nothing\n}\nvar file_session_proto_depIdxs = []int32{\n\t1, // 0: session.AuthChecker.Create:input_type -> session.Session\n\t0, // 1: session.AuthChecker.Check:input_type -> session.SessionID\n\t0, // 2: session.AuthChecker.Delete:input_type -> session.SessionID\n\t0, // 3: session.AuthChecker.Create:output_type -> session.SessionID\n\t1, // 4: session.AuthChecker.Check:output_type -> session.Session\n\t2, // 5: session.AuthChecker.Delete:output_type -> session.Nothing\n\t3, // [3:6] is the sub-list for method output_type\n\t0, // [0:3] is the sub-list for method input_type\n\t0, // [0:0] is the sub-list for extension type_name\n\t0, // [0:0] is the sub-list for extension extendee\n\t0, // [0:0] is the sub-list for field type_name\n}\n\nfunc init() { file_session_proto_init() }\nfunc file_session_proto_init() {\n\tif File_session_proto != nil {\n\t\treturn\n\t}\n\tif !protoimpl.UnsafeEnabled {\n\t\tfile_session_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {\n\t\t\tswitch v := v.(*SessionID); i {\n\t\t\tcase 0:\n\t\t\t\treturn &v.state\n\t\t\tcase 1:\n\t\t\t\treturn &v.sizeCache\n\t\t\tcase 2:\n\t\t\t\treturn &v.unknownFields\n\t\t\tdefault:\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t\tfile_session_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {\n\t\t\tswitch v := v.(*Session); i {\n\t\t\tcase 0:\n\t\t\t\treturn &v.state\n\t\t\tcase 1:\n\t\t\t\treturn &v.sizeCache\n\t\t\tcase 2:\n\t\t\t\treturn &v.unknownFields\n\t\t\tdefault:\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t\tfile_session_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {\n\t\t\tswitch v := v.(*Nothing); i {\n\t\t\tcase 0:\n\t\t\t\treturn &v.state\n\t\t\tcase 1:\n\t\t\t\treturn &v.sizeCache\n\t\t\tcase 2:\n\t\t\t\treturn &v.unknownFields\n\t\t\tdefault:\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t}\n\ttype x struct{}\n\tout := protoimpl.TypeBuilder{\n\t\tFile: protoimpl.DescBuilder{\n\t\t\tGoPackagePath: reflect.TypeOf(x{}).PkgPath(),\n\t\t\tRawDescriptor: file_session_proto_rawDesc,\n\t\t\tNumEnums:      0,\n\t\t\tNumMessages:   3,\n\t\t\tNumExtensions: 0,\n\t\t\tNumServices:   1,\n\t\t},\n\t\tGoTypes:           file_session_proto_goTypes,\n\t\tDependencyIndexes: file_session_proto_depIdxs,\n\t\tMessageInfos:      file_session_proto_msgTypes,\n\t}.Build()\n\tFile_session_proto = out.File\n\tfile_session_proto_rawDesc = nil\n\tfile_session_proto_goTypes = nil\n\tfile_session_proto_depIdxs = nil\n}\n"
  },
  {
    "path": "8-microservices/4_grpc/session/session.proto",
    "content": "syntax = \"proto3\";\n\n// protoc --go_out=. --go-grpc_out=. --go-grpc_opt=paths=source_relative --go_opt=paths=source_relative *.proto  \noption go_package = \"./;session\";\n\npackage session;\n\nmessage SessionID {\n  string ID = 1;\n}\n\nmessage Session {\n  string login = 1;\n  string useragent = 2;\n}\n\nmessage Nothing {\n  bool dummy = 1;\n}\n\n// grpc-сервис проверки авторизации\nservice AuthChecker {\n    rpc Create (Session) returns (SessionID) {}\n    rpc Check (SessionID) returns (Session) {}\n    rpc Delete (SessionID) returns (Nothing) {}\n}\n\n"
  },
  {
    "path": "8-microservices/4_grpc/session/session_grpc.pb.go",
    "content": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n\npackage session\n\nimport (\n\tcontext \"context\"\n\tgrpc \"google.golang.org/grpc\"\n\tcodes \"google.golang.org/grpc/codes\"\n\tstatus \"google.golang.org/grpc/status\"\n)\n\n// This is a compile-time assertion to ensure that this generated file\n// is compatible with the grpc package it is being compiled against.\n// Requires gRPC-Go v1.32.0 or later.\nconst _ = grpc.SupportPackageIsVersion7\n\n// AuthCheckerClient is the client API for AuthChecker service.\n//\n// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.\ntype AuthCheckerClient interface {\n\tCreate(ctx context.Context, in *Session, opts ...grpc.CallOption) (*SessionID, error)\n\tCheck(ctx context.Context, in *SessionID, opts ...grpc.CallOption) (*Session, error)\n\tDelete(ctx context.Context, in *SessionID, opts ...grpc.CallOption) (*Nothing, error)\n}\n\ntype authCheckerClient struct {\n\tcc grpc.ClientConnInterface\n}\n\nfunc NewAuthCheckerClient(cc grpc.ClientConnInterface) AuthCheckerClient {\n\treturn &authCheckerClient{cc}\n}\n\nfunc (c *authCheckerClient) Create(ctx context.Context, in *Session, opts ...grpc.CallOption) (*SessionID, error) {\n\tout := new(SessionID)\n\terr := c.cc.Invoke(ctx, \"/session.AuthChecker/Create\", in, out, opts...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\nfunc (c *authCheckerClient) Check(ctx context.Context, in *SessionID, opts ...grpc.CallOption) (*Session, error) {\n\tout := new(Session)\n\terr := c.cc.Invoke(ctx, \"/session.AuthChecker/Check\", in, out, opts...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\nfunc (c *authCheckerClient) Delete(ctx context.Context, in *SessionID, opts ...grpc.CallOption) (*Nothing, error) {\n\tout := new(Nothing)\n\terr := c.cc.Invoke(ctx, \"/session.AuthChecker/Delete\", in, out, opts...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\n// AuthCheckerServer is the server API for AuthChecker service.\n// All implementations must embed UnimplementedAuthCheckerServer\n// for forward compatibility\ntype AuthCheckerServer interface {\n\tCreate(context.Context, *Session) (*SessionID, error)\n\tCheck(context.Context, *SessionID) (*Session, error)\n\tDelete(context.Context, *SessionID) (*Nothing, error)\n\tmustEmbedUnimplementedAuthCheckerServer()\n}\n\n// UnimplementedAuthCheckerServer must be embedded to have forward compatible implementations.\ntype UnimplementedAuthCheckerServer struct {\n}\n\nfunc (UnimplementedAuthCheckerServer) Create(context.Context, *Session) (*SessionID, error) {\n\treturn nil, status.Errorf(codes.Unimplemented, \"method Create not implemented\")\n}\nfunc (UnimplementedAuthCheckerServer) Check(context.Context, *SessionID) (*Session, error) {\n\treturn nil, status.Errorf(codes.Unimplemented, \"method Check not implemented\")\n}\nfunc (UnimplementedAuthCheckerServer) Delete(context.Context, *SessionID) (*Nothing, error) {\n\treturn nil, status.Errorf(codes.Unimplemented, \"method Delete not implemented\")\n}\nfunc (UnimplementedAuthCheckerServer) mustEmbedUnimplementedAuthCheckerServer() {}\n\n// UnsafeAuthCheckerServer may be embedded to opt out of forward compatibility for this service.\n// Use of this interface is not recommended, as added methods to AuthCheckerServer will\n// result in compilation errors.\ntype UnsafeAuthCheckerServer interface {\n\tmustEmbedUnimplementedAuthCheckerServer()\n}\n\nfunc RegisterAuthCheckerServer(s grpc.ServiceRegistrar, srv AuthCheckerServer) {\n\ts.RegisterService(&AuthChecker_ServiceDesc, srv)\n}\n\nfunc _AuthChecker_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {\n\tin := new(Session)\n\tif err := dec(in); err != nil {\n\t\treturn nil, err\n\t}\n\tif interceptor == nil {\n\t\treturn srv.(AuthCheckerServer).Create(ctx, in)\n\t}\n\tinfo := &grpc.UnaryServerInfo{\n\t\tServer:     srv,\n\t\tFullMethod: \"/session.AuthChecker/Create\",\n\t}\n\thandler := func(ctx context.Context, req interface{}) (interface{}, error) {\n\t\treturn srv.(AuthCheckerServer).Create(ctx, req.(*Session))\n\t}\n\treturn interceptor(ctx, in, info, handler)\n}\n\nfunc _AuthChecker_Check_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {\n\tin := new(SessionID)\n\tif err := dec(in); err != nil {\n\t\treturn nil, err\n\t}\n\tif interceptor == nil {\n\t\treturn srv.(AuthCheckerServer).Check(ctx, in)\n\t}\n\tinfo := &grpc.UnaryServerInfo{\n\t\tServer:     srv,\n\t\tFullMethod: \"/session.AuthChecker/Check\",\n\t}\n\thandler := func(ctx context.Context, req interface{}) (interface{}, error) {\n\t\treturn srv.(AuthCheckerServer).Check(ctx, req.(*SessionID))\n\t}\n\treturn interceptor(ctx, in, info, handler)\n}\n\nfunc _AuthChecker_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {\n\tin := new(SessionID)\n\tif err := dec(in); err != nil {\n\t\treturn nil, err\n\t}\n\tif interceptor == nil {\n\t\treturn srv.(AuthCheckerServer).Delete(ctx, in)\n\t}\n\tinfo := &grpc.UnaryServerInfo{\n\t\tServer:     srv,\n\t\tFullMethod: \"/session.AuthChecker/Delete\",\n\t}\n\thandler := func(ctx context.Context, req interface{}) (interface{}, error) {\n\t\treturn srv.(AuthCheckerServer).Delete(ctx, req.(*SessionID))\n\t}\n\treturn interceptor(ctx, in, info, handler)\n}\n\n// AuthChecker_ServiceDesc is the grpc.ServiceDesc for AuthChecker service.\n// It's only intended for direct use with grpc.RegisterService,\n// and not to be introspected or modified (even as a copy)\nvar AuthChecker_ServiceDesc = grpc.ServiceDesc{\n\tServiceName: \"session.AuthChecker\",\n\tHandlerType: (*AuthCheckerServer)(nil),\n\tMethods: []grpc.MethodDesc{\n\t\t{\n\t\t\tMethodName: \"Create\",\n\t\t\tHandler:    _AuthChecker_Create_Handler,\n\t\t},\n\t\t{\n\t\t\tMethodName: \"Check\",\n\t\t\tHandler:    _AuthChecker_Check_Handler,\n\t\t},\n\t\t{\n\t\t\tMethodName: \"Delete\",\n\t\t\tHandler:    _AuthChecker_Delete_Handler,\n\t\t},\n\t},\n\tStreams:  []grpc.StreamDesc{},\n\tMetadata: \"session.proto\",\n}\n"
  },
  {
    "path": "8-microservices/5_grpc_features/client/client.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"time\"\n\n\t\"golang.org/x/net/context\"\n\n\t\"google.golang.org/grpc\"\n\t\"google.golang.org/grpc/metadata\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/4_grpc/session\"\n)\n\n// {Interceprtor} | serialization | -> request\n\nfunc timingInterceptor(\n\tctx context.Context,\n\tmethod string,\n\treq interface{},\n\treply interface{},\n\tcc *grpc.ClientConn,\n\tinvoker grpc.UnaryInvoker,\n\topts ...grpc.CallOption,\n) error {\n\tstart := time.Now()\n\terr := invoker(ctx, method, req, reply, cc, opts...)\n\tfmt.Printf(`--\n\tcall=%v\n\treq=%#v\n\treply=%#v\n\ttime=%v\n\terr=%v\n`, method, req, reply, time.Since(start), err)\n\treturn err\n}\n\ntype tokenAuth struct {\n\tToken string\n}\n\nfunc (t *tokenAuth) GetRequestMetadata(context.Context, ...string) (map[string]string, error) {\n\treturn map[string]string{\n\t\t\"access-token\": t.Token,\n\t}, nil\n}\n\nfunc (c *tokenAuth) RequireTransportSecurity() bool {\n\treturn false\n}\n\nfunc main() {\n\n\tgrcpConn, err := grpc.Dial(\n\t\t\"127.0.0.1:8081\",\n\t\tgrpc.WithUnaryInterceptor(timingInterceptor),\n\t\tgrpc.WithPerRPCCredentials(&tokenAuth{\"100500\"}),\n\t\tgrpc.WithInsecure(),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"cant connect to grpc\")\n\t}\n\tdefer grcpConn.Close()\n\n\tsessManager := session.NewAuthCheckerClient(grcpConn)\n\n\tctx := context.Background()\n\tmd := metadata.Pairs(\n\t\t\"api-req-id\", \"123\",\n\t\t\"subsystem\", \"cli\",\n\t)\n\tctx = metadata.NewOutgoingContext(ctx, md)\n\n\tvar header, trailer metadata.MD\n\n\t// создаем сессию\n\tsessId, err := sessManager.Create(ctx,\n\t\t&session.Session{\n\t\t\tLogin:     \"rvasily\",\n\t\t\tUseragent: \"chrome\",\n\t\t},\n\t\tgrpc.Header(&header),\n\t\tgrpc.Trailer(&trailer),\n\t)\n\tfmt.Println(\"sessId\", sessId, err)\n\tfmt.Println(\"header\", header)\n\tfmt.Println(\"trailer\", trailer)\n\n\t// проеряем сессию\n\tsess, err := sessManager.Check(ctx,\n\t\t&session.SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\tfmt.Println(\"sess\", sess, err)\n\n\t// удаляем сессию\n\t_, err = sessManager.Delete(ctx,\n\t\t&session.SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\n\t// проверяем еще раз\n\tsess, err = sessManager.Check(ctx,\n\t\t&session.SessionID{\n\t\t\tID: sessId.ID,\n\t\t})\n\tfmt.Println(\"sess\", sess, err)\n}\n"
  },
  {
    "path": "8-microservices/5_grpc_features/server/server.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/4_grpc/session\"\n\t\"golang.org/x/net/context\"\n\t\"google.golang.org/grpc\"\n\t\"google.golang.org/grpc/metadata\"\n\t\"google.golang.org/grpc/tap\"\n)\n\n// request -> {InTapHandle} | parsing | -> {Interceprtor} | handling | ...\n\nfunc authInterceptor(\n\tctx context.Context,\n\treq interface{},\n\tinfo *grpc.UnaryServerInfo,\n\thandler grpc.UnaryHandler,\n) (interface{}, error) {\n\tstart := time.Now()\n\n\tmd, _ := metadata.FromIncomingContext(ctx)\n\n\t// ... auth logic\n\n\treply, err := handler(ctx, req)\n\n\tfmt.Printf(`--\n\tafter incoming call=%v\n\treq=%#v\n\treply=%#v\n\ttime=%v\n\tmd=%v\n\terr=%v\n`, info.FullMethod, req, reply, time.Since(start), md, err)\n\n\treturn reply, err\n}\n\nfunc rateLimiter(ctx context.Context, info *tap.Info) (context.Context, error) {\n\tfmt.Printf(\"--\\ncheck ratelim for %s\\n\", info.FullMethodName)\n\n\t// ... rate limit logic\n\n\treturn ctx, nil\n}\n\nfunc main() {\n\tlis, err := net.Listen(\"tcp\", \":8081\")\n\tif err != nil {\n\t\tlog.Fatalln(\"cant listet port\", err)\n\t}\n\n\tserver := grpc.NewServer(\n\t\tgrpc.UnaryInterceptor(authInterceptor),\n\t\tgrpc.InTapHandle(rateLimiter),\n\t)\n\n\tsession.RegisterAuthCheckerServer(server, NewSessionManager())\n\n\tfmt.Println(\"starting server at :8081\")\n\tserver.Serve(lis)\n}\n"
  },
  {
    "path": "8-microservices/5_grpc_features/server/session.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"sync\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/4_grpc/session\"\n\n\t\"google.golang.org/grpc\"\n\t\"google.golang.org/grpc/codes\"\n\t\"google.golang.org/grpc/metadata\"\n\n\t\"golang.org/x/net/context\"\n)\n\nconst sessKeyLen = 10\n\ntype SessionManager struct {\n\tsession.UnimplementedAuthCheckerServer\n\n\tmu       sync.RWMutex\n\tsessions map[string]*session.Session\n}\n\nfunc NewSessionManager() *SessionManager {\n\treturn &SessionManager{\n\t\tmu:       sync.RWMutex{},\n\t\tsessions: map[string]*session.Session{},\n\t}\n}\n\nfunc (sm *SessionManager) Create(ctx context.Context, in *session.Session) (*session.SessionID, error) {\n\tfmt.Println(\"call Create\", in)\n\n\theader := metadata.Pairs(\"header-key\", \"42\")\n\tgrpc.SendHeader(ctx, header)\n\n\ttrailer := metadata.Pairs(\"trailer-key\", \"3.14\")\n\tgrpc.SetTrailer(ctx, trailer)\n\n\tid := &session.SessionID{ID: RandStringRunes(sessKeyLen)}\n\tsm.mu.Lock()\n\tsm.sessions[id.ID] = in\n\tsm.mu.Unlock()\n\treturn id, nil\n}\n\nfunc (sm *SessionManager) Check(ctx context.Context, in *session.SessionID) (*session.Session, error) {\n\tfmt.Println(\"call Check\", in)\n\tsm.mu.RLock()\n\tdefer sm.mu.RUnlock()\n\tif sess, ok := sm.sessions[in.ID]; ok {\n\t\treturn sess, nil\n\t}\n\treturn nil, grpc.Errorf(codes.NotFound, \"session not found\")\n}\n\nfunc (sm *SessionManager) Delete(ctx context.Context, in *session.SessionID) (*session.Nothing, error) {\n\tfmt.Println(\"call Delete\", in)\n\tsm.mu.Lock()\n\tdefer sm.mu.Unlock()\n\tdelete(sm.sessions, in.ID)\n\treturn &session.Nothing{Dummy: true}, nil\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "8-microservices/6_grpc_stream/client/client.go",
    "content": "package main\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"sync\"\n\n\t\"google.golang.org/grpc\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/6_grpc_stream/translit\"\n)\n\nfunc main() {\n\tgrcpConn, err := grpc.Dial(\n\t\t\"127.0.0.1:8081\",\n\t\tgrpc.WithInsecure(),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"cant connect to grpc\")\n\t}\n\tdefer grcpConn.Close()\n\n\ttr := translit.NewTransliterationClient(grcpConn)\n\n\tctx := context.Background()\n\tstream, err := tr.EnRu(ctx)\n\tif err != nil {\n\t\tprintln(err)\n\t}\n\n\twg := &sync.WaitGroup{}\n\twg.Add(1)\n\n\tgo func(wg *sync.WaitGroup) {\n\t\tdefer wg.Done()\n\t\tfor {\n\t\t\toutWord, err := stream.Recv()\n\t\t\tif err == io.EOF {\n\t\t\t\tfmt.Println(\"\\tstream closed\")\n\t\t\t\treturn\n\t\t\t} else if err != nil {\n\t\t\t\tfmt.Println(\"\\terror happed\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfmt.Println(\" <-\", outWord.Word)\n\t\t}\n\t}(wg)\n\n\tscanner := bufio.NewScanner(os.Stdin)\n\tfor scanner.Scan() {\n\t\terrSend := stream.Send(&translit.Word{\n\t\t\tWord: scanner.Text(),\n\t\t})\n\t\tif err != nil {\n\t\t\tprintln(errSend)\n\t\t}\n\t}\n\tstream.CloseSend()\n\n\twg.Wait()\n\n}\n"
  },
  {
    "path": "8-microservices/6_grpc_stream/client/run_test.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"log\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/6_grpc_stream/translit\"\n\t\"google.golang.org/grpc\"\n)\n\nfunc Test(t *testing.T) {\n\tgrcpConn, err := grpc.Dial(\n\t\t\"127.0.0.1:8081\",\n\t\tgrpc.WithInsecure(),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"cant connect to grpc\")\n\t}\n\tdefer grcpConn.Close()\n\n\ttr := translit.NewTransliterationClient(grcpConn)\n\n\tctx := context.Background()\n\tstream, _ := tr.EnRu(ctx)\n\n\twg := &sync.WaitGroup{}\n\twg.Add(2)\n\n\tgo func(wg *sync.WaitGroup) {\n\t\tdefer wg.Done()\n\t\tfor {\n\t\t\toutWord, err := stream.Recv()\n\t\t\tif err == io.EOF {\n\t\t\t\tlog.Println(\"\\tstream closed\")\n\t\t\t\treturn\n\t\t\t} else if err != nil {\n\t\t\t\tlog.Println(\"\\terror happed\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tlog.Println(\" <-\", outWord.Word)\n\t\t}\n\t}(wg)\n\n\tgo func(wg *sync.WaitGroup) {\n\t\tdefer wg.Done()\n\t\twords := []string{\"privet\", \"kak\", \"dela\"}\n\t\tfor _, w := range words {\n\t\t\tlog.Println(\"-> \", w)\n\t\t\tstream.Send(&translit.Word{\n\t\t\t\tWord: w,\n\t\t\t})\n\t\t\t//time.Sleep(2 * time.Second)\n\t\t}\n\t\tstream.CloseSend()\n\t\tlog.Println(\"\\tsend done\")\n\t}(wg)\n\n\twg.Wait()\n\n\tt.Fail()\n}\n"
  },
  {
    "path": "8-microservices/6_grpc_stream/server/main.go",
    "content": "package main\n"
  },
  {
    "path": "8-microservices/6_grpc_stream/server/server.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/6_grpc_stream/translit\"\n\n\t\"google.golang.org/grpc\"\n)\n\nfunc main() {\n\tlis, err := net.Listen(\"tcp\", \":8081\")\n\tif err != nil {\n\t\tlog.Fatalln(\"cant listet port\", err)\n\t}\n\n\tserver := grpc.NewServer()\n\n\tclientsWriter := []func(string){}\n\n\ttr := NewTr()\n\ttr.SetSendCallback = func(f func(string)) {\n\t\tclientsWriter = append(clientsWriter, f)\n\t}\n\ttranslit.RegisterTransliterationServer(server, tr)\n\n\tfmt.Println(\"starting server at :8081\")\n\tserver.Serve(lis)\n\n\t// for {\n\t// \tfor _, f := range clientsWriter {\n\t// \t\ttime.Sleep(time.Second)\n\t// \t\tf(\"123\")\n\t// \t}\n\t// }\n}\n"
  },
  {
    "path": "8-microservices/6_grpc_stream/server/translit.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\n\ttr \"github.com/gen1us2k/go-translit\"\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/6_grpc_stream/translit\"\n)\n\ntype TrServer struct {\n\ttranslit.UnimplementedTransliterationServer\n\tSetSendCallback func(func(string))\n}\n\nfunc (srv *TrServer) EnRu(inStream translit.Transliteration_EnRuServer) error {\n\tsrv.SetSendCallback(func(s string) {\n\t\tout := &translit.Word{\n\t\t\tWord: s,\n\t\t}\n\t\tinStream.Send(out)\n\t})\n\t// return nil\n\t// go func() {\n\t// \tfor {\n\t// \t\tinStream.Send(&translit.Word{\n\t// \t\t\tWord: \"stat\",\n\t// \t\t})\n\t// \t\ttime.Sleep(time.Second)\n\t// \t}\n\t// }()\n\tfor {\n\t\t// time.Sleep(1 * time.Second)\n\t\tinWord, err := inStream.Recv()\n\t\tif err == io.EOF {\n\t\t\treturn nil\n\t\t}\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tout := &translit.Word{\n\t\t\tWord: tr.Translit(inWord.Word),\n\t\t}\n\t\tfmt.Println(inWord.Word, \"->\", out.Word)\n\t\tinStream.Send(out)\n\t}\n}\n\nfunc NewTr() *TrServer {\n\treturn &TrServer{}\n}\n"
  },
  {
    "path": "8-microservices/6_grpc_stream/translit/translit.pb.go",
    "content": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.26.0\n// \tprotoc        v3.17.3\n// source: translit.proto\n\npackage translit\n\nimport (\n\tprotoreflect \"google.golang.org/protobuf/reflect/protoreflect\"\n\tprotoimpl \"google.golang.org/protobuf/runtime/protoimpl\"\n\treflect \"reflect\"\n\tsync \"sync\"\n)\n\nconst (\n\t// Verify that this generated code is sufficiently up-to-date.\n\t_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)\n\t// Verify that runtime/protoimpl is sufficiently up-to-date.\n\t_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)\n)\n\ntype Word struct {\n\tstate         protoimpl.MessageState\n\tsizeCache     protoimpl.SizeCache\n\tunknownFields protoimpl.UnknownFields\n\n\tWord string `protobuf:\"bytes,1,opt,name=Word,proto3\" json:\"Word,omitempty\"`\n}\n\nfunc (x *Word) Reset() {\n\t*x = Word{}\n\tif protoimpl.UnsafeEnabled {\n\t\tmi := &file_translit_proto_msgTypes[0]\n\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n\t\tms.StoreMessageInfo(mi)\n\t}\n}\n\nfunc (x *Word) String() string {\n\treturn protoimpl.X.MessageStringOf(x)\n}\n\nfunc (*Word) ProtoMessage() {}\n\nfunc (x *Word) ProtoReflect() protoreflect.Message {\n\tmi := &file_translit_proto_msgTypes[0]\n\tif protoimpl.UnsafeEnabled && x != nil {\n\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n\t\tif ms.LoadMessageInfo() == nil {\n\t\t\tms.StoreMessageInfo(mi)\n\t\t}\n\t\treturn ms\n\t}\n\treturn mi.MessageOf(x)\n}\n\n// Deprecated: Use Word.ProtoReflect.Descriptor instead.\nfunc (*Word) Descriptor() ([]byte, []int) {\n\treturn file_translit_proto_rawDescGZIP(), []int{0}\n}\n\nfunc (x *Word) GetWord() string {\n\tif x != nil {\n\t\treturn x.Word\n\t}\n\treturn \"\"\n}\n\nvar File_translit_proto protoreflect.FileDescriptor\n\nvar file_translit_proto_rawDesc = []byte{\n\t0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x69, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,\n\t0x12, 0x08, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x69, 0x74, 0x22, 0x1a, 0x0a, 0x04, 0x57, 0x6f,\n\t0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x57, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,\n\t0x52, 0x04, 0x57, 0x6f, 0x72, 0x64, 0x32, 0x3f, 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c,\n\t0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x04, 0x45, 0x6e, 0x52,\n\t0x75, 0x12, 0x0e, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x69, 0x74, 0x2e, 0x57, 0x6f, 0x72,\n\t0x64, 0x1a, 0x0e, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x69, 0x74, 0x2e, 0x57, 0x6f, 0x72,\n\t0x64, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x0d, 0x5a, 0x0b, 0x2e, 0x2f, 0x3b, 0x74, 0x72,\n\t0x61, 0x6e, 0x73, 0x6c, 0x69, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,\n}\n\nvar (\n\tfile_translit_proto_rawDescOnce sync.Once\n\tfile_translit_proto_rawDescData = file_translit_proto_rawDesc\n)\n\nfunc file_translit_proto_rawDescGZIP() []byte {\n\tfile_translit_proto_rawDescOnce.Do(func() {\n\t\tfile_translit_proto_rawDescData = protoimpl.X.CompressGZIP(file_translit_proto_rawDescData)\n\t})\n\treturn file_translit_proto_rawDescData\n}\n\nvar file_translit_proto_msgTypes = make([]protoimpl.MessageInfo, 1)\nvar file_translit_proto_goTypes = []interface{}{\n\t(*Word)(nil), // 0: translit.Word\n}\nvar file_translit_proto_depIdxs = []int32{\n\t0, // 0: translit.Transliteration.EnRu:input_type -> translit.Word\n\t0, // 1: translit.Transliteration.EnRu:output_type -> translit.Word\n\t1, // [1:2] is the sub-list for method output_type\n\t0, // [0:1] is the sub-list for method input_type\n\t0, // [0:0] is the sub-list for extension type_name\n\t0, // [0:0] is the sub-list for extension extendee\n\t0, // [0:0] is the sub-list for field type_name\n}\n\nfunc init() { file_translit_proto_init() }\nfunc file_translit_proto_init() {\n\tif File_translit_proto != nil {\n\t\treturn\n\t}\n\tif !protoimpl.UnsafeEnabled {\n\t\tfile_translit_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {\n\t\t\tswitch v := v.(*Word); i {\n\t\t\tcase 0:\n\t\t\t\treturn &v.state\n\t\t\tcase 1:\n\t\t\t\treturn &v.sizeCache\n\t\t\tcase 2:\n\t\t\t\treturn &v.unknownFields\n\t\t\tdefault:\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t}\n\ttype x struct{}\n\tout := protoimpl.TypeBuilder{\n\t\tFile: protoimpl.DescBuilder{\n\t\t\tGoPackagePath: reflect.TypeOf(x{}).PkgPath(),\n\t\t\tRawDescriptor: file_translit_proto_rawDesc,\n\t\t\tNumEnums:      0,\n\t\t\tNumMessages:   1,\n\t\t\tNumExtensions: 0,\n\t\t\tNumServices:   1,\n\t\t},\n\t\tGoTypes:           file_translit_proto_goTypes,\n\t\tDependencyIndexes: file_translit_proto_depIdxs,\n\t\tMessageInfos:      file_translit_proto_msgTypes,\n\t}.Build()\n\tFile_translit_proto = out.File\n\tfile_translit_proto_rawDesc = nil\n\tfile_translit_proto_goTypes = nil\n\tfile_translit_proto_depIdxs = nil\n}\n"
  },
  {
    "path": "8-microservices/6_grpc_stream/translit/translit.proto",
    "content": "syntax = \"proto3\";\n\n// protoc --go_out=. --go-grpc_out=. --go-grpc_opt=paths=source_relative --go_opt=paths=source_relative *.proto  \noption go_package = \"./;translit\";\n\npackage translit;\n\nmessage Word {\n  string Word = 1;\n}\n\n// grpc-сервис транслитерации\nservice Transliteration {\n    rpc EnRu (stream Word) returns (stream Word) {}\n}"
  },
  {
    "path": "8-microservices/6_grpc_stream/translit/translit_grpc.pb.go",
    "content": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n\npackage translit\n\nimport (\n\tcontext \"context\"\n\tgrpc \"google.golang.org/grpc\"\n\tcodes \"google.golang.org/grpc/codes\"\n\tstatus \"google.golang.org/grpc/status\"\n)\n\n// This is a compile-time assertion to ensure that this generated file\n// is compatible with the grpc package it is being compiled against.\n// Requires gRPC-Go v1.32.0 or later.\nconst _ = grpc.SupportPackageIsVersion7\n\n// TransliterationClient is the client API for Transliteration service.\n//\n// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.\ntype TransliterationClient interface {\n\tEnRu(ctx context.Context, opts ...grpc.CallOption) (Transliteration_EnRuClient, error)\n}\n\ntype transliterationClient struct {\n\tcc grpc.ClientConnInterface\n}\n\nfunc NewTransliterationClient(cc grpc.ClientConnInterface) TransliterationClient {\n\treturn &transliterationClient{cc}\n}\n\nfunc (c *transliterationClient) EnRu(ctx context.Context, opts ...grpc.CallOption) (Transliteration_EnRuClient, error) {\n\tstream, err := c.cc.NewStream(ctx, &Transliteration_ServiceDesc.Streams[0], \"/translit.Transliteration/EnRu\", opts...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tx := &transliterationEnRuClient{stream}\n\treturn x, nil\n}\n\ntype Transliteration_EnRuClient interface {\n\tSend(*Word) error\n\tRecv() (*Word, error)\n\tgrpc.ClientStream\n}\n\ntype transliterationEnRuClient struct {\n\tgrpc.ClientStream\n}\n\nfunc (x *transliterationEnRuClient) Send(m *Word) error {\n\treturn x.ClientStream.SendMsg(m)\n}\n\nfunc (x *transliterationEnRuClient) Recv() (*Word, error) {\n\tm := new(Word)\n\tif err := x.ClientStream.RecvMsg(m); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// TransliterationServer is the server API for Transliteration service.\n// All implementations must embed UnimplementedTransliterationServer\n// for forward compatibility\ntype TransliterationServer interface {\n\tEnRu(Transliteration_EnRuServer) error\n\tmustEmbedUnimplementedTransliterationServer()\n}\n\n// UnimplementedTransliterationServer must be embedded to have forward compatible implementations.\ntype UnimplementedTransliterationServer struct {\n}\n\nfunc (UnimplementedTransliterationServer) EnRu(Transliteration_EnRuServer) error {\n\treturn status.Errorf(codes.Unimplemented, \"method EnRu not implemented\")\n}\nfunc (UnimplementedTransliterationServer) mustEmbedUnimplementedTransliterationServer() {}\n\n// UnsafeTransliterationServer may be embedded to opt out of forward compatibility for this service.\n// Use of this interface is not recommended, as added methods to TransliterationServer will\n// result in compilation errors.\ntype UnsafeTransliterationServer interface {\n\tmustEmbedUnimplementedTransliterationServer()\n}\n\nfunc RegisterTransliterationServer(s grpc.ServiceRegistrar, srv TransliterationServer) {\n\ts.RegisterService(&Transliteration_ServiceDesc, srv)\n}\n\nfunc _Transliteration_EnRu_Handler(srv interface{}, stream grpc.ServerStream) error {\n\treturn srv.(TransliterationServer).EnRu(&transliterationEnRuServer{stream})\n}\n\ntype Transliteration_EnRuServer interface {\n\tSend(*Word) error\n\tRecv() (*Word, error)\n\tgrpc.ServerStream\n}\n\ntype transliterationEnRuServer struct {\n\tgrpc.ServerStream\n}\n\nfunc (x *transliterationEnRuServer) Send(m *Word) error {\n\treturn x.ServerStream.SendMsg(m)\n}\n\nfunc (x *transliterationEnRuServer) Recv() (*Word, error) {\n\tm := new(Word)\n\tif err := x.ServerStream.RecvMsg(m); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// Transliteration_ServiceDesc is the grpc.ServiceDesc for Transliteration service.\n// It's only intended for direct use with grpc.RegisterService,\n// and not to be introspected or modified (even as a copy)\nvar Transliteration_ServiceDesc = grpc.ServiceDesc{\n\tServiceName: \"translit.Transliteration\",\n\tHandlerType: (*TransliterationServer)(nil),\n\tMethods:     []grpc.MethodDesc{},\n\tStreams: []grpc.StreamDesc{\n\t\t{\n\t\t\tStreamName:    \"EnRu\",\n\t\t\tHandler:       _Transliteration_EnRu_Handler,\n\t\t\tServerStreams: true,\n\t\t\tClientStreams: true,\n\t\t},\n\t},\n\tMetadata: \"translit.proto\",\n}\n"
  },
  {
    "path": "8-microservices/7_grpc_loadbalance/client/main.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"google.golang.org/grpc\"\n\t\"google.golang.org/grpc/resolver\"\n\t\"google.golang.org/grpc/resolver/manual\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/4_grpc/session\"\n\n\tconsulapi \"github.com/hashicorp/consul/api\"\n)\n\nvar (\n\tconsulAddr = flag.String(\"addr\", \"127.0.0.1:8500\", \"consul addr (8500 in original consul)\")\n)\n\nvar (\n\tconsul *consulapi.Client\n)\n\nfunc main() {\n\tflag.Parse()\n\n\tvar err error\n\tconfig := consulapi.DefaultConfig()\n\tconfig.Address = *consulAddr\n\tconsul, err = consulapi.NewClient(config)\n\n\thealth, _, err := consul.Health().Service(\"session-api\", \"\", false, nil)\n\tif err != nil {\n\t\tlog.Fatalf(\"cant get alive services\")\n\t}\n\n\tservers := make([]resolver.Address, 0, len(health))\n\tfor _, item := range health {\n\t\taddr := item.Service.Address +\n\t\t\t\":\" + strconv.Itoa(item.Service.Port)\n\t\tservers = append(servers, resolver.Address{Addr: addr})\n\t}\n\n\tif len(servers) == 0 {\n\t\tpanic(\"no alive session-api servers\")\n\t}\n\n\tnameResolver := manual.NewBuilderWithScheme(\"myservice\")\n\tnameResolver.InitialState(resolver.State{Addresses: servers})\n\n\t// grpclog.SetLogger(log.New(os.Stdout, \"\", log.LstdFlags)) // add logging\n\tgrpcConn, err := grpc.Dial(\n\t\tnameResolver.Scheme()+\":///\",\n\t\tgrpc.WithDefaultServiceConfig(`{\"loadBalancingConfig\": [{\"round_robin\":{}}]}`),\n\t\tgrpc.WithResolvers(nameResolver),\n\t\tgrpc.WithInsecure(),\n\t\tgrpc.WithBlock(),\n\t\tgrpc.WithTimeout(time.Second),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"cant connect to grpc: %v\", err)\n\t}\n\tdefer grpcConn.Close()\n\n\tsessManager := session.NewAuthCheckerClient(grpcConn)\n\n\t// тут мы будем периодически опрашивать консул на предмет изменений\n\tgo runOnlineServiceDiscovery(nameResolver)\n\n\tctx := context.Background()\n\tstep := 1\n\tfor {\n\t\t// проверяем несуществуюущую сессию\n\t\t// потому что сейчас между сервисами нет общения\n\t\t// получаем загшулку\n\t\tsess, err := sessManager.Check(ctx,\n\t\t\t&session.SessionID{\n\t\t\t\tID: \"not_exist_\" + strconv.Itoa(step),\n\t\t\t})\n\t\tfmt.Println(\"get sess\", step, sess, err)\n\n\t\ttime.Sleep(500 * time.Millisecond)\n\t\tstep++\n\t}\n}\n\nfunc runOnlineServiceDiscovery(nameResolver *manual.Resolver) {\n\tticker := time.Tick(5 * time.Second)\n\tfor _ = range ticker {\n\t\thealth, _, err := consul.Health().Service(\"session-api\", \"\", false, nil)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"cant get alive services\")\n\t\t}\n\n\t\tservers := make([]resolver.Address, 0, len(health))\n\t\tfor _, item := range health {\n\t\t\taddr := item.Service.Address +\n\t\t\t\t\":\" + strconv.Itoa(item.Service.Port)\n\t\t\tservers = append(servers, resolver.Address{Addr: addr})\n\t\t}\n\t\tnameResolver.CC.NewAddress(servers)\n\t}\n}\n"
  },
  {
    "path": "8-microservices/7_grpc_loadbalance/docker-compose.yml",
    "content": "version: \"3\"\n\nservices:\n  consul:\n    image: consul\n    ports:\n      - \"8500:8500\"\n"
  },
  {
    "path": "8-microservices/7_grpc_loadbalance/readme.md",
    "content": "пример с балансировкой нагрузки и service discovery для микросервиса на grpc\nв качестве service discovery используется consul (в видео поднят отдельно в докере)\nэто учебный пример, не используйте это как есть в продакшене без понимани всего что там происходит"
  },
  {
    "path": "8-microservices/7_grpc_loadbalance/server/server.go",
    "content": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"strconv\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/4_grpc/session\"\n\n\t\"google.golang.org/grpc\"\n\n\tconsulapi \"github.com/hashicorp/consul/api\"\n)\n\nvar (\n\tgrpcPort   = flag.Int(\"grpc\", 8081, \"listen addr\")\n\tconsulAddr = flag.String(\"consul\", \"127.0.0.1:8500\", \"consul addr (8500 in original consul)\")\n)\n\n/*\n\tgo run *.go --grpc=\"8081\"\n\tgo run *.go --grpc=\"8082\"\n*/\n\nfunc main() {\n\tflag.Parse()\n\n\tport := strconv.Itoa(*grpcPort)\n\n\tlis, err := net.Listen(\"tcp\", \":\"+port)\n\tif err != nil {\n\t\tlog.Fatalln(\"cant listen port\", err)\n\t}\n\n\tserver := grpc.NewServer()\n\n\tsession.RegisterAuthCheckerServer(server, NewSessionManager(port))\n\n\tconfig := consulapi.DefaultConfig()\n\tconfig.Address = *consulAddr\n\tconsul, err := consulapi.NewClient(config)\n\n\tserviceID := \"SAPI_127.0.0.1:\" + port\n\n\terr = consul.Agent().ServiceRegister(&consulapi.AgentServiceRegistration{\n\t\tID:      serviceID,\n\t\tName:    \"session-api\",\n\t\tPort:    *grpcPort,\n\t\tAddress: \"127.0.0.1\",\n\t})\n\tif err != nil {\n\t\tfmt.Println(\"cant add service to consul\", err)\n\t\treturn\n\t}\n\tfmt.Println(\"registered in consul\", serviceID)\n\n\tdefer func() {\n\t\terr := consul.Agent().ServiceDeregister(serviceID)\n\t\tif err != nil {\n\t\t\tfmt.Println(\"cant delete service from consul\", err)\n\t\t\treturn\n\t\t}\n\t\tfmt.Println(\"deregistered in consul\", serviceID)\n\t}()\n\n\tfmt.Println(\"starting server at \" + port)\n\tgo server.Serve(lis)\n\n\tfmt.Println(\"Press any key to exit\")\n\tfmt.Scanln()\n}\n"
  },
  {
    "path": "8-microservices/7_grpc_loadbalance/server/session.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"sync\"\n\n\t\"github.com/go-park-mail-ru/lectures/8-microservices/4_grpc/session\"\n\n\t\"golang.org/x/net/context\"\n)\n\nconst sessKeyLen = 10\n\ntype SessionManager struct {\n\tsession.UnimplementedAuthCheckerServer\n\n\tmu       sync.RWMutex\n\tsessions map[string]*session.Session\n\thost     string\n}\n\nfunc NewSessionManager(port string) *SessionManager {\n\treturn &SessionManager{\n\t\tmu:       sync.RWMutex{},\n\t\tsessions: map[string]*session.Session{},\n\t\thost:     port,\n\t}\n}\n\nfunc (sm *SessionManager) Create(ctx context.Context, in *session.Session) (*session.SessionID, error) {\n\tfmt.Println(\"call Create\", in)\n\tid := &session.SessionID{ID: RandStringRunes(sessKeyLen)}\n\tsm.mu.Lock()\n\tsm.sessions[id.ID] = in\n\tsm.mu.Unlock()\n\treturn id, nil\n}\n\nfunc (sm *SessionManager) Check(ctx context.Context, in *session.SessionID) (*session.Session, error) {\n\tfmt.Println(\"call Check\", in)\n\t// между сервисами нет общения, возвращаем заглушку\n\tfakeLogin := sm.host + \" \" + in.GetID()\n\treturn &session.Session{Login: fakeLogin}, nil\n}\n\nfunc (sm *SessionManager) Delete(ctx context.Context, in *session.SessionID) (*session.Nothing, error) {\n\tfmt.Println(\"call Delete\", in)\n\tsm.mu.Lock()\n\tdefer sm.mu.Unlock()\n\tdelete(sm.sessions, in.ID)\n\treturn &session.Nothing{Dummy: true}, nil\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "9-monitoring/0_services/alertmanager/alertmanager.yml",
    "content": "global:\n  resolve_timeout: 5m\n  smtp_from: park.alerting@mail.ru\n  smtp_hello: mail.ru\n  smtp_smarthost: smtp.mail.ru:465\n  smtp_auth_username: park.alerting@mail.ru\n  smtp_auth_password: gb=D>zTa8)uLkndj@peE\n  smtp_require_tls: false\n\nroute:\n  group_by:\n    - 'alertname'\n  group_wait: 30s\n  group_interval: 10s\n  repeat_interval: 20s\n  receiver: 'email'\n  routes:\n    - receiver: alertmananger-bot\n      continue: true\n    - receiver: email\nreceivers:\n  - name: 'alertmananger-bot'\n    webhook_configs:\n      - url: 'http://alertmanager-bot:8080'\n  - name: email\n    email_configs:\n      - send_resolved: false\n        to: park.alerting@mail.ru\n        headers:\n          From: park.alerting@mail.ru\n          Subject: '{{ template \"email.default.subject\" . }}'\n          To: park.alerting@mail.ru\n        html: '{{ template \"email.default.html\" . }}'\n\ninhibit_rules:\n  - source_match:\n      severity: 'critical'\n    target_match:\n      severity: 'warning'\n    equal: [ 'alertname', 'instance' ]\n"
  },
  {
    "path": "9-monitoring/0_services/alertmanager-bot/templates/default.tmpl",
    "content": "{{ define \"telegram.default\" }}\n{{ range .Alerts }}\n{{ if eq .Status \"firing\"}}🔥 <b>{{ .Status | toUpper }}</b> 🔥{{ else }}<b>{{ .Status | toUpper }}</b>{{ end }}\n<b>{{ .Labels.alertname }}</b>\n{{ if .Annotations.message }}\n{{ .Annotations.message }}\n{{ end }}\n{{ if .Annotations.summary }}\n{{ .Annotations.summary }}\n{{ end }}\n{{ if .Annotations.description }}\n{{ .Annotations.description }}\n{{ end }}\n<b>Duration:</b> {{ duration .StartsAt .EndsAt }}{{ if ne .Status \"firing\"}}\n<b>Ended:</b> {{ .EndsAt | since }}{{ end }}\n{{ end }}\n{{ end }}"
  },
  {
    "path": "9-monitoring/0_services/docker-compose.yml",
    "content": "version: \"3\"\n\nservices:\n  consul:\n    image: hashicorp/consul\n    ports:\n      - \"8500:8500\"\n  vault:\n    image: hashicorp/vault\n    environment:\n      VAULT_DEV_ROOT_TOKEN_ID: 123\n    ports:\n      - \"8200:8200\"\n\n  prometheus:\n    image: prom/prometheus\n    ports:\n      - \"9090:9090\"\n    volumes:\n      - \"./prometheus:/etc/prometheus\"\n  alertmanager:\n    image: prom/alertmanager\n    ports:\n      - \"9093:9093\"\n    command:\n      - '--config.file=/etc/alertmanager/alertmanager.yml'\n    volumes:\n      - \"./alertmanager:/etc/alertmanager\"\n  alertmanager-bot:\n    image: metalmatze/alertmanager-bot\n    command:\n      - \"--listen.addr=0.0.0.0:8080\"\n    environment:\n      ALERTMANAGER_URL: http://alertmanager:9093\n      BOLT_PATH: /data/bot.db\n      STORE: bolt\n      TEMPLATE_PATHS: /templates/default.tmpl\n      TELEGRAM_ADMIN: 164626023\n      TELEGRAM_TOKEN: 997404236:AAGB0453GmnqkD2vhFmz6I8Iq0YRlOut8HE\n    volumes:\n      - \"./alertmanager-bot/templates:/templates\"\n  jaeger:\n    image: jaegertracing/all-in-one\n    ports:\n      - \"6831:6831/udp\"\n      - \"16686:16686\"\n\n  grafana:\n    image: grafana/grafana\n    ports:\n      - \"3000:3000\"\n      "
  },
  {
    "path": "9-monitoring/0_services/prometheus/alerts.yml",
    "content": "groups:\n  - name: default\n    rules:\n    - alert: InternalServerError\n      expr: increase(hits{status=\"500\"}[1m]) > 0\n      for: 1s\n      labels:\n        severity: critical\n      annotations:\n        summary: \"path {{ $labels.path }} returned status 500\"\n        description: \"{{ $labels.path }} of job {{ $labels.job }} returned status {{ $labels.status }}\"\n"
  },
  {
    "path": "9-monitoring/0_services/prometheus/prometheus.yml",
    "content": "global:\n  scrape_interval:     10s\n  evaluation_interval: 10s\n\nscrape_configs:\n  - job_name: 'golang'\n    static_configs:\n      - targets: ['docker.for.mac.localhost:8080']\n\n  - job_name: 'system'\n    static_configs:\n      - targets: ['docker.for.mac.localhost:9100']\n\nrule_files:\n  - 'alerts.yml'\n\nalerting:\n  alertmanagers:\n    - static_configs:\n      - targets:\n        - alertmanager:9093\n\n"
  },
  {
    "path": "9-monitoring/1_config/1_flag/flag.go",
    "content": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"net\"\n\t\"strings\"\n)\n\nvar (\n\tcommentsEnabled = flag.Bool(\"comments\", false, \"Enable comments after post\")\n\n\tcommentsLimit = flag.Int(\"limit\", 10, \"Comments number per page\")\n\n\tcommentsServices = &AddrList{}\n)\n\n// go run flag.go --comments=true --servers=\"127.0.0.1:8081,127.0.0.1:8082\"\n\nfunc init() {\n\tflag.Var(commentsServices, \"servers\", \"Addresses\")\n}\n\nfunc main() {\n\tflag.Parse()\n\n\tif *commentsEnabled {\n\t\tfmt.Println(\"Comments per page\", *commentsLimit)\n\t\tfmt.Println(\"Comments services\", *commentsServices)\n\t} else {\n\t\tfmt.Println(\"Comments disabled\")\n\t}\n}\n\ntype AddrList []string\n\nfunc (v *AddrList) String() string {\n\treturn fmt.Sprint(*v)\n}\n\nfunc (v *AddrList) Set(in string) error {\n\tfor _, addr := range strings.Split(in, \",\") {\n\t\tipRaw, _, err := net.SplitHostPort(addr)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"bad addr %v\", addr)\n\t\t}\n\t\tip := net.ParseIP(ipRaw)\n\t\tif ip.To4() == nil {\n\t\t\treturn fmt.Errorf(\"invalid ipv4 addr %v\", addr)\n\t\t}\n\t\t*v = append(*v, addr)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "9-monitoring/1_config/2_json/config.json",
    "content": "{\n\t\"comments\": true,\n\t\"servers\": [\"127.0.0.1:8081\", \"127.0.0.1:8082\"]\n}"
  },
  {
    "path": "9-monitoring/1_config/2_json/json_config.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n)\n\ntype Config struct {\n\tComments bool `json:\"comments\"`\n\tLimit    int\n\tServers  []string\n}\n\nvar (\n\tconfig = &Config{}\n)\n\nfunc main() {\n\tdata, err := ioutil.ReadFile(\"./config.json\")\n\tif err != nil {\n\t\tlog.Fatalln(\"cant read config file:\", err)\n\t}\n\n\terr = json.Unmarshal(data, config)\n\tif err != nil {\n\t\tlog.Fatalln(\"cant parse config:\", err)\n\t}\n\n\tif config.Comments {\n\t\tfmt.Println(\"Comments per page\", config.Limit)\n\t\tfmt.Println(\"Comments services\", config.Servers)\n\t} else {\n\t\tfmt.Println(\"Comments disabled\")\n\t}\n}\n"
  },
  {
    "path": "9-monitoring/1_config/3_ldflags/ldflags.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\n/*\n\tgo run -ldflags=\"-X 'main.Version=$(git rev-parse HEAD)' -X 'main.Branch=$(git rev-parse --abbrev-ref HEAD)'\" ldflags.go\n*/\n\nvar (\n\tVersion = \"\"\n\tBranch  = \"\"\n)\n\nfunc main() {\n\tfmt.Println(\"[start] starting version \", Version, Branch)\n}\n"
  },
  {
    "path": "9-monitoring/1_config/4_viper/config.yml",
    "content": "port: 8080\n\ndb:\n  host: 127.0.0.1\n  port: 5432\n  username: root\n  password: guest\n"
  },
  {
    "path": "9-monitoring/1_config/4_viper/main.go",
    "content": "package main\n\nimport (\n\t\"log\"\n\n\t\"github.com/spf13/viper\"\n)\n\nfunc main() {\n\tviper.AddConfigPath(\".\")\n\tviper.SetConfigName(\"config\")\n\tif err := viper.ReadInConfig(); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tport := viper.GetString(\"port\")\n\n\thost := viper.GetStringMap(\"db\")\n\n\tlog.Println(port, host)\n}\n"
  },
  {
    "path": "9-monitoring/1_config/5_consul/consul_config.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\tconsulapi \"github.com/hashicorp/consul/api\"\n)\n\nvar (\n\tconsulAddr = flag.String(\"addr\", \"127.0.0.1:8500\", \"consul addr (8500 in original consul)\")\n\n\tconsul          *consulapi.Client\n\tconsulLastIndex uint64 = 0\n\n\tglobalCfg   = make(map[string]string)\n\tglobalCfgMu = &sync.RWMutex{}\n\n\tcfgPrefix      = \"myapi/\"\n\tprefixStripper = strings.NewReplacer(cfgPrefix, \"\")\n)\n\n// линтер ругается если используем базовые типы в Value контекста\n// типа так безопаснее разграничивать\ntype key string\n\nconst configKey key = \"configKey\"\n\nfunc configMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tctx := r.Context()\n\n\t\tglobalCfgMu.RLock()\n\t\tlocalCfg := globalCfg\n\t\tglobalCfgMu.RUnlock()\n\n\t\tctx = context.WithValue(ctx,\n\t\t\tconfigKey,\n\t\t\tlocalCfg)\n\t\tnext.ServeHTTP(w, r.WithContext(ctx))\n\t})\n}\n\nfunc ConfigFromContext(ctx context.Context) (map[string]string, error) {\n\tcfg, ok := ctx.Value(configKey).(map[string]string)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"config not found\")\n\t}\n\treturn cfg, nil\n}\n\nfunc loadPostsHandle(w http.ResponseWriter, req *http.Request) {\n\tctx := req.Context()\n\tlocalCfg, err := ConfigFromContext(ctx)\n\n\tif err != nil {\n\t\thttp.Error(w, \"no config!\", 500)\n\t\treturn\n\t}\n\n\tfmt.Fprintf(w, \"localCfg version %v\\n%#v\\n\", consulLastIndex, localCfg)\n\tfmt.Fprintln(w, \"Request done\")\n}\n\nfunc main() {\n\tflag.Parse()\n\n\tvar err error\n\tconfig := consulapi.DefaultConfig()\n\tconfig.Address = *consulAddr\n\tconsul, err = consulapi.NewClient(config)\n\n\tif err != nil {\n\t\tfmt.Println(\"consul error\", err)\n\t\treturn\n\t}\n\n\tloadConfig()\n\tgo runConfigUpdater()\n\n\tsiteMux := http.NewServeMux()\n\tsiteMux.HandleFunc(\"/\", loadPostsHandle)\n\n\tsiteHandler := configMiddleware(siteMux)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", siteHandler)\n}\n\nfunc runConfigUpdater() {\n\tticker := time.Tick(3 * time.Second)\n\tfor _ = range ticker {\n\t\tloadConfig()\n\t}\n}\n\nfunc loadConfig() {\n\tqo := &consulapi.QueryOptions{\n\t\tWaitIndex: consulLastIndex,\n\t}\n\tkvPairs, qm, err := consul.KV().List(cfgPrefix, qo)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\treturn\n\t}\n\n\tfmt.Println(\"remote consulLastIndex\", qm.LastIndex)\n\tif consulLastIndex == qm.LastIndex {\n\t\tfmt.Println(\"consulLastIndex not changed\")\n\t\treturn\n\t}\n\n\tnewConfig := make(map[string]string)\n\n\tfor idx, item := range kvPairs {\n\t\tif item.Key == cfgPrefix {\n\t\t\tcontinue\n\t\t}\n\t\tfmt.Printf(\"item[%d] %#v\\n\", idx, item)\n\t\tkey := prefixStripper.Replace(item.Key)\n\t\tnewConfig[key] = string(item.Value)\n\t}\n\n\tglobalCfgMu.Lock()\n\tglobalCfg = newConfig\n\tconsulLastIndex = qm.LastIndex\n\tglobalCfgMu.Unlock()\n\n\tfmt.Printf(\"config updated to version %v\\n\\t%#v\\n\\n\", consulLastIndex, newConfig)\n}\n"
  },
  {
    "path": "9-monitoring/2_vault/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\t\"github.com/hashicorp/vault/api\"\n)\n\nfunc main() {\n\tclient, err := api.NewClient(&api.Config{\n\t\tAddress: \"http://127.0.0.1:8200\",\n\t})\n\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\ttoken := os.Getenv(\"token\")\n\tclient.SetToken(token)\n\tsecretValues, err := client.Logical().Read(\"secret/data/postgres\")\n\tif err != nil {\n\t\tlog.Println(err)\n\t}\n\tfmt.Printf(\"secret %s -> %+v\", \"postgres\", secretValues.Data)\n}\n"
  },
  {
    "path": "9-monitoring/2_vault/readme.md",
    "content": "docker run -p 8200:8200 -v $(pwd):/vault/config -d vault\n\nUnseal Key: o8BS/qgI/YWpn95eaaHt60AFnV/yYOOXrqFDq+lVXQg=\nRoot Token: s.yrEcqEeuKv85biCHpBa8TqCH\n"
  },
  {
    "path": "9-monitoring/3_monitoring/expvars/expvars.go",
    "content": "package main\n\nimport (\n\t\"expvar\"\n\t\"fmt\"\n\t\"net/http\"\n)\n\nvar (\n\thits = expvar.NewMap(\"hits\")\n\ti    = 0\n)\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\thits.Add(r.URL.String(), 1)\n\n\tfmt.Println(\"hit to\" + r.URL.String())\n\n\tw.Write([]byte(\"expvar increased\"))\n\ti++\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/\", handler)\n\n\texpvar.Publish(\"mystat\", expvar.Func(func() interface{} {\n\t\treturn map[string]int{\n\t\t\t\"test\":  100500,\n\t\t\t\"value\": i,\n\t\t}\n\t}))\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "9-monitoring/3_monitoring/metrics/context_monitoring.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"net/http\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"gopkg.in/alexcesaro/statsd.v2\"\n)\n\n// сколько в среднем спим при эмуляции работы\nconst AvgSleep = 50\n\nfunc trackContextTimings(ctx context.Context, metricName string, start time.Time) {\n\t// получаем тайминги из контекста\n\t// поскольку там пустой интерфейс, то нам надо преобразовать к нужному типу\n\ttimings, ok := ctx.Value(timingsKey).(*ctxTimings)\n\tif !ok {\n\t\treturn\n\t}\n\telapsed := time.Since(start)\n\t// лочимся на случай конкурентной записи в мапку\n\ttimings.Lock()\n\tdefer timings.Unlock()\n\t// если меткри ещё нет - мы её создадим, если есть - допишем в существующую\n\tif metric, metricExist := timings.Data[metricName]; !metricExist {\n\t\ttimings.Data[metricName] = &Timing{\n\t\t\tCount:    1,\n\t\t\tDuration: elapsed,\n\t\t}\n\t} else {\n\t\tmetric.Count++\n\t\tmetric.Duration += elapsed\n\t}\n}\n\ntype Timing struct {\n\tCount    int\n\tDuration time.Duration\n}\n\ntype ctxTimings struct {\n\tsync.Mutex\n\tData map[string]*Timing\n}\n\n// линтер ругается если используем базовые типы в Value контекста\n// типа так безопаснее разграничивать\ntype key int\n\nconst timingsKey key = 1\n\ntype TimingMiddleware struct {\n\tsync.Mutex\n\tStatsReciever *statsd.Client\n\tMetrics       map[string]int\n}\n\nfunc NewTimingMiddleware(st *statsd.Client) *TimingMiddleware {\n\ttm := &TimingMiddleware{\n\t\tStatsReciever: st,\n\t\tMetrics:       make(map[string]int),\n\t}\n\treturn tm\n}\n\nfunc (tm *TimingMiddleware) TrackRequestTimings(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tctx := r.Context()\n\t\tctx = context.WithValue(ctx,\n\t\t\ttimingsKey,\n\t\t\t&ctxTimings{\n\t\t\t\tData: make(map[string]*Timing),\n\t\t\t})\n\t\tdefer tm.logContextTimings(ctx, r.URL.Path, time.Now())\n\t\tnext.ServeHTTP(w, r.WithContext(ctx))\n\t})\n}\n\nfunc (tm *TimingMiddleware) logContextTimings(ctx context.Context, path string, start time.Time) {\n\t// получаем тайминги из контекста\n\t// поскольку там пустой интерфейс, то нам надо преобразовать к нужному типу\n\ttimings, ok := ctx.Value(timingsKey).(*ctxTimings)\n\tif !ok {\n\t\treturn\n\t}\n\ttotalReal := time.Since(start)\n\n\tpath = strings.Replace(path, \"/\", \"-\", -1)\n\n\tprefix := \"requests.\" + path + \".\"\n\n\t// buf := bytes.NewBufferString(path)\n\tvar total time.Duration\n\tfor timing, value := range timings.Data {\n\t\tmetric := prefix + \"timings.\" + timing\n\t\ttm.StatsReciever.Increment(metric)\n\t\ttm.StatsReciever.Timing(metric+\"_time\", uint64(value.Duration/time.Millisecond))\n\t\ttotal += value.Duration\n\t}\n\n\ttm.StatsReciever.Increment(prefix + \"hits\")\n\ttm.StatsReciever.Timing(prefix+\"tracked\", uint64(totalReal/time.Millisecond))\n\ttm.StatsReciever.Timing(prefix+\"real_time\", uint64(total/time.Millisecond))\n\tlog.Println(prefix+\"real_time\", uint64(total/time.Millisecond))\n}\n\nfunc emulateWork(ctx context.Context, workName string) {\n\tdefer trackContextTimings(ctx, workName, time.Now())\n\n\trnd := time.Duration(rand.Intn(AvgSleep))\n\ttime.Sleep(time.Millisecond * rnd)\n}\n\nfunc loadPostsHandle(w http.ResponseWriter, req *http.Request) {\n\tctx := req.Context()\n\n\temulateWork(ctx, \"checkCache\")\n\temulateWork(ctx, \"loadPosts\")\n\temulateWork(ctx, \"loadPosts\")\n\temulateWork(ctx, \"loadPosts\")\n\ttime.Sleep(10 * time.Millisecond)\n\temulateWork(ctx, \"loadSidebar\")\n\temulateWork(ctx, \"loadComments\")\n\n\tfmt.Fprintln(w, \"Request done\")\n}\n\nvar (\n\tstatsdAddr = flag.String(\"addr\", \"127.0.0.1:8125\", \"statsd addr\")\n)\n\nfunc main() {\n\tflag.Parse()\n\n\trand.Seed(time.Now().UTC().UnixNano())\n\n\tsiteMux := http.NewServeMux()\n\tsiteMux.HandleFunc(\"/\", loadPostsHandle)\n\n\tstatsd, err := statsd.New(\n\t\tstatsd.Prefix(\"prod\"),\n\t\tstatsd.Address(*statsdAddr),\n\t\tstatsd.ErrorHandler(func(err error) {\n\t\t\tlog.Print(err)\n\t\t}),\n\t)\n\tif err != nil {\n\t\tlog.Print(err)\n\t}\n\n\ttm := NewTimingMiddleware(statsd)\n\tsiteHandler := tm.TrackRequestTimings(siteMux)\n\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", siteHandler)\n}\n"
  },
  {
    "path": "9-monitoring/3_monitoring/prometheus/alertmanager/alertmanager.yml",
    "content": "global:\n  resolve_timeout: 5m\n  smtp_from: park.alerting@mail.ru\n  smtp_hello: mail.ru\n  smtp_smarthost: smtp.mail.ru:465\n  smtp_auth_username: park.alerting@mail.ru\n  smtp_auth_password: gb=D>zTa8)uLkndj@peE\n  smtp_require_tls: false\n\nroute:\n  group_by: ['alertname']\n  group_wait: 30s\n  group_interval: 10s\n  repeat_interval: 20s\n  receiver: 'email'\n\nreceivers:\n- name: 'alertmananger-bot'\n  webhook_configs:\n   - url: 'http://alertmanager-bot:8080'\n\n- name: email\n  email_configs:\n  - send_resolved: false\n    to: park.alerting@mail.ru\n    headers:\n      From: park.alerting@mail.ru\n      Subject: '{{ template \"email.default.subject\" . }}'\n      To: park.alerting@mail.ru\n    html: '{{ template \"email.default.html\" . }}'\n\ninhibit_rules:\n  - source_match:\n      severity: 'critical'\n    target_match:\n      severity: 'warning'\n    equal: ['alertname', 'instance']\n"
  },
  {
    "path": "9-monitoring/3_monitoring/prometheus/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\n\t\"github.com/prometheus/client_golang/prometheus\"\n\t\"github.com/prometheus/client_golang/prometheus/promhttp\"\n)\n\nvar fooCount = prometheus.NewCounter(prometheus.CounterOpts{\n\tName: \"foo_total\",\n\tHelp: \"Number of foo successfully processed.\",\n})\n\nvar hits = prometheus.NewCounterVec(prometheus.CounterOpts{\n\tName: \"hits\",\n}, []string{\"status\", \"path\"})\n\nfunc main() {\n\tprometheus.MustRegister(fooCount, hits)\n\n\thttp.Handle(\"/metrics\", promhttp.Handler())\n\n\thttp.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\thits.WithLabelValues(\"200\", r.URL.String()).Inc()\n\t\tfooCount.Add(1)\n\t\tfmt.Fprintf(w, \"foo_total increased\")\n\t})\n\n\thttp.HandleFunc(\"/500\", func(w http.ResponseWriter, r *http.Request) {\n\t\thits.WithLabelValues(\"500\", r.URL.String()).Inc()\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\tw.Write([]byte(\"error\"))\n\t})\n\n\tlog.Fatal(http.ListenAndServe(\":8080\", nil))\n}\n"
  },
  {
    "path": "9-monitoring/3_monitoring/prometheus/prometheus/alerts.yml",
    "content": "groups:\n  - name: default\n    rules:\n    - alert: InternalServerError\n      expr: increase(hits{status=\"500\"}[1m]) > 0\n      for: 1s\n      labels:\n        severity: critical\n      annotations:\n        summary: \"path {{ $labels.path }} returned status 500\"\n        description: \"{{ $labels.path }} of job {{ $labels.job }} returned status {{ $labels.status }}\"\n"
  },
  {
    "path": "9-monitoring/3_monitoring/prometheus/prometheus/prometheus.yml",
    "content": "global:\n  scrape_interval:     10s\n  evaluation_interval: 10s\n\nscrape_configs:\n  - job_name: 'golang'\n    static_configs:\n      - targets: ['docker.for.mac.localhost:8080']\n\n  - job_name: 'system'\n    static_configs:\n      - targets: ['docker.for.mac.localhost:9100']\n\nrule_files:\n  - 'alerts.yml'\n\nalerting:\n  alertmanagers:\n    - static_configs:\n      - targets:\n        - alertmanager:9093\n\n"
  },
  {
    "path": "9-monitoring/3_monitoring/prometheus/readme.md",
    "content": "#Run prometheus\n```\ndocker run -p 9090:9090 -d --name prometheus --network monitoring -v $(pwd)/prometheus:/etc/config prom/prometheus --config.file=/etc/config/prometheus.yml\n```\n\n```\ndocker run -p 9090:9090 -it --name prometheus --network monitoring -v $(pwd)/prometheus:/etc/config prom/prometheus --config.file=/etc/config/prometheus.yml\n```\n\n# Run alert manager\n```\ndocker run -d -p 9093:9093 -v $(pwd)/alertmanager:/etc/config --network monitoring --name alertmanager prom/alertmanager --config.file=/etc/config/alertmanager.yml\n```\n\n# Telegram bot for alerting\n```\ndocker run -d \\\n\t-e 'ALERTMANAGER_URL=http://alertmanager:9093' \\\n\t-e 'BOLT_PATH=/data/bot.db' \\\n\t-e 'STORE=bolt' \\\n\t-e 'TEMPLATE_PATHS=/templates/default.tmpl' \\\n\t-e 'TELEGRAM_ADMIN=164626023' \\\n\t-e 'TELEGRAM_TOKEN=686312965:AAFf0goR98-8uVxGM8tRVxhafHyyQ_KIynk' \\\n\t-v $(pwd)/alertmanager-bot:/data \\\n\t-v $(pwd)/alertmanager-bot:/templates \\\n\t--network monitoring \\\n\t--name alertmanager-bot \\\n\tmetalmatze/alertmanager-bot:0.4.0 --listen.addr 0.0.0.0:8080\n```\n"
  },
  {
    "path": "9-monitoring/3_monitoring/sentry/echo/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"github.com/getsentry/sentry-go\"\n\tsentryecho \"github.com/getsentry/sentry-go/echo\"\n\t\"github.com/labstack/echo/v4\"\n\t\"github.com/labstack/echo/v4/middleware\"\n)\n\nfunc main() {\n\t_ = sentry.Init(sentry.ClientOptions{\n\t\tDsn: \"https://73eda8ec507b464caeb9d8fd331bc9ce@o427877.ingest.sentry.io/5372588\",\n\t\tBeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {\n\t\t\tfmt.Println(event)\n\t\t\treturn event\n\t\t},\n\t\tDebug:            true,\n\t\tAttachStacktrace: true,\n\t})\n\n\tapp := echo.New()\n\n\tapp.Use(middleware.Logger())\n\tapp.Use(middleware.Recover())\n\n\tapp.Use(sentryecho.New(sentryecho.Options{\n\t\tRepanic: true,\n\t}))\n\n\tapp.Use(func(next echo.HandlerFunc) echo.HandlerFunc {\n\t\treturn func(ctx echo.Context) error {\n\t\t\tif hub := sentryecho.GetHubFromContext(ctx); hub != nil {\n\t\t\t\thub.Scope().SetTag(\"someRandomTag\", \"maybeYouNeedIt\")\n\t\t\t}\n\t\t\treturn next(ctx)\n\t\t}\n\t})\n\n\tapp.GET(\"/\", func(ctx echo.Context) error {\n\t\tif hub := sentryecho.GetHubFromContext(ctx); hub != nil {\n\t\t\thub.WithScope(func(scope *sentry.Scope) {\n\t\t\t\tscope.SetExtra(\"unwantedQuery\", \"someQueryDataMaybe\")\n\t\t\t\thub.CaptureMessage(\"User provided unwanted query string, but we recovered just fine\")\n\t\t\t})\n\t\t}\n\t\treturn ctx.String(http.StatusOK, \"Hello, World!\")\n\t})\n\n\tapp.GET(\"/foo\", func(ctx echo.Context) error {\n\t\tpanic(\"y tho\")\n\t})\n\n\tapp.Logger.Fatal(app.Start(\":8080\"))\n}\n"
  },
  {
    "path": "9-monitoring/3_monitoring/sentry/simple/main.go",
    "content": "package main\n\nimport (\n\t\"github.com/pkg/errors\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/getsentry/sentry-go\"\n)\n\nfunc firstError() error {\n\treturn errors.New(\"error\")\n}\n\nfunc returnError() error {\n\treturn errors.Wrap(firstError(), \"failed to do something\")\n}\n\nfunc main() {\n\terr := sentry.Init(sentry.ClientOptions{\n\t\tDsn:   \"https://73eda8ec507b464caeb9d8fd331bc9ce@o427877.ingest.sentry.io/5372588\",\n\t\tDebug: true,\n\t})\n\tif err != nil {\n\t\tlog.Fatalf(\"sentry.Init: %s\", err)\n\t}\n\n\tdefer sentry.Flush(2 * time.Second)\n\n\thttp.HandleFunc(\n\t\t\"/500\",\n\t\tfunc(writer http.ResponseWriter, request *http.Request) {\n\t\t\tsentry.CaptureException(returnError())\n\t\t},\n\t)\n\n\thttp.ListenAndServe(\":8080\", nil)\n}\n"
  },
  {
    "path": "9-monitoring/4_tracing/jaeger_grpc/client/main.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\ttraceutils \"github.com/opentracing-contrib/go-grpc\"\n\t\"github.com/opentracing/opentracing-go\"\n\t\"github.com/uber/jaeger-client-go\"\n\tjaegercfg \"github.com/uber/jaeger-client-go/config\"\n\tjaegerlog \"github.com/uber/jaeger-client-go/log\"\n\t\"github.com/uber/jaeger-lib/metrics\"\n\n\t\"google.golang.org/grpc\"\n\n\t\"github.com/go-park-mail-ru/lectures/9-monitoring/4_tracing/jaeger_grpc/session\"\n)\n\nvar loginFormTmpl = []byte(`\n<html>\n\t<body>\n\t<form action=\"/login\" method=\"post\">\n\t\tLogin: <input type=\"text\" name=\"login\">\n\t\tPassword: <input type=\"password\" name=\"password\">\n\t\t<input type=\"submit\" value=\"Login\">\n\t</form>\n\t</body>\n</html>\n`)\n\nvar (\n\tsessManager session.AuthCheckerClient\n)\n\nfunc checkSession(r *http.Request) (*session.Session, error) {\n\tcookieSessionID, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\treturn nil, nil\n\t} else if err != nil {\n\t\treturn nil, err\n\t}\n\n\tsess, err := sessManager.Check(\n\t\tcontext.Background(),\n\t\t&session.SessionID{\n\t\t\tID: cookieSessionID.Value,\n\t\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn sess, nil\n}\n\nfunc innerPage(w http.ResponseWriter, r *http.Request) {\n\tsess, err := checkSession(r)\n\tif err != nil || sess == nil {\n\t\tw.Write(loginFormTmpl)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"text/html\")\n\tfmt.Fprintln(w, \"Welcome, \"+sess.Login+\" <br />\")\n\tfmt.Fprintln(w, \"Session ua: \"+sess.Useragent+\" <br />\")\n\tfmt.Fprintln(w, `<a href=\"/logout\">logout</a>`)\n}\n\nfunc loginPage(w http.ResponseWriter, r *http.Request) {\n\tinputLogin := r.FormValue(\"login\")\n\texpiration := time.Now().Add(365 * 24 * time.Hour)\n\n\tsess, err := sessManager.Create(\n\t\tcontext.Background(),\n\t\t&session.Session{\n\t\t\tLogin:     inputLogin,\n\t\t\tUseragent: r.UserAgent(),\n\t\t})\n\tif err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tcookie := http.Cookie{\n\t\tName:    \"session_id\",\n\t\tValue:   sess.ID,\n\t\tExpires: expiration,\n\t}\n\thttp.SetCookie(w, &cookie)\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n\nfunc main() {\n\n\tjaegerCfgInstance := jaegercfg.Configuration{\n\t\tServiceName: \"client\",\n\t\tSampler: &jaegercfg.SamplerConfig{\n\t\t\tType:  jaeger.SamplerTypeConst,\n\t\t\tParam: 1,\n\t\t},\n\t\tReporter: &jaegercfg.ReporterConfig{\n\t\t\tLogSpans:           true,\n\t\t\tLocalAgentHostPort: \"localhost:6831\",\n\t\t},\n\t}\n\n\ttracer, closer, err := jaegerCfgInstance.NewTracer(\n\t\tjaegercfg.Logger(jaegerlog.StdLogger),\n\t\tjaegercfg.Metrics(metrics.NullFactory),\n\t)\n\n\tif err != nil {\n\t\tlog.Fatal(\"cannot create tracer\", err)\n\t}\n\n\topentracing.SetGlobalTracer(tracer)\n\tdefer closer.Close()\n\n\tgrcpConn, err := grpc.Dial(\n\t\t\"127.0.0.1:8081\",\n\t\tgrpc.WithInsecure(),\n\t\tgrpc.WithUnaryInterceptor(traceutils.OpenTracingClientInterceptor(tracer)),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"cant connect to grpc\")\n\t}\n\tdefer grcpConn.Close()\n\n\tsessManager = session.NewAuthCheckerClient(grcpConn)\n\n\thttp.HandleFunc(\"/\", innerPage)\n\thttp.HandleFunc(\"/login\", loginPage)\n\thttp.HandleFunc(\"/logout\", logoutPage)\n\tfmt.Println(\"starting server at :8080\")\n\thttp.ListenAndServe(\":8080\", nil)\n}\n\nfunc logoutPage(w http.ResponseWriter, r *http.Request) {\n\tcookieSessionID, err := r.Cookie(\"session_id\")\n\tif err == http.ErrNoCookie {\n\t\thttp.Redirect(w, r, \"/\", http.StatusFound)\n\t\treturn\n\t} else if err != nil {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tsessManager.Delete(\n\t\tcontext.Background(),\n\t\t&session.SessionID{\n\t\t\tID: cookieSessionID.Value,\n\t\t})\n\n\tcookieSessionID.Expires = time.Now().AddDate(0, 0, -1)\n\thttp.SetCookie(w, cookieSessionID)\n\n\thttp.Redirect(w, r, \"/\", http.StatusFound)\n}\n"
  },
  {
    "path": "9-monitoring/4_tracing/jaeger_grpc/readme.md",
    "content": "docker run \\\n  --rm \\\n  --name jaeger \\\n  -p6831:6831/udp \\\n  -p16686:16686 \\\n  jaegertracing/all-in-one:latest"
  },
  {
    "path": "9-monitoring/4_tracing/jaeger_grpc/server/server.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\n\t\"github.com/go-park-mail-ru/lectures/9-monitoring/4_tracing/jaeger_grpc/session\"\n\ttraceutils \"github.com/opentracing-contrib/go-grpc\"\n\topentracing \"github.com/opentracing/opentracing-go\"\n\t\"github.com/uber/jaeger-client-go\"\n\tjaegercfg \"github.com/uber/jaeger-client-go/config\"\n\tjaegerlog \"github.com/uber/jaeger-client-go/log\"\n\n\t\"github.com/uber/jaeger-lib/metrics\"\n\n\t\"google.golang.org/grpc\"\n)\n\nfunc main() {\n\n\tjaegerCfgInstance := jaegercfg.Configuration{\n\t\tServiceName: \"session\",\n\t\tSampler: &jaegercfg.SamplerConfig{\n\t\t\tType:  jaeger.SamplerTypeConst,\n\t\t\tParam: 1,\n\t\t},\n\t\tReporter: &jaegercfg.ReporterConfig{\n\t\t\tLogSpans:           true,\n\t\t\tLocalAgentHostPort: \"localhost:6831\",\n\t\t},\n\t}\n\n\ttracer, closer, err := jaegerCfgInstance.NewTracer(\n\t\tjaegercfg.Logger(jaegerlog.StdLogger),\n\t\tjaegercfg.Metrics(metrics.NullFactory),\n\t)\n\n\tif err != nil {\n\t\tlog.Fatal(\"cannot create tracer\", err)\n\t}\n\n\topentracing.SetGlobalTracer(tracer)\n\tdefer closer.Close()\n\n\tlis, err := net.Listen(\"tcp\", \":8081\")\n\tif err != nil {\n\t\tlog.Fatalln(\"cant listet port\", err)\n\t}\n\n\tserver := grpc.NewServer(grpc.UnaryInterceptor(traceutils.OpenTracingServerInterceptor(tracer)))\n\n\tsession.RegisterAuthCheckerServer(server, NewSessionManager())\n\n\tfmt.Println(\"starting server at :8081\")\n\tserver.Serve(lis)\n}\n"
  },
  {
    "path": "9-monitoring/4_tracing/jaeger_grpc/server/session.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"sync\"\n\n\t\"github.com/go-park-mail-ru/lectures/9-monitoring/4_tracing/jaeger_grpc/session\"\n\n\t\"google.golang.org/grpc\"\n\t\"google.golang.org/grpc/codes\"\n\n\t\"golang.org/x/net/context\"\n)\n\nconst sessKeyLen = 10\n\ntype SessionManager struct {\n\tmu       sync.RWMutex\n\tsessions map[session.SessionID]*session.Session\n}\n\nfunc NewSessionManager() *SessionManager {\n\treturn &SessionManager{\n\t\tmu:       sync.RWMutex{},\n\t\tsessions: map[session.SessionID]*session.Session{},\n\t}\n}\n\nfunc (sm *SessionManager) Create(ctx context.Context, in *session.Session) (*session.SessionID, error) {\n\tfmt.Println(\"call Create\", in)\n\tid := &session.SessionID{RandStringRunes(sessKeyLen)}\n\tsm.mu.Lock()\n\tsm.sessions[*id] = in\n\tsm.mu.Unlock()\n\treturn id, nil\n}\n\nfunc (sm *SessionManager) Check(ctx context.Context, in *session.SessionID) (*session.Session, error) {\n\tfmt.Println(\"call Check\", in)\n\tsm.mu.RLock()\n\tdefer sm.mu.RUnlock()\n\tif sess, ok := sm.sessions[*in]; ok {\n\t\treturn sess, nil\n\t}\n\treturn nil, grpc.Errorf(codes.NotFound, \"session not found\")\n}\n\nfunc (sm *SessionManager) Delete(ctx context.Context, in *session.SessionID) (*session.Nothing, error) {\n\tfmt.Println(\"call Delete\", in)\n\tsm.mu.Lock()\n\tdefer sm.mu.Unlock()\n\tdelete(sm.sessions, *in)\n\treturn &session.Nothing{Dummy: true}, nil\n}\n\nvar letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc RandStringRunes(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letterRunes[rand.Intn(len(letterRunes))]\n\t}\n\treturn string(b)\n}\n"
  },
  {
    "path": "9-monitoring/4_tracing/jaeger_grpc/session/session.pb.go",
    "content": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// source: session.proto\n\n/*\nPackage session is a generated protocol buffer package.\n\nIt is generated from these files:\n\tsession.proto\n\nIt has these top-level messages:\n\tSessionID\n\tSession\n\tNothing\n*/\npackage session\n\nimport proto \"github.com/golang/protobuf/proto\"\nimport fmt \"fmt\"\nimport math \"math\"\n\nimport (\n\tcontext \"golang.org/x/net/context\"\n\tgrpc \"google.golang.org/grpc\"\n)\n\n// Reference imports to suppress errors if they are not otherwise used.\nvar _ = proto.Marshal\nvar _ = fmt.Errorf\nvar _ = math.Inf\n\n// This is a compile-time assertion to ensure that this generated file\n// is compatible with the proto package it is being compiled against.\n// A compilation error at this line likely means your copy of the\n// proto package needs to be updated.\nconst _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package\n\ntype SessionID struct {\n\tID string `protobuf:\"bytes,1,opt,name=ID\" json:\"ID,omitempty\"`\n}\n\nfunc (m *SessionID) Reset()                    { *m = SessionID{} }\nfunc (m *SessionID) String() string            { return proto.CompactTextString(m) }\nfunc (*SessionID) ProtoMessage()               {}\nfunc (*SessionID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }\n\nfunc (m *SessionID) GetID() string {\n\tif m != nil {\n\t\treturn m.ID\n\t}\n\treturn \"\"\n}\n\ntype Session struct {\n\tLogin     string `protobuf:\"bytes,1,opt,name=login\" json:\"login,omitempty\"`\n\tUseragent string `protobuf:\"bytes,2,opt,name=useragent\" json:\"useragent,omitempty\"`\n}\n\nfunc (m *Session) Reset()                    { *m = Session{} }\nfunc (m *Session) String() string            { return proto.CompactTextString(m) }\nfunc (*Session) ProtoMessage()               {}\nfunc (*Session) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }\n\nfunc (m *Session) GetLogin() string {\n\tif m != nil {\n\t\treturn m.Login\n\t}\n\treturn \"\"\n}\n\nfunc (m *Session) GetUseragent() string {\n\tif m != nil {\n\t\treturn m.Useragent\n\t}\n\treturn \"\"\n}\n\ntype Nothing struct {\n\tDummy bool `protobuf:\"varint,1,opt,name=dummy\" json:\"dummy,omitempty\"`\n}\n\nfunc (m *Nothing) Reset()                    { *m = Nothing{} }\nfunc (m *Nothing) String() string            { return proto.CompactTextString(m) }\nfunc (*Nothing) ProtoMessage()               {}\nfunc (*Nothing) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }\n\nfunc (m *Nothing) GetDummy() bool {\n\tif m != nil {\n\t\treturn m.Dummy\n\t}\n\treturn false\n}\n\nfunc init() {\n\tproto.RegisterType((*SessionID)(nil), \"session.SessionID\")\n\tproto.RegisterType((*Session)(nil), \"session.Session\")\n\tproto.RegisterType((*Nothing)(nil), \"session.Nothing\")\n}\n\n// Reference imports to suppress errors if they are not otherwise used.\nvar _ context.Context\nvar _ grpc.ClientConn\n\n// This is a compile-time assertion to ensure that this generated file\n// is compatible with the grpc package it is being compiled against.\nconst _ = grpc.SupportPackageIsVersion4\n\n// Client API for AuthChecker service\n\ntype AuthCheckerClient interface {\n\tCreate(ctx context.Context, in *Session, opts ...grpc.CallOption) (*SessionID, error)\n\tCheck(ctx context.Context, in *SessionID, opts ...grpc.CallOption) (*Session, error)\n\tDelete(ctx context.Context, in *SessionID, opts ...grpc.CallOption) (*Nothing, error)\n}\n\ntype authCheckerClient struct {\n\tcc *grpc.ClientConn\n}\n\nfunc NewAuthCheckerClient(cc *grpc.ClientConn) AuthCheckerClient {\n\treturn &authCheckerClient{cc}\n}\n\nfunc (c *authCheckerClient) Create(ctx context.Context, in *Session, opts ...grpc.CallOption) (*SessionID, error) {\n\tout := new(SessionID)\n\terr := grpc.Invoke(ctx, \"/session.AuthChecker/Create\", in, out, c.cc, opts...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\nfunc (c *authCheckerClient) Check(ctx context.Context, in *SessionID, opts ...grpc.CallOption) (*Session, error) {\n\tout := new(Session)\n\terr := grpc.Invoke(ctx, \"/session.AuthChecker/Check\", in, out, c.cc, opts...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\nfunc (c *authCheckerClient) Delete(ctx context.Context, in *SessionID, opts ...grpc.CallOption) (*Nothing, error) {\n\tout := new(Nothing)\n\terr := grpc.Invoke(ctx, \"/session.AuthChecker/Delete\", in, out, c.cc, opts...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\n// Server API for AuthChecker service\n\ntype AuthCheckerServer interface {\n\tCreate(context.Context, *Session) (*SessionID, error)\n\tCheck(context.Context, *SessionID) (*Session, error)\n\tDelete(context.Context, *SessionID) (*Nothing, error)\n}\n\nfunc RegisterAuthCheckerServer(s *grpc.Server, srv AuthCheckerServer) {\n\ts.RegisterService(&_AuthChecker_serviceDesc, srv)\n}\n\nfunc _AuthChecker_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {\n\tin := new(Session)\n\tif err := dec(in); err != nil {\n\t\treturn nil, err\n\t}\n\tif interceptor == nil {\n\t\treturn srv.(AuthCheckerServer).Create(ctx, in)\n\t}\n\tinfo := &grpc.UnaryServerInfo{\n\t\tServer:     srv,\n\t\tFullMethod: \"/session.AuthChecker/Create\",\n\t}\n\thandler := func(ctx context.Context, req interface{}) (interface{}, error) {\n\t\treturn srv.(AuthCheckerServer).Create(ctx, req.(*Session))\n\t}\n\treturn interceptor(ctx, in, info, handler)\n}\n\nfunc _AuthChecker_Check_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {\n\tin := new(SessionID)\n\tif err := dec(in); err != nil {\n\t\treturn nil, err\n\t}\n\tif interceptor == nil {\n\t\treturn srv.(AuthCheckerServer).Check(ctx, in)\n\t}\n\tinfo := &grpc.UnaryServerInfo{\n\t\tServer:     srv,\n\t\tFullMethod: \"/session.AuthChecker/Check\",\n\t}\n\thandler := func(ctx context.Context, req interface{}) (interface{}, error) {\n\t\treturn srv.(AuthCheckerServer).Check(ctx, req.(*SessionID))\n\t}\n\treturn interceptor(ctx, in, info, handler)\n}\n\nfunc _AuthChecker_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {\n\tin := new(SessionID)\n\tif err := dec(in); err != nil {\n\t\treturn nil, err\n\t}\n\tif interceptor == nil {\n\t\treturn srv.(AuthCheckerServer).Delete(ctx, in)\n\t}\n\tinfo := &grpc.UnaryServerInfo{\n\t\tServer:     srv,\n\t\tFullMethod: \"/session.AuthChecker/Delete\",\n\t}\n\thandler := func(ctx context.Context, req interface{}) (interface{}, error) {\n\t\treturn srv.(AuthCheckerServer).Delete(ctx, req.(*SessionID))\n\t}\n\treturn interceptor(ctx, in, info, handler)\n}\n\nvar _AuthChecker_serviceDesc = grpc.ServiceDesc{\n\tServiceName: \"session.AuthChecker\",\n\tHandlerType: (*AuthCheckerServer)(nil),\n\tMethods: []grpc.MethodDesc{\n\t\t{\n\t\t\tMethodName: \"Create\",\n\t\t\tHandler:    _AuthChecker_Create_Handler,\n\t\t},\n\t\t{\n\t\t\tMethodName: \"Check\",\n\t\t\tHandler:    _AuthChecker_Check_Handler,\n\t\t},\n\t\t{\n\t\t\tMethodName: \"Delete\",\n\t\t\tHandler:    _AuthChecker_Delete_Handler,\n\t\t},\n\t},\n\tStreams:  []grpc.StreamDesc{},\n\tMetadata: \"session.proto\",\n}\n\nfunc init() { proto.RegisterFile(\"session.proto\", fileDescriptor0) }\n\nvar fileDescriptor0 = []byte{\n\t// 205 bytes of a gzipped FileDescriptorProto\n\t0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2d, 0x4e, 0x2d, 0x2e,\n\t0xce, 0xcc, 0xcf, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x72, 0x95, 0xa4, 0xb9,\n\t0x38, 0x83, 0x21, 0x4c, 0x4f, 0x17, 0x21, 0x3e, 0x2e, 0x26, 0x4f, 0x17, 0x09, 0x46, 0x05, 0x46,\n\t0x0d, 0xce, 0x20, 0x26, 0x4f, 0x17, 0x25, 0x5b, 0x2e, 0x76, 0xa8, 0xa4, 0x90, 0x08, 0x17, 0x6b,\n\t0x4e, 0x7e, 0x7a, 0x66, 0x1e, 0x54, 0x16, 0xc2, 0x11, 0x92, 0xe1, 0xe2, 0x2c, 0x2d, 0x4e, 0x2d,\n\t0x4a, 0x4c, 0x4f, 0xcd, 0x2b, 0x91, 0x60, 0x02, 0xcb, 0x20, 0x04, 0x94, 0xe4, 0xb9, 0xd8, 0xfd,\n\t0xf2, 0x4b, 0x32, 0x32, 0xf3, 0xd2, 0x41, 0xda, 0x53, 0x4a, 0x73, 0x73, 0x2b, 0xc1, 0xda, 0x39,\n\t0x82, 0x20, 0x1c, 0xa3, 0x45, 0x8c, 0x5c, 0xdc, 0x8e, 0xa5, 0x25, 0x19, 0xce, 0x19, 0xa9, 0xc9,\n\t0xd9, 0xa9, 0x45, 0x42, 0x06, 0x5c, 0x6c, 0xce, 0x45, 0xa9, 0x89, 0x25, 0xa9, 0x42, 0x02, 0x7a,\n\t0x30, 0xf7, 0x42, 0x1d, 0x20, 0x25, 0x84, 0x2e, 0xe2, 0xe9, 0xa2, 0xc4, 0x20, 0xa4, 0xcf, 0xc5,\n\t0x0a, 0xd6, 0x2c, 0x84, 0x45, 0x5a, 0x0a, 0xc3, 0x10, 0x25, 0x06, 0x90, 0x15, 0x2e, 0xa9, 0x39,\n\t0xa9, 0x25, 0xa9, 0x04, 0x74, 0x40, 0x1d, 0xae, 0xc4, 0x90, 0xc4, 0x06, 0x0e, 0x31, 0x63, 0x40,\n\t0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x14, 0x16, 0x5c, 0x42, 0x01, 0x00, 0x00,\n}\n"
  },
  {
    "path": "9-monitoring/4_tracing/jaeger_grpc/session/session.proto",
    "content": "syntax = \"proto3\";\n\n// protoc --go_out=plugins=grpc:. *.proto\n\npackage session;\n\nmessage SessionID {\n  string ID = 1;\n}\n\nmessage Session {\n  string login = 1;\n  string useragent = 2;\n}\n\nmessage Nothing {\n  bool dummy = 1;\n}\n\n// grpc-сервис проверки авторизации\nservice AuthChecker {\n    rpc Create (Session) returns (SessionID) {}\n    rpc Check (SessionID) returns (Session) {}\n    rpc Delete (SessionID) returns (Nothing) {}\n}\n\n"
  },
  {
    "path": "README.md",
    "content": "# lectures"
  },
  {
    "path": "go.mod",
    "content": "module github.com/go-park-mail-ru/lectures\n\ngo 1.25.0\n\nrequire (\n\tgithub.com/99designs/gqlgen v0.11.1\n\tgithub.com/DATA-DOG/go-sqlmock v1.3.3\n\tgithub.com/IBM/sarama v1.47.0\n\tgithub.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751\n\tgithub.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d\n\tgithub.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d\n\tgithub.com/buaazp/fasthttprouter v0.1.1\n\tgithub.com/casbin/casbin v1.9.1\n\tgithub.com/dgrijalva/jwt-go v3.2.0+incompatible\n\tgithub.com/gen1us2k/go-translit v0.0.0-20160120121136-46f1a0be552c\n\tgithub.com/getsentry/sentry-go v0.13.0\n\tgithub.com/go-sql-driver/mysql v1.6.0\n\tgithub.com/golang/mock v1.6.0\n\tgithub.com/golang/protobuf v1.5.2\n\tgithub.com/gomodule/redigo v1.8.9\n\tgithub.com/gorilla/mux v1.8.0\n\tgithub.com/gorilla/schema v1.2.0\n\tgithub.com/gorilla/websocket v1.5.0\n\tgithub.com/graphql-go/graphql v0.8.0\n\tgithub.com/hashicorp/consul/api v1.15.3\n\tgithub.com/hashicorp/vault/api v1.8.2\n\tgithub.com/icrowley/fake v0.0.0-20220625154756-3c7517006344\n\tgithub.com/jackc/pgx v3.6.2+incompatible\n\tgithub.com/jackc/pgx/v5 v5.9.1\n\tgithub.com/jinzhu/gorm v1.9.16\n\tgithub.com/jmoiron/sqlx v1.3.5\n\tgithub.com/julienschmidt/httprouter v1.3.0\n\tgithub.com/labstack/echo v3.3.10+incompatible\n\tgithub.com/labstack/echo/v4 v4.9.0\n\tgithub.com/mailru/easyjson v0.7.7\n\tgithub.com/microcosm-cc/bluemonday v1.0.21\n\tgithub.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646\n\tgithub.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e\n\tgithub.com/opentracing/opentracing-go v1.2.0\n\tgithub.com/pkg/errors v0.9.1\n\tgithub.com/prometheus/client_golang v1.12.1\n\tgithub.com/sirupsen/logrus v1.9.0\n\tgithub.com/spf13/viper v1.14.0\n\tgithub.com/streadway/amqp v1.0.0\n\tgithub.com/stretchr/testify v1.11.1\n\tgithub.com/swaggo/http-swagger v1.3.3\n\tgithub.com/swaggo/swag v1.8.5\n\tgithub.com/tarantool/go-tarantool v1.12.2\n\tgithub.com/tarantool/go-tarantool/v2 v2.4.2\n\tgithub.com/uber/jaeger-client-go v2.30.0+incompatible\n\tgithub.com/uber/jaeger-lib v2.4.1+incompatible\n\tgithub.com/valyala/fasthttp v1.45.0\n\tgithub.com/vektah/gqlparser v1.3.1\n\tgithub.com/ybbus/jsonrpc/v2 v2.1.6\n\tgo.mongodb.org/mongo-driver v1.11.2\n\tgo.uber.org/mock v0.6.0\n\tgo.uber.org/zap v1.23.0\n\tgolang.org/x/crypto v0.48.0\n\tgolang.org/x/net v0.51.0\n\tgolang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783\n\tgolang.org/x/sync v0.19.0\n\tgoogle.golang.org/grpc v1.50.1\n\tgoogle.golang.org/protobuf v1.28.1\n\tgopkg.in/alexcesaro/statsd.v2 v2.0.0\n\tgopkg.in/vmihailenco/msgpack.v2 v2.9.2\n\tgorm.io/driver/mysql v1.3.6\n\tgorm.io/gorm v1.23.8\n)\n\nrequire (\n\tgithub.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect\n\tgithub.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect\n\tgithub.com/KyleBanks/depth v1.2.1 // indirect\n\tgithub.com/agnivade/levenshtein v1.0.3 // indirect\n\tgithub.com/andybalholm/brotli v1.0.5 // indirect\n\tgithub.com/armon/go-metrics v0.4.0 // indirect\n\tgithub.com/armon/go-radix v1.0.0 // indirect\n\tgithub.com/aymerick/douceur v0.2.0 // indirect\n\tgithub.com/beorn7/perks v1.0.1 // indirect\n\tgithub.com/cenkalti/backoff/v3 v3.0.0 // indirect\n\tgithub.com/cespare/xxhash/v2 v2.1.2 // indirect\n\tgithub.com/cockroachdb/apd v1.1.0 // indirect\n\tgithub.com/corpix/uarand v0.0.0-20170723150923-031be390f409 // indirect\n\tgithub.com/davecgh/go-spew v1.1.1 // indirect\n\tgithub.com/eapache/go-resiliency v1.7.0 // indirect\n\tgithub.com/eapache/queue v1.1.0 // indirect\n\tgithub.com/fatih/color v1.13.0 // indirect\n\tgithub.com/fsnotify/fsnotify v1.6.0 // indirect\n\tgithub.com/go-openapi/jsonpointer v0.19.5 // indirect\n\tgithub.com/go-openapi/jsonreference v0.20.0 // indirect\n\tgithub.com/go-openapi/spec v0.20.6 // indirect\n\tgithub.com/go-openapi/swag v0.19.15 // indirect\n\tgithub.com/gofrs/uuid v4.2.0+incompatible // indirect\n\tgithub.com/golang-jwt/jwt v3.2.2+incompatible // indirect\n\tgithub.com/golang/snappy v0.0.4 // indirect\n\tgithub.com/google/uuid v1.6.0 // indirect\n\tgithub.com/gorilla/css v1.0.0 // indirect\n\tgithub.com/hashicorp/errwrap v1.1.0 // indirect\n\tgithub.com/hashicorp/go-cleanhttp v0.5.2 // indirect\n\tgithub.com/hashicorp/go-hclog v1.2.0 // indirect\n\tgithub.com/hashicorp/go-immutable-radix v1.3.1 // indirect\n\tgithub.com/hashicorp/go-multierror v1.1.1 // indirect\n\tgithub.com/hashicorp/go-plugin v1.4.5 // indirect\n\tgithub.com/hashicorp/go-retryablehttp v0.6.6 // indirect\n\tgithub.com/hashicorp/go-rootcerts v1.0.2 // indirect\n\tgithub.com/hashicorp/go-secure-stdlib/mlock v0.1.1 // indirect\n\tgithub.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect\n\tgithub.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect\n\tgithub.com/hashicorp/go-sockaddr v1.0.2 // indirect\n\tgithub.com/hashicorp/go-uuid v1.0.3 // indirect\n\tgithub.com/hashicorp/go-version v1.2.0 // indirect\n\tgithub.com/hashicorp/golang-lru v0.5.4 // indirect\n\tgithub.com/hashicorp/hcl v1.0.0 // indirect\n\tgithub.com/hashicorp/serf v0.9.8 // indirect\n\tgithub.com/hashicorp/vault/sdk v0.6.0 // indirect\n\tgithub.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect\n\tgithub.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect\n\tgithub.com/jackc/pgpassfile v1.0.0 // indirect\n\tgithub.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect\n\tgithub.com/jackc/puddle/v2 v2.2.2 // indirect\n\tgithub.com/jcmturner/aescts/v2 v2.0.0 // indirect\n\tgithub.com/jcmturner/dnsutils/v2 v2.0.0 // indirect\n\tgithub.com/jcmturner/gofork v1.7.6 // indirect\n\tgithub.com/jcmturner/gokrb5/v8 v8.4.4 // indirect\n\tgithub.com/jcmturner/rpc/v2 v2.0.3 // indirect\n\tgithub.com/jinzhu/inflection v1.0.0 // indirect\n\tgithub.com/jinzhu/now v1.1.5 // indirect\n\tgithub.com/josharian/intern v1.0.0 // indirect\n\tgithub.com/klauspost/compress v1.18.4 // indirect\n\tgithub.com/kr/pretty v0.3.1 // indirect\n\tgithub.com/labstack/gommon v0.3.1 // indirect\n\tgithub.com/magiconair/properties v1.8.6 // indirect\n\tgithub.com/mattn/go-colorable v0.1.12 // indirect\n\tgithub.com/mattn/go-isatty v0.0.14 // indirect\n\tgithub.com/mattn/go-pointer v0.0.1 // indirect\n\tgithub.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect\n\tgithub.com/mitchellh/copystructure v1.0.0 // indirect\n\tgithub.com/mitchellh/go-homedir v1.1.0 // indirect\n\tgithub.com/mitchellh/go-testing-interface v1.0.0 // indirect\n\tgithub.com/mitchellh/mapstructure v1.5.0 // indirect\n\tgithub.com/mitchellh/reflectwalk v1.0.0 // indirect\n\tgithub.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect\n\tgithub.com/oklog/run v1.0.0 // indirect\n\tgithub.com/pelletier/go-toml v1.9.5 // indirect\n\tgithub.com/pelletier/go-toml/v2 v2.0.5 // indirect\n\tgithub.com/pierrec/lz4 v2.5.2+incompatible // indirect\n\tgithub.com/pierrec/lz4/v4 v4.1.25 // indirect\n\tgithub.com/pmezard/go-difflib v1.0.0 // indirect\n\tgithub.com/prometheus/client_model v0.2.0 // indirect\n\tgithub.com/prometheus/common v0.32.1 // indirect\n\tgithub.com/prometheus/procfs v0.7.3 // indirect\n\tgithub.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect\n\tgithub.com/rogpeppe/go-internal v1.14.1 // indirect\n\tgithub.com/ryanuber/go-glob v1.0.0 // indirect\n\tgithub.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect\n\tgithub.com/spf13/afero v1.9.2 // indirect\n\tgithub.com/spf13/cast v1.5.0 // indirect\n\tgithub.com/spf13/jwalterweatherman v1.1.0 // indirect\n\tgithub.com/spf13/pflag v1.0.5 // indirect\n\tgithub.com/subosito/gotenv v1.4.1 // indirect\n\tgithub.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect\n\tgithub.com/tarantool/go-iproto v1.1.0 // indirect\n\tgithub.com/tarantool/go-openssl v0.0.8-0.20230307065445-720eeb389195 // indirect\n\tgithub.com/valyala/bytebufferpool v1.0.0 // indirect\n\tgithub.com/valyala/fasttemplate v1.2.1 // indirect\n\tgithub.com/vektah/gqlparser/v2 v2.5.0 // indirect\n\tgithub.com/vmihailenco/msgpack/v5 v5.4.1 // indirect\n\tgithub.com/vmihailenco/tagparser/v2 v2.0.0 // indirect\n\tgithub.com/xdg-go/pbkdf2 v1.0.0 // indirect\n\tgithub.com/xdg-go/scram v1.1.1 // indirect\n\tgithub.com/xdg-go/stringprep v1.0.3 // indirect\n\tgithub.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect\n\tgo.uber.org/atomic v1.9.0 // indirect\n\tgo.uber.org/multierr v1.8.0 // indirect\n\tgolang.org/x/sys v0.41.0 // indirect\n\tgolang.org/x/text v0.34.0 // indirect\n\tgolang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect\n\tgolang.org/x/tools v0.41.0 // indirect\n\tgoogle.golang.org/appengine v1.6.7 // indirect\n\tgoogle.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e // indirect\n\tgopkg.in/ini.v1 v1.67.0 // indirect\n\tgopkg.in/square/go-jose.v2 v2.5.1 // indirect\n\tgopkg.in/yaml.v2 v2.4.0 // indirect\n\tgopkg.in/yaml.v3 v3.0.1 // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=\ncloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=\ncloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=\ncloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=\ncloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=\ncloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=\ncloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=\ncloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=\ncloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=\ncloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=\ncloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=\ncloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=\ncloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=\ncloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=\ncloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=\ncloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=\ncloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=\ncloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=\ncloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=\ncloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=\ncloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=\ncloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=\ncloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=\ncloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=\ncloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=\ncloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=\ncloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=\ncloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=\ncloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=\ncloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=\ncloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=\ncloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=\ncloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=\ncloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=\ncloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=\ndmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=\ngithub.com/99designs/gqlgen v0.11.1 h1:QoSL8/AAJ2T3UOeQbdnBR32JcG4pO08+P/g5jdbFkUg=\ngithub.com/99designs/gqlgen v0.11.1/go.mod h1:vjFOyBZ7NwDl+GdSD4PFn7BQn5Fy7ohJwXn7Vk8zz+c=\ngithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=\ngithub.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=\ngithub.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=\ngithub.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=\ngithub.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM=\ngithub.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=\ngithub.com/IBM/sarama v1.47.0 h1:GcQFEd12+KzfPYeLgN69Fh7vLCtYRhVIx0rO4TZO318=\ngithub.com/IBM/sarama v1.47.0/go.mod h1:7gLLIU97nznOmA6TX++Qds+DRxH89P2XICY2KAQUzAY=\ngithub.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=\ngithub.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=\ngithub.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=\ngithub.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=\ngithub.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=\ngithub.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=\ngithub.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=\ngithub.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=\ngithub.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=\ngithub.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=\ngithub.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=\ngithub.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=\ngithub.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=\ngithub.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=\ngithub.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=\ngithub.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=\ngithub.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=\ngithub.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=\ngithub.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=\ngithub.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=\ngithub.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=\ngithub.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=\ngithub.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=\ngithub.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=\ngithub.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=\ngithub.com/armon/go-metrics v0.4.0 h1:yCQqn7dwca4ITXb+CbubHmedzaQYHhNhrEXLYUeEe8Q=\ngithub.com/armon/go-metrics v0.4.0/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=\ngithub.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=\ngithub.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=\ngithub.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=\ngithub.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=\ngithub.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=\ngithub.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=\ngithub.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=\ngithub.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=\ngithub.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=\ngithub.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=\ngithub.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=\ngithub.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=\ngithub.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=\ngithub.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=\ngithub.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d h1:pVrfxiGfwelyab6n21ZBkbkmbevaf+WvMIiR7sr97hw=\ngithub.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=\ngithub.com/buaazp/fasthttprouter v0.1.1 h1:4oAnN0C3xZjylvZJdP35cxfclyn4TYkW6Y+DSvS+h8Q=\ngithub.com/buaazp/fasthttprouter v0.1.1/go.mod h1:h/Ap5oRVLeItGKTVBb+heQPks+HdIUtGmI4H5WCYijM=\ngithub.com/casbin/casbin v1.9.1 h1:ucjbS5zTrmSLtH4XogqOG920Poe6QatdXtz1FEbApeM=\ngithub.com/casbin/casbin v1.9.1/go.mod h1:z8uPsfBJGUsnkagrt3G8QvjgTKFMBJ32UP8HpZllfog=\ngithub.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=\ngithub.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=\ngithub.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=\ngithub.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=\ngithub.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=\ngithub.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=\ngithub.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=\ngithub.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=\ngithub.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=\ngithub.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=\ngithub.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=\ngithub.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=\ngithub.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=\ngithub.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=\ngithub.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=\ngithub.com/corpix/uarand v0.0.0-20170723150923-031be390f409 h1:9A+mfQmwzZ6KwUXPc8nHxFtKgn9VIvO3gXAOspIcE3s=\ngithub.com/corpix/uarand v0.0.0-20170723150923-031be390f409/go.mod h1:JSm890tOkDN+M1jqN8pUGDKnzJrsVbJwSMHBY4zwz7M=\ngithub.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=\ngithub.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=\ngithub.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=\ngithub.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=\ngithub.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c h1:TUuUh0Xgj97tLMNtWtNvI9mIV6isjEb9lBMNv+77IGM=\ngithub.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=\ngithub.com/eapache/go-resiliency v1.7.0 h1:n3NRTnBn5N0Cbi/IeOHuQn9s2UwVUH7Ga0ZWcP+9JTA=\ngithub.com/eapache/go-resiliency v1.7.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho=\ngithub.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=\ngithub.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=\ngithub.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=\ngithub.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=\ngithub.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=\ngithub.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=\ngithub.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=\ngithub.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=\ngithub.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=\ngithub.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=\ngithub.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=\ngithub.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=\ngithub.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=\ngithub.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=\ngithub.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=\ngithub.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=\ngithub.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=\ngithub.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=\ngithub.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=\ngithub.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=\ngithub.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=\ngithub.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=\ngithub.com/gen1us2k/go-translit v0.0.0-20160120121136-46f1a0be552c h1:J8HJ/lfhIBjmTPB0dZVRKciFaO60DJ+3n3ZXYU73CaQ=\ngithub.com/gen1us2k/go-translit v0.0.0-20160120121136-46f1a0be552c/go.mod h1:DCO0xCUjZ8eznOd/fx0E75c06B1hCrFHMTqXAQoYffk=\ngithub.com/getsentry/sentry-go v0.13.0 h1:20dgTiUSfxRB/EhMPtxcL9ZEbM1ZdR+W/7f7NWD+xWo=\ngithub.com/getsentry/sentry-go v0.13.0/go.mod h1:EOsfu5ZdvKPfeHYV6pTVQnsjfp30+XA7//UooKNumH0=\ngithub.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=\ngithub.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=\ngithub.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=\ngithub.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=\ngithub.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=\ngithub.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=\ngithub.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=\ngithub.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=\ngithub.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=\ngithub.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=\ngithub.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=\ngithub.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=\ngithub.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=\ngithub.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=\ngithub.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=\ngithub.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=\ngithub.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=\ngithub.com/go-openapi/spec v0.20.6 h1:ich1RQ3WDbfoeTqTAb+5EIxNmpKVJZWBNah9RAT0jIQ=\ngithub.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=\ngithub.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=\ngithub.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=\ngithub.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=\ngithub.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=\ngithub.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=\ngithub.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=\ngithub.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=\ngithub.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=\ngithub.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=\ngithub.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=\ngithub.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=\ngithub.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=\ngithub.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=\ngithub.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=\ngithub.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=\ngithub.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=\ngithub.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=\ngithub.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=\ngithub.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=\ngithub.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=\ngithub.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=\ngithub.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=\ngithub.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=\ngithub.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=\ngithub.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=\ngithub.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=\ngithub.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=\ngithub.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=\ngithub.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=\ngithub.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=\ngithub.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=\ngithub.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=\ngithub.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=\ngithub.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=\ngithub.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=\ngithub.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=\ngithub.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=\ngithub.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=\ngithub.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=\ngithub.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=\ngithub.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=\ngithub.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=\ngithub.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=\ngithub.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=\ngithub.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=\ngithub.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=\ngithub.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=\ngithub.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=\ngithub.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=\ngithub.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=\ngithub.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=\ngithub.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=\ngithub.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=\ngithub.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=\ngithub.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=\ngithub.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=\ngithub.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=\ngithub.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=\ngithub.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=\ngithub.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=\ngithub.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=\ngithub.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=\ngithub.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=\ngithub.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=\ngithub.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=\ngithub.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=\ngithub.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=\ngithub.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=\ngithub.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=\ngithub.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=\ngithub.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=\ngithub.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=\ngithub.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=\ngithub.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=\ngithub.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=\ngithub.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=\ngithub.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=\ngithub.com/graphql-go/graphql v0.8.0 h1:JHRQMeQjofwqVvGwYnr8JnPTY0AxgVy1HpHSGPLdH0I=\ngithub.com/graphql-go/graphql v0.8.0/go.mod h1:nKiHzRM0qopJEwCITUuIsxk9PlVlwIiiI8pnJEhordQ=\ngithub.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw=\ngithub.com/hashicorp/consul/api v1.15.3 h1:WYONYL2rxTXtlekAqblR2SCdJsizMDIj/uXb5wNy9zU=\ngithub.com/hashicorp/consul/api v1.15.3/go.mod h1:/g/qgcoBcEXALCNZgRRisyTW0nY86++L0KbeAMXYCeY=\ngithub.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4=\ngithub.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw=\ngithub.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=\ngithub.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=\ngithub.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=\ngithub.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=\ngithub.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=\ngithub.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=\ngithub.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=\ngithub.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=\ngithub.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=\ngithub.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=\ngithub.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=\ngithub.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=\ngithub.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=\ngithub.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=\ngithub.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=\ngithub.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI=\ngithub.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=\ngithub.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=\ngithub.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=\ngithub.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=\ngithub.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=\ngithub.com/hashicorp/go-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo=\ngithub.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=\ngithub.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=\ngithub.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=\ngithub.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=\ngithub.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=\ngithub.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=\ngithub.com/hashicorp/go-secure-stdlib/mlock v0.1.1 h1:cCRo8gK7oq6A2L6LICkUZ+/a5rLiRXFMf1Qd4xSwxTc=\ngithub.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I=\ngithub.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ=\ngithub.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8=\ngithub.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U=\ngithub.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=\ngithub.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=\ngithub.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=\ngithub.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=\ngithub.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=\ngithub.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=\ngithub.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=\ngithub.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=\ngithub.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=\ngithub.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=\ngithub.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=\ngithub.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=\ngithub.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=\ngithub.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=\ngithub.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=\ngithub.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=\ngithub.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=\ngithub.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=\ngithub.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=\ngithub.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=\ngithub.com/hashicorp/memberlist v0.3.1 h1:MXgUXLqva1QvpVEDQW1IQLG0wivQAtmFlHRQ+1vWZfM=\ngithub.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=\ngithub.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=\ngithub.com/hashicorp/serf v0.9.8 h1:JGklO/2Drf1QGa312EieQN3zhxQ+aJg6pG+aC3MFaVo=\ngithub.com/hashicorp/serf v0.9.8/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=\ngithub.com/hashicorp/vault/api v1.8.2 h1:C7OL9YtOtwQbTKI9ogB0A1wffRbCN+rH/LLCHO3d8HM=\ngithub.com/hashicorp/vault/api v1.8.2/go.mod h1:ML8aYzBIhY5m1MD1B2Q0JV89cC85YVH4t5kBaZiyVaE=\ngithub.com/hashicorp/vault/sdk v0.6.0 h1:6Z+In5DXHiUfZvIZdMx7e2loL1PPyDjA4bVh9ZTIAhs=\ngithub.com/hashicorp/vault/sdk v0.6.0/go.mod h1:+DRpzoXIdMvKc88R4qxr+edwy/RvH5QK8itmxLiDHLc=\ngithub.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=\ngithub.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=\ngithub.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=\ngithub.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=\ngithub.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=\ngithub.com/icrowley/fake v0.0.0-20220625154756-3c7517006344 h1:gvlL0h+DFa2eX4rLg/lbtBV4z81p1qHGcvPIpWtlXn0=\ngithub.com/icrowley/fake v0.0.0-20220625154756-3c7517006344/go.mod h1:dQ6TM/OGAe+cMws81eTe4Btv1dKxfPZ2CX+YaAFAPN4=\ngithub.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc=\ngithub.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=\ngithub.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=\ngithub.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=\ngithub.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=\ngithub.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=\ngithub.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o=\ngithub.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=\ngithub.com/jackc/pgx/v5 v5.9.1 h1:uwrxJXBnx76nyISkhr33kQLlUqjv7et7b9FjCen/tdc=\ngithub.com/jackc/pgx/v5 v5.9.1/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=\ngithub.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=\ngithub.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=\ngithub.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=\ngithub.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=\ngithub.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=\ngithub.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=\ngithub.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=\ngithub.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=\ngithub.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=\ngithub.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=\ngithub.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=\ngithub.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=\ngithub.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=\ngithub.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=\ngithub.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=\ngithub.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=\ngithub.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=\ngithub.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=\ngithub.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=\ngithub.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=\ngithub.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=\ngithub.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=\ngithub.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=\ngithub.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=\ngithub.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=\ngithub.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=\ngithub.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=\ngithub.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=\ngithub.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=\ngithub.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=\ngithub.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=\ngithub.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=\ngithub.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=\ngithub.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=\ngithub.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=\ngithub.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=\ngithub.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=\ngithub.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=\ngithub.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=\ngithub.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=\ngithub.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=\ngithub.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=\ngithub.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=\ngithub.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=\ngithub.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=\ngithub.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY=\ngithub.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=\ngithub.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=\ngithub.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=\ngithub.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=\ngithub.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=\ngithub.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=\ngithub.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=\ngithub.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=\ngithub.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=\ngithub.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=\ngithub.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=\ngithub.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=\ngithub.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=\ngithub.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=\ngithub.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=\ngithub.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=\ngithub.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=\ngithub.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=\ngithub.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=\ngithub.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=\ngithub.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=\ngithub.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=\ngithub.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=\ngithub.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=\ngithub.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=\ngithub.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=\ngithub.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=\ngithub.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=\ngithub.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=\ngithub.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0=\ngithub.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=\ngithub.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=\ngithub.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=\ngithub.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=\ngithub.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=\ngithub.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=\ngithub.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=\ngithub.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=\ngithub.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=\ngithub.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY=\ngithub.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=\ngithub.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=\ngithub.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=\ngithub.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=\ngithub.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=\ngithub.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=\ngithub.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=\ngithub.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=\ngithub.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=\ngithub.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=\ngithub.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=\ngithub.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=\ngithub.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=\ngithub.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=\ngithub.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=\ngithub.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=\ngithub.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=\ngithub.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=\ngithub.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=\ngithub.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=\ngithub.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=\ngithub.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=\ngithub.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=\ngithub.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=\ngithub.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=\ngithub.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=\ngithub.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=\ngithub.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e h1:4cPxUYdgaGzZIT5/j0IfqOrrXmq6bG8AwvwisMXpdrg=\ngithub.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e/go.mod h1:DYR5Eij8rJl8h7gblRrOZ8g0kW1umSpKqYIBTgeDtLo=\ngithub.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=\ngithub.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=\ngithub.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=\ngithub.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=\ngithub.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=\ngithub.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=\ngithub.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=\ngithub.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=\ngithub.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=\ngithub.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=\ngithub.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=\ngithub.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=\ngithub.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=\ngithub.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=\ngithub.com/pierrec/lz4/v4 v4.1.25 h1:kocOqRffaIbU5djlIBr7Wh+cx82C0vtFb0fOurZHqD0=\ngithub.com/pierrec/lz4/v4 v4.1.25/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4=\ngithub.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=\ngithub.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=\ngithub.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=\ngithub.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=\ngithub.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=\ngithub.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=\ngithub.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=\ngithub.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=\ngithub.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=\ngithub.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=\ngithub.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=\ngithub.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=\ngithub.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=\ngithub.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=\ngithub.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=\ngithub.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=\ngithub.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=\ngithub.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=\ngithub.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=\ngithub.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=\ngithub.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=\ngithub.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=\ngithub.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=\ngithub.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=\ngithub.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=\ngithub.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=\ngithub.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=\ngithub.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg=\ngithub.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=\ngithub.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=\ngithub.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=\ngithub.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=\ngithub.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=\ngithub.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=\ngithub.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=\ngithub.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=\ngithub.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=\ngithub.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=\ngithub.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=\ngithub.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=\ngithub.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=\ngithub.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=\ngithub.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=\ngithub.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=\ngithub.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=\ngithub.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=\ngithub.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=\ngithub.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=\ngithub.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=\ngithub.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=\ngithub.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=\ngithub.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=\ngithub.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=\ngithub.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=\ngithub.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=\ngithub.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=\ngithub.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=\ngithub.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=\ngithub.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=\ngithub.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=\ngithub.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=\ngithub.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=\ngithub.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=\ngithub.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo=\ngithub.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=\ngithub.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=\ngithub.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=\ngithub.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=\ngithub.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=\ngithub.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=\ngithub.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=\ngithub.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=\ngithub.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe h1:K8pHPVoTgxFJt1lXuIzzOX7zZhZFldJQK/CgKx9BFIc=\ngithub.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w=\ngithub.com/swaggo/http-swagger v1.3.3 h1:Hu5Z0L9ssyBLofaama21iYaF2VbWyA8jdohaaCGpHsc=\ngithub.com/swaggo/http-swagger v1.3.3/go.mod h1:sE+4PjD89IxMPm77FnkDz0sdO+p5lbXzrVWT6OTVVGo=\ngithub.com/swaggo/swag v1.8.5 h1:7NgtfXsXE+jrcOwRyiftGKW7Ppydj7tZiVenuRf1fE4=\ngithub.com/swaggo/swag v1.8.5/go.mod h1:jMLeXOOmYyjk8PvHTsXBdrubsNd9gUJTTCzL5iBnseg=\ngithub.com/tarantool/go-iproto v1.1.0 h1:HULVOIHsiehI+FnHfM7wMDntuzUddO09DKqu2WnFQ5A=\ngithub.com/tarantool/go-iproto v1.1.0/go.mod h1:LNCtdyZxojUed8SbOiYHoc3v9NvaZTB7p96hUySMlIo=\ngithub.com/tarantool/go-openssl v0.0.8-0.20230307065445-720eeb389195 h1:/AN3eUPsTlvF6W+Ng/8ZjnSU6o7L0H4Wb9GMks6RkzU=\ngithub.com/tarantool/go-openssl v0.0.8-0.20230307065445-720eeb389195/go.mod h1:M7H4xYSbzqpW/ZRBMyH0eyqQBsnhAMfsYk5mv0yid7A=\ngithub.com/tarantool/go-tarantool v1.12.2 h1:u4g+gTOHNxbUDJv0EIUFkRurU/lTQSzWrz8o7bHVAqI=\ngithub.com/tarantool/go-tarantool v1.12.2/go.mod h1:QRiXv0jnxwgxHtr9ZmifSr/eRba76gTUBgp69pDMX1U=\ngithub.com/tarantool/go-tarantool/v2 v2.4.2 h1:rkzYtFhLJLA9RDIhjzN93MJBN5PBxHW4+soq+RB90gE=\ngithub.com/tarantool/go-tarantool/v2 v2.4.2/go.mod h1:MTbhdjFc3Jl63Lgi/UJr5D+QbT+QegqOzsNJGmaw7VM=\ngithub.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=\ngithub.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=\ngithub.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=\ngithub.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=\ngithub.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=\ngithub.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=\ngithub.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=\ngithub.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=\ngithub.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=\ngithub.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=\ngithub.com/valyala/fasthttp v1.45.0 h1:zPkkzpIn8tdHZUrVa6PzYd0i5verqiPSkgTd3bSUcpA=\ngithub.com/valyala/fasthttp v1.45.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=\ngithub.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=\ngithub.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=\ngithub.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=\ngithub.com/vektah/gqlparser v1.3.1 h1:8b0IcD3qZKWJQHSzynbDlrtP3IxVydZ2DZepCGofqfU=\ngithub.com/vektah/gqlparser v1.3.1/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74=\ngithub.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=\ngithub.com/vektah/gqlparser/v2 v2.5.0 h1:GwEwy7AJsqPWrey0bHnn+3JLaHLZVT66wY/+O+Tf9SU=\ngithub.com/vektah/gqlparser/v2 v2.5.0/go.mod h1:mPgqFBu/woKTVYWyNk8cO3kh4S/f4aRFZrvOnp3hmCs=\ngithub.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=\ngithub.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=\ngithub.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=\ngithub.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=\ngithub.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=\ngithub.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=\ngithub.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=\ngithub.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=\ngithub.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=\ngithub.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=\ngithub.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=\ngithub.com/ybbus/jsonrpc/v2 v2.1.6 h1:++pboiaaD6TZ9FJ1JOBBRB/tPtR1njYzqz1iSZGv+3Y=\ngithub.com/ybbus/jsonrpc/v2 v2.1.6/go.mod h1:rIuG1+ORoiqocf9xs/v+ecaAVeo3zcZHQgInyKFMeg0=\ngithub.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=\ngithub.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=\ngithub.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=\ngithub.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=\ngo.mongodb.org/mongo-driver v1.11.2 h1:+1v2rDQUWNcGW7/7E0Jvdz51V38XXxJfhzbV17aNHCw=\ngo.mongodb.org/mongo-driver v1.11.2/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=\ngo.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=\ngo.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=\ngo.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=\ngo.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=\ngo.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=\ngo.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=\ngo.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=\ngo.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=\ngo.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=\ngo.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=\ngo.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=\ngo.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=\ngo.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY=\ngo.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY=\ngolang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=\ngolang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=\ngolang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=\ngolang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=\ngolang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=\ngolang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=\ngolang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=\ngolang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=\ngolang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=\ngolang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=\ngolang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=\ngolang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=\ngolang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=\ngolang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=\ngolang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=\ngolang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=\ngolang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\ngolang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=\ngolang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\ngolang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=\ngolang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=\ngolang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=\ngolang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=\ngolang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=\ngolang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=\ngolang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=\ngolang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=\ngolang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=\ngolang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=\ngolang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=\ngolang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=\ngolang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=\ngolang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=\ngolang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=\ngolang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=\ngolang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=\ngolang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=\ngolang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=\ngolang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=\ngolang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=\ngolang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=\ngolang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=\ngolang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=\ngolang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=\ngolang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=\ngolang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=\ngolang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=\ngolang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=\ngolang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=\ngolang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=\ngolang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=\ngolang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=\ngolang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=\ngolang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=\ngolang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=\ngolang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=\ngolang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=\ngolang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=\ngolang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=\ngolang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=\ngolang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=\ngolang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=\ngolang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=\ngolang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=\ngolang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=\ngonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=\ngonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=\ngonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=\ngoogle.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=\ngoogle.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=\ngoogle.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=\ngoogle.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=\ngoogle.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=\ngoogle.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=\ngoogle.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=\ngoogle.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=\ngoogle.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=\ngoogle.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=\ngoogle.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=\ngoogle.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=\ngoogle.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=\ngoogle.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=\ngoogle.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=\ngoogle.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=\ngoogle.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=\ngoogle.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=\ngoogle.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=\ngoogle.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=\ngoogle.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=\ngoogle.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=\ngoogle.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=\ngoogle.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=\ngoogle.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=\ngoogle.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=\ngoogle.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=\ngoogle.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=\ngoogle.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=\ngoogle.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=\ngoogle.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e h1:S9GbmC1iCgvbLyAokVCwiO6tVIrU9Y7c5oMx1V/ki/Y=\ngoogle.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=\ngoogle.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=\ngoogle.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=\ngoogle.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=\ngoogle.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=\ngoogle.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=\ngoogle.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=\ngoogle.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=\ngoogle.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=\ngoogle.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=\ngoogle.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=\ngoogle.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=\ngoogle.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=\ngoogle.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=\ngoogle.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=\ngoogle.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=\ngoogle.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=\ngoogle.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=\ngoogle.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=\ngoogle.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=\ngoogle.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=\ngoogle.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=\ngoogle.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=\ngoogle.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=\ngoogle.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=\ngoogle.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=\ngoogle.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=\ngoogle.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=\ngopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=\ngopkg.in/alexcesaro/statsd.v2 v2.0.0 h1:FXkZSCZIH17vLCO5sO2UucTHsH9pc+17F6pl3JVCwMc=\ngopkg.in/alexcesaro/statsd.v2 v2.0.0/go.mod h1:i0ubccKGzBVNBpdGV5MocxyA/XlLUJzA7SLonnE4drU=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=\ngopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=\ngopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=\ngopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=\ngopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=\ngopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=\ngopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=\ngopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=\ngopkg.in/vmihailenco/msgpack.v2 v2.9.2 h1:gjPqo9orRVlSAH/065qw3MsFCDpH7fa1KpiizXyllY4=\ngopkg.in/vmihailenco/msgpack.v2 v2.9.2/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8=\ngopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=\ngopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngorm.io/driver/mysql v1.3.6 h1:BhX1Y/RyALb+T9bZ3t07wLnPZBukt+IRkMn8UZSNbGM=\ngorm.io/driver/mysql v1.3.6/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=\ngorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE=\ngorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=\nhonnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=\nhonnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=\nhonnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=\nrsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=\nrsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=\nrsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=\nrsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=\nsourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=\nsourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=\n"
  }
]