spacedrive/core/prisma/schema.prisma
Jamie Pine a253431d0f
[ENG-887] Category empty screens (#1056)
* begin

* default category ui + schema

* yes

* better light icons

* new text icon

* fix schema

* fix merge error

* fix optional

* re-export icons

* tweaks

---------

Co-authored-by: Oscar Beaumont <oscar@otbeaumont.me>
2023-08-12 16:30:03 +00:00

519 lines
14 KiB
Plaintext

datasource db {
provider = "sqlite"
url = "file:dev.db"
}
generator client {
provider = "cargo prisma"
output = "../../crates/prisma/src/prisma"
module_path = "prisma"
client_format = "folder"
}
generator sync {
provider = "cargo prisma-sync"
output = "../../crates/prisma/src/prisma_sync"
client_format = "folder"
}
//// Sync ////
model SharedOperation {
id Bytes @id
timestamp BigInt
model String
record_id Bytes
// Enum: ??
kind String
data Bytes
instance_id Int
instance Instance @relation(fields: [instance_id], references: [id])
// attestation Bytes
@@map("shared_operation")
}
model RelationOperation {
id Bytes @id
timestamp BigInt
relation String
item_id Bytes
group_id Bytes
kind String
data Bytes
instance_id Int
instance Instance @relation(fields: [instance_id], references: [id])
@@map("relation_operation")
}
/// @deprecated: This model has to exist solely for backwards compatibility.
model Node {
id Int @id @default(autoincrement())
pub_id Bytes @unique
name String
// Enum: sd_core::node::Platform
platform Int
date_created DateTime
identity Bytes? // TODO: Change to required field in future
node_peer_id String? // TODO: Remove as part of - https://linear.app/spacedriveapp/issue/ENG-757/p2p-library-portability
@@map("node")
}
/// @local(id: pub_id)
// represents a single `.db` file (SQLite DB) that is paired to the current library.
// A `LibraryInstance` is always owned by a single `Node` but it's possible for that node to change (or two to be owned by a single node).
model Instance {
id Int @id @default(autoincrement()) // This is is NOT globally unique
pub_id Bytes @unique // This UUID is meaningless and exists soley cause the `uhlc::ID` must be 16-bit. Really this should be derived from the `identity` field.
// Enum: sd_core::p2p::IdentityOrRemoteIdentity
identity Bytes
node_id Bytes
node_name String
// Enum: sd_core::node::Platform
node_platform Int
last_seen DateTime // Time core started for owner, last P2P message for P2P node
date_created DateTime
// clock timestamp for sync
timestamp BigInt?
// attestation Bytes
SharedOperation SharedOperation[]
RelationOperation RelationOperation[]
locations Location[]
@@map("instance")
}
model Statistics {
id Int @id @default(autoincrement())
date_captured DateTime @default(now())
total_object_count Int @default(0)
library_db_size String @default("0")
total_bytes_used String @default("0")
total_bytes_capacity String @default("0")
total_unique_bytes String @default("0")
total_bytes_free String @default("0")
preview_media_bytes String @default("0")
@@map("statistics")
}
/// @local
model Volume {
id Int @id @default(autoincrement())
name String
mount_point String
total_bytes_capacity String @default("0")
total_bytes_available String @default("0")
disk_type String?
filesystem String?
is_system Boolean @default(false)
date_modified DateTime @default(now())
@@unique([mount_point, name])
@@map("volume")
}
/// @shared(id: pub_id)
model Location {
id Int @id @default(autoincrement())
pub_id Bytes @unique
name String?
path String?
total_capacity Int?
available_capacity Int?
is_archived Boolean?
generate_preview_media Boolean?
sync_preview_media Boolean?
hidden Boolean?
date_created DateTime?
instance_id Int?
instance Instance? @relation(fields: [instance_id], references: [id], onDelete: SetNull)
file_paths FilePath[]
indexer_rules IndexerRulesInLocation[]
@@map("location")
}
/// @shared(id: pub_id)
model FilePath {
id Int @id @default(autoincrement())
pub_id Bytes @unique
is_dir Boolean?
// content addressable storage id - blake3 sampled checksum
cas_id String?
// full byte contents digested into blake3 checksum
integrity_checksum String?
// location that owns this path
location_id Int?
location Location? @relation(fields: [location_id], references: [id], onDelete: SetNull)
// the path of the file relative to its location
materialized_path String?
// the name and extension, MUST have 'COLLATE NOCASE' in migration
name String?
extension String?
size_in_bytes String? // deprecated
size_in_bytes_bytes Bytes?
inode Bytes? // This is actually an unsigned 64 bit integer, but we don't have this type in SQLite
device Bytes? // This is actually an unsigned 64 bit integer, but we don't have this type in SQLite
// the unique Object for this file path
object_id Int?
object Object? @relation(fields: [object_id], references: [id], onDelete: SetNull)
key_id Int? // replacement for encryption
// permissions String?
date_created DateTime?
date_modified DateTime?
date_indexed DateTime?
// key Key? @relation(fields: [key_id], references: [id])
@@unique([location_id, materialized_path, name, extension])
@@unique([location_id, inode, device])
@@index([location_id])
@@index([location_id, materialized_path])
@@map("file_path")
}
/// @shared(id: pub_id)
model Object {
id Int @id @default(autoincrement())
pub_id Bytes @unique
// Enum: sd_file_ext::kind::ObjectKind
kind Int?
key_id Int?
// handy ways to mark an object
hidden Boolean?
favorite Boolean?
important Boolean?
// if we have generated preview media for this object on at least one Node
// commented out for now by @brendonovich since they they're irrelevant to the sync system
// has_thumbnail Boolean?
// has_thumbstrip Boolean?
// has_video_preview Boolean?
// TODO: change above to:
// has_generated_thumbnail Boolean @default(false)
// has_generated_thumbstrip Boolean @default(false)
// has_generated_video_preview Boolean @default(false)
// integration with ipfs
// ipfs_id String?
// plain text note
note String?
// the original known creation date of this object
date_created DateTime?
date_accessed DateTime?
tags TagOnObject[]
labels LabelOnObject[]
albums ObjectInAlbum[]
spaces ObjectInSpace[]
file_paths FilePath[]
// comments Comment[]
media_data MediaData?
// key Key? @relation(fields: [key_id], references: [id])
@@map("object")
}
// if there is a conflicting cas_id, the conficting file should be updated to have a larger cas_id as the field is unique, however this record is kept to tell the indexer (upon discovering this CAS) that there is alternate versions of the file and to check by a full integrity hash to define for which to associate with.
// @brendan: nah this probably won't fly
// model FileConflict {
// original_object_id Int @unique
// detactched_object_id Int @unique
// @@map("file_conflict")
// }
// keys allow us to know exactly which files can be decrypted with a given key
// they can be "mounted" to a client, and then used to decrypt files automatically
/// @shared(id: uuid)
// model Key {
// id Int @id @default(autoincrement())
// // uuid to identify the key
// uuid String @unique
// version String
// key_type String
// // the name that the user sets
// name String?
// // is this key the default for encryption?
// // was not tagged as unique as i'm not too sure if PCR will handle it
// // can always be tagged as unique, the keys API will need updating to use `find_unique()`
// default Boolean @default(false)
// // nullable if concealed for security
// date_created DateTime? @default(now())
// // encryption algorithm used to encrypt the key
// algorithm String
// // hashing algorithm used for hashing the key with the content salt
// hashing_algorithm String
// // salt used for encrypting data with this key
// content_salt Bytes
// // the *encrypted* master key (48 bytes)
// master_key Bytes
// // the nonce used for encrypting the master key
// master_key_nonce Bytes
// // the nonce used for encrypting the key
// key_nonce Bytes
// // the *encrypted* key
// key Bytes
// // the salt used for deriving the KEK (used for encrypting the master key) from the root key
// salt Bytes
// automount Boolean @default(false)
// objects Object[]
// file_paths FilePath[]
// @@map("key")
// }
model MediaData {
id Int @id
pixel_width Int?
pixel_height Int?
longitude Float?
latitude Float?
fps Int?
capture_device_make String? // eg: "Apple"
capture_device_model String? // eg: "iPhone 12"
capture_device_software String? // eg: "12.1.1"
duration_seconds Int?
codecs String? // eg: "h264,acc"
streams Int?
object Object? @relation(fields: [id], references: [id], onDelete: Cascade)
@@map("media_data")
}
//// Tag ////
/// @shared(id: pub_id)
model Tag {
id Int @id @default(autoincrement())
pub_id Bytes @unique
name String?
color String?
// Enum: ??
redundancy_goal Int?
date_created DateTime?
date_modified DateTime?
tag_objects TagOnObject[]
@@map("tag")
}
/// @relation(item: tag, group: object)
model TagOnObject {
tag_id Int
tag Tag @relation(fields: [tag_id], references: [id], onDelete: Restrict)
object_id Int
object Object @relation(fields: [object_id], references: [id], onDelete: Restrict)
@@id([tag_id, object_id])
@@map("tag_on_object")
}
//// Label ////
model Label {
id Int @id @default(autoincrement())
pub_id Bytes @unique
name String?
date_created DateTime @default(now())
date_modified DateTime @default(now())
label_objects LabelOnObject[]
@@map("label")
}
model LabelOnObject {
date_created DateTime @default(now())
label_id Int
label Label @relation(fields: [label_id], references: [id], onDelete: Restrict)
object_id Int
object Object @relation(fields: [object_id], references: [id], onDelete: Restrict)
@@id([label_id, object_id])
@@map("label_on_object")
}
//// Space ////
model Space {
id Int @id @default(autoincrement())
pub_id Bytes @unique
name String?
description String?
date_created DateTime?
date_modified DateTime?
objects ObjectInSpace[]
@@map("space")
}
model ObjectInSpace {
space_id Int
space Space @relation(fields: [space_id], references: [id], onDelete: Restrict)
object_id Int
object Object @relation(fields: [object_id], references: [id], onDelete: Restrict)
@@id([space_id, object_id])
@@map("object_in_space")
}
//// Job ////
model Job {
id Bytes @id
name String?
action String? // Will be composed of "{action_description}(-{children_order})*"
// Enum: sd_core::job::job_manager:JobStatus
status Int? // 0 = Queued
// List of errors, separated by "\n\n" in case of failed jobs or completed with errors
errors_text String?
data Bytes? // Serialized data to be used on pause/resume
metadata Bytes? // Serialized metadata field with info about the job after completion
parent_id Bytes?
task_count Int?
completed_task_count Int?
date_estimated_completion DateTime? // Estimated timestamp that the job will be complete at
date_created DateTime?
date_started DateTime? // Started execution
date_completed DateTime? // Finished execution
parent Job? @relation("jobs_dependency", fields: [parent_id], references: [id], onDelete: SetNull)
children Job[] @relation("jobs_dependency")
@@map("job")
}
//// Album ////
model Album {
id Int @id
pub_id Bytes @unique
name String?
is_hidden Boolean?
date_created DateTime?
date_modified DateTime?
objects ObjectInAlbum[]
@@map("album")
}
model ObjectInAlbum {
date_created DateTime?
album_id Int
album Album @relation(fields: [album_id], references: [id], onDelete: NoAction)
object_id Int
object Object @relation(fields: [object_id], references: [id], onDelete: NoAction)
@@id([album_id, object_id])
@@map("object_in_album")
}
//// Comment ////
// model Comment {
// id Int @id @default(autoincrement())
// pub_id Bytes @unique
// content String
// date_created DateTime @default(now())
// date_modified DateTime @default(now())
// object_id Int?
// object Object? @relation(fields: [object_id], references: [id])
// @@map("comment")
// }
//// Indexer Rules ////
model IndexerRule {
id Int @id @default(autoincrement())
pub_id Bytes @unique
name String?
default Boolean?
rules_per_kind Bytes?
date_created DateTime?
date_modified DateTime?
locations IndexerRulesInLocation[]
@@map("indexer_rule")
}
model IndexerRulesInLocation {
location_id Int
location Location @relation(fields: [location_id], references: [id], onDelete: Restrict)
indexer_rule_id Int
indexer_rule IndexerRule @relation(fields: [indexer_rule_id], references: [id], onDelete: Restrict)
@@id([location_id, indexer_rule_id])
@@map("indexer_rule_in_location")
}
/// @shared(id: key)
model Preference {
key String @id
value Bytes?
@@map("preference")
}
model Notification {
id Int @id @default(autoincrement())
read Boolean @default(false)
// Enum: crate::api::notifications::NotificationData
data Bytes
expires_at DateTime?
@@map("notification")
}