diff --git a/package/package.json b/package/package.json index 8603321..6cecb8f 100644 --- a/package/package.json +++ b/package/package.json @@ -1,6 +1,6 @@ { "name": "hashnode-client", - "version": "1.0.2", + "version": "1.0.3", "type": "module", "description": "A JavaScript client for the Headless Hashnode. The package contains helpful ReactJS hooks to use blog data using its GraphQL APIs.", "author": { diff --git a/package/src/index.js b/package/src/index.js index 561802e..59eca37 100644 --- a/package/src/index.js +++ b/package/src/index.js @@ -1,12 +1,13 @@ - import useHashnodePosts from "./useHashnodePosts"; import useHashnodePostDetails from "./useHashnodePostDetails"; -import useHashnodePage from './useHashnodePage'; +import useHashnodePage from "./useHashnodePage"; import useHashnodeComments from "./useHashnodeComments"; +import useHashnodePublishPost from "./useHashnodePublishPost"; export { useHashnodePosts, useHashnodePostDetails, useHashnodePage, - useHashnodeComments -} \ No newline at end of file + useHashnodeComments, + useHashnodePublishPost, +}; diff --git a/package/src/lib/graphQLClient.js b/package/src/lib/graphQLClient.js index 9de8653..51e640c 100644 --- a/package/src/lib/graphQLClient.js +++ b/package/src/lib/graphQLClient.js @@ -2,7 +2,11 @@ import { GraphQLClient } from "graphql-request"; -export const getClient = () => { +export const getClient = (token = null) => { const client = new GraphQLClient(`https://gql.hashnode.com`); + + if (token) { + client.setHeader("Authorization", `Bearer ${token}`); + } return client; -} \ No newline at end of file +}; diff --git a/package/src/mutations/post.js b/package/src/mutations/post.js new file mode 100644 index 0000000..c2cc574 --- /dev/null +++ b/package/src/mutations/post.js @@ -0,0 +1,143 @@ +import { gql } from "graphql-request"; +import { getClient } from "../lib/graphQLClient"; + +export const publishPost = async ( + input, + first = 10, + endCursor = null, + personalAccessToken +) => { + const client = getClient(personalAccessToken); + + const data = await client.request( + gql` + mutation PublishPost( + $input: PublishPostInput! + $first: Int! + $after: String + ) { + publishPost(input: $input) { + post { + id + slug + title + subtitle + author { + name + profilePicture + } + coAuthors { + name + profilePicture + } + tags { + id + name + slug + } + url + canonicalUrl + publication { + id + title + displayTitle + descriptionSEO + } + cuid + coverImage { + url + isPortrait + attribution + photographer + isAttributionHidden + } + brief + readTimeInMinutes + views + series { + id + name + createdAt + } + reactionCount + replyCount + responseCount + featured + contributors { + name + profilePicture + } + commenters(first: $first, after: $after) { + edges { + node { + id + name + username + } + } + pageInfo { + endCursor + hasNextPage + } + totalDocuments + } + comments(first: $first, after: $after) { + edges { + node { + id + totalReactions + content { + markdown + } + } + } + pageInfo { + endCursor + hasNextPage + } + totalDocuments + } + bookmarked + content { + text + } + likedBy(first: $first, after: $after) { + totalDocuments + } + featuredAt + publishedAt + updatedAt + preferences { + pinnedToBlog + } + audioUrls { + male + } + seo { + title + description + } + ogMetaData { + image + } + hasLatexInPost + isFollowed + isAutoPublishedFromRSS + features { + tableOfContents { + isEnabled + } + } + } + } + } + `, + { + first: first, + after: endCursor, + input: input, + } + ); + + return data?.publishPost?.post; +}; diff --git a/package/src/queries/blog-data.js b/package/src/queries/blog-data.js index 76ef977..1aecf9e 100644 --- a/package/src/queries/blog-data.js +++ b/package/src/queries/blog-data.js @@ -1,6 +1,30 @@ import { gql } from "graphql-request"; import { getClient } from "../lib/graphQLClient"; +export const getBlogInfo = async (host) => { + const client = getClient(); + + const data = await client.request( + gql` + query Publication($host: String) { + publication(host: $host) { + id + isTeam + title + about { + markdown + } + } + } + `, + { + host: host, + } + ); + + return data?.publication; +}; + export const getAllPosts = async (host, first = 10, endCursor, tags) => { const client = getClient(); @@ -13,6 +37,7 @@ export const getAllPosts = async (host, first = 10, endCursor, tags) => { $tags: [ObjectId!] ) { publication(host: $host) { + id title posts(first: $first, after: $endCursor, filter: { tags: $tags }) { totalDocuments @@ -70,6 +95,7 @@ export const getPost = async (host, slug) => { gql` query postDetails($host: String, $slug: String!) { publication(host: $host) { + id post(slug: $slug) { author { name @@ -117,6 +143,7 @@ export const getPage = async (host, slug) => { gql` query pageData($host: String, $slug: String!) { publication(host: $host) { + id staticPage(slug: $slug) { title content { @@ -148,6 +175,7 @@ export const getComments = async (host, slug, first = 10, endCursor) => { $endCursor: String ) { publication(host: $host) { + id post(slug: $slug) { comments(first: $first, after: $endCursor) { pageInfo { diff --git a/package/src/useHashnodePublishPost.js b/package/src/useHashnodePublishPost.js new file mode 100644 index 0000000..f46b43a --- /dev/null +++ b/package/src/useHashnodePublishPost.js @@ -0,0 +1,71 @@ +import { publishPost } from "./mutations/post"; +import { getBlogInfo } from "./queries/blog-data"; +import { useState } from "react"; + +export default function useHashnodePublishPost(settings = {}) { + const [loading, setLoading] = useState(false); + + const publish = async (data = {}) => { + const { input, first, endCursor } = data; + const { personalAccessToken, host } = settings; + + if (!personalAccessToken) { + return { + post: null, + loading: false, + error: "Personal Access Token is required", + }; + } + + if (!host) { + return { + post: null, + loading: false, + error: "Host is required", + }; + } + + try { + setLoading(true); + + //Get publication id from blog host + const blogInfo = await getBlogInfo(host); + const publicationId = blogInfo?.id; + + if (!publicationId) { + throw new Error("Publication not found, please check your host."); + } + + const finalPayload = { + ...input, + publicationId, + }; + + //Call the publishPost mutation with the final payload + const res = await publishPost( + finalPayload, + first, + endCursor, + personalAccessToken + ); + + return { + post: res, + loading, + error: null, + }; + } catch (err) { + return { + post: null, + loading, + error: err, + }; + } finally { + setLoading(false); + } + }; + + return { + publish, + }; +}