Skip to content

Commit cd32d02

Browse files
authored
feat: [BREAKING] migrate from REST API to Sync API (#263)
1 parent a920126 commit cd32d02

16 files changed

+326
-244
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

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

5+
> [!IMPORTANT]
6+
> 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.
7+
58
## Installation
69

710
```

src/TodoistApi.comments.test.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
DEFAULT_COMMENT,
88
DEFAULT_REQUEST_ID,
99
} from './testUtils/testDefaults'
10-
import { getRestBaseUri, ENDPOINT_REST_COMMENTS } from './consts/endpoints'
10+
import { getSyncBaseUri, ENDPOINT_REST_COMMENTS } from './consts/endpoints'
1111
import { setupRestClientMock } from './testUtils/mocks'
1212

1313
function getTarget() {
@@ -17,16 +17,19 @@ function getTarget() {
1717
describe('TodoistApi comment endpoints', () => {
1818
describe('getComments', () => {
1919
test('calls get request with expected params', async () => {
20-
const getCommentsArgs = { projectId: '12' }
21-
const requestMock = setupRestClientMock([DEFAULT_COMMENT])
20+
const getCommentsArgs = { projectId: '12', limit: 10, cursor: '0' }
21+
const requestMock = setupRestClientMock({
22+
results: [DEFAULT_COMMENT],
23+
nextCursor: '123',
24+
})
2225
const api = getTarget()
2326

2427
await api.getComments(getCommentsArgs)
2528

2629
expect(requestMock).toBeCalledTimes(1)
2730
expect(requestMock).toBeCalledWith(
2831
'GET',
29-
getRestBaseUri(),
32+
getSyncBaseUri(),
3033
ENDPOINT_REST_COMMENTS,
3134
DEFAULT_AUTH_TOKEN,
3235
getCommentsArgs,
@@ -40,12 +43,13 @@ describe('TodoistApi comment endpoints', () => {
4043
COMMENT_WITH_OPTIONALS_AS_NULL_PROJECT,
4144
COMMENT_WITH_ATTACHMENT_WITH_OPTIONALS_AS_NULL,
4245
]
43-
setupRestClientMock(expectedComments)
46+
setupRestClientMock({ results: expectedComments, nextCursor: '123' })
4447
const api = getTarget()
4548

46-
const comments = await api.getComments({ taskId: '12' })
49+
const { results: comments, nextCursor } = await api.getComments({ taskId: '12' })
4750

4851
expect(comments).toEqual(expectedComments)
52+
expect(nextCursor).toBe('123')
4953
})
5054
})
5155

@@ -60,7 +64,7 @@ describe('TodoistApi comment endpoints', () => {
6064
expect(requestMock).toBeCalledTimes(1)
6165
expect(requestMock).toBeCalledWith(
6266
'GET',
63-
getRestBaseUri(),
67+
getSyncBaseUri(),
6468
`${ENDPOINT_REST_COMMENTS}/${commentId}`,
6569
DEFAULT_AUTH_TOKEN,
6670
)
@@ -92,7 +96,7 @@ describe('TodoistApi comment endpoints', () => {
9296
expect(requestMock).toBeCalledTimes(1)
9397
expect(requestMock).toBeCalledWith(
9498
'POST',
95-
getRestBaseUri(),
99+
getSyncBaseUri(),
96100
ENDPOINT_REST_COMMENTS,
97101
DEFAULT_AUTH_TOKEN,
98102
addCommentArgs,
@@ -126,7 +130,7 @@ describe('TodoistApi comment endpoints', () => {
126130
expect(requestMock).toBeCalledTimes(1)
127131
expect(requestMock).toBeCalledWith(
128132
'POST',
129-
getRestBaseUri(),
133+
getSyncBaseUri(),
130134
`${ENDPOINT_REST_COMMENTS}/${taskId}`,
131135
DEFAULT_AUTH_TOKEN,
132136
updateCommentArgs,
@@ -156,7 +160,7 @@ describe('TodoistApi comment endpoints', () => {
156160
expect(requestMock).toBeCalledTimes(1)
157161
expect(requestMock).toBeCalledWith(
158162
'DELETE',
159-
getRestBaseUri(),
163+
getSyncBaseUri(),
160164
`${ENDPOINT_REST_COMMENTS}/${taskId}`,
161165
DEFAULT_AUTH_TOKEN,
162166
undefined,

src/TodoistApi.labels.test.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { TodoistApi } from '.'
22
import { DEFAULT_AUTH_TOKEN, DEFAULT_LABEL, DEFAULT_REQUEST_ID } from './testUtils/testDefaults'
3-
import { getRestBaseUri, ENDPOINT_REST_LABELS } from './consts/endpoints'
3+
import { getSyncBaseUri, ENDPOINT_REST_LABELS } from './consts/endpoints'
44
import { setupRestClientMock } from './testUtils/mocks'
55

66
function getTarget() {
@@ -19,7 +19,7 @@ describe('TodoistApi label endpoints', () => {
1919
expect(requestMock).toBeCalledTimes(1)
2020
expect(requestMock).toBeCalledWith(
2121
'GET',
22-
getRestBaseUri(),
22+
getSyncBaseUri(),
2323
`${ENDPOINT_REST_LABELS}/${labelId}`,
2424
DEFAULT_AUTH_TOKEN,
2525
)
@@ -37,28 +37,39 @@ describe('TodoistApi label endpoints', () => {
3737

3838
describe('getLabels', () => {
3939
test('calls get on labels endpoint', async () => {
40-
const requestMock = setupRestClientMock([DEFAULT_LABEL])
40+
const requestMock = setupRestClientMock({
41+
results: [DEFAULT_LABEL],
42+
nextCursor: '123',
43+
})
4144
const api = getTarget()
4245

43-
await api.getLabels()
46+
await api.getLabels({ limit: 10, cursor: '0' })
4447

4548
expect(requestMock).toBeCalledTimes(1)
4649
expect(requestMock).toBeCalledWith(
4750
'GET',
48-
getRestBaseUri(),
51+
getSyncBaseUri(),
4952
ENDPOINT_REST_LABELS,
5053
DEFAULT_AUTH_TOKEN,
54+
{
55+
limit: 10,
56+
cursor: '0',
57+
},
5158
)
5259
})
5360

5461
test('returns result from rest client', async () => {
5562
const labels = [DEFAULT_LABEL]
56-
setupRestClientMock(labels)
63+
setupRestClientMock({
64+
results: [DEFAULT_LABEL],
65+
nextCursor: '123',
66+
})
5767
const api = getTarget()
5868

59-
const response = await api.getLabels()
69+
const { results, nextCursor } = await api.getLabels()
6070

61-
expect(response).toEqual(labels)
71+
expect(results).toEqual(labels)
72+
expect(nextCursor).toBe('123')
6273
})
6374
})
6475

@@ -76,7 +87,7 @@ describe('TodoistApi label endpoints', () => {
7687
expect(requestMock).toBeCalledTimes(1)
7788
expect(requestMock).toBeCalledWith(
7889
'POST',
79-
getRestBaseUri(),
90+
getSyncBaseUri(),
8091
ENDPOINT_REST_LABELS,
8192
DEFAULT_AUTH_TOKEN,
8293
DEFAULT_ADD_LABEL_ARGS,
@@ -109,7 +120,7 @@ describe('TodoistApi label endpoints', () => {
109120
expect(requestMock).toBeCalledTimes(1)
110121
expect(requestMock).toBeCalledWith(
111122
'POST',
112-
getRestBaseUri(),
123+
getSyncBaseUri(),
113124
`${ENDPOINT_REST_LABELS}/${labelId}`,
114125
DEFAULT_AUTH_TOKEN,
115126
DEFAULT_UPDATE_LABEL_ARGS,
@@ -139,7 +150,7 @@ describe('TodoistApi label endpoints', () => {
139150
expect(requestMock).toBeCalledTimes(1)
140151
expect(requestMock).toBeCalledWith(
141152
'DELETE',
142-
getRestBaseUri(),
153+
getSyncBaseUri(),
143154
`${ENDPOINT_REST_LABELS}/${labelId}`,
144155
DEFAULT_AUTH_TOKEN,
145156
undefined,

src/TodoistApi.projects.test.ts

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
PROJECT_WITH_OPTIONALS_AS_NULL,
88
} from './testUtils/testDefaults'
99
import {
10-
getRestBaseUri,
10+
getSyncBaseUri,
1111
ENDPOINT_REST_PROJECTS,
1212
ENDPOINT_REST_PROJECT_COLLABORATORS,
1313
} from './consts/endpoints'
@@ -29,7 +29,7 @@ describe('TodoistApi project endpoints', () => {
2929
expect(requestMock).toBeCalledTimes(1)
3030
expect(requestMock).toBeCalledWith(
3131
'GET',
32-
getRestBaseUri(),
32+
getSyncBaseUri(),
3333
`${ENDPOINT_REST_PROJECTS}/${projectId}`,
3434
DEFAULT_AUTH_TOKEN,
3535
)
@@ -47,28 +47,34 @@ describe('TodoistApi project endpoints', () => {
4747

4848
describe('getProjects', () => {
4949
test('calls get on projects endpoint', async () => {
50-
const requestMock = setupRestClientMock([DEFAULT_PROJECT])
50+
const requestMock = setupRestClientMock({
51+
results: [DEFAULT_PROJECT],
52+
nextCursor: '123',
53+
})
5154
const api = getTarget()
5255

53-
await api.getProjects()
56+
const args = { limit: 10, cursor: '0' }
57+
await api.getProjects(args)
5458

5559
expect(requestMock).toBeCalledTimes(1)
5660
expect(requestMock).toBeCalledWith(
5761
'GET',
58-
getRestBaseUri(),
62+
getSyncBaseUri(),
5963
ENDPOINT_REST_PROJECTS,
6064
DEFAULT_AUTH_TOKEN,
65+
args,
6166
)
6267
})
6368

6469
test('returns result from rest client', async () => {
6570
const projects = [DEFAULT_PROJECT, PROJECT_WITH_OPTIONALS_AS_NULL]
66-
setupRestClientMock(projects)
71+
setupRestClientMock({ results: projects, nextCursor: '123' })
6772
const api = getTarget()
6873

69-
const response = await api.getProjects()
74+
const { results, nextCursor } = await api.getProjects()
7075

71-
expect(response).toEqual(projects)
76+
expect(results).toEqual(projects)
77+
expect(nextCursor).toBe('123')
7278
})
7379
})
7480

@@ -86,7 +92,7 @@ describe('TodoistApi project endpoints', () => {
8692
expect(requestMock).toBeCalledTimes(1)
8793
expect(requestMock).toBeCalledWith(
8894
'POST',
89-
getRestBaseUri(),
95+
getSyncBaseUri(),
9096
ENDPOINT_REST_PROJECTS,
9197
DEFAULT_AUTH_TOKEN,
9298
DEFAULT_ADD_PROJECT_ARGS,
@@ -117,7 +123,7 @@ describe('TodoistApi project endpoints', () => {
117123
expect(requestMock).toBeCalledTimes(1)
118124
expect(requestMock).toBeCalledWith(
119125
'POST',
120-
getRestBaseUri(),
126+
getSyncBaseUri(),
121127
`${ENDPOINT_REST_PROJECTS}/${projectId}`,
122128
DEFAULT_AUTH_TOKEN,
123129
updateArgs,
@@ -147,7 +153,7 @@ describe('TodoistApi project endpoints', () => {
147153
expect(requestMock).toBeCalledTimes(1)
148154
expect(requestMock).toBeCalledWith(
149155
'DELETE',
150-
getRestBaseUri(),
156+
getSyncBaseUri(),
151157
`${ENDPOINT_REST_PROJECTS}/${projectId}`,
152158
DEFAULT_AUTH_TOKEN,
153159
undefined,
@@ -170,27 +176,30 @@ describe('TodoistApi project endpoints', () => {
170176
const users = [DEFAULT_USER]
171177

172178
test('calls get on expected endpoint', async () => {
173-
const requestMock = setupRestClientMock(users)
179+
const requestMock = setupRestClientMock({ results: users, nextCursor: '123' })
174180
const api = getTarget()
175181

176-
await api.getProjectCollaborators(projectId)
182+
const args = { limit: 10, cursor: '0' }
183+
await api.getProjectCollaborators(projectId, args)
177184

178185
expect(requestMock).toBeCalledTimes(1)
179186
expect(requestMock).toBeCalledWith(
180187
'GET',
181-
getRestBaseUri(),
188+
getSyncBaseUri(),
182189
`${ENDPOINT_REST_PROJECTS}/${projectId}/${ENDPOINT_REST_PROJECT_COLLABORATORS}`,
183190
DEFAULT_AUTH_TOKEN,
191+
args,
184192
)
185193
})
186194

187195
test('returns result from rest client', async () => {
188-
setupRestClientMock(users)
196+
setupRestClientMock({ results: users, nextCursor: '123' })
189197
const api = getTarget()
190198

191-
const returnedUsers = await api.getProjectCollaborators(projectId)
199+
const { results, nextCursor } = await api.getProjectCollaborators(projectId)
192200

193-
expect(returnedUsers).toEqual(users)
201+
expect(results).toEqual(users)
202+
expect(nextCursor).toBe('123')
194203
})
195204
})
196205
})

src/TodoistApi.sections.test.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { TodoistApi } from '.'
22
import { DEFAULT_AUTH_TOKEN, DEFAULT_REQUEST_ID, DEFAULT_SECTION } from './testUtils/testDefaults'
3-
import { getRestBaseUri, ENDPOINT_REST_SECTIONS } from './consts/endpoints'
3+
import { getSyncBaseUri, ENDPOINT_REST_SECTIONS } from './consts/endpoints'
44
import { setupRestClientMock } from './testUtils/mocks'
55

66
function getTarget() {
@@ -19,7 +19,7 @@ describe('TodoistApi section endpoints', () => {
1919
expect(requestMock).toBeCalledTimes(1)
2020
expect(requestMock).toBeCalledWith(
2121
'GET',
22-
getRestBaseUri(),
22+
getSyncBaseUri(),
2323
`${ENDPOINT_REST_SECTIONS}/${sectionId}`,
2424
DEFAULT_AUTH_TOKEN,
2525
)
@@ -38,29 +38,34 @@ describe('TodoistApi section endpoints', () => {
3838
describe('getSections', () => {
3939
test('calls get on sections endpoint', async () => {
4040
const projectId = '123'
41-
const requestMock = setupRestClientMock([DEFAULT_SECTION])
41+
const requestMock = setupRestClientMock({
42+
results: [DEFAULT_SECTION],
43+
nextCursor: '123',
44+
})
4245
const api = getTarget()
4346

44-
await api.getSections(projectId)
47+
const args = { projectId, limit: 10, cursor: '0' }
48+
await api.getSections(args)
4549

4650
expect(requestMock).toBeCalledTimes(1)
4751
expect(requestMock).toBeCalledWith(
4852
'GET',
49-
getRestBaseUri(),
53+
getSyncBaseUri(),
5054
ENDPOINT_REST_SECTIONS,
5155
DEFAULT_AUTH_TOKEN,
52-
{ projectId },
56+
args,
5357
)
5458
})
5559

5660
test('returns result from rest client', async () => {
5761
const sections = [DEFAULT_SECTION]
58-
setupRestClientMock(sections)
62+
setupRestClientMock({ results: sections, nextCursor: '123' })
5963
const api = getTarget()
6064

61-
const response = await api.getSections()
65+
const { results, nextCursor } = await api.getSections({ projectId: '123' })
6266

63-
expect(response).toEqual(sections)
67+
expect(results).toEqual(sections)
68+
expect(nextCursor).toBe('123')
6469
})
6570
})
6671

@@ -79,7 +84,7 @@ describe('TodoistApi section endpoints', () => {
7984
expect(requestMock).toBeCalledTimes(1)
8085
expect(requestMock).toBeCalledWith(
8186
'POST',
82-
getRestBaseUri(),
87+
getSyncBaseUri(),
8388
ENDPOINT_REST_SECTIONS,
8489
DEFAULT_AUTH_TOKEN,
8590
DEFAULT_ADD_SECTION_ARGS,
@@ -110,7 +115,7 @@ describe('TodoistApi section endpoints', () => {
110115
expect(requestMock).toBeCalledTimes(1)
111116
expect(requestMock).toBeCalledWith(
112117
'POST',
113-
getRestBaseUri(),
118+
getSyncBaseUri(),
114119
`${ENDPOINT_REST_SECTIONS}/${sectionId}`,
115120
DEFAULT_AUTH_TOKEN,
116121
DEFAULT_UPDATE_SECTION_ARGS,
@@ -140,7 +145,7 @@ describe('TodoistApi section endpoints', () => {
140145
expect(requestMock).toBeCalledTimes(1)
141146
expect(requestMock).toBeCalledWith(
142147
'DELETE',
143-
getRestBaseUri(),
148+
getSyncBaseUri(),
144149
`${ENDPOINT_REST_SECTIONS}/${sectionId}`,
145150
DEFAULT_AUTH_TOKEN,
146151
undefined,

0 commit comments

Comments
 (0)