mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Update GQLGen and break up the schema.graphql file
This commit is contained in:
4
go.mod
4
go.mod
@@ -1,7 +1,7 @@
|
|||||||
module github.com/stashapp/stash
|
module github.com/stashapp/stash
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/99designs/gqlgen v0.4.5-0.20190127090136-055fb4bc9a6a
|
github.com/99designs/gqlgen v0.8.2
|
||||||
github.com/PuerkitoBio/goquery v1.5.0
|
github.com/PuerkitoBio/goquery v1.5.0
|
||||||
github.com/bmatcuk/doublestar v1.1.1
|
github.com/bmatcuk/doublestar v1.1.1
|
||||||
github.com/disintegration/imaging v1.6.0
|
github.com/disintegration/imaging v1.6.0
|
||||||
@@ -17,6 +17,6 @@ require (
|
|||||||
github.com/sirupsen/logrus v1.3.0
|
github.com/sirupsen/logrus v1.3.0
|
||||||
github.com/spf13/afero v1.2.0 // indirect
|
github.com/spf13/afero v1.2.0 // indirect
|
||||||
github.com/spf13/viper v1.3.2
|
github.com/spf13/viper v1.3.2
|
||||||
github.com/vektah/gqlparser v1.1.0
|
github.com/vektah/gqlparser v1.1.2
|
||||||
golang.org/x/image v0.0.0-20190118043309-183bebdce1b2 // indirect
|
golang.org/x/image v0.0.0-20190118043309-183bebdce1b2 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -6,6 +6,8 @@ git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGy
|
|||||||
git.apache.org/thrift.git v0.0.0-20180924222215-a9235805469b/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
git.apache.org/thrift.git v0.0.0-20180924222215-a9235805469b/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||||
github.com/99designs/gqlgen v0.4.5-0.20190127090136-055fb4bc9a6a h1:oTsAt8YXjEk1fo7uZR7gya1jrH48oPulx5oF6zWTHRw=
|
github.com/99designs/gqlgen v0.4.5-0.20190127090136-055fb4bc9a6a h1:oTsAt8YXjEk1fo7uZR7gya1jrH48oPulx5oF6zWTHRw=
|
||||||
github.com/99designs/gqlgen v0.4.5-0.20190127090136-055fb4bc9a6a/go.mod h1:st7qHA6ssU3uRZkmv+wzrzgX4srvIqEIdE5iuRW8GhE=
|
github.com/99designs/gqlgen v0.4.5-0.20190127090136-055fb4bc9a6a/go.mod h1:st7qHA6ssU3uRZkmv+wzrzgX4srvIqEIdE5iuRW8GhE=
|
||||||
|
github.com/99designs/gqlgen v0.8.2 h1:xOkDPWn/MZjkQ32pu6Axx15mNah0NAq9WalFqT+RavA=
|
||||||
|
github.com/99designs/gqlgen v0.8.2/go.mod h1:aLyJw9xUgdJxZ8EqNQxo2pGFhXXJ/hq8t7J4yn8TgI4=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
@@ -439,6 +441,8 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb
|
|||||||
github.com/vektah/dataloaden v0.2.0/go.mod h1:vxM6NuRlgiR0M6wbVTJeKp9vQIs81ZMfCYO+4yq/jbE=
|
github.com/vektah/dataloaden v0.2.0/go.mod h1:vxM6NuRlgiR0M6wbVTJeKp9vQIs81ZMfCYO+4yq/jbE=
|
||||||
github.com/vektah/gqlparser v1.1.0 h1:3668p2gUlO+PiS81x957Rpr3/FPRWG6cxgCXAvTS1hw=
|
github.com/vektah/gqlparser v1.1.0 h1:3668p2gUlO+PiS81x957Rpr3/FPRWG6cxgCXAvTS1hw=
|
||||||
github.com/vektah/gqlparser v1.1.0/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
github.com/vektah/gqlparser v1.1.0/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||||
|
github.com/vektah/gqlparser v1.1.2 h1:ZsyLGn7/7jDNI+y4SEhI4yAxRChlv15pUHMjijT+e68=
|
||||||
|
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||||
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
# .gqlgen.yml example
|
# Refer to https://gqlgen.com/config/ for detailed .gqlgen.yml documentation.
|
||||||
#
|
|
||||||
# Refer to https://gqlgen.com/config/
|
|
||||||
# for detailed .gqlgen.yml documentation.
|
|
||||||
|
|
||||||
schema:
|
schema:
|
||||||
- schema/schema.graphql
|
- "graphql/schema/types/*.graphql"
|
||||||
|
- "graphql/schema/*.graphql"
|
||||||
exec:
|
exec:
|
||||||
filename: pkg/models/generated_exec.go
|
filename: pkg/models/generated_exec.go
|
||||||
model:
|
model:
|
||||||
|
|||||||
103
graphql/schema/schema.graphql
Normal file
103
graphql/schema/schema.graphql
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
"""The query root for this schema"""
|
||||||
|
type Query {
|
||||||
|
"""Find a scene by ID or Checksum"""
|
||||||
|
findScene(id: ID, checksum: String): Scene
|
||||||
|
"""A function which queries Scene objects"""
|
||||||
|
findScenes(scene_filter: SceneFilterType, scene_ids: [Int!], filter: FindFilterType): FindScenesResultType!
|
||||||
|
|
||||||
|
"""A function which queries SceneMarker objects"""
|
||||||
|
findSceneMarkers(scene_marker_filter: SceneMarkerFilterType filter: FindFilterType): FindSceneMarkersResultType!
|
||||||
|
|
||||||
|
"""Find a performer by ID"""
|
||||||
|
findPerformer(id: ID!): Performer
|
||||||
|
"""A function which queries Performer objects"""
|
||||||
|
findPerformers(performer_filter: PerformerFilterType, filter: FindFilterType): FindPerformersResultType!
|
||||||
|
|
||||||
|
"""Find a studio by ID"""
|
||||||
|
findStudio(id: ID!): Studio
|
||||||
|
"""A function which queries Studio objects"""
|
||||||
|
findStudios(filter: FindFilterType): FindStudiosResultType!
|
||||||
|
|
||||||
|
findGallery(id: ID!): Gallery
|
||||||
|
findGalleries(filter: FindFilterType): FindGalleriesResultType!
|
||||||
|
|
||||||
|
findTag(id: ID!): Tag
|
||||||
|
|
||||||
|
"""Retrieve random scene markers for the wall"""
|
||||||
|
markerWall(q: String): [SceneMarker!]!
|
||||||
|
"""Retrieve random scenes for the wall"""
|
||||||
|
sceneWall(q: String): [Scene!]!
|
||||||
|
|
||||||
|
"""Get marker strings"""
|
||||||
|
markerStrings(q: String, sort: String): [MarkerStringsResultType]!
|
||||||
|
"""Get the list of valid galleries for a given scene ID"""
|
||||||
|
validGalleriesForScene(scene_id: ID): [Gallery!]!
|
||||||
|
"""Get stats"""
|
||||||
|
stats: StatsResultType!
|
||||||
|
"""Organize scene markers by tag for a given scene ID"""
|
||||||
|
sceneMarkerTags(scene_id: ID!): [SceneMarkerTag!]!
|
||||||
|
|
||||||
|
# Scrapers
|
||||||
|
|
||||||
|
"""Scrape a performer using Freeones"""
|
||||||
|
scrapeFreeones(performer_name: String!): ScrapedPerformer
|
||||||
|
"""Scrape a list of performers from a query"""
|
||||||
|
scrapeFreeonesPerformerList(query: String!): [String!]!
|
||||||
|
|
||||||
|
# Config
|
||||||
|
"""Returns the current, complete configuration"""
|
||||||
|
configuration: ConfigResult!
|
||||||
|
"""Returns an array of paths for the given path"""
|
||||||
|
directories(path: String): [String!]!
|
||||||
|
|
||||||
|
# Metadata
|
||||||
|
|
||||||
|
"""Start an import. Returns the job ID"""
|
||||||
|
metadataImport: String!
|
||||||
|
"""Start an export. Returns the job ID"""
|
||||||
|
metadataExport: String!
|
||||||
|
"""Start a scan. Returns the job ID"""
|
||||||
|
metadataScan: String!
|
||||||
|
"""Start generating content. Returns the job ID"""
|
||||||
|
metadataGenerate(input: GenerateMetadataInput!): String!
|
||||||
|
"""Clean metadata. Returns the job ID"""
|
||||||
|
metadataClean: String!
|
||||||
|
|
||||||
|
# Get everything
|
||||||
|
|
||||||
|
allPerformers: [Performer!]!
|
||||||
|
allStudios: [Studio!]!
|
||||||
|
allTags: [Tag!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mutation {
|
||||||
|
sceneUpdate(input: SceneUpdateInput!): Scene
|
||||||
|
|
||||||
|
sceneMarkerCreate(input: SceneMarkerCreateInput!): SceneMarker
|
||||||
|
sceneMarkerUpdate(input: SceneMarkerUpdateInput!): SceneMarker
|
||||||
|
sceneMarkerDestroy(id: ID!): Boolean!
|
||||||
|
|
||||||
|
performerCreate(input: PerformerCreateInput!): Performer
|
||||||
|
performerUpdate(input: PerformerUpdateInput!): Performer
|
||||||
|
|
||||||
|
studioCreate(input: StudioCreateInput!): Studio
|
||||||
|
studioUpdate(input: StudioUpdateInput!): Studio
|
||||||
|
|
||||||
|
tagCreate(input: TagCreateInput!): Tag
|
||||||
|
tagUpdate(input: TagUpdateInput!): Tag
|
||||||
|
tagDestroy(input: TagDestroyInput!): Boolean!
|
||||||
|
|
||||||
|
"""Change general configuration options"""
|
||||||
|
configureGeneral(input: ConfigGeneralInput!): ConfigGeneralResult!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Subscription {
|
||||||
|
"""Update from the metadata manager"""
|
||||||
|
metadataUpdate: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
schema {
|
||||||
|
query: Query
|
||||||
|
mutation: Mutation
|
||||||
|
subscription: Subscription
|
||||||
|
}
|
||||||
22
graphql/schema/types/config.graphql
Normal file
22
graphql/schema/types/config.graphql
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
input ConfigGeneralInput {
|
||||||
|
"""Array of file paths to content"""
|
||||||
|
stashes: [String!]
|
||||||
|
"""Path to the SQLite database"""
|
||||||
|
databasePath: String
|
||||||
|
"""Path to generated files"""
|
||||||
|
generatedPath: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConfigGeneralResult {
|
||||||
|
"""Array of file paths to content"""
|
||||||
|
stashes: [String!]!
|
||||||
|
"""Path to the SQLite database"""
|
||||||
|
databasePath: String!
|
||||||
|
"""Path to generated files"""
|
||||||
|
generatedPath: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""All configuration settings"""
|
||||||
|
type ConfigResult {
|
||||||
|
general: ConfigGeneralResult!
|
||||||
|
}
|
||||||
75
graphql/schema/types/filters.graphql
Normal file
75
graphql/schema/types/filters.graphql
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
enum SortDirectionEnum {
|
||||||
|
ASC
|
||||||
|
DESC
|
||||||
|
}
|
||||||
|
|
||||||
|
input FindFilterType {
|
||||||
|
q: String
|
||||||
|
page: Int
|
||||||
|
per_page: Int
|
||||||
|
sort: String
|
||||||
|
direction: SortDirectionEnum
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ResolutionEnum {
|
||||||
|
"240p", LOW
|
||||||
|
"480p", STANDARD
|
||||||
|
"720p", STANDARD_HD
|
||||||
|
"1080p", FULL_HD
|
||||||
|
"4k", FOUR_K
|
||||||
|
}
|
||||||
|
|
||||||
|
input PerformerFilterType {
|
||||||
|
"""Filter by favorite"""
|
||||||
|
filter_favorites: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
input SceneMarkerFilterType {
|
||||||
|
"""Filter to only include scene markers with this tag"""
|
||||||
|
tag_id: ID
|
||||||
|
"""Filter to only include scene markers with these tags"""
|
||||||
|
tags: [ID!]
|
||||||
|
"""Filter to only include scene markers attached to a scene with these tags"""
|
||||||
|
scene_tags: [ID!]
|
||||||
|
"""Filter to only include scene markers with these performers"""
|
||||||
|
performers: [ID!]
|
||||||
|
}
|
||||||
|
|
||||||
|
input SceneFilterType {
|
||||||
|
"""Filter by rating"""
|
||||||
|
rating: IntCriterionInput
|
||||||
|
"""Filter by resolution"""
|
||||||
|
resolution: ResolutionEnum
|
||||||
|
"""Filter to only include scenes which have markers. `true` or `false`"""
|
||||||
|
has_markers: String
|
||||||
|
"""Filter to only include scenes missing this property"""
|
||||||
|
is_missing: String
|
||||||
|
"""Filter to only include scenes with this studio"""
|
||||||
|
studio_id: ID
|
||||||
|
"""Filter to only include scenes with these tags"""
|
||||||
|
tags: [ID!]
|
||||||
|
"""Filter to only include scenes with this performer"""
|
||||||
|
performer_id: ID
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CriterionModifier {
|
||||||
|
"""="""
|
||||||
|
EQUALS,
|
||||||
|
"""!="""
|
||||||
|
NOT_EQUALS,
|
||||||
|
""">"""
|
||||||
|
GREATER_THAN,
|
||||||
|
"""<"""
|
||||||
|
LESS_THAN,
|
||||||
|
"""IS NULL"""
|
||||||
|
IS_NULL,
|
||||||
|
"""IS NOT NULL"""
|
||||||
|
NOT_NULL,
|
||||||
|
INCLUDES,
|
||||||
|
EXCLUDES,
|
||||||
|
}
|
||||||
|
|
||||||
|
input IntCriterionInput {
|
||||||
|
value: Int!
|
||||||
|
modifier: CriterionModifier!
|
||||||
|
}
|
||||||
21
graphql/schema/types/gallery.graphql
Normal file
21
graphql/schema/types/gallery.graphql
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
"""Gallery type"""
|
||||||
|
type Gallery {
|
||||||
|
id: ID!
|
||||||
|
checksum: String!
|
||||||
|
path: String!
|
||||||
|
title: String
|
||||||
|
|
||||||
|
"""The files in the gallery"""
|
||||||
|
files: [GalleryFilesType!]! # Resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
type GalleryFilesType {
|
||||||
|
index: Int!
|
||||||
|
name: String
|
||||||
|
path: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type FindGalleriesResultType {
|
||||||
|
count: Int!
|
||||||
|
galleries: [Gallery!]!
|
||||||
|
}
|
||||||
6
graphql/schema/types/metadata.graphql
Normal file
6
graphql/schema/types/metadata.graphql
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
input GenerateMetadataInput {
|
||||||
|
sprites: Boolean!
|
||||||
|
previews: Boolean!
|
||||||
|
markers: Boolean!
|
||||||
|
transcodes: Boolean!
|
||||||
|
}
|
||||||
72
graphql/schema/types/performer.graphql
Normal file
72
graphql/schema/types/performer.graphql
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
type Performer {
|
||||||
|
id: ID!
|
||||||
|
checksum: String!
|
||||||
|
name: String
|
||||||
|
url: String
|
||||||
|
twitter: String
|
||||||
|
instagram: String
|
||||||
|
birthdate: String
|
||||||
|
ethnicity: String
|
||||||
|
country: String
|
||||||
|
eye_color: String
|
||||||
|
height: String
|
||||||
|
measurements: String
|
||||||
|
fake_tits: String
|
||||||
|
career_length: String
|
||||||
|
tattoos: String
|
||||||
|
piercings: String
|
||||||
|
aliases: String
|
||||||
|
favorite: Boolean!
|
||||||
|
|
||||||
|
image_path: String # Resolver
|
||||||
|
scene_count: Int # Resolver
|
||||||
|
scenes: [Scene!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
input PerformerCreateInput {
|
||||||
|
name: String
|
||||||
|
url: String
|
||||||
|
birthdate: String
|
||||||
|
ethnicity: String
|
||||||
|
country: String
|
||||||
|
eye_color: String
|
||||||
|
height: String
|
||||||
|
measurements: String
|
||||||
|
fake_tits: String
|
||||||
|
career_length: String
|
||||||
|
tattoos: String
|
||||||
|
piercings: String
|
||||||
|
aliases: String
|
||||||
|
twitter: String
|
||||||
|
instagram: String
|
||||||
|
favorite: Boolean
|
||||||
|
"""This should be base64 encoded"""
|
||||||
|
image: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
input PerformerUpdateInput {
|
||||||
|
id: ID!
|
||||||
|
name: String
|
||||||
|
url: String
|
||||||
|
birthdate: String
|
||||||
|
ethnicity: String
|
||||||
|
country: String
|
||||||
|
eye_color: String
|
||||||
|
height: String
|
||||||
|
measurements: String
|
||||||
|
fake_tits: String
|
||||||
|
career_length: String
|
||||||
|
tattoos: String
|
||||||
|
piercings: String
|
||||||
|
aliases: String
|
||||||
|
twitter: String
|
||||||
|
instagram: String
|
||||||
|
favorite: Boolean
|
||||||
|
"""This should be base64 encoded"""
|
||||||
|
image: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type FindPerformersResultType {
|
||||||
|
count: Int!
|
||||||
|
performers: [Performer!]!
|
||||||
|
}
|
||||||
4
graphql/schema/types/scene-marker-tag.graphql
Normal file
4
graphql/schema/types/scene-marker-tag.graphql
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
type SceneMarkerTag {
|
||||||
|
tag: Tag!
|
||||||
|
scene_markers: [SceneMarker!]!
|
||||||
|
}
|
||||||
41
graphql/schema/types/scene-marker.graphql
Normal file
41
graphql/schema/types/scene-marker.graphql
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
type SceneMarker {
|
||||||
|
id: ID!
|
||||||
|
scene: Scene!
|
||||||
|
title: String!
|
||||||
|
seconds: Float!
|
||||||
|
primary_tag: Tag!
|
||||||
|
tags: [Tag!]!
|
||||||
|
|
||||||
|
"""The path to stream this marker"""
|
||||||
|
stream: String! # Resolver
|
||||||
|
"""The path to the preview image for this marker"""
|
||||||
|
preview: String! # Resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
input SceneMarkerCreateInput {
|
||||||
|
title: String!
|
||||||
|
seconds: Float!
|
||||||
|
scene_id: ID!
|
||||||
|
primary_tag_id: ID!
|
||||||
|
tag_ids: [ID!]
|
||||||
|
}
|
||||||
|
|
||||||
|
input SceneMarkerUpdateInput {
|
||||||
|
id: ID!
|
||||||
|
title: String!
|
||||||
|
seconds: Float!
|
||||||
|
scene_id: ID!
|
||||||
|
primary_tag_id: ID!
|
||||||
|
tag_ids: [ID!]
|
||||||
|
}
|
||||||
|
|
||||||
|
type FindSceneMarkersResultType {
|
||||||
|
count: Int!
|
||||||
|
scene_markers: [SceneMarker!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type MarkerStringsResultType {
|
||||||
|
count: Int!
|
||||||
|
id: ID!
|
||||||
|
title: String!
|
||||||
|
}
|
||||||
59
graphql/schema/types/scene.graphql
Normal file
59
graphql/schema/types/scene.graphql
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
type SceneFileType {
|
||||||
|
size: String
|
||||||
|
duration: Float
|
||||||
|
video_codec: String
|
||||||
|
audio_codec: String
|
||||||
|
width: Int
|
||||||
|
height: Int
|
||||||
|
framerate: Float
|
||||||
|
bitrate: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
type ScenePathsType {
|
||||||
|
screenshot: String # Resolver
|
||||||
|
preview: String # Resolver
|
||||||
|
stream: String # Resolver
|
||||||
|
webp: String # Resolver
|
||||||
|
vtt: String # Resolver
|
||||||
|
chapters_vtt: String # Resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
type Scene {
|
||||||
|
id: ID!
|
||||||
|
checksum: String!
|
||||||
|
title: String
|
||||||
|
details: String
|
||||||
|
url: String
|
||||||
|
date: String
|
||||||
|
rating: Int
|
||||||
|
path: String!
|
||||||
|
|
||||||
|
file: SceneFileType! # Resolver
|
||||||
|
paths: ScenePathsType! # Resolver
|
||||||
|
is_streamable: Boolean! # Resolver
|
||||||
|
|
||||||
|
scene_markers: [SceneMarker!]!
|
||||||
|
gallery: Gallery
|
||||||
|
studio: Studio
|
||||||
|
tags: [Tag!]!
|
||||||
|
performers: [Performer!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
input SceneUpdateInput {
|
||||||
|
clientMutationId: String
|
||||||
|
id: ID!
|
||||||
|
title: String
|
||||||
|
details: String
|
||||||
|
url: String
|
||||||
|
date: String
|
||||||
|
rating: Int
|
||||||
|
studio_id: ID
|
||||||
|
gallery_id: ID
|
||||||
|
performer_ids: [ID!]
|
||||||
|
tag_ids: [ID!]
|
||||||
|
}
|
||||||
|
|
||||||
|
type FindScenesResultType {
|
||||||
|
count: Int!
|
||||||
|
scenes: [Scene!]!
|
||||||
|
}
|
||||||
18
graphql/schema/types/scraped-performer.graphql
Normal file
18
graphql/schema/types/scraped-performer.graphql
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
"""A performer from a scraping operation..."""
|
||||||
|
type ScrapedPerformer {
|
||||||
|
name: String
|
||||||
|
url: String
|
||||||
|
twitter: String
|
||||||
|
instagram: String
|
||||||
|
birthdate: String
|
||||||
|
ethnicity: String
|
||||||
|
country: String
|
||||||
|
eye_color: String
|
||||||
|
height: String
|
||||||
|
measurements: String
|
||||||
|
fake_tits: String
|
||||||
|
career_length: String
|
||||||
|
tattoos: String
|
||||||
|
piercings: String
|
||||||
|
aliases: String
|
||||||
|
}
|
||||||
7
graphql/schema/types/stats.graphql
Normal file
7
graphql/schema/types/stats.graphql
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
type StatsResultType {
|
||||||
|
scene_count: Int!
|
||||||
|
gallery_count: Int!
|
||||||
|
performer_count: Int!
|
||||||
|
studio_count: Int!
|
||||||
|
tag_count: Int!
|
||||||
|
}
|
||||||
29
graphql/schema/types/studio.graphql
Normal file
29
graphql/schema/types/studio.graphql
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
type Studio {
|
||||||
|
id: ID!
|
||||||
|
checksum: String!
|
||||||
|
name: String!
|
||||||
|
url: String
|
||||||
|
|
||||||
|
image_path: String # Resolver
|
||||||
|
scene_count: Int # Resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
input StudioCreateInput {
|
||||||
|
name: String!
|
||||||
|
url: String
|
||||||
|
"""This should be base64 encoded"""
|
||||||
|
image: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
input StudioUpdateInput {
|
||||||
|
id: ID!
|
||||||
|
name: String
|
||||||
|
url: String
|
||||||
|
"""This should be base64 encoded"""
|
||||||
|
image: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type FindStudiosResultType {
|
||||||
|
count: Int!
|
||||||
|
studios: [Studio!]!
|
||||||
|
}
|
||||||
20
graphql/schema/types/tag.graphql
Normal file
20
graphql/schema/types/tag.graphql
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
type Tag {
|
||||||
|
id: ID!
|
||||||
|
name: String!
|
||||||
|
|
||||||
|
scene_count: Int # Resolver
|
||||||
|
scene_marker_count: Int # Resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
input TagCreateInput {
|
||||||
|
name: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
input TagUpdateInput {
|
||||||
|
id: ID!
|
||||||
|
name: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
input TagDestroyInput {
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
@@ -84,7 +84,7 @@ func (r *queryResolver) ValidGalleriesForScene(ctx context.Context, scene_id *st
|
|||||||
return validGalleries, nil
|
return validGalleries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Stats(ctx context.Context) (models.StatsResultType, error) {
|
func (r *queryResolver) Stats(ctx context.Context) (*models.StatsResultType, error) {
|
||||||
scenesQB := models.NewSceneQueryBuilder()
|
scenesQB := models.NewSceneQueryBuilder()
|
||||||
scenesCount, _ := scenesQB.Count()
|
scenesCount, _ := scenesQB.Count()
|
||||||
galleryQB := models.NewGalleryQueryBuilder()
|
galleryQB := models.NewGalleryQueryBuilder()
|
||||||
@@ -95,7 +95,7 @@ func (r *queryResolver) Stats(ctx context.Context) (models.StatsResultType, erro
|
|||||||
studiosCount, _ := studiosQB.Count()
|
studiosCount, _ := studiosQB.Count()
|
||||||
tagsQB := models.NewTagQueryBuilder()
|
tagsQB := models.NewTagQueryBuilder()
|
||||||
tagsCount, _ := tagsQB.Count()
|
tagsCount, _ := tagsQB.Count()
|
||||||
return models.StatsResultType{
|
return &models.StatsResultType{
|
||||||
SceneCount: scenesCount,
|
SceneCount: scenesCount,
|
||||||
GalleryCount: galleryCount,
|
GalleryCount: galleryCount,
|
||||||
PerformerCount: performersCount,
|
PerformerCount: performersCount,
|
||||||
|
|||||||
@@ -3,13 +3,8 @@ package api
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *galleryResolver) ID(ctx context.Context, obj *models.Gallery) (string, error) {
|
|
||||||
return strconv.Itoa(obj.ID), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *galleryResolver) Title(ctx context.Context, obj *models.Gallery) (*string, error) {
|
func (r *galleryResolver) Title(ctx context.Context, obj *models.Gallery) (*string, error) {
|
||||||
return nil, nil // TODO remove this from schema
|
return nil, nil // TODO remove this from schema
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"github.com/stashapp/stash/pkg/api/urlbuilders"
|
"github.com/stashapp/stash/pkg/api/urlbuilders"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *performerResolver) ID(ctx context.Context, obj *models.Performer) (string, error) {
|
|
||||||
return strconv.Itoa(obj.ID), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *performerResolver) Name(ctx context.Context, obj *models.Performer) (*string, error) {
|
func (r *performerResolver) Name(ctx context.Context, obj *models.Performer) (*string, error) {
|
||||||
if obj.Name.Valid {
|
if obj.Name.Valid {
|
||||||
return &obj.Name.String, nil
|
return &obj.Name.String, nil
|
||||||
|
|||||||
@@ -6,13 +6,8 @@ import (
|
|||||||
"github.com/stashapp/stash/pkg/manager"
|
"github.com/stashapp/stash/pkg/manager"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
"github.com/stashapp/stash/pkg/utils"
|
"github.com/stashapp/stash/pkg/utils"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *sceneResolver) ID(ctx context.Context, obj *models.Scene) (string, error) {
|
|
||||||
return strconv.Itoa(obj.ID), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *sceneResolver) Title(ctx context.Context, obj *models.Scene) (*string, error) {
|
func (r *sceneResolver) Title(ctx context.Context, obj *models.Scene) (*string, error) {
|
||||||
if obj.Title.Valid {
|
if obj.Title.Valid {
|
||||||
return &obj.Title.String, nil
|
return &obj.Title.String, nil
|
||||||
@@ -50,11 +45,11 @@ func (r *sceneResolver) Rating(ctx context.Context, obj *models.Scene) (*int, er
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *sceneResolver) File(ctx context.Context, obj *models.Scene) (models.SceneFileType, error) {
|
func (r *sceneResolver) File(ctx context.Context, obj *models.Scene) (*models.SceneFileType, error) {
|
||||||
width := int(obj.Width.Int64)
|
width := int(obj.Width.Int64)
|
||||||
height := int(obj.Height.Int64)
|
height := int(obj.Height.Int64)
|
||||||
bitrate := int(obj.Bitrate.Int64)
|
bitrate := int(obj.Bitrate.Int64)
|
||||||
return models.SceneFileType{
|
return &models.SceneFileType{
|
||||||
Size: &obj.Size.String,
|
Size: &obj.Size.String,
|
||||||
Duration: &obj.Duration.Float64,
|
Duration: &obj.Duration.Float64,
|
||||||
VideoCodec: &obj.VideoCodec.String,
|
VideoCodec: &obj.VideoCodec.String,
|
||||||
@@ -66,7 +61,7 @@ func (r *sceneResolver) File(ctx context.Context, obj *models.Scene) (models.Sce
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *sceneResolver) Paths(ctx context.Context, obj *models.Scene) (models.ScenePathsType, error) {
|
func (r *sceneResolver) Paths(ctx context.Context, obj *models.Scene) (*models.ScenePathsType, error) {
|
||||||
baseURL, _ := ctx.Value(BaseURLCtxKey).(string)
|
baseURL, _ := ctx.Value(BaseURLCtxKey).(string)
|
||||||
builder := urlbuilders.NewSceneURLBuilder(baseURL, obj.ID)
|
builder := urlbuilders.NewSceneURLBuilder(baseURL, obj.ID)
|
||||||
screenshotPath := builder.GetScreenshotURL()
|
screenshotPath := builder.GetScreenshotURL()
|
||||||
@@ -75,7 +70,7 @@ func (r *sceneResolver) Paths(ctx context.Context, obj *models.Scene) (models.Sc
|
|||||||
webpPath := builder.GetStreamPreviewImageURL()
|
webpPath := builder.GetStreamPreviewImageURL()
|
||||||
vttPath := builder.GetSpriteVTTURL()
|
vttPath := builder.GetSpriteVTTURL()
|
||||||
chaptersVttPath := builder.GetChaptersVTTURL()
|
chaptersVttPath := builder.GetChaptersVTTURL()
|
||||||
return models.ScenePathsType{
|
return &models.ScenePathsType{
|
||||||
Screenshot: &screenshotPath,
|
Screenshot: &screenshotPath,
|
||||||
Preview: &previewPath,
|
Preview: &previewPath,
|
||||||
Stream: &streamPath,
|
Stream: &streamPath,
|
||||||
|
|||||||
@@ -4,30 +4,25 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"github.com/stashapp/stash/pkg/api/urlbuilders"
|
"github.com/stashapp/stash/pkg/api/urlbuilders"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *sceneMarkerResolver) ID(ctx context.Context, obj *models.SceneMarker) (string, error) {
|
func (r *sceneMarkerResolver) Scene(ctx context.Context, obj *models.SceneMarker) (*models.Scene, error) {
|
||||||
return strconv.Itoa(obj.ID), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *sceneMarkerResolver) Scene(ctx context.Context, obj *models.SceneMarker) (models.Scene, error) {
|
|
||||||
if !obj.SceneID.Valid {
|
if !obj.SceneID.Valid {
|
||||||
panic("Invalid scene id")
|
panic("Invalid scene id")
|
||||||
}
|
}
|
||||||
qb := models.NewSceneQueryBuilder()
|
qb := models.NewSceneQueryBuilder()
|
||||||
sceneID := int(obj.SceneID.Int64)
|
sceneID := int(obj.SceneID.Int64)
|
||||||
scene, err := qb.Find(sceneID)
|
scene, err := qb.Find(sceneID)
|
||||||
return *scene, err
|
return scene, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *sceneMarkerResolver) PrimaryTag(ctx context.Context, obj *models.SceneMarker) (models.Tag, error) {
|
func (r *sceneMarkerResolver) PrimaryTag(ctx context.Context, obj *models.SceneMarker) (*models.Tag, error) {
|
||||||
qb := models.NewTagQueryBuilder()
|
qb := models.NewTagQueryBuilder()
|
||||||
if !obj.PrimaryTagID.Valid {
|
if !obj.PrimaryTagID.Valid {
|
||||||
panic("TODO no primary tag id")
|
panic("TODO no primary tag id")
|
||||||
}
|
}
|
||||||
tag, err := qb.Find(int(obj.PrimaryTagID.Int64), nil) // TODO make primary tag id not null in DB
|
tag, err := qb.Find(int(obj.PrimaryTagID.Int64), nil) // TODO make primary tag id not null in DB
|
||||||
return *tag, err
|
return tag, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *sceneMarkerResolver) Tags(ctx context.Context, obj *models.SceneMarker) ([]models.Tag, error) {
|
func (r *sceneMarkerResolver) Tags(ctx context.Context, obj *models.SceneMarker) ([]models.Tag, error) {
|
||||||
|
|||||||
@@ -4,13 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"github.com/stashapp/stash/pkg/api/urlbuilders"
|
"github.com/stashapp/stash/pkg/api/urlbuilders"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *studioResolver) ID(ctx context.Context, obj *models.Studio) (string, error) {
|
|
||||||
return strconv.Itoa(obj.ID), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *studioResolver) Name(ctx context.Context, obj *models.Studio) (string, error) {
|
func (r *studioResolver) Name(ctx context.Context, obj *models.Studio) (string, error) {
|
||||||
if obj.Name.Valid {
|
if obj.Name.Valid {
|
||||||
return obj.Name.String, nil
|
return obj.Name.String, nil
|
||||||
|
|||||||
@@ -3,13 +3,8 @@ package api
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *tagResolver) ID(ctx context.Context, obj *models.Tag) (string, error) {
|
|
||||||
return strconv.Itoa(obj.ID), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *tagResolver) SceneCount(ctx context.Context, obj *models.Tag) (*int, error) {
|
func (r *tagResolver) SceneCount(ctx context.Context, obj *models.Tag) (*int, error) {
|
||||||
qb := models.NewSceneQueryBuilder()
|
qb := models.NewSceneQueryBuilder()
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input models.ConfigGeneralInput) (models.ConfigGeneralResult, error) {
|
func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input models.ConfigGeneralInput) (*models.ConfigGeneralResult, error) {
|
||||||
if len(input.Stashes) > 0 {
|
if len(input.Stashes) > 0 {
|
||||||
for _, stashPath := range input.Stashes {
|
for _, stashPath := range input.Stashes {
|
||||||
exists, err := utils.DirExists(stashPath)
|
exists, err := utils.DirExists(stashPath)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/stashapp/stash/pkg/utils"
|
"github.com/stashapp/stash/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *queryResolver) Configuration(ctx context.Context) (models.ConfigResult, error) {
|
func (r *queryResolver) Configuration(ctx context.Context) (*models.ConfigResult, error) {
|
||||||
return makeConfigResult(), nil
|
return makeConfigResult(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,14 +19,14 @@ func (r *queryResolver) Directories(ctx context.Context, path *string) ([]string
|
|||||||
return utils.ListDir(dirPath), nil
|
return utils.ListDir(dirPath), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeConfigResult() models.ConfigResult {
|
func makeConfigResult() *models.ConfigResult {
|
||||||
return models.ConfigResult{
|
return &models.ConfigResult{
|
||||||
General: makeConfigGeneralResult(),
|
General: *makeConfigGeneralResult(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeConfigGeneralResult() models.ConfigGeneralResult {
|
func makeConfigGeneralResult() *models.ConfigGeneralResult {
|
||||||
return models.ConfigGeneralResult{
|
return &models.ConfigGeneralResult{
|
||||||
Stashes: config.GetStashPaths(),
|
Stashes: config.GetStashPaths(),
|
||||||
DatabasePath: config.GetDatabasePath(),
|
DatabasePath: config.GetDatabasePath(),
|
||||||
GeneratedPath: config.GetGeneratedPath(),
|
GeneratedPath: config.GetGeneratedPath(),
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ func (r *queryResolver) FindGallery(ctx context.Context, id string) (*models.Gal
|
|||||||
return qb.Find(idInt)
|
return qb.Find(idInt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) FindGalleries(ctx context.Context, filter *models.FindFilterType) (models.FindGalleriesResultType, error) {
|
func (r *queryResolver) FindGalleries(ctx context.Context, filter *models.FindFilterType) (*models.FindGalleriesResultType, error) {
|
||||||
qb := models.NewGalleryQueryBuilder()
|
qb := models.NewGalleryQueryBuilder()
|
||||||
galleries, total := qb.Query(filter)
|
galleries, total := qb.Query(filter)
|
||||||
return models.FindGalleriesResultType{
|
return &models.FindGalleriesResultType{
|
||||||
Count: total,
|
Count: total,
|
||||||
Galleries: galleries,
|
Galleries: galleries,
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ func (r *queryResolver) FindPerformer(ctx context.Context, id string) (*models.P
|
|||||||
return qb.Find(idInt)
|
return qb.Find(idInt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) FindPerformers(ctx context.Context, performer_filter *models.PerformerFilterType, filter *models.FindFilterType) (models.FindPerformersResultType, error) {
|
func (r *queryResolver) FindPerformers(ctx context.Context, performerFilter *models.PerformerFilterType, filter *models.FindFilterType) (*models.FindPerformersResultType, error) {
|
||||||
qb := models.NewPerformerQueryBuilder()
|
qb := models.NewPerformerQueryBuilder()
|
||||||
performers, total := qb.Query(performer_filter, filter)
|
performers, total := qb.Query(performerFilter, filter)
|
||||||
return models.FindPerformersResultType{
|
return &models.FindPerformersResultType{
|
||||||
Count: total,
|
Count: total,
|
||||||
Performers: performers,
|
Performers: performers,
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ func (r *queryResolver) FindScene(ctx context.Context, id *string, checksum *str
|
|||||||
return scene, err
|
return scene, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) FindScenes(ctx context.Context, scene_filter *models.SceneFilterType, scene_ids []int, filter *models.FindFilterType) (models.FindScenesResultType, error) {
|
func (r *queryResolver) FindScenes(ctx context.Context, sceneFilter *models.SceneFilterType, sceneIds []int, filter *models.FindFilterType) (*models.FindScenesResultType, error) {
|
||||||
qb := models.NewSceneQueryBuilder()
|
qb := models.NewSceneQueryBuilder()
|
||||||
scenes, total := qb.Query(scene_filter, filter)
|
scenes, total := qb.Query(sceneFilter, filter)
|
||||||
return models.FindScenesResultType{
|
return &models.FindScenesResultType{
|
||||||
Count: total,
|
Count: total,
|
||||||
Scenes: scenes,
|
Scenes: scenes,
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import (
|
|||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *queryResolver) FindSceneMarkers(ctx context.Context, scene_marker_filter *models.SceneMarkerFilterType, filter *models.FindFilterType) (models.FindSceneMarkersResultType, error) {
|
func (r *queryResolver) FindSceneMarkers(ctx context.Context, sceneMarkerFilter *models.SceneMarkerFilterType, filter *models.FindFilterType) (*models.FindSceneMarkersResultType, error) {
|
||||||
qb := models.NewSceneMarkerQueryBuilder()
|
qb := models.NewSceneMarkerQueryBuilder()
|
||||||
sceneMarkers, total := qb.Query(scene_marker_filter, filter)
|
sceneMarkers, total := qb.Query(sceneMarkerFilter, filter)
|
||||||
return models.FindSceneMarkersResultType{
|
return &models.FindSceneMarkersResultType{
|
||||||
Count: total,
|
Count: total,
|
||||||
SceneMarkers: sceneMarkers,
|
SceneMarkers: sceneMarkers,
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ func (r *queryResolver) FindStudio(ctx context.Context, id string) (*models.Stud
|
|||||||
return qb.Find(idInt, nil)
|
return qb.Find(idInt, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) FindStudios(ctx context.Context, filter *models.FindFilterType) (models.FindStudiosResultType, error) {
|
func (r *queryResolver) FindStudios(ctx context.Context, filter *models.FindFilterType) (*models.FindStudiosResultType, error) {
|
||||||
qb := models.NewStudioQueryBuilder()
|
qb := models.NewStudioQueryBuilder()
|
||||||
studios, total := qb.Query(filter)
|
studios, total := qb.Query(filter)
|
||||||
return models.FindStudiosResultType{
|
return &models.FindStudiosResultType{
|
||||||
Count: total,
|
Count: total,
|
||||||
Studios: studios,
|
Studios: studios,
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,541 +0,0 @@
|
|||||||
#######################################
|
|
||||||
# Gallery
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
"""Gallery type"""
|
|
||||||
type Gallery {
|
|
||||||
id: ID!
|
|
||||||
checksum: String!
|
|
||||||
path: String!
|
|
||||||
title: String
|
|
||||||
|
|
||||||
"""The files in the gallery"""
|
|
||||||
files: [GalleryFilesType!]! # Resolver
|
|
||||||
}
|
|
||||||
|
|
||||||
type GalleryFilesType {
|
|
||||||
index: Int!
|
|
||||||
name: String
|
|
||||||
path: String
|
|
||||||
}
|
|
||||||
|
|
||||||
type FindGalleriesResultType {
|
|
||||||
count: Int!
|
|
||||||
galleries: [Gallery!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Performer
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
type Performer {
|
|
||||||
id: ID!
|
|
||||||
checksum: String!
|
|
||||||
name: String
|
|
||||||
url: String
|
|
||||||
twitter: String
|
|
||||||
instagram: String
|
|
||||||
birthdate: String
|
|
||||||
ethnicity: String
|
|
||||||
country: String
|
|
||||||
eye_color: String
|
|
||||||
height: String
|
|
||||||
measurements: String
|
|
||||||
fake_tits: String
|
|
||||||
career_length: String
|
|
||||||
tattoos: String
|
|
||||||
piercings: String
|
|
||||||
aliases: String
|
|
||||||
favorite: Boolean!
|
|
||||||
|
|
||||||
image_path: String # Resolver
|
|
||||||
scene_count: Int # Resolver
|
|
||||||
scenes: [Scene!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
input PerformerCreateInput {
|
|
||||||
name: String
|
|
||||||
url: String
|
|
||||||
birthdate: String
|
|
||||||
ethnicity: String
|
|
||||||
country: String
|
|
||||||
eye_color: String
|
|
||||||
height: String
|
|
||||||
measurements: String
|
|
||||||
fake_tits: String
|
|
||||||
career_length: String
|
|
||||||
tattoos: String
|
|
||||||
piercings: String
|
|
||||||
aliases: String
|
|
||||||
twitter: String
|
|
||||||
instagram: String
|
|
||||||
favorite: Boolean
|
|
||||||
"""This should be base64 encoded"""
|
|
||||||
image: String!
|
|
||||||
}
|
|
||||||
|
|
||||||
input PerformerUpdateInput {
|
|
||||||
id: ID!
|
|
||||||
name: String
|
|
||||||
url: String
|
|
||||||
birthdate: String
|
|
||||||
ethnicity: String
|
|
||||||
country: String
|
|
||||||
eye_color: String
|
|
||||||
height: String
|
|
||||||
measurements: String
|
|
||||||
fake_tits: String
|
|
||||||
career_length: String
|
|
||||||
tattoos: String
|
|
||||||
piercings: String
|
|
||||||
aliases: String
|
|
||||||
twitter: String
|
|
||||||
instagram: String
|
|
||||||
favorite: Boolean
|
|
||||||
"""This should be base64 encoded"""
|
|
||||||
image: String
|
|
||||||
}
|
|
||||||
|
|
||||||
type FindPerformersResultType {
|
|
||||||
count: Int!
|
|
||||||
performers: [Performer!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Scene Marker Tag
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
type SceneMarkerTag {
|
|
||||||
tag: Tag!
|
|
||||||
scene_markers: [SceneMarker!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Scene Marker
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
type SceneMarker {
|
|
||||||
id: ID!
|
|
||||||
scene: Scene!
|
|
||||||
title: String!
|
|
||||||
seconds: Float!
|
|
||||||
primary_tag: Tag!
|
|
||||||
tags: [Tag!]!
|
|
||||||
|
|
||||||
"""The path to stream this marker"""
|
|
||||||
stream: String! # Resolver
|
|
||||||
"""The path to the preview image for this marker"""
|
|
||||||
preview: String! # Resolver
|
|
||||||
}
|
|
||||||
|
|
||||||
input SceneMarkerCreateInput {
|
|
||||||
title: String!
|
|
||||||
seconds: Float!
|
|
||||||
scene_id: ID!
|
|
||||||
primary_tag_id: ID!
|
|
||||||
tag_ids: [ID!]
|
|
||||||
}
|
|
||||||
|
|
||||||
input SceneMarkerUpdateInput {
|
|
||||||
id: ID!
|
|
||||||
title: String!
|
|
||||||
seconds: Float!
|
|
||||||
scene_id: ID!
|
|
||||||
primary_tag_id: ID!
|
|
||||||
tag_ids: [ID!]
|
|
||||||
}
|
|
||||||
|
|
||||||
type FindSceneMarkersResultType {
|
|
||||||
count: Int!
|
|
||||||
scene_markers: [SceneMarker!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type MarkerStringsResultType {
|
|
||||||
count: Int!
|
|
||||||
id: ID!
|
|
||||||
title: String!
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Scene
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
type SceneFileType {
|
|
||||||
size: String
|
|
||||||
duration: Float
|
|
||||||
video_codec: String
|
|
||||||
audio_codec: String
|
|
||||||
width: Int
|
|
||||||
height: Int
|
|
||||||
framerate: Float
|
|
||||||
bitrate: Int
|
|
||||||
}
|
|
||||||
|
|
||||||
type ScenePathsType {
|
|
||||||
screenshot: String # Resolver
|
|
||||||
preview: String # Resolver
|
|
||||||
stream: String # Resolver
|
|
||||||
webp: String # Resolver
|
|
||||||
vtt: String # Resolver
|
|
||||||
chapters_vtt: String # Resolver
|
|
||||||
}
|
|
||||||
|
|
||||||
type Scene {
|
|
||||||
id: ID!
|
|
||||||
checksum: String!
|
|
||||||
title: String
|
|
||||||
details: String
|
|
||||||
url: String
|
|
||||||
date: String
|
|
||||||
rating: Int
|
|
||||||
path: String!
|
|
||||||
|
|
||||||
file: SceneFileType! # Resolver
|
|
||||||
paths: ScenePathsType! # Resolver
|
|
||||||
is_streamable: Boolean! # Resolver
|
|
||||||
|
|
||||||
scene_markers: [SceneMarker!]!
|
|
||||||
gallery: Gallery
|
|
||||||
studio: Studio
|
|
||||||
tags: [Tag!]!
|
|
||||||
performers: [Performer!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
input SceneUpdateInput {
|
|
||||||
clientMutationId: String
|
|
||||||
id: ID!
|
|
||||||
title: String
|
|
||||||
details: String
|
|
||||||
url: String
|
|
||||||
date: String
|
|
||||||
rating: Int
|
|
||||||
studio_id: ID
|
|
||||||
gallery_id: ID
|
|
||||||
performer_ids: [ID!]
|
|
||||||
tag_ids: [ID!]
|
|
||||||
}
|
|
||||||
|
|
||||||
type FindScenesResultType {
|
|
||||||
count: Int!
|
|
||||||
scenes: [Scene!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Scraped Performer
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
"""A performer from a scraping operation..."""
|
|
||||||
type ScrapedPerformer {
|
|
||||||
name: String
|
|
||||||
url: String
|
|
||||||
twitter: String
|
|
||||||
instagram: String
|
|
||||||
birthdate: String
|
|
||||||
ethnicity: String
|
|
||||||
country: String
|
|
||||||
eye_color: String
|
|
||||||
height: String
|
|
||||||
measurements: String
|
|
||||||
fake_tits: String
|
|
||||||
career_length: String
|
|
||||||
tattoos: String
|
|
||||||
piercings: String
|
|
||||||
aliases: String
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Stats
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
type StatsResultType {
|
|
||||||
scene_count: Int!
|
|
||||||
gallery_count: Int!
|
|
||||||
performer_count: Int!
|
|
||||||
studio_count: Int!
|
|
||||||
tag_count: Int!
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Studio
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
type Studio {
|
|
||||||
id: ID!
|
|
||||||
checksum: String!
|
|
||||||
name: String!
|
|
||||||
url: String
|
|
||||||
|
|
||||||
image_path: String # Resolver
|
|
||||||
scene_count: Int # Resolver
|
|
||||||
}
|
|
||||||
|
|
||||||
input StudioCreateInput {
|
|
||||||
name: String!
|
|
||||||
url: String
|
|
||||||
"""This should be base64 encoded"""
|
|
||||||
image: String!
|
|
||||||
}
|
|
||||||
|
|
||||||
input StudioUpdateInput {
|
|
||||||
id: ID!
|
|
||||||
name: String
|
|
||||||
url: String
|
|
||||||
"""This should be base64 encoded"""
|
|
||||||
image: String
|
|
||||||
}
|
|
||||||
|
|
||||||
type FindStudiosResultType {
|
|
||||||
count: Int!
|
|
||||||
studios: [Studio!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Tag
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
type Tag {
|
|
||||||
id: ID!
|
|
||||||
name: String!
|
|
||||||
|
|
||||||
scene_count: Int # Resolver
|
|
||||||
scene_marker_count: Int # Resolver
|
|
||||||
}
|
|
||||||
|
|
||||||
input TagCreateInput {
|
|
||||||
name: String!
|
|
||||||
}
|
|
||||||
|
|
||||||
input TagUpdateInput {
|
|
||||||
id: ID!
|
|
||||||
name: String!
|
|
||||||
}
|
|
||||||
|
|
||||||
input TagDestroyInput {
|
|
||||||
id: ID!
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Filters
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
enum SortDirectionEnum {
|
|
||||||
ASC
|
|
||||||
DESC
|
|
||||||
}
|
|
||||||
|
|
||||||
input FindFilterType {
|
|
||||||
q: String
|
|
||||||
page: Int
|
|
||||||
per_page: Int
|
|
||||||
sort: String
|
|
||||||
direction: SortDirectionEnum
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ResolutionEnum {
|
|
||||||
"240p", LOW
|
|
||||||
"480p", STANDARD
|
|
||||||
"720p", STANDARD_HD
|
|
||||||
"1080p", FULL_HD
|
|
||||||
"4k", FOUR_K
|
|
||||||
}
|
|
||||||
|
|
||||||
input PerformerFilterType {
|
|
||||||
"""Filter by favorite"""
|
|
||||||
filter_favorites: Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
input SceneMarkerFilterType {
|
|
||||||
"""Filter to only include scene markers with this tag"""
|
|
||||||
tag_id: ID
|
|
||||||
"""Filter to only include scene markers with these tags"""
|
|
||||||
tags: [ID!]
|
|
||||||
"""Filter to only include scene markers attached to a scene with these tags"""
|
|
||||||
scene_tags: [ID!]
|
|
||||||
"""Filter to only include scene markers with these performers"""
|
|
||||||
performers: [ID!]
|
|
||||||
}
|
|
||||||
|
|
||||||
input SceneFilterType {
|
|
||||||
"""Filter by rating"""
|
|
||||||
rating: IntCriterionInput
|
|
||||||
"""Filter by resolution"""
|
|
||||||
resolution: ResolutionEnum
|
|
||||||
"""Filter to only include scenes which have markers. `true` or `false`"""
|
|
||||||
has_markers: String
|
|
||||||
"""Filter to only include scenes missing this property"""
|
|
||||||
is_missing: String
|
|
||||||
"""Filter to only include scenes with this studio"""
|
|
||||||
studio_id: ID
|
|
||||||
"""Filter to only include scenes with these tags"""
|
|
||||||
tags: [ID!]
|
|
||||||
"""Filter to only include scenes with this performer"""
|
|
||||||
performer_id: ID
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CriterionModifier {
|
|
||||||
"""="""
|
|
||||||
EQUALS,
|
|
||||||
"""!="""
|
|
||||||
NOT_EQUALS,
|
|
||||||
""">"""
|
|
||||||
GREATER_THAN,
|
|
||||||
"""<"""
|
|
||||||
LESS_THAN,
|
|
||||||
"""IS NULL"""
|
|
||||||
IS_NULL,
|
|
||||||
"""IS NOT NULL"""
|
|
||||||
NOT_NULL,
|
|
||||||
INCLUDES,
|
|
||||||
EXCLUDES,
|
|
||||||
}
|
|
||||||
|
|
||||||
input IntCriterionInput {
|
|
||||||
value: Int!
|
|
||||||
modifier: CriterionModifier!
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Config
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
input ConfigGeneralInput {
|
|
||||||
"""Array of file paths to content"""
|
|
||||||
stashes: [String!]
|
|
||||||
"""Path to the SQLite database"""
|
|
||||||
databasePath: String
|
|
||||||
"""Path to generated files"""
|
|
||||||
generatedPath: String
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConfigGeneralResult {
|
|
||||||
"""Array of file paths to content"""
|
|
||||||
stashes: [String!]!
|
|
||||||
"""Path to the SQLite database"""
|
|
||||||
databasePath: String!
|
|
||||||
"""Path to generated files"""
|
|
||||||
generatedPath: String!
|
|
||||||
}
|
|
||||||
|
|
||||||
"""All configuration settings"""
|
|
||||||
type ConfigResult {
|
|
||||||
general: ConfigGeneralResult!
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Metadata
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
input GenerateMetadataInput {
|
|
||||||
sprites: Boolean!
|
|
||||||
previews: Boolean!
|
|
||||||
markers: Boolean!
|
|
||||||
transcodes: Boolean!
|
|
||||||
}
|
|
||||||
|
|
||||||
#############
|
|
||||||
# Root Schema
|
|
||||||
#############
|
|
||||||
|
|
||||||
"""The query root for this schema"""
|
|
||||||
type Query {
|
|
||||||
"""Find a scene by ID or Checksum"""
|
|
||||||
findScene(id: ID, checksum: String): Scene
|
|
||||||
"""A function which queries Scene objects"""
|
|
||||||
findScenes(scene_filter: SceneFilterType, scene_ids: [Int!], filter: FindFilterType): FindScenesResultType!
|
|
||||||
|
|
||||||
"""A function which queries SceneMarker objects"""
|
|
||||||
findSceneMarkers(scene_marker_filter: SceneMarkerFilterType filter: FindFilterType): FindSceneMarkersResultType!
|
|
||||||
|
|
||||||
"""Find a performer by ID"""
|
|
||||||
findPerformer(id: ID!): Performer
|
|
||||||
"""A function which queries Performer objects"""
|
|
||||||
findPerformers(performer_filter: PerformerFilterType, filter: FindFilterType): FindPerformersResultType!
|
|
||||||
|
|
||||||
"""Find a studio by ID"""
|
|
||||||
findStudio(id: ID!): Studio
|
|
||||||
"""A function which queries Studio objects"""
|
|
||||||
findStudios(filter: FindFilterType): FindStudiosResultType!
|
|
||||||
|
|
||||||
findGallery(id: ID!): Gallery
|
|
||||||
findGalleries(filter: FindFilterType): FindGalleriesResultType!
|
|
||||||
|
|
||||||
findTag(id: ID!): Tag
|
|
||||||
|
|
||||||
"""Retrieve random scene markers for the wall"""
|
|
||||||
markerWall(q: String): [SceneMarker!]!
|
|
||||||
"""Retrieve random scenes for the wall"""
|
|
||||||
sceneWall(q: String): [Scene!]!
|
|
||||||
|
|
||||||
"""Get marker strings"""
|
|
||||||
markerStrings(q: String, sort: String): [MarkerStringsResultType]!
|
|
||||||
"""Get the list of valid galleries for a given scene ID"""
|
|
||||||
validGalleriesForScene(scene_id: ID): [Gallery!]!
|
|
||||||
"""Get stats"""
|
|
||||||
stats: StatsResultType!
|
|
||||||
"""Organize scene markers by tag for a given scene ID"""
|
|
||||||
sceneMarkerTags(scene_id: ID!): [SceneMarkerTag!]!
|
|
||||||
|
|
||||||
# Scrapers
|
|
||||||
|
|
||||||
"""Scrape a performer using Freeones"""
|
|
||||||
scrapeFreeones(performer_name: String!): ScrapedPerformer
|
|
||||||
"""Scrape a list of performers from a query"""
|
|
||||||
scrapeFreeonesPerformerList(query: String!): [String!]!
|
|
||||||
|
|
||||||
# Config
|
|
||||||
"""Returns the current, complete configuration"""
|
|
||||||
configuration: ConfigResult!
|
|
||||||
"""Returns an array of paths for the given path"""
|
|
||||||
directories(path: String): [String!]!
|
|
||||||
|
|
||||||
# Metadata
|
|
||||||
|
|
||||||
"""Start an import. Returns the job ID"""
|
|
||||||
metadataImport: String!
|
|
||||||
"""Start an export. Returns the job ID"""
|
|
||||||
metadataExport: String!
|
|
||||||
"""Start a scan. Returns the job ID"""
|
|
||||||
metadataScan: String!
|
|
||||||
"""Start generating content. Returns the job ID"""
|
|
||||||
metadataGenerate(input: GenerateMetadataInput!): String!
|
|
||||||
"""Clean metadata. Returns the job ID"""
|
|
||||||
metadataClean: String!
|
|
||||||
|
|
||||||
# Get everything
|
|
||||||
|
|
||||||
allPerformers: [Performer!]!
|
|
||||||
allStudios: [Studio!]!
|
|
||||||
allTags: [Tag!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type Mutation {
|
|
||||||
sceneUpdate(input: SceneUpdateInput!): Scene
|
|
||||||
|
|
||||||
sceneMarkerCreate(input: SceneMarkerCreateInput!): SceneMarker
|
|
||||||
sceneMarkerUpdate(input: SceneMarkerUpdateInput!): SceneMarker
|
|
||||||
sceneMarkerDestroy(id: ID!): Boolean!
|
|
||||||
|
|
||||||
performerCreate(input: PerformerCreateInput!): Performer
|
|
||||||
performerUpdate(input: PerformerUpdateInput!): Performer
|
|
||||||
|
|
||||||
studioCreate(input: StudioCreateInput!): Studio
|
|
||||||
studioUpdate(input: StudioUpdateInput!): Studio
|
|
||||||
|
|
||||||
tagCreate(input: TagCreateInput!): Tag
|
|
||||||
tagUpdate(input: TagUpdateInput!): Tag
|
|
||||||
tagDestroy(input: TagDestroyInput!): Boolean!
|
|
||||||
|
|
||||||
"""Change general configuration options"""
|
|
||||||
configureGeneral(input: ConfigGeneralInput!): ConfigGeneralResult!
|
|
||||||
}
|
|
||||||
|
|
||||||
type Subscription {
|
|
||||||
"""Update from the metadata manager"""
|
|
||||||
metadataUpdate: String!
|
|
||||||
}
|
|
||||||
|
|
||||||
schema {
|
|
||||||
query: Query
|
|
||||||
mutation: Mutation
|
|
||||||
subscription: Subscription
|
|
||||||
}
|
|
||||||
4071
schema/schema.json
4071
schema/schema.json
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
|||||||
schema: ../../schema/schema.graphql
|
schema: "../../graphql/schema/**/*.graphql"
|
||||||
overwrite: true
|
overwrite: true
|
||||||
generates:
|
generates:
|
||||||
./../../schema/schema.json:
|
./../../schema/schema.json:
|
||||||
- introspection
|
- introspection
|
||||||
./src/app/core/graphql-generated.ts:
|
./src/app/core/graphql-generated.ts:
|
||||||
documents: ./../../schema/documents/**/*.graphql
|
documents: ./../../graphql/documents/**/*.graphql
|
||||||
plugins:
|
plugins:
|
||||||
- add: "/* tslint:disable */"
|
- add: "/* tslint:disable */"
|
||||||
- time
|
- time
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
overwrite: true
|
overwrite: true
|
||||||
schema: "../../schema/schema.graphql"
|
schema: "../../graphql/schema/**/*.graphql"
|
||||||
documents: "../../schema/documents/**/*.graphql"
|
documents: "../../graphql/documents/**/*.graphql"
|
||||||
generates:
|
generates:
|
||||||
src/core/generated-graphql.tsx:
|
src/core/generated-graphql.tsx:
|
||||||
config:
|
config:
|
||||||
|
|||||||
33
vendor/github.com/99designs/gqlgen/graphql/context.go
generated
vendored
33
vendor/github.com/99designs/gqlgen/graphql/context.go
generated
vendored
@@ -12,6 +12,7 @@ import (
|
|||||||
type Resolver func(ctx context.Context) (res interface{}, err error)
|
type Resolver func(ctx context.Context) (res interface{}, err error)
|
||||||
type FieldMiddleware func(ctx context.Context, next Resolver) (res interface{}, err error)
|
type FieldMiddleware func(ctx context.Context, next Resolver) (res interface{}, err error)
|
||||||
type RequestMiddleware func(ctx context.Context, next func(ctx context.Context) []byte) []byte
|
type RequestMiddleware func(ctx context.Context, next func(ctx context.Context) []byte) []byte
|
||||||
|
type ComplexityLimitFunc func(ctx context.Context) int
|
||||||
|
|
||||||
type RequestContext struct {
|
type RequestContext struct {
|
||||||
RawQuery string
|
RawQuery string
|
||||||
@@ -71,12 +72,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GetRequestContext(ctx context.Context) *RequestContext {
|
func GetRequestContext(ctx context.Context) *RequestContext {
|
||||||
val := ctx.Value(request)
|
if val, ok := ctx.Value(request).(*RequestContext); ok {
|
||||||
if val == nil {
|
return val
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
return val.(*RequestContext)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithRequestContext(ctx context.Context, rc *RequestContext) context.Context {
|
func WithRequestContext(ctx context.Context, rc *RequestContext) context.Context {
|
||||||
@@ -95,6 +94,8 @@ type ResolverContext struct {
|
|||||||
Index *int
|
Index *int
|
||||||
// The result object of resolver
|
// The result object of resolver
|
||||||
Result interface{}
|
Result interface{}
|
||||||
|
// IsMethod indicates if the resolver is a method
|
||||||
|
IsMethod bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ResolverContext) Path() []interface{} {
|
func (r *ResolverContext) Path() []interface{} {
|
||||||
@@ -117,8 +118,10 @@ func (r *ResolverContext) Path() []interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetResolverContext(ctx context.Context) *ResolverContext {
|
func GetResolverContext(ctx context.Context) *ResolverContext {
|
||||||
val, _ := ctx.Value(resolver).(*ResolverContext)
|
if val, ok := ctx.Value(resolver).(*ResolverContext); ok {
|
||||||
return val
|
return val
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithResolverContext(ctx context.Context, rc *ResolverContext) context.Context {
|
func WithResolverContext(ctx context.Context, rc *ResolverContext) context.Context {
|
||||||
@@ -132,6 +135,24 @@ func CollectFieldsCtx(ctx context.Context, satisfies []string) []CollectedField
|
|||||||
return CollectFields(ctx, resctx.Field.Selections, satisfies)
|
return CollectFields(ctx, resctx.Field.Selections, satisfies)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CollectAllFields returns a slice of all GraphQL field names that were selected for the current resolver context.
|
||||||
|
// The slice will contain the unique set of all field names requested regardless of fragment type conditions.
|
||||||
|
func CollectAllFields(ctx context.Context) []string {
|
||||||
|
resctx := GetResolverContext(ctx)
|
||||||
|
collected := CollectFields(ctx, resctx.Field.Selections, nil)
|
||||||
|
uniq := make([]string, 0, len(collected))
|
||||||
|
Next:
|
||||||
|
for _, f := range collected {
|
||||||
|
for _, name := range uniq {
|
||||||
|
if name == f.Name {
|
||||||
|
continue Next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uniq = append(uniq, f.Name)
|
||||||
|
}
|
||||||
|
return uniq
|
||||||
|
}
|
||||||
|
|
||||||
// Errorf sends an error string to the client, passing it through the formatter.
|
// Errorf sends an error string to the client, passing it through the formatter.
|
||||||
func (c *RequestContext) Errorf(ctx context.Context, format string, args ...interface{}) {
|
func (c *RequestContext) Errorf(ctx context.Context, format string, args ...interface{}) {
|
||||||
c.errorsMu.Lock()
|
c.errorsMu.Lock()
|
||||||
|
|||||||
2
vendor/github.com/99designs/gqlgen/graphql/error.go
generated
vendored
2
vendor/github.com/99designs/gqlgen/graphql/error.go
generated
vendored
@@ -14,7 +14,9 @@ type ExtendedError interface {
|
|||||||
|
|
||||||
func DefaultErrorPresenter(ctx context.Context, err error) *gqlerror.Error {
|
func DefaultErrorPresenter(ctx context.Context, err error) *gqlerror.Error {
|
||||||
if gqlerr, ok := err.(*gqlerror.Error); ok {
|
if gqlerr, ok := err.(*gqlerror.Error); ok {
|
||||||
|
if gqlerr.Path == nil {
|
||||||
gqlerr.Path = GetResolverContext(ctx).Path()
|
gqlerr.Path = GetResolverContext(ctx).Path()
|
||||||
|
}
|
||||||
return gqlerr
|
return gqlerr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
vendor/github.com/99designs/gqlgen/graphql/exec.go
generated
vendored
10
vendor/github.com/99designs/gqlgen/graphql/exec.go
generated
vendored
@@ -16,6 +16,9 @@ type ExecutableSchema interface {
|
|||||||
Subscription(ctx context.Context, op *ast.OperationDefinition) func() *Response
|
Subscription(ctx context.Context, op *ast.OperationDefinition) func() *Response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CollectFields returns the set of fields from an ast.SelectionSet where all collected fields satisfy at least one of the GraphQL types
|
||||||
|
// passed through satisfies. Providing an empty or nil slice for satisfies will return collect all fields regardless of fragment
|
||||||
|
// type conditions.
|
||||||
func CollectFields(ctx context.Context, selSet ast.SelectionSet, satisfies []string) []CollectedField {
|
func CollectFields(ctx context.Context, selSet ast.SelectionSet, satisfies []string) []CollectedField {
|
||||||
return collectFields(GetRequestContext(ctx), selSet, satisfies, map[string]bool{})
|
return collectFields(GetRequestContext(ctx), selSet, satisfies, map[string]bool{})
|
||||||
}
|
}
|
||||||
@@ -35,7 +38,10 @@ func collectFields(reqCtx *RequestContext, selSet ast.SelectionSet, satisfies []
|
|||||||
|
|
||||||
f.Selections = append(f.Selections, sel.SelectionSet...)
|
f.Selections = append(f.Selections, sel.SelectionSet...)
|
||||||
case *ast.InlineFragment:
|
case *ast.InlineFragment:
|
||||||
if !shouldIncludeNode(sel.Directives, reqCtx.Variables) || !instanceOf(sel.TypeCondition, satisfies) {
|
if !shouldIncludeNode(sel.Directives, reqCtx.Variables) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(satisfies) > 0 && !instanceOf(sel.TypeCondition, satisfies) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, childField := range collectFields(reqCtx, sel.SelectionSet, satisfies, visited) {
|
for _, childField := range collectFields(reqCtx, sel.SelectionSet, satisfies, visited) {
|
||||||
@@ -59,7 +65,7 @@ func collectFields(reqCtx *RequestContext, selSet ast.SelectionSet, satisfies []
|
|||||||
panic(fmt.Errorf("missing fragment %s", fragmentName))
|
panic(fmt.Errorf("missing fragment %s", fragmentName))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !instanceOf(fragment.TypeCondition, satisfies) {
|
if len(satisfies) > 0 && !instanceOf(fragment.TypeCondition, satisfies) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
21
vendor/github.com/99designs/gqlgen/graphql/id.go
generated
vendored
21
vendor/github.com/99designs/gqlgen/graphql/id.go
generated
vendored
@@ -34,3 +34,24 @@ func UnmarshalID(v interface{}) (string, error) {
|
|||||||
return "", fmt.Errorf("%T is not a string", v)
|
return "", fmt.Errorf("%T is not a string", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MarshalIntID(i int) Marshaler {
|
||||||
|
return WriterFunc(func(w io.Writer) {
|
||||||
|
writeQuotedString(w, strconv.Itoa(i))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnmarshalIntID(v interface{}) (int, error) {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case string:
|
||||||
|
return strconv.Atoi(v)
|
||||||
|
case int:
|
||||||
|
return v, nil
|
||||||
|
case int64:
|
||||||
|
return int(v), nil
|
||||||
|
case json.Number:
|
||||||
|
return strconv.Atoi(string(v))
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("%T is not an int", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
50
vendor/github.com/99designs/gqlgen/graphql/int.go
generated
vendored
50
vendor/github.com/99designs/gqlgen/graphql/int.go
generated
vendored
@@ -27,3 +27,53 @@ func UnmarshalInt(v interface{}) (int, error) {
|
|||||||
return 0, fmt.Errorf("%T is not an int", v)
|
return 0, fmt.Errorf("%T is not an int", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MarshalInt64(i int64) Marshaler {
|
||||||
|
return WriterFunc(func(w io.Writer) {
|
||||||
|
io.WriteString(w, strconv.FormatInt(i, 10))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnmarshalInt64(v interface{}) (int64, error) {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case string:
|
||||||
|
return strconv.ParseInt(v, 10, 64)
|
||||||
|
case int:
|
||||||
|
return int64(v), nil
|
||||||
|
case int64:
|
||||||
|
return v, nil
|
||||||
|
case json.Number:
|
||||||
|
return strconv.ParseInt(string(v), 10, 64)
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("%T is not an int", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalInt32(i int32) Marshaler {
|
||||||
|
return WriterFunc(func(w io.Writer) {
|
||||||
|
io.WriteString(w, strconv.FormatInt(int64(i), 10))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnmarshalInt32(v interface{}) (int32, error) {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case string:
|
||||||
|
iv, err := strconv.ParseInt(v, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return int32(iv), nil
|
||||||
|
case int:
|
||||||
|
return int32(v), nil
|
||||||
|
case int64:
|
||||||
|
return int32(v), nil
|
||||||
|
case json.Number:
|
||||||
|
iv, err := strconv.ParseInt(string(v), 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return int32(iv), nil
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("%T is not an int", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
20
vendor/github.com/99designs/gqlgen/graphql/introspection/type.go
generated
vendored
20
vendor/github.com/99designs/gqlgen/graphql/introspection/type.go
generated
vendored
@@ -62,9 +62,9 @@ func (t *Type) Description() string {
|
|||||||
|
|
||||||
func (t *Type) Fields(includeDeprecated bool) []Field {
|
func (t *Type) Fields(includeDeprecated bool) []Field {
|
||||||
if t.def == nil || (t.def.Kind != ast.Object && t.def.Kind != ast.Interface) {
|
if t.def == nil || (t.def.Kind != ast.Object && t.def.Kind != ast.Interface) {
|
||||||
return nil
|
return []Field{}
|
||||||
}
|
}
|
||||||
var fields []Field
|
fields := []Field{}
|
||||||
for _, f := range t.def.Fields {
|
for _, f := range t.def.Fields {
|
||||||
if strings.HasPrefix(f.Name, "__") {
|
if strings.HasPrefix(f.Name, "__") {
|
||||||
continue
|
continue
|
||||||
@@ -93,10 +93,10 @@ func (t *Type) Fields(includeDeprecated bool) []Field {
|
|||||||
|
|
||||||
func (t *Type) InputFields() []InputValue {
|
func (t *Type) InputFields() []InputValue {
|
||||||
if t.def == nil || t.def.Kind != ast.InputObject {
|
if t.def == nil || t.def.Kind != ast.InputObject {
|
||||||
return nil
|
return []InputValue{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var res []InputValue
|
res := []InputValue{}
|
||||||
for _, f := range t.def.Fields {
|
for _, f := range t.def.Fields {
|
||||||
res = append(res, InputValue{
|
res = append(res, InputValue{
|
||||||
Name: f.Name,
|
Name: f.Name,
|
||||||
@@ -118,10 +118,10 @@ func defaultValue(value *ast.Value) *string {
|
|||||||
|
|
||||||
func (t *Type) Interfaces() []Type {
|
func (t *Type) Interfaces() []Type {
|
||||||
if t.def == nil || t.def.Kind != ast.Object {
|
if t.def == nil || t.def.Kind != ast.Object {
|
||||||
return nil
|
return []Type{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var res []Type
|
res := []Type{}
|
||||||
for _, intf := range t.def.Interfaces {
|
for _, intf := range t.def.Interfaces {
|
||||||
res = append(res, *WrapTypeFromDef(t.schema, t.schema.Types[intf]))
|
res = append(res, *WrapTypeFromDef(t.schema, t.schema.Types[intf]))
|
||||||
}
|
}
|
||||||
@@ -131,10 +131,10 @@ func (t *Type) Interfaces() []Type {
|
|||||||
|
|
||||||
func (t *Type) PossibleTypes() []Type {
|
func (t *Type) PossibleTypes() []Type {
|
||||||
if t.def == nil || (t.def.Kind != ast.Interface && t.def.Kind != ast.Union) {
|
if t.def == nil || (t.def.Kind != ast.Interface && t.def.Kind != ast.Union) {
|
||||||
return nil
|
return []Type{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var res []Type
|
res := []Type{}
|
||||||
for _, pt := range t.schema.GetPossibleTypes(t.def) {
|
for _, pt := range t.schema.GetPossibleTypes(t.def) {
|
||||||
res = append(res, *WrapTypeFromDef(t.schema, pt))
|
res = append(res, *WrapTypeFromDef(t.schema, pt))
|
||||||
}
|
}
|
||||||
@@ -143,10 +143,10 @@ func (t *Type) PossibleTypes() []Type {
|
|||||||
|
|
||||||
func (t *Type) EnumValues(includeDeprecated bool) []EnumValue {
|
func (t *Type) EnumValues(includeDeprecated bool) []EnumValue {
|
||||||
if t.def == nil || t.def.Kind != ast.Enum {
|
if t.def == nil || t.def.Kind != ast.Enum {
|
||||||
return nil
|
return []EnumValue{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var res []EnumValue
|
res := []EnumValue{}
|
||||||
for _, val := range t.def.EnumValues {
|
for _, val := range t.def.EnumValues {
|
||||||
res = append(res, EnumValue{
|
res = append(res, EnumValue{
|
||||||
Name: val.Name,
|
Name: val.Name,
|
||||||
|
|||||||
7
vendor/github.com/99designs/gqlgen/graphql/root.go
generated
vendored
Normal file
7
vendor/github.com/99designs/gqlgen/graphql/root.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package graphql
|
||||||
|
|
||||||
|
type Query struct{}
|
||||||
|
|
||||||
|
type Mutation struct{}
|
||||||
|
|
||||||
|
type Subscription struct{}
|
||||||
2
vendor/github.com/99designs/gqlgen/graphql/version.go
generated
vendored
2
vendor/github.com/99designs/gqlgen/graphql/version.go
generated
vendored
@@ -1,3 +1,3 @@
|
|||||||
package graphql
|
package graphql
|
||||||
|
|
||||||
const Version = "dev"
|
const Version = "v0.8.2"
|
||||||
|
|||||||
32
vendor/github.com/99designs/gqlgen/handler/graphql.go
generated
vendored
32
vendor/github.com/99designs/gqlgen/handler/graphql.go
generated
vendored
@@ -7,6 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/99designs/gqlgen/complexity"
|
"github.com/99designs/gqlgen/complexity"
|
||||||
"github.com/99designs/gqlgen/graphql"
|
"github.com/99designs/gqlgen/graphql"
|
||||||
@@ -33,7 +34,9 @@ type Config struct {
|
|||||||
requestHook graphql.RequestMiddleware
|
requestHook graphql.RequestMiddleware
|
||||||
tracer graphql.Tracer
|
tracer graphql.Tracer
|
||||||
complexityLimit int
|
complexityLimit int
|
||||||
|
complexityLimitFunc graphql.ComplexityLimitFunc
|
||||||
disableIntrospection bool
|
disableIntrospection bool
|
||||||
|
connectionKeepAlivePingInterval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) newRequestContext(es graphql.ExecutableSchema, doc *ast.QueryDocument, op *ast.OperationDefinition, query string, variables map[string]interface{}) *graphql.RequestContext {
|
func (c *Config) newRequestContext(es graphql.ExecutableSchema, doc *ast.QueryDocument, op *ast.OperationDefinition, query string, variables map[string]interface{}) *graphql.RequestContext {
|
||||||
@@ -60,7 +63,7 @@ func (c *Config) newRequestContext(es graphql.ExecutableSchema, doc *ast.QueryDo
|
|||||||
reqCtx.Tracer = hook
|
reqCtx.Tracer = hook
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.complexityLimit > 0 {
|
if c.complexityLimit > 0 || c.complexityLimitFunc != nil {
|
||||||
reqCtx.ComplexityLimit = c.complexityLimit
|
reqCtx.ComplexityLimit = c.complexityLimit
|
||||||
operationComplexity := complexity.Calculate(es, op, variables)
|
operationComplexity := complexity.Calculate(es, op, variables)
|
||||||
reqCtx.OperationComplexity = operationComplexity
|
reqCtx.OperationComplexity = operationComplexity
|
||||||
@@ -108,6 +111,15 @@ func ComplexityLimit(limit int) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ComplexityLimitFunc allows you to define a function to dynamically set the maximum query complexity that is allowed
|
||||||
|
// to be executed.
|
||||||
|
// If a query is submitted that exceeds the limit, a 422 status code will be returned.
|
||||||
|
func ComplexityLimitFunc(complexityLimitFunc graphql.ComplexityLimitFunc) Option {
|
||||||
|
return func(cfg *Config) {
|
||||||
|
cfg.complexityLimitFunc = complexityLimitFunc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ResolverMiddleware allows you to define a function that will be called around every resolver,
|
// ResolverMiddleware allows you to define a function that will be called around every resolver,
|
||||||
// useful for logging.
|
// useful for logging.
|
||||||
func ResolverMiddleware(middleware graphql.FieldMiddleware) Option {
|
func ResolverMiddleware(middleware graphql.FieldMiddleware) Option {
|
||||||
@@ -239,11 +251,23 @@ func CacheSize(size int) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WebsocketKeepAliveDuration allows you to reconfigure the keepalive behavior.
|
||||||
|
// By default, keepalive is enabled with a DefaultConnectionKeepAlivePingInterval
|
||||||
|
// duration. Set handler.connectionKeepAlivePingInterval = 0 to disable keepalive
|
||||||
|
// altogether.
|
||||||
|
func WebsocketKeepAliveDuration(duration time.Duration) Option {
|
||||||
|
return func(cfg *Config) {
|
||||||
|
cfg.connectionKeepAlivePingInterval = duration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const DefaultCacheSize = 1000
|
const DefaultCacheSize = 1000
|
||||||
|
const DefaultConnectionKeepAlivePingInterval = 25 * time.Second
|
||||||
|
|
||||||
func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc {
|
func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc {
|
||||||
cfg := &Config{
|
cfg := &Config{
|
||||||
cacheSize: DefaultCacheSize,
|
cacheSize: DefaultCacheSize,
|
||||||
|
connectionKeepAlivePingInterval: DefaultConnectionKeepAlivePingInterval,
|
||||||
upgrader: websocket.Upgrader{
|
upgrader: websocket.Upgrader{
|
||||||
ReadBufferSize: 1024,
|
ReadBufferSize: 1024,
|
||||||
WriteBufferSize: 1024,
|
WriteBufferSize: 1024,
|
||||||
@@ -297,6 +321,7 @@ func (gh *graphqlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
var reqParams params
|
var reqParams params
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
@@ -318,7 +343,6 @@ func (gh *graphqlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
|
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|
||||||
@@ -367,6 +391,10 @@ func (gh *graphqlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
if gh.cfg.complexityLimitFunc != nil {
|
||||||
|
reqCtx.ComplexityLimit = gh.cfg.complexityLimitFunc(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
if reqCtx.ComplexityLimit > 0 && reqCtx.OperationComplexity > reqCtx.ComplexityLimit {
|
if reqCtx.ComplexityLimit > 0 && reqCtx.OperationComplexity > reqCtx.ComplexityLimit {
|
||||||
sendErrorf(w, http.StatusUnprocessableEntity, "operation has complexity %d, which exceeds the limit of %d", reqCtx.OperationComplexity, reqCtx.ComplexityLimit)
|
sendErrorf(w, http.StatusUnprocessableEntity, "operation has complexity %d, which exceeds the limit of %d", reqCtx.OperationComplexity, reqCtx.ComplexityLimit)
|
||||||
return
|
return
|
||||||
|
|||||||
15
vendor/github.com/99designs/gqlgen/handler/playground.go
generated
vendored
15
vendor/github.com/99designs/gqlgen/handler/playground.go
generated
vendored
@@ -11,9 +11,12 @@ var page = template.Must(template.New("graphiql").Parse(`<!DOCTYPE html>
|
|||||||
<meta charset=utf-8/>
|
<meta charset=utf-8/>
|
||||||
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
|
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
|
||||||
<link rel="shortcut icon" href="https://graphcool-playground.netlify.com/favicon.png">
|
<link rel="shortcut icon" href="https://graphcool-playground.netlify.com/favicon.png">
|
||||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/static/css/index.css"/>
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/static/css/index.css"
|
||||||
<link rel="shortcut icon" href="//cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/favicon.png"/>
|
integrity="{{ .cssSRI }}" crossorigin="anonymous"/>
|
||||||
<script src="//cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/static/js/middleware.js"></script>
|
<link rel="shortcut icon" href="https://cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/favicon.png"
|
||||||
|
integrity="{{ .faviconSRI }}" crossorigin="anonymous"/>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/static/js/middleware.js"
|
||||||
|
integrity="{{ .jsSRI }}" crossorigin="anonymous"></script>
|
||||||
<title>{{.title}}</title>
|
<title>{{.title}}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -42,10 +45,14 @@ var page = template.Must(template.New("graphiql").Parse(`<!DOCTYPE html>
|
|||||||
|
|
||||||
func Playground(title string, endpoint string) http.HandlerFunc {
|
func Playground(title string, endpoint string) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Add("Content-Type", "text/html")
|
||||||
err := page.Execute(w, map[string]string{
|
err := page.Execute(w, map[string]string{
|
||||||
"title": title,
|
"title": title,
|
||||||
"endpoint": endpoint,
|
"endpoint": endpoint,
|
||||||
"version": "1.7.8",
|
"version": "1.7.20",
|
||||||
|
"cssSRI": "sha256-cS9Vc2OBt9eUf4sykRWukeFYaInL29+myBmFDSa7F/U=",
|
||||||
|
"faviconSRI": "sha256-GhTyE+McTU79R4+pRO6ih+4TfsTOrpPwD8ReKFzb3PM=",
|
||||||
|
"jsSRI": "sha256-4QG1Uza2GgGdlBL3RCBCGtGeZB6bDbsw8OltCMGeJsA=",
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
30
vendor/github.com/99designs/gqlgen/handler/websocket.go
generated
vendored
30
vendor/github.com/99designs/gqlgen/handler/websocket.go
generated
vendored
@@ -8,6 +8,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/99designs/gqlgen/graphql"
|
"github.com/99designs/gqlgen/graphql"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
@@ -28,7 +29,7 @@ const (
|
|||||||
dataMsg = "data" // Server -> Client
|
dataMsg = "data" // Server -> Client
|
||||||
errorMsg = "error" // Server -> Client
|
errorMsg = "error" // Server -> Client
|
||||||
completeMsg = "complete" // Server -> Client
|
completeMsg = "complete" // Server -> Client
|
||||||
//connectionKeepAliveMsg = "ka" // Server -> Client TODO: keepalives
|
connectionKeepAliveMsg = "ka" // Server -> Client
|
||||||
)
|
)
|
||||||
|
|
||||||
type operationMessage struct {
|
type operationMessage struct {
|
||||||
@@ -45,6 +46,7 @@ type wsConnection struct {
|
|||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
cfg *Config
|
cfg *Config
|
||||||
cache *lru.Cache
|
cache *lru.Cache
|
||||||
|
keepAliveTicker *time.Ticker
|
||||||
|
|
||||||
initPayload InitPayload
|
initPayload InitPayload
|
||||||
}
|
}
|
||||||
@@ -112,6 +114,20 @@ func (c *wsConnection) write(msg *operationMessage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *wsConnection) run() {
|
func (c *wsConnection) run() {
|
||||||
|
// We create a cancellation that will shutdown the keep-alive when we leave
|
||||||
|
// this function.
|
||||||
|
ctx, cancel := context.WithCancel(c.ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// Create a timer that will fire every interval to keep the connection alive.
|
||||||
|
if c.cfg.connectionKeepAlivePingInterval != 0 {
|
||||||
|
c.mu.Lock()
|
||||||
|
c.keepAliveTicker = time.NewTicker(c.cfg.connectionKeepAlivePingInterval)
|
||||||
|
c.mu.Unlock()
|
||||||
|
|
||||||
|
go c.keepAlive(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
message := c.readOp()
|
message := c.readOp()
|
||||||
if message == nil {
|
if message == nil {
|
||||||
@@ -144,6 +160,18 @@ func (c *wsConnection) run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *wsConnection) keepAlive(ctx context.Context) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
c.keepAliveTicker.Stop()
|
||||||
|
return
|
||||||
|
case <-c.keepAliveTicker.C:
|
||||||
|
c.write(&operationMessage{Type: connectionKeepAliveMsg})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *wsConnection) subscribe(message *operationMessage) bool {
|
func (c *wsConnection) subscribe(message *operationMessage) bool {
|
||||||
var reqParams params
|
var reqParams params
|
||||||
if err := jsonDecode(bytes.NewReader(message.Payload), &reqParams); err != nil {
|
if err := jsonDecode(bytes.NewReader(message.Payload), &reqParams); err != nil {
|
||||||
|
|||||||
137
vendor/github.com/vektah/gqlparser/validator/schema.go
generated
vendored
137
vendor/github.com/vektah/gqlparser/validator/schema.go
generated
vendored
@@ -184,13 +184,19 @@ func validateDefinition(schema *Schema, def *Definition) *gqlerror.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, intf := range def.Interfaces {
|
for _, typ := range def.Types {
|
||||||
intDef := schema.Types[intf]
|
typDef := schema.Types[typ]
|
||||||
if intDef == nil {
|
if typDef == nil {
|
||||||
return gqlerror.ErrorPosf(def.Position, "Undefined type %s.", strconv.Quote(intf))
|
return gqlerror.ErrorPosf(def.Position, "Undefined type %s.", strconv.Quote(typ))
|
||||||
}
|
}
|
||||||
if intDef.Kind != Interface {
|
if !isValidKind(typDef.Kind, Object) {
|
||||||
return gqlerror.ErrorPosf(def.Position, "%s is a non interface type %s.", strconv.Quote(intf), intDef.Kind)
|
return gqlerror.ErrorPosf(def.Position, "%s type %s must be %s.", def.Kind, strconv.Quote(typ), kindList(Object))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, intf := range def.Interfaces {
|
||||||
|
if err := validateImplements(schema, def, intf); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,6 +205,13 @@ func validateDefinition(schema *Schema, def *Definition) *gqlerror.Error {
|
|||||||
if len(def.Fields) == 0 {
|
if len(def.Fields) == 0 {
|
||||||
return gqlerror.ErrorPosf(def.Position, "%s must define one or more fields.", def.Kind)
|
return gqlerror.ErrorPosf(def.Position, "%s must define one or more fields.", def.Kind)
|
||||||
}
|
}
|
||||||
|
for _, field := range def.Fields {
|
||||||
|
if typ, ok := schema.Types[field.Type.Name()]; ok {
|
||||||
|
if !isValidKind(typ.Kind, Scalar, Object, Interface, Union, Enum) {
|
||||||
|
return gqlerror.ErrorPosf(field.Position, "%s field must be one of %s.", def.Kind, kindList(Scalar, Object, Interface, Union, Enum))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
case Enum:
|
case Enum:
|
||||||
if len(def.EnumValues) == 0 {
|
if len(def.EnumValues) == 0 {
|
||||||
return gqlerror.ErrorPosf(def.Position, "%s must define one or more unique enum values.", def.Kind)
|
return gqlerror.ErrorPosf(def.Position, "%s must define one or more unique enum values.", def.Kind)
|
||||||
@@ -207,6 +220,13 @@ func validateDefinition(schema *Schema, def *Definition) *gqlerror.Error {
|
|||||||
if len(def.Fields) == 0 {
|
if len(def.Fields) == 0 {
|
||||||
return gqlerror.ErrorPosf(def.Position, "%s must define one or more input fields.", def.Kind)
|
return gqlerror.ErrorPosf(def.Position, "%s must define one or more input fields.", def.Kind)
|
||||||
}
|
}
|
||||||
|
for _, field := range def.Fields {
|
||||||
|
if typ, ok := schema.Types[field.Type.Name()]; ok {
|
||||||
|
if !isValidKind(typ.Kind, Scalar, Enum, InputObject) {
|
||||||
|
return gqlerror.ErrorPosf(field.Position, "%s field must be one of %s.", def.Kind, kindList(Scalar, Enum, InputObject))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx, field1 := range def.Fields {
|
for idx, field1 := range def.Fields {
|
||||||
@@ -244,6 +264,16 @@ func validateArgs(schema *Schema, args ArgumentDefinitionList, currentDirective
|
|||||||
if err := validateTypeRef(schema, arg.Type); err != nil {
|
if err := validateTypeRef(schema, arg.Type); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
def := schema.Types[arg.Type.Name()]
|
||||||
|
if !def.IsInputType() {
|
||||||
|
return gqlerror.ErrorPosf(
|
||||||
|
arg.Position,
|
||||||
|
"cannot use %s as argument %s because %s is not a valid input type",
|
||||||
|
arg.Type.String(),
|
||||||
|
arg.Name,
|
||||||
|
def.Kind,
|
||||||
|
)
|
||||||
|
}
|
||||||
if err := validateDirectives(schema, arg.Directives, currentDirective); err != nil {
|
if err := validateDirectives(schema, arg.Directives, currentDirective); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -268,9 +298,104 @@ func validateDirectives(schema *Schema, dirs DirectiveList, currentDirective *Di
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateImplements(schema *Schema, def *Definition, intfName string) *gqlerror.Error {
|
||||||
|
// see validation rules at the bottom of
|
||||||
|
// https://facebook.github.io/graphql/June2018/#sec-Objects
|
||||||
|
intf := schema.Types[intfName]
|
||||||
|
if intf == nil {
|
||||||
|
return gqlerror.ErrorPosf(def.Position, "Undefined type %s.", strconv.Quote(intfName))
|
||||||
|
}
|
||||||
|
if intf.Kind != Interface {
|
||||||
|
return gqlerror.ErrorPosf(def.Position, "%s is a non interface type %s.", strconv.Quote(intfName), intf.Kind)
|
||||||
|
}
|
||||||
|
for _, requiredField := range intf.Fields {
|
||||||
|
foundField := def.Fields.ForName(requiredField.Name)
|
||||||
|
if foundField == nil {
|
||||||
|
return gqlerror.ErrorPosf(def.Position,
|
||||||
|
`For %s to implement %s it must have a field called %s.`,
|
||||||
|
def.Name, intf.Name, requiredField.Name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isCovariant(schema, requiredField.Type, foundField.Type) {
|
||||||
|
return gqlerror.ErrorPosf(foundField.Position,
|
||||||
|
`For %s to implement %s the field %s must have type %s.`,
|
||||||
|
def.Name, intf.Name, requiredField.Name, requiredField.Type.String(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, requiredArg := range requiredField.Arguments {
|
||||||
|
foundArg := foundField.Arguments.ForName(requiredArg.Name)
|
||||||
|
if foundArg == nil {
|
||||||
|
return gqlerror.ErrorPosf(foundField.Position,
|
||||||
|
`For %s to implement %s the field %s must have the same arguments but it is missing %s.`,
|
||||||
|
def.Name, intf.Name, requiredField.Name, requiredArg.Name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !requiredArg.Type.IsCompatible(foundArg.Type) {
|
||||||
|
return gqlerror.ErrorPosf(foundArg.Position,
|
||||||
|
`For %s to implement %s the field %s must have the same arguments but %s has the wrong type.`,
|
||||||
|
def.Name, intf.Name, requiredField.Name, requiredArg.Name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, foundArgs := range foundField.Arguments {
|
||||||
|
if requiredField.Arguments.ForName(foundArgs.Name) == nil && foundArgs.Type.NonNull && foundArgs.DefaultValue == nil {
|
||||||
|
return gqlerror.ErrorPosf(foundArgs.Position,
|
||||||
|
`For %s to implement %s any additional arguments on %s must be optional or have a default value but %s is required.`,
|
||||||
|
def.Name, intf.Name, foundField.Name, foundArgs.Name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isCovariant(schema *Schema, required *Type, actual *Type) bool {
|
||||||
|
if required.NonNull && !actual.NonNull {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if required.NamedType != "" {
|
||||||
|
if required.NamedType == actual.NamedType {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, pt := range schema.PossibleTypes[required.NamedType] {
|
||||||
|
if pt.Name == actual.NamedType {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if required.Elem != nil && actual.Elem == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return isCovariant(schema, required.Elem, actual.Elem)
|
||||||
|
}
|
||||||
|
|
||||||
func validateName(pos *Position, name string) *gqlerror.Error {
|
func validateName(pos *Position, name string) *gqlerror.Error {
|
||||||
if strings.HasPrefix(name, "__") {
|
if strings.HasPrefix(name, "__") {
|
||||||
return gqlerror.ErrorPosf(pos, `Name "%s" must not begin with "__", which is reserved by GraphQL introspection.`, name)
|
return gqlerror.ErrorPosf(pos, `Name "%s" must not begin with "__", which is reserved by GraphQL introspection.`, name)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isValidKind(kind DefinitionKind, valid ...DefinitionKind) bool {
|
||||||
|
for _, k := range valid {
|
||||||
|
if kind == k {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func kindList(kinds ...DefinitionKind) string {
|
||||||
|
s := make([]string, len(kinds))
|
||||||
|
for i, k := range kinds {
|
||||||
|
s[i] = string(k)
|
||||||
|
}
|
||||||
|
return strings.Join(s, ", ")
|
||||||
|
}
|
||||||
|
|||||||
247
vendor/github.com/vektah/gqlparser/validator/schema_test.yml
generated
vendored
247
vendor/github.com/vektah/gqlparser/validator/schema_test.yml
generated
vendored
@@ -89,6 +89,18 @@ object types:
|
|||||||
message: 'Name "__bar" must not begin with "__", which is reserved by GraphQL introspection.'
|
message: 'Name "__bar" must not begin with "__", which is reserved by GraphQL introspection.'
|
||||||
locations: [{line: 2, column: 7}]
|
locations: [{line: 2, column: 7}]
|
||||||
|
|
||||||
|
- name: must not allow input object as field type
|
||||||
|
input: |
|
||||||
|
input Input {
|
||||||
|
id: ID
|
||||||
|
}
|
||||||
|
type Query {
|
||||||
|
input: Input!
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
message: 'OBJECT field must be one of SCALAR, OBJECT, INTERFACE, UNION, ENUM.'
|
||||||
|
locations: [{line: 5, column: 3}]
|
||||||
|
|
||||||
interfaces:
|
interfaces:
|
||||||
- name: must exist
|
- name: must exist
|
||||||
input: |
|
input: |
|
||||||
@@ -148,6 +160,121 @@ interfaces:
|
|||||||
message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.'
|
message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.'
|
||||||
locations: [{line: 1, column: 11}]
|
locations: [{line: 1, column: 11}]
|
||||||
|
|
||||||
|
- name: must not allow input object as field type
|
||||||
|
input: |
|
||||||
|
input Input {
|
||||||
|
id: ID
|
||||||
|
}
|
||||||
|
type Query {
|
||||||
|
foo: Foo!
|
||||||
|
}
|
||||||
|
interface Foo {
|
||||||
|
input: Input!
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
message: 'INTERFACE field must be one of SCALAR, OBJECT, INTERFACE, UNION, ENUM.'
|
||||||
|
locations: [{line: 8, column: 3}]
|
||||||
|
|
||||||
|
- name: must have all fields from interface
|
||||||
|
input: |
|
||||||
|
type Bar implements BarInterface {
|
||||||
|
someField: Int!
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BarInterface {
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
message: 'For Bar to implement BarInterface it must have a field called id.'
|
||||||
|
locations: [{line: 1, column: 6}]
|
||||||
|
|
||||||
|
- name: must have same type of fields
|
||||||
|
input: |
|
||||||
|
type Bar implements BarInterface {
|
||||||
|
id: Int!
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BarInterface {
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
message: 'For Bar to implement BarInterface the field id must have type ID!.'
|
||||||
|
locations: [{line: 2, column: 5}]
|
||||||
|
|
||||||
|
- name: must have all required arguments
|
||||||
|
input: |
|
||||||
|
type Bar implements BarInterface {
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BarInterface {
|
||||||
|
id(ff: Int!): ID!
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
message: 'For Bar to implement BarInterface the field id must have the same arguments but it is missing ff.'
|
||||||
|
locations: [{line: 2, column: 5}]
|
||||||
|
|
||||||
|
- name: must have same argument types
|
||||||
|
input: |
|
||||||
|
type Bar implements BarInterface {
|
||||||
|
id(ff: ID!): ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BarInterface {
|
||||||
|
id(ff: Int!): ID!
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
message: 'For Bar to implement BarInterface the field id must have the same arguments but ff has the wrong type.'
|
||||||
|
locations: [{line: 2, column: 8}]
|
||||||
|
|
||||||
|
- name: may defined additional nullable arguments
|
||||||
|
input: |
|
||||||
|
type Bar implements BarInterface {
|
||||||
|
id(opt: Int): ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BarInterface {
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: may defined additional required arguments with defaults
|
||||||
|
input: |
|
||||||
|
type Bar implements BarInterface {
|
||||||
|
id(opt: Int! = 1): ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BarInterface {
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: must not define additional required arguments without defaults
|
||||||
|
input: |
|
||||||
|
type Bar implements BarInterface {
|
||||||
|
id(opt: Int!): ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BarInterface {
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
message: 'For Bar to implement BarInterface any additional arguments on id must be optional or have a default value but opt is required.'
|
||||||
|
locations: [{line: 2, column: 8}]
|
||||||
|
|
||||||
|
- name: can have covariant argument types
|
||||||
|
input: |
|
||||||
|
union U = A|B
|
||||||
|
|
||||||
|
type A { name: String }
|
||||||
|
type B { name: String }
|
||||||
|
|
||||||
|
type Bar implements BarInterface {
|
||||||
|
f: A!
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BarInterface {
|
||||||
|
f: U!
|
||||||
|
}
|
||||||
|
|
||||||
inputs:
|
inputs:
|
||||||
- name: must define one or more input fields
|
- name: must define one or more input fields
|
||||||
input: |
|
input: |
|
||||||
@@ -177,6 +304,70 @@ inputs:
|
|||||||
message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.'
|
message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.'
|
||||||
locations: [{line: 1, column: 7}]
|
locations: [{line: 1, column: 7}]
|
||||||
|
|
||||||
|
- name: fields cannot be Objects
|
||||||
|
input: |
|
||||||
|
type Object { id: ID }
|
||||||
|
input Foo { a: Object! }
|
||||||
|
error:
|
||||||
|
message: INPUT_OBJECT field must be one of SCALAR, ENUM, INPUT_OBJECT.
|
||||||
|
locations: [{line: 2, column: 13}]
|
||||||
|
|
||||||
|
- name: fields cannot be Interfaces
|
||||||
|
input: |
|
||||||
|
interface Interface { id: ID! }
|
||||||
|
input Foo { a: Interface! }
|
||||||
|
error:
|
||||||
|
message: INPUT_OBJECT field must be one of SCALAR, ENUM, INPUT_OBJECT.
|
||||||
|
locations: [{line: 2, column: 13}]
|
||||||
|
|
||||||
|
- name: fields cannot be Unions
|
||||||
|
input: |
|
||||||
|
type Object { id: ID }
|
||||||
|
union Union = Object
|
||||||
|
input Foo { a: Union! }
|
||||||
|
error:
|
||||||
|
message: INPUT_OBJECT field must be one of SCALAR, ENUM, INPUT_OBJECT.
|
||||||
|
locations: [{line: 3, column: 13}]
|
||||||
|
|
||||||
|
args:
|
||||||
|
- name: Valid arg types
|
||||||
|
input: |
|
||||||
|
input Input { id: ID }
|
||||||
|
enum Enum { A }
|
||||||
|
scalar Scalar
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
f(a: Input, b: Scalar, c: Enum): Boolean!
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Objects not allowed
|
||||||
|
input: |
|
||||||
|
type Object { id: ID }
|
||||||
|
type Query { f(a: Object): Boolean! }
|
||||||
|
|
||||||
|
error:
|
||||||
|
message: 'cannot use Object as argument a because OBJECT is not a valid input type'
|
||||||
|
locations: [{line: 2, column: 16}]
|
||||||
|
|
||||||
|
- name: Union not allowed
|
||||||
|
input: |
|
||||||
|
type Object { id: ID }
|
||||||
|
union Union = Object
|
||||||
|
type Query { f(a: Union): Boolean! }
|
||||||
|
|
||||||
|
error:
|
||||||
|
message: 'cannot use Union as argument a because UNION is not a valid input type'
|
||||||
|
locations: [{line: 3, column: 16}]
|
||||||
|
|
||||||
|
- name: Interface not allowed
|
||||||
|
input: |
|
||||||
|
interface Interface { id: ID }
|
||||||
|
type Query { f(a: Interface): Boolean! }
|
||||||
|
|
||||||
|
error:
|
||||||
|
message: 'cannot use Interface as argument a because INTERFACE is not a valid input type'
|
||||||
|
locations: [{line: 2, column: 16}]
|
||||||
|
|
||||||
enums:
|
enums:
|
||||||
- name: must define one or more unique enum values
|
- name: must define one or more unique enum values
|
||||||
input: |
|
input: |
|
||||||
@@ -207,6 +398,26 @@ enums:
|
|||||||
message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.'
|
message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.'
|
||||||
locations: [{line: 1, column: 6}]
|
locations: [{line: 1, column: 6}]
|
||||||
|
|
||||||
|
unions:
|
||||||
|
- name: union types must be defined
|
||||||
|
input: |
|
||||||
|
union Foo = Bar | Baz
|
||||||
|
type Bar {
|
||||||
|
id: ID
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
message: "Undefined type \"Baz\"."
|
||||||
|
locations: [{line: 1, column: 7}]
|
||||||
|
- name: union types must be objects
|
||||||
|
input: |
|
||||||
|
union Foo = Baz
|
||||||
|
interface Baz {
|
||||||
|
id: ID
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
message: "UNION type \"Baz\" must be OBJECT."
|
||||||
|
locations: [{line: 1, column: 7}]
|
||||||
|
|
||||||
type extensions:
|
type extensions:
|
||||||
- name: cannot extend non existant types
|
- name: cannot extend non existant types
|
||||||
input: |
|
input: |
|
||||||
@@ -258,6 +469,42 @@ directives:
|
|||||||
message: 'Name "__A" must not begin with "__", which is reserved by GraphQL introspection.'
|
message: 'Name "__A" must not begin with "__", which is reserved by GraphQL introspection.'
|
||||||
locations: [{line: 1, column: 12}]
|
locations: [{line: 1, column: 12}]
|
||||||
|
|
||||||
|
- name: Valid arg types
|
||||||
|
input: |
|
||||||
|
input Input { id: ID }
|
||||||
|
enum Enum { A }
|
||||||
|
scalar Scalar
|
||||||
|
|
||||||
|
directive @A(a: Input, b: Scalar, c: Enum) on FIELD_DEFINITION
|
||||||
|
|
||||||
|
- name: Objects not allowed
|
||||||
|
input: |
|
||||||
|
type Object { id: ID }
|
||||||
|
directive @A(a: Object) on FIELD_DEFINITION
|
||||||
|
|
||||||
|
error:
|
||||||
|
message: 'cannot use Object as argument a because OBJECT is not a valid input type'
|
||||||
|
locations: [{line: 2, column: 14}]
|
||||||
|
|
||||||
|
- name: Union not allowed
|
||||||
|
input: |
|
||||||
|
type Object { id: ID }
|
||||||
|
union Union = Object
|
||||||
|
directive @A(a: Union) on FIELD_DEFINITION
|
||||||
|
|
||||||
|
error:
|
||||||
|
message: 'cannot use Union as argument a because UNION is not a valid input type'
|
||||||
|
locations: [{line: 3, column: 14}]
|
||||||
|
|
||||||
|
- name: Interface not allowed
|
||||||
|
input: |
|
||||||
|
interface Interface { id: ID }
|
||||||
|
directive @A(a: Interface) on FIELD_DEFINITION
|
||||||
|
|
||||||
|
error:
|
||||||
|
message: 'cannot use Interface as argument a because INTERFACE is not a valid input type'
|
||||||
|
locations: [{line: 2, column: 14}]
|
||||||
|
|
||||||
entry points:
|
entry points:
|
||||||
- name: multiple schema entry points
|
- name: multiple schema entry points
|
||||||
input: |
|
input: |
|
||||||
|
|||||||
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@@ -1,4 +1,4 @@
|
|||||||
# github.com/99designs/gqlgen v0.4.5-0.20190127090136-055fb4bc9a6a
|
# github.com/99designs/gqlgen v0.8.2
|
||||||
github.com/99designs/gqlgen/handler
|
github.com/99designs/gqlgen/handler
|
||||||
github.com/99designs/gqlgen/graphql
|
github.com/99designs/gqlgen/graphql
|
||||||
github.com/99designs/gqlgen/graphql/introspection
|
github.com/99designs/gqlgen/graphql/introspection
|
||||||
@@ -124,7 +124,7 @@ github.com/spf13/jwalterweatherman
|
|||||||
github.com/spf13/pflag
|
github.com/spf13/pflag
|
||||||
# github.com/spf13/viper v1.3.2
|
# github.com/spf13/viper v1.3.2
|
||||||
github.com/spf13/viper
|
github.com/spf13/viper
|
||||||
# github.com/vektah/gqlparser v1.1.0
|
# github.com/vektah/gqlparser v1.1.2
|
||||||
github.com/vektah/gqlparser
|
github.com/vektah/gqlparser
|
||||||
github.com/vektah/gqlparser/ast
|
github.com/vektah/gqlparser/ast
|
||||||
github.com/vektah/gqlparser/gqlerror
|
github.com/vektah/gqlparser/gqlerror
|
||||||
|
|||||||
Reference in New Issue
Block a user