Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schemas for content directory #644

Closed
bedeho opened this issue Jun 9, 2020 · 0 comments
Closed

Schemas for content directory #644

bedeho opened this issue Jun 9, 2020 · 0 comments

Comments

@bedeho
Copy link
Member

bedeho commented Jun 9, 2020

# This needs to be lifted out into other schemas
type Block @entity {

  id: ID!

  blockHeight: BigInteger!

  timeStamp: BigInteger!
}

enum PropertyType {
    Bool
    Uint16
    Uint32
    Uint64
    Int16
    Int32
    Int64
    Text
    Reference
    VecBool
    VecUint16
    VecUint32
    VecUint64
    VecInt16
    VecInt32
    VecInt64
    VecText
    VecReference

}

type Property @entity {

  id: ID!

  # Runtime identifier for property in class
  propertyID: BigInteger!

  # ====================================

  # The next four fields flatten representation of property type and permissions

  # Type of property
  propertyType: PropertyType!

  # Upper bound for vector length when property is a vector.
  lengthIfVec: BigInteger

  # What class which must be references when property is a reference.
  mustReferenceClassWhenReference: Class

  # Owner of referenced entity must be the same as source when property is a reference.
  mustBeSameControllerWhenReferenceType: Boolean

  # ====================================

  # If property value can be skipped, when adding entity schema support
  required: Boolean!

  # Used to enforce uniqeness of a property across all entities that have this property
  unique: Boolean!

  # Name of property
  name: String!

  # Description of property
  description: String!

  # Property is locked from maintainer
  isLockedFromMaintainer: Boolean!

  # Property is locked from controller
  isLockedFromController: Boolean!

  # Schemas which involve this property
  schemas: [Schema!] @derivedFrom(field: "properties")

}

type Schema @entity {

  id: ID!

  # Runtime identifier of schema in class
  schemaId: BigInteger!

  # Class to which this schema corresponds
  class: Class!

  # Properties of class that are in this schema
  properties: [Property!]

  # If schema can be added to an entity
  isActive: Boolean!

}

type Class @entity {

  id: ID!

  # Runtime identifier for class
  classId: BigInteger!

  # All properties that have been used on this class across different class schemas.
  properties: [Property!]

  # All schemas that are available for this class, think v0.0 Person, v.1.0 Person, etc.
  schemas: [Schema!]

  # Name of class
  name: String!

  # Description of class
  description: String!

  # The maximum number of entities which can be created.
  maximumEntitiesCount: BigInteger!

  # The current number of entities which exist.
  currentNumberOfEntities: BigInteger!

  # How many entities a given controller may create at most.
  defaultEntityCreationVoucherUpperBound: BigInteger!

  # For this permission, the individual member is allowed to create the entity and become controller.
  anyMemberCanCreate: bool

  # Whether to prevent everyone from creating an entity
  entityCreationBlocked: Boolean!

  # Whether to prevent everyone from updating entity properties.
  allEntityPropertyValuesLocked: Boolean!

  # Current class maintainer curator groups
  maintainers: [CuratorGroup!]e

  # All vouchers for this class
  vouchers: [EntityCreationVoucher!] @derivedFrom(field: "class")

}

type PropertyValue @entity {

  id: ID!

  # Runtime identifier of property value in entity
  propertyValueID: BigInteger!

  # Property to which this value corresponds
  property: Property!

  #########################

  # The next fields encode a flattened representation of non-vector properties,
  # only one of the below will be non-null.

  bool: Boolean

  integer: BigInteger

  text: Bytes

  reference: Entity

  #########################

  # The next fields encode a flattened representation of vector properties,
  # only one of the below will be non-null.

  boolVec: [Boolean!]

  intVec: [BigInteger!]

  textVec: [Bytes!]

  referenceVec: [Entity!]

  nonce: BigInteger!
}

enum EntityControllerType {
  Lead
  Member
  Maintainer
}

type EntityController @entity {

  id: ID!

  # Current controller, which is initially set based on who created entity
  controllerType: EntityControllerType!

  # The member which is the controller if its a member
  controllerWhenMember: Member

  # TODO!
  # Add reverse lookup for events
}

type Entity @entity {

  id: ID!

  # Runtime identifier for entity
  entityID: BigInteger!

  # Controls this entity
  controller: EntityController!

  # Forbid groups to mutate any property value.
  isFrozen: Boolean!

  # Prevent from being referenced by any entity (including self-references)
  referenceable: Boolean!

  # The class of this entity
  class: Class!

  # What schemas under which this entity of a class is available
  supportedSchemas: [Schema!]

  # Values for properties on class that are used by some schema used by this entity!
  values: [PropertyValue!]

  # Total number of inbound references from another entities
  totalNumberOfInboundRefernces: BigInteger!

  # Number of inbound references from another entities with `SameOwner` flag set
  sameOwnerInboundReferences: BigInteger!

  # TODO!
  # Add reverse lookup for events
}

# Actors
##################


# Instance is created when worker is added to curator fr
type Curator @entity {

  id: ID!

  # UNIQUE
  worker: Worker!


  groups:

  # TODO!
  events: [ContentDirectoryEvent!]

}

# Should be created whenver lead is added to corresponding working group
type CurationLead @entity {

  id: ID!

  # UNIQUE
  workingGroupLead: Lead! # This Lead is not defined in this schema

  events: [ContentDirectoryEvent!]


}

type CuratorGroup @entity {

  id: ID!

  # Runtime identifier for group
  groupId: BigInteger!

  # Whether group is removed
  isRemoved: Boolean!

  # Activity stats of group
  isActive: Boolean!

  # All member curators of this group
  curators: [Curator!]

  # All classes this group maintains
  maintainerOfClasses: [Class!] @derivedFrom(field: "maintainers")

  # TODO!
  # Add reverse lookup for events

}

type EntityCreationVoucher @entity {

  id: ID!

  # Class to which voucher applies
  class: Class!

  # Controller to which this voucher applies
  controller: EntityController!

  # How many are allowed in total
  maximumEntitiesCount: BigInteger!

  # How many have currently been created
  entitiesCreated: BigInteger!

}



# TODO

# 1. fix events <== reverse lookup event & itnerfaces

# 2. add curator concept again ... remove all workers.
# 4.
# 3. full text search! <== we may need to introduce specific types.
# 5. Contne dir types: mutiple sources, data objects, platlform content, et.




interface ContentDirectoryEvent {

  id: ID!

  blockHeight: BigInteger!

}

# Event only generated by lead actions
interface ContentDirectoryLeadEvent {

  id: ID!

  blockHeight: BigInteger!

  CurationLead: CurationLead!

}

# Event generated by actions open to any actor
interface ContentDirectoryActorEvent {

  id: ID!

  actor: Actor!

  blockHeight: BigInteger!

}

type CuratorGroupAdded @entity {

  id: ID!

  # Added group
  curatorGroup: CuratorGroup!
}

type CuratorGroupRemoved @entity {

  id: ID!

  # Removed group
  curatorGroup: CuratorGroup!
}

type CuratorGroupStatusSet @entity {

  id: ID!

  # Group whos status is set
  curatorGroup: CuratorGroup!

  # New activity status
  isActive: Boolean!
}

type CuratorAdded @entity {

  id: ID!

  # Group to which curator is added
  curatorGroup: CuratorGroup!

  # Worker as curator
  worker: Worker!
}

type CuratorRemoved @entity {

  id: ID!

  # Group from which curator is removed
  curatorGroup: CuratorGroup!

  # Worker as curator
  worker: Worker!
}

type MaintainerAdded @entity {

  id: ID!

  # Class to which maintainer is added
  class: Class!

  # Group added as maintainer
  curatorGroup: CuratorGroup!
}

type MaintainerRemoved @entity {

  id: ID!

  # Class from which maintainer is removed
  class: Class!

  # Group from which maintainer is removed
  curatorGroup: CuratorGroup!
}

type EntityCreationVoucherUpdated @entity {

  id: ID!

  (EntityController, EntityCreationVoucher),
}

type EntityCreationVoucherCreated @entity {

  id: ID!

  (EntityController, EntityCreationVoucher),
}

type ClassCreated @entity {

  id: ID!

  # Created class
  class: Class!
}

type ClassPermissionsUpdated @entity {

  id: ID!

  # Created class
  class: Class!

  # When set is new value of Class.anyMemberCanCreate
  updatedAnyMemberCanCreate: Boolean

  # When set is new value of Class.entityCreationBlocked
  updatedEntityCreationBlocked: Boolean

  # When set is new value of Class.maintainers
  updatedAllEntityPropertyValuesLocked: Boolean

  # New set of curator groups set as maintainers
  updatedMaintainers: [CuratorGroup!]

}

type ClassSchemaAdded @entity {

  id: ID!

  # ...
  class: Class!

  # ...
  existingProperties: [Property!]

  # ...
  newProperties: [Property!]

  # ...
  newSchema: Schema!

}

type ClassSchemaStatusUpdated @entity {

  id: ID!

  # ...
  class: Class!

  # ...
  schema: Schema!

  # ...
  newStatus: Boolean!

}

type EntityPermissionsUpdated @entity {

  # ...
  entity: Entity!

  # ...
  updatedFrozenForController: Boolean

  # ...
  updatedReferenceable: Boolean

}

enum ActorType {
  CuratorGroupMember
  Member
  Lead
}

type Actor @entity {

  id: ID!

  # The type of actor
  type: ActorType

  # The curator group and actual curator when the actor type is `ActorType.CuratorGroup`
  groupWhenCuratorGroupMember: CuratorGroup
  curatorWhenCuratorGroupMember: Curator

  # The member when the actor type is `ActorType.Member`
  member: Member

  # The lead when the actor type is `ActorType.Lead`
  lead: CurationLead

}

type EntityCreated @entity {

  id: ID!

  # ...
  actor: Actor!

  # ...
  class: Class!

  # ...s
  entity: Entity!

}

type EntityRemoved @entity {

  id: ID!

  # ...
  actor: Actor!

  # ...
  entityID: BigInteger!

  # other side-effects?

}

type EntitySchemaSupportAdded @entity {

  id: ID!

  # ...
  actor: Actor!

  # ...
  entity: Entity!

  # ...
  schema: Schema!

  # Values provided by caller
  propertyValues: [PropertyValue!]

  # other side-effects?

}

type EntityPropertyValuesUpdated @entity {

  id: ID!

  # ...
  actor: Actor!

  # ...
  entity: Entity!

  # Values provided by caller
  newPropertyValues: [PropertyValue!]

  # other side-effects?

}

type EntityPropertyValueVectorCleared @entity {

  id: ID!

  # ...
  actor: Actor!

  # ...
  entity: Entity!

  # Property cleared
  property: Property!

  # other side-effects?

}

type RemovedAtEntityPropertyValueVectorIndex @entity {

  id: ID!

  actor: Actor!




  (Actor, EntityId, PropertyId, VecMaxLength, Nonce),

  actor: Actor<T>,

  entity_id: T::EntityId,

  in_class_schema_property_id: PropertyId,

  index_in_property_vec: VecMaxLength,

  nonce: T::Nonce


  # other side-effects?
}

type InsertedAtEntityPropertyValueVectorIndex @entity {

  id: ID!

  actor: Actor!





  (Actor, EntityId, PropertyId, VecMaxLength, Nonce),

  actor: Actor<T>,

  entity_id: T::EntityId,

  in_class_schema_property_id: PropertyId,

  index_in_property_vec: VecMaxLength,

  # singlePropertyValue: SinglePropertyValue<T>,

  nonce: T::Nonce

  # other side-effects?
}

type TransactionCompleted @entity {

  id: ID!

  actor: Actor!

  # operations: Vec<OperationType<T>>

  # other side-effects?

}

type EntityOwnershipTransfered @entity {

  id: ID!

  (EntityId, EntityController),

  entity_id: T::EntityId,

  new_controller: EntityController<T>,


  # other side-effects?
}

# High level derivative entities
###########

# TODO

# 3. full text search! <== we may need to introduce specific types.
# 5. Contne dir types: mutiple sources, data objects, platlform content, et.

# What is apparent in the schemas below is that, its not possible to define effective full text search on the bare bones representations found.
# For example, to support doing a full text search over videos

# Observation: follower # and other things dont live in chain...

# Recommendations (not sure if they come from API)
#

enum Language {
  Chinese
  English
  Arabic
  Portugese
  French
  # ...
}

type Channel @entity {

  id: ID!

  # Id of underlying entity.
  entityID: BigInteger!

  owner: Member!

  handle: String! @unique @fulltext(query: "universal_search")

  description: String!

  coverPhotoURL: String!

  avatarPhotoURL: String!

  language: Language

  videos: [Video!] @derivedFrom(field: "channel")

  series: [Series!] @derivedFrom(field: "channel")

  playlists: [Playlist!] @derivedFrom(field: "channel")
}

type Category @entity {

  id: ID!

  # Id of underlying entity.
  entityID: BigInteger!

  name: String! @unique

  videos: [Video!] @derivedFrom(field: "channel")

  series: [Series!] @derivedFrom(field: "channel")

  playlists: [Playlist!] @derivedFrom(field: "channel")
}

type JoystreamVideoMediaLocation @variant {
  dataObjectID: BigInteger!
}

type HTTPVideoMediaLocation @variant {
  host: String!
  port: Int
}

# In the future we can add IPFS, Dat, etc.
union MediaLocation = JoystreamMediaLocation | HTTPMediaLocation

# Mixed both encoding and containers, only having popular combos, may need to be changed later.
enum VideoMediaEncoding {
  H264_mpeg4
  VP8_WEBM
  Theroa_Vorbis
}

# Apparently there are lots of different Creative Commons licenses,
# read about all here https://creativecommons.org/licenses/,
# I haven't had the time.
enum CreativeCommonsVersion {
  CC_BY
  CC_BY_SA
  CC_BY_ND
  CC_BY_NC
  CC_BY_NC_SA
  CC_BY_NC_ND
}

type CreativeCommonsLicense @variant {
  version:
}

type UserDefinedLicense @variant {
  text: String!
}

union License = UserDefinedLicense | CreativeCommonsLicense

type VideoMedia @entity {

  id: ID!

  # Id of underlying entity.
  entityID: BigInteger!

  encoding: VideoMediaEncoding!

  # Resolution width
  pixelWidth: Int!

  # Resolution height
  pixelHeight: Int!

  # Size in bytes
  size: BigInteger

  # where to find
  location: MediaLocation!
}

type Video @entity {

  id: ID!

  # Id of underlying entity.
  entityID: BigInteger!

  channel: Channel!

  category: Category!

  title: String! @fulltext(query: "universal_search")

  description: String! @fulltext(query: "universal_search")

  # In seconds
  duration: Int!

  # In intro
  skippableIntroDuration: Int

  thumbnailURL: String!

  Language: Language

  media: VideoMedia!

  hasMarketing: Boolean

  # Timestamp of block
  publishedOnJoystreamInBlock: Block!

  # Possible time when video was published before Joystream
  publishedBeforeJoystream: DateTime

  isPublic: Bool!

  isCurated: Boolean!

  isExplicit: Boolean!

  license: License!

  inPlayLists: [VideoInPlaylistRelationship!] @derivedFrom(field: "video")

  people: [PersonRoleInVideo!] @derivedFrom(field: "video")
}

type Playlist @entity {

  id: ID!

  # Id of underlying entity.
  entityID: BigInteger!

  title: String! @fulltext(query: "universal_search")

  channel: Channel!

  category: Category!

  isPublic: Bool!

  contains: [VideoInPlaylistRelationship!] @derivedFrom(field: "playlist")
}

# We cannot use derived m-2-m relationship, because
# we want to associate number also.
type VideoInPlaylistRelationship @entity {

  id: ID!

  playlist: Playlist!

  video: Video!

  number: Int!
}

type Series @entity {

  id: ID!

  # Id of underlying entity.
  entityID: BigInteger!

  name: String! @fulltext(query: "universal_search")

  channel: Channel!

  category: Category!

  seasons: [SeriesSeason!] @derivedFrom(field: "channel")

  # what people person are associated with this episode

}

type SeriesSeason @entity {

  id: ID!

  # Id of underlying entity.
  entityID: BigInteger!

  series: Series!

  episodes: [SeriesEpisode] @derivedFrom(field: "channel")

  seasonNumberInSeries: Integer!

  # other stuff about when published?
}

type SeriesEpisode @entity {

  id: ID!

  # Id of underlying entity.
  entityID: BigInteger!

  seriesSeason: SeriesSeason!

  episodeNumberInSeason: Integer!

  title: String! @fulltext(query: "universal_search")

  # what people person are associated with this episode
}

type Person @entity {

  id: ID!

  # Id of underlying entity.
  entityID: BigInteger!

  fullName: String! @fulltext(query: "universal_search")

  born: DateTime

  died: DateTime

  bio: String!
}

#
#
# type VideoContent @variant {
#   video: Video!
# }
#
# type SeriesContent @variant {
#   series: Series!
# }
#
# type SeriesEpisodeContent @variant {
#   seriesEpisode: SeriesEpisodeContent!
# }
#
# union Content = VideoContent | SeriesContent | SeriesEpisodeContent
#

type PersonRoleInVideo @entity {

  id: ID!

  # Id of underlying entity.
  entityID: BigInteger!

  person: Person!

  video: Video!

  # Requires reference types in algebraic types
  # content: Content!

  name: String!

  description: String
}

# Note: it would be nice to have high level events as well, but how will it work

interface Event {

  id: ID!

  inBlock: Block!
}

# Events
# These are just examples, later we add
# full set of events for channels, videoes, series, series episodes, personaes, etc.

type ChannelCreatedEvent @entity implement Event {

  id: ID!

  inBlock: Block!

  channel: Channel!
}

type VideoAddedToChannel @entity implement Event {

  id: ID!

  inBlock: Block!

  video: Video!
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant