Compare commits
3 Commits
b4090e74c0
...
5b001f9584
Author | SHA1 | Date | |
---|---|---|---|
5b001f9584 | |||
d06acde882 | |||
bacfe99ef2 |
12
.vscode/settings.json
vendored
12
.vscode/settings.json
vendored
@ -40,13 +40,9 @@
|
||||
}
|
||||
],
|
||||
"rust-analyzer.cargo.features": "all",
|
||||
"rust-analyzer.testExplorer": true
|
||||
"rust-analyzer.testExplorer": true,
|
||||
// https://github.com/rust-lang/rust/issues/141540
|
||||
// "rust-analyzer.cargo.targetDir": "target/rust-analyzer",
|
||||
// "rust-analyzer.check.extraEnv": {
|
||||
// "CARGO_TARGET_DIR": "target/rust-analyzer"
|
||||
// },
|
||||
// "rust-analyzer.cargo.extraEnv": {
|
||||
// "CARGO_TARGET_DIR": "target/analyzer"
|
||||
// }
|
||||
"rust-analyzer.runnables.extraEnv": {
|
||||
"CARGO_INCREMENTAL": "0",
|
||||
}
|
||||
}
|
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -6793,6 +6793,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"opendal",
|
||||
"openidconnect",
|
||||
"paste",
|
||||
"percent-encoding",
|
||||
"polars",
|
||||
"quick-xml",
|
||||
@ -6807,6 +6808,7 @@ dependencies = [
|
||||
"sea-orm",
|
||||
"sea-orm-migration",
|
||||
"seaography",
|
||||
"secrecy",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_variant",
|
||||
@ -7643,16 +7645,16 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||
[[package]]
|
||||
name = "seaography"
|
||||
version = "1.1.4"
|
||||
source = "git+https://github.com/dumtruck/seaography.git?rev=a787c3a#a787c3ab83cf1f8275894e1bc1ca3c766b54674b"
|
||||
source = "git+https://github.com/dumtruck/seaography.git?rev=9f7fc7c#9f7fc7cf05234abe35fd9144c895321dd2b5db62"
|
||||
dependencies = [
|
||||
"async-graphql",
|
||||
"fnv",
|
||||
"heck 0.4.1",
|
||||
"itertools 0.12.1",
|
||||
"heck 0.5.0",
|
||||
"itertools 0.14.0",
|
||||
"lazy_static",
|
||||
"sea-orm",
|
||||
"serde_json",
|
||||
"thiserror 1.0.69",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -7669,6 +7671,16 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "secrecy"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.11.1"
|
||||
|
@ -15,7 +15,7 @@ resolver = "2"
|
||||
[profile.dev]
|
||||
debug = 0
|
||||
# https://github.com/rust-lang/rust/issues/141540
|
||||
incremental = false
|
||||
incremental = true # Then only change rust-analyzer incremental
|
||||
# [simd not supported by cranelift](https://github.com/rust-lang/rustc_codegen_cranelift/issues/171)
|
||||
# codegen-backend = "cranelift"
|
||||
|
||||
@ -87,4 +87,4 @@ nanoid = "0.4.0"
|
||||
webp = "0.3.0"
|
||||
|
||||
[patch.crates-io]
|
||||
seaography = { git = "https://github.com/dumtruck/seaography.git", rev = "a787c3a" }
|
||||
seaography = { git = "https://github.com/dumtruck/seaography.git", rev = "9f7fc7c" }
|
||||
|
@ -125,6 +125,7 @@ seaography = { version = "1.1", features = [
|
||||
"with-bigdecimal",
|
||||
"with-postgres-array",
|
||||
"with-json-as-scalar",
|
||||
"with-custom-as-json",
|
||||
] }
|
||||
tower = { version = "0.5.2", features = ["util"] }
|
||||
tower-http = { version = "0.6", features = [
|
||||
@ -166,6 +167,8 @@ quick-xml = { version = "0.37.5", features = [
|
||||
] }
|
||||
croner = "2.2.0"
|
||||
ts-rs = "11.0.1"
|
||||
secrecy = { version = "0.10.3", features = ["serde"] }
|
||||
paste = "1.0.15"
|
||||
|
||||
[dev-dependencies]
|
||||
inquire = { workspace = true }
|
||||
|
6
apps/recorder/bindings/SubscriberTaskInput.ts
Normal file
6
apps/recorder/bindings/SubscriberTaskInput.ts
Normal file
@ -0,0 +1,6 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { SyncOneSubscriptionFeedsFullTaskInput } from "./SyncOneSubscriptionFeedsFullTaskInput";
|
||||
import type { SyncOneSubscriptionFeedsIncrementalTaskInput } from "./SyncOneSubscriptionFeedsIncrementalTaskInput";
|
||||
import type { SyncOneSubscriptionSourcesTaskInput } from "./SyncOneSubscriptionSourcesTaskInput";
|
||||
|
||||
export type SubscriberTaskInput = { "taskType": "sync_one_subscription_feeds_incremental" } & SyncOneSubscriptionFeedsIncrementalTaskInput | { "taskType": "sync_one_subscription_feeds_full" } & SyncOneSubscriptionFeedsFullTaskInput | { "taskType": "sync_one_subscription_sources" } & SyncOneSubscriptionSourcesTaskInput;
|
6
apps/recorder/bindings/SubscriberTaskType.ts
Normal file
6
apps/recorder/bindings/SubscriberTaskType.ts
Normal file
@ -0,0 +1,6 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { SyncOneSubscriptionFeedsFullTask } from "./SyncOneSubscriptionFeedsFullTask";
|
||||
import type { SyncOneSubscriptionFeedsIncrementalTask } from "./SyncOneSubscriptionFeedsIncrementalTask";
|
||||
import type { SyncOneSubscriptionSourcesTask } from "./SyncOneSubscriptionSourcesTask";
|
||||
|
||||
export type SubscriberTaskType = { "taskType": "sync_one_subscription_feeds_incremental" } & SyncOneSubscriptionFeedsIncrementalTask | { "taskType": "sync_one_subscription_feeds_full" } & SyncOneSubscriptionFeedsFullTask | { "taskType": "sync_one_subscription_sources" } & SyncOneSubscriptionSourcesTask;
|
@ -0,0 +1,3 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type SyncOneSubscriptionFeedsFullTask = { subscriptionId: number, subscriberId: number, cronId?: number | null, };
|
@ -0,0 +1,3 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type SyncOneSubscriptionFeedsFullTaskInput = { subscriptionId: number, subscriberId?: number | null, cronId?: number | null, };
|
@ -0,0 +1,3 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type SyncOneSubscriptionFeedsIncrementalTask = { subscriptionId: number, subscriberId: number, cronId?: number | null, };
|
@ -0,0 +1,3 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type SyncOneSubscriptionFeedsIncrementalTaskInput = { subscriptionId: number, subscriberId?: number | null, cronId?: number | null, };
|
3
apps/recorder/bindings/SyncOneSubscriptionSourcesTask.ts
Normal file
3
apps/recorder/bindings/SyncOneSubscriptionSourcesTask.ts
Normal file
@ -0,0 +1,3 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type SyncOneSubscriptionSourcesTask = { subscriptionId: number, subscriberId: number, cronId?: number | null, };
|
@ -0,0 +1,3 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type SyncOneSubscriptionSourcesTaskInput = { subscriptionId: number, subscriberId?: number | null, cronId?: number | null, };
|
6
apps/recorder/package.json
Normal file
6
apps/recorder/package.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "recorder",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"type": "module"
|
||||
}
|
@ -313,4 +313,10 @@ impl From<http::method::InvalidMethod> for RecorderError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<async_graphql::Error> for RecorderError {
|
||||
fn from(error: async_graphql::Error) -> Self {
|
||||
seaography::SeaographyError::AsyncGraphQLError(error).into()
|
||||
}
|
||||
}
|
||||
|
||||
pub type RecorderResult<T> = Result<T, RecorderError>;
|
||||
|
@ -101,7 +101,7 @@ pub fn register_credential3rd_to_schema_builder(
|
||||
.schema
|
||||
.register(Credential3rdCheckAvailableInfo::generate_output_object());
|
||||
|
||||
let builder_context = builder.context;
|
||||
let builder_context = &builder.context;
|
||||
{
|
||||
let check_available_mutation_name = get_entity_custom_mutation_field_name::<
|
||||
credential_3rd::Entity,
|
||||
|
@ -1,20 +1,15 @@
|
||||
use convert_case::Case;
|
||||
use sea_orm::Iterable;
|
||||
use seaography::{Builder as SeaographyBuilder, BuilderContext};
|
||||
|
||||
use crate::{
|
||||
graphql::{
|
||||
domains::subscribers::restrict_subscriber_for_entity,
|
||||
infra::{
|
||||
custom::register_entity_default_writable,
|
||||
json::{
|
||||
convert_jsonb_output_case_for_entity, restrict_jsonb_filter_input_for_entity,
|
||||
validate_jsonb_input_for_entity,
|
||||
domains::{
|
||||
subscriber_tasks::restrict_subscriber_tasks_for_entity,
|
||||
subscribers::restrict_subscriber_for_entity,
|
||||
},
|
||||
name::get_entity_and_column_name,
|
||||
infra::{custom::register_entity_default_writable, name::get_entity_and_column_name},
|
||||
},
|
||||
},
|
||||
models::{cron, subscriber_tasks},
|
||||
models::cron,
|
||||
};
|
||||
|
||||
fn skip_columns_for_entity_input(context: &mut BuilderContext) {
|
||||
@ -22,7 +17,6 @@ fn skip_columns_for_entity_input(context: &mut BuilderContext) {
|
||||
if matches!(
|
||||
column,
|
||||
cron::Column::SubscriberTask
|
||||
| cron::Column::Id
|
||||
| cron::Column::CronExpr
|
||||
| cron::Column::Enabled
|
||||
| cron::Column::TimeoutMs
|
||||
@ -49,16 +43,7 @@ fn skip_columns_for_entity_input(context: &mut BuilderContext) {
|
||||
pub fn register_cron_to_schema_context(context: &mut BuilderContext) {
|
||||
restrict_subscriber_for_entity::<cron::Entity>(context, &cron::Column::SubscriberId);
|
||||
|
||||
restrict_jsonb_filter_input_for_entity::<cron::Entity>(context, &cron::Column::SubscriberTask);
|
||||
convert_jsonb_output_case_for_entity::<cron::Entity>(
|
||||
context,
|
||||
&cron::Column::SubscriberTask,
|
||||
Case::Camel,
|
||||
);
|
||||
validate_jsonb_input_for_entity::<cron::Entity, Option<subscriber_tasks::SubscriberTask>>(
|
||||
context,
|
||||
&cron::Column::SubscriberTask,
|
||||
);
|
||||
restrict_subscriber_tasks_for_entity::<cron::Entity>(context, &cron::Column::SubscriberTask);
|
||||
skip_columns_for_entity_input(context);
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,15 @@
|
||||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use async_graphql::dynamic::{FieldValue, TypeRef, ValueAccessor};
|
||||
use async_graphql::dynamic::{FieldValue, Scalar, TypeRef};
|
||||
use convert_case::Case;
|
||||
use sea_orm::{
|
||||
ColumnTrait, ConnectionTrait, EntityTrait, Iterable, QueryFilter, QuerySelect, QueryTrait,
|
||||
prelude::Expr, sea_query::Query,
|
||||
ActiveModelBehavior, ColumnTrait, ConnectionTrait, EntityTrait, Iterable, QueryFilter,
|
||||
QuerySelect, QueryTrait, prelude::Expr, sea_query::Query,
|
||||
};
|
||||
use seaography::{Builder as SeaographyBuilder, BuilderContext, GuardAction};
|
||||
use seaography::{
|
||||
Builder as SeaographyBuilder, BuilderContext, SeaographyError, prepare_active_model,
|
||||
};
|
||||
use ts_rs::TS;
|
||||
|
||||
use crate::{
|
||||
auth::AuthUserInfo,
|
||||
@ -20,59 +23,22 @@ use crate::{
|
||||
generate_entity_default_insert_input_object, generate_entity_delete_mutation_field,
|
||||
generate_entity_filtered_mutation_field, register_entity_default_readonly,
|
||||
},
|
||||
json::{
|
||||
convert_jsonb_output_case_for_entity, restrict_jsonb_filter_input_for_entity,
|
||||
validate_jsonb_input_for_entity,
|
||||
},
|
||||
json::{convert_jsonb_output_for_entity, restrict_jsonb_filter_input_for_entity},
|
||||
name::{
|
||||
get_column_name, get_entity_and_column_name, get_entity_basic_type_name,
|
||||
get_entity_create_batch_mutation_data_field_name,
|
||||
get_entity_create_batch_mutation_field_name,
|
||||
get_entity_create_one_mutation_data_field_name,
|
||||
get_entity_create_one_mutation_field_name, get_entity_custom_mutation_field_name,
|
||||
get_entity_update_mutation_field_name,
|
||||
get_entity_and_column_name, get_entity_basic_type_name,
|
||||
get_entity_custom_mutation_field_name,
|
||||
},
|
||||
},
|
||||
},
|
||||
models::subscriber_tasks,
|
||||
task::{ApalisJobs, ApalisSchema},
|
||||
task::{ApalisJobs, ApalisSchema, SubscriberTaskTrait},
|
||||
};
|
||||
|
||||
pub fn check_entity_and_task_subscriber_id_matches(
|
||||
value_accessor: &ValueAccessor<'_>,
|
||||
subscriber_id: i32,
|
||||
subscriber_id_column_name: &str,
|
||||
subscriber_task_column_name: &str,
|
||||
) -> bool {
|
||||
value_accessor.object().is_ok_and(|input_object| {
|
||||
input_object
|
||||
.get(subscriber_task_column_name)
|
||||
.and_then(|subscriber_task_value| subscriber_task_value.object().ok())
|
||||
.and_then(|subscriber_task_object| {
|
||||
subscriber_task_object
|
||||
.get("subscriber_id")
|
||||
.and_then(|job_subscriber_id| job_subscriber_id.i64().ok())
|
||||
})
|
||||
.is_some_and(|subscriber_task_subscriber_id| {
|
||||
subscriber_task_subscriber_id as i32
|
||||
== input_object
|
||||
.get(subscriber_id_column_name)
|
||||
.and_then(|subscriber_id_object| subscriber_id_object.i64().ok())
|
||||
.map(|subscriber_id| subscriber_id as i32)
|
||||
.unwrap_or(subscriber_id)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn skip_columns_for_entity_input(context: &mut BuilderContext) {
|
||||
for column in subscriber_tasks::Column::iter() {
|
||||
if matches!(
|
||||
column,
|
||||
subscriber_tasks::Column::Job
|
||||
| subscriber_tasks::Column::Id
|
||||
| subscriber_tasks::Column::SubscriberId
|
||||
| subscriber_tasks::Column::Priority
|
||||
| subscriber_tasks::Column::MaxAttempts
|
||||
subscriber_tasks::Column::Job | subscriber_tasks::Column::SubscriberId
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
@ -82,115 +48,77 @@ fn skip_columns_for_entity_input(context: &mut BuilderContext) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn restrict_subscriber_tasks_for_entity<T>(context: &mut BuilderContext, column: &T::Column)
|
||||
where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync,
|
||||
{
|
||||
let entity_and_column = get_entity_and_column_name::<T>(context, column);
|
||||
|
||||
restrict_jsonb_filter_input_for_entity::<T>(context, column);
|
||||
convert_jsonb_output_for_entity::<T>(context, column, Some(Case::Camel));
|
||||
let entity_column_name = get_entity_and_column_name::<T>(context, column);
|
||||
|
||||
context.types.input_type_overwrites.insert(
|
||||
entity_column_name.clone(),
|
||||
TypeRef::Named(subscriber_tasks::SubscriberTask::ident().into()),
|
||||
);
|
||||
context.types.output_type_overwrites.insert(
|
||||
entity_column_name.clone(),
|
||||
TypeRef::Named(subscriber_tasks::SubscriberTask::ident().into()),
|
||||
);
|
||||
context.types.input_conversions.insert(
|
||||
entity_column_name.clone(),
|
||||
Box::new(move |resolve_context, value_accessor| {
|
||||
let task: subscriber_tasks::SubscriberTaskInput = value_accessor.deserialize()?;
|
||||
|
||||
let subscriber_id = resolve_context
|
||||
.data::<AuthUserInfo>()?
|
||||
.subscriber_auth
|
||||
.subscriber_id;
|
||||
|
||||
let task = subscriber_tasks::SubscriberTask::from_input(task, subscriber_id);
|
||||
|
||||
let json_value = serde_json::to_value(task).map_err(|err| {
|
||||
SeaographyError::TypeConversionError(
|
||||
err.to_string(),
|
||||
format!("Json - {entity_column_name}"),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(sea_orm::Value::Json(Some(Box::new(json_value))))
|
||||
}),
|
||||
);
|
||||
|
||||
context.entity_input.update_skips.push(entity_and_column);
|
||||
}
|
||||
|
||||
pub fn register_subscriber_tasks_to_schema_context(context: &mut BuilderContext) {
|
||||
restrict_subscriber_for_entity::<subscriber_tasks::Entity>(
|
||||
context,
|
||||
&subscriber_tasks::Column::SubscriberId,
|
||||
);
|
||||
restrict_jsonb_filter_input_for_entity::<subscriber_tasks::Entity>(
|
||||
context,
|
||||
&subscriber_tasks::Column::Job,
|
||||
);
|
||||
convert_jsonb_output_case_for_entity::<subscriber_tasks::Entity>(
|
||||
context,
|
||||
&subscriber_tasks::Column::Job,
|
||||
Case::Camel,
|
||||
);
|
||||
validate_jsonb_input_for_entity::<subscriber_tasks::Entity, subscriber_tasks::SubscriberTask>(
|
||||
restrict_subscriber_tasks_for_entity::<subscriber_tasks::Entity>(
|
||||
context,
|
||||
&subscriber_tasks::Column::Job,
|
||||
);
|
||||
|
||||
skip_columns_for_entity_input(context);
|
||||
|
||||
context.guards.field_guards.insert(
|
||||
get_entity_and_column_name::<subscriber_tasks::Entity>(
|
||||
context,
|
||||
&subscriber_tasks::Column::Job,
|
||||
),
|
||||
{
|
||||
let create_one_mutation_field_name =
|
||||
Arc::new(get_entity_create_one_mutation_field_name::<
|
||||
subscriber_tasks::Entity,
|
||||
>(context));
|
||||
let create_one_mutation_data_field_name =
|
||||
Arc::new(get_entity_create_one_mutation_data_field_name(context).to_string());
|
||||
let create_batch_mutation_field_name =
|
||||
Arc::new(get_entity_create_batch_mutation_field_name::<
|
||||
subscriber_tasks::Entity,
|
||||
>(context));
|
||||
let create_batch_mutation_data_field_name =
|
||||
Arc::new(get_entity_create_batch_mutation_data_field_name(context).to_string());
|
||||
let update_mutation_field_name = Arc::new(get_entity_update_mutation_field_name::<
|
||||
subscriber_tasks::Entity,
|
||||
>(context));
|
||||
let job_column_name = Arc::new(get_column_name::<subscriber_tasks::Entity>(
|
||||
context,
|
||||
&subscriber_tasks::Column::Job,
|
||||
));
|
||||
let subscriber_id_column_name = Arc::new(get_column_name::<subscriber_tasks::Entity>(
|
||||
context,
|
||||
&subscriber_tasks::Column::SubscriberId,
|
||||
));
|
||||
|
||||
Box::new(move |resolve_context| {
|
||||
let field_name = resolve_context.field().name();
|
||||
let subscriber_id = resolve_context
|
||||
.data_opt::<AuthUserInfo>()
|
||||
.unwrap()
|
||||
.subscriber_auth
|
||||
.subscriber_id;
|
||||
let matched_subscriber_id = match field_name {
|
||||
field if field == create_one_mutation_field_name.as_str() => resolve_context
|
||||
.args
|
||||
.get(create_one_mutation_data_field_name.as_str())
|
||||
.is_some_and(|value_accessor| {
|
||||
check_entity_and_task_subscriber_id_matches(
|
||||
&value_accessor,
|
||||
subscriber_id,
|
||||
subscriber_id_column_name.as_str(),
|
||||
job_column_name.as_str(),
|
||||
)
|
||||
}),
|
||||
field if field == create_batch_mutation_field_name.as_str() => resolve_context
|
||||
.args
|
||||
.get(create_batch_mutation_data_field_name.as_str())
|
||||
.and_then(|value| value.list().ok())
|
||||
.is_some_and(|list| {
|
||||
list.iter().all(|value| {
|
||||
check_entity_and_task_subscriber_id_matches(
|
||||
&value,
|
||||
subscriber_id,
|
||||
subscriber_id_column_name.as_str(),
|
||||
job_column_name.as_str(),
|
||||
)
|
||||
})
|
||||
}),
|
||||
field if field == update_mutation_field_name.as_str() => {
|
||||
unreachable!("subscriberTask entity do not support update job")
|
||||
}
|
||||
_ => true,
|
||||
};
|
||||
if matched_subscriber_id {
|
||||
GuardAction::Allow
|
||||
} else {
|
||||
GuardAction::Block(Some(
|
||||
"subscriber_id mismatch between entity and job".to_string(),
|
||||
))
|
||||
}
|
||||
})
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn register_subscriber_tasks_to_schema_builder(
|
||||
mut builder: SeaographyBuilder,
|
||||
) -> SeaographyBuilder {
|
||||
builder.schema = builder.schema.register(
|
||||
Scalar::new(subscriber_tasks::SubscriberTask::ident())
|
||||
.description(subscriber_tasks::SubscriberTask::decl()),
|
||||
);
|
||||
builder.register_enumeration::<subscriber_tasks::SubscriberTaskType>();
|
||||
builder.register_enumeration::<subscriber_tasks::SubscriberTaskStatus>();
|
||||
|
||||
builder = register_entity_default_readonly!(builder, subscriber_tasks);
|
||||
|
||||
let builder_context = builder.context;
|
||||
|
||||
{
|
||||
builder
|
||||
.outputs
|
||||
@ -278,23 +206,30 @@ pub fn register_subscriber_tasks_to_schema_builder(
|
||||
subscriber_tasks::Entity,
|
||||
>(builder_context));
|
||||
let create_one_mutation =
|
||||
generate_entity_create_one_mutation_field::<subscriber_tasks::Entity, TypeRef>(
|
||||
generate_entity_create_one_mutation_field::<subscriber_tasks::Entity>(
|
||||
builder_context,
|
||||
None,
|
||||
Arc::new(|_resolver_ctx, app_ctx, input_object| {
|
||||
let job_column_name = get_column_name::<subscriber_tasks::Entity>(
|
||||
builder_context,
|
||||
&subscriber_tasks::Column::Job,
|
||||
);
|
||||
let task = input_object
|
||||
.get(job_column_name.as_str())
|
||||
.unwrap()
|
||||
.deserialize::<subscriber_tasks::SubscriberTask>()
|
||||
.unwrap();
|
||||
|
||||
Arc::new(move |resolver_ctx, app_ctx, input_object| {
|
||||
Box::pin(async move {
|
||||
let active_model: Result<subscriber_tasks::ActiveModel, _> =
|
||||
prepare_active_model(builder_context, &input_object, resolver_ctx);
|
||||
|
||||
let task_service = app_ctx.task();
|
||||
|
||||
let active_model = active_model?;
|
||||
|
||||
let db = app_ctx.db();
|
||||
|
||||
let active_model = active_model.before_save(db, true).await?;
|
||||
|
||||
let task = active_model.job.unwrap();
|
||||
let subscriber_id = active_model.subscriber_id.unwrap();
|
||||
|
||||
if task.get_subscriber_id() != subscriber_id {
|
||||
Err(async_graphql::Error::new(
|
||||
"subscriber_id does not match with job.subscriber_id",
|
||||
))?;
|
||||
}
|
||||
|
||||
let task_id = task_service.add_subscriber_task(task).await?.to_string();
|
||||
|
||||
let db = app_ctx.db();
|
||||
|
@ -7,7 +7,7 @@ use sea_orm::{ColumnTrait, Condition, EntityTrait, Iterable, Value as SeaValue};
|
||||
use seaography::{
|
||||
Builder as SeaographyBuilder, BuilderContext, FilterInfo,
|
||||
FilterOperation as SeaographqlFilterOperation, FilterType, FilterTypesMapHelper,
|
||||
FnFilterCondition, FnGuard, FnInputTypeNoneConversion, GuardAction, SeaResult, SeaographyError,
|
||||
FnFilterCondition, FnGuard, FnInputTypeNoneConversion, GuardAction, SeaResult,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -219,11 +219,10 @@ where
|
||||
if let Some(value) = filter.get("eq") {
|
||||
let value: i32 = value.i64()?.try_into()?;
|
||||
if value != subscriber_id {
|
||||
return Err(SeaographyError::AsyncGraphQLError(
|
||||
async_graphql::Error::new(
|
||||
return Err(async_graphql::Error::new(
|
||||
"subscriber_id and auth_info does not match",
|
||||
),
|
||||
));
|
||||
)
|
||||
.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -319,13 +318,11 @@ pub fn register_subscribers_to_schema_context(context: &mut BuilderContext) {
|
||||
|
||||
pub fn register_subscribers_to_schema_builder(mut builder: SeaographyBuilder) -> SeaographyBuilder {
|
||||
{
|
||||
let filter_types_map_helper = FilterTypesMapHelper {
|
||||
context: builder.context,
|
||||
};
|
||||
|
||||
builder.schema = builder
|
||||
.schema
|
||||
.register(filter_types_map_helper.generate_filter_input(&SUBSCRIBER_ID_FILTER_INFO));
|
||||
.register(FilterTypesMapHelper::generate_filter_input(
|
||||
&SUBSCRIBER_ID_FILTER_INFO,
|
||||
));
|
||||
}
|
||||
|
||||
builder = register_entity_default_readonly!(builder, subscribers);
|
||||
|
@ -1,23 +1,11 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_graphql::dynamic::{FieldValue, TypeRef};
|
||||
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
|
||||
use seaography::{Builder as SeaographyBuilder, BuilderContext};
|
||||
|
||||
use crate::{
|
||||
errors::RecorderError,
|
||||
graphql::{
|
||||
domains::subscribers::restrict_subscriber_for_entity,
|
||||
infra::{
|
||||
custom::{generate_entity_filtered_mutation_field, register_entity_default_writable},
|
||||
name::{get_entity_basic_type_name, get_entity_custom_mutation_field_name},
|
||||
},
|
||||
},
|
||||
models::{subscriber_tasks, subscriptions},
|
||||
task::{
|
||||
SyncOneSubscriptionFeedsFullTask, SyncOneSubscriptionFeedsIncrementalTask,
|
||||
SyncOneSubscriptionSourcesTask,
|
||||
infra::custom::register_entity_default_writable,
|
||||
},
|
||||
models::subscriptions,
|
||||
};
|
||||
|
||||
pub fn register_subscriptions_to_schema_context(context: &mut BuilderContext) {
|
||||
@ -32,162 +20,5 @@ pub fn register_subscriptions_to_schema_builder(
|
||||
) -> SeaographyBuilder {
|
||||
builder.register_enumeration::<subscriptions::SubscriptionCategory>();
|
||||
builder = register_entity_default_writable!(builder, subscriptions, false);
|
||||
|
||||
let context = builder.context;
|
||||
|
||||
{
|
||||
let sync_one_feeds_incremental_mutation_name = get_entity_custom_mutation_field_name::<
|
||||
subscriptions::Entity,
|
||||
>(context, "SyncOneFeedsIncremental");
|
||||
|
||||
let sync_one_feeds_incremental_mutation =
|
||||
generate_entity_filtered_mutation_field::<subscriptions::Entity, _, _>(
|
||||
builder.context,
|
||||
sync_one_feeds_incremental_mutation_name,
|
||||
TypeRef::named_nn(get_entity_basic_type_name::<subscriber_tasks::Entity>(
|
||||
context,
|
||||
)),
|
||||
Arc::new(|_resolver_ctx, app_ctx, filters| {
|
||||
Box::pin(async move {
|
||||
let db = app_ctx.db();
|
||||
|
||||
let subscription_model = subscriptions::Entity::find()
|
||||
.filter(filters)
|
||||
.one(db)
|
||||
.await?
|
||||
.ok_or_else(|| {
|
||||
RecorderError::from_entity_not_found::<subscriptions::Entity>()
|
||||
})?;
|
||||
|
||||
let task_service = app_ctx.task();
|
||||
|
||||
let task_id = task_service
|
||||
.add_subscriber_task(
|
||||
SyncOneSubscriptionFeedsIncrementalTask::builder()
|
||||
.subscriber_id(subscription_model.subscriber_id)
|
||||
.subscription_id(subscription_model.id)
|
||||
.build()
|
||||
.into(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let task_model = subscriber_tasks::Entity::find()
|
||||
.filter(subscriber_tasks::Column::Id.eq(task_id.to_string()))
|
||||
.one(db)
|
||||
.await?
|
||||
.ok_or_else(|| {
|
||||
RecorderError::from_entity_not_found::<subscriber_tasks::Entity>()
|
||||
})?;
|
||||
|
||||
Ok(Some(FieldValue::owned_any(task_model)))
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
builder.mutations.push(sync_one_feeds_incremental_mutation);
|
||||
}
|
||||
{
|
||||
let sync_one_feeds_full_mutation_name = get_entity_custom_mutation_field_name::<
|
||||
subscriptions::Entity,
|
||||
>(builder.context, "SyncOneFeedsFull");
|
||||
let sync_one_feeds_full_mutation =
|
||||
generate_entity_filtered_mutation_field::<subscriptions::Entity, _, _>(
|
||||
builder.context,
|
||||
sync_one_feeds_full_mutation_name,
|
||||
TypeRef::named_nn(get_entity_basic_type_name::<subscriber_tasks::Entity>(
|
||||
context,
|
||||
)),
|
||||
Arc::new(|_resolver_ctx, app_ctx, filters| {
|
||||
Box::pin(async move {
|
||||
let db = app_ctx.db();
|
||||
|
||||
let subscription_model = subscriptions::Entity::find()
|
||||
.filter(filters)
|
||||
.one(db)
|
||||
.await?
|
||||
.ok_or_else(|| {
|
||||
RecorderError::from_entity_not_found::<subscriptions::Entity>()
|
||||
})?;
|
||||
|
||||
let task_service = app_ctx.task();
|
||||
|
||||
let task_id = task_service
|
||||
.add_subscriber_task(
|
||||
SyncOneSubscriptionFeedsFullTask::builder()
|
||||
.subscriber_id(subscription_model.subscriber_id)
|
||||
.subscription_id(subscription_model.id)
|
||||
.build()
|
||||
.into(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let task_model = subscriber_tasks::Entity::find()
|
||||
.filter(subscriber_tasks::Column::Id.eq(task_id.to_string()))
|
||||
.one(db)
|
||||
.await?
|
||||
.ok_or_else(|| {
|
||||
RecorderError::from_entity_not_found::<subscriber_tasks::Entity>()
|
||||
})?;
|
||||
|
||||
Ok(Some(FieldValue::owned_any(task_model)))
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
builder.mutations.push(sync_one_feeds_full_mutation);
|
||||
}
|
||||
|
||||
{
|
||||
let sync_one_sources_mutation_name = get_entity_custom_mutation_field_name::<
|
||||
subscriptions::Entity,
|
||||
>(context, "SyncOneSources");
|
||||
|
||||
let sync_one_sources_mutation =
|
||||
generate_entity_filtered_mutation_field::<subscriptions::Entity, _, _>(
|
||||
builder.context,
|
||||
sync_one_sources_mutation_name,
|
||||
TypeRef::named_nn(get_entity_basic_type_name::<subscriber_tasks::Entity>(
|
||||
context,
|
||||
)),
|
||||
Arc::new(|_resolver_ctx, app_ctx, filters| {
|
||||
Box::pin(async move {
|
||||
let db = app_ctx.db();
|
||||
|
||||
let subscription_model = subscriptions::Entity::find()
|
||||
.filter(filters)
|
||||
.one(db)
|
||||
.await?
|
||||
.ok_or_else(|| {
|
||||
RecorderError::from_entity_not_found::<subscriptions::Entity>()
|
||||
})?;
|
||||
|
||||
let task_service = app_ctx.task();
|
||||
|
||||
let task_id = task_service
|
||||
.add_subscriber_task(
|
||||
SyncOneSubscriptionSourcesTask::builder()
|
||||
.subscriber_id(subscription_model.subscriber_id)
|
||||
.subscription_id(subscription_model.id)
|
||||
.build()
|
||||
.into(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let task_model = subscriber_tasks::Entity::find()
|
||||
.filter(subscriber_tasks::Column::Id.eq(task_id.to_string()))
|
||||
.one(db)
|
||||
.await?
|
||||
.ok_or_else(|| {
|
||||
RecorderError::from_entity_not_found::<subscriber_tasks::Entity>()
|
||||
})?;
|
||||
|
||||
Ok(Some(FieldValue::owned_any(task_model)))
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
builder.mutations.push(sync_one_sources_mutation);
|
||||
}
|
||||
|
||||
builder
|
||||
}
|
||||
|
@ -4,27 +4,20 @@ use async_graphql::dynamic::{
|
||||
Field, FieldFuture, FieldValue, InputObject, InputValue, Object, ObjectAccessor,
|
||||
ResolverContext, TypeRef,
|
||||
};
|
||||
use sea_orm::{
|
||||
ActiveModelTrait, Condition, EntityTrait, IntoActiveModel, QueryFilter, TransactionTrait,
|
||||
};
|
||||
use sea_orm::{ActiveModelTrait, Condition, EntityTrait, IntoActiveModel};
|
||||
use seaography::{
|
||||
Builder as SeaographyBuilder, BuilderContext, GuardAction, RelationBuilder, SeaographyError,
|
||||
get_filter_conditions, prepare_active_model,
|
||||
Builder as SeaographyBuilder, BuilderContext, EntityCreateBatchMutationBuilder,
|
||||
EntityCreateOneMutationBuilder, EntityDeleteMutationBuilder, EntityInputBuilder,
|
||||
EntityObjectBuilder, EntityUpdateMutationBuilder, GuardAction, RelationBuilder,
|
||||
get_filter_conditions,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::AppContextTrait,
|
||||
errors::RecorderResult,
|
||||
graphql::infra::name::{
|
||||
get_entity_and_column_name_from_column_str, get_entity_basic_type_name,
|
||||
get_entity_create_batch_mutation_data_field_name,
|
||||
get_entity_create_batch_mutation_field_name,
|
||||
get_entity_create_one_mutation_data_field_name, get_entity_create_one_mutation_field_name,
|
||||
get_entity_delete_mutation_field_name, get_entity_delete_mutation_filter_field_name,
|
||||
get_entity_filter_input_type_name, get_entity_insert_data_input_type_name, get_entity_name,
|
||||
get_entity_renormalized_filter_field_name, get_entity_update_data_input_type_name,
|
||||
get_entity_update_mutation_data_field_name, get_entity_update_mutation_field_name,
|
||||
get_entity_update_mutation_filter_field_name,
|
||||
get_entity_filter_input_type_name, get_entity_name,
|
||||
get_entity_renormalized_filter_field_name,
|
||||
},
|
||||
};
|
||||
|
||||
@ -41,9 +34,9 @@ pub type FilterMutationFn = Arc<
|
||||
|
||||
pub type CreateOneMutationFn<M> = Arc<
|
||||
dyn for<'a> Fn(
|
||||
&ResolverContext<'a>,
|
||||
&'a ResolverContext<'a>,
|
||||
Arc<dyn AppContextTrait>,
|
||||
ObjectAccessor<'_>,
|
||||
ObjectAccessor<'a>,
|
||||
) -> Pin<Box<dyn Future<Output = RecorderResult<M>> + Send + 'a>>
|
||||
+ Send
|
||||
+ Sync,
|
||||
@ -51,9 +44,9 @@ pub type CreateOneMutationFn<M> = Arc<
|
||||
|
||||
pub type CreateBatchMutationFn<M> = Arc<
|
||||
dyn for<'a> Fn(
|
||||
&ResolverContext<'a>,
|
||||
&'a ResolverContext<'a>,
|
||||
Arc<dyn AppContextTrait>,
|
||||
Vec<ObjectAccessor<'_>>,
|
||||
Vec<ObjectAccessor<'a>>,
|
||||
) -> Pin<Box<dyn Future<Output = RecorderResult<Vec<M>>> + Send + 'a>>
|
||||
+ Send
|
||||
+ Sync,
|
||||
@ -61,10 +54,10 @@ pub type CreateBatchMutationFn<M> = Arc<
|
||||
|
||||
pub type UpdateMutationFn<M> = Arc<
|
||||
dyn for<'a> Fn(
|
||||
&ResolverContext<'a>,
|
||||
&'a ResolverContext<'a>,
|
||||
Arc<dyn AppContextTrait>,
|
||||
Condition,
|
||||
ObjectAccessor<'_>,
|
||||
ObjectAccessor<'a>,
|
||||
) -> Pin<Box<dyn Future<Output = RecorderResult<Vec<M>>> + Send + 'a>>
|
||||
+ Send
|
||||
+ Sync,
|
||||
@ -80,48 +73,46 @@ pub type DeleteMutationFn = Arc<
|
||||
+ Sync,
|
||||
>;
|
||||
|
||||
pub fn generate_entity_default_insert_input_object<T>(
|
||||
builder_context: &'static BuilderContext,
|
||||
) -> InputObject
|
||||
pub fn generate_entity_default_insert_input_object<T>(context: &BuilderContext) -> InputObject
|
||||
where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync,
|
||||
{
|
||||
let entity_input_builder = seaography::EntityInputBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
|
||||
entity_input_builder.insert_input_object::<T>()
|
||||
EntityInputBuilder::insert_input_object::<T>(context)
|
||||
}
|
||||
|
||||
pub fn generate_entity_default_update_input_object<T>(
|
||||
builder_context: &'static BuilderContext,
|
||||
) -> InputObject
|
||||
pub fn generate_entity_default_update_input_object<T>(context: &BuilderContext) -> InputObject
|
||||
where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync,
|
||||
{
|
||||
let entity_input_builder = seaography::EntityInputBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
|
||||
entity_input_builder.update_input_object::<T>()
|
||||
EntityInputBuilder::update_input_object::<T>(context)
|
||||
}
|
||||
|
||||
pub fn generate_entity_default_basic_entity_object<T>(
|
||||
builder_context: &'static BuilderContext,
|
||||
) -> Object
|
||||
pub fn generate_entity_default_basic_entity_object<T>(context: &'static BuilderContext) -> Object
|
||||
where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync,
|
||||
{
|
||||
let entity_object_builder = seaography::EntityObjectBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
|
||||
let entity_object_builder = EntityObjectBuilder { context };
|
||||
entity_object_builder.basic_to_object::<T>()
|
||||
}
|
||||
|
||||
pub fn generate_entity_input_object<T>(
|
||||
context: &'static BuilderContext,
|
||||
is_insert: bool,
|
||||
) -> InputObject
|
||||
where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync,
|
||||
{
|
||||
if is_insert {
|
||||
EntityInputBuilder::insert_input_object::<T>(context)
|
||||
} else {
|
||||
EntityInputBuilder::update_input_object::<T>(context)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_entity_filtered_mutation_field<E, N, R>(
|
||||
builder_context: &'static BuilderContext,
|
||||
field_name: N,
|
||||
@ -138,11 +129,12 @@ where
|
||||
|
||||
let guard = builder_context.guards.entity_guards.get(&object_name);
|
||||
|
||||
Field::new(field_name, type_ref, move |ctx| {
|
||||
Field::new(field_name, type_ref, move |resolve_context| {
|
||||
let mutation_fn = mutation_fn.clone();
|
||||
|
||||
FieldFuture::new(async move {
|
||||
let guard_flag = if let Some(guard) = guard {
|
||||
(*guard)(&ctx)
|
||||
(*guard)(&resolve_context)
|
||||
} else {
|
||||
GuardAction::Allow
|
||||
};
|
||||
@ -153,15 +145,15 @@ where
|
||||
));
|
||||
}
|
||||
|
||||
let app_ctx = ctx.data::<Arc<dyn AppContextTrait>>()?;
|
||||
let filters = resolve_context
|
||||
.args
|
||||
.get(get_entity_renormalized_filter_field_name());
|
||||
|
||||
let filters = ctx.args.get(get_entity_renormalized_filter_field_name());
|
||||
let filters = get_filter_conditions::<E>(&resolve_context, builder_context, filters);
|
||||
|
||||
let filters = get_filter_conditions::<E>(&ctx, builder_context, filters);
|
||||
let app_ctx = resolve_context.data::<Arc<dyn AppContextTrait>>()?;
|
||||
|
||||
let result = mutation_fn(&ctx, app_ctx.clone(), filters)
|
||||
.await
|
||||
.map_err(async_graphql::Error::new_with_source)?;
|
||||
let result = mutation_fn(&resolve_context, app_ctx.clone(), filters).await?;
|
||||
|
||||
Ok(result)
|
||||
})
|
||||
@ -172,137 +164,30 @@ where
|
||||
))
|
||||
}
|
||||
|
||||
pub fn generate_entity_create_one_mutation_field<E, ID>(
|
||||
pub fn generate_entity_create_one_mutation_field<E>(
|
||||
builder_context: &'static BuilderContext,
|
||||
input_data_type_ref: Option<ID>,
|
||||
mutation_fn: CreateOneMutationFn<E::Model>,
|
||||
) -> Field
|
||||
where
|
||||
E: EntityTrait,
|
||||
<E as EntityTrait>::Model: Sync,
|
||||
ID: Into<TypeRef>,
|
||||
{
|
||||
let guard = builder_context
|
||||
.guards
|
||||
.entity_guards
|
||||
.get(&get_entity_name::<E>(builder_context));
|
||||
let field_guards = &builder_context.guards.field_guards;
|
||||
|
||||
Field::new(
|
||||
get_entity_create_one_mutation_field_name::<E>(builder_context),
|
||||
TypeRef::named_nn(get_entity_basic_type_name::<E>(builder_context)),
|
||||
move |ctx| {
|
||||
let entity_create_one_mutation_builder = EntityCreateOneMutationBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
entity_create_one_mutation_builder.to_field_with_mutation_fn::<E>(Arc::new(
|
||||
move |resolver_ctx, input_object| {
|
||||
let mutation_fn = mutation_fn.clone();
|
||||
FieldFuture::new(async move {
|
||||
let guard_flag = if let Some(guard) = guard {
|
||||
(*guard)(&ctx)
|
||||
} else {
|
||||
GuardAction::Allow
|
||||
};
|
||||
|
||||
if let GuardAction::Block(reason) = guard_flag {
|
||||
return Err::<Option<_>, async_graphql::Error>(async_graphql::Error::new(
|
||||
reason.unwrap_or("Entity guard triggered.".into()),
|
||||
));
|
||||
}
|
||||
|
||||
let app_ctx = ctx.data::<Arc<dyn AppContextTrait>>()?;
|
||||
|
||||
let value_accessor = ctx
|
||||
.args
|
||||
.get(get_entity_create_one_mutation_data_field_name(
|
||||
builder_context,
|
||||
))
|
||||
.unwrap();
|
||||
let input_object = value_accessor.object()?;
|
||||
|
||||
for (column, _) in input_object.iter() {
|
||||
let field_guard = field_guards.get(
|
||||
&get_entity_and_column_name_from_column_str::<E>(builder_context, column),
|
||||
);
|
||||
let field_guard_flag = if let Some(field_guard) = field_guard {
|
||||
(*field_guard)(&ctx)
|
||||
} else {
|
||||
GuardAction::Allow
|
||||
};
|
||||
if let GuardAction::Block(reason) = field_guard_flag {
|
||||
return match reason {
|
||||
Some(reason) => Err::<Option<_>, async_graphql::Error>(
|
||||
async_graphql::Error::new(reason),
|
||||
),
|
||||
None => Err::<Option<_>, async_graphql::Error>(
|
||||
async_graphql::Error::new("Field guard triggered."),
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let result = mutation_fn(&ctx, app_ctx.clone(), input_object)
|
||||
.await
|
||||
.map_err(async_graphql::Error::new_with_source)?;
|
||||
|
||||
Ok(Some(FieldValue::owned_any(result)))
|
||||
})
|
||||
},
|
||||
)
|
||||
.argument(InputValue::new(
|
||||
get_entity_create_one_mutation_data_field_name(builder_context),
|
||||
input_data_type_ref.map(|t| t.into()).unwrap_or_else(|| {
|
||||
TypeRef::named_nn(get_entity_insert_data_input_type_name::<E>(builder_context))
|
||||
}),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn generate_entity_default_create_one_mutation_fn<T, A>(
|
||||
builder_context: &'static BuilderContext,
|
||||
active_model_hooks: bool,
|
||||
) -> CreateOneMutationFn<T::Model>
|
||||
where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync + IntoActiveModel<A>,
|
||||
A: ActiveModelTrait<Entity = T> + sea_orm::ActiveModelBehavior + std::marker::Send + 'static,
|
||||
{
|
||||
Arc::new(move |resolve_context, app_ctx, input_object| {
|
||||
let entity_input_builder = seaography::EntityInputBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
let entity_object_builder = seaography::EntityObjectBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
let active_model = prepare_active_model::<T, A>(
|
||||
&entity_input_builder,
|
||||
&entity_object_builder,
|
||||
&input_object,
|
||||
resolve_context,
|
||||
)
|
||||
.map_err(SeaographyError::AsyncGraphQLError);
|
||||
|
||||
Box::pin(async move {
|
||||
if active_model_hooks {
|
||||
let transaction = app_ctx.db().begin().await?;
|
||||
let app_ctx = resolver_ctx.data::<Arc<dyn AppContextTrait>>()?;
|
||||
|
||||
let active_model = active_model?;
|
||||
|
||||
let active_model = active_model.before_save(&transaction, true).await?;
|
||||
|
||||
let result: T::Model = active_model.insert(&transaction).await?;
|
||||
|
||||
let result = A::after_save(result, &transaction, true).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
let result = mutation_fn(resolver_ctx, app_ctx.clone(), input_object).await?;
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
let db = app_ctx.db();
|
||||
|
||||
let active_model = active_model?;
|
||||
|
||||
let result: T::Model = active_model.insert(db).await?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn generate_entity_default_create_one_mutation_field<E, A>(
|
||||
@ -311,175 +196,39 @@ pub fn generate_entity_default_create_one_mutation_field<E, A>(
|
||||
) -> Field
|
||||
where
|
||||
E: EntityTrait,
|
||||
<E as EntityTrait>::Model: Sync,
|
||||
<E as EntityTrait>::Model: IntoActiveModel<A>,
|
||||
A: ActiveModelTrait<Entity = E> + sea_orm::ActiveModelBehavior + std::marker::Send + 'static,
|
||||
<E as EntityTrait>::Model: Sync + IntoActiveModel<A>,
|
||||
A: ActiveModelTrait<Entity = E> + sea_orm::ActiveModelBehavior + std::marker::Send,
|
||||
{
|
||||
generate_entity_create_one_mutation_field::<E, TypeRef>(
|
||||
builder_context,
|
||||
None,
|
||||
generate_entity_default_create_one_mutation_fn::<E, A>(builder_context, active_model_hooks),
|
||||
)
|
||||
let entity_create_one_mutation_builder = EntityCreateOneMutationBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
entity_create_one_mutation_builder.to_field::<E, A>(active_model_hooks)
|
||||
}
|
||||
|
||||
pub fn generate_entity_create_batch_mutation_field<E, ID>(
|
||||
builder_context: &'static BuilderContext,
|
||||
input_data_type_ref: Option<ID>,
|
||||
mutation_fn: CreateBatchMutationFn<E::Model>,
|
||||
) -> Field
|
||||
where
|
||||
E: EntityTrait,
|
||||
<E as EntityTrait>::Model: Sync,
|
||||
ID: Into<TypeRef>,
|
||||
{
|
||||
let object_name: String = get_entity_name::<E>(builder_context);
|
||||
let guard = builder_context.guards.entity_guards.get(&object_name);
|
||||
let field_guards = &builder_context.guards.field_guards;
|
||||
|
||||
Field::new(
|
||||
get_entity_create_batch_mutation_field_name::<E>(builder_context),
|
||||
TypeRef::named_nn_list_nn(get_entity_basic_type_name::<E>(builder_context)),
|
||||
move |ctx| {
|
||||
let entity_create_batch_mutation_builder = EntityCreateBatchMutationBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
entity_create_batch_mutation_builder.to_field_with_mutation_fn::<E>(Arc::new(
|
||||
move |resolver_ctx, input_objects| {
|
||||
let mutation_fn = mutation_fn.clone();
|
||||
FieldFuture::new(async move {
|
||||
let guard_flag = if let Some(guard) = guard {
|
||||
(*guard)(&ctx)
|
||||
} else {
|
||||
GuardAction::Allow
|
||||
};
|
||||
|
||||
if let GuardAction::Block(reason) = guard_flag {
|
||||
return match reason {
|
||||
Some(reason) => Err::<Option<_>, async_graphql::Error>(
|
||||
async_graphql::Error::new(reason),
|
||||
),
|
||||
None => Err::<Option<_>, async_graphql::Error>(async_graphql::Error::new(
|
||||
"Entity guard triggered.",
|
||||
)),
|
||||
};
|
||||
}
|
||||
|
||||
let mut input_objects: Vec<ObjectAccessor<'_>> = vec![];
|
||||
let list = ctx
|
||||
.args
|
||||
.get(get_entity_create_batch_mutation_data_field_name(
|
||||
builder_context,
|
||||
))
|
||||
.unwrap()
|
||||
.list()?;
|
||||
for input in list.iter() {
|
||||
let input_object = input.object()?;
|
||||
for (column, _) in input_object.iter() {
|
||||
let field_guard =
|
||||
field_guards.get(&get_entity_and_column_name_from_column_str::<E>(
|
||||
builder_context,
|
||||
column,
|
||||
));
|
||||
let field_guard_flag = if let Some(field_guard) = field_guard {
|
||||
(*field_guard)(&ctx)
|
||||
} else {
|
||||
GuardAction::Allow
|
||||
};
|
||||
if let GuardAction::Block(reason) = field_guard_flag {
|
||||
return match reason {
|
||||
Some(reason) => Err::<Option<_>, async_graphql::Error>(
|
||||
async_graphql::Error::new(reason),
|
||||
),
|
||||
None => Err::<Option<_>, async_graphql::Error>(
|
||||
async_graphql::Error::new("Field guard triggered."),
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
input_objects.push(input_object);
|
||||
}
|
||||
|
||||
let app_ctx = ctx.data::<Arc<dyn AppContextTrait>>()?;
|
||||
|
||||
let results = mutation_fn(&ctx, app_ctx.clone(), input_objects)
|
||||
.await
|
||||
.map_err(async_graphql::Error::new_with_source)?;
|
||||
|
||||
Ok(Some(FieldValue::list(
|
||||
results.into_iter().map(FieldValue::owned_any),
|
||||
)))
|
||||
})
|
||||
},
|
||||
)
|
||||
.argument(InputValue::new(
|
||||
get_entity_create_batch_mutation_data_field_name(builder_context),
|
||||
input_data_type_ref.map(|t| t.into()).unwrap_or_else(|| {
|
||||
TypeRef::named_nn_list_nn(get_entity_insert_data_input_type_name::<E>(builder_context))
|
||||
}),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn generate_entity_default_create_batch_mutation_fn<E, A>(
|
||||
builder_context: &'static BuilderContext,
|
||||
active_model_hooks: bool,
|
||||
) -> CreateBatchMutationFn<E::Model>
|
||||
where
|
||||
E: EntityTrait,
|
||||
<E as EntityTrait>::Model: Sync,
|
||||
<E as EntityTrait>::Model: IntoActiveModel<A>,
|
||||
A: ActiveModelTrait<Entity = E> + sea_orm::ActiveModelBehavior + std::marker::Send + 'static,
|
||||
{
|
||||
Arc::new(move |resolve_context, app_ctx, input_objects| {
|
||||
let entity_input_builder = seaography::EntityInputBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
let entity_object_builder = seaography::EntityObjectBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
let active_models = input_objects
|
||||
.into_iter()
|
||||
.map(|input_object| {
|
||||
prepare_active_model::<E, A>(
|
||||
&entity_input_builder,
|
||||
&entity_object_builder,
|
||||
&input_object,
|
||||
resolve_context,
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(SeaographyError::AsyncGraphQLError);
|
||||
|
||||
Box::pin(async move {
|
||||
if active_model_hooks {
|
||||
let transaction = app_ctx.db().begin().await?;
|
||||
let app_ctx = resolver_ctx.data::<Arc<dyn AppContextTrait>>()?;
|
||||
|
||||
let mut before_save_models = vec![];
|
||||
|
||||
for active_model in active_models? {
|
||||
let before_save_model = active_model.before_save(&transaction, false).await?;
|
||||
before_save_models.push(before_save_model);
|
||||
}
|
||||
|
||||
let models: Vec<E::Model> = E::insert_many(before_save_models)
|
||||
.exec_with_returning_many(&transaction)
|
||||
.await?;
|
||||
|
||||
let mut result = vec![];
|
||||
for model in models {
|
||||
let after_save_model = A::after_save(model, &transaction, false).await?;
|
||||
result.push(after_save_model);
|
||||
}
|
||||
|
||||
transaction.commit().await?;
|
||||
let result = mutation_fn(resolver_ctx, app_ctx.clone(), input_objects).await?;
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
let db = app_ctx.db();
|
||||
let active_models = active_models?;
|
||||
let results: Vec<E::Model> = E::insert_many(active_models)
|
||||
.exec_with_returning_many(db)
|
||||
.await?;
|
||||
|
||||
Ok(results)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn generate_entity_default_create_batch_mutation_field<E, A>(
|
||||
@ -490,177 +239,45 @@ where
|
||||
E: EntityTrait,
|
||||
<E as EntityTrait>::Model: Sync,
|
||||
<E as EntityTrait>::Model: IntoActiveModel<A>,
|
||||
A: ActiveModelTrait<Entity = E> + sea_orm::ActiveModelBehavior + std::marker::Send + 'static,
|
||||
A: ActiveModelTrait<Entity = E> + sea_orm::ActiveModelBehavior + std::marker::Send,
|
||||
{
|
||||
generate_entity_create_batch_mutation_field::<E, TypeRef>(
|
||||
builder_context,
|
||||
None,
|
||||
generate_entity_default_create_batch_mutation_fn::<E, A>(
|
||||
builder_context,
|
||||
active_model_hooks,
|
||||
),
|
||||
)
|
||||
let entity_create_batch_mutation_builder = EntityCreateBatchMutationBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
entity_create_batch_mutation_builder.to_field::<E, A>(active_model_hooks)
|
||||
}
|
||||
|
||||
pub fn generate_entity_update_mutation_field<E, I>(
|
||||
pub fn generate_entity_update_mutation_field<E>(
|
||||
builder_context: &'static BuilderContext,
|
||||
input_data_type_ref: Option<I>,
|
||||
mutation_fn: UpdateMutationFn<E::Model>,
|
||||
) -> Field
|
||||
where
|
||||
E: EntityTrait,
|
||||
<E as EntityTrait>::Model: Sync,
|
||||
I: Into<TypeRef>,
|
||||
{
|
||||
let guard = builder_context
|
||||
.guards
|
||||
.entity_guards
|
||||
.get(&get_entity_name::<E>(builder_context));
|
||||
let field_guards = &builder_context.guards.field_guards;
|
||||
|
||||
Field::new(
|
||||
get_entity_update_mutation_field_name::<E>(builder_context),
|
||||
TypeRef::named_nn_list_nn(get_entity_basic_type_name::<E>(builder_context)),
|
||||
move |ctx| {
|
||||
let entity_update_mutation_builder = EntityUpdateMutationBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
entity_update_mutation_builder.to_field_with_mutation_fn::<E>(Arc::new(
|
||||
move |resolver_ctx, filters, input_object| {
|
||||
let mutation_fn = mutation_fn.clone();
|
||||
FieldFuture::new(async move {
|
||||
let guard_flag = if let Some(guard) = guard {
|
||||
(*guard)(&ctx)
|
||||
} else {
|
||||
GuardAction::Allow
|
||||
};
|
||||
|
||||
if let GuardAction::Block(reason) = guard_flag {
|
||||
return match reason {
|
||||
Some(reason) => Err::<Option<_>, async_graphql::Error>(
|
||||
async_graphql::Error::new(reason),
|
||||
),
|
||||
None => Err::<Option<_>, async_graphql::Error>(async_graphql::Error::new(
|
||||
"Entity guard triggered.",
|
||||
)),
|
||||
};
|
||||
}
|
||||
Box::pin(async move {
|
||||
let app_ctx = resolver_ctx.data::<Arc<dyn AppContextTrait>>()?;
|
||||
|
||||
let app_ctx = ctx.data::<Arc<dyn AppContextTrait>>()?;
|
||||
|
||||
let filters = ctx.args.get(get_entity_update_mutation_filter_field_name(
|
||||
builder_context,
|
||||
));
|
||||
let filter_condition = get_filter_conditions::<E>(&ctx, builder_context, filters);
|
||||
|
||||
let value_accessor = ctx
|
||||
.args
|
||||
.get(get_entity_update_mutation_data_field_name(builder_context))
|
||||
.unwrap();
|
||||
let input_object = value_accessor.object()?;
|
||||
|
||||
for (column, _) in input_object.iter() {
|
||||
let field_guard = field_guards.get(
|
||||
&get_entity_and_column_name_from_column_str::<E>(builder_context, column),
|
||||
);
|
||||
let field_guard_flag = if let Some(field_guard) = field_guard {
|
||||
(*field_guard)(&ctx)
|
||||
} else {
|
||||
GuardAction::Allow
|
||||
};
|
||||
if let GuardAction::Block(reason) = field_guard_flag {
|
||||
return match reason {
|
||||
Some(reason) => Err::<Option<_>, async_graphql::Error>(
|
||||
async_graphql::Error::new(reason),
|
||||
),
|
||||
None => Err::<Option<_>, async_graphql::Error>(
|
||||
async_graphql::Error::new("Field guard triggered."),
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let result = mutation_fn(&ctx, app_ctx.clone(), filter_condition, input_object)
|
||||
let result = mutation_fn(
|
||||
resolver_ctx,
|
||||
app_ctx.clone(),
|
||||
get_filter_conditions::<E>(resolver_ctx, builder_context, filters),
|
||||
input_object,
|
||||
)
|
||||
.await
|
||||
.map_err(async_graphql::Error::new_with_source)?;
|
||||
|
||||
Ok(Some(FieldValue::list(
|
||||
result.into_iter().map(FieldValue::owned_any),
|
||||
)))
|
||||
Ok(result)
|
||||
})
|
||||
},
|
||||
)
|
||||
.argument(InputValue::new(
|
||||
get_entity_update_mutation_data_field_name(builder_context),
|
||||
input_data_type_ref.map(|t| t.into()).unwrap_or_else(|| {
|
||||
TypeRef::named_nn(get_entity_update_data_input_type_name::<E>(builder_context))
|
||||
}),
|
||||
))
|
||||
.argument(InputValue::new(
|
||||
get_entity_update_mutation_filter_field_name(builder_context),
|
||||
TypeRef::named(get_entity_filter_input_type_name::<E>(builder_context)),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn generate_entity_default_update_mutation_fn<T, A>(
|
||||
builder_context: &'static BuilderContext,
|
||||
active_model_hooks: bool,
|
||||
) -> UpdateMutationFn<T::Model>
|
||||
where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync + IntoActiveModel<A>,
|
||||
A: ActiveModelTrait<Entity = T> + sea_orm::ActiveModelBehavior + std::marker::Send + 'static,
|
||||
{
|
||||
Arc::new(
|
||||
move |resolve_context, app_ctx, filter_condition, input_object| {
|
||||
let entity_input_builder = seaography::EntityInputBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
let entity_object_builder = seaography::EntityObjectBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
|
||||
let active_model = prepare_active_model::<T, A>(
|
||||
&entity_input_builder,
|
||||
&entity_object_builder,
|
||||
&input_object,
|
||||
resolve_context,
|
||||
)
|
||||
.map_err(SeaographyError::AsyncGraphQLError);
|
||||
|
||||
Box::pin(async move {
|
||||
if active_model_hooks {
|
||||
let transaction = app_ctx.db().begin().await?;
|
||||
|
||||
let active_model = active_model?;
|
||||
|
||||
let active_model = active_model.before_save(&transaction, false).await?;
|
||||
|
||||
let models = T::update_many()
|
||||
.set(active_model)
|
||||
.filter(filter_condition.clone())
|
||||
.exec_with_returning(&transaction)
|
||||
.await?;
|
||||
let mut result = vec![];
|
||||
|
||||
for model in models {
|
||||
result.push(A::after_save(model, &transaction, false).await?);
|
||||
}
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
let db = app_ctx.db();
|
||||
|
||||
let active_model = active_model?;
|
||||
|
||||
let result = T::update_many()
|
||||
.set(active_model)
|
||||
.filter(filter_condition.clone())
|
||||
.exec_with_returning(db)
|
||||
.await?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn generate_entity_default_update_mutation_field<E, A>(
|
||||
@ -671,13 +288,12 @@ where
|
||||
E: EntityTrait,
|
||||
<E as EntityTrait>::Model: Sync,
|
||||
<E as EntityTrait>::Model: IntoActiveModel<A>,
|
||||
A: ActiveModelTrait<Entity = E> + sea_orm::ActiveModelBehavior + std::marker::Send + 'static,
|
||||
A: ActiveModelTrait<Entity = E> + sea_orm::ActiveModelBehavior + std::marker::Send,
|
||||
{
|
||||
generate_entity_update_mutation_field::<E, TypeRef>(
|
||||
builder_context,
|
||||
None,
|
||||
generate_entity_default_update_mutation_fn::<E, A>(builder_context, active_model_hooks),
|
||||
)
|
||||
let entity_update_mutation_builder = EntityUpdateMutationBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
entity_update_mutation_builder.to_field::<E, A>(active_model_hooks)
|
||||
}
|
||||
|
||||
pub fn generate_entity_delete_mutation_field<E>(
|
||||
@ -688,111 +304,42 @@ where
|
||||
E: EntityTrait,
|
||||
<E as EntityTrait>::Model: Sync,
|
||||
{
|
||||
let object_name: String = get_entity_name::<E>(builder_context);
|
||||
let guard = builder_context.guards.entity_guards.get(&object_name);
|
||||
|
||||
Field::new(
|
||||
get_entity_delete_mutation_field_name::<E>(builder_context),
|
||||
TypeRef::named_nn(TypeRef::INT),
|
||||
move |ctx| {
|
||||
let mutation_fn = mutation_fn.clone();
|
||||
FieldFuture::new(async move {
|
||||
let guard_flag = if let Some(guard) = guard {
|
||||
(*guard)(&ctx)
|
||||
} else {
|
||||
GuardAction::Allow
|
||||
let entity_delete_mutation_builder = EntityDeleteMutationBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
entity_delete_mutation_builder.to_field_with_mutation_fn::<E>(Arc::new(
|
||||
move |resolver_ctx, filters| {
|
||||
let mutation_fn = mutation_fn.clone();
|
||||
|
||||
if let GuardAction::Block(reason) = guard_flag {
|
||||
return Err::<Option<_>, async_graphql::Error>(async_graphql::Error::new(
|
||||
reason.unwrap_or("Entity guard triggered.".into()),
|
||||
));
|
||||
}
|
||||
|
||||
let filters = ctx.args.get(get_entity_delete_mutation_filter_field_name(
|
||||
builder_context,
|
||||
));
|
||||
let filter_condition = get_filter_conditions::<E>(&ctx, builder_context, filters);
|
||||
|
||||
let app_ctx = ctx.data::<Arc<dyn AppContextTrait>>()?;
|
||||
|
||||
let res = mutation_fn(&ctx, app_ctx.clone(), filter_condition)
|
||||
Box::pin(async move {
|
||||
let app_ctx = resolver_ctx.data::<Arc<dyn AppContextTrait>>()?;
|
||||
let result = mutation_fn(
|
||||
resolver_ctx,
|
||||
app_ctx.clone(),
|
||||
get_filter_conditions::<E>(resolver_ctx, builder_context, filters),
|
||||
)
|
||||
.await
|
||||
.map_err(async_graphql::Error::new_with_source)?;
|
||||
|
||||
Ok(Some(async_graphql::Value::from(res)))
|
||||
Ok(result)
|
||||
})
|
||||
},
|
||||
)
|
||||
.argument(InputValue::new(
|
||||
get_entity_delete_mutation_filter_field_name(builder_context),
|
||||
TypeRef::named(get_entity_filter_input_type_name::<E>(builder_context)),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn generate_entity_default_delete_mutation_fn<E, A>(
|
||||
_builder_context: &'static BuilderContext,
|
||||
active_model_hooks: bool,
|
||||
) -> DeleteMutationFn
|
||||
where
|
||||
E: EntityTrait,
|
||||
<E as EntityTrait>::Model: Sync,
|
||||
<E as EntityTrait>::Model: IntoActiveModel<A>,
|
||||
A: ActiveModelTrait<Entity = E> + sea_orm::ActiveModelBehavior + std::marker::Send + 'static,
|
||||
{
|
||||
Arc::new(move |_resolve_context, app_ctx, filter_condition| {
|
||||
Box::pin(async move {
|
||||
if active_model_hooks {
|
||||
let transaction = app_ctx.db().begin().await?;
|
||||
|
||||
let models: Vec<E::Model> = E::find()
|
||||
.filter(filter_condition.clone())
|
||||
.all(&transaction)
|
||||
.await?;
|
||||
|
||||
let mut active_models: Vec<A> = vec![];
|
||||
for model in models {
|
||||
let active_model = model.into_active_model();
|
||||
active_models.push(active_model.before_delete(&transaction).await?);
|
||||
}
|
||||
|
||||
let result = E::delete_many()
|
||||
.filter(filter_condition)
|
||||
.exec(&transaction)
|
||||
.await?;
|
||||
|
||||
for active_model in active_models {
|
||||
active_model.after_delete(&transaction).await?;
|
||||
}
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(result.rows_affected)
|
||||
} else {
|
||||
let db = app_ctx.db();
|
||||
|
||||
let result = E::delete_many().filter(filter_condition).exec(db).await?;
|
||||
|
||||
Ok(result.rows_affected)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn generate_entity_default_delete_mutation_field<E, A>(
|
||||
builder_context: &'static BuilderContext,
|
||||
active_model_hooks: bool,
|
||||
) -> Field
|
||||
where
|
||||
E: EntityTrait,
|
||||
<E as EntityTrait>::Model: Sync,
|
||||
<E as EntityTrait>::Model: IntoActiveModel<A>,
|
||||
A: ActiveModelTrait<Entity = E> + sea_orm::ActiveModelBehavior + std::marker::Send + 'static,
|
||||
<E as EntityTrait>::Model: Sync + IntoActiveModel<A>,
|
||||
A: ActiveModelTrait<Entity = E> + sea_orm::ActiveModelBehavior + std::marker::Send,
|
||||
{
|
||||
generate_entity_delete_mutation_field::<E>(
|
||||
builder_context,
|
||||
generate_entity_default_delete_mutation_fn::<E, A>(builder_context, active_model_hooks),
|
||||
)
|
||||
let entity_delete_mutation_builder = EntityDeleteMutationBuilder {
|
||||
context: builder_context,
|
||||
};
|
||||
entity_delete_mutation_builder.to_field::<E, A>(active_model_hooks)
|
||||
}
|
||||
|
||||
pub fn register_entity_default_mutations<E, A>(
|
||||
@ -802,30 +349,31 @@ pub fn register_entity_default_mutations<E, A>(
|
||||
where
|
||||
E: EntityTrait,
|
||||
<E as EntityTrait>::Model: Sync + IntoActiveModel<A>,
|
||||
A: ActiveModelTrait<Entity = E> + sea_orm::ActiveModelBehavior + std::marker::Send + 'static,
|
||||
A: ActiveModelTrait<Entity = E> + sea_orm::ActiveModelBehavior + std::marker::Send,
|
||||
{
|
||||
let builder_context = builder.context;
|
||||
builder
|
||||
.outputs
|
||||
.push(generate_entity_default_basic_entity_object::<E>(
|
||||
builder.context,
|
||||
builder_context,
|
||||
));
|
||||
|
||||
builder.inputs.extend([
|
||||
generate_entity_default_insert_input_object::<E>(builder.context),
|
||||
generate_entity_default_update_input_object::<E>(builder.context),
|
||||
generate_entity_default_insert_input_object::<E>(builder_context),
|
||||
generate_entity_default_update_input_object::<E>(builder_context),
|
||||
]);
|
||||
|
||||
builder.mutations.extend([
|
||||
generate_entity_default_create_one_mutation_field::<E, A>(
|
||||
builder.context,
|
||||
builder_context,
|
||||
active_model_hooks,
|
||||
),
|
||||
generate_entity_default_create_batch_mutation_field::<E, A>(
|
||||
builder.context,
|
||||
builder_context,
|
||||
active_model_hooks,
|
||||
),
|
||||
generate_entity_default_update_mutation_field::<E, A>(builder.context, active_model_hooks),
|
||||
generate_entity_default_delete_mutation_field::<E, A>(builder.context, active_model_hooks),
|
||||
generate_entity_default_update_mutation_field::<E, A>(builder_context, active_model_hooks),
|
||||
generate_entity_default_delete_mutation_field::<E, A>(builder_context, active_model_hooks),
|
||||
]);
|
||||
|
||||
builder
|
||||
@ -859,7 +407,7 @@ pub(crate) fn register_entity_default_writable_impl<T, RE, A, I>(
|
||||
where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync + IntoActiveModel<A>,
|
||||
A: ActiveModelTrait<Entity = T> + sea_orm::ActiveModelBehavior + std::marker::Send + 'static,
|
||||
A: ActiveModelTrait<Entity = T> + sea_orm::ActiveModelBehavior + std::marker::Send,
|
||||
RE: sea_orm::Iterable<Iterator = I> + RelationBuilder,
|
||||
I: Iterator<Item = RE> + Clone + DoubleEndedIterator + ExactSizeIterator + FusedIterator,
|
||||
{
|
||||
|
@ -911,18 +911,15 @@ where
|
||||
Box::new(
|
||||
move |_resolve_context: &ResolverContext<'_>, condition, filter| {
|
||||
if let Some(filter) = filter {
|
||||
let filter_value = to_value(filter.as_index_map()).map_err(|e| {
|
||||
SeaographyError::AsyncGraphQLError(GraphqlError::new_with_source(e))
|
||||
})?;
|
||||
let filter_value =
|
||||
to_value(filter.as_index_map()).map_err(GraphqlError::new_with_source)?;
|
||||
|
||||
let filter_json: JsonValue = filter_value.into_json().map_err(|e| {
|
||||
SeaographyError::AsyncGraphQLError(GraphqlError::new(format!("{e:?}")))
|
||||
})?;
|
||||
let filter_json: JsonValue = filter_value
|
||||
.into_json()
|
||||
.map_err(GraphqlError::new_with_source)?;
|
||||
|
||||
let cond_where = prepare_jsonb_filter_input(&Expr::col(column), filter_json)
|
||||
.map_err(|e| {
|
||||
SeaographyError::AsyncGraphQLError(GraphqlError::new_with_source(e))
|
||||
})?;
|
||||
.map_err(GraphqlError::new_with_source)?;
|
||||
|
||||
let condition = condition.add(cond_where);
|
||||
Ok(condition)
|
||||
@ -946,14 +943,22 @@ where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync,
|
||||
{
|
||||
let entity_column_name = get_entity_and_column_name::<T>(context, column);
|
||||
context.filter_types.overwrites.insert(
|
||||
get_entity_and_column_name::<T>(context, column),
|
||||
Some(FilterType::Custom(JSONB_FILTER_NAME.to_string())),
|
||||
);
|
||||
context.filter_types.condition_functions.insert(
|
||||
entity_column_name.clone(),
|
||||
generate_jsonb_filter_condition_function::<T>(context, column),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn validate_jsonb_input_for_entity<T, S>(context: &mut BuilderContext, column: &T::Column)
|
||||
where
|
||||
pub fn try_convert_jsonb_input_for_entity<T, S>(
|
||||
context: &mut BuilderContext,
|
||||
column: &T::Column,
|
||||
case: Option<Case<'static>>,
|
||||
) where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync,
|
||||
S: DeserializeOwned + Serialize,
|
||||
@ -962,49 +967,52 @@ where
|
||||
context.types.input_conversions.insert(
|
||||
entity_column_name.clone(),
|
||||
Box::new(move |_resolve_context, accessor| {
|
||||
let deserialized = accessor.deserialize::<S>().map_err(|err| {
|
||||
SeaographyError::TypeConversionError(
|
||||
err.message,
|
||||
format!("Json - {entity_column_name}"),
|
||||
)
|
||||
})?;
|
||||
let json_value = serde_json::to_value(deserialized).map_err(|err| {
|
||||
let mut json_value: serde_json::Value = accessor.deserialize()?;
|
||||
|
||||
if let Some(case) = case {
|
||||
json_value = convert_json_keys(json_value, case);
|
||||
}
|
||||
|
||||
serde_json::from_value::<S>(json_value.clone()).map_err(|err| {
|
||||
SeaographyError::TypeConversionError(
|
||||
err.to_string(),
|
||||
format!("Json - {entity_column_name}"),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(sea_orm::Value::Json(Some(Box::new(json_value))))
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn convert_jsonb_output_case_for_entity<T>(
|
||||
pub fn convert_jsonb_output_for_entity<T>(
|
||||
context: &mut BuilderContext,
|
||||
column: &T::Column,
|
||||
case: Case<'static>,
|
||||
case: Option<Case<'static>>,
|
||||
) where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync,
|
||||
{
|
||||
let entity_column_key = get_entity_and_column_name::<T>(context, column);
|
||||
let entity_column_name = get_entity_and_column_name::<T>(context, column);
|
||||
context.types.output_conversions.insert(
|
||||
entity_column_key.clone(),
|
||||
entity_column_name.clone(),
|
||||
Box::new(move |value| {
|
||||
if let sea_orm::Value::Json(Some(json)) = value {
|
||||
let result =
|
||||
async_graphql::Value::from_json(convert_json_keys(json.as_ref().clone(), case))
|
||||
.map_err(|err| {
|
||||
let mut json_value = json.as_ref().clone();
|
||||
if let Some(case) = case {
|
||||
json_value = convert_json_keys(json_value, case);
|
||||
}
|
||||
let result = async_graphql::Value::from_json(json_value).map_err(|err| {
|
||||
SeaographyError::TypeConversionError(
|
||||
err.to_string(),
|
||||
format!("Json - {entity_column_key}"),
|
||||
format!("Json - {entity_column_name}"),
|
||||
)
|
||||
})?;
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(SeaographyError::TypeConversionError(
|
||||
"value should be json".to_string(),
|
||||
format!("Json - {entity_column_key}"),
|
||||
format!("Json - {entity_column_name}"),
|
||||
))
|
||||
}
|
||||
}),
|
||||
|
@ -78,7 +78,7 @@ where
|
||||
context.filter_input.type_name.as_ref()(&entity_name)
|
||||
}
|
||||
|
||||
pub fn get_entity_insert_data_input_type_name<T>(context: &BuilderContext) -> String
|
||||
pub fn get_entity_insert_input_type_name<T>(context: &BuilderContext) -> String
|
||||
where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync,
|
||||
@ -87,7 +87,7 @@ where
|
||||
format!("{entity_name}{}", context.entity_input.insert_suffix)
|
||||
}
|
||||
|
||||
pub fn get_entity_update_data_input_type_name<T>(context: &BuilderContext) -> String
|
||||
pub fn get_entity_update_input_type_name<T>(context: &BuilderContext) -> String
|
||||
where
|
||||
T: EntityTrait,
|
||||
<T as EntityTrait>::Model: Sync,
|
||||
|
@ -128,20 +128,14 @@ impl ActiveModelBehavior for ActiveModel {
|
||||
Model::calculate_next_run(cron_expr).map_err(|e| DbErr::Custom(e.to_string()))?;
|
||||
self.next_run = Set(Some(next_run));
|
||||
}
|
||||
if let ActiveValue::Set(Some(subscriber_id)) = self.subscriber_id {
|
||||
if let ActiveValue::Set(Some(ref subscriber_task)) = self.subscriber_task {
|
||||
if subscriber_task.get_subscriber_id() != subscriber_id {
|
||||
if let ActiveValue::Set(Some(subscriber_id)) = self.subscriber_id
|
||||
&& let ActiveValue::Set(Some(ref subscriber_task)) = self.subscriber_task
|
||||
&& subscriber_task.get_subscriber_id() != subscriber_id
|
||||
{
|
||||
return Err(DbErr::Custom(
|
||||
"Subscriber task subscriber_id does not match cron subscriber_id"
|
||||
.to_string(),
|
||||
"Cron subscriber_id does not match subscriber_task.subscriber_id".to_string(),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
return Err(DbErr::Custom(
|
||||
"Cron subscriber_id is set but subscriber_task is not set".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
use async_trait::async_trait;
|
||||
use sea_orm::entity::prelude::*;
|
||||
use sea_orm::{ActiveValue, entity::prelude::*};
|
||||
|
||||
use crate::task::SubscriberTaskTrait;
|
||||
pub use crate::task::{
|
||||
SubscriberTask, SubscriberTaskType, SubscriberTaskTypeEnum, SubscriberTaskTypeVariant,
|
||||
SubscriberTaskTypeVariantIter,
|
||||
SubscriberTask, SubscriberTaskInput, SubscriberTaskType, SubscriberTaskTypeEnum,
|
||||
SubscriberTaskTypeVariant, SubscriberTaskTypeVariantIter,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveActiveEnum, EnumIter, DeriveDisplay)]
|
||||
@ -84,4 +85,19 @@ pub enum RelatedEntity {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
impl ActiveModelBehavior for ActiveModel {
|
||||
async fn before_save<C>(mut self, _db: &C, _insert: bool) -> Result<Self, DbErr>
|
||||
where
|
||||
C: ConnectionTrait,
|
||||
{
|
||||
if let ActiveValue::Set(subscriber_id) = self.subscriber_id
|
||||
&& let ActiveValue::Set(ref job) = self.job
|
||||
&& job.get_subscriber_id() != subscriber_id
|
||||
{
|
||||
return Err(DbErr::Custom(
|
||||
"SubscriberTask subscriber_id does not match job.subscriber_id".to_string(),
|
||||
));
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
@ -42,9 +42,13 @@ where
|
||||
}
|
||||
|
||||
pub trait SubscriberTaskTrait: AsyncTaskTrait {
|
||||
type InputType: Serialize + DeserializeOwned + Sized + Send;
|
||||
|
||||
fn get_subscriber_id(&self) -> i32;
|
||||
|
||||
fn get_cron_id(&self) -> Option<i32>;
|
||||
|
||||
fn from_input(input: Self::InputType, subscriber_id: i32) -> Self;
|
||||
}
|
||||
|
||||
pub trait SystemTaskTrait: AsyncTaskTrait {}
|
||||
|
@ -12,9 +12,10 @@ pub use core::{
|
||||
pub use config::TaskConfig;
|
||||
pub use r#extern::{ApalisJobs, ApalisSchema};
|
||||
pub use registry::{
|
||||
OptimizeImageTask, SubscriberTask, SubscriberTaskType, SubscriberTaskTypeEnum,
|
||||
SubscriberTaskTypeVariant, SubscriberTaskTypeVariantIter, SyncOneSubscriptionFeedsFullTask,
|
||||
SyncOneSubscriptionFeedsIncrementalTask, SyncOneSubscriptionSourcesTask, SystemTask,
|
||||
SystemTaskType, SystemTaskTypeEnum, SystemTaskTypeVariant, SystemTaskTypeVariantIter,
|
||||
OptimizeImageTask, SubscriberTask, SubscriberTaskInput, SubscriberTaskType,
|
||||
SubscriberTaskTypeEnum, SubscriberTaskTypeVariant, SubscriberTaskTypeVariantIter,
|
||||
SyncOneSubscriptionFeedsFullTask, SyncOneSubscriptionFeedsIncrementalTask,
|
||||
SyncOneSubscriptionSourcesTask, SystemTask, SystemTaskType, SystemTaskTypeEnum,
|
||||
SystemTaskTypeVariant, SystemTaskTypeVariantIter,
|
||||
};
|
||||
pub use service::TaskService;
|
||||
|
@ -2,8 +2,8 @@ mod subscriber;
|
||||
mod system;
|
||||
|
||||
pub use subscriber::{
|
||||
SubscriberTask, SubscriberTaskType, SubscriberTaskTypeEnum, SubscriberTaskTypeVariant,
|
||||
SubscriberTaskTypeVariantIter, SyncOneSubscriptionFeedsFullTask,
|
||||
SubscriberTask, SubscriberTaskInput, SubscriberTaskType, SubscriberTaskTypeEnum,
|
||||
SubscriberTaskTypeVariant, SubscriberTaskTypeVariantIter, SyncOneSubscriptionFeedsFullTask,
|
||||
SyncOneSubscriptionFeedsIncrementalTask, SyncOneSubscriptionSourcesTask,
|
||||
};
|
||||
pub use system::{
|
||||
|
@ -6,15 +6,36 @@ macro_rules! register_subscriber_task_type {
|
||||
}
|
||||
) => {
|
||||
$(#[$type_meta])*
|
||||
#[derive(typed_builder::TypedBuilder)]
|
||||
#[derive(typed_builder::TypedBuilder, ts_rs::TS, serde::Serialize, serde::Deserialize)]
|
||||
#[ts(export, rename_all = "camelCase")]
|
||||
$task_vis struct $task_name {
|
||||
$($(#[$field_meta])* pub $field_name: $field_type,)*
|
||||
pub subscriber_id: i32,
|
||||
#[builder(default = None)]
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub cron_id: Option<i32>,
|
||||
}
|
||||
|
||||
paste::paste! {
|
||||
$(#[$type_meta])*
|
||||
#[derive(ts_rs::TS, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export, rename_all = "camelCase")]
|
||||
$task_vis struct [<$task_name Input>] {
|
||||
$($(#[$field_meta])* pub $field_name: $field_type,)*
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub subscriber_id: Option<i32>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub cron_id: Option<i32>,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl $crate::task::SubscriberTaskTrait for $task_name {
|
||||
paste::paste! {
|
||||
type InputType = [<$task_name Input>];
|
||||
}
|
||||
|
||||
fn get_subscriber_id(&self) -> i32 {
|
||||
self.subscriber_id
|
||||
}
|
||||
@ -22,6 +43,14 @@ macro_rules! register_subscriber_task_type {
|
||||
fn get_cron_id(&self) -> Option<i32> {
|
||||
self.cron_id
|
||||
}
|
||||
|
||||
fn from_input(input: Self::InputType, subscriber_id: i32) -> Self {
|
||||
Self {
|
||||
$($field_name: input.$field_name,)*
|
||||
cron_id: input.cron_id,
|
||||
subscriber_id: input.subscriber_id.unwrap_or(subscriber_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ mod base;
|
||||
mod subscription;
|
||||
|
||||
use sea_orm::{DeriveActiveEnum, DeriveDisplay, EnumIter, FromJsonQueryResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub use subscription::{
|
||||
SyncOneSubscriptionFeedsFullTask, SyncOneSubscriptionFeedsIncrementalTask,
|
||||
SyncOneSubscriptionSourcesTask,
|
||||
@ -12,7 +11,7 @@ macro_rules! register_subscriber_task_types {
|
||||
(
|
||||
task_type_enum: {
|
||||
$(#[$type_enum_meta:meta])*
|
||||
pub enum $type_enum_name:ident {
|
||||
$type_vis:vis enum $type_enum_name:ident {
|
||||
$(
|
||||
$(#[$variant_meta:meta])*
|
||||
$variant:ident => $string_value:literal
|
||||
@ -21,7 +20,7 @@ macro_rules! register_subscriber_task_types {
|
||||
},
|
||||
task_enum: {
|
||||
$(#[$task_enum_meta:meta])*
|
||||
pub enum $task_enum_name:ident {
|
||||
$task_vis:vis enum $task_enum_name:ident {
|
||||
$(
|
||||
$(#[$task_variant_meta:meta])*
|
||||
$task_variant:ident($task_type:ty)
|
||||
@ -30,8 +29,9 @@ macro_rules! register_subscriber_task_types {
|
||||
}
|
||||
) => {
|
||||
$(#[$type_enum_meta])*
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[sea_orm(rs_type = "String", db_type = "Text")]
|
||||
pub enum $type_enum_name {
|
||||
$type_vis enum $type_enum_name {
|
||||
$(
|
||||
$(#[$variant_meta])*
|
||||
#[serde(rename = $string_value)]
|
||||
@ -42,8 +42,10 @@ macro_rules! register_subscriber_task_types {
|
||||
|
||||
|
||||
$(#[$task_enum_meta])*
|
||||
#[derive(ts_rs::TS, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(tag = "task_type")]
|
||||
pub enum $task_enum_name {
|
||||
#[ts(export,rename = "SubscriberTaskType", rename_all = "camelCase", tag = "taskType")]
|
||||
$task_vis enum $task_enum_name {
|
||||
$(
|
||||
$(#[$task_variant_meta])*
|
||||
#[serde(rename = $string_value)]
|
||||
@ -51,6 +53,20 @@ macro_rules! register_subscriber_task_types {
|
||||
)*
|
||||
}
|
||||
|
||||
paste::paste! {
|
||||
$(#[$task_enum_meta])*
|
||||
#[derive(ts_rs::TS, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(tag = "taskType", rename_all = "camelCase")]
|
||||
#[ts(export,rename_all = "camelCase", tag = "taskType")]
|
||||
$task_vis enum [<$task_enum_name Input>] {
|
||||
$(
|
||||
$(#[$task_variant_meta])*
|
||||
#[serde(rename = $string_value)]
|
||||
$task_variant(<$task_type as $crate::task::SubscriberTaskTrait>::InputType),
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<$task_enum_name> for serde_json::Value {
|
||||
type Error = $crate::errors::RecorderError;
|
||||
|
||||
@ -87,6 +103,10 @@ macro_rules! register_subscriber_task_types {
|
||||
}
|
||||
|
||||
impl $crate::task::SubscriberTaskTrait for $task_enum_name {
|
||||
paste::paste! {
|
||||
type InputType = [<$task_enum_name Input>];
|
||||
}
|
||||
|
||||
fn get_subscriber_id(&self) -> i32 {
|
||||
match self {
|
||||
$(Self::$task_variant(t) =>
|
||||
@ -100,6 +120,14 @@ macro_rules! register_subscriber_task_types {
|
||||
<$task_type as $crate::task::SubscriberTaskTrait>::get_cron_id(t),)*
|
||||
}
|
||||
}
|
||||
|
||||
fn from_input(input: Self::InputType, subscriber_id: i32) -> Self {
|
||||
match input {
|
||||
$(Self::InputType::$task_variant(t) =>
|
||||
Self::$task_variant(<$task_type as $crate::task::SubscriberTaskTrait>::from_input(t, subscriber_id)),)*
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
@ -117,8 +145,6 @@ register_subscriber_task_types!(
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Copy,
|
||||
@ -133,7 +159,7 @@ register_subscriber_task_types!(
|
||||
}
|
||||
},
|
||||
task_enum: {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, FromJsonQueryResult)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, FromJsonQueryResult)]
|
||||
pub enum SubscriberTask {
|
||||
SyncOneSubscriptionFeedsIncremental(SyncOneSubscriptionFeedsIncrementalTask),
|
||||
SyncOneSubscriptionFeedsFull(SyncOneSubscriptionFeedsFullTask),
|
||||
|
@ -1,5 +1,4 @@
|
||||
use sea_orm::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::base::register_subscriber_task_type;
|
||||
use crate::{errors::RecorderResult, models::subscriptions::SubscriptionTrait};
|
||||
@ -40,7 +39,7 @@ macro_rules! register_subscription_task_type {
|
||||
}
|
||||
|
||||
register_subscription_task_type! {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct SyncOneSubscriptionFeedsIncrementalTask {
|
||||
} => async |subscription, ctx| -> RecorderResult<()> {
|
||||
subscription.sync_feeds_incremental(ctx).await?;
|
||||
@ -49,7 +48,7 @@ register_subscription_task_type! {
|
||||
}
|
||||
|
||||
register_subscription_task_type! {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct SyncOneSubscriptionFeedsFullTask {
|
||||
} => async |subscription, ctx| -> RecorderResult<()> {
|
||||
subscription.sync_feeds_full(ctx).await?;
|
||||
@ -58,7 +57,7 @@ register_subscription_task_type! {
|
||||
}
|
||||
|
||||
register_subscription_task_type! {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct SyncOneSubscriptionSourcesTask {
|
||||
} => async |subscription, ctx| -> RecorderResult<()> {
|
||||
subscription.sync_sources(ctx).await?;
|
||||
|
10
apps/recorder/tsconfig.json
Normal file
10
apps/recorder/tsconfig.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler"
|
||||
},
|
||||
"include": ["bindings"]
|
||||
}
|
@ -12,6 +12,12 @@ const config: CodegenConfig = {
|
||||
},
|
||||
config: {
|
||||
enumsAsConst: true,
|
||||
scalars: {
|
||||
SubscriberTaskType: {
|
||||
input: 'recorder/bindings/SubscriberTaskInput#SubscriberTaskInput',
|
||||
output: 'recorder/bindings/SubscriberTaskType#SubscriberTaskType',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -11,6 +11,7 @@
|
||||
"codegen-watch": "graphql-codegen --config graphql-codegen.ts --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"recorder": "workspace:*",
|
||||
"@abraham/reflection": "^0.13.0",
|
||||
"@apollo/client": "^3.13.8",
|
||||
"@codemirror/language": "6.11.1",
|
||||
|
@ -89,6 +89,7 @@ query GetSubscriptionDetail ($id: Int!) {
|
||||
} }) {
|
||||
nodes {
|
||||
id
|
||||
subscriberId
|
||||
displayName
|
||||
createdAt
|
||||
updatedAt
|
||||
@ -137,30 +138,6 @@ query GetSubscriptionDetail ($id: Int!) {
|
||||
}
|
||||
`;
|
||||
|
||||
export const SYNC_SUBSCRIPTION_FEEDS_INCREMENTAL = gql`
|
||||
mutation SyncSubscriptionFeedsIncremental($filter: SubscriptionsFilterInput!) {
|
||||
subscriptionsSyncOneFeedsIncremental(filter: $filter) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const SYNC_SUBSCRIPTION_FEEDS_FULL = gql`
|
||||
mutation SyncSubscriptionFeedsFull($filter: SubscriptionsFilterInput!) {
|
||||
subscriptionsSyncOneFeedsFull(filter: $filter) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const SYNC_SUBSCRIPTION_SOURCES = gql`
|
||||
mutation SyncSubscriptionSources($filter: SubscriptionsFilterInput!) {
|
||||
subscriptionsSyncOneSources(filter: $filter) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const SubscriptionFormTypedMikanSeasonSchema =
|
||||
MikanSubscriptionSeasonSourceUrlSchema.and(
|
||||
type({
|
||||
|
@ -1,10 +1,5 @@
|
||||
import {
|
||||
type GetTasksQuery,
|
||||
SubscriberTaskTypeEnum,
|
||||
} from '@/infra/graphql/gql/graphql';
|
||||
import type { GetTasksQuery } from '@/infra/graphql/gql/graphql';
|
||||
import { gql } from '@apollo/client';
|
||||
import { type } from 'arktype';
|
||||
import { SubscriptionSchema } from './subscriptions';
|
||||
|
||||
export const GET_TASKS = gql`
|
||||
query GetTasks($filter: SubscriberTasksFilterInput!, $orderBy: SubscriberTasksOrderInput!, $pagination: PaginationInput!) {
|
||||
@ -25,7 +20,11 @@ export const GET_TASKS = gql`
|
||||
lockAt,
|
||||
lockBy,
|
||||
doneAt,
|
||||
priority
|
||||
priority,
|
||||
subscription {
|
||||
displayName
|
||||
sourceUrl
|
||||
}
|
||||
}
|
||||
paginationInfo {
|
||||
total
|
||||
@ -35,6 +34,14 @@ export const GET_TASKS = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export const INSERT_SUBSCRIBER_TASK = gql`
|
||||
mutation InsertSubscriberTask($data: SubscriberTasksInsertInput!) {
|
||||
subscriberTasksCreateOne(data: $data) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const DELETE_TASKS = gql`
|
||||
mutation DeleteTasks($filter: SubscriberTasksFilterInput!) {
|
||||
subscriberTasksDelete(filter: $filter)
|
||||
@ -60,27 +67,4 @@ export const RETRY_TASKS = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export const TaskTypedSyncOneSubscriptionFeedsIncrementalSchema = type({
|
||||
taskType: `'${SubscriberTaskTypeEnum.SyncOneSubscriptionFeedsIncremental}'`,
|
||||
}).and(SubscriptionSchema);
|
||||
|
||||
export const TaskTypedSyncOneSubscriptionFeedsFullSchema = type({
|
||||
taskType: `'${SubscriberTaskTypeEnum.SyncOneSubscriptionFeedsFull}'`,
|
||||
}).and(SubscriptionSchema);
|
||||
|
||||
export const TaskTypedSyncOneSubscriptionSourcesSchema = type({
|
||||
taskType: `'${SubscriberTaskTypeEnum.SyncOneSubscriptionSources}'`,
|
||||
}).and(SubscriptionSchema);
|
||||
|
||||
export const TaskTypedSchema = TaskTypedSyncOneSubscriptionFeedsFullSchema.or(
|
||||
TaskTypedSyncOneSubscriptionFeedsIncrementalSchema
|
||||
).or(TaskTypedSyncOneSubscriptionSourcesSchema);
|
||||
|
||||
export type TaskTypedDto = typeof TaskTypedSchema.infer;
|
||||
|
||||
export type TaskDto = Omit<
|
||||
GetTasksQuery['subscriberTasks']['nodes'][number],
|
||||
'job'
|
||||
> & {
|
||||
job: TaskTypedDto;
|
||||
};
|
||||
export type TaskDto = GetTasksQuery['subscriberTasks']['nodes'][number];
|
||||
|
@ -0,0 +1,7 @@
|
||||
import { AuthService } from '@/domains/auth/auth.service';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
|
||||
@Injectable()
|
||||
export class SubscriberService {
|
||||
authService = inject(AuthService);
|
||||
}
|
@ -26,11 +26,9 @@ type Documents = {
|
||||
"\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 $filter: SubscriptionsFilterInput!,\n ) {\n subscriptionsUpdate (\n data: $data\n filter: $filter\n ) {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n }\n}\n": typeof types.UpdateSubscriptionsDocument,
|
||||
"\n mutation DeleteSubscriptions($filter: SubscriptionsFilterInput) {\n subscriptionsDelete(filter: $filter)\n }\n": typeof types.DeleteSubscriptionsDocument,
|
||||
"\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filter: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n feed {\n nodes {\n id\n createdAt\n updatedAt\n token\n feedType\n feedSource\n }\n }\n subscriberTask {\n nodes {\n id\n taskType\n status\n }\n }\n credential3rd {\n id\n username\n }\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n homepage\n }\n }\n }\n }\n}\n": typeof types.GetSubscriptionDetailDocument,
|
||||
"\n mutation SyncSubscriptionFeedsIncremental($filter: SubscriptionsFilterInput!) {\n subscriptionsSyncOneFeedsIncremental(filter: $filter) {\n id\n }\n }\n": typeof types.SyncSubscriptionFeedsIncrementalDocument,
|
||||
"\n mutation SyncSubscriptionFeedsFull($filter: SubscriptionsFilterInput!) {\n subscriptionsSyncOneFeedsFull(filter: $filter) {\n id\n }\n }\n": typeof types.SyncSubscriptionFeedsFullDocument,
|
||||
"\n mutation SyncSubscriptionSources($filter: SubscriptionsFilterInput!) {\n subscriptionsSyncOneSources(filter: $filter) {\n id\n }\n }\n": typeof types.SyncSubscriptionSourcesDocument,
|
||||
"\n query GetTasks($filter: SubscriberTasksFilterInput!, $orderBy: SubscriberTasksOrderInput!, $pagination: PaginationInput!) {\n subscriberTasks(\n pagination: $pagination\n filter: $filter\n orderBy: $orderBy\n ) {\n nodes {\n id,\n job,\n taskType,\n status,\n attempts,\n maxAttempts,\n runAt,\n lastError,\n lockAt,\n lockBy,\n doneAt,\n priority\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": typeof types.GetTasksDocument,
|
||||
"\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filter: { id: {\n eq: $id\n } }) {\n nodes {\n id\n subscriberId\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n feed {\n nodes {\n id\n createdAt\n updatedAt\n token\n feedType\n feedSource\n }\n }\n subscriberTask {\n nodes {\n id\n taskType\n status\n }\n }\n credential3rd {\n id\n username\n }\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n homepage\n }\n }\n }\n }\n}\n": typeof types.GetSubscriptionDetailDocument,
|
||||
"\n query GetTasks($filter: SubscriberTasksFilterInput!, $orderBy: SubscriberTasksOrderInput!, $pagination: PaginationInput!) {\n subscriberTasks(\n pagination: $pagination\n filter: $filter\n orderBy: $orderBy\n ) {\n nodes {\n id,\n job,\n taskType,\n status,\n attempts,\n maxAttempts,\n runAt,\n lastError,\n lockAt,\n lockBy,\n doneAt,\n priority,\n subscription {\n displayName\n sourceUrl\n }\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": typeof types.GetTasksDocument,
|
||||
"\n mutation InsertSubscriberTask($data: SubscriberTasksInsertInput!) {\n subscriberTasksCreateOne(data: $data) {\n id\n }\n }\n": typeof types.InsertSubscriberTaskDocument,
|
||||
"\n mutation DeleteTasks($filter: SubscriberTasksFilterInput!) {\n subscriberTasksDelete(filter: $filter)\n }\n": typeof types.DeleteTasksDocument,
|
||||
"\n mutation RetryTasks($filter: SubscriberTasksFilterInput!) {\n subscriberTasksRetryOne(filter: $filter) {\n id,\n job,\n taskType,\n status,\n attempts,\n maxAttempts,\n runAt,\n lastError,\n lockAt,\n lockBy,\n doneAt,\n priority\n }\n }\n": typeof types.RetryTasksDocument,
|
||||
};
|
||||
@ -47,11 +45,9 @@ const documents: Documents = {
|
||||
"\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 $filter: SubscriptionsFilterInput!,\n ) {\n subscriptionsUpdate (\n data: $data\n filter: $filter\n ) {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n }\n}\n": types.UpdateSubscriptionsDocument,
|
||||
"\n mutation DeleteSubscriptions($filter: SubscriptionsFilterInput) {\n subscriptionsDelete(filter: $filter)\n }\n": types.DeleteSubscriptionsDocument,
|
||||
"\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filter: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n feed {\n nodes {\n id\n createdAt\n updatedAt\n token\n feedType\n feedSource\n }\n }\n subscriberTask {\n nodes {\n id\n taskType\n status\n }\n }\n credential3rd {\n id\n username\n }\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n homepage\n }\n }\n }\n }\n}\n": types.GetSubscriptionDetailDocument,
|
||||
"\n mutation SyncSubscriptionFeedsIncremental($filter: SubscriptionsFilterInput!) {\n subscriptionsSyncOneFeedsIncremental(filter: $filter) {\n id\n }\n }\n": types.SyncSubscriptionFeedsIncrementalDocument,
|
||||
"\n mutation SyncSubscriptionFeedsFull($filter: SubscriptionsFilterInput!) {\n subscriptionsSyncOneFeedsFull(filter: $filter) {\n id\n }\n }\n": types.SyncSubscriptionFeedsFullDocument,
|
||||
"\n mutation SyncSubscriptionSources($filter: SubscriptionsFilterInput!) {\n subscriptionsSyncOneSources(filter: $filter) {\n id\n }\n }\n": types.SyncSubscriptionSourcesDocument,
|
||||
"\n query GetTasks($filter: SubscriberTasksFilterInput!, $orderBy: SubscriberTasksOrderInput!, $pagination: PaginationInput!) {\n subscriberTasks(\n pagination: $pagination\n filter: $filter\n orderBy: $orderBy\n ) {\n nodes {\n id,\n job,\n taskType,\n status,\n attempts,\n maxAttempts,\n runAt,\n lastError,\n lockAt,\n lockBy,\n doneAt,\n priority\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": types.GetTasksDocument,
|
||||
"\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filter: { id: {\n eq: $id\n } }) {\n nodes {\n id\n subscriberId\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n feed {\n nodes {\n id\n createdAt\n updatedAt\n token\n feedType\n feedSource\n }\n }\n subscriberTask {\n nodes {\n id\n taskType\n status\n }\n }\n credential3rd {\n id\n username\n }\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n homepage\n }\n }\n }\n }\n}\n": types.GetSubscriptionDetailDocument,
|
||||
"\n query GetTasks($filter: SubscriberTasksFilterInput!, $orderBy: SubscriberTasksOrderInput!, $pagination: PaginationInput!) {\n subscriberTasks(\n pagination: $pagination\n filter: $filter\n orderBy: $orderBy\n ) {\n nodes {\n id,\n job,\n taskType,\n status,\n attempts,\n maxAttempts,\n runAt,\n lastError,\n lockAt,\n lockBy,\n doneAt,\n priority,\n subscription {\n displayName\n sourceUrl\n }\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": types.GetTasksDocument,
|
||||
"\n mutation InsertSubscriberTask($data: SubscriberTasksInsertInput!) {\n subscriberTasksCreateOne(data: $data) {\n id\n }\n }\n": types.InsertSubscriberTaskDocument,
|
||||
"\n mutation DeleteTasks($filter: SubscriberTasksFilterInput!) {\n subscriberTasksDelete(filter: $filter)\n }\n": types.DeleteTasksDocument,
|
||||
"\n mutation RetryTasks($filter: SubscriberTasksFilterInput!) {\n subscriberTasksRetryOne(filter: $filter) {\n id,\n job,\n taskType,\n status,\n attempts,\n maxAttempts,\n runAt,\n lastError,\n lockAt,\n lockBy,\n doneAt,\n priority\n }\n }\n": types.RetryTasksDocument,
|
||||
};
|
||||
@ -121,23 +117,15 @@ export function gql(source: "\n mutation DeleteSubscriptions($filter: Subscri
|
||||
/**
|
||||
* 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(filter: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n feed {\n nodes {\n id\n createdAt\n updatedAt\n token\n feedType\n feedSource\n }\n }\n subscriberTask {\n nodes {\n id\n taskType\n status\n }\n }\n credential3rd {\n id\n username\n }\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n homepage\n }\n }\n }\n }\n}\n"): (typeof documents)["\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filter: { id: {\n eq: $id\n } }) {\n nodes {\n id\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n feed {\n nodes {\n id\n createdAt\n updatedAt\n token\n feedType\n feedSource\n }\n }\n subscriberTask {\n nodes {\n id\n taskType\n status\n }\n }\n credential3rd {\n id\n username\n }\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n homepage\n }\n }\n }\n }\n}\n"];
|
||||
export function gql(source: "\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filter: { id: {\n eq: $id\n } }) {\n nodes {\n id\n subscriberId\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n feed {\n nodes {\n id\n createdAt\n updatedAt\n token\n feedType\n feedSource\n }\n }\n subscriberTask {\n nodes {\n id\n taskType\n status\n }\n }\n credential3rd {\n id\n username\n }\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\n homepage\n }\n }\n }\n }\n}\n"): (typeof documents)["\nquery GetSubscriptionDetail ($id: Int!) {\n subscriptions(filter: { id: {\n eq: $id\n } }) {\n nodes {\n id\n subscriberId\n displayName\n createdAt\n updatedAt\n category\n sourceUrl\n enabled\n feed {\n nodes {\n id\n createdAt\n updatedAt\n token\n feedType\n feedSource\n }\n }\n subscriberTask {\n nodes {\n id\n taskType\n status\n }\n }\n credential3rd {\n id\n username\n }\n bangumi {\n nodes {\n createdAt\n updatedAt\n id\n mikanBangumiId\n displayName\n season\n seasonRaw\n fansub\n mikanFansubId\n rssLink\n posterLink\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($filter: SubscriptionsFilterInput!) {\n subscriptionsSyncOneFeedsIncremental(filter: $filter) {\n id\n }\n }\n"): (typeof documents)["\n mutation SyncSubscriptionFeedsIncremental($filter: SubscriptionsFilterInput!) {\n subscriptionsSyncOneFeedsIncremental(filter: $filter) {\n id\n }\n }\n"];
|
||||
export function gql(source: "\n query GetTasks($filter: SubscriberTasksFilterInput!, $orderBy: SubscriberTasksOrderInput!, $pagination: PaginationInput!) {\n subscriberTasks(\n pagination: $pagination\n filter: $filter\n orderBy: $orderBy\n ) {\n nodes {\n id,\n job,\n taskType,\n status,\n attempts,\n maxAttempts,\n runAt,\n lastError,\n lockAt,\n lockBy,\n doneAt,\n priority,\n subscription {\n displayName\n sourceUrl\n }\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n"): (typeof documents)["\n query GetTasks($filter: SubscriberTasksFilterInput!, $orderBy: SubscriberTasksOrderInput!, $pagination: PaginationInput!) {\n subscriberTasks(\n pagination: $pagination\n filter: $filter\n orderBy: $orderBy\n ) {\n nodes {\n id,\n job,\n taskType,\n status,\n attempts,\n maxAttempts,\n runAt,\n lastError,\n lockAt,\n lockBy,\n doneAt,\n priority,\n subscription {\n displayName\n sourceUrl\n }\n }\n paginationInfo {\n total\n pages\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 SyncSubscriptionFeedsFull($filter: SubscriptionsFilterInput!) {\n subscriptionsSyncOneFeedsFull(filter: $filter) {\n id\n }\n }\n"): (typeof documents)["\n mutation SyncSubscriptionFeedsFull($filter: SubscriptionsFilterInput!) {\n subscriptionsSyncOneFeedsFull(filter: $filter) {\n id\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($filter: SubscriptionsFilterInput!) {\n subscriptionsSyncOneSources(filter: $filter) {\n id\n }\n }\n"): (typeof documents)["\n mutation SyncSubscriptionSources($filter: SubscriptionsFilterInput!) {\n subscriptionsSyncOneSources(filter: $filter) {\n id\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 GetTasks($filter: SubscriberTasksFilterInput!, $orderBy: SubscriberTasksOrderInput!, $pagination: PaginationInput!) {\n subscriberTasks(\n pagination: $pagination\n filter: $filter\n orderBy: $orderBy\n ) {\n nodes {\n id,\n job,\n taskType,\n status,\n attempts,\n maxAttempts,\n runAt,\n lastError,\n lockAt,\n lockBy,\n doneAt,\n priority\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n"): (typeof documents)["\n query GetTasks($filter: SubscriberTasksFilterInput!, $orderBy: SubscriberTasksOrderInput!, $pagination: PaginationInput!) {\n subscriberTasks(\n pagination: $pagination\n filter: $filter\n orderBy: $orderBy\n ) {\n nodes {\n id,\n job,\n taskType,\n status,\n attempts,\n maxAttempts,\n runAt,\n lastError,\n lockAt,\n lockBy,\n doneAt,\n priority\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n"];
|
||||
export function gql(source: "\n mutation InsertSubscriberTask($data: SubscriberTasksInsertInput!) {\n subscriberTasksCreateOne(data: $data) {\n id\n }\n }\n"): (typeof documents)["\n mutation InsertSubscriberTask($data: SubscriberTasksInsertInput!) {\n subscriberTasksCreateOne(data: $data) {\n id\n }\n }\n"];
|
||||
/**
|
||||
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
@ -1,4 +1,6 @@
|
||||
/* eslint-disable */
|
||||
import { SubscriberTaskInput } from 'recorder/bindings/SubscriberTaskInput';
|
||||
import { SubscriberTaskType } from 'recorder/bindings/SubscriberTaskType';
|
||||
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
|
||||
export type Maybe<T> = T | null;
|
||||
export type InputMaybe<T> = Maybe<T>;
|
||||
@ -17,6 +19,8 @@ export type Scalars = {
|
||||
/** The `JSON` scalar type represents raw JSON values */
|
||||
Json: { input: any; output: any; }
|
||||
JsonbFilterInput: { input: any; output: any; }
|
||||
/** type SubscriberTaskType = { "taskType": "sync_one_subscription_feeds_incremental" } & SyncOneSubscriptionFeedsIncrementalTask | { "taskType": "sync_one_subscription_feeds_full" } & SyncOneSubscriptionFeedsFullTask | { "taskType": "sync_one_subscription_sources" } & SyncOneSubscriptionSourcesTask; */
|
||||
SubscriberTaskType: { input: SubscriberTaskInput; output: SubscriberTaskType; }
|
||||
};
|
||||
|
||||
export type Bangumi = {
|
||||
@ -350,7 +354,7 @@ export type Cron = {
|
||||
status: CronStatusEnum;
|
||||
subscriber?: Maybe<Subscribers>;
|
||||
subscriberId?: Maybe<Scalars['Int']['output']>;
|
||||
subscriberTask?: Maybe<Scalars['Json']['output']>;
|
||||
subscriberTask?: Maybe<Scalars['SubscriberTaskType']['output']>;
|
||||
subscription?: Maybe<Subscriptions>;
|
||||
subscriptionId?: Maybe<Scalars['Int']['output']>;
|
||||
timeoutMs: Scalars['Int']['output'];
|
||||
@ -373,7 +377,7 @@ export type CronBasic = {
|
||||
priority: Scalars['Int']['output'];
|
||||
status: CronStatusEnum;
|
||||
subscriberId?: Maybe<Scalars['Int']['output']>;
|
||||
subscriberTask?: Maybe<Scalars['Json']['output']>;
|
||||
subscriberTask?: Maybe<Scalars['SubscriberTaskType']['output']>;
|
||||
subscriptionId?: Maybe<Scalars['Int']['output']>;
|
||||
timeoutMs: Scalars['Int']['output'];
|
||||
updatedAt: Scalars['String']['output'];
|
||||
@ -419,9 +423,8 @@ export type CronFilterInput = {
|
||||
export type CronInsertInput = {
|
||||
cronExpr: Scalars['String']['input'];
|
||||
enabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
id?: InputMaybe<Scalars['Int']['input']>;
|
||||
maxAttempts?: InputMaybe<Scalars['Int']['input']>;
|
||||
subscriberTask?: InputMaybe<Scalars['Json']['input']>;
|
||||
subscriberTask?: InputMaybe<Scalars['SubscriberTaskType']['input']>;
|
||||
timeoutMs?: InputMaybe<Scalars['Int']['input']>;
|
||||
};
|
||||
|
||||
@ -1166,9 +1169,6 @@ export type Mutation = {
|
||||
subscriptionsCreateBatch: Array<SubscriptionsBasic>;
|
||||
subscriptionsCreateOne: SubscriptionsBasic;
|
||||
subscriptionsDelete: Scalars['Int']['output'];
|
||||
subscriptionsSyncOneFeedsFull: SubscriberTasksBasic;
|
||||
subscriptionsSyncOneFeedsIncremental: SubscriberTasksBasic;
|
||||
subscriptionsSyncOneSources: SubscriberTasksBasic;
|
||||
subscriptionsUpdate: Array<SubscriptionsBasic>;
|
||||
};
|
||||
|
||||
@ -1397,21 +1397,6 @@ export type MutationSubscriptionsDeleteArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationSubscriptionsSyncOneFeedsFullArgs = {
|
||||
filter?: InputMaybe<SubscriptionsFilterInput>;
|
||||
};
|
||||
|
||||
|
||||
export type MutationSubscriptionsSyncOneFeedsIncrementalArgs = {
|
||||
filter?: InputMaybe<SubscriptionsFilterInput>;
|
||||
};
|
||||
|
||||
|
||||
export type MutationSubscriptionsSyncOneSourcesArgs = {
|
||||
filter?: InputMaybe<SubscriptionsFilterInput>;
|
||||
};
|
||||
|
||||
|
||||
export type MutationSubscriptionsUpdateArgs = {
|
||||
data: SubscriptionsUpdateInput;
|
||||
filter?: InputMaybe<SubscriptionsFilterInput>;
|
||||
@ -1607,7 +1592,7 @@ export type SubscriberTasks = {
|
||||
attempts: Scalars['Int']['output'];
|
||||
doneAt?: Maybe<Scalars['String']['output']>;
|
||||
id: Scalars['String']['output'];
|
||||
job: Scalars['Json']['output'];
|
||||
job: Scalars['SubscriberTaskType']['output'];
|
||||
lastError?: Maybe<Scalars['String']['output']>;
|
||||
lockAt?: Maybe<Scalars['String']['output']>;
|
||||
lockBy?: Maybe<Scalars['String']['output']>;
|
||||
@ -1627,7 +1612,7 @@ export type SubscriberTasksBasic = {
|
||||
attempts: Scalars['Int']['output'];
|
||||
doneAt?: Maybe<Scalars['String']['output']>;
|
||||
id: Scalars['String']['output'];
|
||||
job: Scalars['Json']['output'];
|
||||
job: Scalars['SubscriberTaskType']['output'];
|
||||
lastError?: Maybe<Scalars['String']['output']>;
|
||||
lockAt?: Maybe<Scalars['String']['output']>;
|
||||
lockBy?: Maybe<Scalars['String']['output']>;
|
||||
@ -1674,10 +1659,7 @@ export type SubscriberTasksFilterInput = {
|
||||
};
|
||||
|
||||
export type SubscriberTasksInsertInput = {
|
||||
id?: InputMaybe<Scalars['String']['input']>;
|
||||
job: Scalars['Json']['input'];
|
||||
maxAttempts: Scalars['Int']['input'];
|
||||
priority: Scalars['Int']['input'];
|
||||
job: Scalars['SubscriberTaskType']['input'];
|
||||
subscriberId?: InputMaybe<Scalars['Int']['input']>;
|
||||
};
|
||||
|
||||
@ -2184,28 +2166,7 @@ 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, feed: { __typename?: 'FeedsConnection', nodes: Array<{ __typename?: 'Feeds', id: number, createdAt: string, updatedAt: string, token: string, feedType: FeedTypeEnum, feedSource: FeedSourceEnum }> }, subscriberTask: { __typename?: 'SubscriberTasksConnection', nodes: Array<{ __typename?: 'SubscriberTasks', id: string, taskType: SubscriberTaskTypeEnum, status: SubscriberTaskStatusEnum }> }, 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, season: number, seasonRaw?: string | null, fansub?: string | null, mikanFansubId?: string | null, rssLink?: string | null, posterLink?: string | null, homepage?: string | null }> } }> } };
|
||||
|
||||
export type SyncSubscriptionFeedsIncrementalMutationVariables = Exact<{
|
||||
filter: SubscriptionsFilterInput;
|
||||
}>;
|
||||
|
||||
|
||||
export type SyncSubscriptionFeedsIncrementalMutation = { __typename?: 'Mutation', subscriptionsSyncOneFeedsIncremental: { __typename?: 'SubscriberTasksBasic', id: string } };
|
||||
|
||||
export type SyncSubscriptionFeedsFullMutationVariables = Exact<{
|
||||
filter: SubscriptionsFilterInput;
|
||||
}>;
|
||||
|
||||
|
||||
export type SyncSubscriptionFeedsFullMutation = { __typename?: 'Mutation', subscriptionsSyncOneFeedsFull: { __typename?: 'SubscriberTasksBasic', id: string } };
|
||||
|
||||
export type SyncSubscriptionSourcesMutationVariables = Exact<{
|
||||
filter: SubscriptionsFilterInput;
|
||||
}>;
|
||||
|
||||
|
||||
export type SyncSubscriptionSourcesMutation = { __typename?: 'Mutation', subscriptionsSyncOneSources: { __typename?: 'SubscriberTasksBasic', id: string } };
|
||||
export type GetSubscriptionDetailQuery = { __typename?: 'Query', subscriptions: { __typename?: 'SubscriptionsConnection', nodes: Array<{ __typename?: 'Subscriptions', id: number, subscriberId: number, displayName: string, createdAt: string, updatedAt: string, category: SubscriptionCategoryEnum, sourceUrl: string, enabled: boolean, feed: { __typename?: 'FeedsConnection', nodes: Array<{ __typename?: 'Feeds', id: number, createdAt: string, updatedAt: string, token: string, feedType: FeedTypeEnum, feedSource: FeedSourceEnum }> }, subscriberTask: { __typename?: 'SubscriberTasksConnection', nodes: Array<{ __typename?: 'SubscriberTasks', id: string, taskType: SubscriberTaskTypeEnum, status: SubscriberTaskStatusEnum }> }, 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, season: number, seasonRaw?: string | null, fansub?: string | null, mikanFansubId?: string | null, rssLink?: string | null, posterLink?: string | null, homepage?: string | null }> } }> } };
|
||||
|
||||
export type GetTasksQueryVariables = Exact<{
|
||||
filter: SubscriberTasksFilterInput;
|
||||
@ -2214,7 +2175,14 @@ export type GetTasksQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type GetTasksQuery = { __typename?: 'Query', subscriberTasks: { __typename?: 'SubscriberTasksConnection', nodes: Array<{ __typename?: 'SubscriberTasks', id: string, job: any, taskType: SubscriberTaskTypeEnum, status: SubscriberTaskStatusEnum, attempts: number, maxAttempts: number, runAt: string, lastError?: string | null, lockAt?: string | null, lockBy?: string | null, doneAt?: string | null, priority: number }>, paginationInfo?: { __typename?: 'PaginationInfo', total: number, pages: number } | null } };
|
||||
export type GetTasksQuery = { __typename?: 'Query', subscriberTasks: { __typename?: 'SubscriberTasksConnection', nodes: Array<{ __typename?: 'SubscriberTasks', id: string, job: SubscriberTaskType, taskType: SubscriberTaskTypeEnum, status: SubscriberTaskStatusEnum, attempts: number, maxAttempts: number, runAt: string, lastError?: string | null, lockAt?: string | null, lockBy?: string | null, doneAt?: string | null, priority: number, subscription?: { __typename?: 'Subscriptions', displayName: string, sourceUrl: string } | null }>, paginationInfo?: { __typename?: 'PaginationInfo', total: number, pages: number } | null } };
|
||||
|
||||
export type InsertSubscriberTaskMutationVariables = Exact<{
|
||||
data: SubscriberTasksInsertInput;
|
||||
}>;
|
||||
|
||||
|
||||
export type InsertSubscriberTaskMutation = { __typename?: 'Mutation', subscriberTasksCreateOne: { __typename?: 'SubscriberTasksBasic', id: string } };
|
||||
|
||||
export type DeleteTasksMutationVariables = Exact<{
|
||||
filter: SubscriberTasksFilterInput;
|
||||
@ -2228,7 +2196,7 @@ export type RetryTasksMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type RetryTasksMutation = { __typename?: 'Mutation', subscriberTasksRetryOne: { __typename?: 'SubscriberTasksBasic', id: string, job: any, taskType: SubscriberTaskTypeEnum, status: SubscriberTaskStatusEnum, attempts: number, maxAttempts: number, runAt: string, lastError?: string | null, lockAt?: string | null, lockBy?: string | null, doneAt?: string | null, priority: number } };
|
||||
export type RetryTasksMutation = { __typename?: 'Mutation', subscriberTasksRetryOne: { __typename?: 'SubscriberTasksBasic', id: string, job: SubscriberTaskType, taskType: SubscriberTaskTypeEnum, status: SubscriberTaskStatusEnum, attempts: number, maxAttempts: number, runAt: string, lastError?: string | null, lockAt?: string | null, lockBy?: string | null, doneAt?: string | null, priority: number } };
|
||||
|
||||
|
||||
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":"filter"}},"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":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}},{"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>;
|
||||
@ -2243,10 +2211,8 @@ export const GetSubscriptionsDocument = {"kind":"Document","definitions":[{"kind
|
||||
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":"filter"}},"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":"filter"}}}],"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":"filter"}},"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":"filter"}}}]}]}}]} 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":"filter"},"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":"feed"},"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":"token"}},{"kind":"Field","name":{"kind":"Name","value":"feedType"}},{"kind":"Field","name":{"kind":"Name","value":"feedSource"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"subscriberTask"},"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":"taskType"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}},{"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":"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":"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":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptionsSyncOneFeedsIncremental"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} 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":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptionsSyncOneFeedsFull"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} 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":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptionsSyncOneSources"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode<SyncSubscriptionSourcesMutation, SyncSubscriptionSourcesMutationVariables>;
|
||||
export const GetTasksDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetTasks"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriberTasksFilterInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriberTasksOrderInput"}}}},{"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":"subscriberTasks"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"pagination"},"value":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}},{"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":"job"}},{"kind":"Field","name":{"kind":"Name","value":"taskType"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"attempts"}},{"kind":"Field","name":{"kind":"Name","value":"maxAttempts"}},{"kind":"Field","name":{"kind":"Name","value":"runAt"}},{"kind":"Field","name":{"kind":"Name","value":"lastError"}},{"kind":"Field","name":{"kind":"Name","value":"lockAt"}},{"kind":"Field","name":{"kind":"Name","value":"lockBy"}},{"kind":"Field","name":{"kind":"Name","value":"doneAt"}},{"kind":"Field","name":{"kind":"Name","value":"priority"}}]}},{"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<GetTasksQuery, GetTasksQueryVariables>;
|
||||
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":"filter"},"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":"subscriberId"}},{"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":"feed"},"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":"token"}},{"kind":"Field","name":{"kind":"Name","value":"feedType"}},{"kind":"Field","name":{"kind":"Name","value":"feedSource"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"subscriberTask"},"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":"taskType"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}},{"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":"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":"homepage"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode<GetSubscriptionDetailQuery, GetSubscriptionDetailQueryVariables>;
|
||||
export const GetTasksDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetTasks"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriberTasksFilterInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriberTasksOrderInput"}}}},{"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":"subscriberTasks"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"pagination"},"value":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}},{"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":"job"}},{"kind":"Field","name":{"kind":"Name","value":"taskType"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"attempts"}},{"kind":"Field","name":{"kind":"Name","value":"maxAttempts"}},{"kind":"Field","name":{"kind":"Name","value":"runAt"}},{"kind":"Field","name":{"kind":"Name","value":"lastError"}},{"kind":"Field","name":{"kind":"Name","value":"lockAt"}},{"kind":"Field","name":{"kind":"Name","value":"lockBy"}},{"kind":"Field","name":{"kind":"Name","value":"doneAt"}},{"kind":"Field","name":{"kind":"Name","value":"priority"}},{"kind":"Field","name":{"kind":"Name","value":"subscription"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrl"}}]}}]}},{"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<GetTasksQuery, GetTasksQueryVariables>;
|
||||
export const InsertSubscriberTaskDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"InsertSubscriberTask"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriberTasksInsertInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriberTasksCreateOne"},"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"}}]}}]}}]} as unknown as DocumentNode<InsertSubscriberTaskMutation, InsertSubscriberTaskMutationVariables>;
|
||||
export const DeleteTasksDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteTasks"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriberTasksFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriberTasksDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}]}]}}]} as unknown as DocumentNode<DeleteTasksMutation, DeleteTasksMutationVariables>;
|
||||
export const RetryTasksDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RetryTasks"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriberTasksFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriberTasksRetryOne"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"job"}},{"kind":"Field","name":{"kind":"Name","value":"taskType"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"attempts"}},{"kind":"Field","name":{"kind":"Name","value":"maxAttempts"}},{"kind":"Field","name":{"kind":"Name","value":"runAt"}},{"kind":"Field","name":{"kind":"Name","value":"lastError"}},{"kind":"Field","name":{"kind":"Name","value":"lockAt"}},{"kind":"Field","name":{"kind":"Name","value":"lockBy"}},{"kind":"Field","name":{"kind":"Name","value":"doneAt"}},{"kind":"Field","name":{"kind":"Name","value":"priority"}}]}}]}}]} as unknown as DocumentNode<RetryTasksMutation, RetryTasksMutationVariables>;
|
@ -6,18 +6,11 @@ import {
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { INSERT_SUBSCRIBER_TASK } from '@/domains/recorder/schema/tasks';
|
||||
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,
|
||||
type InsertSubscriberTaskMutation,
|
||||
type InsertSubscriberTaskMutationVariables,
|
||||
SubscriberTaskTypeEnum,
|
||||
} from '@/infra/graphql/gql/graphql';
|
||||
import { useMutation } from '@apollo/client';
|
||||
import { useNavigate } from '@tanstack/react-router';
|
||||
@ -36,14 +29,13 @@ export interface SubscriptionSyncViewProps {
|
||||
|
||||
export const SubscriptionSyncView = memo(
|
||||
({ id, onComplete }: SubscriptionSyncViewProps) => {
|
||||
const [syncSubscriptionFeedsIncremental, { loading: loadingIncremental }] =
|
||||
useMutation<
|
||||
SyncSubscriptionFeedsIncrementalMutation,
|
||||
SyncSubscriptionFeedsIncrementalMutationVariables
|
||||
>(SYNC_SUBSCRIPTION_FEEDS_INCREMENTAL, {
|
||||
const [insertSubscriberTask, { loading: loadingInsert }] = useMutation<
|
||||
InsertSubscriberTaskMutation,
|
||||
InsertSubscriberTaskMutationVariables
|
||||
>(INSERT_SUBSCRIBER_TASK, {
|
||||
onCompleted: (data) => {
|
||||
toast.success('Sync completed');
|
||||
onComplete(data.subscriptionsSyncOneFeedsIncremental);
|
||||
onComplete(data.subscriberTasksCreateOne);
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error('Failed to sync subscription', {
|
||||
@ -52,37 +44,7 @@ export const SubscriptionSyncView = memo(
|
||||
},
|
||||
});
|
||||
|
||||
const [syncSubscriptionFeedsFull, { loading: loadingFull }] = useMutation<
|
||||
SyncSubscriptionFeedsFullMutation,
|
||||
SyncSubscriptionFeedsFullMutationVariables
|
||||
>(SYNC_SUBSCRIPTION_FEEDS_FULL, {
|
||||
onCompleted: (data) => {
|
||||
toast.success('Sync completed');
|
||||
onComplete(data.subscriptionsSyncOneFeedsFull);
|
||||
},
|
||||
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.subscriptionsSyncOneSources);
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error('Failed to sync subscription', {
|
||||
description: error.message,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const loading = loadingIncremental || loadingFull || loadingSources;
|
||||
const loading = loadingInsert;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
@ -90,8 +52,15 @@ export const SubscriptionSyncView = memo(
|
||||
size="lg"
|
||||
variant="outline"
|
||||
onClick={() =>
|
||||
syncSubscriptionSources({
|
||||
variables: { filter: { id: { eq: id } } },
|
||||
insertSubscriberTask({
|
||||
variables: {
|
||||
data: {
|
||||
job: {
|
||||
subscriptionId: id,
|
||||
taskType: SubscriberTaskTypeEnum.SyncOneSubscriptionSources,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
>
|
||||
@ -102,8 +71,16 @@ export const SubscriptionSyncView = memo(
|
||||
size="lg"
|
||||
variant="outline"
|
||||
onClick={() =>
|
||||
syncSubscriptionFeedsIncremental({
|
||||
variables: { filter: { id: { eq: id } } },
|
||||
insertSubscriberTask({
|
||||
variables: {
|
||||
data: {
|
||||
job: {
|
||||
subscriptionId: id,
|
||||
taskType:
|
||||
SubscriberTaskTypeEnum.SyncOneSubscriptionFeedsIncremental,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
>
|
||||
@ -114,8 +91,16 @@ export const SubscriptionSyncView = memo(
|
||||
size="lg"
|
||||
variant="outline"
|
||||
onClick={() =>
|
||||
syncSubscriptionFeedsFull({
|
||||
variables: { filter: { id: { eq: id } } },
|
||||
insertSubscriberTask({
|
||||
variables: {
|
||||
data: {
|
||||
job: {
|
||||
subscriptionId: id,
|
||||
taskType:
|
||||
SubscriberTaskTypeEnum.SyncOneSubscriptionFeedsFull,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
>
|
||||
|
@ -32,6 +32,7 @@ import {
|
||||
} from '@tanstack/react-router';
|
||||
import { format } from 'date-fns';
|
||||
import { ArrowLeft, RefreshCw } from 'lucide-react';
|
||||
import { useMemo } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
import { prettyTaskType } from './-pretty-task-type';
|
||||
import { getStatusBadge } from './-status-badge';
|
||||
@ -104,6 +105,16 @@ function TaskDetailRouteComponent() {
|
||||
},
|
||||
});
|
||||
|
||||
const job = useMemo(() => {
|
||||
if (!task) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
...task.job,
|
||||
subscription: task.subscription,
|
||||
};
|
||||
}, [task]);
|
||||
|
||||
if (loading) {
|
||||
return <DetailCardSkeleton />;
|
||||
}
|
||||
@ -247,14 +258,14 @@ function TaskDetailRouteComponent() {
|
||||
</div>
|
||||
|
||||
{/* Job Details */}
|
||||
{task.job && (
|
||||
{job && (
|
||||
<>
|
||||
<Separator />
|
||||
<div className="space-y-2">
|
||||
<Label className="font-medium text-sm">Job Details</Label>
|
||||
<div className="rounded-md bg-muted p-3">
|
||||
<pre className="overflow-x-auto whitespace-pre-wrap text-sm">
|
||||
<code>{JSON.stringify(task.job, null, 2)}</code>
|
||||
<code>{JSON.stringify(job, null, 2)}</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -11,5 +11,10 @@
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src"]
|
||||
"include": ["src"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../apps/recorder"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
6
justfile
6
justfile
@ -11,8 +11,8 @@ prepare-dev-testcontainers:
|
||||
docker pull ghcr.io/dumtruck/konobangu-testing-torrents:latest
|
||||
docker pull postgres:17-alpine
|
||||
|
||||
dev-optimize-images:
|
||||
npx -y zx apps/recorder/examples/optimize_image.mjs
|
||||
export-recorder-ts-bindings:
|
||||
cargo test export_bindings -p recorder
|
||||
|
||||
dev-webui:
|
||||
pnpm run --filter=webui dev
|
||||
@ -27,7 +27,7 @@ dev-proxy:
|
||||
pnpm run --parallel --filter=proxy dev
|
||||
|
||||
dev-recorder:
|
||||
watchexec -r -e rs,toml,yaml,json,env -- cargo run -p recorder --bin recorder_cli -- --environment=development --graceful-shutdown=false
|
||||
watchexec -r -e rs,toml,yaml,json -- cargo run -p recorder --bin recorder_cli -- --environment=development --graceful-shutdown=false
|
||||
|
||||
prod-recorder: prod-webui
|
||||
cargo run --release -p recorder --bin recorder_cli -- --environment=production --working-dir=apps/recorder --graceful-shutdown=false
|
||||
|
@ -3,8 +3,9 @@ extern crate proc_macro;
|
||||
use convert_case::{Case, Casing};
|
||||
use darling::{FromDeriveInput, FromField, ast::Data, util::Ignored};
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::Ident;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{Attribute, DeriveInput, Generics, Ident, parse_macro_input};
|
||||
use syn::{Attribute, DeriveInput, Generics, parse_macro_input};
|
||||
|
||||
#[derive(snafu::Snafu, Debug)]
|
||||
enum GeneratorError {
|
||||
|
5
pnpm-lock.yaml
generated
5
pnpm-lock.yaml
generated
@ -67,6 +67,8 @@ importers:
|
||||
specifier: ^2.9.99
|
||||
version: 2.9.99
|
||||
|
||||
apps/recorder: {}
|
||||
|
||||
apps/webui:
|
||||
dependencies:
|
||||
'@abraham/reflection':
|
||||
@ -249,6 +251,9 @@ importers:
|
||||
recharts:
|
||||
specifier: ^2.15.3
|
||||
version: 2.15.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
recorder:
|
||||
specifier: workspace:*
|
||||
version: link:../recorder
|
||||
rxjs:
|
||||
specifier: ^7.8.2
|
||||
version: 7.8.2
|
||||
|
@ -4,9 +4,13 @@
|
||||
{
|
||||
"path": "./apps/email-playground"
|
||||
},
|
||||
{
|
||||
"path": "./apps/recorder"
|
||||
},
|
||||
{
|
||||
"path": "./apps/webui"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "./packages/email"
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user