package s3browser import ( "fmt" "path/filepath" "strings" "github.com/graph-gophers/dataloader" "github.com/graphql-go/graphql" ) var graphqlDirType *graphql.Object var graphqlFileType *graphql.Object // graphqlTypes create all graphql types and stores the in the global variables func graphqlTypes() { graphqlDirType = graphql.NewObject(graphql.ObjectConfig{ Name: "Directory", Description: "Represents a directory", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.NewNonNull(graphql.ID), }, "name": &graphql.Field{ Type: graphql.String, Resolve: func(p graphql.ResolveParams) (interface{}, error) { source, ok := p.Source.(Directory) if !ok { return nil, fmt.Errorf("Failed to parse source for resolve") } return filepath.Base(source.ID), nil }, }, }, }) graphqlFileType = graphql.NewObject(graphql.ObjectConfig{ Name: "File", Description: "Represents a file, not a directory", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.NewNonNull(graphql.ID), Description: "The uniqe ID of the file. Represents the path and the s3 key.", }, "name": &graphql.Field{ Type: graphql.String, Resolve: func(p graphql.ResolveParams) (interface{}, error) { source, ok := p.Source.(File) if !ok { return nil, fmt.Errorf("Failed to parse source for resolve") } return filepath.Base(source.ID), nil }, }, "size": &graphql.Field{ Type: graphql.NewNonNull(graphql.Int), Resolve: func(p graphql.ResolveParams) (interface{}, error) { file, err := loadFile(p) if err != nil { return nil, err } return file.Size, nil }, }, "contentType": &graphql.Field{ Type: graphql.String, Resolve: func(p graphql.ResolveParams) (interface{}, error) { file, err := loadFile(p) if err != nil { return nil, err } return file.ContentType, nil }, }, "etag": &graphql.Field{ Type: graphql.String, Resolve: func(p graphql.ResolveParams) (interface{}, error) { file, err := loadFile(p) if err != nil { return nil, err } return file.ETag, nil }, }, "parent": &graphql.Field{ Type: graphqlDirType, Resolve: func(p graphql.ResolveParams) (interface{}, error) { source, ok := p.Source.(File) if !ok { return nil, fmt.Errorf("Failed to parse Source for parent resolve") } basename := filepath.Dir(source.ID) if basename == "." { basename = "/" } return Directory{ ID: basename, }, nil }, }, }, }) graphqlDirType.AddFieldConfig("files", &graphql.Field{ Type: graphql.NewList(graphqlFileType), Resolve: func(p graphql.ResolveParams) (interface{}, error) { source, ok := p.Source.(Directory) if !ok { return nil, fmt.Errorf("Failed to parse Source for files resolve") } loader := p.Context.Value("loader").(map[string]*dataloader.Loader) thunk := loader["getFiles"].Load(p.Context, dataloader.StringKey(source.ID)) return thunk() }, }) graphqlDirType.AddFieldConfig("directorys", &graphql.Field{ Type: graphql.NewList(graphqlDirType), Resolve: func(p graphql.ResolveParams) (interface{}, error) { source, ok := p.Source.(Directory) if !ok { return nil, fmt.Errorf("Failed to parse Source for directories resolve") } loader := p.Context.Value("loader").(map[string]*dataloader.Loader) thunk := loader["getDirs"].Load(p.Context, dataloader.StringKey(source.ID)) return thunk() }, }) graphqlDirType.AddFieldConfig("parent", &graphql.Field{ Type: graphqlDirType, Resolve: func(p graphql.ResolveParams) (interface{}, error) { source, ok := p.Source.(Directory) if !ok { return nil, fmt.Errorf("Failed to parse Source for directories resolve") } dirs := strings.Split(source.ID, "/") return Directory{ ID: strings.Join(dirs[:len(dirs)-2], "/") + "/", }, nil }, }) } // graphqlTypes helper func for using the dataloader to get a file func loadFile(p graphql.ResolveParams) (*File, error) { source, ok := p.Source.(File) if !ok { return nil, fmt.Errorf("Failed to parse source for resolve") } loader := p.Context.Value("loader").(map[string]*dataloader.Loader) thunk := loader["getFile"].Load(p.Context, dataloader.StringKey(source.ID)) result, err := thunk() file, ok := result.(*File) if !ok { return nil, fmt.Errorf("Failed to load file") } return file, err }