From 308dc536904b85ded330a60e4ff0e4c67fd77527 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Thu, 7 Mar 2024 17:19:58 +0800 Subject: [PATCH] make baseUrl optional --- src/client.ts | 187 ++++--------------------------------------------- src/errors.ts | 2 + src/graphql.ts | 171 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 185 insertions(+), 175 deletions(-) diff --git a/src/client.ts b/src/client.ts index b07da05..dc1175e 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,184 +1,18 @@ import { Client, fetchExchange } from 'urql' import { buildOmnivoreError } from './errors' -import { graphql } from './graphql' +import { + DeleteMutation, + SearchQuery, + UpdatesSinceQuery, + saveByURLMutation, +} from './graphql' export interface ClientOptions { authToken: string - baseUrl: string + baseUrl?: string timeoutMs?: number } -const LabelFragment = graphql(` - fragment LabelFragment on Label @_unmask { - name - color - createdAt - id - internal - source - description - } -`) - -const HighlightFragment = graphql( - ` - fragment HighlightFragment on Highlight @_unmask { - id - quote - annotation - patch - updatedAt - labels { - ...LabelFragment - } - type - highlightPositionPercent - color - highlightPositionAnchorIndex - prefix - suffix - createdAt - } - `, - [LabelFragment], -) - -const SearchItemFragment = graphql( - ` - fragment SearchItemFragment on SearchItem @_unmask { - id - title - siteName - originalArticleUrl - author - description - slug - labels { - ...LabelFragment - } - highlights { - ...HighlightFragment - } - updatedAt - savedAt - pageType - content - publishedAt - url - image - readAt - wordsCount - readingProgressPercent - isArchived - archivedAt - contentReader - } - `, - [LabelFragment, HighlightFragment], -) - -const PageInfoFragment = graphql(` - fragment PageInfoFragment on PageInfo @_unmask { - hasNextPage - hasPreviousPage - startCursor - endCursor - totalCount - } -`) - -const SearchQuery = graphql( - ` - query Search( - $after: String - $first: Int - $format: String - $includeContent: Boolean - $query: String - ) { - search( - after: $after - first: $first - format: $format - includeContent: $includeContent - query: $query - ) { - __typename - ... on SearchSuccess { - edges { - node { - ...SearchItemFragment - } - } - pageInfo { - ...PageInfoFragment - } - } - ... on SearchError { - errorCodes - } - } - } - `, - [SearchItemFragment, PageInfoFragment], -) - -const UpdatesSinceQuery = graphql( - ` - query UpdatesSince($since: Date!) { - updatesSince(since: $since) { - __typename - ... on UpdatesSinceSuccess { - edges { - itemID - updateReason - node { - ...SearchItemFragment - } - } - pageInfo { - ...PageInfoFragment - } - } - ... on UpdatesSinceError { - errorCodes - } - } - } - `, - [SearchItemFragment, PageInfoFragment], -) - -const DeleteMutation = graphql(` - mutation Delete($input: SetBookmarkArticleInput!) { - setBookmarkArticle(input: $input) { - __typename - ... on SetBookmarkArticleSuccess { - bookmarkedArticle { - id - } - } - ... on SetBookmarkArticleError { - errorCodes - } - } - } -`) - -const saveByURLMutation = graphql(` - mutation SaveByURL($input: SaveUrlInput!) { - saveUrl(input: $input) { - __typename - ... on SaveSuccess { - clientRequestId - } - ... on SaveError { - errorCodes - } - } - } -`) - export type PageType = | 'ARTICLE' | 'BOOK' @@ -303,7 +137,7 @@ export class Omnivore { constructor(clientOptions: ClientOptions) { this.client = new Client({ - url: `${clientOptions.baseUrl}/api/graphql`, + url: `${clientOptions.baseUrl || 'https://api-prod.omnivore.app'}/api/graphql`, exchanges: [fetchExchange], fetchOptions: () => ({ headers: { @@ -314,7 +148,9 @@ export class Omnivore { }) } + // Omnivore API methods public readonly items = { + // search for items search: async (params: SearchParameters): Promise => { const { data, error } = await this.client .query(SearchQuery, params) @@ -330,6 +166,7 @@ export class Omnivore { return search }, + // get updates since a given date updates: async (since: string): Promise => { const { data, error } = await this.client .query(UpdatesSinceQuery, { since }) @@ -349,6 +186,7 @@ export class Omnivore { return updatesSince }, + // delete an item delete: async (id: string): Promise => { const { data, error } = await this.client .mutation(DeleteMutation, { input: { articleID: id, bookmark: false } }) @@ -368,6 +206,7 @@ export class Omnivore { return { id: deleteArticle.bookmarkedArticle.id } }, + // save an item by URL saveByUrl: async ( params: SaveByURLParameters, ): Promise => { diff --git a/src/errors.ts b/src/errors.ts index 88e874e..af2242e 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -1,5 +1,6 @@ import { CombinedError } from 'urql' +// Error codes are used to identify the type of error that occurred export enum OmnivoreErrorCode { GraphQLError = 'GRAPHQL_ERROR', NetworkError = 'NETWORK_ERROR', @@ -31,6 +32,7 @@ class UnknownError extends OmnivoreErrorBase { } } +// OmnivoreError is a union type of all possible errors export type OmnivoreError = GraphQLError | NetworkError | UnknownError export const buildOmnivoreError = ( diff --git a/src/graphql.ts b/src/graphql.ts index 8016bd0..564a2c3 100644 --- a/src/graphql.ts +++ b/src/graphql.ts @@ -1,7 +1,7 @@ import { initGraphQLTada } from 'gql.tada' import type { introspection } from './graphql-env.d.ts' -export const graphql = initGraphQLTada<{ +const graphql = initGraphQLTada<{ introspection: introspection scalars: { @@ -10,3 +10,172 @@ export const graphql = initGraphQLTada<{ JSON: any } }>() + +const LabelFragment = graphql(` + fragment LabelFragment on Label @_unmask { + name + color + createdAt + id + internal + source + description + } +`) + +const HighlightFragment = graphql( + ` + fragment HighlightFragment on Highlight @_unmask { + id + quote + annotation + patch + updatedAt + labels { + ...LabelFragment + } + type + highlightPositionPercent + color + highlightPositionAnchorIndex + prefix + suffix + createdAt + } + `, + [LabelFragment], +) + +const SearchItemFragment = graphql( + ` + fragment SearchItemFragment on SearchItem @_unmask { + id + title + siteName + originalArticleUrl + author + description + slug + labels { + ...LabelFragment + } + highlights { + ...HighlightFragment + } + updatedAt + savedAt + pageType + content + publishedAt + url + image + readAt + wordsCount + readingProgressPercent + isArchived + archivedAt + contentReader + } + `, + [LabelFragment, HighlightFragment], +) + +export const SearchQuery = graphql( + ` + query Search( + $after: String + $first: Int + $format: String + $includeContent: Boolean + $query: String + ) { + search( + after: $after + first: $first + format: $format + includeContent: $includeContent + query: $query + ) { + __typename + ... on SearchSuccess { + edges { + node { + ...SearchItemFragment + } + } + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + totalCount + } + } + ... on SearchError { + errorCodes + } + } + } + `, + [SearchItemFragment], +) + +export const UpdatesSinceQuery = graphql( + ` + query UpdatesSince($since: Date!) { + updatesSince(since: $since) { + __typename + ... on UpdatesSinceSuccess { + edges { + itemID + updateReason + node { + ...SearchItemFragment + } + } + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + totalCount + } + } + ... on UpdatesSinceError { + errorCodes + } + } + } + `, + [SearchItemFragment], +) + +export const DeleteMutation = graphql(` + mutation Delete($input: SetBookmarkArticleInput!) { + setBookmarkArticle(input: $input) { + __typename + ... on SetBookmarkArticleSuccess { + bookmarkedArticle { + id + } + } + ... on SetBookmarkArticleError { + errorCodes + } + } + } +`) + +export const saveByURLMutation = graphql(` + mutation SaveByURL($input: SaveUrlInput!) { + saveUrl(input: $input) { + __typename + ... on SaveSuccess { + clientRequestId + } + ... on SaveError { + errorCodes + } + } + } +`)