mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
add updateSubscription api
This commit is contained in:
parent
abd59f0527
commit
56a27878dc
5 changed files with 218 additions and 25 deletions
|
|
@ -1292,6 +1292,7 @@ export type Mutation = {
|
|||
updatePage: UpdatePageResult;
|
||||
updateReminder: UpdateReminderResult;
|
||||
updateSharedComment: UpdateSharedCommentResult;
|
||||
updateSubscription: UpdateSubscriptionResult;
|
||||
updateUser: UpdateUserResult;
|
||||
updateUserProfile: UpdateUserProfileResult;
|
||||
uploadFileRequest: UploadFileRequestResult;
|
||||
|
|
@ -1619,6 +1620,11 @@ export type MutationUpdateSharedCommentArgs = {
|
|||
};
|
||||
|
||||
|
||||
export type MutationUpdateSubscriptionArgs = {
|
||||
input: UpdateSubscriptionInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationUpdateUserArgs = {
|
||||
input: UpdateUserInput;
|
||||
};
|
||||
|
|
@ -2995,6 +3001,31 @@ export type UpdateSharedCommentSuccess = {
|
|||
sharedComment: Scalars['String'];
|
||||
};
|
||||
|
||||
export type UpdateSubscriptionError = {
|
||||
__typename?: 'UpdateSubscriptionError';
|
||||
errorCodes: Array<UpdateSubscriptionErrorCode>;
|
||||
};
|
||||
|
||||
export enum UpdateSubscriptionErrorCode {
|
||||
BadRequest = 'BAD_REQUEST',
|
||||
NotFound = 'NOT_FOUND',
|
||||
Unauthorized = 'UNAUTHORIZED'
|
||||
}
|
||||
|
||||
export type UpdateSubscriptionInput = {
|
||||
description?: InputMaybe<Scalars['String']>;
|
||||
id: Scalars['ID'];
|
||||
lastFetchedAt?: InputMaybe<Scalars['Date']>;
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type UpdateSubscriptionResult = UpdateSubscriptionError | UpdateSubscriptionSuccess;
|
||||
|
||||
export type UpdateSubscriptionSuccess = {
|
||||
__typename?: 'UpdateSubscriptionSuccess';
|
||||
subscription: Subscription;
|
||||
};
|
||||
|
||||
export type UpdateUserError = {
|
||||
__typename?: 'UpdateUserError';
|
||||
errorCodes: Array<UpdateUserErrorCode>;
|
||||
|
|
@ -3759,6 +3790,11 @@ export type ResolversTypes = {
|
|||
UpdateSharedCommentInput: UpdateSharedCommentInput;
|
||||
UpdateSharedCommentResult: ResolversTypes['UpdateSharedCommentError'] | ResolversTypes['UpdateSharedCommentSuccess'];
|
||||
UpdateSharedCommentSuccess: ResolverTypeWrapper<UpdateSharedCommentSuccess>;
|
||||
UpdateSubscriptionError: ResolverTypeWrapper<UpdateSubscriptionError>;
|
||||
UpdateSubscriptionErrorCode: UpdateSubscriptionErrorCode;
|
||||
UpdateSubscriptionInput: UpdateSubscriptionInput;
|
||||
UpdateSubscriptionResult: ResolversTypes['UpdateSubscriptionError'] | ResolversTypes['UpdateSubscriptionSuccess'];
|
||||
UpdateSubscriptionSuccess: ResolverTypeWrapper<UpdateSubscriptionSuccess>;
|
||||
UpdateUserError: ResolverTypeWrapper<UpdateUserError>;
|
||||
UpdateUserErrorCode: UpdateUserErrorCode;
|
||||
UpdateUserInput: UpdateUserInput;
|
||||
|
|
@ -4154,6 +4190,10 @@ export type ResolversParentTypes = {
|
|||
UpdateSharedCommentInput: UpdateSharedCommentInput;
|
||||
UpdateSharedCommentResult: ResolversParentTypes['UpdateSharedCommentError'] | ResolversParentTypes['UpdateSharedCommentSuccess'];
|
||||
UpdateSharedCommentSuccess: UpdateSharedCommentSuccess;
|
||||
UpdateSubscriptionError: UpdateSubscriptionError;
|
||||
UpdateSubscriptionInput: UpdateSubscriptionInput;
|
||||
UpdateSubscriptionResult: ResolversParentTypes['UpdateSubscriptionError'] | ResolversParentTypes['UpdateSubscriptionSuccess'];
|
||||
UpdateSubscriptionSuccess: UpdateSubscriptionSuccess;
|
||||
UpdateUserError: UpdateUserError;
|
||||
UpdateUserInput: UpdateUserInput;
|
||||
UpdateUserProfileError: UpdateUserProfileError;
|
||||
|
|
@ -5142,6 +5182,7 @@ export type MutationResolvers<ContextType = ResolverContext, ParentType extends
|
|||
updatePage?: Resolver<ResolversTypes['UpdatePageResult'], ParentType, ContextType, RequireFields<MutationUpdatePageArgs, 'input'>>;
|
||||
updateReminder?: Resolver<ResolversTypes['UpdateReminderResult'], ParentType, ContextType, RequireFields<MutationUpdateReminderArgs, 'input'>>;
|
||||
updateSharedComment?: Resolver<ResolversTypes['UpdateSharedCommentResult'], ParentType, ContextType, RequireFields<MutationUpdateSharedCommentArgs, 'input'>>;
|
||||
updateSubscription?: Resolver<ResolversTypes['UpdateSubscriptionResult'], ParentType, ContextType, RequireFields<MutationUpdateSubscriptionArgs, 'input'>>;
|
||||
updateUser?: Resolver<ResolversTypes['UpdateUserResult'], ParentType, ContextType, RequireFields<MutationUpdateUserArgs, 'input'>>;
|
||||
updateUserProfile?: Resolver<ResolversTypes['UpdateUserProfileResult'], ParentType, ContextType, RequireFields<MutationUpdateUserProfileArgs, 'input'>>;
|
||||
uploadFileRequest?: Resolver<ResolversTypes['UploadFileRequestResult'], ParentType, ContextType, RequireFields<MutationUploadFileRequestArgs, 'input'>>;
|
||||
|
|
@ -5938,6 +5979,20 @@ export type UpdateSharedCommentSuccessResolvers<ContextType = ResolverContext, P
|
|||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type UpdateSubscriptionErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['UpdateSubscriptionError'] = ResolversParentTypes['UpdateSubscriptionError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['UpdateSubscriptionErrorCode']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type UpdateSubscriptionResultResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['UpdateSubscriptionResult'] = ResolversParentTypes['UpdateSubscriptionResult']> = {
|
||||
__resolveType: TypeResolveFn<'UpdateSubscriptionError' | 'UpdateSubscriptionSuccess', ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type UpdateSubscriptionSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['UpdateSubscriptionSuccess'] = ResolversParentTypes['UpdateSubscriptionSuccess']> = {
|
||||
subscription?: Resolver<ResolversTypes['Subscription'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type UpdateUserErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['UpdateUserError'] = ResolversParentTypes['UpdateUserError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['UpdateUserErrorCode']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
|
|
@ -6405,6 +6460,9 @@ export type Resolvers<ContextType = ResolverContext> = {
|
|||
UpdateSharedCommentError?: UpdateSharedCommentErrorResolvers<ContextType>;
|
||||
UpdateSharedCommentResult?: UpdateSharedCommentResultResolvers<ContextType>;
|
||||
UpdateSharedCommentSuccess?: UpdateSharedCommentSuccessResolvers<ContextType>;
|
||||
UpdateSubscriptionError?: UpdateSubscriptionErrorResolvers<ContextType>;
|
||||
UpdateSubscriptionResult?: UpdateSubscriptionResultResolvers<ContextType>;
|
||||
UpdateSubscriptionSuccess?: UpdateSubscriptionSuccessResolvers<ContextType>;
|
||||
UpdateUserError?: UpdateUserErrorResolvers<ContextType>;
|
||||
UpdateUserProfileError?: UpdateUserProfileErrorResolvers<ContextType>;
|
||||
UpdateUserProfileResult?: UpdateUserProfileResultResolvers<ContextType>;
|
||||
|
|
|
|||
|
|
@ -1160,6 +1160,7 @@ type Mutation {
|
|||
updatePage(input: UpdatePageInput!): UpdatePageResult!
|
||||
updateReminder(input: UpdateReminderInput!): UpdateReminderResult!
|
||||
updateSharedComment(input: UpdateSharedCommentInput!): UpdateSharedCommentResult!
|
||||
updateSubscription(input: UpdateSubscriptionInput!): UpdateSubscriptionResult!
|
||||
updateUser(input: UpdateUserInput!): UpdateUserResult!
|
||||
updateUserProfile(input: UpdateUserProfileInput!): UpdateUserProfileResult!
|
||||
uploadFileRequest(input: UploadFileRequestInput!): UploadFileRequestResult!
|
||||
|
|
@ -2323,6 +2324,29 @@ type UpdateSharedCommentSuccess {
|
|||
sharedComment: String!
|
||||
}
|
||||
|
||||
type UpdateSubscriptionError {
|
||||
errorCodes: [UpdateSubscriptionErrorCode!]!
|
||||
}
|
||||
|
||||
enum UpdateSubscriptionErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
input UpdateSubscriptionInput {
|
||||
description: String
|
||||
id: ID!
|
||||
lastFetchedAt: Date
|
||||
name: String
|
||||
}
|
||||
|
||||
union UpdateSubscriptionResult = UpdateSubscriptionError | UpdateSubscriptionSuccess
|
||||
|
||||
type UpdateSubscriptionSuccess {
|
||||
subscription: Subscription!
|
||||
}
|
||||
|
||||
type UpdateUserError {
|
||||
errorCodes: [UpdateUserErrorCode!]!
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { getShareInfoForArticle } from '../datalayer/links/share_info'
|
||||
import { getPageByParam } from '../elastic/pages'
|
||||
import { Subscription } from '../entity/subscription'
|
||||
import {
|
||||
Article,
|
||||
ArticleHighlightsInput,
|
||||
|
|
@ -109,6 +110,7 @@ import {
|
|||
updateReminderResolver,
|
||||
updateSharedCommentResolver,
|
||||
updatesSinceResolver,
|
||||
updateSubscriptionResolver,
|
||||
updateUserProfileResolver,
|
||||
updateUserResolver,
|
||||
uploadFileRequestResolver,
|
||||
|
|
@ -206,6 +208,7 @@ export const functionResolvers = {
|
|||
bulkAction: bulkActionResolver,
|
||||
importFromIntegration: importFromIntegrationResolver,
|
||||
setFavoriteArticle: setFavoriteArticleResolver,
|
||||
updateSubscription: updateSubscriptionResolver,
|
||||
},
|
||||
Query: {
|
||||
me: getMeUserResolver,
|
||||
|
|
@ -573,6 +576,16 @@ export const functionResolvers = {
|
|||
return item.pageType || PageType.Unknown
|
||||
},
|
||||
},
|
||||
Subscription: {
|
||||
newsletterEmail(subscription: Subscription) {
|
||||
return subscription.newsletterEmail?.address
|
||||
},
|
||||
icon(subscription: Subscription) {
|
||||
return (
|
||||
subscription.icon && createImageProxyUrl(subscription.icon, 128, 128)
|
||||
)
|
||||
},
|
||||
},
|
||||
...resultResolveTypeResolver('Login'),
|
||||
...resultResolveTypeResolver('LogOut'),
|
||||
...resultResolveTypeResolver('GoogleSignup'),
|
||||
|
|
@ -662,4 +675,5 @@ export const functionResolvers = {
|
|||
...resultResolveTypeResolver('BulkAction'),
|
||||
...resultResolveTypeResolver('ImportFromIntegration'),
|
||||
...resultResolveTypeResolver('SetFavoriteArticle'),
|
||||
...resultResolveTypeResolver('UpdateSubscription'),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { env } from '../../env'
|
|||
import {
|
||||
MutationSubscribeArgs,
|
||||
MutationUnsubscribeArgs,
|
||||
MutationUpdateSubscriptionArgs,
|
||||
QuerySubscriptionsArgs,
|
||||
SortBy,
|
||||
SortOrder,
|
||||
|
|
@ -20,16 +21,25 @@ import {
|
|||
UnsubscribeError,
|
||||
UnsubscribeErrorCode,
|
||||
UnsubscribeSuccess,
|
||||
UpdateSubscriptionError,
|
||||
UpdateSubscriptionErrorCode,
|
||||
UpdateSubscriptionSuccess,
|
||||
} from '../../generated/graphql'
|
||||
import { getSubscribeHandler, unsubscribe } from '../../services/subscriptions'
|
||||
import { Merge } from '../../util'
|
||||
import { analytics } from '../../utils/analytics'
|
||||
import { authorized } from '../../utils/helpers'
|
||||
import { createImageProxyUrl } from '../../utils/imageproxy'
|
||||
|
||||
type PartialSubscription = Omit<Subscription, 'newsletterEmail'>
|
||||
|
||||
const parser = new Parser()
|
||||
|
||||
export const subscriptionsResolver = authorized<
|
||||
export type SubscriptionsSuccessPartial = Merge<
|
||||
SubscriptionsSuccess,
|
||||
{ subscriptions: PartialSubscription[] }
|
||||
>
|
||||
export const subscriptionsResolver = authorized<
|
||||
SubscriptionsSuccessPartial,
|
||||
SubscriptionsError,
|
||||
QuerySubscriptionsArgs
|
||||
>(async (_obj, { sort, type: subscriptionType }, { claims: { uid }, log }) => {
|
||||
|
|
@ -66,11 +76,7 @@ export const subscriptionsResolver = authorized<
|
|||
.getMany()
|
||||
|
||||
return {
|
||||
subscriptions: subscriptions.map((s) => ({
|
||||
...s,
|
||||
icon: s.icon && createImageProxyUrl(s.icon, 128, 128),
|
||||
newsletterEmail: s.newsletterEmail?.address,
|
||||
})),
|
||||
subscriptions,
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(error)
|
||||
|
|
@ -80,8 +86,12 @@ export const subscriptionsResolver = authorized<
|
|||
}
|
||||
})
|
||||
|
||||
export const unsubscribeResolver = authorized<
|
||||
export type UnsubscribeSuccessPartial = Merge<
|
||||
UnsubscribeSuccess,
|
||||
{ subscription: PartialSubscription }
|
||||
>
|
||||
export const unsubscribeResolver = authorized<
|
||||
UnsubscribeSuccessPartial,
|
||||
UnsubscribeError,
|
||||
MutationUnsubscribeArgs
|
||||
>(async (_, { name, subscriptionId }, { claims: { uid }, log }) => {
|
||||
|
|
@ -122,8 +132,12 @@ export const unsubscribeResolver = authorized<
|
|||
}
|
||||
}
|
||||
|
||||
if (!subscription.unsubscribeMailTo && !subscription.unsubscribeHttpUrl) {
|
||||
log.info('No unsubscribe method found')
|
||||
if (
|
||||
subscription.type === SubscriptionType.Newsletter &&
|
||||
!subscription.unsubscribeMailTo &&
|
||||
!subscription.unsubscribeHttpUrl
|
||||
) {
|
||||
log.info('No unsubscribe method found for newsletter subscription')
|
||||
}
|
||||
|
||||
await unsubscribe(subscription)
|
||||
|
|
@ -138,10 +152,7 @@ export const unsubscribeResolver = authorized<
|
|||
})
|
||||
|
||||
return {
|
||||
subscription: {
|
||||
...subscription,
|
||||
newsletterEmail: subscription.newsletterEmail?.address,
|
||||
},
|
||||
subscription,
|
||||
}
|
||||
} catch (error) {
|
||||
log.error('failed to unsubscribe', error)
|
||||
|
|
@ -151,8 +162,12 @@ export const unsubscribeResolver = authorized<
|
|||
}
|
||||
})
|
||||
|
||||
export const subscribeResolver = authorized<
|
||||
export type SubscribeSuccessPartial = Merge<
|
||||
SubscribeSuccess,
|
||||
{ subscriptions: PartialSubscription[] }
|
||||
>
|
||||
export const subscribeResolver = authorized<
|
||||
SubscribeSuccessPartial,
|
||||
SubscribeError,
|
||||
MutationSubscribeArgs
|
||||
>(async (_, { input }, { claims: { uid }, log }) => {
|
||||
|
|
@ -209,10 +224,7 @@ export const subscribeResolver = authorized<
|
|||
}
|
||||
|
||||
return {
|
||||
subscriptions: newSubscriptions.map((s) => ({
|
||||
...s,
|
||||
newsletterEmail: s.newsletterEmail?.address,
|
||||
})),
|
||||
subscriptions: newSubscriptions,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -231,12 +243,7 @@ export const subscribeResolver = authorized<
|
|||
})
|
||||
|
||||
return {
|
||||
subscriptions: [
|
||||
{
|
||||
...newSubscription,
|
||||
newsletterEmail: null,
|
||||
},
|
||||
],
|
||||
subscriptions: [newSubscription],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -251,3 +258,65 @@ export const subscribeResolver = authorized<
|
|||
}
|
||||
}
|
||||
})
|
||||
|
||||
export type UpdateSubscriptionSuccessPartial = Merge<
|
||||
UpdateSubscriptionSuccess,
|
||||
{ subscription: PartialSubscription }
|
||||
>
|
||||
export const updateSubscriptionResolver = authorized<
|
||||
UpdateSubscriptionSuccessPartial,
|
||||
UpdateSubscriptionError,
|
||||
MutationUpdateSubscriptionArgs
|
||||
>(async (_, { input }, { claims: { uid }, log }) => {
|
||||
log.info('updateSubscriptionResolver')
|
||||
|
||||
try {
|
||||
analytics.track({
|
||||
userId: uid,
|
||||
event: 'update_subscription',
|
||||
properties: {
|
||||
...input,
|
||||
env: env.server.apiEnv,
|
||||
},
|
||||
})
|
||||
|
||||
const user = await getRepository(User).findOneBy({ id: uid })
|
||||
if (!user) {
|
||||
return {
|
||||
errorCodes: [UpdateSubscriptionErrorCode.Unauthorized],
|
||||
}
|
||||
}
|
||||
|
||||
// find existing subscription
|
||||
const subscription = await getRepository(Subscription).findOneBy({
|
||||
id: input.id,
|
||||
user: { id: uid },
|
||||
status: SubscriptionStatus.Active,
|
||||
})
|
||||
if (!subscription) {
|
||||
log.info('subscription not found')
|
||||
return {
|
||||
errorCodes: [UpdateSubscriptionErrorCode.NotFound],
|
||||
}
|
||||
}
|
||||
|
||||
// update subscription
|
||||
const updatedSubscription = await getRepository(Subscription).save({
|
||||
id: input.id,
|
||||
name: input.name || undefined,
|
||||
description: input.description || undefined,
|
||||
lastFetchedAt: input.lastFetchedAt
|
||||
? new Date(input.lastFetchedAt)
|
||||
: undefined,
|
||||
})
|
||||
|
||||
return {
|
||||
subscription: updatedSubscription,
|
||||
}
|
||||
} catch (error) {
|
||||
log.error('failed to update subscription', error)
|
||||
return {
|
||||
errorCodes: [UpdateSubscriptionErrorCode.BadRequest],
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2492,6 +2492,31 @@ const schema = gql`
|
|||
subscriptionType: SubscriptionType
|
||||
}
|
||||
|
||||
input UpdateSubscriptionInput {
|
||||
id: ID!
|
||||
name: String
|
||||
description: String
|
||||
lastFetchedAt: Date
|
||||
}
|
||||
|
||||
union UpdateSubscriptionResult =
|
||||
UpdateSubscriptionSuccess
|
||||
| UpdateSubscriptionError
|
||||
|
||||
type UpdateSubscriptionSuccess {
|
||||
subscription: Subscription!
|
||||
}
|
||||
|
||||
type UpdateSubscriptionError {
|
||||
errorCodes: [UpdateSubscriptionErrorCode!]!
|
||||
}
|
||||
|
||||
enum UpdateSubscriptionErrorCode {
|
||||
UNAUTHORIZED
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
}
|
||||
|
||||
# Mutations
|
||||
type Mutation {
|
||||
googleLogin(input: GoogleLoginInput!): LoginResult!
|
||||
|
|
@ -2590,6 +2615,9 @@ const schema = gql`
|
|||
): BulkActionResult!
|
||||
importFromIntegration(integrationId: ID!): ImportFromIntegrationResult!
|
||||
setFavoriteArticle(id: ID!): SetFavoriteArticleResult!
|
||||
updateSubscription(
|
||||
input: UpdateSubscriptionInput!
|
||||
): UpdateSubscriptionResult!
|
||||
}
|
||||
|
||||
# FIXME: remove sort from feedArticles after all cached tabs are closed
|
||||
|
|
|
|||
Loading…
Reference in a new issue