mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Add createIntegration API implementation
This commit is contained in:
parent
e66d047d51
commit
dd2db71876
8 changed files with 237 additions and 90 deletions
|
|
@ -25,7 +25,7 @@ export class Integration {
|
||||||
@Column('enum', { enum: IntegrationType })
|
@Column('enum', { enum: IntegrationType })
|
||||||
type!: IntegrationType
|
type!: IntegrationType
|
||||||
|
|
||||||
@Column('varchar')
|
@Column('varchar', { length: 255 })
|
||||||
token!: string
|
token!: string
|
||||||
|
|
||||||
@Column('boolean', { default: true })
|
@Column('boolean', { default: true })
|
||||||
|
|
|
||||||
|
|
@ -331,30 +331,6 @@ export type CreateHighlightSuccess = {
|
||||||
highlight: Highlight;
|
highlight: Highlight;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreateIntegrationError = {
|
|
||||||
__typename?: 'CreateIntegrationError';
|
|
||||||
errorCodes: Array<CreateIntegrationErrorCode>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum CreateIntegrationErrorCode {
|
|
||||||
BadRequest = 'BAD_REQUEST',
|
|
||||||
InvalidToken = 'INVALID_TOKEN',
|
|
||||||
NotFound = 'NOT_FOUND',
|
|
||||||
Unauthorized = 'UNAUTHORIZED'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type CreateIntegrationInput = {
|
|
||||||
token: Scalars['String'];
|
|
||||||
type: IntegrationType;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CreateIntegrationResult = CreateIntegrationError | CreateIntegrationSuccess;
|
|
||||||
|
|
||||||
export type CreateIntegrationSuccess = {
|
|
||||||
__typename?: 'CreateIntegrationSuccess';
|
|
||||||
integration: Integration;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CreateLabelError = {
|
export type CreateLabelError = {
|
||||||
__typename?: 'CreateLabelError';
|
__typename?: 'CreateLabelError';
|
||||||
errorCodes: Array<CreateLabelErrorCode>;
|
errorCodes: Array<CreateLabelErrorCode>;
|
||||||
|
|
@ -774,6 +750,7 @@ export type Integration = {
|
||||||
createdAt: Scalars['Date'];
|
createdAt: Scalars['Date'];
|
||||||
enabled: Scalars['Boolean'];
|
enabled: Scalars['Boolean'];
|
||||||
id: Scalars['ID'];
|
id: Scalars['ID'];
|
||||||
|
token: Scalars['String'];
|
||||||
type: IntegrationType;
|
type: IntegrationType;
|
||||||
updatedAt: Scalars['Date'];
|
updatedAt: Scalars['Date'];
|
||||||
};
|
};
|
||||||
|
|
@ -934,7 +911,6 @@ export type Mutation = {
|
||||||
createArticleSavingRequest: CreateArticleSavingRequestResult;
|
createArticleSavingRequest: CreateArticleSavingRequestResult;
|
||||||
createHighlight: CreateHighlightResult;
|
createHighlight: CreateHighlightResult;
|
||||||
createHighlightReply: CreateHighlightReplyResult;
|
createHighlightReply: CreateHighlightReplyResult;
|
||||||
createIntegration: CreateIntegrationResult;
|
|
||||||
createLabel: CreateLabelResult;
|
createLabel: CreateLabelResult;
|
||||||
createNewsletterEmail: CreateNewsletterEmailResult;
|
createNewsletterEmail: CreateNewsletterEmailResult;
|
||||||
createReaction: CreateReactionResult;
|
createReaction: CreateReactionResult;
|
||||||
|
|
@ -962,6 +938,7 @@ export type Mutation = {
|
||||||
setBookmarkArticle: SetBookmarkArticleResult;
|
setBookmarkArticle: SetBookmarkArticleResult;
|
||||||
setDeviceToken: SetDeviceTokenResult;
|
setDeviceToken: SetDeviceTokenResult;
|
||||||
setFollow: SetFollowResult;
|
setFollow: SetFollowResult;
|
||||||
|
setIntegration: SetIntegrationResult;
|
||||||
setLabels: SetLabelsResult;
|
setLabels: SetLabelsResult;
|
||||||
setLabelsForHighlight: SetLabelsResult;
|
setLabelsForHighlight: SetLabelsResult;
|
||||||
setLinkArchived: ArchiveLinkResult;
|
setLinkArchived: ArchiveLinkResult;
|
||||||
|
|
@ -1009,11 +986,6 @@ export type MutationCreateHighlightReplyArgs = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateIntegrationArgs = {
|
|
||||||
input: CreateIntegrationInput;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateLabelArgs = {
|
export type MutationCreateLabelArgs = {
|
||||||
input: CreateLabelInput;
|
input: CreateLabelInput;
|
||||||
};
|
};
|
||||||
|
|
@ -1139,6 +1111,11 @@ export type MutationSetFollowArgs = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationSetIntegrationArgs = {
|
||||||
|
input: SetIntegrationInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationSetLabelsArgs = {
|
export type MutationSetLabelsArgs = {
|
||||||
input: SetLabelsInput;
|
input: SetLabelsInput;
|
||||||
};
|
};
|
||||||
|
|
@ -1737,6 +1714,33 @@ export type SetFollowSuccess = {
|
||||||
updatedUser: User;
|
updatedUser: User;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type SetIntegrationError = {
|
||||||
|
__typename?: 'SetIntegrationError';
|
||||||
|
errorCodes: Array<SetIntegrationErrorCode>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum SetIntegrationErrorCode {
|
||||||
|
AlreadyExists = 'ALREADY_EXISTS',
|
||||||
|
BadRequest = 'BAD_REQUEST',
|
||||||
|
InvalidToken = 'INVALID_TOKEN',
|
||||||
|
NotFound = 'NOT_FOUND',
|
||||||
|
Unauthorized = 'UNAUTHORIZED'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SetIntegrationInput = {
|
||||||
|
enabled?: InputMaybe<Scalars['Boolean']>;
|
||||||
|
id?: InputMaybe<Scalars['ID']>;
|
||||||
|
token: Scalars['String'];
|
||||||
|
type: IntegrationType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SetIntegrationResult = SetIntegrationError | SetIntegrationSuccess;
|
||||||
|
|
||||||
|
export type SetIntegrationSuccess = {
|
||||||
|
__typename?: 'SetIntegrationSuccess';
|
||||||
|
integration: Integration;
|
||||||
|
};
|
||||||
|
|
||||||
export type SetLabelsError = {
|
export type SetLabelsError = {
|
||||||
__typename?: 'SetLabelsError';
|
__typename?: 'SetLabelsError';
|
||||||
errorCodes: Array<SetLabelsErrorCode>;
|
errorCodes: Array<SetLabelsErrorCode>;
|
||||||
|
|
@ -2548,11 +2552,6 @@ export type ResolversTypes = {
|
||||||
CreateHighlightReplySuccess: ResolverTypeWrapper<CreateHighlightReplySuccess>;
|
CreateHighlightReplySuccess: ResolverTypeWrapper<CreateHighlightReplySuccess>;
|
||||||
CreateHighlightResult: ResolversTypes['CreateHighlightError'] | ResolversTypes['CreateHighlightSuccess'];
|
CreateHighlightResult: ResolversTypes['CreateHighlightError'] | ResolversTypes['CreateHighlightSuccess'];
|
||||||
CreateHighlightSuccess: ResolverTypeWrapper<CreateHighlightSuccess>;
|
CreateHighlightSuccess: ResolverTypeWrapper<CreateHighlightSuccess>;
|
||||||
CreateIntegrationError: ResolverTypeWrapper<CreateIntegrationError>;
|
|
||||||
CreateIntegrationErrorCode: CreateIntegrationErrorCode;
|
|
||||||
CreateIntegrationInput: CreateIntegrationInput;
|
|
||||||
CreateIntegrationResult: ResolversTypes['CreateIntegrationError'] | ResolversTypes['CreateIntegrationSuccess'];
|
|
||||||
CreateIntegrationSuccess: ResolverTypeWrapper<CreateIntegrationSuccess>;
|
|
||||||
CreateLabelError: ResolverTypeWrapper<CreateLabelError>;
|
CreateLabelError: ResolverTypeWrapper<CreateLabelError>;
|
||||||
CreateLabelErrorCode: CreateLabelErrorCode;
|
CreateLabelErrorCode: CreateLabelErrorCode;
|
||||||
CreateLabelInput: CreateLabelInput;
|
CreateLabelInput: CreateLabelInput;
|
||||||
|
|
@ -2732,6 +2731,11 @@ export type ResolversTypes = {
|
||||||
SetFollowInput: SetFollowInput;
|
SetFollowInput: SetFollowInput;
|
||||||
SetFollowResult: ResolversTypes['SetFollowError'] | ResolversTypes['SetFollowSuccess'];
|
SetFollowResult: ResolversTypes['SetFollowError'] | ResolversTypes['SetFollowSuccess'];
|
||||||
SetFollowSuccess: ResolverTypeWrapper<SetFollowSuccess>;
|
SetFollowSuccess: ResolverTypeWrapper<SetFollowSuccess>;
|
||||||
|
SetIntegrationError: ResolverTypeWrapper<SetIntegrationError>;
|
||||||
|
SetIntegrationErrorCode: SetIntegrationErrorCode;
|
||||||
|
SetIntegrationInput: SetIntegrationInput;
|
||||||
|
SetIntegrationResult: ResolversTypes['SetIntegrationError'] | ResolversTypes['SetIntegrationSuccess'];
|
||||||
|
SetIntegrationSuccess: ResolverTypeWrapper<SetIntegrationSuccess>;
|
||||||
SetLabelsError: ResolverTypeWrapper<SetLabelsError>;
|
SetLabelsError: ResolverTypeWrapper<SetLabelsError>;
|
||||||
SetLabelsErrorCode: SetLabelsErrorCode;
|
SetLabelsErrorCode: SetLabelsErrorCode;
|
||||||
SetLabelsForHighlightInput: SetLabelsForHighlightInput;
|
SetLabelsForHighlightInput: SetLabelsForHighlightInput;
|
||||||
|
|
@ -2909,10 +2913,6 @@ export type ResolversParentTypes = {
|
||||||
CreateHighlightReplySuccess: CreateHighlightReplySuccess;
|
CreateHighlightReplySuccess: CreateHighlightReplySuccess;
|
||||||
CreateHighlightResult: ResolversParentTypes['CreateHighlightError'] | ResolversParentTypes['CreateHighlightSuccess'];
|
CreateHighlightResult: ResolversParentTypes['CreateHighlightError'] | ResolversParentTypes['CreateHighlightSuccess'];
|
||||||
CreateHighlightSuccess: CreateHighlightSuccess;
|
CreateHighlightSuccess: CreateHighlightSuccess;
|
||||||
CreateIntegrationError: CreateIntegrationError;
|
|
||||||
CreateIntegrationInput: CreateIntegrationInput;
|
|
||||||
CreateIntegrationResult: ResolversParentTypes['CreateIntegrationError'] | ResolversParentTypes['CreateIntegrationSuccess'];
|
|
||||||
CreateIntegrationSuccess: CreateIntegrationSuccess;
|
|
||||||
CreateLabelError: CreateLabelError;
|
CreateLabelError: CreateLabelError;
|
||||||
CreateLabelInput: CreateLabelInput;
|
CreateLabelInput: CreateLabelInput;
|
||||||
CreateLabelResult: ResolversParentTypes['CreateLabelError'] | ResolversParentTypes['CreateLabelSuccess'];
|
CreateLabelResult: ResolversParentTypes['CreateLabelError'] | ResolversParentTypes['CreateLabelSuccess'];
|
||||||
|
|
@ -3056,6 +3056,10 @@ export type ResolversParentTypes = {
|
||||||
SetFollowInput: SetFollowInput;
|
SetFollowInput: SetFollowInput;
|
||||||
SetFollowResult: ResolversParentTypes['SetFollowError'] | ResolversParentTypes['SetFollowSuccess'];
|
SetFollowResult: ResolversParentTypes['SetFollowError'] | ResolversParentTypes['SetFollowSuccess'];
|
||||||
SetFollowSuccess: SetFollowSuccess;
|
SetFollowSuccess: SetFollowSuccess;
|
||||||
|
SetIntegrationError: SetIntegrationError;
|
||||||
|
SetIntegrationInput: SetIntegrationInput;
|
||||||
|
SetIntegrationResult: ResolversParentTypes['SetIntegrationError'] | ResolversParentTypes['SetIntegrationSuccess'];
|
||||||
|
SetIntegrationSuccess: SetIntegrationSuccess;
|
||||||
SetLabelsError: SetLabelsError;
|
SetLabelsError: SetLabelsError;
|
||||||
SetLabelsForHighlightInput: SetLabelsForHighlightInput;
|
SetLabelsForHighlightInput: SetLabelsForHighlightInput;
|
||||||
SetLabelsInput: SetLabelsInput;
|
SetLabelsInput: SetLabelsInput;
|
||||||
|
|
@ -3382,20 +3386,6 @@ export type CreateHighlightSuccessResolvers<ContextType = ResolverContext, Paren
|
||||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreateIntegrationErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['CreateIntegrationError'] = ResolversParentTypes['CreateIntegrationError']> = {
|
|
||||||
errorCodes?: Resolver<Array<ResolversTypes['CreateIntegrationErrorCode']>, ParentType, ContextType>;
|
|
||||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CreateIntegrationResultResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['CreateIntegrationResult'] = ResolversParentTypes['CreateIntegrationResult']> = {
|
|
||||||
__resolveType: TypeResolveFn<'CreateIntegrationError' | 'CreateIntegrationSuccess', ParentType, ContextType>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CreateIntegrationSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['CreateIntegrationSuccess'] = ResolversParentTypes['CreateIntegrationSuccess']> = {
|
|
||||||
integration?: Resolver<ResolversTypes['Integration'], ParentType, ContextType>;
|
|
||||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CreateLabelErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['CreateLabelError'] = ResolversParentTypes['CreateLabelError']> = {
|
export type CreateLabelErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['CreateLabelError'] = ResolversParentTypes['CreateLabelError']> = {
|
||||||
errorCodes?: Resolver<Array<ResolversTypes['CreateLabelErrorCode']>, ParentType, ContextType>;
|
errorCodes?: Resolver<Array<ResolversTypes['CreateLabelErrorCode']>, ParentType, ContextType>;
|
||||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||||
|
|
@ -3717,6 +3707,7 @@ export type IntegrationResolvers<ContextType = ResolverContext, ParentType exten
|
||||||
createdAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
|
createdAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
|
||||||
enabled?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
|
enabled?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
|
||||||
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
|
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
|
||||||
|
token?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
||||||
type?: Resolver<ResolversTypes['IntegrationType'], ParentType, ContextType>;
|
type?: Resolver<ResolversTypes['IntegrationType'], ParentType, ContextType>;
|
||||||
updatedAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
|
updatedAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
|
||||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||||
|
|
@ -3833,7 +3824,6 @@ export type MutationResolvers<ContextType = ResolverContext, ParentType extends
|
||||||
createArticleSavingRequest?: Resolver<ResolversTypes['CreateArticleSavingRequestResult'], ParentType, ContextType, RequireFields<MutationCreateArticleSavingRequestArgs, 'input'>>;
|
createArticleSavingRequest?: Resolver<ResolversTypes['CreateArticleSavingRequestResult'], ParentType, ContextType, RequireFields<MutationCreateArticleSavingRequestArgs, 'input'>>;
|
||||||
createHighlight?: Resolver<ResolversTypes['CreateHighlightResult'], ParentType, ContextType, RequireFields<MutationCreateHighlightArgs, 'input'>>;
|
createHighlight?: Resolver<ResolversTypes['CreateHighlightResult'], ParentType, ContextType, RequireFields<MutationCreateHighlightArgs, 'input'>>;
|
||||||
createHighlightReply?: Resolver<ResolversTypes['CreateHighlightReplyResult'], ParentType, ContextType, RequireFields<MutationCreateHighlightReplyArgs, 'input'>>;
|
createHighlightReply?: Resolver<ResolversTypes['CreateHighlightReplyResult'], ParentType, ContextType, RequireFields<MutationCreateHighlightReplyArgs, 'input'>>;
|
||||||
createIntegration?: Resolver<ResolversTypes['CreateIntegrationResult'], ParentType, ContextType, RequireFields<MutationCreateIntegrationArgs, 'input'>>;
|
|
||||||
createLabel?: Resolver<ResolversTypes['CreateLabelResult'], ParentType, ContextType, RequireFields<MutationCreateLabelArgs, 'input'>>;
|
createLabel?: Resolver<ResolversTypes['CreateLabelResult'], ParentType, ContextType, RequireFields<MutationCreateLabelArgs, 'input'>>;
|
||||||
createNewsletterEmail?: Resolver<ResolversTypes['CreateNewsletterEmailResult'], ParentType, ContextType>;
|
createNewsletterEmail?: Resolver<ResolversTypes['CreateNewsletterEmailResult'], ParentType, ContextType>;
|
||||||
createReaction?: Resolver<ResolversTypes['CreateReactionResult'], ParentType, ContextType, RequireFields<MutationCreateReactionArgs, 'input'>>;
|
createReaction?: Resolver<ResolversTypes['CreateReactionResult'], ParentType, ContextType, RequireFields<MutationCreateReactionArgs, 'input'>>;
|
||||||
|
|
@ -3861,6 +3851,7 @@ export type MutationResolvers<ContextType = ResolverContext, ParentType extends
|
||||||
setBookmarkArticle?: Resolver<ResolversTypes['SetBookmarkArticleResult'], ParentType, ContextType, RequireFields<MutationSetBookmarkArticleArgs, 'input'>>;
|
setBookmarkArticle?: Resolver<ResolversTypes['SetBookmarkArticleResult'], ParentType, ContextType, RequireFields<MutationSetBookmarkArticleArgs, 'input'>>;
|
||||||
setDeviceToken?: Resolver<ResolversTypes['SetDeviceTokenResult'], ParentType, ContextType, RequireFields<MutationSetDeviceTokenArgs, 'input'>>;
|
setDeviceToken?: Resolver<ResolversTypes['SetDeviceTokenResult'], ParentType, ContextType, RequireFields<MutationSetDeviceTokenArgs, 'input'>>;
|
||||||
setFollow?: Resolver<ResolversTypes['SetFollowResult'], ParentType, ContextType, RequireFields<MutationSetFollowArgs, 'input'>>;
|
setFollow?: Resolver<ResolversTypes['SetFollowResult'], ParentType, ContextType, RequireFields<MutationSetFollowArgs, 'input'>>;
|
||||||
|
setIntegration?: Resolver<ResolversTypes['SetIntegrationResult'], ParentType, ContextType, RequireFields<MutationSetIntegrationArgs, 'input'>>;
|
||||||
setLabels?: Resolver<ResolversTypes['SetLabelsResult'], ParentType, ContextType, RequireFields<MutationSetLabelsArgs, 'input'>>;
|
setLabels?: Resolver<ResolversTypes['SetLabelsResult'], ParentType, ContextType, RequireFields<MutationSetLabelsArgs, 'input'>>;
|
||||||
setLabelsForHighlight?: Resolver<ResolversTypes['SetLabelsResult'], ParentType, ContextType, RequireFields<MutationSetLabelsForHighlightArgs, 'input'>>;
|
setLabelsForHighlight?: Resolver<ResolversTypes['SetLabelsResult'], ParentType, ContextType, RequireFields<MutationSetLabelsForHighlightArgs, 'input'>>;
|
||||||
setLinkArchived?: Resolver<ResolversTypes['ArchiveLinkResult'], ParentType, ContextType, RequireFields<MutationSetLinkArchivedArgs, 'input'>>;
|
setLinkArchived?: Resolver<ResolversTypes['ArchiveLinkResult'], ParentType, ContextType, RequireFields<MutationSetLinkArchivedArgs, 'input'>>;
|
||||||
|
|
@ -4167,6 +4158,20 @@ export type SetFollowSuccessResolvers<ContextType = ResolverContext, ParentType
|
||||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type SetIntegrationErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['SetIntegrationError'] = ResolversParentTypes['SetIntegrationError']> = {
|
||||||
|
errorCodes?: Resolver<Array<ResolversTypes['SetIntegrationErrorCode']>, ParentType, ContextType>;
|
||||||
|
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SetIntegrationResultResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['SetIntegrationResult'] = ResolversParentTypes['SetIntegrationResult']> = {
|
||||||
|
__resolveType: TypeResolveFn<'SetIntegrationError' | 'SetIntegrationSuccess', ParentType, ContextType>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SetIntegrationSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['SetIntegrationSuccess'] = ResolversParentTypes['SetIntegrationSuccess']> = {
|
||||||
|
integration?: Resolver<ResolversTypes['Integration'], ParentType, ContextType>;
|
||||||
|
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||||
|
};
|
||||||
|
|
||||||
export type SetLabelsErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['SetLabelsError'] = ResolversParentTypes['SetLabelsError']> = {
|
export type SetLabelsErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['SetLabelsError'] = ResolversParentTypes['SetLabelsError']> = {
|
||||||
errorCodes?: Resolver<Array<ResolversTypes['SetLabelsErrorCode']>, ParentType, ContextType>;
|
errorCodes?: Resolver<Array<ResolversTypes['SetLabelsErrorCode']>, ParentType, ContextType>;
|
||||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||||
|
|
@ -4635,9 +4640,6 @@ export type Resolvers<ContextType = ResolverContext> = {
|
||||||
CreateHighlightReplySuccess?: CreateHighlightReplySuccessResolvers<ContextType>;
|
CreateHighlightReplySuccess?: CreateHighlightReplySuccessResolvers<ContextType>;
|
||||||
CreateHighlightResult?: CreateHighlightResultResolvers<ContextType>;
|
CreateHighlightResult?: CreateHighlightResultResolvers<ContextType>;
|
||||||
CreateHighlightSuccess?: CreateHighlightSuccessResolvers<ContextType>;
|
CreateHighlightSuccess?: CreateHighlightSuccessResolvers<ContextType>;
|
||||||
CreateIntegrationError?: CreateIntegrationErrorResolvers<ContextType>;
|
|
||||||
CreateIntegrationResult?: CreateIntegrationResultResolvers<ContextType>;
|
|
||||||
CreateIntegrationSuccess?: CreateIntegrationSuccessResolvers<ContextType>;
|
|
||||||
CreateLabelError?: CreateLabelErrorResolvers<ContextType>;
|
CreateLabelError?: CreateLabelErrorResolvers<ContextType>;
|
||||||
CreateLabelResult?: CreateLabelResultResolvers<ContextType>;
|
CreateLabelResult?: CreateLabelResultResolvers<ContextType>;
|
||||||
CreateLabelSuccess?: CreateLabelSuccessResolvers<ContextType>;
|
CreateLabelSuccess?: CreateLabelSuccessResolvers<ContextType>;
|
||||||
|
|
@ -4760,6 +4762,9 @@ export type Resolvers<ContextType = ResolverContext> = {
|
||||||
SetFollowError?: SetFollowErrorResolvers<ContextType>;
|
SetFollowError?: SetFollowErrorResolvers<ContextType>;
|
||||||
SetFollowResult?: SetFollowResultResolvers<ContextType>;
|
SetFollowResult?: SetFollowResultResolvers<ContextType>;
|
||||||
SetFollowSuccess?: SetFollowSuccessResolvers<ContextType>;
|
SetFollowSuccess?: SetFollowSuccessResolvers<ContextType>;
|
||||||
|
SetIntegrationError?: SetIntegrationErrorResolvers<ContextType>;
|
||||||
|
SetIntegrationResult?: SetIntegrationResultResolvers<ContextType>;
|
||||||
|
SetIntegrationSuccess?: SetIntegrationSuccessResolvers<ContextType>;
|
||||||
SetLabelsError?: SetLabelsErrorResolvers<ContextType>;
|
SetLabelsError?: SetLabelsErrorResolvers<ContextType>;
|
||||||
SetLabelsResult?: SetLabelsResultResolvers<ContextType>;
|
SetLabelsResult?: SetLabelsResultResolvers<ContextType>;
|
||||||
SetLabelsSuccess?: SetLabelsSuccessResolvers<ContextType>;
|
SetLabelsSuccess?: SetLabelsSuccessResolvers<ContextType>;
|
||||||
|
|
|
||||||
|
|
@ -284,28 +284,6 @@ type CreateHighlightSuccess {
|
||||||
highlight: Highlight!
|
highlight: Highlight!
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateIntegrationError {
|
|
||||||
errorCodes: [CreateIntegrationErrorCode!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CreateIntegrationErrorCode {
|
|
||||||
BAD_REQUEST
|
|
||||||
INVALID_TOKEN
|
|
||||||
NOT_FOUND
|
|
||||||
UNAUTHORIZED
|
|
||||||
}
|
|
||||||
|
|
||||||
input CreateIntegrationInput {
|
|
||||||
token: String!
|
|
||||||
type: IntegrationType!
|
|
||||||
}
|
|
||||||
|
|
||||||
union CreateIntegrationResult = CreateIntegrationError | CreateIntegrationSuccess
|
|
||||||
|
|
||||||
type CreateIntegrationSuccess {
|
|
||||||
integration: Integration!
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateLabelError {
|
type CreateLabelError {
|
||||||
errorCodes: [CreateLabelErrorCode!]!
|
errorCodes: [CreateLabelErrorCode!]!
|
||||||
}
|
}
|
||||||
|
|
@ -684,6 +662,7 @@ type Integration {
|
||||||
createdAt: Date!
|
createdAt: Date!
|
||||||
enabled: Boolean!
|
enabled: Boolean!
|
||||||
id: ID!
|
id: ID!
|
||||||
|
token: String!
|
||||||
type: IntegrationType!
|
type: IntegrationType!
|
||||||
updatedAt: Date!
|
updatedAt: Date!
|
||||||
}
|
}
|
||||||
|
|
@ -830,7 +809,6 @@ type Mutation {
|
||||||
createArticleSavingRequest(input: CreateArticleSavingRequestInput!): CreateArticleSavingRequestResult!
|
createArticleSavingRequest(input: CreateArticleSavingRequestInput!): CreateArticleSavingRequestResult!
|
||||||
createHighlight(input: CreateHighlightInput!): CreateHighlightResult!
|
createHighlight(input: CreateHighlightInput!): CreateHighlightResult!
|
||||||
createHighlightReply(input: CreateHighlightReplyInput!): CreateHighlightReplyResult!
|
createHighlightReply(input: CreateHighlightReplyInput!): CreateHighlightReplyResult!
|
||||||
createIntegration(input: CreateIntegrationInput!): CreateIntegrationResult!
|
|
||||||
createLabel(input: CreateLabelInput!): CreateLabelResult!
|
createLabel(input: CreateLabelInput!): CreateLabelResult!
|
||||||
createNewsletterEmail: CreateNewsletterEmailResult!
|
createNewsletterEmail: CreateNewsletterEmailResult!
|
||||||
createReaction(input: CreateReactionInput!): CreateReactionResult!
|
createReaction(input: CreateReactionInput!): CreateReactionResult!
|
||||||
|
|
@ -858,6 +836,7 @@ type Mutation {
|
||||||
setBookmarkArticle(input: SetBookmarkArticleInput!): SetBookmarkArticleResult!
|
setBookmarkArticle(input: SetBookmarkArticleInput!): SetBookmarkArticleResult!
|
||||||
setDeviceToken(input: SetDeviceTokenInput!): SetDeviceTokenResult!
|
setDeviceToken(input: SetDeviceTokenInput!): SetDeviceTokenResult!
|
||||||
setFollow(input: SetFollowInput!): SetFollowResult!
|
setFollow(input: SetFollowInput!): SetFollowResult!
|
||||||
|
setIntegration(input: SetIntegrationInput!): SetIntegrationResult!
|
||||||
setLabels(input: SetLabelsInput!): SetLabelsResult!
|
setLabels(input: SetLabelsInput!): SetLabelsResult!
|
||||||
setLabelsForHighlight(input: SetLabelsForHighlightInput!): SetLabelsResult!
|
setLabelsForHighlight(input: SetLabelsForHighlightInput!): SetLabelsResult!
|
||||||
setLinkArchived(input: ArchiveLinkInput!): ArchiveLinkResult!
|
setLinkArchived(input: ArchiveLinkInput!): ArchiveLinkResult!
|
||||||
|
|
@ -1260,6 +1239,31 @@ type SetFollowSuccess {
|
||||||
updatedUser: User!
|
updatedUser: User!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SetIntegrationError {
|
||||||
|
errorCodes: [SetIntegrationErrorCode!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SetIntegrationErrorCode {
|
||||||
|
ALREADY_EXISTS
|
||||||
|
BAD_REQUEST
|
||||||
|
INVALID_TOKEN
|
||||||
|
NOT_FOUND
|
||||||
|
UNAUTHORIZED
|
||||||
|
}
|
||||||
|
|
||||||
|
input SetIntegrationInput {
|
||||||
|
enabled: Boolean
|
||||||
|
id: ID
|
||||||
|
token: String!
|
||||||
|
type: IntegrationType!
|
||||||
|
}
|
||||||
|
|
||||||
|
union SetIntegrationResult = SetIntegrationError | SetIntegrationSuccess
|
||||||
|
|
||||||
|
type SetIntegrationSuccess {
|
||||||
|
integration: Integration!
|
||||||
|
}
|
||||||
|
|
||||||
type SetLabelsError {
|
type SetLabelsError {
|
||||||
errorCodes: [SetLabelsErrorCode!]!
|
errorCodes: [SetLabelsErrorCode!]!
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ import {
|
||||||
generateUploadFilePathName,
|
generateUploadFilePathName,
|
||||||
} from '../utils/uploads'
|
} from '../utils/uploads'
|
||||||
import { getPageByParam } from '../elastic/pages'
|
import { getPageByParam } from '../elastic/pages'
|
||||||
|
import { setIntegrationResolver } from './integrations'
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
type ResultResolveType = {
|
type ResultResolveType = {
|
||||||
|
|
@ -165,6 +166,7 @@ export const functionResolvers = {
|
||||||
revokeApiKey: revokeApiKeyResolver,
|
revokeApiKey: revokeApiKeyResolver,
|
||||||
setLabelsForHighlight: setLabelsForHighlightResolver,
|
setLabelsForHighlight: setLabelsForHighlightResolver,
|
||||||
moveLabel: moveLabelResolver,
|
moveLabel: moveLabelResolver,
|
||||||
|
setIntegration: setIntegrationResolver,
|
||||||
},
|
},
|
||||||
Query: {
|
Query: {
|
||||||
me: getMeUserResolver,
|
me: getMeUserResolver,
|
||||||
|
|
@ -592,4 +594,5 @@ export const functionResolvers = {
|
||||||
...resultResolveTypeResolver('TypeaheadSearch'),
|
...resultResolveTypeResolver('TypeaheadSearch'),
|
||||||
...resultResolveTypeResolver('UpdatesSince'),
|
...resultResolveTypeResolver('UpdatesSince'),
|
||||||
...resultResolveTypeResolver('MoveLabel'),
|
...resultResolveTypeResolver('MoveLabel'),
|
||||||
|
...resultResolveTypeResolver('SetIntegration'),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
97
packages/api/src/resolvers/integrations/index.ts
Normal file
97
packages/api/src/resolvers/integrations/index.ts
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
import { authorized } from '../../utils/helpers'
|
||||||
|
import {
|
||||||
|
MutationSetIntegrationArgs,
|
||||||
|
SetIntegrationError,
|
||||||
|
SetIntegrationErrorCode,
|
||||||
|
SetIntegrationSuccess,
|
||||||
|
} from '../../generated/graphql'
|
||||||
|
import { getRepository } from '../../entity/utils'
|
||||||
|
import { User } from '../../entity/user'
|
||||||
|
import { Integration } from '../../entity/integration'
|
||||||
|
import { analytics } from '../../utils/analytics'
|
||||||
|
import { env } from '../../env'
|
||||||
|
import { validateToken } from '../../services/integrations'
|
||||||
|
|
||||||
|
export const setIntegrationResolver = authorized<
|
||||||
|
SetIntegrationSuccess,
|
||||||
|
SetIntegrationError,
|
||||||
|
MutationSetIntegrationArgs
|
||||||
|
>(async (_, { input }, { claims: { uid }, log }) => {
|
||||||
|
log.info('setIntegrationResolver')
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await getRepository(User).findOneBy({ id: uid })
|
||||||
|
if (!user) {
|
||||||
|
return {
|
||||||
|
errorCodes: [SetIntegrationErrorCode.Unauthorized],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const integrationToSave: Partial<Integration> = {
|
||||||
|
user,
|
||||||
|
token: input.token,
|
||||||
|
type: input.type,
|
||||||
|
enabled: input.enabled === null ? true : input.enabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.id) {
|
||||||
|
// Update
|
||||||
|
const existingIntegration = await getRepository(Integration).findOne({
|
||||||
|
where: { id: input.id },
|
||||||
|
relations: ['user'],
|
||||||
|
})
|
||||||
|
if (!existingIntegration) {
|
||||||
|
return {
|
||||||
|
errorCodes: [SetIntegrationErrorCode.NotFound],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (existingIntegration.user.id !== uid) {
|
||||||
|
return {
|
||||||
|
errorCodes: [SetIntegrationErrorCode.Unauthorized],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
integrationToSave.id = input.id
|
||||||
|
} else {
|
||||||
|
// Create
|
||||||
|
const existingIntegration = await getRepository(Integration).findOneBy({
|
||||||
|
user: { id: uid },
|
||||||
|
type: input.type,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (existingIntegration) {
|
||||||
|
return {
|
||||||
|
errorCodes: [SetIntegrationErrorCode.AlreadyExists],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate token
|
||||||
|
if (!(await validateToken(input.token, input.type))) {
|
||||||
|
return {
|
||||||
|
errorCodes: [SetIntegrationErrorCode.InvalidToken],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const integration = await getRepository(Integration).save(integrationToSave)
|
||||||
|
|
||||||
|
analytics.track({
|
||||||
|
userId: uid,
|
||||||
|
event: 'integration_set',
|
||||||
|
properties: {
|
||||||
|
id: integration.id,
|
||||||
|
env: env.server.apiEnv,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
integration,
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
log.error(error)
|
||||||
|
|
||||||
|
return {
|
||||||
|
errorCodes: [SetIntegrationErrorCode.BadRequest],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
@ -1812,17 +1812,16 @@ const schema = gql`
|
||||||
NOT_FOUND
|
NOT_FOUND
|
||||||
}
|
}
|
||||||
|
|
||||||
union CreateIntegrationResult =
|
union SetIntegrationResult = SetIntegrationSuccess | SetIntegrationError
|
||||||
CreateIntegrationSuccess
|
|
||||||
| CreateIntegrationError
|
|
||||||
|
|
||||||
type CreateIntegrationSuccess {
|
type SetIntegrationSuccess {
|
||||||
integration: Integration!
|
integration: Integration!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Integration {
|
type Integration {
|
||||||
id: ID!
|
id: ID!
|
||||||
type: IntegrationType!
|
type: IntegrationType!
|
||||||
|
token: String!
|
||||||
enabled: Boolean!
|
enabled: Boolean!
|
||||||
createdAt: Date!
|
createdAt: Date!
|
||||||
updatedAt: Date!
|
updatedAt: Date!
|
||||||
|
|
@ -1832,20 +1831,23 @@ const schema = gql`
|
||||||
READWISE
|
READWISE
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateIntegrationError {
|
type SetIntegrationError {
|
||||||
errorCodes: [CreateIntegrationErrorCode!]!
|
errorCodes: [SetIntegrationErrorCode!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CreateIntegrationErrorCode {
|
enum SetIntegrationErrorCode {
|
||||||
UNAUTHORIZED
|
UNAUTHORIZED
|
||||||
BAD_REQUEST
|
BAD_REQUEST
|
||||||
NOT_FOUND
|
NOT_FOUND
|
||||||
INVALID_TOKEN
|
INVALID_TOKEN
|
||||||
|
ALREADY_EXISTS
|
||||||
}
|
}
|
||||||
|
|
||||||
input CreateIntegrationInput {
|
input SetIntegrationInput {
|
||||||
|
id: ID
|
||||||
type: IntegrationType!
|
type: IntegrationType!
|
||||||
token: String!
|
token: String!
|
||||||
|
enabled: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
# Mutations
|
# Mutations
|
||||||
|
|
@ -1917,7 +1919,7 @@ const schema = gql`
|
||||||
revokeApiKey(id: ID!): RevokeApiKeyResult!
|
revokeApiKey(id: ID!): RevokeApiKeyResult!
|
||||||
setLabelsForHighlight(input: SetLabelsForHighlightInput!): SetLabelsResult!
|
setLabelsForHighlight(input: SetLabelsForHighlightInput!): SetLabelsResult!
|
||||||
moveLabel(input: MoveLabelInput!): MoveLabelResult!
|
moveLabel(input: MoveLabelInput!): MoveLabelResult!
|
||||||
createIntegration(input: CreateIntegrationInput!): CreateIntegrationResult!
|
setIntegration(input: SetIntegrationInput!): SetIntegrationResult!
|
||||||
}
|
}
|
||||||
|
|
||||||
# FIXME: remove sort from feedArticles after all cached tabs are closed
|
# FIXME: remove sort from feedArticles after all cached tabs are closed
|
||||||
|
|
|
||||||
27
packages/api/src/services/integrations.ts
Normal file
27
packages/api/src/services/integrations.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { IntegrationType } from '../generated/graphql'
|
||||||
|
import { env } from '../env'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
const READWISE_API_URL = 'https://readwise.io/api/v2'
|
||||||
|
|
||||||
|
export const validateToken = async (
|
||||||
|
token: string,
|
||||||
|
type: IntegrationType
|
||||||
|
): Promise<boolean> => {
|
||||||
|
switch (type) {
|
||||||
|
case IntegrationType.Readwise:
|
||||||
|
return validateReadwiseToken(token)
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const validateReadwiseToken = async (token: string): Promise<boolean> => {
|
||||||
|
const authUrl = `${env.readwise.apiUrl || READWISE_API_URL}/auth`
|
||||||
|
const response = await axios.get(authUrl, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Token ${token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return response.status === 204
|
||||||
|
}
|
||||||
|
|
@ -84,6 +84,9 @@ interface BackendEnv {
|
||||||
resetPasswordTemplateId: string
|
resetPasswordTemplateId: string
|
||||||
installationTemplateId: string
|
installationTemplateId: string
|
||||||
}
|
}
|
||||||
|
readwise: {
|
||||||
|
apiUrl: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
|
@ -132,6 +135,7 @@ const nullableEnvVars = [
|
||||||
'SENDGRID_REMINDER_TEMPLATE_ID',
|
'SENDGRID_REMINDER_TEMPLATE_ID',
|
||||||
'SENDGRID_RESET_PASSWORD_TEMPLATE_ID',
|
'SENDGRID_RESET_PASSWORD_TEMPLATE_ID',
|
||||||
'SENDGRID_INSTALLATION_TEMPLATE_ID',
|
'SENDGRID_INSTALLATION_TEMPLATE_ID',
|
||||||
|
'READWISE_API_URL',
|
||||||
] // Allow some vars to be null/empty
|
] // Allow some vars to be null/empty
|
||||||
|
|
||||||
/* If not in GAE and Prod/QA/Demo env (f.e. on localhost/dev env), allow following env vars to be null */
|
/* If not in GAE and Prod/QA/Demo env (f.e. on localhost/dev env), allow following env vars to be null */
|
||||||
|
|
@ -245,6 +249,10 @@ export function getEnv(): BackendEnv {
|
||||||
installationTemplateId: parse('SENDGRID_INSTALLATION_TEMPLATE_ID'),
|
installationTemplateId: parse('SENDGRID_INSTALLATION_TEMPLATE_ID'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const readwise = {
|
||||||
|
apiUrl: parse('READWISE_API_URL'),
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pg,
|
pg,
|
||||||
client,
|
client,
|
||||||
|
|
@ -262,6 +270,7 @@ export function getEnv(): BackendEnv {
|
||||||
elastic,
|
elastic,
|
||||||
sender,
|
sender,
|
||||||
sendgrid,
|
sendgrid,
|
||||||
|
readwise,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue