feat(core): invoice service (#8124)

This commit is contained in:
EYHN
2024-09-05 23:56:58 +08:00
committed by GitHub
parent 9cbe416c2c
commit 74cd175d37
12 changed files with 229 additions and 394 deletions
@@ -0,0 +1,78 @@
import type { InvoicesQuery } from '@affine/graphql';
import {
backoffRetry,
catchErrorInto,
effect,
Entity,
exhaustMapSwitchUntilChanged,
fromPromise,
LiveData,
onComplete,
onStart,
} from '@toeverything/infra';
import { EMPTY, map, mergeMap } from 'rxjs';
import { isBackendError, isNetworkError } from '../error';
import type { InvoicesStore } from '../stores/invoices';
export type Invoice = NonNullable<
InvoicesQuery['currentUser']
>['invoices'][number];
export class Invoices extends Entity {
constructor(private readonly store: InvoicesStore) {
super();
}
pageNum$ = new LiveData(0);
invoiceCount$ = new LiveData<number | undefined>(undefined);
pageInvoices$ = new LiveData<Invoice[] | undefined>(undefined);
isLoading$ = new LiveData(false);
error$ = new LiveData<any>(null);
readonly PAGE_SIZE = 8;
readonly revalidate = effect(
map(() => this.pageNum$.value),
exhaustMapSwitchUntilChanged(
(a, b) => a === b,
pageNum => {
return fromPromise(async signal => {
return this.store.fetchInvoices(
pageNum * this.PAGE_SIZE,
this.PAGE_SIZE,
signal
);
}).pipe(
mergeMap(data => {
this.invoiceCount$.setValue(data.invoiceCount);
this.pageInvoices$.setValue(data.invoices);
return EMPTY;
}),
backoffRetry({
when: isNetworkError,
count: Infinity,
}),
backoffRetry({
when: isBackendError,
}),
catchErrorInto(this.error$),
onStart(() => {
this.pageInvoices$.setValue(undefined);
this.isLoading$.setValue(true);
}),
onComplete(() => this.isLoading$.setValue(false))
);
}
)
);
setPageNum(pageNum: number) {
this.pageNum$.setValue(pageNum);
}
override dispose(): void {
this.revalidate.unsubscribe();
}
}
@@ -1,3 +1,4 @@
export type { Invoice } from './entities/invoices';
export type { AuthAccountInfo } from './entities/session';
export {
BackendError,
@@ -8,6 +9,7 @@ export {
export { AccountChanged, AuthService } from './services/auth';
export { FetchService } from './services/fetch';
export { GraphQLService } from './services/graphql';
export { InvoicesService } from './services/invoices';
export { ServerConfigService } from './services/server-config';
export { SubscriptionService } from './services/subscription';
export { UserCopilotQuotaService } from './services/user-copilot-quota';
@@ -25,6 +27,7 @@ import {
} from '@toeverything/infra';
import { CloudDocMeta } from './entities/cloud-doc-meta';
import { Invoices } from './entities/invoices';
import { ServerConfig } from './entities/server-config';
import { AuthSession } from './entities/session';
import { Subscription } from './entities/subscription';
@@ -36,6 +39,7 @@ import { AuthService } from './services/auth';
import { CloudDocMetaService } from './services/cloud-doc-meta';
import { FetchService } from './services/fetch';
import { GraphQLService } from './services/graphql';
import { InvoicesService } from './services/invoices';
import { ServerConfigService } from './services/server-config';
import { SubscriptionService } from './services/subscription';
import { UserCopilotQuotaService } from './services/user-copilot-quota';
@@ -44,6 +48,7 @@ import { UserQuotaService } from './services/user-quota';
import { WebSocketService } from './services/websocket';
import { AuthStore } from './stores/auth';
import { CloudDocMetaStore } from './stores/cloud-doc-meta';
import { InvoicesStore } from './stores/invoices';
import { ServerConfigStore } from './stores/server-config';
import { SubscriptionStore } from './stores/subscription';
import { UserCopilotQuotaStore } from './stores/user-copilot-quota';
@@ -78,6 +83,9 @@ export function configureCloudModule(framework: Framework) {
.service(UserFeatureService)
.entity(UserFeature, [AuthService, UserFeatureStore])
.store(UserFeatureStore, [GraphQLService])
.service(InvoicesService)
.store(InvoicesStore, [GraphQLService])
.entity(Invoices, [InvoicesStore])
.scope(WorkspaceScope)
.scope(DocScope)
.service(CloudDocMetaService)
@@ -0,0 +1,7 @@
import { Service } from '@toeverything/infra';
import { Invoices } from '../entities/invoices';
export class InvoicesService extends Service {
invoices = this.framework.createEntity(Invoices);
}
@@ -0,0 +1,24 @@
import { invoicesQuery } from '@affine/graphql';
import { Store } from '@toeverything/infra';
import type { GraphQLService } from '../services/graphql';
export class InvoicesStore extends Store {
constructor(private readonly graphqlService: GraphQLService) {
super();
}
async fetchInvoices(skip: number, take: number, signal?: AbortSignal) {
const data = await this.graphqlService.gql({
query: invoicesQuery,
variables: { skip, take },
context: { signal },
});
if (!data.currentUser) {
throw new Error('No logged in');
}
return data.currentUser;
}
}
@@ -5,12 +5,13 @@ import {
catchErrorInto,
effect,
Entity,
exhaustMapSwitchUntilChanged,
fromPromise,
LiveData,
onComplete,
onStart,
} from '@toeverything/infra';
import { distinctUntilChanged, EMPTY, map, mergeMap, switchMap } from 'rxjs';
import { EMPTY, map, mergeMap } from 'rxjs';
import { isBackendError, isNetworkError } from '../../cloud';
import type { WorkspaceMembersStore } from '../stores/members';
@@ -37,36 +38,38 @@ export class WorkspaceMembers extends Entity {
readonly revalidate = effect(
map(() => this.pageNum$.value),
distinctUntilChanged<number>(),
switchMap(pageNum => {
return fromPromise(async signal => {
return this.store.fetchMembers(
this.workspaceService.workspace.id,
pageNum * this.PAGE_SIZE,
this.PAGE_SIZE,
signal
exhaustMapSwitchUntilChanged(
(a, b) => a === b,
pageNum => {
return fromPromise(async signal => {
return this.store.fetchMembers(
this.workspaceService.workspace.id,
pageNum * this.PAGE_SIZE,
this.PAGE_SIZE,
signal
);
}).pipe(
mergeMap(data => {
this.memberCount$.setValue(data.memberCount);
this.pageMembers$.setValue(data.members);
return EMPTY;
}),
backoffRetry({
when: isNetworkError,
count: Infinity,
}),
backoffRetry({
when: isBackendError,
}),
catchErrorInto(this.error$),
onStart(() => {
this.pageMembers$.setValue(undefined);
this.isLoading$.setValue(true);
}),
onComplete(() => this.isLoading$.setValue(false))
);
}).pipe(
mergeMap(data => {
this.memberCount$.setValue(data.memberCount);
this.pageMembers$.setValue(data.members);
return EMPTY;
}),
backoffRetry({
when: isNetworkError,
count: Infinity,
}),
backoffRetry({
when: isBackendError,
}),
catchErrorInto(this.error$),
onStart(() => {
this.pageMembers$.setValue(undefined);
this.isLoading$.setValue(true);
}),
onComplete(() => this.isLoading$.setValue(false))
);
})
}
)
);
setPageNum(pageNum: number) {