From 3aad31a36b891cbfa244f01be20b32bde211ce5f Mon Sep 17 00:00:00 2001 From: lonelyhentxi Date: Sat, 5 Jul 2025 04:08:56 +0800 Subject: [PATCH] feat: more cron webui --- Cargo.lock | 1 + apps/recorder/Cargo.toml | 1 + apps/recorder/src/errors/app_error.rs | 2 + apps/recorder/src/graphql/domains/cron.rs | 4 +- apps/recorder/src/migrations/defs.rs | 1 + .../migrations/m20250629_065628_add_cron.rs | 1 + apps/recorder/src/models/cron/mod.rs | 62 +- apps/webui/package.json | 5 +- apps/webui/src/app.css | 4 +- .../src/components/domains/cron/README.md | 291 ++ .../components/domains/cron/cron-builder.tsx | 643 +++++ .../components/domains/cron/cron-display.tsx | 277 ++ .../components/domains/cron/cron-example.tsx | 413 +++ .../components/domains/cron/cron-input.tsx | 186 ++ .../src/components/domains/cron/cron.tsx | 500 ++++ .../src/components/domains/cron/index.ts | 20 + .../src/components/domains/cron/types.ts | 162 ++ .../{ => ui}/detail-card-skeleton.tsx | 4 +- .../webui/src/domains/recorder/schema/cron.ts | 62 + apps/webui/src/infra/graphql/gql/gql.ts | 6 + apps/webui/src/infra/graphql/gql/graphql.ts | 2528 ++--------------- .../routes/_app/credential3rd/detail.$id.tsx | 2 +- .../routes/_app/credential3rd/edit.$id.tsx | 2 +- .../_app/subscriptions/-cron-creation.tsx | 152 + .../{-sync.tsx => -task-creation.tsx} | 45 +- .../routes/_app/subscriptions/detail.$id.tsx | 24 +- .../routes/_app/subscriptions/edit.$id.tsx | 2 +- .../routes/_app/subscriptions/manage.tsx | 6 +- .../routes/_app/tasks/detail.$id.tsx | 2 +- biome.json | 8 + pnpm-lock.yaml | 62 +- tsconfig.base.json | 5 +- tsconfig.json | 1 - 33 files changed, 3096 insertions(+), 2388 deletions(-) create mode 100644 apps/webui/src/components/domains/cron/README.md create mode 100644 apps/webui/src/components/domains/cron/cron-builder.tsx create mode 100644 apps/webui/src/components/domains/cron/cron-display.tsx create mode 100644 apps/webui/src/components/domains/cron/cron-example.tsx create mode 100644 apps/webui/src/components/domains/cron/cron-input.tsx create mode 100644 apps/webui/src/components/domains/cron/cron.tsx create mode 100644 apps/webui/src/components/domains/cron/index.ts create mode 100644 apps/webui/src/components/domains/cron/types.ts rename apps/webui/src/components/{ => ui}/detail-card-skeleton.tsx (90%) create mode 100644 apps/webui/src/presentation/routes/_app/subscriptions/-cron-creation.tsx rename apps/webui/src/presentation/routes/_app/subscriptions/{-sync.tsx => -task-creation.tsx} (75%) diff --git a/Cargo.lock b/Cargo.lock index 35f9f99..aaa6632 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6757,6 +6757,7 @@ dependencies = [ "base64 0.22.1", "bytes", "chrono", + "chrono-tz 0.10.3", "clap", "cocoon", "color-eyre", diff --git a/apps/recorder/Cargo.toml b/apps/recorder/Cargo.toml index e189c81..bef7b93 100644 --- a/apps/recorder/Cargo.toml +++ b/apps/recorder/Cargo.toml @@ -169,6 +169,7 @@ croner = "2.2.0" ts-rs = "11.0.1" secrecy = { version = "0.10.3", features = ["serde"] } paste = "1.0.15" +chrono-tz = "0.10.3" [dev-dependencies] inquire = { workspace = true } diff --git a/apps/recorder/src/errors/app_error.rs b/apps/recorder/src/errors/app_error.rs index 3b3616c..3c4d4ec 100644 --- a/apps/recorder/src/errors/app_error.rs +++ b/apps/recorder/src/errors/app_error.rs @@ -18,6 +18,8 @@ use crate::{ #[derive(Snafu, Debug)] #[snafu(visibility(pub(crate)))] pub enum RecorderError { + #[snafu(transparent)] + ChronoTzParseError { source: chrono_tz::ParseError }, #[snafu(transparent)] SeaographyError { source: seaography::SeaographyError }, #[snafu(transparent)] diff --git a/apps/recorder/src/graphql/domains/cron.rs b/apps/recorder/src/graphql/domains/cron.rs index e77bd69..a1445e5 100644 --- a/apps/recorder/src/graphql/domains/cron.rs +++ b/apps/recorder/src/graphql/domains/cron.rs @@ -20,6 +20,7 @@ fn skip_columns_for_entity_input(context: &mut BuilderContext) { cron::Column::SubscriberTaskCron | cron::Column::SystemTaskCron | cron::Column::CronExpr + | cron::Column::CronTimezone | cron::Column::Enabled | cron::Column::TimeoutMs | cron::Column::MaxAttempts @@ -30,7 +31,8 @@ fn skip_columns_for_entity_input(context: &mut BuilderContext) { context.entity_input.insert_skips.push(entity_column_key); } for column in cron::Column::iter() { - if matches!(column, |cron::Column::CronExpr| cron::Column::Enabled + if matches!(column, |cron::Column::CronExpr| cron::Column::CronTimezone + | cron::Column::Enabled | cron::Column::TimeoutMs | cron::Column::Priority | cron::Column::MaxAttempts) diff --git a/apps/recorder/src/migrations/defs.rs b/apps/recorder/src/migrations/defs.rs index 39f9c93..be6da4f 100644 --- a/apps/recorder/src/migrations/defs.rs +++ b/apps/recorder/src/migrations/defs.rs @@ -178,6 +178,7 @@ pub enum Cron { SubscriberId, SubscriptionId, CronExpr, + CronTimezone, NextRun, LastRun, LastError, diff --git a/apps/recorder/src/migrations/m20250629_065628_add_cron.rs b/apps/recorder/src/migrations/m20250629_065628_add_cron.rs index 98eae15..a34a2a0 100644 --- a/apps/recorder/src/migrations/m20250629_065628_add_cron.rs +++ b/apps/recorder/src/migrations/m20250629_065628_add_cron.rs @@ -40,6 +40,7 @@ impl MigrationTrait for Migration { table_auto_z(Cron::Table) .col(pk_auto(Cron::Id)) .col(string(Cron::CronExpr)) + .col(string(Cron::CronTimezone)) .col(integer_null(Cron::SubscriberId)) .col(integer_null(Cron::SubscriptionId)) .col(timestamp_with_time_zone_null(Cron::NextRun)) diff --git a/apps/recorder/src/models/cron/mod.rs b/apps/recorder/src/models/cron/mod.rs index 51921ad..32eec72 100644 --- a/apps/recorder/src/models/cron/mod.rs +++ b/apps/recorder/src/models/cron/mod.rs @@ -8,6 +8,7 @@ pub use core::{ use async_trait::async_trait; use chrono::{DateTime, Utc}; +use chrono_tz::Tz; use croner::Cron; use sea_orm::{ ActiveValue::{self, Set}, @@ -54,6 +55,7 @@ pub struct Model { pub subscriber_id: Option, pub subscription_id: Option, pub cron_expr: String, + pub cron_timezone: String, pub next_run: Option, pub last_run: Option, pub last_error: Option, @@ -140,16 +142,37 @@ impl ActiveModelBehavior for ActiveModel { where C: ConnectionTrait, { - if let ActiveValue::Set(ref cron_expr) = self.cron_expr - && matches!( - self.next_run, - ActiveValue::NotSet | ActiveValue::Unchanged(_) - ) - { - let next_run = - Model::calculate_next_run(cron_expr).map_err(|e| DbErr::Custom(e.to_string()))?; - self.next_run = Set(Some(next_run)); - } + match ( + &self.cron_expr as &ActiveValue, + &self.cron_timezone as &ActiveValue, + ) { + (ActiveValue::Set(cron_expr), ActiveValue::Set(timezone)) => { + if matches!( + &self.next_run, + ActiveValue::NotSet | ActiveValue::Unchanged(_) + ) { + let next_run = Model::calculate_next_run(cron_expr, timezone) + .map_err(|e| DbErr::Custom(e.to_string()))?; + self.next_run = Set(Some(next_run)); + } + } + ( + ActiveValue::Unchanged(_) | ActiveValue::NotSet, + ActiveValue::Unchanged(_) | ActiveValue::NotSet, + ) => {} + (_, _) => { + if matches!( + self.next_run, + ActiveValue::NotSet | ActiveValue::Unchanged(_) + ) { + return Err(DbErr::Custom( + "Cron expr and timezone must be insert or update at same time when next \ + run is not set" + .to_string(), + )); + } + } + }; if let ActiveValue::Set(Some(subscriber_id)) = self.subscriber_id && let ActiveValue::Set(Some(ref subscriber_task)) = self.subscriber_task_cron && subscriber_task.get_subscriber_id() != subscriber_id @@ -272,7 +295,7 @@ impl Model { async fn mark_cron_completed(&self, ctx: &dyn AppContextTrait) -> RecorderResult<()> { let db = ctx.db(); - let next_run = Self::calculate_next_run(&self.cron_expr)?; + let next_run = Self::calculate_next_run(&self.cron_expr, &self.cron_timezone)?; ActiveModel { id: Set(self.id), @@ -310,7 +333,10 @@ impl Model { let next_run = if should_retry { Some(Utc::now() + retry_duration) } else { - Some(Self::calculate_next_run(&self.cron_expr)?) + Some(Self::calculate_next_run( + &self.cron_expr, + &self.cron_timezone, + )?) }; ActiveModel { @@ -399,11 +425,17 @@ impl Model { Ok(()) } - pub fn calculate_next_run(cron_expr: &str) -> RecorderResult> { + pub fn calculate_next_run(cron_expr: &str, timezone: &str) -> RecorderResult> { + let user_tz = timezone.parse::()?; + + let user_tz_now = Utc::now().with_timezone(&user_tz); + let cron_expr = Cron::new(cron_expr).with_seconds_optional().parse()?; - let next = cron_expr.find_next_occurrence(&Utc::now(), false)?; + let next = cron_expr.find_next_occurrence(&user_tz_now, false)?; - Ok(next) + let next_utc = next.with_timezone(&Utc); + + Ok(next_utc) } } diff --git a/apps/webui/package.json b/apps/webui/package.json index 9249fcd..98bc4fa 100644 --- a/apps/webui/package.json +++ b/apps/webui/package.json @@ -11,13 +11,14 @@ "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", "@corvu/drawer": "^0.2.4", "@corvu/otp-field": "^0.1.4", "@corvu/resizable": "^0.2.5", + "@datasert/cronjs-matcher": "^1.4.0", + "@datasert/cronjs-parser": "^1.4.0", "@graphiql/toolkit": "^0.11.3", "@hookform/resolvers": "^5.1.1", "@outposts/injection-js": "^2.5.1", @@ -72,9 +73,11 @@ "react-dom": "^19.1.0", "react-resizable-panels": "^3.0.2", "recharts": "^2.15.3", + "recorder": "workspace:*", "rxjs": "^7.8.2", "sonner": "^2.0.5", "tailwind-merge": "^3.3.1", + "tailwind-scrollbar": "^4.0.2", "tailwindcss": "^4.1.10", "tw-animate-css": "^1.3.4", "type-fest": "^4.41.0", diff --git a/apps/webui/src/app.css b/apps/webui/src/app.css index b34cddb..ab49972 100644 --- a/apps/webui/src/app.css +++ b/apps/webui/src/app.css @@ -144,4 +144,6 @@ [role="button"]:not(:disabled) { cursor: pointer; } -} \ No newline at end of file +} + +@plugin "tailwind-scrollbar"; diff --git a/apps/webui/src/components/domains/cron/README.md b/apps/webui/src/components/domains/cron/README.md new file mode 100644 index 0000000..c5b5f0c --- /dev/null +++ b/apps/webui/src/components/domains/cron/README.md @@ -0,0 +1,291 @@ +# Cron Components + +A comprehensive set of React components for creating, editing, and displaying cron expressions with TypeScript support and shadcn/ui integration. + +## Features + +- 🎯 **Multiple Input Modes**: Text input, visual builder, or both +- 🔍 **Real-time Validation**: Powered by `@datasert/cronjs-parser` +- ⏰ **Next Run Preview**: Shows upcoming execution times with `@datasert/cronjs-matcher` +- 🌍 **Timezone Support**: Display times in different timezones +- 📱 **Responsive Design**: Works seamlessly on desktop and mobile +- 🎨 **shadcn/ui Integration**: Consistent with your existing design system +- 🔧 **TypeScript Support**: Full type definitions included +- 🚀 **Customizable**: Extensive props for customization + +## Components + +### `` - Main Component + +The primary component that combines all functionality. + +```tsx +import { Cron } from '@/components/cron'; + +function MyScheduler() { + const [cronExpression, setCronExpression] = useState('0 0 9 * * 1-5'); + + return ( + + ); +} +``` + +#### Props + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `value` | `string` | `''` | Current cron expression | +| `onChange` | `(value: string) => void` | - | Called when expression changes | +| `onValidate` | `(isValid: boolean) => void` | - | Called when validation state changes | +| `mode` | `'input' \| 'builder' \| 'both'` | `'both'` | Display mode | +| `disabled` | `boolean` | `false` | Disable all inputs | +| `placeholder` | `string` | `'0 0 * * * *'` | Input placeholder text | +| `showPreview` | `boolean` | `true` | Show next run times preview | +| `showDescription` | `boolean` | `true` | Show human-readable description | +| `timezone` | `string` | `'UTC'` | Timezone for preview times | +| `error` | `string` | - | External error message | +| `className` | `ClassValue` | - | Additional CSS classes | + +### `` - Text Input Component + +Simple text input with validation and help text. + +```tsx +import { CronInput } from '@/components/cron'; + +function QuickEntry() { + const [expression, setExpression] = useState(''); + const [isValid, setIsValid] = useState(false); + + return ( + + ); +} +``` + +#### Props + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `value` | `string` | - | Current expression value | +| `onChange` | `(value: string) => void` | - | Called when input changes | +| `onValidate` | `(isValid: boolean) => void` | - | Called when validation changes | +| `placeholder` | `string` | `'0 0 * * * *'` | Placeholder text | +| `disabled` | `boolean` | `false` | Disable input | +| `readOnly` | `boolean` | `false` | Make input read-only | +| `error` | `string` | - | Error message to display | +| `className` | `ClassValue` | - | Additional CSS classes | + +### `` - Visual Builder Component + +Visual interface for building cron expressions with presets and field editors. + +```tsx +import { CronBuilder } from '@/components/cron'; + +function VisualScheduler() { + const [expression, setExpression] = useState('0 0 * * * *'); + + return ( + + ); +} +``` + +#### Props + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `value` | `string` | `'0 0 * * * *'` | Current expression | +| `onChange` | `(value: string) => void` | - | Called when expression changes | +| `disabled` | `boolean` | `false` | Disable all controls | +| `showPreview` | `boolean` | `true` | Show preview section | +| `defaultTab` | `CronPeriod` | `'hourly'` | Default active tab | +| `allowedPeriods` | `CronPeriod[]` | All periods | Which tabs to show | +| `presets` | `CronPreset[]` | Built-in presets | Custom preset list | +| `className` | `ClassValue` | - | Additional CSS classes | + +### `` - Display Component + +Read-only component for displaying cron expression information. + +```tsx +import { CronDisplay } from '@/components/cron'; + +function ScheduleInfo({ schedule }) { + return ( + + ); +} +``` + +#### Props + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `expression` | `string` | - | Cron expression to display | +| `showNextRuns` | `boolean` | `true` | Show upcoming run times | +| `showDescription` | `boolean` | `true` | Show human-readable description | +| `nextRunsCount` | `number` | `5` | Number of future runs to show | +| `timezone` | `string` | `'UTC'` | Timezone for times | +| `className` | `ClassValue` | - | Additional CSS classes | + +## Cron Expression Format + +The components support 6-field cron expressions with seconds: + +``` +┌─────────────── second (0-59) +│ ┌───────────── minute (0-59) +│ │ ┌─────────── hour (0-23) +│ │ │ ┌───────── day of month (1-31) +│ │ │ │ ┌─────── month (1-12) +│ │ │ │ │ ┌───── day of week (0-6, Sunday=0) +│ │ │ │ │ │ +* * * * * * +``` + +### Special Characters + +| Character | Description | Example | +|-----------|-------------|---------| +| `*` | Any value | `*` = every value | +| `,` | List separator | `1,3,5` = values 1, 3, and 5 | +| `-` | Range | `1-5` = values 1 through 5 | +| `/` | Step values | `*/5` = every 5th value | +| `?` | No specific value | Used when day/weekday conflict | +| `L` | Last | Last day of month/week | +| `W` | Weekday | Nearest weekday | + +### Common Examples + +| Expression | Description | +|------------|-------------| +| `0 * * * * *` | Every minute | +| `0 */5 * * * *` | Every 5 minutes | +| `0 0 * * * *` | Every hour | +| `0 0 9 * * *` | Daily at 9 AM | +| `0 30 9 * * 1-5` | Weekdays at 9:30 AM | +| `0 0 0 * * 0` | Every Sunday at midnight | +| `0 0 0 1 * *` | First day of every month | +| `0 0 0 1 1 *` | Every January 1st | + +## Dependencies + +- `@datasert/cronjs-parser` - For parsing and validating cron expressions +- `@datasert/cronjs-matcher` - For calculating next run times +- `@radix-ui/react-*` - UI primitives (via shadcn/ui) +- `lucide-react` - Icons + +## Installation + +1. Copy the component files to your project +2. Ensure you have the required dependencies: + +```bash +npm install @datasert/cronjs-parser @datasert/cronjs-matcher +``` + +3. Import and use the components: + +```tsx +import { Cron } from '@/components/cron'; +``` + +## Customization + +### Custom Presets + +```tsx +const customPresets = [ + { + label: 'Business Hours', + value: '0 0 9-17 * * 1-5', + description: 'Every hour during business hours', + category: 'custom' + }, + // ... more presets +]; + + +``` + +### Restricted Periods + +```tsx + +``` + +### Custom Validation + +```tsx +function MyComponent() { + const [expression, setExpression] = useState(''); + const [isValid, setIsValid] = useState(false); + + const handleValidation = (valid: boolean) => { + setIsValid(valid); + // Custom validation logic + }; + + return ( + + ); +} +``` + +## TypeScript Support + +All components include comprehensive TypeScript definitions: + +```tsx +import type { + CronProps, + CronExpression, + CronValidationResult, + CronPeriod +} from '@/components/cron'; +``` + +## Examples + +See `CronExample` component for comprehensive usage examples and interactive demos. + +## Browser Support + +- Modern browsers with ES2015+ support +- React 16.8+ (hooks support required) +- TypeScript 4.0+ recommended diff --git a/apps/webui/src/components/domains/cron/cron-builder.tsx b/apps/webui/src/components/domains/cron/cron-builder.tsx new file mode 100644 index 0000000..89dbb95 --- /dev/null +++ b/apps/webui/src/components/domains/cron/cron-builder.tsx @@ -0,0 +1,643 @@ +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@/components/ui/card'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { Separator } from '@/components/ui/separator'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'; +import { cn } from '@/presentation/utils'; +import { getFutureMatches } from '@datasert/cronjs-matcher'; +import { Calendar, Clock, Info, Settings, Zap } from 'lucide-react'; +import { + type CSSProperties, + type FC, + useCallback, + useEffect, + useMemo, + useState, +} from 'react'; +import { + type CronBuilderProps, + CronField, + type CronFieldConfig, + CronPeriod, + type CronPreset, +} from './types'; + +const CRON_PRESETS: CronPreset[] = [ + { + label: 'Every minute', + value: '0 * * * * *', + description: 'Runs every minute', + category: 'common', + }, + { + label: 'Every 5 minutes', + value: '0 */5 * * * *', + description: 'Runs every 5 minutes', + category: 'common', + }, + { + label: 'Every 15 minutes', + value: '0 */15 * * * *', + description: 'Runs every 15 minutes', + category: 'common', + }, + { + label: 'Every 30 minutes', + value: '0 */30 * * * *', + description: 'Runs every 30 minutes', + category: 'common', + }, + { + label: 'Every hour', + value: '0 0 * * * *', + description: 'Runs at the top of every hour', + category: 'common', + }, + { + label: 'Every 6 hours', + value: '0 0 */6 * * *', + description: 'Runs every 6 hours', + category: 'common', + }, + { + label: 'Daily at midnight', + value: '0 0 0 * * *', + description: 'Runs once daily at 00:00', + category: 'daily', + }, + { + label: 'Daily at 9 AM', + value: '0 0 9 * * *', + description: 'Runs daily at 9:00 AM', + category: 'daily', + }, + { + label: 'Weekdays at 9 AM', + value: '0 0 9 * * 1-5', + description: 'Runs Monday to Friday at 9:00 AM', + category: 'weekly', + }, + { + label: 'Every Sunday', + value: '0 0 0 * * 0', + description: 'Runs every Sunday at midnight', + category: 'weekly', + }, + { + label: 'First day of month', + value: '0 0 0 1 * *', + description: 'Runs on the 1st day of every month', + category: 'monthly', + }, + { + label: 'Every year', + value: '0 0 0 1 1 *', + description: 'Runs on January 1st every year', + category: 'yearly', + }, +]; + +const FIELD_CONFIGS: Record = { + seconds: { + min: 0, + max: 59, + step: 1, + allowSpecial: ['*', '?'], + }, + minutes: { + min: 0, + max: 59, + step: 1, + allowSpecial: ['*', '?'], + }, + hours: { + min: 0, + max: 23, + step: 1, + allowSpecial: ['*', '?'], + }, + dayOfMonth: { + min: 1, + max: 31, + step: 1, + allowSpecial: ['*', '?', 'L', 'W'], + options: [ + { label: 'Any day', value: '*' }, + { label: 'No specific day', value: '?' }, + { label: 'Last day', value: 'L' }, + { label: 'Weekday', value: 'W' }, + ], + }, + month: { + min: 1, + max: 12, + step: 1, + allowSpecial: ['*'], + options: [ + { label: 'January', value: 1 }, + { label: 'February', value: 2 }, + { label: 'March', value: 3 }, + { label: 'April', value: 4 }, + { label: 'May', value: 5 }, + { label: 'June', value: 6 }, + { label: 'July', value: 7 }, + { label: 'August', value: 8 }, + { label: 'September', value: 9 }, + { label: 'October', value: 10 }, + { label: 'November', value: 11 }, + { label: 'December', value: 12 }, + ], + }, + dayOfWeek: { + min: 0, + max: 6, + step: 1, + allowSpecial: ['*', '?'], + options: [ + { label: 'Sunday', value: 0 }, + { label: 'Monday', value: 1 }, + { label: 'Tuesday', value: 2 }, + { label: 'Wednesday', value: 3 }, + { label: 'Thursday', value: 4 }, + { label: 'Friday', value: 5 }, + { label: 'Saturday', value: 6 }, + ], + }, + year: { + min: 0, + max: 9999, + step: 1, + allowSpecial: ['*', '?'], + }, +}; + +const PERIOD_CONFIGS = { + minute: { + label: CronPeriod.Minute, + description: 'Run every minute', + template: '0 * * * * *', + fields: [CronField.Minutes], + }, + hourly: { + label: CronPeriod.Hourly, + description: 'Run every hour', + template: '0 0 * * * *', + fields: [CronField.Minutes, CronField.Hours], + }, + daily: { + label: CronPeriod.Daily, + description: 'Run every day', + template: '0 0 0 * * *', + fields: [CronField.Seconds, CronField.Minutes, CronField.Hours], + }, + weekly: { + label: CronPeriod.Weekly, + description: 'Run every week', + template: '0 0 0 * * 0', + fields: [ + CronField.Seconds, + CronField.Minutes, + CronField.Hours, + CronField.DayOfWeek, + ], + }, + monthly: { + label: CronPeriod.Monthly, + description: 'Run every month', + template: '0 0 0 1 * *', + fields: [ + CronField.Seconds, + CronField.Minutes, + CronField.Hours, + CronField.DayOfMonth, + ], + }, + yearly: { + label: CronPeriod.Yearly, + description: 'Run every year', + template: '0 0 0 1 1 *', + fields: [ + CronField.Seconds, + CronField.Minutes, + CronField.Hours, + CronField.DayOfMonth, + CronField.Month, + ], + }, + custom: { + label: CronPeriod.Custom, + description: 'Custom expression', + template: '0 0 * * * *', + fields: [ + CronField.Seconds, + CronField.Minutes, + CronField.Hours, + CronField.DayOfMonth, + CronField.Month, + CronField.DayOfWeek, + ], + }, +} as const; + +const CronBuilder: FC = ({ + timezone = 'UTC', + value = '0 0 * * * *', + onChange, + className, + disabled = false, + showPreview = true, + showPresets = true, + displayPeriods = [ + CronPeriod.Custom, + CronPeriod.Minute, + CronPeriod.Hourly, + CronPeriod.Daily, + CronPeriod.Weekly, + CronPeriod.Monthly, + CronPeriod.Yearly, + ], + defaultTab = CronPeriod.Custom, + presets = CRON_PRESETS, + showGeneratedExpression = true, + withCard = true, +}) => { + const [activeTab, setActiveTab] = useState(defaultTab); + const [cronFields, setCronFields] = useState(() => + parseCronExpression(value) + ); + + const currentExpression = useMemo(() => { + return `${cronFields.seconds} ${cronFields.minutes} ${cronFields.hours} ${cronFields.dayOfMonth} ${cronFields.month} ${cronFields.dayOfWeek}`; + }, [cronFields]); + + const nextRuns = useMemo(() => { + if (!showPreview) { + return []; + } + + try { + const matches = getFutureMatches(`${currentExpression} *`, { + matchCount: 3, + timezone, + formatInTimezone: true, + hasSeconds: true, + }); + return matches.map((match) => new Date(match)); + } catch (error) { + console.error('Failed to get future matched runs', error); + return []; + } + }, [currentExpression, showPreview, timezone]); + + useEffect(() => { + setCronFields(parseCronExpression(value)); + }, [value]); + + useEffect(() => { + onChange?.(currentExpression); + }, [currentExpression, onChange]); + + const handlePresetSelect = useCallback((preset: CronPreset) => { + setCronFields(parseCronExpression(preset.value)); + }, []); + + const handleFieldChange = useCallback( + (field: CronField, newValue: string) => { + setCronFields((prev) => ({ ...prev, [field]: newValue })); + }, + [] + ); + + const handlePeriodChange = useCallback((period: CronPeriod) => { + setActiveTab(period); + if (period !== 'custom') { + const config = PERIOD_CONFIGS[period]; + setCronFields(parseCronExpression(config.template)); + } + }, []); + + const filteredPresets = useMemo(() => { + return presets.filter((preset) => { + if (activeTab === 'custom') { + return true; + } + return preset.category === activeTab; + }); + }, [presets, activeTab]); + + return ( +
+ handlePeriodChange(value as CronPeriod)} + > +
+ 4 + ? `${displayPeriods.length * 25 - 20}%` + : '100%', + } as CSSProperties + } + > + {displayPeriods.map((period) => ( + + {PERIOD_CONFIGS[period].label} + + ))} + +
+ {displayPeriods.map((period) => ( + + + + + + + {PERIOD_CONFIGS[period].label} Configuration + + + + {PERIOD_CONFIGS[period].description} + + + + + + + + {showPresets && filteredPresets.length > 0 && ( + + + + + Quick Presets + + + Common cron expressions for quick setup + + + +
+ {filteredPresets.map((preset, index) => ( + + ))} +
+
+
+ )} +
+ ))} +
+ {/* Current Expression & Preview */} + {showGeneratedExpression && ( + + + + + Generated Expression + + + +
+ + {currentExpression} + +
+ + {showPreview && nextRuns.length > 0 && ( + <> + +
+

+ + Next Runs({timezone}) +

+
+ {nextRuns.map((date, index) => ( +
+ + #{index + 1} + + + + {date.toLocaleString()} + +
+ ))} +
+
+ + )} +
+
+ )} +
+ ); +}; + +interface CronFieldEditorProps { + period: CronPeriod; + fields: Record; + onChange: (field: CronField, value: string) => void; + disabled?: boolean; +} + +const CronFieldEditor: FC = ({ + period, + fields, + onChange, + disabled = false, +}) => { + const relevantFields = [...PERIOD_CONFIGS[period].fields] as CronField[]; + + return ( +
+ {relevantFields.map((field) => { + const config = FIELD_CONFIGS[field]; + const currentValue = fields[field]; + + return ( +
+ + + {field === 'month' || field === 'dayOfWeek' ? ( + + // biome-ignore lint/nursery/noNestedTernary: + ) : field === 'dayOfMonth' ? ( +
+ +
+ ) : ( +
+ { + if (value === '*') { + onChange(field, '*'); + } else if (value === 'specific' && currentValue === '*') { + onChange(field, '0'); + } + }} + disabled={disabled} + > + + Any + + + Specific + + + + {currentValue !== '*' && ( + onChange(field, e.target.value)} + placeholder={`0-${config.max}`} + disabled={disabled} + className="font-mono text-sm" + /> + )} + +
+
+ + + Range: {config.min}-{config.max} + +
+
+ Supports: *, numbers, ranges (1-5), lists (1,3,5), steps + (*/5) +
+
+
+ )} +
+ ); + })} +
+ ); +}; + +function parseCronExpression(expression: string): Record { + const parts = expression.split(' '); + + // Ensure we have 6 parts, pad with defaults if needed + while (parts.length < 6) { + parts.push('*'); + } + + return { + seconds: parts[0] || '0', + minutes: parts[1] || '*', + hours: parts[2] || '*', + dayOfMonth: parts[3] || '*', + month: parts[4] || '*', + dayOfWeek: parts[5] || '*', + year: parts[6] || '*', + }; +} + +export { CronBuilder }; diff --git a/apps/webui/src/components/domains/cron/cron-display.tsx b/apps/webui/src/components/domains/cron/cron-display.tsx new file mode 100644 index 0000000..dcdf3da --- /dev/null +++ b/apps/webui/src/components/domains/cron/cron-display.tsx @@ -0,0 +1,277 @@ +import { Badge } from '@/components/ui/badge'; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@/components/ui/card'; +import { cn } from '@/presentation/utils'; +import { getFutureMatches, isTimeMatches } from '@datasert/cronjs-matcher'; +import { parse } from '@datasert/cronjs-parser'; +import { AlertCircle, CalendarDays, CheckCircle, Clock } from 'lucide-react'; +import { type FC, useMemo } from 'react'; +import type { + CronDisplayProps, + CronNextRun, + CronValidationResult, +} from './types.js'; + +const CronDisplay: FC = ({ + expression, + className, + showNextRuns = true, + nextRunsCount = 5, + timezone = 'UTC', + showDescription = true, + withCard = true, +}) => { + const validationResult = useMemo((): CronValidationResult => { + if (!expression) { + return { isValid: false, error: 'No expression provided' }; + } + + try { + const _parsed = parse(`${expression} *`, { hasSeconds: true }); + return { + isValid: true, + description: generateDescription(expression), + }; + } catch (error) { + return { + isValid: false, + error: error instanceof Error ? error.message : 'Invalid expression', + }; + } + }, [expression]); + + const nextRuns = useMemo((): CronNextRun[] => { + if (!expression || !validationResult.isValid || !showNextRuns) { + return []; + } + + try { + const matches = getFutureMatches(`${expression} *`, { + matchCount: nextRunsCount, + timezone, + formatInTimezone: true, + hasSeconds: true, + }); + + return matches.map((match) => { + const date = new Date(match); + return { + date, + timestamp: date.getTime(), + formatted: date.toLocaleString(), + relative: getRelativeTime(date), + }; + }); + } catch (error) { + console.warn('Failed to get future matches:', error); + return []; + } + }, [ + expression, + validationResult.isValid, + showNextRuns, + nextRunsCount, + timezone, + ]); + + const isCurrentTimeMatch = useMemo(() => { + if (!expression || !validationResult.isValid) { + return false; + } + + try { + return isTimeMatches( + `${expression} *`, + new Date().toISOString(), + timezone + ); + } catch (_error: unknown) { + return false; + } + }, [expression, validationResult.isValid, timezone]); + + if (!expression) { + return ( + + +
+ + No cron expression set +
+
+
+ ); + } + + return ( + + +
+ + + Cron Expression + {isCurrentTimeMatch && ( + + + Active Now + + )} + + + {expression} + +
+ + {validationResult.isValid && + showDescription && + validationResult.description && ( + + {validationResult.description} + + )} + + {!validationResult.isValid && validationResult.error && ( + + + {validationResult.error} + + )} +
+ + {validationResult.isValid && showNextRuns && nextRuns.length > 0 && ( + +
+

+ + Next Runs + + {timezone} + +

+
+ {nextRuns.map((run, index) => ( +
+
+ + #{index + 1} + + {run.formatted} +
+ + {run.relative} + +
+ ))} +
+
+
+ )} +
+ ); +}; + +function generateDescription(expression: string): string { + // Enhanced description generator based on common patterns + const parts = expression.split(' '); + if (parts.length !== 6) { + return expression; + } + + const [sec, min, hour, day, month, weekday] = parts; + + // Common patterns + const patterns: Record = { + '* * * * * *': 'Every second', + '0 * * * * *': 'Every minute', + '0 0 * * * *': 'Every hour', + '0 0 0 * * *': 'Daily at midnight', + '0 0 0 * * 0': 'Every Sunday at midnight', + '0 0 0 * * 1': 'Every Monday at midnight', + '0 0 0 * * 2': 'Every Tuesday at midnight', + '0 0 0 * * 3': 'Every Wednesday at midnight', + '0 0 0 * * 4': 'Every Thursday at midnight', + '0 0 0 * * 5': 'Every Friday at midnight', + '0 0 0 * * 6': 'Every Saturday at midnight', + '0 0 0 1 * *': 'Monthly on the 1st at midnight', + '0 0 0 1 1 *': 'Yearly on January 1st at midnight', + '0 30 9 * * 1-5': 'Weekdays at 9:30 AM', + '0 0 */6 * * *': 'Every 6 hours', + '0 */30 * * * *': 'Every 30 minutes', + '0 */15 * * * *': 'Every 15 minutes', + '0 */5 * * * *': 'Every 5 minutes', + }; + + if (patterns[expression]) { + return patterns[expression]; + } + + // Generate dynamic description + let description = 'At '; + + if (sec !== '*' && sec !== '0') { + description += `second ${sec}, `; + } + if (min !== '*') { + description += `minute ${min}, `; + } + if (hour !== '*') { + description += `hour ${hour}, `; + } + + if (day !== '*' && weekday !== '*') { + description += `on day ${day} and weekday ${weekday} `; + } else if (day !== '*') { + description += `on day ${day} `; + } else if (weekday !== '*') { + description += `on weekday ${weekday} `; + } + + if (month !== '*') { + description += `in month ${month}`; + } + + // biome-ignore lint/performance/useTopLevelRegex: + return description.replace(/,\s*$/, '').replace(/At\s*$/, 'Every occurrence'); +} + +function getRelativeTime(date: Date): string { + const now = new Date(); + const diffMs = date.getTime() - now.getTime(); + + if (diffMs < 0) { + return 'Past'; + } + + const diffSec = Math.floor(diffMs / 1000); + const diffMin = Math.floor(diffSec / 60); + const diffHour = Math.floor(diffMin / 60); + const diffDay = Math.floor(diffHour / 24); + + if (diffSec < 60) { + return `in ${diffSec}s`; + } + if (diffMin < 60) { + return `in ${diffMin}m`; + } + if (diffHour < 24) { + return `in ${diffHour}h`; + } + if (diffDay < 7) { + return `in ${diffDay}d`; + } + + return `in ${Math.floor(diffDay / 7)}w`; +} + +export { CronDisplay }; diff --git a/apps/webui/src/components/domains/cron/cron-example.tsx b/apps/webui/src/components/domains/cron/cron-example.tsx new file mode 100644 index 0000000..0742dc6 --- /dev/null +++ b/apps/webui/src/components/domains/cron/cron-example.tsx @@ -0,0 +1,413 @@ +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@/components/ui/card'; +import { Separator } from '@/components/ui/separator'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { Code2, Play, Settings, Type } from 'lucide-react'; +import { type FC, useCallback, useState } from 'react'; +import { CronBuilder } from './cron-builder.js'; +import { CronDisplay } from './cron-display.js'; +import { CronInput } from './cron-input.js'; +import { Cron } from './cron.js'; + +const CronExample: FC = () => { + const [inputValue, setInputValue] = useState('0 30 9 * * 1-5'); + const [builderValue, setBuilderValue] = useState('0 0 */6 * * *'); + const [fullValue, setFullValue] = useState('0 */15 * * * *'); + const [displayValue] = useState('0 0 0 * * 0'); + + const examples = [ + { + label: 'Every minute', + expression: '0 * * * * *', + description: 'Runs at the start of every minute', + }, + { + label: 'Every 5 minutes', + expression: '0 */5 * * * *', + description: 'Runs every 5 minutes', + }, + { + label: 'Every hour', + expression: '0 0 * * * *', + description: 'Runs at the start of every hour', + }, + { + label: 'Daily at 9 AM', + expression: '0 0 9 * * *', + description: 'Runs every day at 9:00 AM', + }, + { + label: 'Weekdays at 9:30 AM', + expression: '0 30 9 * * 1-5', + description: 'Runs Monday through Friday at 9:30 AM', + }, + { + label: 'Every Sunday', + expression: '0 0 0 * * 0', + description: 'Runs every Sunday at midnight', + }, + { + label: 'First day of month', + expression: '0 0 0 1 * *', + description: 'Runs on the 1st day of every month', + }, + { + label: 'Every quarter', + expression: '0 0 0 1 */3 *', + description: 'Runs on the 1st day of every quarter', + }, + ]; + + const handleCopyExample = useCallback(async (expression: string) => { + try { + await navigator.clipboard.writeText(expression); + } catch (error) { + console.warn('Failed to copy to clipboard:', error); + } + }, []); + + return ( +
+ {/* Header */} +
+

Cron Expression Components

+

+ A comprehensive set of components for creating and managing cron + expressions. +

+
+ + {/* Quick Examples */} + + + + + Common Examples + + + Click any example to copy the expression to your clipboard + + + +
+ {examples.map((example, index) => ( + + ))} +
+
+
+ + + + {/* Component Examples */} +
+
+

Component Examples

+

+ Interactive examples showing different ways to use the cron + components. +

+
+ + + + Complete + Input Only + Builder Only + Display Only + + + + + + + + Complete Cron Component + + + Full-featured component with both input and visual builder + modes, validation, preview, and help documentation. + + + +
+ + +
+

Current Value:

+ + {fullValue || 'No expression set'} + +
+
+
+
+
+ + + + + + + Text Input Component + + + Simple text input with validation, help text, and real-time + feedback. + + + +
+ + +
+

Current Value:

+ + {inputValue || 'No expression set'} + +
+
+
+
+ + + + Input-Only Mode + + Using the main Cron component in input-only mode with preview. + + + + + + +
+ + + + + + + Visual Builder Component + + + Visual interface for building cron expressions with presets + and field editors. + + + +
+ + +
+

Current Value:

+ + {builderValue || 'No expression set'} + +
+
+
+
+ + + + Builder-Only Mode + + Using the main Cron component in builder-only mode. + + + + + + +
+ + + + + + + Display Component + + + Read-only component that shows cron expression details, + description, and next run times. + + + +
+ +
+
+
+ + + + Multiple Timezone Display + + Same expression displayed in different timezones. + + + +
+
+

UTC

+ +
+
+

+ America/New_York +

+ +
+
+
+
+
+
+
+ + {/* Usage Examples */} + + + Usage Examples + + Code examples showing how to integrate these components into your + application. + + + +
+
+

Basic Usage

+
+
{`import { Cron } from '@/components/cron';
+
+function MyComponent() {
+  const [cronExpression, setCronExpression] = useState('0 0 * * * *');
+
+  return (
+    
+  );
+}`}
+
+
+ +
+

+ Input Only with Validation +

+
+
{`import { CronInput } from '@/components/cron';
+
+function ScheduleForm() {
+  const [expression, setExpression] = useState('');
+  const [isValid, setIsValid] = useState(false);
+
+  return (
+    
+  );
+}`}
+
+
+ +
+

+ Display Schedule Information +

+
+
{`import { CronDisplay } from '@/components/cron';
+
+function SchedulePreview({ schedule }) {
+  return (
+    
+  );
+}`}
+
+
+
+
+
+
+ ); +}; + +export { CronExample }; diff --git a/apps/webui/src/components/domains/cron/cron-input.tsx b/apps/webui/src/components/domains/cron/cron-input.tsx new file mode 100644 index 0000000..7a317cc --- /dev/null +++ b/apps/webui/src/components/domains/cron/cron-input.tsx @@ -0,0 +1,186 @@ +import { Badge } from '@/components/ui/badge'; +import { Input } from '@/components/ui/input'; +import { cn } from '@/presentation/utils'; +import { parse } from '@datasert/cronjs-parser'; +import { AlertCircle, CheckCircle, Info } from 'lucide-react'; +import { + type ChangeEvent, + forwardRef, + useCallback, + useEffect, + useMemo, + useState, +} from 'react'; +import type { CronInputProps, CronValidationResult } from './types.js'; + +const CronInput = forwardRef( + ( + { + value, + onChange, + onValidate, + placeholder = '0 0 * * * *', + className, + disabled, + readOnly, + error, + ...props + }, + ref + ) => { + const [internalValue, setInternalValue] = useState(value || ''); + const [isFocused, setIsFocused] = useState(false); + + const validationResult = useMemo((): CronValidationResult => { + if (!internalValue.trim()) { + return { isValid: false, error: 'Expression is required' }; + } + + try { + parse(`${internalValue} *`, { hasSeconds: true }); + return { isValid: true }; + } catch (parseError) { + return { + isValid: false, + error: + parseError instanceof Error + ? parseError.message + : 'Invalid cron expression', + }; + } + }, [internalValue]); + + useEffect(() => { + setInternalValue(value || ''); + }, [value]); + + useEffect(() => { + onValidate?.(validationResult.isValid); + }, [validationResult.isValid, onValidate]); + + const handleChange = useCallback( + (e: ChangeEvent) => { + const newValue = e.target.value; + setInternalValue(newValue); + onChange?.(newValue); + }, + [onChange] + ); + + const handleFocus = useCallback(() => { + setIsFocused(true); + }, []); + + const handleBlur = useCallback(() => { + setIsFocused(false); + }, []); + + const hasError = + error || (!validationResult.isValid && internalValue.trim()); + const showSuccess = + validationResult.isValid && internalValue.trim() && !isFocused; + + return ( +
+
+ + + {/* Status icon */} +
+ {hasError && } + {showSuccess && } +
+
+ + {/* Error message */} + {hasError && ( +
+ + {error || validationResult.error} +
+ )} + + {/* Help text when focused */} + {isFocused && !hasError && ( +
+
+ + Format: second minute hour day month weekday +
+
+
+ + * + + any value +
+
+ + , + + list separator +
+
+ + - + + range +
+
+ + / + + step value +
+
+
+
Examples:
+
+
+ + 0 * * * * * + + Every minute +
+
+ + 0 0 * * * * + + Every hour +
+
+ + 0 30 9 * * 1-5 + + Weekdays at 9:30 AM +
+
+
+
+ )} +
+ ); + } +); + +CronInput.displayName = 'CronInput'; + +export { CronInput }; diff --git a/apps/webui/src/components/domains/cron/cron.tsx b/apps/webui/src/components/domains/cron/cron.tsx new file mode 100644 index 0000000..a815d2c --- /dev/null +++ b/apps/webui/src/components/domains/cron/cron.tsx @@ -0,0 +1,500 @@ +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@/components/ui/card'; +import { Separator } from '@/components/ui/separator'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { cn } from '@/presentation/utils'; +import { parse } from '@datasert/cronjs-parser'; +import { + AlertCircle, + Bolt, + Check, + Code2, + Copy, + Settings, + Type, +} from 'lucide-react'; +import { type FC, useCallback, useEffect, useMemo, useState } from 'react'; +import { CronBuilder } from './cron-builder'; +import { CronDisplay } from './cron-display'; +import { CronInput } from './cron-input'; +import { + CronMode, + type CronPrimitiveMode, + type CronProps, + type CronValidationResult, +} from './types'; + +const PLACEHOLDER = '0 0 * * * *'; + +const Cron: FC = ({ + value = '', + onChange, + activeMode = 'input', + onActiveModeChange, + onValidate, + className, + mode = 'both', + disabled = false, + placeholder = PLACEHOLDER, + showPreview = true, + showDescription = true, + timezone = 'UTC', + error, + children, + showHelp = true, + displayPeriods, + defaultTab, + presets, + showPresets, + withCard = true, + // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: +}) => { + const [internalValue, setInternalValue] = useState(value || ''); + const [internalActiveMode, setInternalActiveMode] = + useState( + mode === CronMode.Both ? activeMode : (mode as CronPrimitiveMode) + ); + const [copied, setCopied] = useState(false); + + const validationResult = useMemo((): CronValidationResult => { + if (!internalValue.trim()) { + return { isValid: false, error: 'Expression is required', isEmpty: true }; + } + + try { + parse(`${internalValue} *`, { hasSeconds: true }); + return { isValid: true }; + } catch (parseError) { + return { + isValid: false, + error: + parseError instanceof Error + ? parseError.message + : 'Invalid cron expression', + }; + } + }, [internalValue]); + + useEffect(() => { + setInternalValue(value || ''); + }, [value]); + + useEffect(() => { + onValidate?.(validationResult.isValid); + }, [validationResult.isValid, onValidate]); + + useEffect(() => { + if (mode === 'both') { + setInternalActiveMode(activeMode); + } + }, [activeMode, mode]); + + const handleChange = useCallback( + (newValue: string) => { + setInternalValue(newValue); + onChange?.(newValue); + }, + [onChange] + ); + + const handleActiveModeChange = useCallback( + (mode: CronPrimitiveMode) => { + setInternalActiveMode(mode); + onActiveModeChange?.(mode); + }, + [onActiveModeChange] + ); + + const handleCopy = useCallback(async () => { + if (!internalValue) { + return; + } + + try { + await navigator.clipboard.writeText(internalValue); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (error) { + console.warn('Failed to copy to clipboard:', error); + } + }, [internalValue]); + + const hasError = + !!error || !!(!validationResult.isValid && internalValue.trim()); + + if (mode === 'input') { + return ( +
+ + + {showPreview && + (validationResult.isValid || validationResult.isEmpty) && ( + + )} + + {children} +
+ ); + } + + if (mode === 'builder') { + return ( +
+ + + {children} +
+ ); + } + + return ( +
+ + +
+
+ + + Cron Expression Builder + + + Create and validate cron expressions using visual builder or + text input + +
+ {internalValue && ( +
+ + {internalValue} + + +
+ )} +
+ + {hasError && ( +
+ + {error || validationResult.error} +
+ )} +
+ + + + handleActiveModeChange(value as 'input' | 'builder') + } + > + + + + Text Input + + + + Visual Builder + + + + + + + + + + + + +
+ + {/* Preview Section */} + {showPreview && + (validationResult.isValid || validationResult.isEmpty) && ( + <> + {!withCard && } + + + )} + + {/* Help Section */} + {showHelp && ( + <> + {!withCard && } + + + + + Cron Expression Format + + + +
+
+
+
+ Second +
+
0-59
+
+
+
+ Minute +
+
0-59
+
+
+
+ Hour +
+
0-23
+
+
+
+ Day +
+
1-31
+
+
+
+ Month +
+
1-12
+
+
+
+ Weekday +
+
0-6
+
+
+ + + +
+
+
+ + * + + Any value +
+
+ Matches all possible values +
+
+ +
+
+ + 5 + + Specific value +
+
+ Matches exactly this value +
+
+ +
+
+ + 1-5 + + Range +
+
+ Matches values 1 through 5 +
+
+ +
+
+ + 1,3,5 + + List +
+
+ Matches values 1, 3, and 5 +
+
+ +
+
+ + */5 + + Step +
+
+ Every 5th value +
+
+ +
+
+ + 0-10/2 + + Range + Step +
+
+ Even values 0-10 +
+
+ +
+
+ + ? + + No specific +
+
+ Used when day/weekday conflicts +
+
+ +
+
+ + L + + Last +
+
+ Last day of month/week +
+
+
+ + + +
+

Common Examples:

+
+
+ + 0 0 * * * * + + Every hour +
+
+ + 0 */15 * * * * + + + Every 15 minutes + +
+
+ + 0 0 0 * * * + + + Daily at midnight + +
+
+ + 0 30 9 * * 1-5 + + + Weekdays at 9:30 AM + +
+
+
+
+
+
+ + )} + {children} +
+ ); +}; + +export { Cron }; diff --git a/apps/webui/src/components/domains/cron/index.ts b/apps/webui/src/components/domains/cron/index.ts new file mode 100644 index 0000000..ccc38df --- /dev/null +++ b/apps/webui/src/components/domains/cron/index.ts @@ -0,0 +1,20 @@ +export { Cron } from './cron'; +export { CronInput } from './cron-input'; +export { CronBuilder } from './cron-builder'; +export { CronDisplay } from './cron-display'; +export { CronExample } from './cron-example'; + +export { + type CronProps, + type CronInputProps, + type CronBuilderProps, + type CronDisplayProps, + type CronExpression, + CronPeriod, + type CronPreset, + type CronValidationResult, + type CronNextRun, + type CronFieldConfig, + CronField, + type PeriodConfig, +} from './types'; diff --git a/apps/webui/src/components/domains/cron/types.ts b/apps/webui/src/components/domains/cron/types.ts new file mode 100644 index 0000000..4bbeeec --- /dev/null +++ b/apps/webui/src/components/domains/cron/types.ts @@ -0,0 +1,162 @@ +import type { ClassValue } from 'clsx'; +import type { ReactNode } from 'react'; + +export interface CronExpression { + seconds?: string; + minutes?: string; + hours?: string; + dayOfMonth?: string; + month?: string; + dayOfWeek?: string; + year?: string; +} + +export interface CronDisplayProps { + expression: string; + className?: ClassValue; + showNextRuns?: boolean; + nextRunsCount?: number; + timezone?: string; + showDescription?: boolean; + withCard?: boolean; +} + +export interface CronInputProps { + value?: string; + onChange?: (value: string) => void; + onValidate?: (isValid: boolean) => void; + placeholder?: string; + className?: ClassValue; + disabled?: boolean; + readOnly?: boolean; + error?: string; +} + +export interface CronBuilderProps { + value?: string; + onChange?: (value: string) => void; + className?: ClassValue; + disabled?: boolean; + showPreview?: boolean; + defaultTab?: CronPeriod; + displayPeriods?: CronPeriod[]; + presets?: CronPreset[]; + showPresets?: boolean; + showGeneratedExpression?: boolean; + timezone?: string; + withCard?: boolean; +} + +export const CronPrimitiveMode = { + Input: 'input', + Builder: 'builder', +} as const; + +export type CronPrimitiveMode = + (typeof CronPrimitiveMode)[keyof typeof CronPrimitiveMode]; + +export const CronMode = { + Input: 'input', + Builder: 'builder', + Both: 'both', +} as const; + +export type CronMode = (typeof CronMode)[keyof typeof CronMode]; + +export interface CronProps { + value?: string; + onChange?: (value: string) => void; + activeMode?: CronPrimitiveMode; + onActiveModeChange?: (mode: CronPrimitiveMode) => void; + onValidate?: (isValid: boolean) => void; + className?: ClassValue; + mode?: CronMode; + disabled?: boolean; + placeholder?: string; + showPreview?: boolean; + showDescription?: boolean; + timezone?: string; + error?: string; + children?: ReactNode; + defaultTab?: CronPeriod; + displayPeriods?: CronPeriod[]; + presets?: CronPreset[]; + showHelp?: boolean; + showPresets?: boolean; + withCard?: boolean; +} + +export const CronPeriod = { + Minute: 'minute', + Hourly: 'hourly', + Daily: 'daily', + Weekly: 'weekly', + Monthly: 'monthly', + Yearly: 'yearly', + Custom: 'custom', +} as const; + +export type CronPeriod = (typeof CronPeriod)[keyof typeof CronPeriod]; + +export interface CronFieldProps { + period: CronPeriod; + value: string; + onChange: (value: string) => void; + disabled?: boolean; + className?: ClassValue; +} + +export interface CronPreset { + label: string; + value: string; + description: string; + category?: string; +} + +export interface CronValidationResult { + isValid: boolean; + error?: string; + description?: string; + isEmpty?: boolean; +} + +export interface CronNextRun { + date: Date; + timestamp: number; + formatted: string; + relative: string; +} + +export interface PeriodConfig { + label: string; + description: string; + defaultValue: string; + fields: { + seconds?: boolean; + minutes?: boolean; + hours?: boolean; + dayOfMonth?: boolean; + month?: boolean; + dayOfWeek?: boolean; + }; +} + +export const CronField = { + Seconds: 'seconds', + Minutes: 'minutes', + Hours: 'hours', + DayOfMonth: 'dayOfMonth', + Month: 'month', + DayOfWeek: 'dayOfWeek', + Year: 'year', +} as const; + +export type CronField = (typeof CronField)[keyof typeof CronField]; + +export interface CronFieldConfig { + min: number; + max: number; + step?: number; + options?: Array<{ label: string; value: number | string }>; + allowSpecial?: string[]; +} diff --git a/apps/webui/src/components/detail-card-skeleton.tsx b/apps/webui/src/components/ui/detail-card-skeleton.tsx similarity index 90% rename from apps/webui/src/components/detail-card-skeleton.tsx rename to apps/webui/src/components/ui/detail-card-skeleton.tsx index 0f44d96..e623ad0 100644 --- a/apps/webui/src/components/detail-card-skeleton.tsx +++ b/apps/webui/src/components/ui/detail-card-skeleton.tsx @@ -1,5 +1,5 @@ -import { Card, CardContent, CardHeader } from './ui/card'; -import { Skeleton } from './ui/skeleton'; +import { Card, CardContent, CardHeader } from "./card"; +import { Skeleton } from "./skeleton"; export function DetailCardSkeleton() { return ( diff --git a/apps/webui/src/domains/recorder/schema/cron.ts b/apps/webui/src/domains/recorder/schema/cron.ts index ec597da..5fbe2ba 100644 --- a/apps/webui/src/domains/recorder/schema/cron.ts +++ b/apps/webui/src/domains/recorder/schema/cron.ts @@ -1,3 +1,4 @@ +import type { CronPreset } from '@/components/domains/cron'; import type { GetCronsQuery } from '@/infra/graphql/gql/graphql'; import { gql } from '@apollo/client'; @@ -56,3 +57,64 @@ export const DELETE_CRONS = gql` cronDelete(filter: $filter) } `; + +export const INSERT_CRON = gql` + mutation InsertCron($data: CronInsertInput!) { + cronCreateOne(data: $data) { + id + cronExpr + nextRun + lastRun + lastError + status + lockedAt + lockedBy + createdAt + updatedAt + timeoutMs + maxAttempts + priority + attempts + subscriberTaskCron + } + } +`; + +export const SUBSCRIPTION_TASK_CRON_PRESETS: CronPreset[] = [ + { + label: 'Daily at midnight', + value: '0 0 0 * * *', + description: 'Runs once daily at 00:00', + category: 'daily', + }, + { + label: 'Daily at 9 AM', + value: '0 0 9 * * *', + description: 'Runs daily at 9:00 AM', + category: 'daily', + }, + { + label: 'Weekdays at 9 AM', + value: '0 0 9 * * 1-5', + description: 'Runs Monday to Friday at 9:00 AM', + category: 'weekly', + }, + { + label: 'Every Sunday', + value: '0 0 0 * * 0', + description: 'Runs every Sunday at midnight', + category: 'weekly', + }, + { + label: 'First day of month', + value: '0 0 0 1 * *', + description: 'Runs on the 1st day of every month', + category: 'monthly', + }, + { + label: 'Every year', + value: '0 0 0 1 1 *', + description: 'Runs on January 1st every year', + category: 'yearly', + }, +]; diff --git a/apps/webui/src/infra/graphql/gql/gql.ts b/apps/webui/src/infra/graphql/gql/gql.ts index ba247f5..26ee7cd 100644 --- a/apps/webui/src/infra/graphql/gql/gql.ts +++ b/apps/webui/src/infra/graphql/gql/gql.ts @@ -22,6 +22,7 @@ type Documents = { "\n mutation CheckCredential3rdAvailable($filter: Credential3rdFilterInput!) {\n credential3rdCheckAvailable(filter: $filter) {\n available\n }\n }\n": typeof types.CheckCredential3rdAvailableDocument, "\nquery GetCrons($filter: CronFilterInput!, $orderBy: CronOrderInput!, $pagination: PaginationInput!) {\n cron(pagination: $pagination, filter: $filter, orderBy: $orderBy) {\n nodes {\n id\n cronExpr\n nextRun\n lastRun\n lastError\n status\n lockedAt\n lockedBy\n createdAt\n updatedAt\n timeoutMs\n maxAttempts\n priority\n attempts\n subscriberTaskCron\n subscriberTask {\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 }\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": typeof types.GetCronsDocument, "\n mutation DeleteCrons($filter: CronFilterInput!) {\n cronDelete(filter: $filter)\n }\n": typeof types.DeleteCronsDocument, + "\n mutation InsertCron($data: CronInsertInput!) {\n cronCreateOne(data: $data) {\n id\n cronExpr\n nextRun\n lastRun\n lastError\n status\n lockedAt\n lockedBy\n createdAt\n updatedAt\n timeoutMs\n maxAttempts\n priority\n attempts\n subscriberTaskCron\n }\n }\n": typeof types.InsertCronDocument, "\n mutation InsertFeed($data: FeedsInsertInput!) {\n feedsCreateOne(data: $data) {\n id\n createdAt\n updatedAt\n feedType\n token\n }\n }\n": typeof types.InsertFeedDocument, "\n mutation DeleteFeed($filter: FeedsFilterInput!) {\n feedsDelete(filter: $filter)\n }\n": typeof types.DeleteFeedDocument, "\n query GetSubscriptions($filter: SubscriptionsFilterInput!, $orderBy: SubscriptionsOrderInput!, $pagination: PaginationInput!) {\n subscriptions(\n pagination: $pagination\n filter: $filter\n orderBy: $orderBy\n ) {\n nodes {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n credentialId\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": typeof types.GetSubscriptionsDocument, @@ -43,6 +44,7 @@ const documents: Documents = { "\n mutation CheckCredential3rdAvailable($filter: Credential3rdFilterInput!) {\n credential3rdCheckAvailable(filter: $filter) {\n available\n }\n }\n": types.CheckCredential3rdAvailableDocument, "\nquery GetCrons($filter: CronFilterInput!, $orderBy: CronOrderInput!, $pagination: PaginationInput!) {\n cron(pagination: $pagination, filter: $filter, orderBy: $orderBy) {\n nodes {\n id\n cronExpr\n nextRun\n lastRun\n lastError\n status\n lockedAt\n lockedBy\n createdAt\n updatedAt\n timeoutMs\n maxAttempts\n priority\n attempts\n subscriberTaskCron\n subscriberTask {\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 }\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": types.GetCronsDocument, "\n mutation DeleteCrons($filter: CronFilterInput!) {\n cronDelete(filter: $filter)\n }\n": types.DeleteCronsDocument, + "\n mutation InsertCron($data: CronInsertInput!) {\n cronCreateOne(data: $data) {\n id\n cronExpr\n nextRun\n lastRun\n lastError\n status\n lockedAt\n lockedBy\n createdAt\n updatedAt\n timeoutMs\n maxAttempts\n priority\n attempts\n subscriberTaskCron\n }\n }\n": types.InsertCronDocument, "\n mutation InsertFeed($data: FeedsInsertInput!) {\n feedsCreateOne(data: $data) {\n id\n createdAt\n updatedAt\n feedType\n token\n }\n }\n": types.InsertFeedDocument, "\n mutation DeleteFeed($filter: FeedsFilterInput!) {\n feedsDelete(filter: $filter)\n }\n": types.DeleteFeedDocument, "\n query GetSubscriptions($filter: SubscriptionsFilterInput!, $orderBy: SubscriptionsOrderInput!, $pagination: PaginationInput!) {\n subscriptions(\n pagination: $pagination\n filter: $filter\n orderBy: $orderBy\n ) {\n nodes {\n id\n createdAt\n updatedAt\n displayName\n category\n sourceUrl\n enabled\n credentialId\n }\n paginationInfo {\n total\n pages\n }\n }\n }\n": types.GetSubscriptionsDocument, @@ -102,6 +104,10 @@ export function gql(source: "\nquery GetCrons($filter: CronFilterInput!, $orderB * 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 DeleteCrons($filter: CronFilterInput!) {\n cronDelete(filter: $filter)\n }\n"): (typeof documents)["\n mutation DeleteCrons($filter: CronFilterInput!) {\n cronDelete(filter: $filter)\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 InsertCron($data: CronInsertInput!) {\n cronCreateOne(data: $data) {\n id\n cronExpr\n nextRun\n lastRun\n lastError\n status\n lockedAt\n lockedBy\n createdAt\n updatedAt\n timeoutMs\n maxAttempts\n priority\n attempts\n subscriberTaskCron\n }\n }\n"): (typeof documents)["\n mutation InsertCron($data: CronInsertInput!) {\n cronCreateOne(data: $data) {\n id\n cronExpr\n nextRun\n lastRun\n lastError\n status\n lockedAt\n lockedBy\n createdAt\n updatedAt\n timeoutMs\n maxAttempts\n priority\n attempts\n subscriberTaskCron\n }\n }\n"]; /** * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/apps/webui/src/infra/graphql/gql/graphql.ts b/apps/webui/src/infra/graphql/gql/graphql.ts index c16c4c8..f00d2a9 100644 --- a/apps/webui/src/infra/graphql/gql/graphql.ts +++ b/apps/webui/src/infra/graphql/gql/graphql.ts @@ -1,44 +1,28 @@ -import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; /* 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 | null; export type InputMaybe = Maybe; -export type Exact = { - [K in keyof T]: T[K]; -}; -export type MakeOptional = Omit & { - [SubKey in K]?: Maybe; -}; -export type MakeMaybe = Omit & { - [SubKey in K]: Maybe; -}; -export type MakeEmpty< - T extends { [key: string]: unknown }, - K extends keyof T, -> = { [_ in K]?: never }; -export type Incremental = - | T - | { - [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never; - }; +export type Exact = { [K in keyof T]: T[K] }; +export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; +export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; +export type MakeEmpty = { [_ in K]?: never }; +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; + ID: { input: string; output: string; } + String: { input: string; output: string; } + Boolean: { input: boolean; output: boolean; } + Int: { input: number; output: number; } + Float: { input: number; output: number; } /** The `JSON` scalar type represents raw JSON values */ - Json: { input: any; output: any }; - JsonbFilterInput: { input: any; output: any }; + 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; - }; + SubscriberTaskType: { input: SubscriberTaskInput; output: SubscriberTaskType; } /** type SystemTaskType = { "taskType": "optimize_image" } & OptimizeImageTask | { "taskType": "test" } & EchoTask; */ - SystemTaskType: { input: any; output: any }; + SystemTaskType: { input: any; output: any; } }; export type Bangumi = { @@ -66,18 +50,21 @@ export type Bangumi = { updatedAt: Scalars['String']['output']; }; + export type BangumiEpisodeArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type BangumiSubscriptionArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type BangumiSubscriptionBangumiArgs = { filter?: InputMaybe; orderBy?: InputMaybe; @@ -181,11 +168,10 @@ export type BangumiOrderInput = { }; export const BangumiTypeEnum = { - Mikan: 'mikan', + Mikan: 'mikan' } as const; -export type BangumiTypeEnum = - (typeof BangumiTypeEnum)[keyof typeof BangumiTypeEnum]; +export type BangumiTypeEnum = typeof BangumiTypeEnum[keyof typeof BangumiTypeEnum]; export type BangumiTypeEnumFilterInput = { eq?: InputMaybe; gt?: InputMaybe; @@ -246,6 +232,7 @@ export type Credential3rd = { username?: Maybe; }; + export type Credential3rdSubscriptionArgs = { filter?: InputMaybe; orderBy?: InputMaybe; @@ -324,11 +311,10 @@ export type Credential3rdOrderInput = { }; export const Credential3rdTypeEnum = { - Mikan: 'mikan', + Mikan: 'mikan' } as const; -export type Credential3rdTypeEnum = - (typeof Credential3rdTypeEnum)[keyof typeof Credential3rdTypeEnum]; +export type Credential3rdTypeEnum = typeof Credential3rdTypeEnum[keyof typeof Credential3rdTypeEnum]; export type Credential3rdTypeEnumFilterInput = { eq?: InputMaybe; gt?: InputMaybe; @@ -358,6 +344,7 @@ export type Cron = { attempts: Scalars['Int']['output']; createdAt: Scalars['String']['output']; cronExpr: Scalars['String']['output']; + cronTimezone: Scalars['String']['output']; enabled: Scalars['Boolean']['output']; id: Scalars['Int']['output']; lastError?: Maybe; @@ -380,12 +367,14 @@ export type Cron = { updatedAt: Scalars['String']['output']; }; + export type CronSubscriberTaskArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type CronSystemTaskArgs = { filter?: InputMaybe; orderBy?: InputMaybe; @@ -397,6 +386,7 @@ export type CronBasic = { attempts: Scalars['Int']['output']; createdAt: Scalars['String']['output']; cronExpr: Scalars['String']['output']; + cronTimezone: Scalars['String']['output']; enabled: Scalars['Boolean']['output']; id: Scalars['Int']['output']; lastError?: Maybe; @@ -434,6 +424,7 @@ export type CronFilterInput = { attempts?: InputMaybe; createdAt?: InputMaybe; cronExpr?: InputMaybe; + cronTimezone?: InputMaybe; enabled?: InputMaybe; id?: InputMaybe; lastError?: InputMaybe; @@ -455,6 +446,7 @@ export type CronFilterInput = { export type CronInsertInput = { cronExpr: Scalars['String']['input']; + cronTimezone: Scalars['String']['input']; enabled?: InputMaybe; maxAttempts?: InputMaybe; subscriberTaskCron?: InputMaybe; @@ -466,6 +458,7 @@ export type CronOrderInput = { attempts?: InputMaybe; createdAt?: InputMaybe; cronExpr?: InputMaybe; + cronTimezone?: InputMaybe; enabled?: InputMaybe; id?: InputMaybe; lastError?: InputMaybe; @@ -488,11 +481,10 @@ export const CronStatusEnum = { Completed: 'completed', Failed: 'failed', Pending: 'pending', - Running: 'running', + Running: 'running' } as const; -export type CronStatusEnum = - (typeof CronStatusEnum)[keyof typeof CronStatusEnum]; +export type CronStatusEnum = typeof CronStatusEnum[keyof typeof CronStatusEnum]; export type CronStatusEnumFilterInput = { eq?: InputMaybe; gt?: InputMaybe; @@ -508,6 +500,7 @@ export type CronStatusEnumFilterInput = { export type CronUpdateInput = { cronExpr?: InputMaybe; + cronTimezone?: InputMaybe; enabled?: InputMaybe; maxAttempts?: InputMaybe; priority?: InputMaybe; @@ -521,11 +514,10 @@ export type CursorInput = { export const DownloadMimeEnum = { Applicationoctetstream: 'applicationoctetstream', - Applicationxbittorrent: 'applicationxbittorrent', + Applicationxbittorrent: 'applicationxbittorrent' } as const; -export type DownloadMimeEnum = - (typeof DownloadMimeEnum)[keyof typeof DownloadMimeEnum]; +export type DownloadMimeEnum = typeof DownloadMimeEnum[keyof typeof DownloadMimeEnum]; export type DownloadMimeEnumFilterInput = { eq?: InputMaybe; gt?: InputMaybe; @@ -545,11 +537,10 @@ export const DownloadStatusEnum = { Downloading: 'downloading', Failed: 'failed', Paused: 'paused', - Pending: 'pending', + Pending: 'pending' } as const; -export type DownloadStatusEnum = - (typeof DownloadStatusEnum)[keyof typeof DownloadStatusEnum]; +export type DownloadStatusEnum = typeof DownloadStatusEnum[keyof typeof DownloadStatusEnum]; export type DownloadStatusEnumFilterInput = { eq?: InputMaybe; gt?: InputMaybe; @@ -565,11 +556,10 @@ export type DownloadStatusEnumFilterInput = { export const DownloaderCategoryEnum = { Dandanplay: 'dandanplay', - Qbittorrent: 'qbittorrent', + Qbittorrent: 'qbittorrent' } as const; -export type DownloaderCategoryEnum = - (typeof DownloaderCategoryEnum)[keyof typeof DownloaderCategoryEnum]; +export type DownloaderCategoryEnum = typeof DownloaderCategoryEnum[keyof typeof DownloaderCategoryEnum]; export type DownloaderCategoryEnumFilterInput = { eq?: InputMaybe; gt?: InputMaybe; @@ -598,6 +588,7 @@ export type Downloaders = { username: Scalars['String']['output']; }; + export type DownloadersDownloadArgs = { filter?: InputMaybe; orderBy?: InputMaybe; @@ -809,11 +800,10 @@ export type DownloadsUpdateInput = { }; export const EpisodeTypeEnum = { - Mikan: 'mikan', + Mikan: 'mikan' } as const; -export type EpisodeTypeEnum = - (typeof EpisodeTypeEnum)[keyof typeof EpisodeTypeEnum]; +export type EpisodeTypeEnum = typeof EpisodeTypeEnum[keyof typeof EpisodeTypeEnum]; export type EpisodeTypeEnumFilterInput = { eq?: InputMaybe; gt?: InputMaybe; @@ -859,18 +849,21 @@ export type Episodes = { updatedAt: Scalars['String']['output']; }; + export type EpisodesDownloadArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type EpisodesSubscriptionArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type EpisodesSubscriptionEpisodeArgs = { filter?: InputMaybe; orderBy?: InputMaybe; @@ -1024,11 +1017,10 @@ export type EpisodesUpdateInput = { }; export const FeedSourceEnum = { - SubscriptionEpisode: 'subscription_episode', + SubscriptionEpisode: 'subscription_episode' } as const; -export type FeedSourceEnum = - (typeof FeedSourceEnum)[keyof typeof FeedSourceEnum]; +export type FeedSourceEnum = typeof FeedSourceEnum[keyof typeof FeedSourceEnum]; export type FeedSourceEnumFilterInput = { eq?: InputMaybe; gt?: InputMaybe; @@ -1043,10 +1035,10 @@ export type FeedSourceEnumFilterInput = { }; export const FeedTypeEnum = { - Rss: 'rss', + Rss: 'rss' } as const; -export type FeedTypeEnum = (typeof FeedTypeEnum)[keyof typeof FeedTypeEnum]; +export type FeedTypeEnum = typeof FeedTypeEnum[keyof typeof FeedTypeEnum]; export type FeedTypeEnumFilterInput = { eq?: InputMaybe; gt?: InputMaybe; @@ -1212,200 +1204,247 @@ export type Mutation = { systemTasksRetryOne: SystemTasksBasic; }; + export type MutationBangumiCreateBatchArgs = { data: Array; }; + export type MutationBangumiCreateOneArgs = { data: BangumiInsertInput; }; + export type MutationBangumiDeleteArgs = { filter?: InputMaybe; }; + export type MutationBangumiUpdateArgs = { data: BangumiUpdateInput; filter?: InputMaybe; }; + export type MutationCredential3rdCheckAvailableArgs = { filter?: InputMaybe; }; + export type MutationCredential3rdCreateBatchArgs = { data: Array; }; + export type MutationCredential3rdCreateOneArgs = { data: Credential3rdInsertInput; }; + export type MutationCredential3rdDeleteArgs = { filter?: InputMaybe; }; + export type MutationCredential3rdUpdateArgs = { data: Credential3rdUpdateInput; filter?: InputMaybe; }; + export type MutationCronCreateBatchArgs = { data: Array; }; + export type MutationCronCreateOneArgs = { data: CronInsertInput; }; + export type MutationCronDeleteArgs = { filter?: InputMaybe; }; + export type MutationCronUpdateArgs = { data: CronUpdateInput; filter?: InputMaybe; }; + export type MutationDownloadersCreateBatchArgs = { data: Array; }; + export type MutationDownloadersCreateOneArgs = { data: DownloadersInsertInput; }; + export type MutationDownloadersDeleteArgs = { filter?: InputMaybe; }; + export type MutationDownloadersUpdateArgs = { data: DownloadersUpdateInput; filter?: InputMaybe; }; + export type MutationDownloadsCreateBatchArgs = { data: Array; }; + export type MutationDownloadsCreateOneArgs = { data: DownloadsInsertInput; }; + export type MutationDownloadsDeleteArgs = { filter?: InputMaybe; }; + export type MutationDownloadsUpdateArgs = { data: DownloadsUpdateInput; filter?: InputMaybe; }; + export type MutationEpisodesCreateBatchArgs = { data: Array; }; + export type MutationEpisodesCreateOneArgs = { data: EpisodesInsertInput; }; + export type MutationEpisodesDeleteArgs = { filter?: InputMaybe; }; + export type MutationEpisodesUpdateArgs = { data: EpisodesUpdateInput; filter?: InputMaybe; }; + export type MutationFeedsCreateBatchArgs = { data: Array; }; + export type MutationFeedsCreateOneArgs = { data: FeedsInsertInput; }; + export type MutationFeedsDeleteArgs = { filter?: InputMaybe; }; + export type MutationFeedsUpdateArgs = { data: FeedsUpdateInput; filter?: InputMaybe; }; + export type MutationSubscriberTasksCreateOneArgs = { data: SubscriberTasksInsertInput; }; + export type MutationSubscriberTasksDeleteArgs = { filter?: InputMaybe; }; + export type MutationSubscriberTasksRetryOneArgs = { filter?: InputMaybe; }; + export type MutationSubscriptionBangumiCreateBatchArgs = { data: Array; }; + export type MutationSubscriptionBangumiCreateOneArgs = { data: SubscriptionBangumiInsertInput; }; + export type MutationSubscriptionBangumiDeleteArgs = { filter?: InputMaybe; }; + export type MutationSubscriptionBangumiUpdateArgs = { data: SubscriptionBangumiUpdateInput; filter?: InputMaybe; }; + export type MutationSubscriptionEpisodeCreateBatchArgs = { data: Array; }; + export type MutationSubscriptionEpisodeCreateOneArgs = { data: SubscriptionEpisodeInsertInput; }; + export type MutationSubscriptionEpisodeDeleteArgs = { filter?: InputMaybe; }; + export type MutationSubscriptionEpisodeUpdateArgs = { data: SubscriptionEpisodeUpdateInput; filter?: InputMaybe; }; + export type MutationSubscriptionsCreateBatchArgs = { data: Array; }; + export type MutationSubscriptionsCreateOneArgs = { data: SubscriptionsInsertInput; }; + export type MutationSubscriptionsDeleteArgs = { filter?: InputMaybe; }; + export type MutationSubscriptionsUpdateArgs = { data: SubscriptionsUpdateInput; filter?: InputMaybe; }; + export type MutationSystemTasksCreateOneArgs = { data: SystemTasksInsertInput; }; + export type MutationSystemTasksDeleteArgs = { filter?: InputMaybe; }; + export type MutationSystemTasksRetryOneArgs = { filter?: InputMaybe; }; @@ -1417,10 +1456,10 @@ export type OffsetInput = { export const OrderByEnum = { Asc: 'ASC', - Desc: 'DESC', + Desc: 'DESC' } as const; -export type OrderByEnum = (typeof OrderByEnum)[keyof typeof OrderByEnum]; +export type OrderByEnum = typeof OrderByEnum[keyof typeof OrderByEnum]; export type PageInfo = { __typename?: 'PageInfo'; endCursor?: Maybe; @@ -1466,82 +1505,96 @@ export type Query = { systemTasks: SystemTasksConnection; }; + export type Query_Sea_Orm_Entity_MetadataArgs = { table_name: Scalars['String']['input']; }; + export type QueryBangumiArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type QueryCredential3rdArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type QueryCronArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type QueryDownloadersArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type QueryDownloadsArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type QueryEpisodesArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type QueryFeedsArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type QuerySubscriberTasksArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type QuerySubscribersArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type QuerySubscriptionBangumiArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type QuerySubscriptionEpisodeArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type QuerySubscriptionsArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type QuerySystemTasksArgs = { filter?: InputMaybe; orderBy?: InputMaybe; @@ -1578,20 +1631,17 @@ export const SubscriberTaskStatusEnum = { Killed: 'Killed', Pending: 'Pending', Running: 'Running', - Scheduled: 'Scheduled', + Scheduled: 'Scheduled' } as const; -export type SubscriberTaskStatusEnum = - (typeof SubscriberTaskStatusEnum)[keyof typeof SubscriberTaskStatusEnum]; +export type SubscriberTaskStatusEnum = typeof SubscriberTaskStatusEnum[keyof typeof SubscriberTaskStatusEnum]; export const SubscriberTaskTypeEnum = { SyncOneSubscriptionFeedsFull: 'sync_one_subscription_feeds_full', - SyncOneSubscriptionFeedsIncremental: - 'sync_one_subscription_feeds_incremental', - SyncOneSubscriptionSources: 'sync_one_subscription_sources', + SyncOneSubscriptionFeedsIncremental: 'sync_one_subscription_feeds_incremental', + SyncOneSubscriptionSources: 'sync_one_subscription_sources' } as const; -export type SubscriberTaskTypeEnum = - (typeof SubscriberTaskTypeEnum)[keyof typeof SubscriberTaskTypeEnum]; +export type SubscriberTaskTypeEnum = typeof SubscriberTaskTypeEnum[keyof typeof SubscriberTaskTypeEnum]; export type SubscriberTasks = { __typename?: 'SubscriberTasks'; attempts: Scalars['Int']['output']; @@ -1707,48 +1757,56 @@ export type Subscribers = { updatedAt: Scalars['String']['output']; }; + export type SubscribersBangumiArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscribersCredential3rdArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscribersDownloaderArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscribersEpisodeArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscribersFeedArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscribersSubscriberTaskArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscribersSubscriptionArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscribersSystemTaskArgs = { filter?: InputMaybe; orderBy?: InputMaybe; @@ -1848,11 +1906,10 @@ export type SubscriptionBangumiUpdateInput = { export const SubscriptionCategoryEnum = { MikanBangumi: 'mikan_bangumi', MikanSeason: 'mikan_season', - MikanSubscriber: 'mikan_subscriber', + MikanSubscriber: 'mikan_subscriber' } as const; -export type SubscriptionCategoryEnum = - (typeof SubscriptionCategoryEnum)[keyof typeof SubscriptionCategoryEnum]; +export type SubscriptionCategoryEnum = typeof SubscriptionCategoryEnum[keyof typeof SubscriptionCategoryEnum]; export type SubscriptionCategoryEnumFilterInput = { eq?: InputMaybe; gt?: InputMaybe; @@ -1950,42 +2007,49 @@ export type Subscriptions = { updatedAt: Scalars['String']['output']; }; + export type SubscriptionsBangumiArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscriptionsCronArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscriptionsEpisodeArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscriptionsFeedArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscriptionsSubscriberTaskArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscriptionsSubscriptionBangumiArgs = { filter?: InputMaybe; orderBy?: InputMaybe; pagination?: InputMaybe; }; + export type SubscriptionsSubscriptionEpisodeArgs = { filter?: InputMaybe; orderBy?: InputMaybe; @@ -2074,18 +2138,16 @@ export const SystemTaskStatusEnum = { Killed: 'Killed', Pending: 'Pending', Running: 'Running', - Scheduled: 'Scheduled', + Scheduled: 'Scheduled' } as const; -export type SystemTaskStatusEnum = - (typeof SystemTaskStatusEnum)[keyof typeof SystemTaskStatusEnum]; +export type SystemTaskStatusEnum = typeof SystemTaskStatusEnum[keyof typeof SystemTaskStatusEnum]; export const SystemTaskTypeEnum = { OptimizeImage: 'optimize_image', - Test: 'test', + Test: 'test' } as const; -export type SystemTaskTypeEnum = - (typeof SystemTaskTypeEnum)[keyof typeof SystemTaskTypeEnum]; +export type SystemTaskTypeEnum = typeof SystemTaskTypeEnum[keyof typeof SystemTaskTypeEnum]; export type SystemTasks = { __typename?: 'SystemTasks'; attempts: Scalars['Int']['output']; @@ -2200,110 +2262,44 @@ export type GetCredential3rdQueryVariables = Exact<{ pagination?: InputMaybe; }>; -export type GetCredential3rdQuery = { - __typename?: 'Query'; - credential3rd: { - __typename?: 'Credential3rdConnection'; - nodes: Array<{ - __typename?: 'Credential3rd'; - id: number; - cookies?: string | null; - username?: string | null; - password?: string | null; - userAgent?: string | null; - createdAt: string; - updatedAt: string; - credentialType: Credential3rdTypeEnum; - }>; - paginationInfo?: { - __typename?: 'PaginationInfo'; - total: number; - pages: number; - } | null; - }; -}; + +export type GetCredential3rdQuery = { __typename?: 'Query', credential3rd: { __typename?: 'Credential3rdConnection', nodes: Array<{ __typename?: 'Credential3rd', id: number, cookies?: string | null, username?: string | null, password?: string | null, userAgent?: string | null, createdAt: string, updatedAt: string, credentialType: Credential3rdTypeEnum }>, paginationInfo?: { __typename?: 'PaginationInfo', total: number, pages: number } | null } }; export type InsertCredential3rdMutationVariables = Exact<{ data: Credential3rdInsertInput; }>; -export type InsertCredential3rdMutation = { - __typename?: 'Mutation'; - credential3rdCreateOne: { - __typename?: 'Credential3rdBasic'; - id: number; - cookies?: string | null; - username?: string | null; - password?: string | null; - userAgent?: string | null; - createdAt: string; - updatedAt: string; - credentialType: Credential3rdTypeEnum; - }; -}; + +export type InsertCredential3rdMutation = { __typename?: 'Mutation', credential3rdCreateOne: { __typename?: 'Credential3rdBasic', id: number, cookies?: string | null, username?: string | null, password?: string | null, userAgent?: string | null, createdAt: string, updatedAt: string, credentialType: Credential3rdTypeEnum } }; export type UpdateCredential3rdMutationVariables = Exact<{ data: Credential3rdUpdateInput; filter: Credential3rdFilterInput; }>; -export type UpdateCredential3rdMutation = { - __typename?: 'Mutation'; - credential3rdUpdate: Array<{ - __typename?: 'Credential3rdBasic'; - id: number; - cookies?: string | null; - username?: string | null; - password?: string | null; - userAgent?: string | null; - createdAt: string; - updatedAt: string; - credentialType: Credential3rdTypeEnum; - }>; -}; + +export type UpdateCredential3rdMutation = { __typename?: 'Mutation', credential3rdUpdate: Array<{ __typename?: 'Credential3rdBasic', id: number, cookies?: string | null, username?: string | null, password?: string | null, userAgent?: string | null, createdAt: string, updatedAt: string, credentialType: Credential3rdTypeEnum }> }; export type DeleteCredential3rdMutationVariables = Exact<{ filter: Credential3rdFilterInput; }>; -export type DeleteCredential3rdMutation = { - __typename?: 'Mutation'; - credential3rdDelete: number; -}; + +export type DeleteCredential3rdMutation = { __typename?: 'Mutation', credential3rdDelete: number }; export type GetCredential3rdDetailQueryVariables = Exact<{ id: Scalars['Int']['input']; }>; -export type GetCredential3rdDetailQuery = { - __typename?: 'Query'; - credential3rd: { - __typename?: 'Credential3rdConnection'; - nodes: Array<{ - __typename?: 'Credential3rd'; - id: number; - cookies?: string | null; - username?: string | null; - password?: string | null; - userAgent?: string | null; - createdAt: string; - updatedAt: string; - credentialType: Credential3rdTypeEnum; - }>; - }; -}; + +export type GetCredential3rdDetailQuery = { __typename?: 'Query', credential3rd: { __typename?: 'Credential3rdConnection', nodes: Array<{ __typename?: 'Credential3rd', id: number, cookies?: string | null, username?: string | null, password?: string | null, userAgent?: string | null, createdAt: string, updatedAt: string, credentialType: Credential3rdTypeEnum }> } }; export type CheckCredential3rdAvailableMutationVariables = Exact<{ filter: Credential3rdFilterInput; }>; -export type CheckCredential3rdAvailableMutation = { - __typename?: 'Mutation'; - credential3rdCheckAvailable: { - __typename?: 'Credential3rdCheckAvailableInfo'; - available: boolean; - }; -}; + +export type CheckCredential3rdAvailableMutation = { __typename?: 'Mutation', credential3rdCheckAvailable: { __typename?: 'Credential3rdCheckAvailableInfo', available: boolean } }; export type GetCronsQueryVariables = Exact<{ filter: CronFilterInput; @@ -2311,92 +2307,36 @@ export type GetCronsQueryVariables = Exact<{ pagination: PaginationInput; }>; -export type GetCronsQuery = { - __typename?: 'Query'; - cron: { - __typename?: 'CronConnection'; - nodes: Array<{ - __typename?: 'Cron'; - id: number; - cronExpr: string; - nextRun?: string | null; - lastRun?: string | null; - lastError?: string | null; - status: CronStatusEnum; - lockedAt?: string | null; - lockedBy?: string | null; - createdAt: string; - updatedAt: string; - timeoutMs?: number | null; - maxAttempts: number; - priority: number; - attempts: number; - subscriberTaskCron?: SubscriberTaskType | null; - subscriberTask: { - __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 GetCronsQuery = { __typename?: 'Query', cron: { __typename?: 'CronConnection', nodes: Array<{ __typename?: 'Cron', id: number, cronExpr: string, nextRun?: string | null, lastRun?: string | null, lastError?: string | null, status: CronStatusEnum, lockedAt?: string | null, lockedBy?: string | null, createdAt: string, updatedAt: string, timeoutMs?: number | null, maxAttempts: number, priority: number, attempts: number, subscriberTaskCron?: SubscriberTaskType | null, subscriberTask: { __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 DeleteCronsMutationVariables = Exact<{ filter: CronFilterInput; }>; -export type DeleteCronsMutation = { - __typename?: 'Mutation'; - cronDelete: number; -}; + +export type DeleteCronsMutation = { __typename?: 'Mutation', cronDelete: number }; + +export type InsertCronMutationVariables = Exact<{ + data: CronInsertInput; +}>; + + +export type InsertCronMutation = { __typename?: 'Mutation', cronCreateOne: { __typename?: 'CronBasic', id: number, cronExpr: string, nextRun?: string | null, lastRun?: string | null, lastError?: string | null, status: CronStatusEnum, lockedAt?: string | null, lockedBy?: string | null, createdAt: string, updatedAt: string, timeoutMs?: number | null, maxAttempts: number, priority: number, attempts: number, subscriberTaskCron?: SubscriberTaskType | null } }; export type InsertFeedMutationVariables = Exact<{ data: FeedsInsertInput; }>; -export type InsertFeedMutation = { - __typename?: 'Mutation'; - feedsCreateOne: { - __typename?: 'FeedsBasic'; - id: number; - createdAt: string; - updatedAt: string; - feedType: FeedTypeEnum; - token: string; - }; -}; + +export type InsertFeedMutation = { __typename?: 'Mutation', feedsCreateOne: { __typename?: 'FeedsBasic', id: number, createdAt: string, updatedAt: string, feedType: FeedTypeEnum, token: string } }; export type DeleteFeedMutationVariables = Exact<{ filter: FeedsFilterInput; }>; -export type DeleteFeedMutation = { - __typename?: 'Mutation'; - feedsDelete: number; -}; + +export type DeleteFeedMutation = { __typename?: 'Mutation', feedsDelete: number }; export type GetSubscriptionsQueryVariables = Exact<{ filter: SubscriptionsFilterInput; @@ -2404,162 +2344,37 @@ export type GetSubscriptionsQueryVariables = Exact<{ pagination: PaginationInput; }>; -export type GetSubscriptionsQuery = { - __typename?: 'Query'; - subscriptions: { - __typename?: 'SubscriptionsConnection'; - nodes: Array<{ - __typename?: 'Subscriptions'; - id: number; - createdAt: string; - updatedAt: string; - displayName: string; - category: SubscriptionCategoryEnum; - sourceUrl: string; - enabled: boolean; - credentialId?: number | null; - }>; - paginationInfo?: { - __typename?: 'PaginationInfo'; - total: number; - pages: number; - } | null; - }; -}; + +export type GetSubscriptionsQuery = { __typename?: 'Query', subscriptions: { __typename?: 'SubscriptionsConnection', nodes: Array<{ __typename?: 'Subscriptions', id: number, createdAt: string, updatedAt: string, displayName: string, category: SubscriptionCategoryEnum, sourceUrl: string, enabled: boolean, credentialId?: number | null }>, paginationInfo?: { __typename?: 'PaginationInfo', total: number, pages: number } | null } }; export type InsertSubscriptionMutationVariables = Exact<{ data: SubscriptionsInsertInput; }>; -export type InsertSubscriptionMutation = { - __typename?: 'Mutation'; - subscriptionsCreateOne: { - __typename?: 'SubscriptionsBasic'; - id: number; - createdAt: string; - updatedAt: string; - displayName: string; - category: SubscriptionCategoryEnum; - sourceUrl: string; - enabled: boolean; - credentialId?: number | null; - }; -}; + +export type InsertSubscriptionMutation = { __typename?: 'Mutation', subscriptionsCreateOne: { __typename?: 'SubscriptionsBasic', id: number, createdAt: string, updatedAt: string, displayName: string, category: SubscriptionCategoryEnum, sourceUrl: string, enabled: boolean, credentialId?: number | null } }; export type UpdateSubscriptionsMutationVariables = Exact<{ data: SubscriptionsUpdateInput; filter: SubscriptionsFilterInput; }>; -export type UpdateSubscriptionsMutation = { - __typename?: 'Mutation'; - subscriptionsUpdate: Array<{ - __typename?: 'SubscriptionsBasic'; - id: number; - createdAt: string; - updatedAt: string; - displayName: string; - category: SubscriptionCategoryEnum; - sourceUrl: string; - enabled: boolean; - }>; -}; + +export type UpdateSubscriptionsMutation = { __typename?: 'Mutation', subscriptionsUpdate: Array<{ __typename?: 'SubscriptionsBasic', id: number, createdAt: string, updatedAt: string, displayName: string, category: SubscriptionCategoryEnum, sourceUrl: string, enabled: boolean }> }; export type DeleteSubscriptionsMutationVariables = Exact<{ filter?: InputMaybe; }>; -export type DeleteSubscriptionsMutation = { - __typename?: 'Mutation'; - subscriptionsDelete: number; -}; + +export type DeleteSubscriptionsMutation = { __typename?: 'Mutation', subscriptionsDelete: number }; export type GetSubscriptionDetailQueryVariables = Exact<{ id: Scalars['Int']['input']; }>; -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; - cron: { - __typename?: 'CronConnection'; - nodes: Array<{ - __typename?: 'Cron'; - id: number; - cronExpr: string; - nextRun?: string | null; - lastRun?: string | null; - lastError?: string | null; - status: CronStatusEnum; - lockedAt?: string | null; - lockedBy?: string | null; - createdAt: string; - updatedAt: string; - timeoutMs?: number | null; - maxAttempts: number; - priority: number; - attempts: number; - subscriberTaskCron?: SubscriberTaskType | 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 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, cron: { __typename?: 'CronConnection', nodes: Array<{ __typename?: 'Cron', id: number, cronExpr: string, nextRun?: string | null, lastRun?: string | null, lastError?: string | null, status: CronStatusEnum, lockedAt?: string | null, lockedBy?: string | null, createdAt: string, updatedAt: string, timeoutMs?: number | null, maxAttempts: number, priority: number, attempts: number, subscriberTaskCron?: SubscriberTaskType | 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; @@ -2567,1983 +2382,48 @@ export type GetTasksQueryVariables = Exact<{ pagination: PaginationInput; }>; -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 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 InsertSubscriberTaskMutation = { __typename?: 'Mutation', subscriberTasksCreateOne: { __typename?: 'SubscriberTasksBasic', id: string } }; export type DeleteTasksMutationVariables = Exact<{ filter: SubscriberTasksFilterInput; }>; -export type DeleteTasksMutation = { - __typename?: 'Mutation'; - subscriberTasksDelete: number; -}; + +export type DeleteTasksMutation = { __typename?: 'Mutation', subscriberTasksDelete: number }; export type RetryTasksMutationVariables = Exact<{ filter: SubscriberTasksFilterInput; }>; -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 ->; -export const InsertCredential3rdDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'mutation', - name: { kind: 'Name', value: 'InsertCredential3rd' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'data' } }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Credential3rdInsertInput' }, - }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'credential3rdCreateOne' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'data' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'data' }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'cookies' } }, - { kind: 'Field', name: { kind: 'Name', value: 'username' } }, - { kind: 'Field', name: { kind: 'Name', value: 'password' } }, - { kind: 'Field', name: { kind: 'Name', value: 'userAgent' } }, - { kind: 'Field', name: { kind: 'Name', value: 'createdAt' } }, - { kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'credentialType' }, - }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode< - InsertCredential3rdMutation, - InsertCredential3rdMutationVariables ->; -export const UpdateCredential3rdDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'mutation', - name: { kind: 'Name', value: 'UpdateCredential3rd' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'data' } }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Credential3rdUpdateInput' }, - }, - }, - }, - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'filter' }, - }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Credential3rdFilterInput' }, - }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'credential3rdUpdate' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'data' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'data' }, - }, - }, - { - kind: 'Argument', - name: { kind: 'Name', value: 'filter' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'filter' }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'cookies' } }, - { kind: 'Field', name: { kind: 'Name', value: 'username' } }, - { kind: 'Field', name: { kind: 'Name', value: 'password' } }, - { kind: 'Field', name: { kind: 'Name', value: 'userAgent' } }, - { kind: 'Field', name: { kind: 'Name', value: 'createdAt' } }, - { kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'credentialType' }, - }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode< - UpdateCredential3rdMutation, - UpdateCredential3rdMutationVariables ->; -export const DeleteCredential3rdDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'mutation', - name: { kind: 'Name', value: 'DeleteCredential3rd' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'filter' }, - }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Credential3rdFilterInput' }, - }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'credential3rdDelete' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'filter' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'filter' }, - }, - }, - ], - }, - ], - }, - }, - ], -} as unknown as DocumentNode< - DeleteCredential3rdMutation, - DeleteCredential3rdMutationVariables ->; -export const GetCredential3rdDetailDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'GetCredential3rdDetail' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'id' } }, - type: { - kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'Int' } }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'credential3rd' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: '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: 'cookies' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'username' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'password' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'userAgent' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'createdAt' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'updatedAt' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'credentialType' }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode< - GetCredential3rdDetailQuery, - GetCredential3rdDetailQueryVariables ->; -export const CheckCredential3rdAvailableDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'mutation', - name: { kind: 'Name', value: 'CheckCredential3rdAvailable' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'filter' }, - }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Credential3rdFilterInput' }, - }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'credential3rdCheckAvailable' }, - 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: 'available' } }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode< - CheckCredential3rdAvailableMutation, - CheckCredential3rdAvailableMutationVariables ->; -export const GetCronsDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'GetCrons' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'filter' }, - }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'CronFilterInput' }, - }, - }, - }, - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'orderBy' }, - }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'CronOrderInput' }, - }, - }, - }, - { - 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: 'cron' }, - 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: 'cronExpr' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'nextRun' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'lastRun' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'lastError' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'status' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'lockedAt' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'lockedBy' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'createdAt' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'updatedAt' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'timeoutMs' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'maxAttempts' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'priority' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'attempts' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'subscriberTaskCron' }, - }, - { - 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: '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; -export const DeleteCronsDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'mutation', - name: { kind: 'Name', value: 'DeleteCrons' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'filter' }, - }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'CronFilterInput' }, - }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'cronDelete' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'filter' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'filter' }, - }, - }, - ], - }, - ], - }, - }, - ], -} as unknown as DocumentNode; -export const InsertFeedDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'mutation', - name: { kind: 'Name', value: 'InsertFeed' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'data' } }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'FeedsInsertInput' }, - }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'feedsCreateOne' }, - 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: 'feedType' } }, - { kind: 'Field', name: { kind: 'Name', value: 'token' } }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode; -export const DeleteFeedDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'mutation', - name: { kind: 'Name', value: 'DeleteFeed' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'filter' }, - }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'FeedsFilterInput' }, - }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'feedsDelete' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'filter' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'filter' }, - }, - }, - ], - }, - ], - }, - }, - ], -} as unknown as DocumentNode; -export const GetSubscriptionsDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'GetSubscriptions' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'filter' }, - }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'SubscriptionsFilterInput' }, - }, - }, - }, - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'orderBy' }, - }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'SubscriptionsOrderInput' }, - }, - }, - }, - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'pagination' }, - }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'PaginationInput' }, - }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'subscriptions' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'pagination' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'pagination' }, - }, - }, - { - kind: 'Argument', - name: { kind: 'Name', value: '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: 'createdAt' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'updatedAt' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'displayName' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'category' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'sourceUrl' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'enabled' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'credentialId' }, - }, - ], - }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'paginationInfo' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'total' } }, - { kind: 'Field', name: { kind: 'Name', value: 'pages' } }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode< - GetSubscriptionsQuery, - GetSubscriptionsQueryVariables ->; -export const InsertSubscriptionDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'mutation', - name: { kind: 'Name', value: 'InsertSubscription' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'data' } }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'SubscriptionsInsertInput' }, - }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'subscriptionsCreateOne' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'data' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'data' }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'createdAt' } }, - { kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } }, - { kind: 'Field', name: { kind: 'Name', value: 'displayName' } }, - { kind: 'Field', name: { kind: 'Name', value: 'category' } }, - { kind: 'Field', name: { kind: 'Name', value: 'sourceUrl' } }, - { kind: 'Field', name: { kind: 'Name', value: 'enabled' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'credentialId' }, - }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode< - InsertSubscriptionMutation, - InsertSubscriptionMutationVariables ->; -export const UpdateSubscriptionsDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'mutation', - name: { kind: 'Name', value: 'UpdateSubscriptions' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'data' } }, - type: { - kind: 'NonNullType', - type: { - kind: 'NamedType', - name: { kind: 'Name', value: 'SubscriptionsUpdateInput' }, - }, - }, - }, - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: '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: '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: 'cron' }, - 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: 'cronExpr' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'nextRun' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'lastRun' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'lastError' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'status' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'lockedAt' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'lockedBy' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'createdAt' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'updatedAt' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'timeoutMs' }, - }, - { - kind: 'Field', - name: { - kind: 'Name', - value: 'maxAttempts', - }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'priority' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'attempts' }, - }, - { - kind: 'Field', - name: { - kind: 'Name', - value: 'subscriberTaskCron', - }, - }, - ], - }, - }, - ], - }, - }, - { - 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; -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; -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; +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; +export const InsertCredential3rdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"InsertCredential3rd"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Credential3rdInsertInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"credential3rdCreateOne"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"cookies"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"password"}},{"kind":"Field","name":{"kind":"Name","value":"userAgent"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"credentialType"}}]}}]}}]} as unknown as DocumentNode; +export const UpdateCredential3rdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateCredential3rd"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Credential3rdUpdateInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Credential3rdFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"credential3rdUpdate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"cookies"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"password"}},{"kind":"Field","name":{"kind":"Name","value":"userAgent"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"credentialType"}}]}}]}}]} as unknown as DocumentNode; +export const DeleteCredential3rdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteCredential3rd"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Credential3rdFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"credential3rdDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}]}]}}]} as unknown as DocumentNode; +export const GetCredential3rdDetailDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetCredential3rdDetail"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"credential3rd"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"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":"cookies"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"password"}},{"kind":"Field","name":{"kind":"Name","value":"userAgent"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"credentialType"}}]}}]}}]}}]} as unknown as DocumentNode; +export const CheckCredential3rdAvailableDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CheckCredential3rdAvailable"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Credential3rdFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"credential3rdCheckAvailable"},"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":"available"}}]}}]}}]} as unknown as DocumentNode; +export const GetCronsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetCrons"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CronFilterInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CronOrderInput"}}}},{"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":"cron"},"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":"cronExpr"}},{"kind":"Field","name":{"kind":"Name","value":"nextRun"}},{"kind":"Field","name":{"kind":"Name","value":"lastRun"}},{"kind":"Field","name":{"kind":"Name","value":"lastError"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"lockedAt"}},{"kind":"Field","name":{"kind":"Name","value":"lockedBy"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"timeoutMs"}},{"kind":"Field","name":{"kind":"Name","value":"maxAttempts"}},{"kind":"Field","name":{"kind":"Name","value":"priority"}},{"kind":"Field","name":{"kind":"Name","value":"attempts"}},{"kind":"Field","name":{"kind":"Name","value":"subscriberTaskCron"}},{"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":"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; +export const DeleteCronsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteCrons"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CronFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cronDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}]}]}}]} as unknown as DocumentNode; +export const InsertCronDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"InsertCron"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CronInsertInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cronCreateOne"},"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":"cronExpr"}},{"kind":"Field","name":{"kind":"Name","value":"nextRun"}},{"kind":"Field","name":{"kind":"Name","value":"lastRun"}},{"kind":"Field","name":{"kind":"Name","value":"lastError"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"lockedAt"}},{"kind":"Field","name":{"kind":"Name","value":"lockedBy"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"timeoutMs"}},{"kind":"Field","name":{"kind":"Name","value":"maxAttempts"}},{"kind":"Field","name":{"kind":"Name","value":"priority"}},{"kind":"Field","name":{"kind":"Name","value":"attempts"}},{"kind":"Field","name":{"kind":"Name","value":"subscriberTaskCron"}}]}}]}}]} as unknown as DocumentNode; +export const InsertFeedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"InsertFeed"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"FeedsInsertInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"feedsCreateOne"},"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":"feedType"}},{"kind":"Field","name":{"kind":"Name","value":"token"}}]}}]}}]} as unknown as DocumentNode; +export const DeleteFeedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteFeed"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"FeedsFilterInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"feedsDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}]}]}}]} as unknown as DocumentNode; +export const GetSubscriptionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSubscriptions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsFilterInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SubscriptionsOrderInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"PaginationInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subscriptions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"pagination"},"value":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}}},{"kind":"Argument","name":{"kind":"Name","value":"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":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrl"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"credentialId"}}]}},{"kind":"Field","name":{"kind":"Name","value":"paginationInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total"}},{"kind":"Field","name":{"kind":"Name","value":"pages"}}]}}]}}]}}]} as unknown as DocumentNode; +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; +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; +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; +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":"cron"},"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":"cronExpr"}},{"kind":"Field","name":{"kind":"Name","value":"nextRun"}},{"kind":"Field","name":{"kind":"Name","value":"lastRun"}},{"kind":"Field","name":{"kind":"Name","value":"lastError"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"lockedAt"}},{"kind":"Field","name":{"kind":"Name","value":"lockedBy"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"timeoutMs"}},{"kind":"Field","name":{"kind":"Name","value":"maxAttempts"}},{"kind":"Field","name":{"kind":"Name","value":"priority"}},{"kind":"Field","name":{"kind":"Name","value":"attempts"}},{"kind":"Field","name":{"kind":"Name","value":"subscriberTaskCron"}}]}}]}},{"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; +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; +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; +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; +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; \ No newline at end of file diff --git a/apps/webui/src/presentation/routes/_app/credential3rd/detail.$id.tsx b/apps/webui/src/presentation/routes/_app/credential3rd/detail.$id.tsx index ecf2f33..0bfb507 100644 --- a/apps/webui/src/presentation/routes/_app/credential3rd/detail.$id.tsx +++ b/apps/webui/src/presentation/routes/_app/credential3rd/detail.$id.tsx @@ -1,4 +1,3 @@ -import { DetailCardSkeleton } from '@/components/detail-card-skeleton'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { @@ -9,6 +8,7 @@ import { CardTitle, } from '@/components/ui/card'; import { ContainerHeader } from '@/components/ui/container-header'; +import { DetailCardSkeleton } from '@/components/ui/detail-card-skeleton'; import { DetailEmptyView } from '@/components/ui/detail-empty-view'; import { Dialog, DialogTrigger } from '@/components/ui/dialog'; import { Label } from '@/components/ui/label'; diff --git a/apps/webui/src/presentation/routes/_app/credential3rd/edit.$id.tsx b/apps/webui/src/presentation/routes/_app/credential3rd/edit.$id.tsx index e9f90ef..8bb3275 100644 --- a/apps/webui/src/presentation/routes/_app/credential3rd/edit.$id.tsx +++ b/apps/webui/src/presentation/routes/_app/credential3rd/edit.$id.tsx @@ -1,4 +1,3 @@ -import { DetailCardSkeleton } from '@/components/detail-card-skeleton'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { @@ -9,6 +8,7 @@ import { CardTitle, } from '@/components/ui/card'; import { ContainerHeader } from '@/components/ui/container-header'; +import { DetailCardSkeleton } from '@/components/ui/detail-card-skeleton'; import { DetailEmptyView } from '@/components/ui/detail-empty-view'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; diff --git a/apps/webui/src/presentation/routes/_app/subscriptions/-cron-creation.tsx b/apps/webui/src/presentation/routes/_app/subscriptions/-cron-creation.tsx new file mode 100644 index 0000000..bb09e31 --- /dev/null +++ b/apps/webui/src/presentation/routes/_app/subscriptions/-cron-creation.tsx @@ -0,0 +1,152 @@ +import { Cron } from '@/components/domains/cron'; +import { CronMode } from '@/components/domains/cron/types'; +import { + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Spinner } from '@/components/ui/spinner'; +import { INSERT_CRON } from '@/domains/recorder/schema/cron'; +import type { + InsertCronMutation, + InsertCronMutationVariables, +} from '@/infra/graphql/gql/graphql'; +import { useMutation } from '@apollo/client'; +import { useNavigate } from '@tanstack/react-router'; +import { memo, useCallback } from 'react'; +import { toast } from 'sonner'; + +const SUBSCRIPTION_TASK_CRON_PRESETS = [ + { + label: 'Every hour', + value: '0 0 * * * *', + description: 'Runs at the top of every hour', + category: 'common', + }, + { + label: 'Daily at midnight', + value: '0 0 0 * * *', + description: 'Runs once daily at 00:00', + category: 'daily', + }, + { + label: 'Daily at 9 AM', + value: '0 0 9 * * *', + description: 'Runs daily at 9:00 AM', + category: 'daily', + }, + { + label: 'Every Sunday', + value: '0 0 0 * * 0', + description: 'Runs every Sunday at midnight', + category: 'weekly', + }, + { + label: 'First day of month', + value: '0 0 0 1 * *', + description: 'Runs on the 1st day of every month', + category: 'monthly', + }, + { + label: 'Every year', + value: '0 0 0 1 1 *', + description: 'Runs on January 1st every year', + category: 'yearly', + }, +]; + +export type SubscriptionCronCreationViewCompletePayload = { + id: number; +}; + +export interface SubscriptionCronCreationViewProps { + subscriptionId: number; + onComplete: (payload: SubscriptionCronCreationViewCompletePayload) => void; +} + +export const SubscriptionCronCreationView = memo( + ({ subscriptionId, onComplete }: SubscriptionCronCreationViewProps) => { + const [insertCron, { loading: loadingInsert }] = useMutation< + InsertCronMutation, + InsertCronMutationVariables + >(INSERT_CRON, { + onCompleted: (data) => { + toast.success('Cron created'); + onComplete(data.cronCreateOne); + }, + onError: (error) => { + toast.error('Failed to sync subscription', { + description: error.message, + }); + }, + }); + + const loading = loadingInsert; + + return ( +
+ + + {loading && ( +
+ + Creating cron... +
+ )} +
+ ); + } +); + +export interface SubscriptionCronCreationDialogContentProps { + subscriptionId: number; + onCancel?: VoidFunction; +} + +export const SubscriptionCronCreationDialogContent = memo( + ({ + subscriptionId, + onCancel, + }: SubscriptionCronCreationDialogContentProps) => { + const navigate = useNavigate(); + + const handleCreationComplete = useCallback( + (payload: SubscriptionCronCreationViewCompletePayload) => { + navigate({ + to: '/tasks/cron/detail/$id', + params: { + id: `${payload.id}`, + }, + }); + }, + [navigate] + ); + + return ( + + + Create Cron + + Create a cron to execute the subscription. + + +
+ +
+
+ ); + } +); diff --git a/apps/webui/src/presentation/routes/_app/subscriptions/-sync.tsx b/apps/webui/src/presentation/routes/_app/subscriptions/-task-creation.tsx similarity index 75% rename from apps/webui/src/presentation/routes/_app/subscriptions/-sync.tsx rename to apps/webui/src/presentation/routes/_app/subscriptions/-task-creation.tsx index 93ae935..4b8d181 100644 --- a/apps/webui/src/presentation/routes/_app/subscriptions/-sync.tsx +++ b/apps/webui/src/presentation/routes/_app/subscriptions/-task-creation.tsx @@ -18,17 +18,17 @@ import { RefreshCcwIcon } from 'lucide-react'; import { memo, useCallback } from 'react'; import { toast } from 'sonner'; -export type SubscriptionSyncViewCompletePayload = { +export type SubscriptionTaskCreationViewCompletePayload = { id: string; }; -export interface SubscriptionSyncViewProps { - id: number; - onComplete: (payload: SubscriptionSyncViewCompletePayload) => void; +export interface SubscriptionTaskCreationViewProps { + subscriptionId: number; + onComplete: (payload: SubscriptionTaskCreationViewCompletePayload) => void; } -export const SubscriptionSyncView = memo( - ({ id, onComplete }: SubscriptionSyncViewProps) => { +export const SubscriptionTaskCreationView = memo( + ({ subscriptionId, onComplete }: SubscriptionTaskCreationViewProps) => { const [insertSubscriberTask, { loading: loadingInsert }] = useMutation< InsertSubscriberTaskMutation, InsertSubscriberTaskMutationVariables @@ -56,7 +56,7 @@ export const SubscriptionSyncView = memo( variables: { data: { job: { - subscriptionId: id, + subscriptionId: subscriptionId, taskType: SubscriberTaskTypeEnum.SyncOneSubscriptionSources, }, }, @@ -75,7 +75,7 @@ export const SubscriptionSyncView = memo( variables: { data: { job: { - subscriptionId: id, + subscriptionId: subscriptionId, taskType: SubscriberTaskTypeEnum.SyncOneSubscriptionFeedsIncremental, }, @@ -95,7 +95,7 @@ export const SubscriptionSyncView = memo( variables: { data: { job: { - subscriptionId: id, + subscriptionId: subscriptionId, taskType: SubscriberTaskTypeEnum.SyncOneSubscriptionFeedsFull, }, @@ -111,7 +111,7 @@ export const SubscriptionSyncView = memo( {loading && (
- Syncing... + Running...
)} @@ -119,18 +119,20 @@ export const SubscriptionSyncView = memo( } ); -export interface SubscriptionSyncDialogContentProps { - id: number; +export interface SubscriptionTaskCreationDialogContentProps { + subscriptionId: number; onCancel?: VoidFunction; - isCron?: boolean; } -export const SubscriptionSyncDialogContent = memo( - ({ id, onCancel }: SubscriptionSyncDialogContentProps) => { +export const SubscriptionTaskCreationDialogContent = memo( + ({ + subscriptionId, + onCancel, + }: SubscriptionTaskCreationDialogContentProps) => { const navigate = useNavigate(); - const handleSyncComplete = useCallback( - (payload: SubscriptionSyncViewCompletePayload) => { + const handleCreationComplete = useCallback( + (payload: SubscriptionTaskCreationViewCompletePayload) => { navigate({ to: '/tasks/detail/$id', params: { @@ -144,12 +146,15 @@ export const SubscriptionSyncDialogContent = memo( return ( - Sync Subscription + Run Task - Sync the subscription with sources and feeds. + Run the task for the subscription. - + ); } diff --git a/apps/webui/src/presentation/routes/_app/subscriptions/detail.$id.tsx b/apps/webui/src/presentation/routes/_app/subscriptions/detail.$id.tsx index 56e241d..463fc1b 100644 --- a/apps/webui/src/presentation/routes/_app/subscriptions/detail.$id.tsx +++ b/apps/webui/src/presentation/routes/_app/subscriptions/detail.$id.tsx @@ -1,4 +1,3 @@ -import { DetailCardSkeleton } from '@/components/detail-card-skeleton'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { @@ -9,6 +8,7 @@ import { CardTitle, } from '@/components/ui/card'; import { ContainerHeader } from '@/components/ui/container-header'; +import { DetailCardSkeleton } from '@/components/ui/detail-card-skeleton'; import { DetailEmptyView } from '@/components/ui/detail-empty-view'; import { Dialog, DialogTrigger } from '@/components/ui/dialog'; import { Img } from '@/components/ui/img'; @@ -47,7 +47,8 @@ import { import { useMemo } from 'react'; import { toast } from 'sonner'; import { prettyTaskType } from '../tasks/-pretty-task-type'; -import { SubscriptionSyncDialogContent } from './-sync'; +import { SubscriptionCronCreationDialogContent } from './-cron-creation'; +import { SubscriptionTaskCreationDialogContent } from './-task-creation'; export const Route = createFileRoute('/_app/subscriptions/detail/$id')({ component: SubscriptionDetailRouteComponent, @@ -404,19 +405,18 @@ function SubscriptionDetailRouteComponent() { } > - Crons + More - @@ -477,17 +477,17 @@ function SubscriptionDetailRouteComponent() { } > - Tasks + More - diff --git a/apps/webui/src/presentation/routes/_app/subscriptions/edit.$id.tsx b/apps/webui/src/presentation/routes/_app/subscriptions/edit.$id.tsx index fa38b13..5a4c698 100644 --- a/apps/webui/src/presentation/routes/_app/subscriptions/edit.$id.tsx +++ b/apps/webui/src/presentation/routes/_app/subscriptions/edit.$id.tsx @@ -1,4 +1,3 @@ -import { DetailCardSkeleton } from '@/components/detail-card-skeleton'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { @@ -9,6 +8,7 @@ import { CardTitle, } from '@/components/ui/card'; import { ContainerHeader } from '@/components/ui/container-header'; +import { DetailCardSkeleton } from '@/components/ui/detail-card-skeleton'; import { DetailEmptyView } from '@/components/ui/detail-empty-view'; import { FormFieldErrors } from '@/components/ui/form-field-errors'; import { Input } from '@/components/ui/input'; diff --git a/apps/webui/src/presentation/routes/_app/subscriptions/manage.tsx b/apps/webui/src/presentation/routes/_app/subscriptions/manage.tsx index 5d2d211..e62179d 100644 --- a/apps/webui/src/presentation/routes/_app/subscriptions/manage.tsx +++ b/apps/webui/src/presentation/routes/_app/subscriptions/manage.tsx @@ -47,7 +47,7 @@ import { format } from 'date-fns'; import { Plus } from 'lucide-react'; import { useMemo, useState } from 'react'; import { toast } from 'sonner'; -import { SubscriptionSyncDialogContent } from './-sync'; +import { SubscriptionTaskCreationDialogContent } from './-task-creation'; export const Route = createFileRoute('/_app/subscriptions/manage')({ component: SubscriptionManageRouteComponent, @@ -238,7 +238,9 @@ function SubscriptionManageRouteComponent() { Sync - + ), diff --git a/apps/webui/src/presentation/routes/_app/tasks/detail.$id.tsx b/apps/webui/src/presentation/routes/_app/tasks/detail.$id.tsx index 4cc8d53..b3a2516 100644 --- a/apps/webui/src/presentation/routes/_app/tasks/detail.$id.tsx +++ b/apps/webui/src/presentation/routes/_app/tasks/detail.$id.tsx @@ -1,4 +1,3 @@ -import { DetailCardSkeleton } from '@/components/detail-card-skeleton'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { @@ -9,6 +8,7 @@ import { CardTitle, } from '@/components/ui/card'; import { ContainerHeader } from '@/components/ui/container-header'; +import { DetailCardSkeleton } from '@/components/ui/detail-card-skeleton'; import { DetailEmptyView } from '@/components/ui/detail-empty-view'; import { Label } from '@/components/ui/label'; import { QueryErrorView } from '@/components/ui/query-error-view'; diff --git a/biome.json b/biome.json index 71ec6aa..1d06af7 100644 --- a/biome.json +++ b/biome.json @@ -44,6 +44,14 @@ } }, "overrides": [ + { + "include": ["**/tsconfig.json", "**/tsconfig.*.json"], + "json": { + "parser": { + "allowComments": true + } + } + }, { "include": ["apps/webui/src/infra/graphql/gql/**/*"], "linter": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 69d6496..aa1f59d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,6 +89,12 @@ importers: '@corvu/resizable': specifier: ^0.2.5 version: 0.2.5(solid-js@1.9.7) + '@datasert/cronjs-matcher': + specifier: ^1.4.0 + version: 1.4.0 + '@datasert/cronjs-parser': + specifier: ^1.4.0 + version: 1.4.0 '@graphiql/toolkit': specifier: ^0.11.3 version: 0.11.3(@types/node@24.0.10)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@6.0.5)))(graphql@16.11.0) @@ -263,6 +269,9 @@ importers: tailwind-merge: specifier: ^3.3.1 version: 3.3.1 + tailwind-scrollbar: + specifier: ^4.0.2 + version: 4.0.2(react@19.1.0)(tailwindcss@4.1.10) tailwindcss: specifier: ^4.1.10 version: 4.1.10 @@ -712,6 +721,12 @@ packages: resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} engines: {node: '>=18'} + '@datasert/cronjs-matcher@1.4.0': + resolution: {integrity: sha512-5wAAKYfClZQDWjOeGReEnGLlBKds5K0CitnTv17sH32X4PSuck1dysX71zzCgrm0JCSpobDNg4b292ewhoy6ww==} + + '@datasert/cronjs-parser@1.4.0': + resolution: {integrity: sha512-zHGlrWanS4Zjgf0aMi/sp/HTSa2xWDEtXW9xshhlGf/jPx3zTIqfX14PZnoFF7XVOwzC49Zy0SFWG90rlRY36Q==} + '@date-fns/tz@1.2.0': resolution: {integrity: sha512-LBrd7MiJZ9McsOgxqWX7AaxrDjcFVjWH/tIKJd7pnR7McaslGYOP1QmmiBXdJH/H/yLCT+rcQ7FaPBUxRGUtrg==} @@ -3167,6 +3182,9 @@ packages: '@types/node@24.0.10': resolution: {integrity: sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA==} + '@types/prismjs@1.26.5': + resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==} + '@types/react-dom@19.1.6': resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==} peerDependencies: @@ -5008,6 +5026,10 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + luxon@3.6.1: + resolution: {integrity: sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==} + engines: {node: '>=12'} + magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} @@ -5467,6 +5489,11 @@ packages: engines: {node: '>=14'} hasBin: true + prism-react-renderer@2.4.1: + resolution: {integrity: sha512-ey8Ls/+Di31eqzUxC46h8MksNuGx/n0AAC8uKpwFau4RPDYLuE3EXTp8N8G2vX2N7UC/+IXeNUnlWBGGcAG+Ig==} + peerDependencies: + react: '>=16.0.0' + prismjs@1.29.0: resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} engines: {node: '>=6'} @@ -6162,6 +6189,12 @@ packages: tailwind-merge@3.3.1: resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==} + tailwind-scrollbar@4.0.2: + resolution: {integrity: sha512-wAQiIxAPqk0MNTPptVe/xoyWi27y+NRGnTwvn4PQnbvB9kp8QUBiGl/wsfoVBHnQxTmhXJSNt9NHTmcz9EivFA==} + engines: {node: '>=12.13.0'} + peerDependencies: + tailwindcss: 4.x + tailwindcss@4.1.10: resolution: {integrity: sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==} @@ -7216,6 +7249,13 @@ snapshots: '@csstools/css-tokenizer@3.0.4': optional: true + '@datasert/cronjs-matcher@1.4.0': + dependencies: + '@datasert/cronjs-parser': 1.4.0 + luxon: 3.6.1 + + '@datasert/cronjs-parser@1.4.0': {} + '@date-fns/tz@1.2.0': {} '@emnapi/runtime@1.4.3': @@ -9812,6 +9852,8 @@ snapshots: dependencies: undici-types: 7.8.0 + '@types/prismjs@1.26.5': {} + '@types/react-dom@19.1.6(@types/react@19.0.1)': dependencies: '@types/react': 19.0.1 @@ -10219,7 +10261,7 @@ snapshots: browserslist@4.25.0: dependencies: - caniuse-lite: 1.0.30001721 + caniuse-lite: 1.0.30001726 electron-to-chromium: 1.5.165 node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.25.0) @@ -10282,8 +10324,7 @@ snapshots: caniuse-lite@1.0.30001721: {} - caniuse-lite@1.0.30001726: - optional: true + caniuse-lite@1.0.30001726: {} capital-case@1.0.4: dependencies: @@ -11892,6 +11933,8 @@ snapshots: dependencies: react: 19.1.0 + luxon@3.6.1: {} + magic-string@0.30.17: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -12317,6 +12360,12 @@ snapshots: prettier@3.5.3: {} + prism-react-renderer@2.4.1(react@19.1.0): + dependencies: + '@types/prismjs': 1.26.5 + clsx: 2.1.1 + react: 19.1.0 + prismjs@1.29.0: {} prismjs@1.30.0: {} @@ -13154,6 +13203,13 @@ snapshots: tailwind-merge@3.3.1: {} + tailwind-scrollbar@4.0.2(react@19.1.0)(tailwindcss@4.1.10): + dependencies: + prism-react-renderer: 2.4.1(react@19.1.0) + tailwindcss: 4.1.10 + transitivePeerDependencies: + - react + tailwindcss@4.1.10: {} tapable@2.2.2: {} diff --git a/tsconfig.base.json b/tsconfig.base.json index 8946064..c06246f 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -19,8 +19,9 @@ "target": "ES2020", "strictNullChecks": true, "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, + // controlled by biome + "noUnusedLocals": false, + "noUnusedParameters": false, "useDefineForClassFields": true } } diff --git a/tsconfig.json b/tsconfig.json index 9616a0b..0c97c74 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,6 @@ { "path": "./apps/webui" }, - { "path": "./packages/email" },