@doist/todoist-api-typescript 6.0.1 → 6.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +105 -5
  2. package/dist/cjs/authentication.js +59 -63
  3. package/dist/cjs/rest-client.js +12 -10
  4. package/dist/cjs/test-utils/mocks.js +2 -45
  5. package/dist/cjs/test-utils/msw-setup.js +74 -5
  6. package/dist/cjs/test-utils/obsidian-fetch-adapter.js +53 -0
  7. package/dist/cjs/todoist-api.js +80 -30
  8. package/dist/cjs/types/entities.js +4 -4
  9. package/dist/cjs/types/index.js +1 -0
  10. package/dist/cjs/utils/fetch-with-retry.js +37 -14
  11. package/dist/cjs/utils/multipart-upload.js +2 -1
  12. package/dist/esm/authentication.js +59 -63
  13. package/dist/esm/rest-client.js +12 -10
  14. package/dist/esm/test-utils/mocks.js +3 -10
  15. package/dist/esm/test-utils/msw-setup.js +67 -2
  16. package/dist/esm/test-utils/obsidian-fetch-adapter.js +50 -0
  17. package/dist/esm/todoist-api.js +80 -30
  18. package/dist/esm/types/entities.js +4 -4
  19. package/dist/esm/types/index.js +1 -0
  20. package/dist/esm/utils/fetch-with-retry.js +37 -14
  21. package/dist/esm/utils/multipart-upload.js +2 -1
  22. package/dist/types/authentication.d.ts +20 -0
  23. package/dist/types/rest-client.d.ts +2 -1
  24. package/dist/types/test-utils/mocks.d.ts +0 -1
  25. package/dist/types/test-utils/msw-setup.d.ts +31 -1
  26. package/dist/types/test-utils/obsidian-fetch-adapter.d.ts +29 -0
  27. package/dist/types/todoist-api.d.ts +18 -7
  28. package/dist/types/types/entities.d.ts +4 -4
  29. package/dist/types/types/http.d.ts +17 -0
  30. package/dist/types/types/index.d.ts +1 -0
  31. package/dist/types/types/sync.d.ts +5 -5
  32. package/dist/types/utils/fetch-with-retry.d.ts +2 -1
  33. package/dist/types/utils/multipart-upload.d.ts +2 -0
  34. package/package.json +4 -3
@@ -1,4 +1,4 @@
1
- import { HttpMethod, HttpResponse } from './types/http';
1
+ import { HttpMethod, HttpResponse, CustomFetch } from './types/http';
2
2
  type RequestArgs = {
3
3
  httpMethod: HttpMethod;
4
4
  baseUri: string;
@@ -8,6 +8,7 @@ type RequestArgs = {
8
8
  requestId?: string;
9
9
  hasSyncCommands?: boolean;
10
10
  customHeaders?: Record<string, string>;
11
+ customFetch?: CustomFetch;
11
12
  };
12
13
  export declare function paramsSerializer(params: Record<string, unknown>): string;
13
14
  export declare function isSuccess(response: HttpResponse): boolean;
@@ -1 +0,0 @@
1
- export declare function setupRestClientMock(responseData: unknown, status?: number): jest.SpyInstance;
@@ -1,3 +1,33 @@
1
+ import { http, HttpResponse, type DefaultBodyType } from 'msw';
2
+ export type MockApiOptions = {
3
+ status?: number;
4
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
5
+ headers?: Record<string, string>;
6
+ };
7
+ export type CapturedRequest = {
8
+ url: string;
9
+ method: string;
10
+ headers: Record<string, string>;
11
+ body: unknown;
12
+ };
13
+ export declare function captureRequest({ request, body }: {
14
+ request: Request;
15
+ body: unknown;
16
+ }): void;
17
+ export declare function getLastRequest(): CapturedRequest | undefined;
18
+ export declare function getAllRequests(): CapturedRequest[];
19
+ export declare function clearCapturedRequests(): void;
1
20
  export declare const handlers: never[];
2
21
  export declare const server: import("msw/node").SetupServerApi;
3
- export { http, HttpResponse } from 'msw';
22
+ export declare function mockApiResponse<T extends DefaultBodyType>({ endpoint, data, options, }: {
23
+ endpoint: string;
24
+ data: T;
25
+ options?: MockApiOptions;
26
+ }): void;
27
+ export declare function mockApiError<T extends DefaultBodyType>({ endpoint, data, status, options, }: {
28
+ endpoint: string;
29
+ data: T;
30
+ status: number;
31
+ options?: Omit<MockApiOptions, 'status'>;
32
+ }): void;
33
+ export { http, HttpResponse };
@@ -0,0 +1,29 @@
1
+ import type { RequestUrlParam, RequestUrlResponse } from 'obsidian';
2
+ import type { CustomFetch } from '../types/http';
3
+ /**
4
+ * Creates a CustomFetch adapter for Obsidian's requestUrl API.
5
+ *
6
+ * This adapter bridges the gap between Obsidian's requestUrl interface and the
7
+ * standard fetch-like interface expected by the Todoist API SDK.
8
+ *
9
+ * Key differences handled by this adapter:
10
+ * - Obsidian returns response data as properties (response.json, response.text)
11
+ * while the SDK expects methods (response.json(), response.text())
12
+ * - Obsidian's requestUrl bypasses CORS restrictions that would block standard fetch
13
+ * - Obsidian throws on HTTP errors by default; we set throw: false to handle manually
14
+ * - Obsidian doesn't provide statusText; we default to empty string
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { requestUrl } from 'obsidian';
19
+ * import { createObsidianFetchAdapter } from './obsidian-fetch-adapter';
20
+ *
21
+ * const api = new TodoistApi('your-token', {
22
+ * customFetch: createObsidianFetchAdapter(requestUrl)
23
+ * });
24
+ * ```
25
+ *
26
+ * @param requestUrl - The Obsidian requestUrl function
27
+ * @returns A CustomFetch function compatible with the Todoist API SDK
28
+ */
29
+ export declare function createObsidianFetchAdapter(requestUrl: (request: RequestUrlParam | string) => Promise<RequestUrlResponse>): CustomFetch;
@@ -1,5 +1,6 @@
1
1
  import { Attachment, PersonalProject, WorkspaceProject, Label, Section, Comment, Task, CurrentUser, ProductivityStats, WorkspaceInvitation, WorkspacePlanDetails, JoinWorkspaceResult } from './types/entities';
2
2
  import { AddCommentArgs, AddLabelArgs, AddProjectArgs, AddSectionArgs, AddTaskArgs, GetProjectCommentsArgs, GetTaskCommentsArgs, GetTasksArgs, GetTasksByFilterArgs, UpdateCommentArgs, UpdateLabelArgs, UpdateProjectArgs, UpdateSectionArgs, UpdateTaskArgs, QuickAddTaskArgs, GetSharedLabelsArgs, RenameSharedLabelArgs, RemoveSharedLabelArgs, GetProjectsArgs, GetProjectCollaboratorsArgs, GetLabelsArgs, GetLabelsResponse, GetTasksResponse, GetProjectsResponse, GetProjectCollaboratorsResponse, GetSectionsArgs, GetSectionsResponse, GetSharedLabelsResponse, GetCommentsResponse, type MoveTaskArgs, GetCompletedTasksByCompletionDateArgs, GetCompletedTasksByDueDateArgs, GetCompletedTasksResponse, GetArchivedProjectsArgs, GetArchivedProjectsResponse, SearchCompletedTasksArgs, GetActivityLogsArgs, GetActivityLogsResponse, UploadFileArgs, DeleteUploadArgs, GetWorkspaceInvitationsArgs, DeleteWorkspaceInvitationArgs, WorkspaceInvitationActionArgs, JoinWorkspaceArgs, WorkspaceLogoArgs, GetWorkspacePlanDetailsArgs, GetWorkspaceUsersArgs, GetWorkspaceUsersResponse, GetWorkspaceProjectsArgs, WorkspaceInvitationsResponse, AllWorkspaceInvitationsResponse, WorkspaceLogoResponse } from './types/requests';
3
+ import { CustomFetch } from './types/http';
3
4
  /**
4
5
  * A client for interacting with the Todoist API v1.
5
6
  * This class provides methods to manage tasks, projects, sections, labels, and comments in Todoist.
@@ -21,18 +22,28 @@ import { AddCommentArgs, AddLabelArgs, AddProjectArgs, AddSectionArgs, AddTaskAr
21
22
  * For more information about the Todoist API v1, see the [official documentation](https://todoist.com/api/v1).
22
23
  * If you're migrating from v9, please refer to the [migration guide](https://todoist.com/api/v1/docs#tag/Migrating-from-v9).
23
24
  */
25
+ /**
26
+ * Configuration options for the TodoistApi constructor
27
+ */
28
+ export type TodoistApiOptions = {
29
+ /**
30
+ * Optional custom API base URL. If not provided, defaults to Todoist's standard API endpoint
31
+ */
32
+ baseUrl?: string;
33
+ /**
34
+ * Optional custom fetch function for alternative HTTP clients (e.g., Obsidian's requestUrl, React Native fetch)
35
+ */
36
+ customFetch?: CustomFetch;
37
+ };
24
38
  export declare class TodoistApi {
25
39
  private authToken;
26
40
  private syncApiBase;
27
- constructor(
41
+ private customFetch?;
28
42
  /**
29
- * Your Todoist API token.
30
- */
31
- authToken: string,
32
- /**
33
- * Optional custom API base URL. If not provided, defaults to Todoist's standard API endpoint
43
+ * @deprecated Use options object instead: new TodoistApi(token, { baseUrl, customFetch })
34
44
  */
35
- baseUrl?: string);
45
+ constructor(authToken: string, baseUrl?: string);
46
+ constructor(authToken: string, options?: TodoistApiOptions);
36
47
  /**
37
48
  * Retrieves information about the authenticated user.
38
49
  *
@@ -818,15 +818,15 @@ export declare const WorkspacePlanDetailsSchema: z.ZodObject<{
818
818
  */
819
819
  export type WorkspacePlanDetails = z.infer<typeof WorkspacePlanDetailsSchema>;
820
820
  export declare const JoinWorkspaceResultSchema: z.ZodObject<{
821
- custom_sorting_applied: z.ZodBoolean;
822
- project_sort_preference: z.ZodString;
821
+ customSortingApplied: z.ZodBoolean;
822
+ projectSortPreference: z.ZodString;
823
823
  role: z.ZodEnum<{
824
824
  ADMIN: "ADMIN";
825
825
  MEMBER: "MEMBER";
826
826
  GUEST: "GUEST";
827
827
  }>;
828
- user_id: z.ZodString;
829
- workspace_id: z.ZodString;
828
+ userId: z.ZodString;
829
+ workspaceId: z.ZodString;
830
830
  }, z.core.$strip>;
831
831
  /**
832
832
  * Result returned when successfully joining a workspace.
@@ -66,3 +66,20 @@ export declare function isNetworkError(error: Error): error is NetworkError;
66
66
  * Type guard to check if an error is an HTTP error
67
67
  */
68
68
  export declare function isHttpError(error: Error): error is HttpError;
69
+ /**
70
+ * Custom fetch response interface that custom HTTP clients must implement
71
+ */
72
+ export type CustomFetchResponse = {
73
+ ok: boolean;
74
+ status: number;
75
+ statusText: string;
76
+ headers: Record<string, string>;
77
+ text(): Promise<string>;
78
+ json(): Promise<unknown>;
79
+ };
80
+ /**
81
+ * Custom fetch function type for alternative HTTP clients
82
+ */
83
+ export type CustomFetch = (url: string, options?: RequestInit & {
84
+ timeout?: number;
85
+ }) => Promise<CustomFetchResponse>;
@@ -1,3 +1,4 @@
1
1
  export * from './entities';
2
2
  export * from './errors';
3
3
  export * from './requests';
4
+ export * from './http';
@@ -6,10 +6,10 @@ export type Command = {
6
6
  };
7
7
  export type SyncError = {
8
8
  error: string;
9
- error_code: number;
10
- error_extra: Record<string, unknown>;
11
- error_tag: string;
12
- http_code: number;
9
+ errorCode: number;
10
+ errorExtra: Record<string, unknown>;
11
+ errorTag: string;
12
+ httpCode: number;
13
13
  };
14
14
  export type SyncRequest = {
15
15
  commands: Command[];
@@ -17,5 +17,5 @@ export type SyncRequest = {
17
17
  };
18
18
  export type SyncResponse = {
19
19
  items?: Task[];
20
- sync_status?: Record<string, 'ok' | SyncError>;
20
+ syncStatus?: Record<string, 'ok' | SyncError>;
21
21
  };
@@ -1,4 +1,4 @@
1
- import type { HttpResponse, RetryConfig } from '../types/http';
1
+ import type { HttpResponse, RetryConfig, CustomFetch } from '../types/http';
2
2
  /**
3
3
  * Performs a fetch request with retry logic and timeout support
4
4
  */
@@ -8,4 +8,5 @@ export declare function fetchWithRetry<T = unknown>(args: {
8
8
  timeout?: number;
9
9
  };
10
10
  retryConfig?: Partial<RetryConfig>;
11
+ customFetch?: CustomFetch;
11
12
  }): Promise<HttpResponse<T>>;
@@ -1,3 +1,4 @@
1
+ import type { CustomFetch } from '../types/http';
1
2
  type UploadMultipartFileArgs = {
2
3
  baseUrl: string;
3
4
  authToken: string;
@@ -6,6 +7,7 @@ type UploadMultipartFileArgs = {
6
7
  fileName?: string;
7
8
  additionalFields: Record<string, string | number | boolean>;
8
9
  requestId?: string;
10
+ customFetch?: CustomFetch;
9
11
  };
10
12
  /**
11
13
  * Uploads a file using multipart/form-data.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doist/todoist-api-typescript",
3
- "version": "6.0.1",
3
+ "version": "6.1.4",
4
4
  "description": "A typescript wrapper for the Todoist REST API.",
5
5
  "author": "Doist developers",
6
6
  "repository": "git@github.com:doist/todoist-api-typescript.git",
@@ -23,8 +23,8 @@
23
23
  },
24
24
  "scripts": {
25
25
  "clean": "rimraf dist",
26
- "format-check": "npx prettier --check \"./**/*.{ts,tsx,json,md,yml,babelrc,html}\"",
27
- "format-fix": "npx prettier --write \"./**/*.{ts,tsx,json,md,yml,babelrc,html}\"",
26
+ "format-check": "npx prettier --check \"./**/*.{ts,tsx,json,md,yml,babelrc,html}\" --ignore-path .prettierignore",
27
+ "format-fix": "npx prettier --write \"./**/*.{ts,tsx,json,md,yml,babelrc,html}\" --ignore-path .prettierignore",
28
28
  "lint": "eslint ./src --ext ts,tsx --fix",
29
29
  "lint-check": "eslint ./src --ext ts,tsx",
30
30
  "ts-compile-check": "npx tsc -p tsconfig.typecheck.json",
@@ -63,6 +63,7 @@
63
63
  "lint-staged": "16.1.6",
64
64
  "msw": "2.11.6",
65
65
  "npm-run-all2": "8.0.4",
66
+ "obsidian": "^1.10.2-1",
66
67
  "prettier": "3.3.2",
67
68
  "rimraf": "6.0.1",
68
69
  "ts-jest": "29.4.5",