mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2025-12-11 20:15:30 +01:00
Migrate all cloud routes to the new API system
All cloud routes are now migrated to the new system in the backend. The old routes are still available, as the frontend has not been modified to use the new ones yet.
This commit is contained in:
parent
8718de0928
commit
e2d1862766
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -4379,7 +4379,7 @@ dependencies = [
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core 0.51.1",
|
||||
"windows-core 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -9144,7 +9144,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "sd-cloud-schema"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/spacedriveapp/cloud-services-schema?branch=main#ff92c41e2b908732c58e77c26e0e3eec05f95549"
|
||||
source = "git+https://github.com/spacedriveapp/cloud-services-schema?branch=main#dfbab0a7f19c1c3fafacb2053b1de628760d8dc8"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"async-stream",
|
||||
|
||||
164
core/src/api/cloud/libraries.rs
Normal file
164
core/src/api/cloud/libraries.rs
Normal file
@ -0,0 +1,164 @@
|
||||
use crate::{api::utils::library, invalidate_query};
|
||||
use rspc::alpha::AlphaRouter;
|
||||
use sd_cloud_schema::libraries;
|
||||
use tracing::debug;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
api::{Ctx, R},
|
||||
try_get_cloud_services_client,
|
||||
};
|
||||
|
||||
pub fn mount() -> AlphaRouter<Ctx> {
|
||||
R.router()
|
||||
.procedure("get", {
|
||||
R.query(|node, req: libraries::get::Request| async move {
|
||||
let libraries::get::Response(library) = super::handle_comm_error(
|
||||
try_get_cloud_services_client!(node)?
|
||||
.libraries()
|
||||
.get(req)
|
||||
.await,
|
||||
"Failed to get library;",
|
||||
)??;
|
||||
|
||||
debug!(?library, "Got library");
|
||||
|
||||
Ok(library)
|
||||
})
|
||||
})
|
||||
.procedure("list", {
|
||||
R.query(|node, req: libraries::list::Request| async move {
|
||||
let libraries::list::Response(libraries) = super::handle_comm_error(
|
||||
try_get_cloud_services_client!(node)?
|
||||
.libraries()
|
||||
.list(req)
|
||||
.await,
|
||||
"Failed to list libraries;",
|
||||
)??;
|
||||
|
||||
debug!(?libraries, "Listed libraries");
|
||||
|
||||
Ok(libraries)
|
||||
})
|
||||
})
|
||||
.procedure("create", {
|
||||
R.with2(library())
|
||||
.mutation(|(node, library), _: ()| async move {
|
||||
// let node_config = node.config.get().await;
|
||||
// let cloud_library = sd_cloud_api::library::create(
|
||||
// node.cloud_api_config().await,
|
||||
// library.id,
|
||||
// &library.config().await.name,
|
||||
// library.instance_uuid,
|
||||
// library.identity.to_remote_identity(),
|
||||
// node_config.id,
|
||||
// node_config.identity.to_remote_identity(),
|
||||
// &node.p2p.peer_metadata(),
|
||||
// )
|
||||
// .await?;
|
||||
// node.libraries
|
||||
// .edit(
|
||||
// library.id,
|
||||
// None,
|
||||
// MaybeUndefined::Undefined,
|
||||
// MaybeUndefined::Value(cloud_library.id),
|
||||
// None,
|
||||
// )
|
||||
// .await?;
|
||||
|
||||
invalidate_query!(library, "cloud.library.get");
|
||||
// invalidate_query!(library, "cloud.library.get");
|
||||
debug!("TODO: Functionality not implemented");
|
||||
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
.procedure("join", {
|
||||
R.mutation(|node, library_id: Uuid| async move {
|
||||
// let Some(cloud_library) =
|
||||
// sd_cloud_api::library::get(node.cloud_api_config().await, library_id).await?
|
||||
// else {
|
||||
// return Err(rspc::Error::new(
|
||||
// rspc::ErrorCode::NotFound,
|
||||
// "Library not found".to_string(),
|
||||
// ));
|
||||
// };
|
||||
|
||||
// let library = node
|
||||
// .libraries
|
||||
// .create_with_uuid(
|
||||
// library_id,
|
||||
// LibraryName::new(cloud_library.name).map_err(|e| {
|
||||
// rspc::Error::new(rspc::ErrorCode::InternalServerError, e.to_string())
|
||||
// })?,
|
||||
// None,
|
||||
// false,
|
||||
// None,
|
||||
// &node,
|
||||
// true,
|
||||
// )
|
||||
// .await?;
|
||||
// node.libraries
|
||||
// .edit(
|
||||
// library.id,
|
||||
// None,
|
||||
// MaybeUndefined::Undefined,
|
||||
// MaybeUndefined::Value(cloud_library.id),
|
||||
// None,
|
||||
// )
|
||||
// .await?;
|
||||
|
||||
// let node_config = node.config.get().await;
|
||||
// let instances = sd_cloud_api::library::join(
|
||||
// node.cloud_api_config().await,
|
||||
// library_id,
|
||||
// library.instance_uuid,
|
||||
// library.identity.to_remote_identity(),
|
||||
// node_config.id,
|
||||
// node_config.identity.to_remote_identity(),
|
||||
// node.p2p.peer_metadata(),
|
||||
// )
|
||||
// .await?;
|
||||
|
||||
// for instance in instances {
|
||||
// crate::cloud::sync::receive::upsert_instance(
|
||||
// library.id,
|
||||
// &library.db,
|
||||
// &library.sync,
|
||||
// &node.libraries,
|
||||
// &instance.uuid,
|
||||
// instance.identity,
|
||||
// &instance.node_id,
|
||||
// RemoteIdentity::from_str(&instance.node_remote_identity)
|
||||
// .expect("malformed remote identity in the DB"),
|
||||
// instance.metadata,
|
||||
// )
|
||||
// .await?;
|
||||
// }
|
||||
|
||||
// invalidate_query!(library, "cloud.library.get");
|
||||
// invalidate_query!(library, "cloud.library.list");
|
||||
|
||||
// Ok(LibraryConfigWrapped::from_library(&library).await)
|
||||
|
||||
debug!("TODO: Functionality not implemented. Joining will be removed in the future, but for now, it's a no-op");
|
||||
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
.procedure("update", {
|
||||
R.mutation(|node, req: libraries::update::Request| async move {
|
||||
super::handle_comm_error(
|
||||
try_get_cloud_services_client!(node)?
|
||||
.libraries()
|
||||
.update(req)
|
||||
.await,
|
||||
"Failed to update library;",
|
||||
)??;
|
||||
|
||||
debug!("Updated library");
|
||||
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -1,3 +1,6 @@
|
||||
// This file is being deprecated in favor of libraries.rs
|
||||
// This is due to the migration to the new API system, but the frontend is still using this file
|
||||
|
||||
use crate::{api::utils::library, invalidate_query};
|
||||
|
||||
use super::*;
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// This file is being deprecated in favor of libraries.rs
|
||||
// This is due to the migration to the new API system, but the frontend is still using this file
|
||||
|
||||
use crate::api::{Ctx, R};
|
||||
|
||||
use rspc::alpha::AlphaRouter;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::{api::libraries::LibraryConfigWrapped, invalidate_query, library::LibraryName};
|
||||
// use crate::{api::libraries::LibraryConfigWrapped, invalidate_query, library::LibraryName};
|
||||
|
||||
use sd_cloud_schema::{auth, users};
|
||||
|
||||
@ -11,6 +11,8 @@ use super::{Ctx, R};
|
||||
mod devices;
|
||||
mod library;
|
||||
mod locations;
|
||||
mod new_locations;
|
||||
mod libraries;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! try_get_cloud_services_client {
|
||||
@ -29,7 +31,9 @@ macro_rules! try_get_cloud_services_client {
|
||||
pub(crate) fn mount() -> AlphaRouter<Ctx> {
|
||||
R.router()
|
||||
.merge("library.", library::mount())
|
||||
.merge("libraries.", libraries::mount())
|
||||
.merge("locations.", locations::mount())
|
||||
.merge("new_locations.", new_locations::mount())
|
||||
.merge("devices.", devices::mount())
|
||||
.procedure("bootstrap", {
|
||||
R.mutation(|node, access_token: auth::AccessToken| async move {
|
||||
|
||||
89
core/src/api/cloud/new_locations.rs
Normal file
89
core/src/api/cloud/new_locations.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use crate::{
|
||||
api::{Ctx, R},
|
||||
try_get_cloud_services_client,
|
||||
};
|
||||
|
||||
use rspc::alpha::AlphaRouter;
|
||||
use sd_cloud_schema::locations;
|
||||
use tracing::debug;
|
||||
|
||||
pub fn mount() -> AlphaRouter<Ctx> {
|
||||
R.router()
|
||||
.procedure("get", {
|
||||
R.query(|node, req: locations::get::Request| async move {
|
||||
let locations::get::Response(location) = super::handle_comm_error(
|
||||
try_get_cloud_services_client!(node)?
|
||||
.locations()
|
||||
.get(req)
|
||||
.await,
|
||||
"Failed to get location;",
|
||||
)??;
|
||||
|
||||
debug!(?location, "Got location");
|
||||
|
||||
Ok(location)
|
||||
})
|
||||
})
|
||||
.procedure("list", {
|
||||
R.query(|node, req: locations::list::Request| async move {
|
||||
let locations::list::Response(locations) = super::handle_comm_error(
|
||||
try_get_cloud_services_client!(node)?
|
||||
.locations()
|
||||
.list(req)
|
||||
.await,
|
||||
"Failed to list locations;",
|
||||
)??;
|
||||
|
||||
debug!(?locations, "Listed locations");
|
||||
|
||||
Ok(locations)
|
||||
})
|
||||
})
|
||||
.procedure("create", {
|
||||
R.mutation(|node, req: locations::create::Request| async move {
|
||||
super::handle_comm_error(
|
||||
try_get_cloud_services_client!(node)?
|
||||
.locations()
|
||||
.create(req)
|
||||
.await,
|
||||
"Failed to create location;",
|
||||
)??;
|
||||
|
||||
debug!("Created location");
|
||||
|
||||
// Should we invalidate the location list cache here?
|
||||
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
.procedure("delete", {
|
||||
R.mutation(|node, req: locations::delete::Request| async move {
|
||||
super::handle_comm_error(
|
||||
try_get_cloud_services_client!(node)?
|
||||
.locations()
|
||||
.delete(req)
|
||||
.await,
|
||||
"Failed to delete location;",
|
||||
)??;
|
||||
|
||||
debug!("Deleted location");
|
||||
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
.procedure("update", {
|
||||
R.mutation(|node, req: locations::update::Request| async move {
|
||||
super::handle_comm_error(
|
||||
try_get_cloud_services_client!(node)?
|
||||
.locations()
|
||||
.update(req)
|
||||
.await,
|
||||
"Failed to update location;",
|
||||
)??;
|
||||
|
||||
debug!("Updated location");
|
||||
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -517,6 +517,7 @@ pub mod library {
|
||||
}
|
||||
|
||||
#[derive(Type, Serialize, Deserialize)]
|
||||
#[specta(rename = "Core_CloudLocation")]
|
||||
pub struct CloudLocation {
|
||||
id: String,
|
||||
name: String,
|
||||
|
||||
@ -2,8 +2,6 @@ import { CheckCircle, XCircle } from '@phosphor-icons/react';
|
||||
import { Suspense, useMemo } from 'react';
|
||||
import {
|
||||
auth,
|
||||
CloudInstance,
|
||||
CloudLibrary,
|
||||
HardwareModel,
|
||||
useBridgeQuery,
|
||||
useLibraryContext,
|
||||
@ -51,16 +49,22 @@ export const Component = () => {
|
||||
// million-ignore
|
||||
function Authenticated() {
|
||||
const { library } = useLibraryContext();
|
||||
const cloudLibrary = useLibraryQuery(['cloud.library.get'], { suspense: true, retry: false });
|
||||
const cloudLibraryList = useBridgeQuery(['cloud.library.list'], { suspense: true, retry: false });
|
||||
console.log("[DEBUG] cloudLibraryList", cloudLibraryList);
|
||||
const cloudLibrary: any = useLibraryQuery(['cloud.library.get'], {
|
||||
suspense: true,
|
||||
retry: false
|
||||
});
|
||||
const cloudLibraryList = useBridgeQuery(['cloud.library.list'], {
|
||||
suspense: true,
|
||||
retry: false
|
||||
});
|
||||
console.log('[DEBUG] cloudLibraryList', cloudLibraryList);
|
||||
const createLibrary = useLibraryMutation(['cloud.library.create']);
|
||||
const { t } = useLocale();
|
||||
|
||||
const thisInstance = useMemo(() => {
|
||||
if (!cloudLibrary.data) return undefined;
|
||||
return cloudLibrary.data.instances.find(
|
||||
(instance) => instance.uuid === library.instance_id
|
||||
(instance: any) => instance.uuid === library.instance_id
|
||||
);
|
||||
}, [cloudLibrary.data, library.instance_id]);
|
||||
|
||||
@ -113,7 +117,7 @@ function Authenticated() {
|
||||
}
|
||||
|
||||
// million-ignore
|
||||
const Instances = ({ instances }: { instances: CloudInstance[] }) => {
|
||||
const Instances = ({ instances }: { instances: any[] }) => {
|
||||
const { library } = useLibraryContext();
|
||||
const filteredInstances = instances.filter((instance) => instance.uuid !== library.instance_id);
|
||||
return (
|
||||
@ -173,8 +177,8 @@ const Instances = ({ instances }: { instances: CloudInstance[] }) => {
|
||||
};
|
||||
|
||||
interface LibraryProps {
|
||||
cloudLibrary: CloudLibrary;
|
||||
thisInstance: CloudInstance | undefined;
|
||||
cloudLibrary: any;
|
||||
thisInstance: any | undefined;
|
||||
}
|
||||
|
||||
// million-ignore
|
||||
@ -206,7 +210,7 @@ const Library = ({ thisInstance, cloudLibrary }: LibraryProps) => {
|
||||
};
|
||||
|
||||
interface ThisInstanceProps {
|
||||
instance: CloudInstance;
|
||||
instance: any;
|
||||
}
|
||||
|
||||
// million-ignore
|
||||
|
||||
@ -86,14 +86,6 @@ function HostedLocationsPlayground() {
|
||||
locations.refetch();
|
||||
}
|
||||
});
|
||||
const doTheThing = useBridgeMutation('cloud.locations.testing', {
|
||||
onSuccess() {
|
||||
toast.success('Uploaded file!');
|
||||
},
|
||||
onError(err) {
|
||||
toast.error(err.message);
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (path === '' && locations.data?.[0]) {
|
||||
@ -101,7 +93,7 @@ function HostedLocationsPlayground() {
|
||||
}
|
||||
}, [path, locations.data]);
|
||||
|
||||
const isLoading = createLocation.isLoading || removeLocation.isLoading || doTheThing.isLoading;
|
||||
const isLoading = createLocation.isLoading || removeLocation.isLoading;
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -153,19 +145,6 @@ function HostedLocationsPlayground() {
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
<Button
|
||||
variant="accent"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
doTheThing.mutate({
|
||||
id: location.id,
|
||||
path
|
||||
})
|
||||
}
|
||||
disabled={isLoading}
|
||||
>
|
||||
Do the thing
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@ -8,9 +8,13 @@ export type Procedures = {
|
||||
{ key: "buildInfo", input: never, result: BuildInfo } |
|
||||
{ key: "cloud.devices.get", input: DeviceGetRequest, result: Device } |
|
||||
{ key: "cloud.devices.list", input: DeviceListRequest, result: Device[] } |
|
||||
{ key: "cloud.libraries.get", input: LibraryGetRequest, result: Library } |
|
||||
{ key: "cloud.libraries.list", input: LibraryListRequest, result: Library[] } |
|
||||
{ key: "cloud.library.get", input: LibraryArgs<null>, result: null } |
|
||||
{ key: "cloud.library.list", input: never, result: null } |
|
||||
{ key: "cloud.locations.list", input: never, result: CloudLocation[] } |
|
||||
{ key: "cloud.locations.list", input: never, result: Core_CloudLocation[] } |
|
||||
{ key: "cloud.new_locations.get", input: LocationGetRequest, result: CloudLocation } |
|
||||
{ key: "cloud.new_locations.list", input: LocationListRequest, result: CloudLocation[] } |
|
||||
{ key: "ephemeralFiles.getMediaData", input: string, result: MediaData | null } |
|
||||
{ key: "files.get", input: LibraryArgs<number>, result: ObjectWithFilePaths2 | null } |
|
||||
{ key: "files.getConvertibleImageExtensions", input: never, result: string[] } |
|
||||
@ -67,11 +71,17 @@ export type Procedures = {
|
||||
{ key: "cloud.bootstrap", input: AccessToken, result: null } |
|
||||
{ key: "cloud.devices.delete", input: DeviceDeleteRequest, result: null } |
|
||||
{ key: "cloud.devices.update", input: DeviceUpdateRequest, result: null } |
|
||||
{ key: "cloud.libraries.create", input: LibraryArgs<null>, result: null } |
|
||||
{ key: "cloud.libraries.join", input: string, result: null } |
|
||||
{ key: "cloud.libraries.update", input: LibraryUpdateRequest, result: null } |
|
||||
{ key: "cloud.library.create", input: LibraryArgs<null>, result: null } |
|
||||
{ key: "cloud.library.join", input: string, result: null } |
|
||||
{ key: "cloud.library.sync", input: LibraryArgs<null>, result: null } |
|
||||
{ key: "cloud.locations.create", input: string, result: CloudLocation } |
|
||||
{ key: "cloud.locations.remove", input: string, result: CloudLocation } |
|
||||
{ key: "cloud.locations.create", input: string, result: Core_CloudLocation } |
|
||||
{ key: "cloud.locations.remove", input: string, result: Core_CloudLocation } |
|
||||
{ key: "cloud.new_locations.create", input: LocationCreateRequest, result: null } |
|
||||
{ key: "cloud.new_locations.delete", input: LocationDeleteRequest, result: null } |
|
||||
{ key: "cloud.new_locations.update", input: LocationUpdateRequest, result: null } |
|
||||
{ key: "ephemeralFiles.copyFiles", input: LibraryArgs<EphemeralFileSystemOps>, result: null } |
|
||||
{ key: "ephemeralFiles.createFile", input: LibraryArgs<CreateEphemeralFileArgs>, result: string } |
|
||||
{ key: "ephemeralFiles.createFolder", input: LibraryArgs<CreateEphemeralFolderArgs>, result: string } |
|
||||
@ -183,7 +193,7 @@ export type ChangeNodeNameArgs = { name: string | null; p2p_port: Port | null; p
|
||||
|
||||
export type Chapter = { id: number; start: [number, number]; end: [number, number]; time_base_den: number; time_base_num: number; metadata: Metadata }
|
||||
|
||||
export type CloudLocation = { id: string; name: string }
|
||||
export type CloudLocation = { pub_id: LocationPubId; name: string; device: Device | null; library: Library | null; created_at: string; updated_at: string }
|
||||
|
||||
export type Codec = { kind: string | null; sub_kind: string | null; tag: string | null; name: string | null; profile: string | null; bit_rate: number; props: Props | null }
|
||||
|
||||
@ -217,6 +227,8 @@ export type ConvertImageArgs = { location_id: number; file_path_id: number; dele
|
||||
|
||||
export type ConvertibleExtension = "bmp" | "dib" | "ff" | "gif" | "ico" | "jpg" | "jpeg" | "png" | "pnm" | "qoi" | "tga" | "icb" | "vda" | "vst" | "tiff" | "tif" | "hif" | "heif" | "heifs" | "heic" | "heics" | "avif" | "avci" | "avcs" | "svg" | "svgz" | "pdf" | "webp"
|
||||
|
||||
export type Core_CloudLocation = { id: string; name: string }
|
||||
|
||||
export type CreateEphemeralFileArgs = { path: string; context: EphemeralFileCreateContextTypes; name: string | null }
|
||||
|
||||
export type CreateEphemeralFolderArgs = { path: string; name: string | null }
|
||||
@ -411,6 +423,8 @@ export type Label = { id: number; name: string; date_created: string | null; dat
|
||||
|
||||
export type LabelWithObjects = { id: number; name: string; date_created: string | null; date_modified: string | null; label_objects: { object: { id: number; file_paths: FilePath[] } }[] }
|
||||
|
||||
export type Library = { pub_id: LibraryPubId; name: string; original_device: Device | null; created_at: string; updated_at: string }
|
||||
|
||||
/**
|
||||
* Can wrap a query argument to require it to contain a `library_id` and provide helpers for working with libraries.
|
||||
*/
|
||||
@ -442,10 +456,18 @@ export type LibraryConfigVersion = "V0" | "V1" | "V2" | "V3" | "V4" | "V5" | "V6
|
||||
|
||||
export type LibraryConfigWrapped = { uuid: string; instance_id: string; instance_public_key: RemoteIdentity; config: LibraryConfig }
|
||||
|
||||
export type LibraryGetRequest = { access_token: AccessToken; pub_id: LibraryPubId; with_device: boolean }
|
||||
|
||||
export type LibraryListRequest = { access_token: AccessToken; with_device: boolean }
|
||||
|
||||
export type LibraryName = string
|
||||
|
||||
export type LibraryPreferences = { location?: { [key in string]: LocationSettings }; tag?: { [key in string]: TagSettings } }
|
||||
|
||||
export type LibraryPubId = string
|
||||
|
||||
export type LibraryUpdateRequest = { access_token: AccessToken; pub_id: LibraryPubId; name: string }
|
||||
|
||||
export type LightScanArgs = { location_id: number; sub_path: string }
|
||||
|
||||
export type ListenerState = { type: "Listening" } | { type: "Error"; error: string } | { type: "NotListening" }
|
||||
@ -461,6 +483,16 @@ export type Location = { id: number; pub_id: number[]; name: string | null; path
|
||||
*/
|
||||
export type LocationCreateArgs = { path: string; dry_run: boolean; indexer_rules_ids: number[] }
|
||||
|
||||
export type LocationCreateRequest = { access_token: AccessToken; pub_id: LocationPubId; name: string; library_pub_id: LibraryPubId; device_pub_id: DevicePubId }
|
||||
|
||||
export type LocationDeleteRequest = { access_token: AccessToken; pub_id: LocationPubId }
|
||||
|
||||
export type LocationGetRequest = { access_token: AccessToken; pub_id: LocationPubId; with_library: boolean; with_device: boolean }
|
||||
|
||||
export type LocationListRequest = { access_token: AccessToken; with_library: boolean; with_device: boolean }
|
||||
|
||||
export type LocationPubId = string
|
||||
|
||||
export type LocationSettings = { explorer: ExplorerSettings<FilePathOrder> }
|
||||
|
||||
/**
|
||||
@ -473,6 +505,8 @@ export type LocationSettings = { explorer: ExplorerSettings<FilePathOrder> }
|
||||
*/
|
||||
export type LocationUpdateArgs = { id: number; name: string | null; generate_preview_media: boolean | null; sync_preview_media: boolean | null; hidden: boolean | null; indexer_rules_ids: number[]; path: string | null }
|
||||
|
||||
export type LocationUpdateRequest = { access_token: AccessToken; pub_id: LocationPubId; name: string }
|
||||
|
||||
export type LocationWithIndexerRule = { id: number; pub_id: number[]; name: string | null; path: string | null; total_capacity: number | null; available_capacity: number | null; size_in_bytes: number[] | null; is_archived: boolean | null; generate_preview_media: boolean | null; sync_preview_media: boolean | null; hidden: boolean | null; date_created: string | null; instance_id: number | null; indexer_rules: IndexerRule[] }
|
||||
|
||||
export type MaybeUndefined<T> = null | T
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user