fix: add sync subscription webui and check credential web ui

This commit is contained in:
2025-06-08 00:36:59 +08:00
parent 946d4e8c2c
commit d2aab7369d
46 changed files with 1120 additions and 195 deletions

View File

@@ -9,7 +9,6 @@
"keywords": [],
"license": "MIT",
"devDependencies": {
"cross-env": "^7.0.3",
"whistle": "^2.9.93"
}
}

View File

@@ -11,3 +11,6 @@ BASIC_PASSWORD = "konobangu"
# OIDC_EXTRA_SCOPES = "read:konobangu write:konobangu"
# OIDC_EXTRA_CLAIM_KEY = ""
# OIDC_EXTRA_CLAIM_VALUE = ""
# MIKAN_PROXY = ""
# MIKAN_PROXY_AUTH_HEADER = ""
# MIKAN_NO_PROXY = ""

View File

@@ -65,7 +65,7 @@ async fn main() -> Result<()> {
.prompt()?;
let mikan_scrape_client = mikan_scrape_client
.fork_with_credential(UserPassCredential {
.fork_with_userpass_credential(UserPassCredential {
username,
password,
user_agent: None,

View File

@@ -86,6 +86,14 @@ leaky_bucket_initial_tokens = 1
leaky_bucket_refill_tokens = 1
leaky_bucket_refill_interval = 500
[mikan.http_client.proxy]
server = '{{ get_env(name="MIKAN_PROXY", default = "") }}'
auth_header = '{{ get_env(name="MIKAN_PROXY_AUTH_HEADER", default = "") }}'
no_proxy = '{{ get_env(name="MIKAN_NO_PROXY", default = "") }}'
accept_invalid_certs = '{{ get_env(name="MIKAN_PROXY_ACCEPT_INVALID_CERTS", default = "false") }}'
[auth]
auth_type = '{{ get_env(name="AUTH_TYPE", default = "basic") }}'
basic_user = '{{ get_env(name="BASIC_USER", default = "konobangu") }}'

View File

@@ -11,6 +11,10 @@ leaky_bucket_initial_tokens = 0
leaky_bucket_refill_tokens = 1
leaky_bucket_refill_interval = 500
[mikan.http_client.proxy]
[mikan.http_client.proxy.headers]
[graphql]
depth_limit = inf
complexity_limit = inf

View File

@@ -1,4 +1,4 @@
use std::{fmt::Debug, ops::Deref, sync::Arc};
use std::{fmt::Debug, ops::Deref};
use fetch::{HttpClient, HttpClientTrait};
use maplit::hashmap;
@@ -136,7 +136,7 @@ impl MikanClient {
pub async fn submit_credential_form(
&self,
ctx: Arc<dyn AppContextTrait>,
ctx: &dyn AppContextTrait,
subscriber_id: i32,
credential_form: MikanCredentialForm,
) -> RecorderResult<credential_3rd::Model> {
@@ -149,7 +149,7 @@ impl MikanClient {
subscriber_id: Set(subscriber_id),
..Default::default()
}
.try_encrypt(ctx.clone())
.try_encrypt(ctx)
.await?;
let credential: credential_3rd::Model = am.save(db).await?.try_into_model()?;
@@ -158,8 +158,9 @@ impl MikanClient {
pub async fn sync_credential_cookies(
&self,
ctx: Arc<dyn AppContextTrait>,
ctx: &dyn AppContextTrait,
credential_id: i32,
subscriber_id: i32,
) -> RecorderResult<()> {
let cookies = self.http_client.save_cookie_store_to_json()?;
if let Some(cookies) = cookies {
@@ -167,19 +168,20 @@ impl MikanClient {
cookies: Set(Some(cookies)),
..Default::default()
}
.try_encrypt(ctx.clone())
.try_encrypt(ctx)
.await?;
credential_3rd::Entity::update_many()
.set(am)
.filter(credential_3rd::Column::Id.eq(credential_id))
.filter(credential_3rd::Column::SubscriberId.eq(subscriber_id))
.exec(ctx.db())
.await?;
}
Ok(())
}
pub async fn fork_with_credential(
pub async fn fork_with_userpass_credential(
&self,
userpass_credential: UserPassCredential,
) -> RecorderResult<Self> {
@@ -204,10 +206,13 @@ impl MikanClient {
pub async fn fork_with_credential_id(
&self,
ctx: Arc<dyn AppContextTrait>,
ctx: &dyn AppContextTrait,
credential_id: i32,
subscriber_id: i32,
) -> RecorderResult<Self> {
let credential = credential_3rd::Model::find_by_id(ctx.clone(), credential_id).await?;
let credential =
credential_3rd::Model::find_by_id_and_subscriber_id(ctx, credential_id, subscriber_id)
.await?;
if let Some(credential) = credential {
if credential.credential_type != Credential3rdType::Mikan {
return Err(RecorderError::Credential3rdError {
@@ -219,7 +224,8 @@ impl MikanClient {
let userpass_credential: UserPassCredential =
credential.try_into_userpass_credential(ctx)?;
self.fork_with_credential(userpass_credential).await
self.fork_with_userpass_credential(userpass_credential)
.await
} else {
Err(RecorderError::from_db_record_not_found(
DbErr::RecordNotFound(format!("credential={credential_id} not found")),
@@ -249,7 +255,7 @@ impl HttpClientTrait for MikanClient {}
#[cfg(test)]
mod tests {
#![allow(unused_variables)]
use std::assert_matches::assert_matches;
use std::{assert_matches::assert_matches, sync::Arc};
use rstest::{fixture, rstest};
use tracing::Level;
@@ -297,8 +303,10 @@ mod tests {
let credential_form = build_testing_mikan_credential_form();
let subscriber_id = 1;
let credential_model = mikan_client
.submit_credential_form(app_ctx.clone(), 1, credential_form.clone())
.submit_credential_form(app_ctx.as_ref(), subscriber_id, credential_form.clone())
.await?;
let expected_username = &credential_form.username;
@@ -322,7 +330,7 @@ mod tests {
);
let mikan_client = mikan_client
.fork_with_credential_id(app_ctx.clone(), credential_model.id)
.fork_with_credential_id(app_ctx.as_ref(), credential_model.id, subscriber_id)
.await?;
mikan_client.login().await?;

View File

@@ -2,7 +2,7 @@ use fetch::HttpClientConfig;
use serde::{Deserialize, Serialize};
use url::Url;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MikanConfig {
pub http_client: HttpClientConfig,
pub base_url: Url,

View File

@@ -387,6 +387,7 @@ impl MikanSeasonSubscription {
ctx,
mikan_season_flow_url,
credential_id,
self.get_subscriber_id(),
)
}

View File

@@ -917,10 +917,11 @@ pub fn scrape_mikan_bangumi_meta_stream_from_season_flow_url(
ctx: Arc<dyn AppContextTrait>,
mikan_season_flow_url: Url,
credential_id: i32,
subscriber_id: i32,
) -> impl Stream<Item = RecorderResult<MikanBangumiMeta>> {
try_stream! {
let mikan_base_url = ctx.mikan().base_url().clone();
let mikan_client = ctx.mikan().fork_with_credential_id(ctx.clone(), credential_id).await?;
let mikan_client = ctx.mikan().fork_with_credential_id(ctx.as_ref(), credential_id, subscriber_id).await?;
let content = fetch_html(&mikan_client, mikan_season_flow_url.clone()).await?;
@@ -940,7 +941,7 @@ pub fn scrape_mikan_bangumi_meta_stream_from_season_flow_url(
mikan_client
.sync_credential_cookies(ctx.clone(), credential_id)
.sync_credential_cookies(ctx.as_ref(), credential_id, subscriber_id)
.await?;
for bangumi_index in bangumi_indices_meta {
@@ -969,7 +970,7 @@ pub fn scrape_mikan_bangumi_meta_stream_from_season_flow_url(
}
mikan_client
.sync_credential_cookies(ctx, credential_id)
.sync_credential_cookies(ctx.as_ref(), credential_id, subscriber_id)
.await?;
}
}
@@ -978,11 +979,13 @@ pub async fn scrape_mikan_bangumi_meta_list_from_season_flow_url(
ctx: Arc<dyn AppContextTrait>,
mikan_season_flow_url: Url,
credential_id: i32,
subscriber_id: i32,
) -> RecorderResult<Vec<MikanBangumiMeta>> {
let stream = scrape_mikan_bangumi_meta_stream_from_season_flow_url(
ctx,
mikan_season_flow_url,
credential_id,
subscriber_id,
);
pin_mut!(stream);
@@ -1160,7 +1163,7 @@ mod test {
let mikan_client = build_testing_mikan_client(mikan_base_url.clone())
.await?
.fork_with_credential(build_testing_mikan_credential())
.fork_with_userpass_credential(build_testing_mikan_credential())
.await?;
mikan_client.login().await?;
@@ -1268,8 +1271,14 @@ mod test {
let mikan_client = app_ctx.mikan();
let subscriber_id = 1;
let credential = mikan_client
.submit_credential_form(app_ctx.clone(), 1, build_testing_mikan_credential_form())
.submit_credential_form(
app_ctx.as_ref(),
subscriber_id,
build_testing_mikan_credential_form(),
)
.await?;
let mikan_season_flow_url =
@@ -1279,6 +1288,7 @@ mod test {
app_ctx.clone(),
mikan_season_flow_url,
credential.id,
subscriber_id,
);
pin_mut!(bangumi_meta_stream);

View File

@@ -20,7 +20,7 @@ use crate::{
},
util::{get_entity_column_key, get_entity_key},
},
views::register_subscriptions_to_schema,
views::{register_credential3rd_to_schema, register_subscriptions_to_schema},
},
};
@@ -156,7 +156,7 @@ pub fn build_schema(
&mut context,
&subscriber_tasks::Column::Job,
);
add_crypto_transformers(&mut context, app_ctx);
add_crypto_transformers(&mut context, app_ctx.clone());
for column in subscribers::Column::iter() {
if !matches!(column, subscribers::Column::Id) {
restrict_filter_input_for_entity::<subscribers::Entity>(
@@ -215,6 +215,7 @@ pub fn build_schema(
{
builder = register_subscriptions_to_schema(builder);
builder = register_credential3rd_to_schema(builder);
}
let schema = builder.schema_builder();
@@ -231,6 +232,7 @@ pub fn build_schema(
};
schema
.data(database)
.data(app_ctx)
.finish()
.inspect_err(|e| tracing::error!(e = ?e))
}

View File

@@ -0,0 +1,113 @@
use std::sync::Arc;
use async_graphql::dynamic::{
Field, FieldFuture, FieldValue, InputObject, InputValue, Object, TypeRef,
};
use seaography::Builder as SeaographyBuilder;
use serde::{Deserialize, Serialize};
use util_derive::DynamicGraphql;
use crate::{
app::AppContextTrait, auth::AuthUserInfo, errors::RecorderError, models::credential_3rd,
};
#[derive(DynamicGraphql, Serialize, Deserialize, Clone, Debug)]
struct Credential3rdCheckAvailableInput {
pub id: i32,
}
impl Credential3rdCheckAvailableInput {
fn input_type_name() -> &'static str {
"Credential3rdCheckAvailableInput"
}
fn arg_name() -> &'static str {
"filter"
}
fn generate_input_object() -> InputObject {
InputObject::new(Self::input_type_name())
.description("The input of the credential3rdCheckAvailable query")
.field(InputValue::new(
Credential3rdCheckAvailableInputFieldEnum::Id.as_str(),
TypeRef::named_nn(TypeRef::INT),
))
}
}
#[derive(DynamicGraphql, Serialize, Deserialize, Clone, Debug)]
pub struct Credential3rdCheckAvailableInfo {
pub available: bool,
}
impl Credential3rdCheckAvailableInfo {
fn object_type_name() -> &'static str {
"Credential3rdCheckAvailableInfo"
}
fn generate_output_object() -> Object {
Object::new(Self::object_type_name())
.description("The output of the credential3rdCheckAvailable query")
.field(Field::new(
Credential3rdCheckAvailableInfoFieldEnum::Available,
TypeRef::named_nn(TypeRef::BOOLEAN),
move |ctx| {
FieldFuture::new(async move {
let subscription_info = ctx.parent_value.try_downcast_ref::<Self>()?;
Ok(Some(async_graphql::Value::from(
subscription_info.available,
)))
})
},
))
}
}
pub fn register_credential3rd_to_schema(mut builder: SeaographyBuilder) -> SeaographyBuilder {
builder.schema = builder
.schema
.register(Credential3rdCheckAvailableInput::generate_input_object());
builder.schema = builder
.schema
.register(Credential3rdCheckAvailableInfo::generate_output_object());
builder.queries.push(
Field::new(
"credential3rdCheckAvailable",
TypeRef::named_nn(Credential3rdCheckAvailableInfo::object_type_name()),
move |ctx| {
FieldFuture::new(async move {
let auth_user_info = ctx.data::<AuthUserInfo>()?;
let input: Credential3rdCheckAvailableInput = ctx
.args
.get(Credential3rdCheckAvailableInput::arg_name())
.unwrap()
.deserialize()?;
let app_ctx = ctx.data::<Arc<dyn AppContextTrait>>()?;
let credential_model = credential_3rd::Model::find_by_id_and_subscriber_id(
app_ctx.as_ref(),
input.id,
auth_user_info.subscriber_auth.subscriber_id,
)
.await?
.ok_or_else(|| RecorderError::Credential3rdError {
message: format!("credential = {} not found", input.id),
source: None.into(),
})?;
let available = credential_model.check_available(app_ctx.as_ref()).await?;
Ok(Some(FieldValue::owned_any(
Credential3rdCheckAvailableInfo { available },
)))
})
},
)
.argument(InputValue::new(
Credential3rdCheckAvailableInput::arg_name(),
TypeRef::named_nn(Credential3rdCheckAvailableInput::input_type_name()),
)),
);
builder
}

View File

@@ -1,3 +1,5 @@
mod credential_3rd;
mod subscription;
pub use credential_3rd::register_credential3rd_to_schema;
pub use subscription::register_subscriptions_to_schema;

View File

@@ -16,7 +16,7 @@ use crate::{
#[derive(DynamicGraphql, Serialize, Deserialize, Clone, Debug)]
struct SyncOneSubscriptionFilterInput {
pub subscription_id: i32,
pub id: i32,
}
impl SyncOneSubscriptionFilterInput {
@@ -32,7 +32,7 @@ impl SyncOneSubscriptionFilterInput {
InputObject::new(Self::input_type_name())
.description("The input of the subscriptionSyncOne series of mutations")
.field(InputValue::new(
SyncOneSubscriptionFilterInputFieldEnum::SubscriptionId.as_str(),
SyncOneSubscriptionFilterInputFieldEnum::Id.as_str(),
TypeRef::named_nn(TypeRef::INT),
))
}
@@ -74,7 +74,7 @@ pub fn register_subscriptions_to_schema(mut builder: SeaographyBuilder) -> Seaog
.schema
.register(SyncOneSubscriptionInfo::generate_output_object());
builder.queries.push(
builder.mutations.push(
Field::new(
"subscriptionSyncOneFeedsIncremental",
TypeRef::named_nn(SyncOneSubscriptionInfo::object_type_name()),
@@ -93,7 +93,7 @@ pub fn register_subscriptions_to_schema(mut builder: SeaographyBuilder) -> Seaog
let subscription_model = subscriptions::Model::find_by_id_and_subscriber_id(
app_ctx.as_ref(),
filter_input.subscription_id,
filter_input.id,
subscriber_id,
)
.await?;
@@ -124,7 +124,7 @@ pub fn register_subscriptions_to_schema(mut builder: SeaographyBuilder) -> Seaog
)),
);
builder.queries.push(
builder.mutations.push(
Field::new(
"subscriptionSyncOneFeedsFull",
TypeRef::named_nn(SyncOneSubscriptionInfo::object_type_name()),
@@ -143,7 +143,7 @@ pub fn register_subscriptions_to_schema(mut builder: SeaographyBuilder) -> Seaog
let subscription_model = subscriptions::Model::find_by_id_and_subscriber_id(
app_ctx.as_ref(),
filter_input.subscription_id,
filter_input.id,
subscriber_id,
)
.await?;
@@ -193,7 +193,7 @@ pub fn register_subscriptions_to_schema(mut builder: SeaographyBuilder) -> Seaog
let subscription_model = subscriptions::Model::find_by_id_and_subscriber_id(
app_ctx.as_ref(),
filter_input.subscription_id,
filter_input.id,
subscriber_id,
)
.await?;

View File

@@ -1,5 +1,3 @@
use std::sync::Arc;
use async_trait::async_trait;
use sea_orm::{ActiveValue, prelude::*};
use serde::{Deserialize, Serialize};
@@ -79,7 +77,7 @@ pub enum RelatedEntity {
impl ActiveModelBehavior for ActiveModel {}
impl ActiveModel {
pub async fn try_encrypt(mut self, ctx: Arc<dyn AppContextTrait>) -> RecorderResult<Self> {
pub async fn try_encrypt(mut self, ctx: &dyn AppContextTrait) -> RecorderResult<Self> {
let crypto = ctx.crypto();
if let ActiveValue::Set(Some(username)) = self.username {
@@ -102,19 +100,24 @@ impl ActiveModel {
}
impl Model {
pub async fn find_by_id(
ctx: Arc<dyn AppContextTrait>,
pub async fn find_by_id_and_subscriber_id(
ctx: &dyn AppContextTrait,
id: i32,
subscriber_id: i32,
) -> RecorderResult<Option<Self>> {
let db = ctx.db();
let credential = Entity::find_by_id(id).one(db).await?;
let credential = Entity::find()
.filter(Column::Id.eq(id))
.filter(Column::SubscriberId.eq(subscriber_id))
.one(db)
.await?;
Ok(credential)
}
pub fn try_into_userpass_credential(
self,
ctx: Arc<dyn AppContextTrait>,
ctx: &dyn AppContextTrait,
) -> RecorderResult<UserPassCredential> {
let crypto = ctx.crypto();
let username_enc = self
@@ -149,4 +152,31 @@ impl Model {
user_agent: self.user_agent,
})
}
pub async fn check_available(self, ctx: &dyn AppContextTrait) -> RecorderResult<bool> {
let credential_id = self.id;
let subscriber_id = self.subscriber_id;
match self.credential_type {
Credential3rdType::Mikan => {
let mikan_client = {
let userpass_credential: UserPassCredential =
self.try_into_userpass_credential(ctx)?;
ctx.mikan()
.fork_with_userpass_credential(userpass_credential)
.await?
};
let mut has_login = mikan_client.has_login().await?;
if !has_login {
mikan_client.login().await?;
has_login = true;
}
if has_login {
mikan_client
.sync_credential_cookies(ctx, credential_id, subscriber_id)
.await?;
}
Ok(has_login)
}
}
}
}

View File

@@ -80,6 +80,14 @@ export const GET_CREDENTIAL_3RD_DETAIL = gql`
}
`;
export const CHECK_CREDENTIAL_3RD_AVAILABLE = gql`
query CheckCredential3rdAvailable($id: Int!) {
credential3rdCheckAvailable(filter: { id: $id }) {
available
}
}
`;
export const Credential3rdTypedMikanSchema = type({
credentialType: `'${Credential3rdTypeEnum.Mikan}'`,
username: 'string > 0',

View File

@@ -121,6 +121,30 @@ query GetSubscriptionDetail ($id: Int!) {
}
`;
export const SYNC_SUBSCRIPTION_FEEDS_INCREMENTAL = gql`
mutation SyncSubscriptionFeedsIncremental($id: Int!) {
subscriptionSyncOneFeedsIncremental(filter: { id: $id }) {
taskId
}
}
`;
export const SYNC_SUBSCRIPTION_FEEDS_FULL = gql`
mutation SyncSubscriptionFeedsFull($id: Int!) {
subscriptionSyncOneFeedsFull(filter: { id: $id }) {
taskId
}
}
`;
export const SYNC_SUBSCRIPTION_SOURCES = gql`
mutation SyncSubscriptionSources($id: Int!) {
subscriptionSyncOneSources(filter: { id: $id }) {
taskId
}
}
`;
export const SubscriptionTypedMikanSeasonSchema =
MikanSubscriptionSeasonSourceUrlSchema.and(
type({

View File

@@ -0,0 +1,26 @@
import type { ApolloError, ApolloQueryResult } from '@apollo/client';
import type { GraphQLFormattedError } from 'graphql';
export function getApolloQueryError<T>(
response: ApolloQueryResult<T>
): ApolloError | readonly GraphQLFormattedError[] | null {
if (response.error) {
return response.error;
}
if (response.errors) {
return response.errors;
}
return null;
}
export function apolloErrorToMessage(
error: ApolloError | readonly GraphQLFormattedError[]
) {
if (Array.isArray(error)) {
return error.map((e) => e.message).join('\n');
}
if ('message' in error) {
return error.message;
}
return 'Unknown error';
}

View File

@@ -19,11 +19,15 @@ type Documents = {
"\n mutation UpdateCredential3rd($data: Credential3rdUpdateInput!, $filters: Credential3rdFilterInput!) {\n credential3rdUpdate(data: $data, filter: $filters) {\n id\n cookies\n username\n password\n userAgent\n createdAt\n updatedAt\n credentialType\n }\n }\n": typeof types.UpdateCredential3rdDocument,
"\n mutation DeleteCredential3rd($filters: Credential3rdFilterInput!) {\n credential3rdDelete(filter: $filters)\n }\n": typeof types.DeleteCredential3rdDocument,
"\n query GetCredential3rdDetail($id: Int!) {\n credential3rd(filters: { id: { eq: $id } }) {\n nodes {\n id\n cookies\n username\n password\n userAgent\n createdAt\n updatedAt\n credentialType\n }\n }\n }\n": typeof types.GetCredential3rdDetailDocument,
"\n query CheckCredential3rdAvailable($id: Int!) {\n credential3rdCheckAvailable(filter: { id: $id }) {\n available\n }\n }\n": typeof types.CheckCredential3rdAvailableDocument,
"\n query GetSubscriptions($filters: SubscriptionsFilterInput!, $orderBy: SubscriptionsOrderInput!, $pagination: PaginationInput!) {\n subscriptions(\n pagination: $pagination\n filters: $filters\n orderBy: $orderBy\n ) {\n nodes {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n credentialId\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": typeof types.GetSubscriptionsDocument,
"\n mutation InsertSubscription($data: SubscriptionsInsertInput!) {\n subscriptionsCreateOne(data: $data) {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n credentialId\n }\n }\n": typeof types.InsertSubscriptionDocument,
"\n mutation UpdateSubscriptions(\n $data: SubscriptionsUpdateInput!,\n $filters: SubscriptionsFilterInput!,\n ) {\n subscriptionsUpdate (\n data: $data\n filter: $filters\n ) {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n }\n}\n": typeof types.UpdateSubscriptionsDocument,
"\n mutation DeleteSubscriptions($filters: SubscriptionsFilterInput) {\n subscriptionsDelete(filter: $filters)\n }\n": typeof types.DeleteSubscriptionsDocument,
"\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filters: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n credential3rd {\n id\n username\n }\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n rawName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n savePath\n homepage\n }\n }\n }\n }\n}\n": typeof types.GetSubscriptionDetailDocument,
"\n mutation SyncSubscriptionFeedsIncremental($id: Int!) {\n subscriptionSyncOneFeedsIncremental(filter: { id: $id }) {\n taskId\n }\n }\n": typeof types.SyncSubscriptionFeedsIncrementalDocument,
"\n mutation SyncSubscriptionFeedsFull($id: Int!) {\n subscriptionSyncOneFeedsFull(filter: { id: $id }) {\n taskId\n }\n }\n": typeof types.SyncSubscriptionFeedsFullDocument,
"\n mutation SyncSubscriptionSources($id: Int!) {\n subscriptionSyncOneSources(filter: { id: $id }) {\n taskId\n }\n }\n": typeof types.SyncSubscriptionSourcesDocument,
};
const documents: Documents = {
"\n query GetCredential3rd($filters: Credential3rdFilterInput!, $orderBy: Credential3rdOrderInput, $pagination: PaginationInput) {\n credential3rd(filters: $filters, orderBy: $orderBy, pagination: $pagination) {\n nodes {\n id\n cookies\n username\n password\n userAgent\n createdAt\n updatedAt\n credentialType\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": types.GetCredential3rdDocument,
@@ -31,11 +35,15 @@ const documents: Documents = {
"\n mutation UpdateCredential3rd($data: Credential3rdUpdateInput!, $filters: Credential3rdFilterInput!) {\n credential3rdUpdate(data: $data, filter: $filters) {\n id\n cookies\n username\n password\n userAgent\n createdAt\n updatedAt\n credentialType\n }\n }\n": types.UpdateCredential3rdDocument,
"\n mutation DeleteCredential3rd($filters: Credential3rdFilterInput!) {\n credential3rdDelete(filter: $filters)\n }\n": types.DeleteCredential3rdDocument,
"\n query GetCredential3rdDetail($id: Int!) {\n credential3rd(filters: { id: { eq: $id } }) {\n nodes {\n id\n cookies\n username\n password\n userAgent\n createdAt\n updatedAt\n credentialType\n }\n }\n }\n": types.GetCredential3rdDetailDocument,
"\n query CheckCredential3rdAvailable($id: Int!) {\n credential3rdCheckAvailable(filter: { id: $id }) {\n available\n }\n }\n": types.CheckCredential3rdAvailableDocument,
"\n query GetSubscriptions($filters: SubscriptionsFilterInput!, $orderBy: SubscriptionsOrderInput!, $pagination: PaginationInput!) {\n subscriptions(\n pagination: $pagination\n filters: $filters\n orderBy: $orderBy\n ) {\n nodes {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n credentialId\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": types.GetSubscriptionsDocument,
"\n mutation InsertSubscription($data: SubscriptionsInsertInput!) {\n subscriptionsCreateOne(data: $data) {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n credentialId\n }\n }\n": types.InsertSubscriptionDocument,
"\n mutation UpdateSubscriptions(\n $data: SubscriptionsUpdateInput!,\n $filters: SubscriptionsFilterInput!,\n ) {\n subscriptionsUpdate (\n data: $data\n filter: $filters\n ) {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n }\n}\n": types.UpdateSubscriptionsDocument,
"\n mutation DeleteSubscriptions($filters: SubscriptionsFilterInput) {\n subscriptionsDelete(filter: $filters)\n }\n": types.DeleteSubscriptionsDocument,
"\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filters: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n credential3rd {\n id\n username\n }\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n rawName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n savePath\n homepage\n }\n }\n }\n }\n}\n": types.GetSubscriptionDetailDocument,
"\n mutation SyncSubscriptionFeedsIncremental($id: Int!) {\n subscriptionSyncOneFeedsIncremental(filter: { id: $id }) {\n taskId\n }\n }\n": types.SyncSubscriptionFeedsIncrementalDocument,
"\n mutation SyncSubscriptionFeedsFull($id: Int!) {\n subscriptionSyncOneFeedsFull(filter: { id: $id }) {\n taskId\n }\n }\n": types.SyncSubscriptionFeedsFullDocument,
"\n mutation SyncSubscriptionSources($id: Int!) {\n subscriptionSyncOneSources(filter: { id: $id }) {\n taskId\n }\n }\n": types.SyncSubscriptionSourcesDocument,
};
/**
@@ -72,6 +80,10 @@ export function gql(source: "\n mutation DeleteCredential3rd($filters: Credenti
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: "\n query GetCredential3rdDetail($id: Int!) {\n credential3rd(filters: { id: { eq: $id } }) {\n nodes {\n id\n cookies\n username\n password\n userAgent\n createdAt\n updatedAt\n credentialType\n }\n }\n }\n"): (typeof documents)["\n query GetCredential3rdDetail($id: Int!) {\n credential3rd(filters: { id: { eq: $id } }) {\n nodes {\n id\n cookies\n username\n password\n userAgent\n createdAt\n updatedAt\n credentialType\n }\n }\n }\n"];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: "\n query CheckCredential3rdAvailable($id: Int!) {\n credential3rdCheckAvailable(filter: { id: $id }) {\n available\n }\n }\n"): (typeof documents)["\n query CheckCredential3rdAvailable($id: Int!) {\n credential3rdCheckAvailable(filter: { id: $id }) {\n available\n }\n }\n"];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -92,6 +104,18 @@ export function gql(source: "\n mutation DeleteSubscriptions($filters: Subscr
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: "\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filters: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n credential3rd {\n id\n username\n }\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n rawName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n savePath\n homepage\n }\n }\n }\n }\n}\n"): (typeof documents)["\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filters: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n credential3rd {\n id\n username\n }\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n rawName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n savePath\n homepage\n }\n }\n }\n }\n}\n"];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: "\n mutation SyncSubscriptionFeedsIncremental($id: Int!) {\n subscriptionSyncOneFeedsIncremental(filter: { id: $id }) {\n taskId\n }\n }\n"): (typeof documents)["\n mutation SyncSubscriptionFeedsIncremental($id: Int!) {\n subscriptionSyncOneFeedsIncremental(filter: { id: $id }) {\n taskId\n }\n }\n"];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: "\n mutation SyncSubscriptionFeedsFull($id: Int!) {\n subscriptionSyncOneFeedsFull(filter: { id: $id }) {\n taskId\n }\n }\n"): (typeof documents)["\n mutation SyncSubscriptionFeedsFull($id: Int!) {\n subscriptionSyncOneFeedsFull(filter: { id: $id }) {\n taskId\n }\n }\n"];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: "\n mutation SyncSubscriptionSources($id: Int!) {\n subscriptionSyncOneSources(filter: { id: $id }) {\n taskId\n }\n }\n"): (typeof documents)["\n mutation SyncSubscriptionSources($id: Int!) {\n subscriptionSyncOneSources(filter: { id: $id }) {\n taskId\n }\n }\n"];
export function gql(source: string) {
return (documents as any)[source] ?? {};

View File

@@ -216,6 +216,17 @@ export type Credential3rdBasic = {
username?: Maybe<Scalars['String']['output']>;
};
/** The output of the credential3rdCheckAvailable query */
export type Credential3rdCheckAvailableInfo = {
__typename?: 'Credential3rdCheckAvailableInfo';
available: Scalars['Boolean']['output'];
};
/** The input of the credential3rdCheckAvailable query */
export type Credential3rdCheckAvailableInput = {
id: Scalars['Int']['input'];
};
export type Credential3rdConnection = {
__typename?: 'Credential3rdConnection';
edges: Array<Credential3rdEdge>;
@@ -805,6 +816,8 @@ export type Mutation = {
subscriptionEpisodeCreateOne: SubscriptionEpisodeBasic;
subscriptionEpisodeDelete: Scalars['Int']['output'];
subscriptionEpisodeUpdate: Array<SubscriptionEpisodeBasic>;
subscriptionSyncOneFeedsFull: SyncOneSubscriptionInfo;
subscriptionSyncOneFeedsIncremental: SyncOneSubscriptionInfo;
subscriptionSyncOneSources: SyncOneSubscriptionInfo;
subscriptionsCreateBatch: Array<SubscriptionsBasic>;
subscriptionsCreateOne: SubscriptionsBasic;
@@ -981,6 +994,16 @@ export type MutationSubscriptionEpisodeUpdateArgs = {
};
export type MutationSubscriptionSyncOneFeedsFullArgs = {
filter: SyncOneSubscriptionFilterInput;
};
export type MutationSubscriptionSyncOneFeedsIncrementalArgs = {
filter: SyncOneSubscriptionFilterInput;
};
export type MutationSubscriptionSyncOneSourcesArgs = {
filter: SyncOneSubscriptionFilterInput;
};
@@ -1049,6 +1072,7 @@ export type Query = {
_sea_orm_entity_metadata?: Maybe<Scalars['String']['output']>;
bangumi: BangumiConnection;
credential3rd: Credential3rdConnection;
credential3rdCheckAvailable: Credential3rdCheckAvailableInfo;
downloaders: DownloadersConnection;
downloads: DownloadsConnection;
episodes: EpisodesConnection;
@@ -1056,8 +1080,6 @@ export type Query = {
subscribers: SubscribersConnection;
subscriptionBangumi: SubscriptionBangumiConnection;
subscriptionEpisode: SubscriptionEpisodeConnection;
subscriptionSyncOneFeedsFull: SyncOneSubscriptionInfo;
subscriptionSyncOneFeedsIncremental: SyncOneSubscriptionInfo;
subscriptions: SubscriptionsConnection;
};
@@ -1081,6 +1103,11 @@ export type QueryCredential3rdArgs = {
};
export type QueryCredential3rdCheckAvailableArgs = {
filter: Credential3rdCheckAvailableInput;
};
export type QueryDownloadersArgs = {
filters?: InputMaybe<DownloadersFilterInput>;
orderBy?: InputMaybe<DownloadersOrderInput>;
@@ -1130,16 +1157,6 @@ export type QuerySubscriptionEpisodeArgs = {
};
export type QuerySubscriptionSyncOneFeedsFullArgs = {
filter: SyncOneSubscriptionFilterInput;
};
export type QuerySubscriptionSyncOneFeedsIncrementalArgs = {
filter: SyncOneSubscriptionFilterInput;
};
export type QuerySubscriptionsArgs = {
filters?: InputMaybe<SubscriptionsFilterInput>;
orderBy?: InputMaybe<SubscriptionsOrderInput>;
@@ -1616,7 +1633,7 @@ export type SubscriptionsUpdateInput = {
/** The input of the subscriptionSyncOne series of mutations */
export type SyncOneSubscriptionFilterInput = {
subscriptionId: Scalars['Int']['input'];
id: Scalars['Int']['input'];
};
/** The output of the subscriptionSyncOne series of mutations */
@@ -1678,6 +1695,13 @@ export type GetCredential3rdDetailQueryVariables = Exact<{
export type GetCredential3rdDetailQuery = { __typename?: 'Query', credential3rd: { __typename?: 'Credential3rdConnection', nodes: Array<{ __typename?: 'Credential3rd', id: number, cookies?: string | null, username?: string | null, password?: string | null, userAgent?: string | null, createdAt: string, updatedAt: string, credentialType: Credential3rdTypeEnum }> } };
export type CheckCredential3rdAvailableQueryVariables = Exact<{
id: Scalars['Int']['input'];
}>;
export type CheckCredential3rdAvailableQuery = { __typename?: 'Query', credential3rdCheckAvailable: { __typename?: 'Credential3rdCheckAvailableInfo', available: boolean } };
export type GetSubscriptionsQueryVariables = Exact<{
filters: SubscriptionsFilterInput;
orderBy: SubscriptionsOrderInput;
@@ -1716,14 +1740,39 @@ export type GetSubscriptionDetailQueryVariables = Exact<{
export type GetSubscriptionDetailQuery = { __typename?: 'Query', subscriptions: { __typename?: 'SubscriptionsConnection', nodes: Array<{ __typename?: 'Subscriptions', id: number, displayName: string, createdAt: string, updatedAt: string, category: SubscriptionCategoryEnum, sourceUrl: string, enabled: boolean, credential3rd?: { __typename?: 'Credential3rd', id: number, username?: string | null } | null, bangumi: { __typename?: 'BangumiConnection', nodes: Array<{ __typename?: 'Bangumi', createdAt: string, updatedAt: string, id: number, mikanBangumiId?: string | null, displayName: string, rawName: string, season: number, seasonRaw?: string | null, fansub?: string | null, mikanFansubId?: string | null, rssLink?: string | null, posterLink?: string | null, savePath?: string | null, homepage?: string | null }> } }> } };
export type SyncSubscriptionFeedsIncrementalMutationVariables = Exact<{
id: Scalars['Int']['input'];
}>;
export type SyncSubscriptionFeedsIncrementalMutation = { __typename?: 'Mutation', subscriptionSyncOneFeedsIncremental: { __typename?: 'SyncOneSubscriptionInfo', taskId: string } };
export type SyncSubscriptionFeedsFullMutationVariables = Exact<{
id: Scalars['Int']['input'];
}>;
export type SyncSubscriptionFeedsFullMutation = { __typename?: 'Mutation', subscriptionSyncOneFeedsFull: { __typename?: 'SyncOneSubscriptionInfo', taskId: string } };
export type SyncSubscriptionSourcesMutationVariables = Exact<{
id: Scalars['Int']['input'];
}>;
export type SyncSubscriptionSourcesMutation = { __typename?: 'Mutation', subscriptionSyncOneSources: { __typename?: 'SyncOneSubscriptionInfo', taskId: string } };
export const GetCredential3rdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetCredential3rd"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Credential3rdFilterInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Credential3rdOrderInput"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"PaginationInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"credential3rd"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}},{"kind":"Argument","name":{"kind":"Name","value":"orderBy"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}}},{"kind":"Argument","name":{"kind":"Name","value":"pagination"},"value":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"cookies"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"password"}},{"kind":"Field","name":{"kind":"Name","value":"userAgent"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"credentialType"}}]}},{"kind":"Field","name":{"kind":"Name","value":"paginationInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total"}},{"kind":"Field","name":{"kind":"Name","value":"pages"}}]}}]}}]}}]} as unknown as DocumentNode<GetCredential3rdQuery, GetCredential3rdQueryVariables>;
export const InsertCredential3rdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"InsertCredential3rd"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Credential3rdInsertInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"credential3rdCreateOne"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"cookies"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"password"}},{"kind":"Field","name":{"kind":"Name","value":"userAgent"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"credentialType"}}]}}]}}]} as unknown as DocumentNode<InsertCredential3rdMutation, InsertCredential3rdMutationVariables>;
export const UpdateCredential3rdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateCredential3rd"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Credential3rdUpdateInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Credential3rdFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"credential3rdUpdate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"cookies"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"password"}},{"kind":"Field","name":{"kind":"Name","value":"userAgent"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"credentialType"}}]}}]}}]} as unknown as DocumentNode<UpdateCredential3rdMutation, UpdateCredential3rdMutationVariables>;
export const DeleteCredential3rdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteCredential3rd"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Credential3rdFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"credential3rdDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}}]}]}}]} as unknown as DocumentNode<DeleteCredential3rdMutation, DeleteCredential3rdMutationVariables>;
export const GetCredential3rdDetailDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetCredential3rdDetail"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"credential3rd"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"cookies"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"password"}},{"kind":"Field","name":{"kind":"Name","value":"userAgent"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"credentialType"}}]}}]}}]}}]} as unknown as DocumentNode<GetCredential3rdDetailQuery, GetCredential3rdDetailQueryVariables>;
export const CheckCredential3rdAvailableDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CheckCredential3rdAvailable"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"credential3rdCheckAvailable"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"available"}}]}}]}}]} as unknown as DocumentNode<CheckCredential3rdAvailableQuery, CheckCredential3rdAvailableQueryVariables>;
export const GetSubscriptionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSubscriptions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsFilterInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsOrderInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"PaginationInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"pagination"},"value":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}}},{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}},{"kind":"Argument","name":{"kind":"Name","value":"orderBy"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrl"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"credentialId"}}]}},{"kind":"Field","name":{"kind":"Name","value":"paginationInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total"}},{"kind":"Field","name":{"kind":"Name","value":"pages"}}]}}]}}]}}]} as unknown as DocumentNode<GetSubscriptionsQuery, GetSubscriptionsQueryVariables>;
export const InsertSubscriptionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"InsertSubscription"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsInsertInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptionsCreateOne"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrl"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"credentialId"}}]}}]}}]} as unknown as DocumentNode<InsertSubscriptionMutation, InsertSubscriptionMutationVariables>;
export const UpdateSubscriptionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateSubscriptions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsUpdateInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptionsUpdate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrl"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}}]}}]}}]} as unknown as DocumentNode<UpdateSubscriptionsMutation, UpdateSubscriptionsMutationVariables>;
export const DeleteSubscriptionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteSubscriptions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsFilterInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptionsDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}}]}]}}]} as unknown as DocumentNode<DeleteSubscriptionsMutation, DeleteSubscriptionsMutationVariables>;
export const GetSubscriptionDetailDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSubscriptionDetail"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrl"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"credential3rd"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"bangumi"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"mikanBangumiId"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"rawName"}},{"kind":"Field","name":{"kind":"Name","value":"season"}},{"kind":"Field","name":{"kind":"Name","value":"seasonRaw"}},{"kind":"Field","name":{"kind":"Name","value":"fansub"}},{"kind":"Field","name":{"kind":"Name","value":"mikanFansubId"}},{"kind":"Field","name":{"kind":"Name","value":"rssLink"}},{"kind":"Field","name":{"kind":"Name","value":"posterLink"}},{"kind":"Field","name":{"kind":"Name","value":"savePath"}},{"kind":"Field","name":{"kind":"Name","value":"homepage"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode<GetSubscriptionDetailQuery, GetSubscriptionDetailQueryVariables>;
export const GetSubscriptionDetailDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSubscriptionDetail"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrl"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"credential3rd"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"bangumi"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"mikanBangumiId"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"rawName"}},{"kind":"Field","name":{"kind":"Name","value":"season"}},{"kind":"Field","name":{"kind":"Name","value":"seasonRaw"}},{"kind":"Field","name":{"kind":"Name","value":"fansub"}},{"kind":"Field","name":{"kind":"Name","value":"mikanFansubId"}},{"kind":"Field","name":{"kind":"Name","value":"rssLink"}},{"kind":"Field","name":{"kind":"Name","value":"posterLink"}},{"kind":"Field","name":{"kind":"Name","value":"savePath"}},{"kind":"Field","name":{"kind":"Name","value":"homepage"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode<GetSubscriptionDetailQuery, GetSubscriptionDetailQueryVariables>;
export const SyncSubscriptionFeedsIncrementalDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SyncSubscriptionFeedsIncremental"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptionSyncOneFeedsIncremental"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"taskId"}}]}}]}}]} as unknown as DocumentNode<SyncSubscriptionFeedsIncrementalMutation, SyncSubscriptionFeedsIncrementalMutationVariables>;
export const SyncSubscriptionFeedsFullDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SyncSubscriptionFeedsFull"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptionSyncOneFeedsFull"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"taskId"}}]}}]}}]} as unknown as DocumentNode<SyncSubscriptionFeedsFullMutation, SyncSubscriptionFeedsFullMutationVariables>;
export const SyncSubscriptionSourcesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SyncSubscriptionSources"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptionSyncOneSources"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"taskId"}}]}}]}}]} as unknown as DocumentNode<SyncSubscriptionSourcesMutation, SyncSubscriptionSourcesMutationVariables>;

View File

@@ -22,6 +22,17 @@ export class GraphQLService {
_apollo = new ApolloClient({
link: this.authLink.concat(this.apiLink),
cache: new InMemoryCache(),
defaultOptions: {
watchQuery: {
fetchPolicy: 'cache-and-network',
nextFetchPolicy: 'network-only',
errorPolicy: 'all',
},
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
},
});
query = this._apollo.query;

View File

@@ -17,12 +17,14 @@ import { Route as AppRouteImport } from './routes/_app/route'
import { Route as IndexImport } from './routes/index'
import { Route as AuthSignUpImport } from './routes/auth/sign-up'
import { Route as AuthSignInImport } from './routes/auth/sign-in'
import { Route as AppTasksRouteImport } from './routes/_app/tasks/route'
import { Route as AppSubscriptionsRouteImport } from './routes/_app/subscriptions/route'
import { Route as AppSettingsRouteImport } from './routes/_app/settings/route'
import { Route as AppPlaygroundRouteImport } from './routes/_app/playground/route'
import { Route as AppCredential3rdRouteImport } from './routes/_app/credential3rd/route'
import { Route as AppBangumiRouteImport } from './routes/_app/bangumi/route'
import { Route as AuthOidcCallbackImport } from './routes/auth/oidc/callback'
import { Route as AppTasksManageImport } from './routes/_app/tasks/manage'
import { Route as AppSubscriptionsManageImport } from './routes/_app/subscriptions/manage'
import { Route as AppSubscriptionsCreateImport } from './routes/_app/subscriptions/create'
import { Route as AppSettingsDownloaderImport } from './routes/_app/settings/downloader'
@@ -32,6 +34,7 @@ import { Route as AppCredential3rdCreateImport } from './routes/_app/credential3
import { Route as AppBangumiManageImport } from './routes/_app/bangumi/manage'
import { Route as AppExploreFeedImport } from './routes/_app/_explore/feed'
import { Route as AppExploreExploreImport } from './routes/_app/_explore/explore'
import { Route as AppTasksDetailIdImport } from './routes/_app/tasks/detail.$id'
import { Route as AppSubscriptionsEditIdImport } from './routes/_app/subscriptions/edit.$id'
import { Route as AppSubscriptionsDetailIdImport } from './routes/_app/subscriptions/detail.$id'
import { Route as AppCredential3rdEditIdImport } from './routes/_app/credential3rd/edit.$id'
@@ -74,6 +77,12 @@ const AuthSignInRoute = AuthSignInImport.update({
getParentRoute: () => rootRoute,
} as any)
const AppTasksRouteRoute = AppTasksRouteImport.update({
id: '/tasks',
path: '/tasks',
getParentRoute: () => AppRouteRoute,
} as any)
const AppSubscriptionsRouteRoute = AppSubscriptionsRouteImport.update({
id: '/subscriptions',
path: '/subscriptions',
@@ -110,6 +119,12 @@ const AuthOidcCallbackRoute = AuthOidcCallbackImport.update({
getParentRoute: () => rootRoute,
} as any)
const AppTasksManageRoute = AppTasksManageImport.update({
id: '/manage',
path: '/manage',
getParentRoute: () => AppTasksRouteRoute,
} as any)
const AppSubscriptionsManageRoute = AppSubscriptionsManageImport.update({
id: '/manage',
path: '/manage',
@@ -166,6 +181,12 @@ const AppExploreExploreRoute = AppExploreExploreImport.update({
getParentRoute: () => AppRouteRoute,
} as any)
const AppTasksDetailIdRoute = AppTasksDetailIdImport.update({
id: '/detail/$id',
path: '/detail/$id',
getParentRoute: () => AppTasksRouteRoute,
} as any)
const AppSubscriptionsEditIdRoute = AppSubscriptionsEditIdImport.update({
id: '/edit/$id',
path: '/edit/$id',
@@ -257,6 +278,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppSubscriptionsRouteImport
parentRoute: typeof AppRouteImport
}
'/_app/tasks': {
id: '/_app/tasks'
path: '/tasks'
fullPath: '/tasks'
preLoaderRoute: typeof AppTasksRouteImport
parentRoute: typeof AppRouteImport
}
'/auth/sign-in': {
id: '/auth/sign-in'
path: '/auth/sign-in'
@@ -334,6 +362,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppSubscriptionsManageImport
parentRoute: typeof AppSubscriptionsRouteImport
}
'/_app/tasks/manage': {
id: '/_app/tasks/manage'
path: '/manage'
fullPath: '/tasks/manage'
preLoaderRoute: typeof AppTasksManageImport
parentRoute: typeof AppTasksRouteImport
}
'/auth/oidc/callback': {
id: '/auth/oidc/callback'
path: '/auth/oidc/callback'
@@ -369,6 +404,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppSubscriptionsEditIdImport
parentRoute: typeof AppSubscriptionsRouteImport
}
'/_app/tasks/detail/$id': {
id: '/_app/tasks/detail/$id'
path: '/detail/$id'
fullPath: '/tasks/detail/$id'
preLoaderRoute: typeof AppTasksDetailIdImport
parentRoute: typeof AppTasksRouteImport
}
}
}
@@ -446,12 +488,27 @@ const AppSubscriptionsRouteRouteWithChildren =
AppSubscriptionsRouteRouteChildren,
)
interface AppTasksRouteRouteChildren {
AppTasksManageRoute: typeof AppTasksManageRoute
AppTasksDetailIdRoute: typeof AppTasksDetailIdRoute
}
const AppTasksRouteRouteChildren: AppTasksRouteRouteChildren = {
AppTasksManageRoute: AppTasksManageRoute,
AppTasksDetailIdRoute: AppTasksDetailIdRoute,
}
const AppTasksRouteRouteWithChildren = AppTasksRouteRoute._addFileChildren(
AppTasksRouteRouteChildren,
)
interface AppRouteRouteChildren {
AppBangumiRouteRoute: typeof AppBangumiRouteRouteWithChildren
AppCredential3rdRouteRoute: typeof AppCredential3rdRouteRouteWithChildren
AppPlaygroundRouteRoute: typeof AppPlaygroundRouteRouteWithChildren
AppSettingsRouteRoute: typeof AppSettingsRouteRouteWithChildren
AppSubscriptionsRouteRoute: typeof AppSubscriptionsRouteRouteWithChildren
AppTasksRouteRoute: typeof AppTasksRouteRouteWithChildren
AppExploreExploreRoute: typeof AppExploreExploreRoute
AppExploreFeedRoute: typeof AppExploreFeedRoute
}
@@ -462,6 +519,7 @@ const AppRouteRouteChildren: AppRouteRouteChildren = {
AppPlaygroundRouteRoute: AppPlaygroundRouteRouteWithChildren,
AppSettingsRouteRoute: AppSettingsRouteRouteWithChildren,
AppSubscriptionsRouteRoute: AppSubscriptionsRouteRouteWithChildren,
AppTasksRouteRoute: AppTasksRouteRouteWithChildren,
AppExploreExploreRoute: AppExploreExploreRoute,
AppExploreFeedRoute: AppExploreFeedRoute,
}
@@ -480,6 +538,7 @@ export interface FileRoutesByFullPath {
'/playground': typeof AppPlaygroundRouteRouteWithChildren
'/settings': typeof AppSettingsRouteRouteWithChildren
'/subscriptions': typeof AppSubscriptionsRouteRouteWithChildren
'/tasks': typeof AppTasksRouteRouteWithChildren
'/auth/sign-in': typeof AuthSignInRoute
'/auth/sign-up': typeof AuthSignUpRoute
'/explore': typeof AppExploreExploreRoute
@@ -491,11 +550,13 @@ export interface FileRoutesByFullPath {
'/settings/downloader': typeof AppSettingsDownloaderRoute
'/subscriptions/create': typeof AppSubscriptionsCreateRoute
'/subscriptions/manage': typeof AppSubscriptionsManageRoute
'/tasks/manage': typeof AppTasksManageRoute
'/auth/oidc/callback': typeof AuthOidcCallbackRoute
'/credential3rd/detail/$id': typeof AppCredential3rdDetailIdRoute
'/credential3rd/edit/$id': typeof AppCredential3rdEditIdRoute
'/subscriptions/detail/$id': typeof AppSubscriptionsDetailIdRoute
'/subscriptions/edit/$id': typeof AppSubscriptionsEditIdRoute
'/tasks/detail/$id': typeof AppTasksDetailIdRoute
}
export interface FileRoutesByTo {
@@ -508,6 +569,7 @@ export interface FileRoutesByTo {
'/playground': typeof AppPlaygroundRouteRouteWithChildren
'/settings': typeof AppSettingsRouteRouteWithChildren
'/subscriptions': typeof AppSubscriptionsRouteRouteWithChildren
'/tasks': typeof AppTasksRouteRouteWithChildren
'/auth/sign-in': typeof AuthSignInRoute
'/auth/sign-up': typeof AuthSignUpRoute
'/explore': typeof AppExploreExploreRoute
@@ -519,11 +581,13 @@ export interface FileRoutesByTo {
'/settings/downloader': typeof AppSettingsDownloaderRoute
'/subscriptions/create': typeof AppSubscriptionsCreateRoute
'/subscriptions/manage': typeof AppSubscriptionsManageRoute
'/tasks/manage': typeof AppTasksManageRoute
'/auth/oidc/callback': typeof AuthOidcCallbackRoute
'/credential3rd/detail/$id': typeof AppCredential3rdDetailIdRoute
'/credential3rd/edit/$id': typeof AppCredential3rdEditIdRoute
'/subscriptions/detail/$id': typeof AppSubscriptionsDetailIdRoute
'/subscriptions/edit/$id': typeof AppSubscriptionsEditIdRoute
'/tasks/detail/$id': typeof AppTasksDetailIdRoute
}
export interface FileRoutesById {
@@ -537,6 +601,7 @@ export interface FileRoutesById {
'/_app/playground': typeof AppPlaygroundRouteRouteWithChildren
'/_app/settings': typeof AppSettingsRouteRouteWithChildren
'/_app/subscriptions': typeof AppSubscriptionsRouteRouteWithChildren
'/_app/tasks': typeof AppTasksRouteRouteWithChildren
'/auth/sign-in': typeof AuthSignInRoute
'/auth/sign-up': typeof AuthSignUpRoute
'/_app/_explore/explore': typeof AppExploreExploreRoute
@@ -548,11 +613,13 @@ export interface FileRoutesById {
'/_app/settings/downloader': typeof AppSettingsDownloaderRoute
'/_app/subscriptions/create': typeof AppSubscriptionsCreateRoute
'/_app/subscriptions/manage': typeof AppSubscriptionsManageRoute
'/_app/tasks/manage': typeof AppTasksManageRoute
'/auth/oidc/callback': typeof AuthOidcCallbackRoute
'/_app/credential3rd/detail/$id': typeof AppCredential3rdDetailIdRoute
'/_app/credential3rd/edit/$id': typeof AppCredential3rdEditIdRoute
'/_app/subscriptions/detail/$id': typeof AppSubscriptionsDetailIdRoute
'/_app/subscriptions/edit/$id': typeof AppSubscriptionsEditIdRoute
'/_app/tasks/detail/$id': typeof AppTasksDetailIdRoute
}
export interface FileRouteTypes {
@@ -567,6 +634,7 @@ export interface FileRouteTypes {
| '/playground'
| '/settings'
| '/subscriptions'
| '/tasks'
| '/auth/sign-in'
| '/auth/sign-up'
| '/explore'
@@ -578,11 +646,13 @@ export interface FileRouteTypes {
| '/settings/downloader'
| '/subscriptions/create'
| '/subscriptions/manage'
| '/tasks/manage'
| '/auth/oidc/callback'
| '/credential3rd/detail/$id'
| '/credential3rd/edit/$id'
| '/subscriptions/detail/$id'
| '/subscriptions/edit/$id'
| '/tasks/detail/$id'
fileRoutesByTo: FileRoutesByTo
to:
| '/'
@@ -594,6 +664,7 @@ export interface FileRouteTypes {
| '/playground'
| '/settings'
| '/subscriptions'
| '/tasks'
| '/auth/sign-in'
| '/auth/sign-up'
| '/explore'
@@ -605,11 +676,13 @@ export interface FileRouteTypes {
| '/settings/downloader'
| '/subscriptions/create'
| '/subscriptions/manage'
| '/tasks/manage'
| '/auth/oidc/callback'
| '/credential3rd/detail/$id'
| '/credential3rd/edit/$id'
| '/subscriptions/detail/$id'
| '/subscriptions/edit/$id'
| '/tasks/detail/$id'
id:
| '__root__'
| '/'
@@ -621,6 +694,7 @@ export interface FileRouteTypes {
| '/_app/playground'
| '/_app/settings'
| '/_app/subscriptions'
| '/_app/tasks'
| '/auth/sign-in'
| '/auth/sign-up'
| '/_app/_explore/explore'
@@ -632,11 +706,13 @@ export interface FileRouteTypes {
| '/_app/settings/downloader'
| '/_app/subscriptions/create'
| '/_app/subscriptions/manage'
| '/_app/tasks/manage'
| '/auth/oidc/callback'
| '/_app/credential3rd/detail/$id'
| '/_app/credential3rd/edit/$id'
| '/_app/subscriptions/detail/$id'
| '/_app/subscriptions/edit/$id'
| '/_app/tasks/detail/$id'
fileRoutesById: FileRoutesById
}
@@ -690,6 +766,7 @@ export const routeTree = rootRoute
"/_app/playground",
"/_app/settings",
"/_app/subscriptions",
"/_app/tasks",
"/_app/_explore/explore",
"/_app/_explore/feed"
]
@@ -741,6 +818,14 @@ export const routeTree = rootRoute
"/_app/subscriptions/edit/$id"
]
},
"/_app/tasks": {
"filePath": "_app/tasks/route.tsx",
"parent": "/_app",
"children": [
"/_app/tasks/manage",
"/_app/tasks/detail/$id"
]
},
"/auth/sign-in": {
"filePath": "auth/sign-in.tsx"
},
@@ -783,6 +868,10 @@ export const routeTree = rootRoute
"filePath": "_app/subscriptions/manage.tsx",
"parent": "/_app/subscriptions"
},
"/_app/tasks/manage": {
"filePath": "_app/tasks/manage.tsx",
"parent": "/_app/tasks"
},
"/auth/oidc/callback": {
"filePath": "auth/oidc/callback.tsx"
},
@@ -801,6 +890,10 @@ export const routeTree = rootRoute
"/_app/subscriptions/edit/$id": {
"filePath": "_app/subscriptions/edit.$id.tsx",
"parent": "/_app/subscriptions"
},
"/_app/tasks/detail/$id": {
"filePath": "_app/tasks/detail.$id.tsx",
"parent": "/_app/tasks"
}
}
}

View File

@@ -0,0 +1,92 @@
import { Button } from '@/components/ui/button';
import {
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { CHECK_CREDENTIAL_3RD_AVAILABLE } from '@/domains/recorder/schema/credential3rd';
import {
apolloErrorToMessage,
getApolloQueryError,
} from '@/infra/errors/apollo';
import type { CheckCredential3rdAvailableQuery } from '@/infra/graphql/gql/graphql';
import { useLazyQuery } from '@apollo/client';
import { CheckIcon, Loader2, XIcon } from 'lucide-react';
import { memo, useCallback } from 'react';
import { toast } from 'sonner';
export interface Credential3rdCheckAvailableViewProps {
id: number;
}
export const Credential3rdCheckAvailableView = memo(
({ id }: Credential3rdCheckAvailableViewProps) => {
const [checkAvailable, { data, error, loading }] =
useLazyQuery<CheckCredential3rdAvailableQuery>(
CHECK_CREDENTIAL_3RD_AVAILABLE,
{
variables: { id },
}
);
const handleCheckAvailable = useCallback(async () => {
const checkResult = await checkAvailable();
const error = getApolloQueryError(checkResult);
console.error('error', error);
if (error) {
toast.error('Failed to check available', {
description: apolloErrorToMessage(error),
});
return;
}
if (checkResult.data?.credential3rdCheckAvailable.available) {
toast.success('Credential is available');
} else {
toast.error('Credential is not available');
}
}, [checkAvailable]);
const available = data?.credential3rdCheckAvailable?.available;
return (
<div className="flex flex-col gap-2">
<Button
variant="outline"
size="lg"
onClick={handleCheckAvailable}
disabled={loading}
>
<span> Check Available </span>
{available === true && (
<CheckIcon className="h-4 w-4 text-green-300" />
)}
{(available === false || !!error) && (
<XIcon className="h-4 w-4 text-red-500" />
)}
{loading && <Loader2 className="h-4 w-4 animate-spin" />}
</Button>
</div>
);
}
);
export interface Credential3rdCheckAvailableViewDialogContentProps {
id: number;
}
export const Credential3rdCheckAvailableViewDialogContent = memo(
({ id }: Credential3rdCheckAvailableViewDialogContentProps) => {
return (
<DialogContent>
<DialogHeader>
<DialogTitle>Check Available</DialogTitle>
<DialogDescription>
Check if the credential is available.
</DialogDescription>
</DialogHeader>
<Credential3rdCheckAvailableView id={id} />
</DialogContent>
);
}
);

View File

@@ -9,6 +9,7 @@ import {
CardTitle,
} from '@/components/ui/card';
import { DetailEmptyView } from '@/components/ui/detail-empty-view';
import { Dialog, DialogTrigger } from '@/components/ui/dialog';
import { Label } from '@/components/ui/label';
import { QueryErrorView } from '@/components/ui/query-error-view';
import { Separator } from '@/components/ui/separator';
@@ -23,8 +24,9 @@ import {
useRouter,
} from '@tanstack/react-router';
import { format } from 'date-fns/format';
import { ArrowLeft, Edit, Eye, EyeOff } from 'lucide-react';
import { ArrowLeft, CheckIcon, Edit, Eye, EyeOff } from 'lucide-react';
import { useState } from 'react';
import { Credential3rdCheckAvailableViewDialogContent } from './-check-available';
export const Route = createFileRoute('/_app/credential3rd/detail/$id')({
component: Credential3rdDetailRouteComponent,
@@ -57,7 +59,6 @@ function Credential3rdDetailRouteComponent() {
variables: {
id: Number.parseInt(id),
},
fetchPolicy: 'cache-and-network',
}
);
@@ -125,7 +126,19 @@ function Credential3rdDetailRouteComponent() {
View credential detail
</CardDescription>
</div>
<Badge variant="secondary">{credential.credentialType}</Badge>
<div className="flex items-center gap-2">
<Dialog>
<DialogTrigger asChild>
<Button variant="outline" size="sm">
<CheckIcon className="h-4 w-4" />
Check Available
</Button>
</DialogTrigger>
<Credential3rdCheckAvailableViewDialogContent
id={credential.id}
/>
</Dialog>
</div>
</div>
</CardHeader>
<CardContent>

View File

@@ -27,6 +27,10 @@ import {
GET_CREDENTIAL_3RD_DETAIL,
UPDATE_CREDENTIAL_3RD,
} from '@/domains/recorder/schema/credential3rd';
import {
apolloErrorToMessage,
getApolloQueryError,
} from '@/infra/errors/apollo';
import type {
Credential3rdTypeEnum,
GetCredential3rdDetailQuery,
@@ -260,19 +264,19 @@ function Credential3rdEditRouteComponent() {
variables: {
id: Number.parseInt(id),
},
fetchPolicy: 'cache-and-network',
});
const credential = data?.credential3rd?.nodes?.[0];
const onCompleted = useCallback(async () => {
const refetchResult = await refetch();
if (refetchResult.errors) {
toast('Update credential failed', {
description: refetchResult.errors[0].message,
const error = getApolloQueryError(refetchResult);
if (error) {
toast.error('Update credential failed', {
description: apolloErrorToMessage(error),
});
} else {
toast('Update credential successfully');
toast.success('Update credential successfully');
}
}, [refetch]);

View File

@@ -18,6 +18,10 @@ import {
DELETE_CREDENTIAL_3RD,
GET_CREDENTIAL_3RD,
} from '@/domains/recorder/schema/credential3rd';
import {
apolloErrorToMessage,
getApolloQueryError,
} from '@/infra/errors/apollo';
import type { GetCredential3rdQuery } from '@/infra/graphql/gql/graphql';
import type { RouteStateDataOption } from '@/infra/routes/traits';
import { useDebouncedSkeleton } from '@/presentation/hooks/use-debounded-skeleton';
@@ -79,17 +83,16 @@ function CredentialManageRouteComponent() {
},
},
},
fetchPolicy: 'cache-and-network',
nextFetchPolicy: 'network-only',
}
);
const [deleteCredential] = useMutation(DELETE_CREDENTIAL_3RD, {
onCompleted: async () => {
const refetchResult = await refetch();
if (refetchResult.errors) {
const error = getApolloQueryError(refetchResult);
if (error) {
toast.error('Failed to delete credential', {
description: refetchResult.errors[0].message,
description: apolloErrorToMessage(error),
});
return;
}

View File

@@ -28,8 +28,6 @@ export function Credential3rdSelectContent({
GetCredential3rdQuery,
GetCredential3rdQueryVariables
>(GET_CREDENTIAL_3RD, {
fetchPolicy: 'cache-and-network',
nextFetchPolicy: 'cache-and-network',
variables: {
filters: {
credentialType: {

View File

@@ -0,0 +1,160 @@
import { Button } from '@/components/ui/button';
import {
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { Spinner } from '@/components/ui/spinner';
import {
SYNC_SUBSCRIPTION_FEEDS_FULL,
SYNC_SUBSCRIPTION_FEEDS_INCREMENTAL,
SYNC_SUBSCRIPTION_SOURCES,
} from '@/domains/recorder/schema/subscriptions';
import type {
SyncSubscriptionFeedsFullMutation,
SyncSubscriptionFeedsFullMutationVariables,
SyncSubscriptionFeedsIncrementalMutation,
SyncSubscriptionFeedsIncrementalMutationVariables,
SyncSubscriptionSourcesMutation,
SyncSubscriptionSourcesMutationVariables,
} from '@/infra/graphql/gql/graphql';
import { useMutation } from '@apollo/client';
import { useNavigate } from '@tanstack/react-router';
import { RefreshCcwIcon } from 'lucide-react';
import { memo, useCallback } from 'react';
import { toast } from 'sonner';
export type SubscriptionSyncViewCompletePayload = {
taskId: string;
};
export interface SubscriptionSyncViewProps {
id: number;
onComplete: (payload: SubscriptionSyncViewCompletePayload) => void;
}
export const SubscriptionSyncView = memo(
({ id, onComplete }: SubscriptionSyncViewProps) => {
const [syncSubscriptionFeedsIncremental, { loading: loadingIncremental }] =
useMutation<
SyncSubscriptionFeedsIncrementalMutation,
SyncSubscriptionFeedsIncrementalMutationVariables
>(SYNC_SUBSCRIPTION_FEEDS_INCREMENTAL, {
onCompleted: (data) => {
toast.success('Sync completed');
onComplete(data.subscriptionSyncOneFeedsIncremental);
},
onError: (error) => {
toast.error('Failed to sync subscription', {
description: error.message,
});
},
});
const [syncSubscriptionFeedsFull, { loading: loadingFull }] = useMutation<
SyncSubscriptionFeedsFullMutation,
SyncSubscriptionFeedsFullMutationVariables
>(SYNC_SUBSCRIPTION_FEEDS_FULL, {
onCompleted: (data) => {
toast.success('Sync completed');
onComplete(data.subscriptionSyncOneFeedsFull);
},
onError: (error) => {
toast.error('Failed to sync subscription', {
description: error.message,
});
},
});
const [syncSubscriptionSources, { loading: loadingSources }] = useMutation<
SyncSubscriptionSourcesMutation,
SyncSubscriptionSourcesMutationVariables
>(SYNC_SUBSCRIPTION_SOURCES, {
onCompleted: (data) => {
toast.success('Sync completed');
onComplete(data.subscriptionSyncOneSources);
},
onError: (error) => {
toast.error('Failed to sync subscription', {
description: error.message,
});
},
});
const loading = loadingIncremental || loadingFull || loadingSources;
return (
<div className="flex flex-col gap-2">
<Button
size="lg"
variant="outline"
onClick={() => syncSubscriptionSources({ variables: { id } })}
>
<RefreshCcwIcon className="h-4 w-4" />
<span>Sources</span>
</Button>
<Button
size="lg"
variant="outline"
onClick={() =>
syncSubscriptionFeedsIncremental({ variables: { id } })
}
>
<RefreshCcwIcon className="h-4 w-4" />
<span>Incremental Feeds</span>
</Button>
<Button
size="lg"
variant="outline"
onClick={() => syncSubscriptionFeedsFull({ variables: { id } })}
>
<RefreshCcwIcon className="h-4 w-4" />
<span>Full Feeds</span>
</Button>
{loading && (
<div className="absolute inset-0 flex flex-row items-center justify-center gap-2">
<Spinner variant="circle-filled" size="16" />
<span>Syncing...</span>
</div>
)}
</div>
);
}
);
export interface SubscriptionSyncDialogContentProps {
id: number;
onCancel: VoidFunction;
}
export const SubscriptionSyncDialogContent = memo(
({ id, onCancel }: SubscriptionSyncDialogContentProps) => {
const navigate = useNavigate();
const handleSyncComplete = useCallback(
(payload: SubscriptionSyncViewCompletePayload) => {
navigate({
to: '/tasks/detail/$id',
params: {
id: `${payload.taskId}`,
},
});
},
[navigate]
);
return (
<DialogContent onAbort={onCancel}>
<DialogHeader>
<DialogTitle>Sync Subscription</DialogTitle>
<DialogDescription>
Sync the subscription with sources and feeds.
</DialogDescription>
</DialogHeader>
<SubscriptionSyncView id={id} onComplete={handleSyncComplete} />
</DialogContent>
);
}
);

View File

@@ -9,12 +9,17 @@ import {
CardTitle,
} from '@/components/ui/card';
import { DetailEmptyView } from '@/components/ui/detail-empty-view';
import { Dialog, DialogTrigger } from '@/components/ui/dialog';
import { Label } from '@/components/ui/label';
import { QueryErrorView } from '@/components/ui/query-error-view';
import { Separator } from '@/components/ui/separator';
import { GET_SUBSCRIPTION_DETAIL } from '@/domains/recorder/schema/subscriptions';
import { SubscriptionService } from '@/domains/recorder/services/subscription.service';
import { useInject } from '@/infra/di/inject';
import {
apolloErrorToMessage,
getApolloQueryError,
} from '@/infra/errors/apollo';
import {
type GetSubscriptionDetailQuery,
SubscriptionCategoryEnum,
@@ -27,8 +32,16 @@ import {
useRouter,
} from '@tanstack/react-router';
import { format } from 'date-fns';
import { ArrowLeft, Edit, ExternalLink } from 'lucide-react';
import {
ArrowLeft,
Edit,
ExternalLink,
ListIcon,
RefreshCcwIcon,
} from 'lucide-react';
import { useMemo } from 'react';
import { toast } from 'sonner';
import { SubscriptionSyncDialogContent } from './-sync';
export const Route = createFileRoute('/_app/subscriptions/detail/$id')({
component: SubscriptionDetailRouteComponent,
@@ -51,15 +64,22 @@ function SubscriptionDetailRouteComponent() {
}
};
const { data, loading, error } = useQuery<GetSubscriptionDetailQuery>(
GET_SUBSCRIPTION_DETAIL,
{
const handleReload = async () => {
const result = await refetch();
const error = getApolloQueryError(result);
if (error) {
toast.error('Failed to reload subscription', {
description: apolloErrorToMessage(error),
});
}
};
const { data, loading, error, refetch } =
useQuery<GetSubscriptionDetailQuery>(GET_SUBSCRIPTION_DETAIL, {
variables: {
id: Number.parseInt(id),
},
fetchPolicy: 'cache-and-network',
}
);
});
const handleEnterEditMode = () => {
navigate({
@@ -69,6 +89,7 @@ function SubscriptionDetailRouteComponent() {
},
});
};
const subscription = data?.subscriptions?.nodes?.[0];
const sourceUrlMeta = useMemo(
@@ -123,7 +144,7 @@ function SubscriptionDetailRouteComponent() {
<Button onClick={handleEnterEditMode}>
<Edit className="mr-2 h-4 w-4" />
Edit
</Button>
</Button>{' '}
</div>
</div>
@@ -137,10 +158,30 @@ function SubscriptionDetailRouteComponent() {
</CardDescription>
</div>
<div className="flex gap-2">
<Badge variant={subscription.enabled ? 'default' : 'secondary'}>
{subscription.enabled ? 'Enabled' : 'Disabled'}
</Badge>
<Badge variant="outline">{subscription.category}</Badge>
<Dialog>
<DialogTrigger asChild>
<Button variant="outline" size="sm">
<RefreshCcwIcon className="h-4 w-4" />
Sync
</Button>
</DialogTrigger>
<SubscriptionSyncDialogContent
id={subscription.id}
onCancel={handleReload}
/>
</Dialog>
<Button
variant="outline"
size="sm"
onClick={() =>
navigate({
to: '/tasks/manage',
})
}
>
<ListIcon className="h-4 w-4" />
Tasks
</Button>
</div>
</div>
</CardHeader>
@@ -173,11 +214,9 @@ function SubscriptionDetailRouteComponent() {
<div className="space-y-2">
<Label className="font-medium text-sm">Enabled</Label>
<div className="rounded-md bg-muted p-3">
<Badge
variant={subscription.enabled ? 'default' : 'secondary'}
>
<span className="text-sm">
{subscription.enabled ? 'Enabled' : 'Disabled'}
</Badge>
</span>
</div>
</div>

View File

@@ -31,6 +31,10 @@ import {
} from '@/domains/recorder/schema/subscriptions';
import { SubscriptionService } from '@/domains/recorder/services/subscription.service';
import { useInject } from '@/infra/di/inject';
import {
apolloErrorToMessage,
getApolloQueryError,
} from '@/infra/errors/apollo';
import {
Credential3rdTypeEnum,
type GetSubscriptionDetailQuery,
@@ -382,16 +386,16 @@ function SubscriptionEditRouteComponent() {
variables: {
id: Number.parseInt(id),
},
fetchPolicy: 'cache-and-network',
});
const subscription = data?.subscriptions?.nodes?.[0];
const onCompleted = useCallback(async () => {
const refetchResult = await refetch();
if (refetchResult.errors) {
const error = getApolloQueryError(refetchResult);
if (error) {
toast.error('Update subscription failed', {
description: refetchResult.errors[0].message,
description: apolloErrorToMessage(error),
});
} else {
toast.success('Update subscription successfully');

View File

@@ -19,6 +19,10 @@ import {
type SubscriptionDto,
UPDATE_SUBSCRIPTIONS,
} from '@/domains/recorder/schema/subscriptions';
import {
apolloErrorToMessage,
getApolloQueryError,
} from '@/infra/errors/apollo';
import type {
GetSubscriptionsQuery,
SubscriptionsUpdateInput,
@@ -81,15 +85,16 @@ function SubscriptionManageRouteComponent() {
updatedAt: 'DESC',
},
},
refetchWritePolicy: 'overwrite',
nextFetchPolicy: 'network-only',
}
);
const [updateSubscription] = useMutation(UPDATE_SUBSCRIPTIONS, {
onCompleted: async () => {
const refetchResult = await refetch();
if (refetchResult.errors) {
toast.error(refetchResult.errors[0].message);
const error = getApolloQueryError(refetchResult);
if (error) {
toast.error('Failed to update subscription', {
description: apolloErrorToMessage(error),
});
return;
}
toast.success('Subscription updated');
@@ -103,8 +108,11 @@ function SubscriptionManageRouteComponent() {
const [deleteSubscription] = useMutation(DELETE_SUBSCRIPTIONS, {
onCompleted: async () => {
const refetchResult = await refetch();
if (refetchResult.errors) {
toast.error(refetchResult.errors[0].message);
const error = getApolloQueryError(refetchResult);
if (error) {
toast.error('Failed to delete subscription', {
description: apolloErrorToMessage(error),
});
return;
}
toast.success('Subscription deleted');

View File

@@ -0,0 +1,13 @@
import type { RouteStateDataOption } from '@/infra/routes/traits';
import { createFileRoute } from '@tanstack/react-router';
export const Route = createFileRoute('/_app/tasks/detail/$id')({
component: TaskDetailRouteComponent,
staticData: {
breadcrumb: { label: 'Detail' },
} satisfies RouteStateDataOption,
});
function TaskDetailRouteComponent() {
return <div>Hello "/_app/tasks/detail/$id"!</div>;
}

View File

@@ -0,0 +1,13 @@
import type { RouteStateDataOption } from '@/infra/routes/traits';
import { createFileRoute } from '@tanstack/react-router';
export const Route = createFileRoute('/_app/tasks/manage')({
component: TaskManageRouteComponent,
staticData: {
breadcrumb: { label: 'Manage' },
} satisfies RouteStateDataOption,
});
function TaskManageRouteComponent() {
return <div>Hello "/_app/tasks/manage"!</div>;
}

View File

@@ -0,0 +1,8 @@
import { buildVirtualBranchRouteOptions } from '@/infra/routes/utils';
import { createFileRoute } from '@tanstack/react-router';
export const Route = createFileRoute('/_app/tasks')(
buildVirtualBranchRouteOptions({
title: 'Tasks',
})
);