From e1d670740f06727012f4ea7d09ebf90a4c1fe09a Mon Sep 17 00:00:00 2001 From: MrOrz Date: Wed, 10 Jan 2024 23:26:41 +0800 Subject: [PATCH 1/3] refactor(typegen): turn off fragment masking - because it complicates things too much and gives little gain for devs --- codegen.ts | 4 +- lib/__tests__/text.tsx | 59 ++--- lib/text.tsx | 21 +- typegen/fragment-masking.ts | 55 ----- typegen/graphql.ts | 453 ++++++++++++++++++++++++++++-------- typegen/index.ts | 1 - 6 files changed, 386 insertions(+), 207 deletions(-) delete mode 100644 typegen/fragment-masking.ts diff --git a/codegen.ts b/codegen.ts index bf6e2d4c..780d956a 100644 --- a/codegen.ts +++ b/codegen.ts @@ -9,9 +9,7 @@ const config: CodegenConfig = { preset: 'client', plugins: [], presetConfig: { - // Rename useFragment to avoid conflicting with ESLint React hook rule - // https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#embrace-fragment-masking-principles - fragmentMasking: { unmaskFunctionName: 'getFragmentData' }, + fragmentMasking: false, }, }, }, diff --git a/lib/__tests__/text.tsx b/lib/__tests__/text.tsx index b3752408..b24e4d02 100644 --- a/lib/__tests__/text.tsx +++ b/lib/__tests__/text.tsx @@ -1,11 +1,9 @@ import React from 'react'; -import { makeFragmentData } from '../../typegen'; import { linkify, nl2br, truncate, highlightSections, - HighlightFields, } from '../text'; describe('text', () => { @@ -185,28 +183,22 @@ describe('highlightSections', () => { it('return empty arrays for empty highlights', () => { expect( highlightSections( - makeFragmentData( - { - text: null, - reference: null, - hyperlinks: null, - }, - HighlightFields - ), + { + text: null, + reference: null, + hyperlinks: null, + }, classes ) ).toMatchInlineSnapshot(`Array []`); expect( highlightSections( - makeFragmentData( - { - text: null, - reference: null, - hyperlinks: [], - }, - HighlightFields - ), + { + text: null, + reference: null, + hyperlinks: [], + }, classes ) ).toMatchInlineSnapshot(`Array []`); @@ -215,23 +207,20 @@ describe('highlightSections', () => { it('wraps to all highlightable fields', () => { expect( highlightSections( - makeFragmentData( - { - text: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', - reference: - '【誤導】大陸東北男子穿短袖短褲晨跑凍成人型冰棍影片?2018酒醉凍傷致死事件\n\nMyGoPen查證參考:\nhttps://www.mygopen.com/2021/01/freeze-Morning-jogging.html', - hyperlinks: [ - { - title: - 'MyGoPen|這是假消息: 【假LINE】大同寶寶貼圖詐騙新手法!連到外部網站再騙你加', - summary: - '今年為一九六四年以來首度無颱風侵台', - }, - ], - }, - HighlightFields - ), + { + text: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', + reference: + '【誤導】大陸東北男子穿短袖短褲晨跑凍成人型冰棍影片?2018酒醉凍傷致死事件\n\nMyGoPen查證參考:\nhttps://www.mygopen.com/2021/01/freeze-Morning-jogging.html', + hyperlinks: [ + { + title: + 'MyGoPen|這是假消息: 【假LINE】大同寶寶貼圖詐騙新手法!連到外部網站再騙你加', + summary: + '今年為一九六四年以來首度無颱風侵台', + }, + ], + }, classes ) ).toMatchInlineSnapshot(` diff --git a/lib/text.tsx b/lib/text.tsx index 5aeb82cb..5d715a2f 100644 --- a/lib/text.tsx +++ b/lib/text.tsx @@ -1,9 +1,7 @@ import React, { CSSProperties } from 'react'; import { gql } from 'graphql-tag'; -import { print } from 'graphql'; import { withStyles, WithStyles, createStyles } from '@material-ui/core/styles'; -import { FragmentType, getFragmentData } from '../typegen/fragment-masking'; -import { graphql } from '../typegen'; +import { HighlightFieldsFragment } from 'typegen/graphql'; const BREAK = { $$BREAK: true } as const; @@ -260,7 +258,7 @@ function getMarkElems( .filter(jsxElem => !!jsxElem); } -const TypedHighlightFields = graphql(/* GraphQL */ ` +export const HighlightFields = gql` fragment HighlightFields on Highlights { text reference @@ -269,31 +267,20 @@ const TypedHighlightFields = graphql(/* GraphQL */ ` summary } } -`); - -/** - * @deprecated - Remove export after all dependent queries use codegen graphql() instead of graphql-tag gql. - * @see https://stackoverflow.com/a/72802504/1582110 - */ -export const HighlightFields = gql` - ${print(TypedHighlightFields)} `; /** * Processes Highlights object from rumors-api */ export function highlightSections( - highlightFields: FragmentType, + highlightFields: HighlightFieldsFragment, classes: { highlight?: string; reference?: string; hyperlinks?: string; } ) { - const { text, reference, hyperlinks } = getFragmentData( - TypedHighlightFields, - highlightFields - ); + const { text, reference, hyperlinks } = highlightFields; const jsxElems = []; diff --git a/typegen/fragment-masking.ts b/typegen/fragment-masking.ts deleted file mode 100644 index ae28cdfb..00000000 --- a/typegen/fragment-masking.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { - TypedDocumentNode as DocumentNode, - ResultOf, -} from '@graphql-typed-document-node/core'; - -export type FragmentType< - TDocumentType extends DocumentNode -> = TDocumentType extends DocumentNode - ? TType extends { ' $fragmentName'?: infer TKey } - ? TKey extends string - ? { ' $fragmentRefs'?: { [key in TKey]: TType } } - : never - : never - : never; - -// return non-nullable if `fragmentType` is non-nullable -export function getFragmentData( - _documentNode: DocumentNode, - fragmentType: FragmentType> -): TType; -// return nullable if `fragmentType` is nullable -export function getFragmentData( - _documentNode: DocumentNode, - fragmentType: FragmentType> | null | undefined -): TType | null | undefined; -// return array of non-nullable if `fragmentType` is array of non-nullable -export function getFragmentData( - _documentNode: DocumentNode, - fragmentType: ReadonlyArray>> -): ReadonlyArray; -// return array of nullable if `fragmentType` is array of nullable -export function getFragmentData( - _documentNode: DocumentNode, - fragmentType: - | ReadonlyArray>> - | null - | undefined -): ReadonlyArray | null | undefined; -export function getFragmentData( - _documentNode: DocumentNode, - fragmentType: - | FragmentType> - | ReadonlyArray>> - | null - | undefined -): TType | ReadonlyArray | null | undefined { - return fragmentType as any; -} - -export function makeFragmentData< - F extends DocumentNode, - FT extends ResultOf ->(data: FT, _fragment: F): FragmentType { - return data as FragmentType; -} diff --git a/typegen/graphql.ts b/typegen/graphql.ts index a80795b2..a64a818f 100644 --- a/typegen/graphql.ts +++ b/typegen/graphql.ts @@ -26,11 +26,14 @@ export type Query = { * */ GetUser?: Maybe; + GetYdoc?: Maybe; + ListAIResponses: AiResponseConnection; ListAnalytics: AnalyticsConnection; ListArticleReplyFeedbacks?: Maybe; ListArticles?: Maybe; ListBlockedUsers: UserConnection; ListCategories?: Maybe; + ListCooccurrences?: Maybe; ListReplies?: Maybe; ListReplyRequests?: Maybe; ValidateSlug?: Maybe; @@ -58,6 +61,20 @@ export type QueryGetUserArgs = { }; +export type QueryGetYdocArgs = { + id: Scalars['String']; +}; + + +export type QueryListAiResponsesArgs = { + after?: InputMaybe; + before?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + orderBy?: InputMaybe>>; +}; + + export type QueryListAnalyticsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -102,6 +119,15 @@ export type QueryListCategoriesArgs = { }; +export type QueryListCooccurrencesArgs = { + after?: InputMaybe; + before?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + orderBy?: InputMaybe>>; +}; + + export type QueryListRepliesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -126,9 +152,13 @@ export type QueryValidateSlugArgs = { export type Article = Node & { __typename?: 'Article'; - articleCategories?: Maybe>>; + /** Automated reply from AI before human fact checkers compose an fact check */ + aiReplies: Array; + /** Automated transcript */ + aiTranscripts: Array; + articleCategories: Array; /** Connections between this article and replies. Sorted by the logic described in https://github.com/cofacts/rumors-line-bot/issues/78. */ - articleReplies?: Maybe>>; + articleReplies: Array; /** Message event type */ articleType: ArticleTypeEnum; /** Attachment hash to search or identify files */ @@ -136,16 +166,18 @@ export type Article = Node & { /** Attachment URL for this article. */ attachmentUrl?: Maybe; /** Number of normal article categories */ - categoryCount?: Maybe; + categoryCount: Scalars['Int']; + cooccurrences?: Maybe>; + /** May be null for legacy articles */ createdAt?: Maybe; /** Hyperlinks in article text */ hyperlinks?: Maybe>>; id: Scalars['ID']; lastRequestedAt?: Maybe; references?: Maybe>>; - relatedArticles?: Maybe; + relatedArticles: ArticleConnection; /** Number of normal article replies */ - replyCount?: Maybe; + replyCount: Scalars['Int']; replyRequestCount?: Maybe; replyRequests?: Maybe>>; /** If the current user has requested for reply for this article. Null if not logged in. */ @@ -172,6 +204,7 @@ export type ArticleArticleRepliesArgs = { status?: InputMaybe; statuses?: InputMaybe>; userId?: InputMaybe; + userIds?: InputMaybe>; }; @@ -203,6 +236,158 @@ export type Node = { id: Scalars['ID']; }; +/** A ChatGPT reply for an article with no human fact-checks yet */ +export type AiReply = AiResponse & Node & { + __typename?: 'AIReply'; + createdAt: Scalars['String']; + /** The id for the document that this AI response is for. */ + docId?: Maybe; + id: Scalars['ID']; + /** Processing status of AI */ + status: AiResponseStatusEnum; + /** AI response text. Populated after status becomes SUCCESS. */ + text?: Maybe; + /** AI response type */ + type: AiResponseTypeEnum; + updatedAt?: Maybe; + /** The usage returned from OpenAI. Populated after status becomes SUCCESS. */ + usage?: Maybe; + /** The user triggered this AI response */ + user?: Maybe; +}; + +/** Denotes an AI processed response and its processing status. */ +export type AiResponse = { + createdAt: Scalars['String']; + /** The id for the document that this AI response is for. */ + docId?: Maybe; + id: Scalars['ID']; + /** Processing status of AI */ + status: AiResponseStatusEnum; + /** AI response text. Populated after status becomes SUCCESS. */ + text?: Maybe; + /** AI response type */ + type: AiResponseTypeEnum; + updatedAt?: Maybe; + /** The user triggered this AI response */ + user?: Maybe; +}; + +export enum AiResponseStatusEnum { + Error = 'ERROR', + Loading = 'LOADING', + Success = 'SUCCESS' +} + +export enum AiResponseTypeEnum { + /** The AI Response is an automated analysis / reply of an article. */ + AiReply = 'AI_REPLY', + /** AI transcribed text of the specified article. */ + Transcript = 'TRANSCRIPT' +} + +export type User = Node & { + __typename?: 'User'; + appId?: Maybe; + /** Returns only for current user. Returns `null` otherwise. */ + appUserId?: Maybe; + /** Returns only for current user. Returns `null` otherwise. */ + availableAvatarTypes?: Maybe>>; + /** return avatar data as JSON string, currently only used when avatarType is OpenPeeps */ + avatarData?: Maybe; + avatarType?: Maybe; + /** returns avatar url from facebook, github or gravatar */ + avatarUrl?: Maybe; + bio?: Maybe; + /** If not null, the user is blocked with the announcement in this string. */ + blockedReason?: Maybe; + /** List of contributions made by the user */ + contributions?: Maybe>>; + createdAt?: Maybe; + /** Returns only for current user. Returns `null` otherwise. */ + email?: Maybe; + /** Returns only for current user. Returns `null` otherwise. */ + facebookId?: Maybe; + /** Returns only for current user. Returns `null` otherwise. */ + githubId?: Maybe; + id: Scalars['ID']; + lastActiveAt?: Maybe; + level: Scalars['Int']; + name?: Maybe; + points: PointInfo; + /** Number of articles this user has replied to */ + repliedArticleCount: Scalars['Int']; + slug?: Maybe; + /** Returns only for current user. Returns `null` otherwise. */ + twitterId?: Maybe; + updatedAt?: Maybe; + /** Number of article replies this user has given feedbacks */ + votedArticleReplyCount: Scalars['Int']; +}; + + +export type UserContributionsArgs = { + dateRange?: InputMaybe; +}; + +export enum AvatarTypeEnum { + Facebook = 'Facebook', + Github = 'Github', + Gravatar = 'Gravatar', + OpenPeeps = 'OpenPeeps' +} + +/** List only the entries that were created between the specific time range. The time range value is in elasticsearch date format (https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html) */ +export type TimeRangeInput = { + EQ?: InputMaybe; + GT?: InputMaybe; + GTE?: InputMaybe; + LT?: InputMaybe; + LTE?: InputMaybe; +}; + +export type Contribution = { + __typename?: 'Contribution'; + count?: Maybe; + date?: Maybe; +}; + +/** Information of a user's point. Only available for current user. */ +export type PointInfo = { + __typename?: 'PointInfo'; + /** Points required for current level */ + currentLevel: Scalars['Int']; + /** Points required for next level. null when there is no next level. */ + nextLevel: Scalars['Int']; + /** Points earned by the current user */ + total: Scalars['Int']; +}; + +export type OpenAiCompletionUsage = { + __typename?: 'OpenAICompletionUsage'; + completionTokens: Scalars['Int']; + promptTokens: Scalars['Int']; + totalTokens: Scalars['Int']; +}; + +/** Transcript from OCR or speech-to-text AI models for the specified MediaEntry ID as docId. */ +export type AiTranscript = AiResponse & Node & { + __typename?: 'AITranscript'; + createdAt: Scalars['String']; + /** The id for the document that this AI response is for. */ + docId?: Maybe; + id: Scalars['ID']; + /** Processing status of AI */ + status: AiResponseStatusEnum; + /** AI response text. Populated after status becomes SUCCESS. */ + text?: Maybe; + /** AI response type */ + type: AiResponseTypeEnum; + updatedAt?: Maybe; + /** The user triggered this AI response */ + user?: Maybe; +}; + export enum ArticleCategoryStatusEnum { /** Created by a blocked user violating terms of use. */ Blocked = 'BLOCKED', @@ -347,83 +532,6 @@ export type ArticleCategoryFeedback = { vote?: Maybe; }; -export type User = Node & { - __typename?: 'User'; - appId?: Maybe; - /** Returns only for current user. Returns `null` otherwise. */ - appUserId?: Maybe; - /** Returns only for current user. Returns `null` otherwise. */ - availableAvatarTypes?: Maybe>>; - /** return avatar data as JSON string, currently only used when avatarType is OpenPeeps */ - avatarData?: Maybe; - avatarType?: Maybe; - /** returns avatar url from facebook, github or gravatar */ - avatarUrl?: Maybe; - bio?: Maybe; - /** If not null, the user is blocked with the announcement in this string. */ - blockedReason?: Maybe; - /** List of contributions made by the user */ - contributions?: Maybe>>; - createdAt?: Maybe; - /** Returns only for current user. Returns `null` otherwise. */ - email?: Maybe; - /** Returns only for current user. Returns `null` otherwise. */ - facebookId?: Maybe; - /** Returns only for current user. Returns `null` otherwise. */ - githubId?: Maybe; - id: Scalars['ID']; - lastActiveAt?: Maybe; - level: Scalars['Int']; - name?: Maybe; - points: PointInfo; - /** Number of articles this user has replied to */ - repliedArticleCount: Scalars['Int']; - slug?: Maybe; - /** Returns only for current user. Returns `null` otherwise. */ - twitterId?: Maybe; - updatedAt?: Maybe; - /** Number of article replies this user has given feedbacks */ - votedArticleReplyCount: Scalars['Int']; -}; - - -export type UserContributionsArgs = { - dateRange?: InputMaybe; -}; - -export enum AvatarTypeEnum { - Facebook = 'Facebook', - Github = 'Github', - Gravatar = 'Gravatar', - OpenPeeps = 'OpenPeeps' -} - -/** List only the entries that were created between the specific time range. The time range value is in elasticsearch date format (https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html) */ -export type TimeRangeInput = { - EQ?: InputMaybe; - GT?: InputMaybe; - GTE?: InputMaybe; - LT?: InputMaybe; - LTE?: InputMaybe; -}; - -export type Contribution = { - __typename?: 'Contribution'; - count?: Maybe; - date?: Maybe; -}; - -/** Information of a user's point. Only available for current user. */ -export type PointInfo = { - __typename?: 'PointInfo'; - /** Points required for current level */ - currentLevel: Scalars['Int']; - /** Points required for next level. null when there is no next level. */ - nextLevel: Scalars['Int']; - /** Points earned by the current user */ - total: Scalars['Int']; -}; - export enum FeedbackVote { Downvote = 'DOWNVOTE', Neutral = 'NEUTRAL', @@ -442,20 +550,21 @@ export type ArticleReply = { __typename?: 'ArticleReply'; appId: Scalars['String']; article?: Maybe
; - articleId?: Maybe; - canUpdateStatus?: Maybe; + articleId: Scalars['String']; + canUpdateStatus: Scalars['Boolean']; + /** May be null for legacy article-replies */ createdAt?: Maybe; - feedbackCount?: Maybe; - feedbacks?: Maybe>>; - negativeFeedbackCount?: Maybe; + feedbackCount: Scalars['Int']; + feedbacks: Array; + negativeFeedbackCount: Scalars['Int']; /** The feedback of current user. null when not logged in or not voted yet. */ ownVote?: Maybe; - positiveFeedbackCount?: Maybe; + positiveFeedbackCount: Scalars['Int']; reply?: Maybe; - replyId?: Maybe; + replyId: Scalars['String']; /** Cached reply type value stored in ArticleReply */ replyType?: Maybe; - status?: Maybe; + status: ArticleReplyStatusEnum; updatedAt?: Maybe; /** The user who conencted this reply and this article. */ user?: Maybe; @@ -506,16 +615,17 @@ export type ArticleReplyFeedback = Node & { export type Reply = Node & { __typename?: 'Reply'; - articleReplies?: Maybe>>; + articleReplies: Array; + /** May be null for legacy replies */ createdAt?: Maybe; /** Hyperlinks in reply text or reference. May be empty array if no URLs are included. `null` when hyperlinks are still fetching. */ hyperlinks?: Maybe>>; id: Scalars['ID']; reference?: Maybe; /** Replies that has similar text or references of this current reply */ - similarReplies?: Maybe; + similarReplies: ReplyConnection; text?: Maybe; - type?: Maybe; + type: ReplyTypeEnum; /** The user submitted this reply version */ user?: Maybe; }; @@ -590,11 +700,22 @@ export enum AttachmentVariantEnum { Thumbnail = 'THUMBNAIL' } +export type Cooccurrence = Node & { + __typename?: 'Cooccurrence'; + appId: Scalars['String']; + articleIds: Array; + articles: Array
; + createdAt: Scalars['String']; + id: Scalars['ID']; + updatedAt: Scalars['String']; + userId: Scalars['String']; +}; + export type ArticleReference = { __typename?: 'ArticleReference'; - createdAt?: Maybe; + createdAt: Scalars['String']; permalink?: Maybe; - type?: Maybe; + type: ArticleReferenceTypeEnum; }; /** Where this article is collected from. */ @@ -636,6 +757,11 @@ export type ArticleConnectionEdge = Edge & { __typename?: 'ArticleConnectionEdge'; cursor: Scalars['String']; highlight?: Maybe; + /** + * The search hit's similarity with provided mediaUrl. + * Ranges from 0 to 1. 0 if mediaUrl is not provided, or the hit is not matched by mediaUrl. + */ + mediaSimilarity: Scalars['Float']; node: Article; score?: Maybe; }; @@ -709,6 +835,72 @@ export enum AnalyticsDocTypeEnum { Reply = 'REPLY' } +export type Ydoc = { + __typename?: 'Ydoc'; + /** Binary that stores as base64 encoded string */ + data?: Maybe; + /** Ydoc snapshots which are used to restore to specific version */ + versions?: Maybe>>; +}; + +export type YdocVersion = { + __typename?: 'YdocVersion'; + createdAt?: Maybe; + /** Binary that stores as base64 encoded string */ + snapshot?: Maybe; +}; + +export type ListAiResponsesFilter = { + /** Show only AI responses created by a specific app. */ + appId?: InputMaybe; + /** List only the AI responses that were created between the specific time range. */ + createdAt?: InputMaybe; + /** If specified, only return AI repsonses under the specified doc IDs. */ + docIds?: InputMaybe>; + /** If given, only list out AI responses with specific IDs */ + ids?: InputMaybe>; + /** Only list the AI responses created by the currently logged in user */ + selfOnly?: InputMaybe; + /** If specified, only return AI repsonses under the specified statuses. */ + statuses?: InputMaybe>; + /** If specified, only return AI repsonses with the specified types. */ + types?: InputMaybe>; + /** List only the AI responses updated within the specific time range. */ + updatedAt?: InputMaybe; + /** Show only AI responses created by the specific user. */ + userId?: InputMaybe; + /** Show only AI responses created by the specified users. */ + userIds?: InputMaybe>; +}; + +/** An entry of orderBy argument. Specifies field name and the sort order. Only one field name is allowd per entry. */ +export type ListAiResponsesOrderBy = { + createdAt?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type AiResponseConnection = Connection & { + __typename?: 'AIResponseConnection'; + edges: Array; + pageInfo: AiResponseConnectionPageInfo; + /** The total count of the entire collection, regardless of "before", "after". */ + totalCount: Scalars['Int']; +}; + +export type AiResponseConnectionEdge = Edge & { + __typename?: 'AIResponseConnectionEdge'; + cursor: Scalars['String']; + highlight?: Maybe; + node: AiResponse; + score?: Maybe; +}; + +export type AiResponseConnectionPageInfo = PageInfo & { + __typename?: 'AIResponseConnectionPageInfo'; + firstCursor?: Maybe; + lastCursor?: Maybe; +}; + export type ListAnalyticsFilter = { /** List only the activities between the specific time range. */ date?: InputMaybe; @@ -770,6 +962,8 @@ export type ListArticleReplyFeedbackFilter = { updatedAt?: InputMaybe; /** Show only article reply feedbacks created by the specific user. */ userId?: InputMaybe; + /** Show only article reply feedbacks created by the specified users. */ + userIds?: InputMaybe>; /** When specified, list only article reply feedbacks with specified vote */ vote?: InputMaybe>>; }; @@ -862,8 +1056,12 @@ export type ListArticleFilter = { selfOnly?: InputMaybe; /** Returns only articles with the specified statuses */ statuses?: InputMaybe>; + /** Specifies how the transcript of `mediaUrl` can be used to search. Can only specify `transcript` when `mediaUrl` is specified. */ + transcript?: InputMaybe; /** Show only articles created by the specific user. */ userId?: InputMaybe; + /** Show only articles created by the specified users. */ + userIds?: InputMaybe>; }; export type UserAndExistInput = { @@ -888,6 +1086,8 @@ export type ArticleReplyFilterInput = { statuses?: InputMaybe>; /** Show only articleReplies created by the specific user. */ userId?: InputMaybe; + /** Show only articleReplies created by the specified users. */ + userIds?: InputMaybe>; }; export enum ArticleStatusEnum { @@ -896,6 +1096,16 @@ export enum ArticleStatusEnum { Normal = 'NORMAL' } +export type TranscriptFilter = { + /** + * more_like_this query's "minimum_should_match" query param for the transcript of `mediaUrl` + * See https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-minimum-should-match.html for possible values. + */ + minimumShouldMatch?: InputMaybe; + /** Only used when `filter.mediaUrl` is provided. Generates transcript if provided `filter.mediaUrl` is not transcribed previously. */ + shouldCreate?: InputMaybe; +}; + /** An entry of orderBy argument. Specifies field name and the sort order. Only one field name is allowd per entry. */ export type ListArticleOrderBy = { _score?: InputMaybe; @@ -967,6 +1177,39 @@ export type ListCategoryConnectionPageInfo = PageInfo & { lastCursor?: Maybe; }; +export type ListCooccurrenceFilter = { + /** List only the cooccurrence that were last updated within the specific time range. */ + updatedAt?: InputMaybe; +}; + +/** An entry of orderBy argument. Specifies field name and the sort order. Only one field name is allowd per entry. */ +export type ListCooccurrenceOrderBy = { + createdAt?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type ListCooccurrenceConnection = Connection & { + __typename?: 'ListCooccurrenceConnection'; + edges: Array; + pageInfo: ListCooccurrenceConnectionPageInfo; + /** The total count of the entire collection, regardless of "before", "after". */ + totalCount: Scalars['Int']; +}; + +export type ListCooccurrenceConnectionEdge = Edge & { + __typename?: 'ListCooccurrenceConnectionEdge'; + cursor: Scalars['String']; + highlight?: Maybe; + node: Cooccurrence; + score?: Maybe; +}; + +export type ListCooccurrenceConnectionPageInfo = PageInfo & { + __typename?: 'ListCooccurrenceConnectionPageInfo'; + firstCursor?: Maybe; + lastCursor?: Maybe; +}; + export type ListReplyFilter = { /** Show only replies created by a specific app. */ appId?: InputMaybe; @@ -983,6 +1226,8 @@ export type ListReplyFilter = { types?: InputMaybe>>; /** Show only replies created by the specific user. */ userId?: InputMaybe; + /** Show only replies created by the specified users. */ + userIds?: InputMaybe>; }; /** An entry of orderBy argument. Specifies field name and the sort order. Only one field name is allowd per entry. */ @@ -1005,6 +1250,8 @@ export type ListReplyRequestFilter = { statuses?: InputMaybe>; /** Show only reply requests created by the specific user. */ userId?: InputMaybe; + /** Show only reply requests created by the specified users. */ + userIds?: InputMaybe>; }; /** An entry of orderBy argument. Specifies field name and the sort order. Only one field name is allowd per entry. */ @@ -1055,6 +1302,8 @@ export enum SlugErrorEnum { export type Mutation = { __typename?: 'Mutation'; + /** Create an AI reply for a specific article. If existed, returns an existing one. If information in the article is not sufficient for AI, return null. */ + CreateAIReply?: Maybe; /** Create an article and/or a replyRequest */ CreateArticle?: Maybe; /** Adds specified category to specified article. */ @@ -1069,6 +1318,8 @@ export type Mutation = { CreateOrUpdateArticleCategoryFeedback?: Maybe; /** Create or update a feedback on an article-reply connection */ CreateOrUpdateArticleReplyFeedback?: Maybe; + /** Create or update a cooccurrence for the given articles */ + CreateOrUpdateCooccurrence?: Maybe; /** Create or update a reply request for the given article */ CreateOrUpdateReplyRequest?: Maybe
; /** Create or update a feedback on a reply request reason */ @@ -1089,6 +1340,11 @@ export type Mutation = { }; +export type MutationCreateAiReplyArgs = { + articleId: Scalars['String']; +}; + + export type MutationCreateArticleArgs = { reason?: InputMaybe; reference: ArticleReferenceInput; @@ -1140,6 +1396,11 @@ export type MutationCreateOrUpdateArticleReplyFeedbackArgs = { }; +export type MutationCreateOrUpdateCooccurrenceArgs = { + articleIds?: InputMaybe>; +}; + + export type MutationCreateOrUpdateReplyRequestArgs = { articleId: Scalars['String']; reason?: InputMaybe; @@ -1199,6 +1460,6 @@ export type MutationResult = { id?: Maybe; }; -export type HighlightFieldsFragment = { __typename?: 'Highlights', text?: string | null, reference?: string | null, hyperlinks?: Array<{ __typename?: 'Hyperlink', title?: string | null, summary?: string | null } | null> | null } & { ' $fragmentName'?: 'HighlightFieldsFragment' }; +export type HighlightFieldsFragment = { __typename?: 'Highlights', text?: string | null, reference?: string | null, hyperlinks?: Array<{ __typename?: 'Hyperlink', title?: string | null, summary?: string | null } | null> | null }; export const HighlightFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"HighlightFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Highlights"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"text"}},{"kind":"Field","name":{"kind":"Name","value":"reference"}},{"kind":"Field","name":{"kind":"Name","value":"hyperlinks"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"summary"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/typegen/index.ts b/typegen/index.ts index e33dcd39..8a12aabd 100644 --- a/typegen/index.ts +++ b/typegen/index.ts @@ -1,2 +1 @@ export * from './gql'; -export * from './fragment-masking'; From c7d71dd5be1a7aa5524d3a3544cd7aaf45e7dab3 Mon Sep 17 00:00:00 2001 From: MrOrz Date: Wed, 10 Jan 2024 23:34:46 +0800 Subject: [PATCH 2/3] fix(lib): lint --- lib/__tests__/text.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/__tests__/text.tsx b/lib/__tests__/text.tsx index b24e4d02..66bb69c6 100644 --- a/lib/__tests__/text.tsx +++ b/lib/__tests__/text.tsx @@ -1,10 +1,5 @@ import React from 'react'; -import { - linkify, - nl2br, - truncate, - highlightSections, -} from '../text'; +import { linkify, nl2br, truncate, highlightSections } from '../text'; describe('text', () => { describe('linkify', () => { From 9982f1798942f54ce6f05dd47358fb6e956fb838 Mon Sep 17 00:00:00 2001 From: MrOrz Date: Wed, 10 Jan 2024 23:42:59 +0800 Subject: [PATCH 3/3] fix(codegen): document syntax - ? is preventing the codegen from matching anything --- codegen.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/codegen.ts b/codegen.ts index 780d956a..672e4285 100644 --- a/codegen.ts +++ b/codegen.ts @@ -3,7 +3,11 @@ import { CodegenConfig } from '@graphql-codegen/cli'; const config: CodegenConfig = { // schema: 'http://localhost:5000/graphql', schema: 'https://dev-api.cofacts.tw/graphql', - documents: ['pages/**/*.tsx?', 'components/**/*.tsx?', 'lib/**/*.tsx'], + documents: [ + 'pages/**/*.{ts,tsx}', + 'components/**/*.{ts,tsx}', + 'lib/**/*.{ts,tsx}', + ], generates: { './typegen/': { preset: 'client',