
      
scalar DateTime

scalar EmailAddress

scalar BigInt

scalar JSONObject


      directive @hasScope(scope: String!) on FIELD_DEFINITION
      directive @hasRole(role: String!) on FIELD_DEFINITION

      type Query {
      """
      Stare into the void.
      """
        _: String
      }
      type Mutation{
      """
      The void stares back.
      """
      _: String
      }
      type Subscription{
        """
        It's lonely in the void.
        """
        _: String
      },extend type Query {
  """
  Gets a specific app from the server.
  """
  app( id: String! ): ServerApp

  """
  Returns all the publicly available apps on this server.
  """
  apps: [ServerAppListItem]
}

type ServerApp {
  id: String!
  secret: String!
  name: String!
  description: String
  termsAndConditionsLink: String
  logo: String
  public: Boolean
  trustByDefault: Boolean
  author: AppAuthor
  createdAt: DateTime!
  redirectUrl: String!
  scopes: [Scope]!
}

type ServerAppListItem {
  id: String!
  name: String!
  description: String
  termsAndConditionsLink: String
  logo: String
  author: AppAuthor
}

type AppAuthor {
  name: String
  id: String
}

extend type User {
  """
  Returns the apps you have authorized.
  """
  authorizedApps: [ServerAppListItem]
    @hasRole(role: "server:user")
    @hasScope(scope: "apps:read")

  """
  Returns the apps you have created.
  """
  createdApps: [ServerAppListItem]
    @hasRole(role: "server:user")
    @hasScope(scope: "apps:read")
}

extend type Mutation {
  """
  Register a new third party application.
  """
  appCreate(app: AppCreateInput!): String!
    @hasRole(role: "server:user")
    @hasScope(scope: "apps:write")

  """
  Update an existing third party application. **Note: This will invalidate all existing tokens, refresh tokens and access codes and will require existing users to re-authorize it.**
  """
  appUpdate(app: AppUpdateInput!): Boolean!
    @hasRole(role: "server:user")
    @hasScope(scope: "apps:write")

  """
  Deletes a thirty party application.
  """
  appDelete(appId: String!): Boolean!
    @hasRole(role: "server:user")
    @hasScope(scope: "apps:write")

  """
  Revokes (de-authorizes) an application that you have previously authorized.
  """
  appRevokeAccess(appId: String!): Boolean
    @hasRole(role: "server:user")
    @hasScope(scope: "apps:write")

}

input AppCreateInput {
  name: String!
  description: String!
  termsAndConditionsLink: String
  logo: String
  public: Boolean
  redirectUrl: String!
  scopes: [String]!
}

input AppUpdateInput {
  id: String!
  name: String!
  description: String!
  termsAndConditionsLink: String
  logo: String
  public: Boolean
  redirectUrl: String!
  scopes: [String]!
}
,extend type ServerInfo {
  """
  The authentication strategies available on this server.
  """
  authStrategies: [AuthStrategy]
}

type AuthStrategy {
  id: String!,
  name: String!,
  icon: String!,
  url: String!,
  color: String
}
,extend type User{
  """
  Returns a list of your personal api tokens.
  """
  apiTokens: [ApiToken]
    @hasRole(role: "server:user")
    @hasScope(scope: "tokens:read")
}

type ApiToken {
  id: String!
  name: String!
  lastChars: String!
  scopes: [String]!
  createdAt: DateTime! #date
  lifespan: BigInt!
  lastUsed: String! #date
}

input ApiTokenCreateInput {
  scopes: [String!]!,
  name: String!,
  lifespan: BigInt
}

extend type Mutation {
  """
  Creates an personal api token.
  """
  apiTokenCreate(token: ApiTokenCreateInput!):String!
    @hasRole(role: "server:user")
    @hasScope(scope: "tokens:write")
  """
  Revokes (deletes) an personal api token.
  """
  apiTokenRevoke(token: String!):Boolean!
    @hasRole(role: "server:user")
    @hasScope(scope: "tokens:write")
}
,extend type Stream {
  commits(limit: Int! = 25, cursor: String): CommitCollection
  commit(id: String!): Commit
  branches(limit: Int! = 25, cursor: String): BranchCollection
  branch(name: String!): Branch
}

extend type User {
  commits(limit: Int! = 25, cursor: String): CommitCollectionUser
}

type Branch {
  id: String!
  name: String!
  author: User!
  description: String
  commits(limit: Int! = 25, cursor: String): CommitCollection
}

type Commit {
  id: String!
  referencedObject: String!
  message: String
  authorName: String
  authorId: String
  createdAt: DateTime
}

type CommitCollectionUserNode {
  id: String!
  referencedObject: String!
  message: String
  streamId: String
  streamName: String
  createdAt: DateTime
}

type BranchCollection {
  totalCount: Int!
  cursor: String
  items: [Branch]
}

type CommitCollection {
  totalCount: Int!
  cursor: String
  items: [Commit]
}

type CommitCollectionUser {
  totalCount: Int!
  cursor: String
  items: [CommitCollectionUserNode]
}

extend type Mutation {
  branchCreate(branch: BranchCreateInput!): String!
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:write")
  branchUpdate(branch: BranchUpdateInput!): Boolean!
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:write")
  branchDelete(branch: BranchDeleteInput!): Boolean!
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:write")

  commitCreate(commit: CommitCreateInput!): String!
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:write")
  commitUpdate(commit: CommitUpdateInput!): Boolean!
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:write")
  commitDelete(commit: CommitDeleteInput!): Boolean!
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:write")
}

extend type Subscription {
  # TODO: auth for these subscriptions
  """
  Subscribe to branch created event
  """
  branchCreated(streamId: String!): JSONObject
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:read")
  """
  Subscribe to branch updated event.
  """
  branchUpdated(streamId: String!, branchId: String): JSONObject
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:read")
  """
  Subscribe to branch deleted event
  """
  branchDeleted(streamId: String!): JSONObject
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:read")

  """
  Subscribe to commit created event
  """
  commitCreated(streamId: String!): JSONObject
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:read")
  """
  Subscribe to commit updated event.
  """
  commitUpdated(streamId: String!, commitId: String): JSONObject
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:read")
  """
  Subscribe to commit deleted event
  """
  commitDeleted(streamId: String!): JSONObject
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:read")
}

input BranchCreateInput {
  streamId: String!
  name: String!
  description: String
}

input BranchUpdateInput {
  streamId: String!
  id: String!
  name: String
  description: String
}

input BranchDeleteInput {
  streamId: String!
  id: String!
}

input CommitCreateInput {
  streamId: String!
  branchName: String!
  objectId: String!
  message: String
  previousCommitIds: [String]
}

input CommitUpdateInput {
  streamId: String!
  id: String!
  message: String!
}

input CommitDeleteInput {
  streamId: String!
  id: String!
}
,extend type Stream {
  object( id: String! ): Object
}

type Object {
  id: String! 
  speckleType: String!
  applicationId: String
  createdAt: DateTime
  totalChildrenCount: Int
  """
  The full object, with all its props & other things. **NOTE:** If you're requesting objects for the purpose of recreating & displaying, you probably only want to request this specific field.
  """
  data: JSONObject
  """
  Get any objects that this object references. In the case of commits, this will give you a commit's constituent objects.
  **NOTE**: Providing any of the two last arguments ( `query`, `orderBy` ) will trigger a different code branch that executes a much more expensive SQL query. It is not recommended to do so for basic clients that are interested in purely getting all the objects of a given commit.
  """
  children(
    limit: Int! = 100, 
    depth: Int! = 50, 
    select: [String], 
    cursor: String, 
    query: [JSONObject!],
    orderBy: JSONObject  ): ObjectCollection!
}

type ObjectCollection {
  totalCount: Int!
  cursor: String
  objects: [Object]!
}

extend type Mutation {
  objectCreate( objectInput: ObjectCreateInput! ): [String]!
}

input ObjectCreateInput {
  """
  The stream against which these objects will be created. 
  """
  streamId: String!
  """
  The objects you want to create.
  """
  objects: [JSONObject]!
},extend type Query {
  serverInfo: ServerInfo!
}

"""
Information about this server.
"""
type ServerInfo {
  name: String!
  company: String
  description: String
  adminContact: String
  canonicalUrl: String
  termsOfService: String
  roles: [Role]!
  scopes: [Scope]!
}

"""
Available roles.
"""
type Role {
  name: String!
  description: String!
  resourceTarget: String!
}

"""
Available scopes.
"""
type Scope {
  name: String!
  description: String!
}

extend type Mutation {
  serverInfoUpdate(info: ServerInfoUpdateInput!): Boolean
    @hasRole(role: "server:admin")
    @hasScope(scope: "server:setup")
}

input ServerInfoUpdateInput {
  name: String!
  company: String
  description: String
  adminContact: String
  termsOfService: String
}
,extend type Query {
  """
  Returns a specific stream.
  """
  stream( id: String! ): Stream

  """
  All the streams of the current user, pass in the `query` parameter to seach by name, description or ID.
  """
  streams( query: String, limit: Int = 25, cursor: String ): StreamCollection
    @hasScope(scope: "streams:read")
}

type Stream {
  id: String!
  name: String!
  description: String
  isPublic: Boolean!
  createdAt: DateTime!
  updatedAt: DateTime!
  collaborators: [ StreamCollaborator ]!
}

extend type User {
  """
  All the streams that a user has access to.
  """
  streams( limit: Int! = 25, cursor: String ): StreamCollection
}

type StreamCollaborator {
  id: String!
  name: String!
  role: String!
  company: String
  avatar: String
}

type StreamCollection {
  totalCount: Int!
  cursor: String
  items: [ Stream ]
}


extend type Mutation {
  """
  Creates a new stream.
  """
  streamCreate( stream: StreamCreateInput! ): String
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:write")
  """
  Updates an existing stream.
  """
  streamUpdate( stream: StreamUpdateInput! ): Boolean!
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:write")
  """
  Deletes an existing stream.
  """
  streamDelete( id: String! ): Boolean!
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:write")
  """
  Grants permissions to a user on a given stream.
  """
  streamGrantPermission( permissionParams: StreamGrantPermissionInput! ): Boolean
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:write")
  """
  Revokes the permissions of a user on a given stream.
  """
  streamRevokePermission( permissionParams: StreamRevokePermissionInput! ): Boolean
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:write")
}

extend type Subscription {

  #
  # User bound subscriptions that operate on the stream collection of an user
  # Example relevant view/usecase: updating the list of streams for a user.
  #

  """
  Subscribes to new stream added event for your profile. Use this to display an up-to-date list of streams.
  **NOTE**: If someone shares a stream with you, this subscription will be triggered with an extra value of `sharedBy` in the payload.
  """
  userStreamAdded: JSONObject
    @hasRole(role: "server:user")
    @hasScope(scope: "profile:read")

  """
  Subscribes to stream removed event for your profile. Use this to display an up-to-date list of streams for your profile.
  **NOTE**: If someone revokes your permissions on a stream, this subscription will be triggered with an extra value of `revokedBy` in the payload.
  """
  userStreamRemoved: JSONObject
    @hasRole(role: "server:user")
    @hasScope(scope: "profile:read")

  #
  # Stream bound subscriptions that operate on the stream itself.
  # Example relevant view/usecase: a single stream connector, or view, or component in a web app
  #

  """
  Subscribes to stream updated event. Use this in clients/components that pertain only to this stream.
  """
  streamUpdated( streamId: String ): JSONObject
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:read")

  """
  Subscribes to stream deleted event. Use this in clients/components that pertain only to this stream.
  """
  streamDeleted( streamId: String ): JSONObject
    @hasRole(role: "server:user")
    @hasScope(scope: "streams:read")

}

input StreamCreateInput {
  name: String
  description: String
  isPublic: Boolean
}

input StreamUpdateInput {
  id: String!
  name: String
  description: String
  isPublic: Boolean
}

input StreamGrantPermissionInput {
  streamId: String!,
  userId: String!,
  role: String!
}

input StreamRevokePermissionInput {
  streamId: String!,
  userId: String!
}
,extend type Query {
  """
  Gets the profile of a user. If no id argument is provided, will return the current authenticated user's profile (as extracted from the authorization header).
  """
  user(id: String): User
  userSearch(
    query: String!
    limit: Int! = 25
    cursor: String
  ): UserSearchResultCollection
  userPwdStrength(pwd: String!): JSONObject
}

"""
Base user type.
"""
type User {
  id: String!
  suuid: String
  email: String
  name: String
  bio: String
  company: String
  avatar: String
  verified: Boolean
  profiles: JSONObject
  role: String
}

type UserSearchResultCollection {
  cursor: String
  items: [UserSearchResult]
}

type UserSearchResult {
  id: String!
  name: String
  bio: String
  company: String
  avatar: String
  verified: Boolean
}

extend type Mutation {
  """
  Edits a user's profile.
  """
  userUpdate(user: UserUpdateInput!): Boolean!
}

input UserUpdateInput {
  name: String
  company: String
  bio: String
}
