diff --git a/packages/api/package.json b/packages/api/package.json index 7a8cfbc11..404c13024 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -53,6 +53,7 @@ "firebase-admin": "^10.0.2", "googleapis": "^105.0.0", "graphql": "^15.3.0", + "graphql-fields": "^2.0.3", "graphql-middleware": "^6.0.10", "graphql-shield": "^7.5.0", "highlightjs": "^9.16.2", @@ -95,6 +96,7 @@ "@types/cookie-parser": "^1.4.2", "@types/dompurify": "^2.0.4", "@types/express": "^4.17.7", + "@types/graphql-fields": "^1.3.4", "@types/highlightjs": "^9.12.2", "@types/intercom-client": "^2.11.8", "@types/jsonwebtoken": "^8.5.0", diff --git a/packages/api/src/elastic/pages.ts b/packages/api/src/elastic/pages.ts index 2b53c9509..d503e83a1 100644 --- a/packages/api/src/elastic/pages.ts +++ b/packages/api/src/elastic/pages.ts @@ -274,7 +274,8 @@ export const deletePage = async ( } export const getPageByParam = async ( - param: Record + param: Record, + includeOriginalHtml = false ): Promise => { try { const params = { @@ -291,7 +292,7 @@ export const getPageByParam = async ( }, size: 1, _source: { - excludes: ['originalHtml'], + excludes: includeOriginalHtml ? [] : ['originalHtml'], }, } diff --git a/packages/api/src/resolvers/article/index.ts b/packages/api/src/resolvers/article/index.ts index 013cab0d1..679757f33 100644 --- a/packages/api/src/resolvers/article/index.ts +++ b/packages/api/src/resolvers/article/index.ts @@ -69,6 +69,7 @@ import { parseSearchQuery } from '../../utils/search' import { createPageSaveRequest } from '../../services/create_page_save_request' import { analytics } from '../../utils/analytics' import { env } from '../../env' +import graphqlFields from 'graphql-fields' import { ArticleSavingRequestStatus, @@ -397,12 +398,14 @@ export const getArticleResolver: ResolverFn< Record, WithDataSourcesContext, QueryArticleArgs -> = async (_obj, { slug }, { claims, pubsub }) => { +> = async (_obj, { slug }, { claims, pubsub }, info) => { try { if (!claims?.uid) { return { errorCodes: [ArticleErrorCode.Unauthorized] } } + const includeOriginalHtml = !!graphqlFields(info).article.originalHtml + analytics.track({ userId: claims?.uid, event: 'link_fetched', @@ -414,8 +417,14 @@ export const getArticleResolver: ResolverFn< // We allow the backend to use the ID instead of a slug to fetch the article const page = - (await getPageByParam({ userId: claims.uid, slug })) || - (await getPageByParam({ userId: claims.uid, _id: slug })) + (await getPageByParam( + { userId: claims.uid, slug }, + includeOriginalHtml + )) || + (await getPageByParam( + { userId: claims.uid, _id: slug }, + includeOriginalHtml + )) if (!page) { return { errorCodes: [ArticleErrorCode.NotFound] } diff --git a/packages/web/lib/networking/queries/useGetArticleOriginalHtmlQuery.tsx b/packages/web/lib/networking/queries/useGetArticleOriginalHtmlQuery.tsx new file mode 100644 index 000000000..bfb4c4e14 --- /dev/null +++ b/packages/web/lib/networking/queries/useGetArticleOriginalHtmlQuery.tsx @@ -0,0 +1,77 @@ +import { gql } from 'graphql-request' +import useSWRImmutable, { Cache } from 'swr' +import { makeGqlFetcher, RequestContext, ssrFetcher } from '../networkHelpers' +import { ScopedMutator } from 'swr/dist/types' +import { LibraryItems } from './useGetLibraryItemsQuery' + +type ArticleQueryInput = { + username?: string + slug?: string + includeFriendsHighlights?: boolean +} + +type ArticleData = { + article: NestedArticleData +} + +type NestedArticleData = { + article: ArticleAttributes + errorCodes?: string[] +} + +export type ArticleAttributes = { + id: string + originalHtml: string +} + +const query = gql` + query GetArticle( + $username: String! + $slug: String! + ) { + article(username: $username, slug: $slug) { + ... on ArticleSuccess { + article { + id + originalHtml + } + } + ... on ArticleError { + errorCodes + } + } + } +` + +export function useGetArticleOriginalHtmlQuery({ + username, + slug, +}: ArticleQueryInput): string | undefined { + const variables = { + username, + slug, + } + + const { data } = useSWRImmutable( + slug ? [query, username, slug] : null, + makeGqlFetcher(variables) + ) + + const resultData: ArticleData | undefined = data as ArticleData + console.log("RESULT", JSON.stringify(data)) + + return resultData?.article.article.originalHtml +} + +export async function originalHtmlQuery( + context: RequestContext, + input: ArticleQueryInput +): Promise { + const resultData = (await ssrFetcher(context, query, input, false)) as ArticleData + console.log(JSON.stringify(resultData)) + // if (resultData?.article.article.originalHtml) { + // return resultData?.article.article.originalHtml + // } + + return Promise.reject() +} diff --git a/packages/web/pages/[username]/[slug]/original.tsx b/packages/web/pages/[username]/[slug]/original.tsx new file mode 100644 index 000000000..507c493b3 --- /dev/null +++ b/packages/web/pages/[username]/[slug]/original.tsx @@ -0,0 +1,21 @@ +import { useRouter } from 'next/router' +import { useGetArticleOriginalHtmlQuery } from '../../../lib/networking/queries/useGetArticleOriginalHtmlQuery' + +export default function Home(): JSX.Element { + const router = useRouter() + const originalHtml = useGetArticleOriginalHtmlQuery({ + username: router.query.username as string, + slug: router.query.slug as string, + includeFriendsHighlights: false, + }) + + if (!originalHtml) { + return
error
+ } + + return ( + + ) +}