Skip to content

Commit

Permalink
feat: [BREAKING] migrate from REST API to Sync API (#263)
Browse files Browse the repository at this point in the history
  • Loading branch information
pedroalves0 authored Jan 17, 2025
1 parent a920126 commit cd32d02
Show file tree
Hide file tree
Showing 16 changed files with 326 additions and 244 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

This is the official TypeScript API client for the Todoist REST API.

> [!IMPORTANT]
> This library is currently being migrated from the Todoist REST API to the Todoist Sync API. As a result, parts of the documentation may be outdated. However, the client API remains consistent with the latest stable release, [v3.0.3](https://github.com/Doist/todoist-api-typescript/releases/tag/v3.0.3). Please note that some client methods may return unexpected data or encounter failures during this transition.
## Installation

```
Expand Down
24 changes: 14 additions & 10 deletions src/TodoistApi.comments.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
DEFAULT_COMMENT,
DEFAULT_REQUEST_ID,
} from './testUtils/testDefaults'
import { getRestBaseUri, ENDPOINT_REST_COMMENTS } from './consts/endpoints'
import { getSyncBaseUri, ENDPOINT_REST_COMMENTS } from './consts/endpoints'
import { setupRestClientMock } from './testUtils/mocks'

function getTarget() {
Expand All @@ -17,16 +17,19 @@ function getTarget() {
describe('TodoistApi comment endpoints', () => {
describe('getComments', () => {
test('calls get request with expected params', async () => {
const getCommentsArgs = { projectId: '12' }
const requestMock = setupRestClientMock([DEFAULT_COMMENT])
const getCommentsArgs = { projectId: '12', limit: 10, cursor: '0' }
const requestMock = setupRestClientMock({
results: [DEFAULT_COMMENT],
nextCursor: '123',
})
const api = getTarget()

await api.getComments(getCommentsArgs)

expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'GET',
getRestBaseUri(),
getSyncBaseUri(),
ENDPOINT_REST_COMMENTS,
DEFAULT_AUTH_TOKEN,
getCommentsArgs,
Expand All @@ -40,12 +43,13 @@ describe('TodoistApi comment endpoints', () => {
COMMENT_WITH_OPTIONALS_AS_NULL_PROJECT,
COMMENT_WITH_ATTACHMENT_WITH_OPTIONALS_AS_NULL,
]
setupRestClientMock(expectedComments)
setupRestClientMock({ results: expectedComments, nextCursor: '123' })
const api = getTarget()

const comments = await api.getComments({ taskId: '12' })
const { results: comments, nextCursor } = await api.getComments({ taskId: '12' })

expect(comments).toEqual(expectedComments)
expect(nextCursor).toBe('123')
})
})

Expand All @@ -60,7 +64,7 @@ describe('TodoistApi comment endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'GET',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_COMMENTS}/${commentId}`,
DEFAULT_AUTH_TOKEN,
)
Expand Down Expand Up @@ -92,7 +96,7 @@ describe('TodoistApi comment endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'POST',
getRestBaseUri(),
getSyncBaseUri(),
ENDPOINT_REST_COMMENTS,
DEFAULT_AUTH_TOKEN,
addCommentArgs,
Expand Down Expand Up @@ -126,7 +130,7 @@ describe('TodoistApi comment endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'POST',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_COMMENTS}/${taskId}`,
DEFAULT_AUTH_TOKEN,
updateCommentArgs,
Expand Down Expand Up @@ -156,7 +160,7 @@ describe('TodoistApi comment endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'DELETE',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_COMMENTS}/${taskId}`,
DEFAULT_AUTH_TOKEN,
undefined,
Expand Down
33 changes: 22 additions & 11 deletions src/TodoistApi.labels.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TodoistApi } from '.'
import { DEFAULT_AUTH_TOKEN, DEFAULT_LABEL, DEFAULT_REQUEST_ID } from './testUtils/testDefaults'
import { getRestBaseUri, ENDPOINT_REST_LABELS } from './consts/endpoints'
import { getSyncBaseUri, ENDPOINT_REST_LABELS } from './consts/endpoints'
import { setupRestClientMock } from './testUtils/mocks'

function getTarget() {
Expand All @@ -19,7 +19,7 @@ describe('TodoistApi label endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'GET',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_LABELS}/${labelId}`,
DEFAULT_AUTH_TOKEN,
)
Expand All @@ -37,28 +37,39 @@ describe('TodoistApi label endpoints', () => {

describe('getLabels', () => {
test('calls get on labels endpoint', async () => {
const requestMock = setupRestClientMock([DEFAULT_LABEL])
const requestMock = setupRestClientMock({
results: [DEFAULT_LABEL],
nextCursor: '123',
})
const api = getTarget()

await api.getLabels()
await api.getLabels({ limit: 10, cursor: '0' })

expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'GET',
getRestBaseUri(),
getSyncBaseUri(),
ENDPOINT_REST_LABELS,
DEFAULT_AUTH_TOKEN,
{
limit: 10,
cursor: '0',
},
)
})

test('returns result from rest client', async () => {
const labels = [DEFAULT_LABEL]
setupRestClientMock(labels)
setupRestClientMock({
results: [DEFAULT_LABEL],
nextCursor: '123',
})
const api = getTarget()

const response = await api.getLabels()
const { results, nextCursor } = await api.getLabels()

expect(response).toEqual(labels)
expect(results).toEqual(labels)
expect(nextCursor).toBe('123')
})
})

Expand All @@ -76,7 +87,7 @@ describe('TodoistApi label endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'POST',
getRestBaseUri(),
getSyncBaseUri(),
ENDPOINT_REST_LABELS,
DEFAULT_AUTH_TOKEN,
DEFAULT_ADD_LABEL_ARGS,
Expand Down Expand Up @@ -109,7 +120,7 @@ describe('TodoistApi label endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'POST',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_LABELS}/${labelId}`,
DEFAULT_AUTH_TOKEN,
DEFAULT_UPDATE_LABEL_ARGS,
Expand Down Expand Up @@ -139,7 +150,7 @@ describe('TodoistApi label endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'DELETE',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_LABELS}/${labelId}`,
DEFAULT_AUTH_TOKEN,
undefined,
Expand Down
43 changes: 26 additions & 17 deletions src/TodoistApi.projects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
PROJECT_WITH_OPTIONALS_AS_NULL,
} from './testUtils/testDefaults'
import {
getRestBaseUri,
getSyncBaseUri,
ENDPOINT_REST_PROJECTS,
ENDPOINT_REST_PROJECT_COLLABORATORS,
} from './consts/endpoints'
Expand All @@ -29,7 +29,7 @@ describe('TodoistApi project endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'GET',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_PROJECTS}/${projectId}`,
DEFAULT_AUTH_TOKEN,
)
Expand All @@ -47,28 +47,34 @@ describe('TodoistApi project endpoints', () => {

describe('getProjects', () => {
test('calls get on projects endpoint', async () => {
const requestMock = setupRestClientMock([DEFAULT_PROJECT])
const requestMock = setupRestClientMock({
results: [DEFAULT_PROJECT],
nextCursor: '123',
})
const api = getTarget()

await api.getProjects()
const args = { limit: 10, cursor: '0' }
await api.getProjects(args)

expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'GET',
getRestBaseUri(),
getSyncBaseUri(),
ENDPOINT_REST_PROJECTS,
DEFAULT_AUTH_TOKEN,
args,
)
})

test('returns result from rest client', async () => {
const projects = [DEFAULT_PROJECT, PROJECT_WITH_OPTIONALS_AS_NULL]
setupRestClientMock(projects)
setupRestClientMock({ results: projects, nextCursor: '123' })
const api = getTarget()

const response = await api.getProjects()
const { results, nextCursor } = await api.getProjects()

expect(response).toEqual(projects)
expect(results).toEqual(projects)
expect(nextCursor).toBe('123')
})
})

Expand All @@ -86,7 +92,7 @@ describe('TodoistApi project endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'POST',
getRestBaseUri(),
getSyncBaseUri(),
ENDPOINT_REST_PROJECTS,
DEFAULT_AUTH_TOKEN,
DEFAULT_ADD_PROJECT_ARGS,
Expand Down Expand Up @@ -117,7 +123,7 @@ describe('TodoistApi project endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'POST',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_PROJECTS}/${projectId}`,
DEFAULT_AUTH_TOKEN,
updateArgs,
Expand Down Expand Up @@ -147,7 +153,7 @@ describe('TodoistApi project endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'DELETE',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_PROJECTS}/${projectId}`,
DEFAULT_AUTH_TOKEN,
undefined,
Expand All @@ -170,27 +176,30 @@ describe('TodoistApi project endpoints', () => {
const users = [DEFAULT_USER]

test('calls get on expected endpoint', async () => {
const requestMock = setupRestClientMock(users)
const requestMock = setupRestClientMock({ results: users, nextCursor: '123' })
const api = getTarget()

await api.getProjectCollaborators(projectId)
const args = { limit: 10, cursor: '0' }
await api.getProjectCollaborators(projectId, args)

expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'GET',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_PROJECTS}/${projectId}/${ENDPOINT_REST_PROJECT_COLLABORATORS}`,
DEFAULT_AUTH_TOKEN,
args,
)
})

test('returns result from rest client', async () => {
setupRestClientMock(users)
setupRestClientMock({ results: users, nextCursor: '123' })
const api = getTarget()

const returnedUsers = await api.getProjectCollaborators(projectId)
const { results, nextCursor } = await api.getProjectCollaborators(projectId)

expect(returnedUsers).toEqual(users)
expect(results).toEqual(users)
expect(nextCursor).toBe('123')
})
})
})
29 changes: 17 additions & 12 deletions src/TodoistApi.sections.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TodoistApi } from '.'
import { DEFAULT_AUTH_TOKEN, DEFAULT_REQUEST_ID, DEFAULT_SECTION } from './testUtils/testDefaults'
import { getRestBaseUri, ENDPOINT_REST_SECTIONS } from './consts/endpoints'
import { getSyncBaseUri, ENDPOINT_REST_SECTIONS } from './consts/endpoints'
import { setupRestClientMock } from './testUtils/mocks'

function getTarget() {
Expand All @@ -19,7 +19,7 @@ describe('TodoistApi section endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'GET',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_SECTIONS}/${sectionId}`,
DEFAULT_AUTH_TOKEN,
)
Expand All @@ -38,29 +38,34 @@ describe('TodoistApi section endpoints', () => {
describe('getSections', () => {
test('calls get on sections endpoint', async () => {
const projectId = '123'
const requestMock = setupRestClientMock([DEFAULT_SECTION])
const requestMock = setupRestClientMock({
results: [DEFAULT_SECTION],
nextCursor: '123',
})
const api = getTarget()

await api.getSections(projectId)
const args = { projectId, limit: 10, cursor: '0' }
await api.getSections(args)

expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'GET',
getRestBaseUri(),
getSyncBaseUri(),
ENDPOINT_REST_SECTIONS,
DEFAULT_AUTH_TOKEN,
{ projectId },
args,
)
})

test('returns result from rest client', async () => {
const sections = [DEFAULT_SECTION]
setupRestClientMock(sections)
setupRestClientMock({ results: sections, nextCursor: '123' })
const api = getTarget()

const response = await api.getSections()
const { results, nextCursor } = await api.getSections({ projectId: '123' })

expect(response).toEqual(sections)
expect(results).toEqual(sections)
expect(nextCursor).toBe('123')
})
})

Expand All @@ -79,7 +84,7 @@ describe('TodoistApi section endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'POST',
getRestBaseUri(),
getSyncBaseUri(),
ENDPOINT_REST_SECTIONS,
DEFAULT_AUTH_TOKEN,
DEFAULT_ADD_SECTION_ARGS,
Expand Down Expand Up @@ -110,7 +115,7 @@ describe('TodoistApi section endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'POST',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_SECTIONS}/${sectionId}`,
DEFAULT_AUTH_TOKEN,
DEFAULT_UPDATE_SECTION_ARGS,
Expand Down Expand Up @@ -140,7 +145,7 @@ describe('TodoistApi section endpoints', () => {
expect(requestMock).toBeCalledTimes(1)
expect(requestMock).toBeCalledWith(
'DELETE',
getRestBaseUri(),
getSyncBaseUri(),
`${ENDPOINT_REST_SECTIONS}/${sectionId}`,
DEFAULT_AUTH_TOKEN,
undefined,
Expand Down
Loading

0 comments on commit cd32d02

Please sign in to comment.