Compare commits

...

5 Commits

Author SHA1 Message Date
gamer147
c25f59a4b4 [FA-misc] Add IJobStatusUpdate event contract and publishing helper 2026-01-30 16:32:01 -05:00
gamer147
be1ebbea39 [FA-misc] Add JobStatus enum 2026-01-30 16:31:42 -05:00
67521d6530 Merge pull request '[FA-misc] Fix issues with novel imports' (#63) from epic/FA-misc_MassTransit into master
All checks were successful
CI / build-backend (push) Successful in 1m6s
CI / build-frontend (push) Successful in 43s
Build Gateway / build-subgraphs (map[name:novel-service project:FictionArchive.Service.NovelService subgraph:Novel]) (push) Successful in 49s
Build Gateway / build-subgraphs (map[name:scheduler-service project:FictionArchive.Service.SchedulerService subgraph:Scheduler]) (push) Successful in 45s
Build Gateway / build-subgraphs (map[name:translation-service project:FictionArchive.Service.TranslationService subgraph:Translation]) (push) Successful in 47s
Build Gateway / build-subgraphs (map[name:user-service project:FictionArchive.Service.UserService subgraph:User]) (push) Successful in 51s
Build Gateway / build-subgraphs (map[name:usernoveldata-service project:FictionArchive.Service.UserNovelDataService subgraph:UserNovelData]) (push) Successful in 47s
Release / build-and-push (map[dockerfile:FictionArchive.Service.FileService/Dockerfile name:file-service]) (push) Successful in 2m3s
Release / build-and-push (map[dockerfile:FictionArchive.Service.NovelService/Dockerfile name:novel-service]) (push) Successful in 1m52s
Release / build-and-push (map[dockerfile:FictionArchive.Service.SchedulerService/Dockerfile name:scheduler-service]) (push) Successful in 1m44s
Release / build-and-push (map[dockerfile:FictionArchive.Service.TranslationService/Dockerfile name:translation-service]) (push) Successful in 1m46s
Release / build-and-push (map[dockerfile:FictionArchive.Service.UserNovelDataService/Dockerfile name:usernoveldata-service]) (push) Successful in 1m38s
Release / build-and-push (map[dockerfile:FictionArchive.Service.UserService/Dockerfile name:user-service]) (push) Successful in 1m40s
Release / build-frontend (push) Successful in 1m44s
Build Gateway / build-gateway (push) Successful in 3m29s
Reviewed-on: #63
2026-01-30 17:55:40 +00:00
gamer147
a6242fdb2a [FA-misc] Fix release.yml
All checks were successful
CI / build-backend (pull_request) Successful in 1m7s
CI / build-frontend (pull_request) Successful in 44s
2026-01-30 12:53:10 -05:00
gamer147
3c8c8c8707 [FA-misc] Fix issues with novel imports
All checks were successful
CI / build-backend (pull_request) Successful in 1m46s
CI / build-frontend (pull_request) Successful in 44s
2026-01-30 12:48:40 -05:00
14 changed files with 138 additions and 23 deletions

View File

@@ -25,8 +25,6 @@ jobs:
dockerfile: FictionArchive.Service.FileService/Dockerfile dockerfile: FictionArchive.Service.FileService/Dockerfile
- name: scheduler-service - name: scheduler-service
dockerfile: FictionArchive.Service.SchedulerService/Dockerfile dockerfile: FictionArchive.Service.SchedulerService/Dockerfile
- name: authentication-service
dockerfile: FictionArchive.Service.AuthenticationService/Dockerfile
- name: usernoveldata-service - name: usernoveldata-service
dockerfile: FictionArchive.Service.UserNovelDataService/Dockerfile dockerfile: FictionArchive.Service.UserNovelDataService/Dockerfile
steps: steps:

View File

@@ -0,0 +1,9 @@
namespace FictionArchive.Common.Enums;
public enum JobStatus
{
Failed = -1,
Pending = 0,
InProgress = 1,
Completed = 2
}

View File

@@ -38,7 +38,8 @@ public class FileUploadRequestCreatedConsumer : IConsumer<IFileUploadRequestCrea
var putObjectRequest = new PutObjectRequest var putObjectRequest = new PutObjectRequest
{ {
BucketName = _s3Configuration.Bucket, BucketName = _s3Configuration.Bucket,
Key = message.FilePath Key = message.FilePath,
UseChunkEncoding = false
}; };
using var memoryStream = new MemoryStream(message.FileData); using var memoryStream = new MemoryStream(message.FileData);

View File

@@ -38,7 +38,7 @@ public class NovelImportSagaTests
var importId = Guid.NewGuid(); var importId = Guid.NewGuid();
await harness.Bus.Publish<INovelImportRequested>(new NovelImportRequested(importId, "https://example.com/novel")); await harness.Bus.Publish<INovelImportRequested>(new NovelImportRequested(importId, "https://example.com/novel"));
await harness.Bus.Publish<INovelMetadataImported>(new NovelMetadataImported(importId, 1, 0)); await harness.Bus.Publish<INovelMetadataImported>(new NovelMetadataImported(importId, 1, 0, false));
var sagaHarness = harness.GetSagaStateMachineHarness<NovelImportSaga, NovelImportSagaState>(); var sagaHarness = harness.GetSagaStateMachineHarness<NovelImportSaga, NovelImportSagaState>();
(await sagaHarness.Exists(importId, x => x.Completed)).HasValue.Should().BeTrue(); (await sagaHarness.Exists(importId, x => x.Completed)).HasValue.Should().BeTrue();
@@ -56,7 +56,7 @@ public class NovelImportSagaTests
var importId = Guid.NewGuid(); var importId = Guid.NewGuid();
await harness.Bus.Publish<INovelImportRequested>(new NovelImportRequested(importId, "https://example.com/novel")); await harness.Bus.Publish<INovelImportRequested>(new NovelImportRequested(importId, "https://example.com/novel"));
await harness.Bus.Publish<INovelMetadataImported>(new NovelMetadataImported(importId, 1, 2)); await harness.Bus.Publish<INovelMetadataImported>(new NovelMetadataImported(importId, 1, 2, false));
var sagaHarness = harness.GetSagaStateMachineHarness<NovelImportSaga, NovelImportSagaState>(); var sagaHarness = harness.GetSagaStateMachineHarness<NovelImportSaga, NovelImportSagaState>();
(await sagaHarness.Exists(importId, x => x.Processing)).HasValue.Should().BeTrue(); (await sagaHarness.Exists(importId, x => x.Processing)).HasValue.Should().BeTrue();
@@ -71,7 +71,7 @@ public class NovelImportSagaTests
var importId = Guid.NewGuid(); var importId = Guid.NewGuid();
await harness.Bus.Publish<INovelImportRequested>(new NovelImportRequested(importId, "https://example.com/novel")); await harness.Bus.Publish<INovelImportRequested>(new NovelImportRequested(importId, "https://example.com/novel"));
await harness.Bus.Publish<INovelMetadataImported>(new NovelMetadataImported(importId, 1, 2)); await harness.Bus.Publish<INovelMetadataImported>(new NovelMetadataImported(importId, 1, 2, false));
await harness.Bus.Publish<IChapterPullCompleted>(new ChapterPullCompleted(importId, 1, 1)); await harness.Bus.Publish<IChapterPullCompleted>(new ChapterPullCompleted(importId, 1, 1));
await harness.Bus.Publish<IChapterPullCompleted>(new ChapterPullCompleted(importId, 2, 0)); await harness.Bus.Publish<IChapterPullCompleted>(new ChapterPullCompleted(importId, 2, 0));
await harness.Bus.Publish<IFileUploadRequestStatusUpdate>(new FileUploadRequestStatusUpdate( await harness.Bus.Publish<IFileUploadRequestStatusUpdate>(new FileUploadRequestStatusUpdate(
@@ -81,6 +81,48 @@ public class NovelImportSagaTests
(await sagaHarness.Exists(importId, x => x.Completed)).HasValue.Should().BeTrue(); (await sagaHarness.Exists(importId, x => x.Completed)).HasValue.Should().BeTrue();
} }
[Fact]
public async Task Should_transition_to_processing_when_cover_image_queued_with_no_chapters()
{
await using var provider = CreateTestProvider();
var harness = provider.GetRequiredService<ITestHarness>();
await harness.Start();
var importId = Guid.NewGuid();
await harness.Bus.Publish<INovelImportRequested>(new NovelImportRequested(importId, "https://example.com/novel"));
await harness.Bus.Publish<INovelMetadataImported>(new NovelMetadataImported(importId, 1, 0, true));
var sagaHarness = harness.GetSagaStateMachineHarness<NovelImportSaga, NovelImportSagaState>();
(await sagaHarness.Exists(importId, x => x.Processing)).HasValue.Should().BeTrue();
}
[Fact]
public async Task Should_complete_when_chapters_pulled_images_uploaded_and_cover_uploaded()
{
await using var provider = CreateTestProvider();
var harness = provider.GetRequiredService<ITestHarness>();
await harness.Start();
var importId = Guid.NewGuid();
await harness.Bus.Publish<INovelImportRequested>(new NovelImportRequested(importId, "https://example.com/novel"));
await harness.Bus.Publish<INovelMetadataImported>(new NovelMetadataImported(importId, 1, 1, true));
await harness.Bus.Publish<IChapterPullCompleted>(new ChapterPullCompleted(importId, 1, 0));
var sagaHarness = harness.GetSagaStateMachineHarness<NovelImportSaga, NovelImportSagaState>();
// Should still be processing - cover image not yet uploaded
(await sagaHarness.Exists(importId, x => x.Processing)).HasValue.Should().BeTrue();
// Upload cover image
await harness.Bus.Publish<IFileUploadRequestStatusUpdate>(new FileUploadRequestStatusUpdate(
importId, Guid.NewGuid(), RequestStatus.Success, "https://cdn.example.com/cover.jpg", null));
(await sagaHarness.Exists(importId, x => x.Completed)).HasValue.Should().BeTrue();
(await harness.Published.Any<INovelImportCompleted>(x =>
x.Context.Message.ImportId == importId && x.Context.Message.Success)).Should().BeTrue();
}
private ServiceProvider CreateTestProvider() private ServiceProvider CreateTestProvider()
{ {
return new ServiceCollection() return new ServiceCollection()

View File

@@ -0,0 +1,3 @@
namespace FictionArchive.Service.NovelService.Contracts;
public record ImportNovelResult(Guid ImportId, string NovelUrl);

View File

@@ -16,7 +16,7 @@ public class Mutation
{ {
[Error<InvalidOperationException>] [Error<InvalidOperationException>]
[Authorize] [Authorize]
public async Task<NovelImportRequested> ImportNovel(string novelUrl, NovelUpdateService service) public async Task<ImportNovelResult> ImportNovel(string novelUrl, NovelUpdateService service)
{ {
return await service.QueueNovelImport(novelUrl); return await service.QueueNovelImport(novelUrl);
} }

View File

@@ -57,9 +57,10 @@ public class NovelImportSaga : MassTransitStateMachine<NovelImportSagaState>
{ {
ctx.Saga.NovelId = ctx.Message.NovelId; ctx.Saga.NovelId = ctx.Message.NovelId;
ctx.Saga.ExpectedChapters = ctx.Message.ChaptersPendingPull; ctx.Saga.ExpectedChapters = ctx.Message.ChaptersPendingPull;
ctx.Saga.ExpectedImages += ctx.Message.CoverImageQueued ? 1 : 0;
}) })
.IfElse( .IfElse(
ctx => ctx.Saga.ExpectedChapters == 0, ctx => ctx.Saga.ExpectedChapters == 0 && !ctx.Message.CoverImageQueued,
thenBinder => thenBinder thenBinder => thenBinder
.Then(ctx => ctx.Saga.CompletedAt = _clock.GetCurrentInstant()) .Then(ctx => ctx.Saga.CompletedAt = _clock.GetCurrentInstant())
.TransitionTo(Completed) .TransitionTo(Completed)

View File

@@ -427,15 +427,18 @@ public class NovelUpdateService
.Where(c => c.Body?.Texts == null || !c.Body.Texts.Any()) .Where(c => c.Body?.Texts == null || !c.Body.Texts.Any())
.ToList(); .ToList();
var hasCoverToUpload = shouldPublishCoverEvent && novel.CoverImage != null && metadata.CoverImage != null;
// Publish metadata imported event for saga // Publish metadata imported event for saga
await _publishEndpoint.Publish<INovelMetadataImported>(new NovelMetadataImported( await _publishEndpoint.Publish<INovelMetadataImported>(new NovelMetadataImported(
importId, importId,
novel.Id, novel.Id,
chaptersNeedingPull.Count chaptersNeedingPull.Count,
hasCoverToUpload
)); ));
// Publish cover image event if needed // Publish cover image event if needed
if (shouldPublishCoverEvent && novel.CoverImage != null && metadata.CoverImage != null) if (hasCoverToUpload)
{ {
await _publishEndpoint.Publish<IFileUploadRequestCreated>(new FileUploadRequestCreated( await _publishEndpoint.Publish<IFileUploadRequestCreated>(new FileUploadRequestCreated(
importId, importId,
@@ -568,7 +571,7 @@ public class NovelUpdateService
await _dbContext.SaveChangesAsync(); await _dbContext.SaveChangesAsync();
} }
public async Task<NovelImportRequested> QueueNovelImport(string novelUrl) public async Task<ImportNovelResult> QueueNovelImport(string novelUrl)
{ {
var importId = Guid.NewGuid(); var importId = Guid.NewGuid();
var activeImport = new ActiveImport var activeImport = new ActiveImport
@@ -590,7 +593,7 @@ public class NovelUpdateService
var importNovelRequestEvent = new NovelImportRequested(importId, novelUrl); var importNovelRequestEvent = new NovelImportRequested(importId, novelUrl);
await _publishEndpoint.Publish<INovelImportRequested>(importNovelRequestEvent); await _publishEndpoint.Publish<INovelImportRequested>(importNovelRequestEvent);
return importNovelRequestEvent; return new ImportNovelResult(importId, novelUrl);
} }
public async Task<ChapterPullRequested> QueueChapterPull(Guid importId, uint novelId, uint volumeId, uint chapterOrder) public async Task<ChapterPullRequested> QueueChapterPull(Guid importId, uint novelId, uint volumeId, uint chapterOrder)

View File

@@ -0,0 +1,23 @@
using FictionArchive.Common.Enums;
namespace FictionArchive.Service.Shared.Contracts.Events;
public interface IJobStatusUpdate
{
Guid JobId { get; }
Guid? ParentJobId { get; }
string JobType { get; }
string DisplayName { get; }
JobStatus Status { get; }
string? ErrorMessage { get; }
Dictionary<string, string>? Metadata { get; }
}
public record JobStatusUpdate(
Guid JobId,
Guid? ParentJobId,
string JobType,
string DisplayName,
JobStatus Status,
string? ErrorMessage,
Dictionary<string, string>? Metadata) : IJobStatusUpdate;

View File

@@ -5,6 +5,7 @@ public interface INovelMetadataImported
Guid ImportId { get; } Guid ImportId { get; }
uint NovelId { get; } uint NovelId { get; }
int ChaptersPendingPull { get; } int ChaptersPendingPull { get; }
bool CoverImageQueued { get; }
} }
public record NovelMetadataImported(Guid ImportId, uint NovelId, int ChaptersPendingPull) : INovelMetadataImported; public record NovelMetadataImported(Guid ImportId, uint NovelId, int ChaptersPendingPull, bool CoverImageQueued) : INovelMetadataImported;

View File

@@ -0,0 +1,20 @@
using FictionArchive.Common.Enums;
using FictionArchive.Service.Shared.Contracts.Events;
using MassTransit;
namespace FictionArchive.Service.Shared.Extensions;
public static class JobStatusPublisher
{
public static Task ReportJobStatus(
this IPublishEndpoint endpoint,
Guid jobId,
string jobType,
string displayName,
JobStatus status,
Guid? parentJobId = null,
string? errorMessage = null,
Dictionary<string, string>? metadata = null)
=> endpoint.Publish<IJobStatusUpdate>(new JobStatusUpdate(
jobId, parentJobId, jobType, displayName, status, errorMessage, metadata));
}

View File

@@ -39,7 +39,13 @@
return; return;
} }
if (result.data?.importNovel?.novelUpdateRequestedEvent) { const mutationErrors = result.data?.importNovel?.errors;
if (mutationErrors && mutationErrors.length > 0) {
error = mutationErrors[0].message;
return;
}
if (result.data?.importNovel?.importNovelResult) {
success = true; success = true;
setTimeout(() => { setTimeout(() => {
handleClose(); handleClose();

View File

@@ -200,12 +200,20 @@ export type ImageDtoSortInput = {
newPath?: InputMaybe<SortEnumType>; newPath?: InputMaybe<SortEnumType>;
}; };
export type ImportNovelError = InvalidOperationError;
export type ImportNovelInput = { export type ImportNovelInput = {
novelUrl: Scalars['String']['input']; novelUrl: Scalars['String']['input'];
}; };
export type ImportNovelPayload = { export type ImportNovelPayload = {
novelImportRequested: Maybe<NovelImportRequested>; errors: Maybe<Array<ImportNovelError>>;
importNovelResult: Maybe<ImportNovelResult>;
};
export type ImportNovelResult = {
importId: Scalars['UUID']['output'];
novelUrl: Scalars['String']['output'];
}; };
export type InstantFilterInput = { export type InstantFilterInput = {
@@ -463,11 +471,6 @@ export type NovelDtoSortInput = {
url?: InputMaybe<SortEnumType>; url?: InputMaybe<SortEnumType>;
}; };
export type NovelImportRequested = {
importId: Scalars['UUID']['output'];
novelUrl: Scalars['String']['output'];
};
export const NovelStatus = { export const NovelStatus = {
Abandoned: 'ABANDONED', Abandoned: 'ABANDONED',
Completed: 'COMPLETED', Completed: 'COMPLETED',
@@ -1013,7 +1016,7 @@ export type ImportNovelMutationVariables = Exact<{
}>; }>;
export type ImportNovelMutation = { importNovel: { novelImportRequested: { importId: any, novelUrl: string } | null } }; export type ImportNovelMutation = { importNovel: { importNovelResult: { importId: any, novelUrl: string } | null, errors: Array<{ message: string }> | null } };
export type InviteUserMutationVariables = Exact<{ export type InviteUserMutationVariables = Exact<{
input: InviteUserInput; input: InviteUserInput;
@@ -1117,7 +1120,7 @@ export const AddToReadingListDocument = {"kind":"Document","definitions":[{"kind
export const CreateReadingListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateReadingList"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateReadingListInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createReadingList"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"readingListPayload"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"success"}},{"kind":"Field","name":{"kind":"Name","value":"readingList"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"itemCount"}},{"kind":"Field","name":{"kind":"Name","value":"createdTime"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Error"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<CreateReadingListMutation, CreateReadingListMutationVariables>; export const CreateReadingListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateReadingList"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateReadingListInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createReadingList"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"readingListPayload"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"success"}},{"kind":"Field","name":{"kind":"Name","value":"readingList"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"itemCount"}},{"kind":"Field","name":{"kind":"Name","value":"createdTime"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Error"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<CreateReadingListMutation, CreateReadingListMutationVariables>;
export const DeleteNovelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteNovel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DeleteNovelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteNovel"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"boolean"}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Error"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<DeleteNovelMutation, DeleteNovelMutationVariables>; export const DeleteNovelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteNovel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DeleteNovelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteNovel"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"boolean"}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Error"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<DeleteNovelMutation, DeleteNovelMutationVariables>;
export const DeleteReadingListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteReadingList"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DeleteReadingListInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteReadingList"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"success"}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Error"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<DeleteReadingListMutation, DeleteReadingListMutationVariables>; export const DeleteReadingListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteReadingList"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DeleteReadingListInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteReadingList"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"success"}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Error"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<DeleteReadingListMutation, DeleteReadingListMutationVariables>;
export const ImportNovelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"ImportNovel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ImportNovelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"importNovel"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"novelImportRequested"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"importId"}},{"kind":"Field","name":{"kind":"Name","value":"novelUrl"}}]}}]}}]}}]} as unknown as DocumentNode<ImportNovelMutation, ImportNovelMutationVariables>; export const ImportNovelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"ImportNovel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ImportNovelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"importNovel"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"importNovelResult"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"importId"}},{"kind":"Field","name":{"kind":"Name","value":"novelUrl"}}]}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"InvalidOperationError"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<ImportNovelMutation, ImportNovelMutationVariables>;
export const InviteUserDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"InviteUser"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"InviteUserInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"inviteUser"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userDto"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"email"}}]}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"InvalidOperationError"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<InviteUserMutation, InviteUserMutationVariables>; export const InviteUserDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"InviteUser"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"InviteUserInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"inviteUser"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userDto"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"email"}}]}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"InvalidOperationError"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<InviteUserMutation, InviteUserMutationVariables>;
export const RemoveBookmarkDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RemoveBookmark"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoveBookmarkInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"removeBookmark"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"bookmarkPayload"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"success"}}]}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Error"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<RemoveBookmarkMutation, RemoveBookmarkMutationVariables>; export const RemoveBookmarkDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RemoveBookmark"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoveBookmarkInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"removeBookmark"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"bookmarkPayload"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"success"}}]}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Error"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<RemoveBookmarkMutation, RemoveBookmarkMutationVariables>;
export const RemoveFromReadingListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RemoveFromReadingList"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoveFromReadingListInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"removeFromReadingList"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"readingListPayload"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"success"}},{"kind":"Field","name":{"kind":"Name","value":"readingList"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"itemCount"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Error"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<RemoveFromReadingListMutation, RemoveFromReadingListMutationVariables>; export const RemoveFromReadingListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RemoveFromReadingList"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoveFromReadingListInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"removeFromReadingList"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"readingListPayload"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"success"}},{"kind":"Field","name":{"kind":"Name","value":"readingList"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"itemCount"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Error"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<RemoveFromReadingListMutation, RemoveFromReadingListMutationVariables>;

View File

@@ -1,8 +1,13 @@
mutation ImportNovel($input: ImportNovelInput!) { mutation ImportNovel($input: ImportNovelInput!) {
importNovel(input: $input) { importNovel(input: $input) {
novelImportRequested { importNovelResult {
importId importId
novelUrl novelUrl
} }
errors {
... on InvalidOperationError {
message
}
}
} }
} }