@doist/todoist-api-typescript 5.9.0 → 6.0.0
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.
- package/dist/cjs/authentication.js +158 -0
- package/dist/{consts → cjs/consts}/endpoints.js +10 -12
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/rest-client.js +124 -0
- package/dist/{test-utils → cjs/test-utils}/asserts.js +1 -1
- package/dist/{test-utils → cjs/test-utils}/mocks.js +8 -4
- package/dist/cjs/test-utils/msw-setup.js +27 -0
- package/dist/{test-utils → cjs/test-utils}/test-defaults.js +41 -52
- package/dist/cjs/todoist-api.js +1235 -0
- package/dist/{types → cjs/types}/entities.js +19 -30
- package/dist/cjs/types/errors.js +22 -0
- package/dist/cjs/types/http.js +22 -0
- package/dist/cjs/utils/case-conversion.js +69 -0
- package/dist/{utils → cjs/utils}/colors.js +3 -3
- package/dist/cjs/utils/fetch-with-retry.js +150 -0
- package/dist/cjs/utils/multipart-upload.js +126 -0
- package/dist/{utils → cjs/utils}/processing-helpers.js +3 -3
- package/dist/{utils → cjs/utils}/sanitization.js +17 -28
- package/dist/{utils → cjs/utils}/url-helpers.js +15 -15
- package/dist/{utils → cjs/utils}/validators.js +2 -2
- package/dist/esm/authentication.js +151 -0
- package/dist/esm/consts/endpoints.js +65 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/rest-client.js +119 -0
- package/dist/esm/test-utils/asserts.js +8 -0
- package/dist/esm/test-utils/mocks.js +10 -0
- package/dist/esm/test-utils/msw-setup.js +22 -0
- package/dist/esm/test-utils/test-defaults.js +198 -0
- package/dist/esm/todoist-api.js +1231 -0
- package/dist/esm/types/entities.js +366 -0
- package/dist/esm/types/errors.js +18 -0
- package/dist/esm/types/http.js +18 -0
- package/dist/esm/types/index.js +3 -0
- package/dist/esm/types/requests.js +1 -0
- package/dist/esm/types/sync.js +1 -0
- package/dist/esm/utils/activity-helpers.js +36 -0
- package/dist/esm/utils/case-conversion.js +61 -0
- package/dist/esm/utils/colors.js +215 -0
- package/dist/esm/utils/fetch-with-retry.js +147 -0
- package/dist/esm/utils/index.js +3 -0
- package/dist/esm/utils/multipart-upload.js +120 -0
- package/dist/esm/utils/processing-helpers.js +12 -0
- package/dist/esm/utils/sanitization.js +112 -0
- package/dist/esm/utils/url-helpers.js +68 -0
- package/dist/esm/utils/validators.js +97 -0
- package/dist/{authentication.d.ts → types/authentication.d.ts} +6 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/{rest-client.d.ts → types/rest-client.d.ts} +3 -4
- package/dist/types/test-utils/msw-setup.d.ts +3 -0
- package/dist/types/types/http.d.ts +68 -0
- package/dist/types/types/index.d.ts +3 -0
- package/dist/types/utils/case-conversion.d.ts +12 -0
- package/dist/types/utils/fetch-with-retry.d.ts +11 -0
- package/package.json +24 -8
- package/dist/authentication.js +0 -220
- package/dist/index.d.ts +0 -4
- package/dist/rest-client.js +0 -178
- package/dist/todoist-api.js +0 -1845
- package/dist/types/errors.js +0 -39
- package/dist/types/http.d.ts +0 -1
- package/dist/types/http.js +0 -2
- package/dist/utils/multipart-upload.js +0 -171
- /package/dist/{index.js → cjs/index.js} +0 -0
- /package/dist/{types → cjs/types}/index.js +0 -0
- /package/dist/{types → cjs/types}/requests.js +0 -0
- /package/dist/{types → cjs/types}/sync.js +0 -0
- /package/dist/{utils → cjs/utils}/activity-helpers.js +0 -0
- /package/dist/{utils → cjs/utils}/index.js +0 -0
- /package/dist/{consts → types/consts}/endpoints.d.ts +0 -0
- /package/dist/{test-utils → types/test-utils}/asserts.d.ts +0 -0
- /package/dist/{test-utils → types/test-utils}/mocks.d.ts +0 -0
- /package/dist/{test-utils → types/test-utils}/test-defaults.d.ts +0 -0
- /package/dist/{todoist-api.d.ts → types/todoist-api.d.ts} +0 -0
- /package/dist/types/{entities.d.ts → types/entities.d.ts} +0 -0
- /package/dist/types/{errors.d.ts → types/errors.d.ts} +0 -0
- /package/dist/types/{requests.d.ts → types/requests.d.ts} +0 -0
- /package/dist/types/{sync.d.ts → types/sync.d.ts} +0 -0
- /package/dist/{utils → types/utils}/activity-helpers.d.ts +0 -0
- /package/dist/{utils → types/utils}/colors.d.ts +0 -0
- /package/dist/{utils → types/utils}/index.d.ts +0 -0
- /package/dist/{utils → types/utils}/multipart-upload.d.ts +0 -0
- /package/dist/{utils → types/utils}/processing-helpers.d.ts +0 -0
- /package/dist/{utils → types/utils}/sanitization.d.ts +0 -0
- /package/dist/{utils → types/utils}/url-helpers.d.ts +0 -0
- /package/dist/{utils → types/utils}/validators.d.ts +0 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { AttachmentSchema, SectionSchema, LabelSchema, CommentSchema, UserSchema, CurrentUserSchema, TaskSchema, PersonalProjectSchema, WorkspaceProjectSchema, ProductivityStatsSchema, ActivityEventSchema, WorkspaceUserSchema, WorkspaceInvitationSchema, WorkspacePlanDetailsSchema, JoinWorkspaceResultSchema, } from '../types/entities.js';
|
|
2
|
+
export function validateTask(input) {
|
|
3
|
+
return TaskSchema.parse(input);
|
|
4
|
+
}
|
|
5
|
+
export function validateTaskArray(input) {
|
|
6
|
+
return input.map(validateTask);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Type guard to check if a project is a workspace project.
|
|
10
|
+
* @param project The project to check
|
|
11
|
+
* @returns True if the project is a workspace project
|
|
12
|
+
*/
|
|
13
|
+
export function isWorkspaceProject(project) {
|
|
14
|
+
return 'workspaceId' in project;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Type guard to check if a project is a personal project.
|
|
18
|
+
* @param project The project to check
|
|
19
|
+
* @returns True if the project is a personal project
|
|
20
|
+
*/
|
|
21
|
+
export function isPersonalProject(project) {
|
|
22
|
+
return !isWorkspaceProject(project);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Validates and parses a project input.
|
|
26
|
+
* @param input The input to validate
|
|
27
|
+
* @returns A validated project (either PersonalProject or WorkspaceProject)
|
|
28
|
+
*/
|
|
29
|
+
export function validateProject(input) {
|
|
30
|
+
if ('workspaceId' in input) {
|
|
31
|
+
return WorkspaceProjectSchema.parse(input);
|
|
32
|
+
}
|
|
33
|
+
return PersonalProjectSchema.parse(input);
|
|
34
|
+
}
|
|
35
|
+
export function validateProjectArray(input) {
|
|
36
|
+
return input.map(validateProject);
|
|
37
|
+
}
|
|
38
|
+
export function validateSection(input) {
|
|
39
|
+
return SectionSchema.parse(input);
|
|
40
|
+
}
|
|
41
|
+
export function validateSectionArray(input) {
|
|
42
|
+
return input.map(validateSection);
|
|
43
|
+
}
|
|
44
|
+
export function validateLabel(input) {
|
|
45
|
+
return LabelSchema.parse(input);
|
|
46
|
+
}
|
|
47
|
+
export function validateLabelArray(input) {
|
|
48
|
+
return input.map(validateLabel);
|
|
49
|
+
}
|
|
50
|
+
export function validateComment(input) {
|
|
51
|
+
return CommentSchema.parse(input);
|
|
52
|
+
}
|
|
53
|
+
export function validateCommentArray(input) {
|
|
54
|
+
return input.map(validateComment);
|
|
55
|
+
}
|
|
56
|
+
export function validateUser(input) {
|
|
57
|
+
return UserSchema.parse(input);
|
|
58
|
+
}
|
|
59
|
+
export function validateUserArray(input) {
|
|
60
|
+
return input.map(validateUser);
|
|
61
|
+
}
|
|
62
|
+
export function validateProductivityStats(input) {
|
|
63
|
+
return ProductivityStatsSchema.parse(input);
|
|
64
|
+
}
|
|
65
|
+
export function validateCurrentUser(input) {
|
|
66
|
+
return CurrentUserSchema.parse(input);
|
|
67
|
+
}
|
|
68
|
+
export function validateActivityEvent(input) {
|
|
69
|
+
return ActivityEventSchema.parse(input);
|
|
70
|
+
}
|
|
71
|
+
export function validateActivityEventArray(input) {
|
|
72
|
+
return input.map(validateActivityEvent);
|
|
73
|
+
}
|
|
74
|
+
export function validateAttachment(input) {
|
|
75
|
+
return AttachmentSchema.parse(input);
|
|
76
|
+
}
|
|
77
|
+
export function validateWorkspaceUser(input) {
|
|
78
|
+
return WorkspaceUserSchema.parse(input);
|
|
79
|
+
}
|
|
80
|
+
export function validateWorkspaceUserArray(input) {
|
|
81
|
+
if (!Array.isArray(input)) {
|
|
82
|
+
throw new Error(`Expected array for workspace users, got ${typeof input}`);
|
|
83
|
+
}
|
|
84
|
+
return input.map(validateWorkspaceUser);
|
|
85
|
+
}
|
|
86
|
+
export function validateWorkspaceInvitation(input) {
|
|
87
|
+
return WorkspaceInvitationSchema.parse(input);
|
|
88
|
+
}
|
|
89
|
+
export function validateWorkspaceInvitationArray(input) {
|
|
90
|
+
return input.map(validateWorkspaceInvitation);
|
|
91
|
+
}
|
|
92
|
+
export function validateWorkspacePlanDetails(input) {
|
|
93
|
+
return WorkspacePlanDetailsSchema.parse(input);
|
|
94
|
+
}
|
|
95
|
+
export function validateJoinWorkspaceResult(input) {
|
|
96
|
+
return JoinWorkspaceResultSchema.parse(input);
|
|
97
|
+
}
|
|
@@ -68,7 +68,12 @@ export declare function getAuthStateParameter(): string;
|
|
|
68
68
|
* @returns The full authorization URL to redirect users to
|
|
69
69
|
* @see https://todoist.com/api/v1/docs#tag/Authorization/OAuth
|
|
70
70
|
*/
|
|
71
|
-
export declare function getAuthorizationUrl(clientId
|
|
71
|
+
export declare function getAuthorizationUrl({ clientId, permissions, state, baseUrl, }: {
|
|
72
|
+
clientId: string;
|
|
73
|
+
permissions: Permission[];
|
|
74
|
+
state: string;
|
|
75
|
+
baseUrl?: string;
|
|
76
|
+
}): string;
|
|
72
77
|
/**
|
|
73
78
|
* Exchanges an authorization code for an access token.
|
|
74
79
|
*
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './
|
|
1
|
+
export * from './todoist-api';
|
|
2
|
+
export * from './authentication';
|
|
3
|
+
export * from './types';
|
|
4
|
+
export * from './utils';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { HttpMethod } from './types/http';
|
|
1
|
+
import { HttpMethod, HttpResponse } from './types/http';
|
|
3
2
|
type RequestArgs = {
|
|
4
3
|
httpMethod: HttpMethod;
|
|
5
4
|
baseUri: string;
|
|
@@ -11,6 +10,6 @@ type RequestArgs = {
|
|
|
11
10
|
customHeaders?: Record<string, string>;
|
|
12
11
|
};
|
|
13
12
|
export declare function paramsSerializer(params: Record<string, unknown>): string;
|
|
14
|
-
export declare function isSuccess(response:
|
|
15
|
-
export declare function request<T>(args: RequestArgs): Promise<
|
|
13
|
+
export declare function isSuccess(response: HttpResponse): boolean;
|
|
14
|
+
export declare function request<T>(args: RequestArgs): Promise<HttpResponse<T>>;
|
|
16
15
|
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export type HttpMethod = 'POST' | 'GET' | 'DELETE' | 'PUT';
|
|
2
|
+
/**
|
|
3
|
+
* HTTP response type that replaces AxiosResponse
|
|
4
|
+
*/
|
|
5
|
+
export type HttpResponse<T = unknown> = {
|
|
6
|
+
data: T;
|
|
7
|
+
status: number;
|
|
8
|
+
statusText: string;
|
|
9
|
+
headers: Record<string, string>;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* HTTP request configuration
|
|
13
|
+
*/
|
|
14
|
+
export type HttpRequestConfig = {
|
|
15
|
+
method?: HttpMethod;
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
timeout?: number;
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Internal HTTP request options
|
|
22
|
+
*/
|
|
23
|
+
export type HttpRequestOptions = HttpRequestConfig & {
|
|
24
|
+
url: string;
|
|
25
|
+
params?: Record<string, unknown>;
|
|
26
|
+
data?: unknown;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Configuration for retry behavior
|
|
30
|
+
*/
|
|
31
|
+
export type RetryConfig = {
|
|
32
|
+
retries: number;
|
|
33
|
+
retryCondition: (error: Error) => boolean;
|
|
34
|
+
retryDelay: (retryNumber: number) => number;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Configuration for the HTTP client
|
|
38
|
+
*/
|
|
39
|
+
export type HttpClientConfig = {
|
|
40
|
+
baseURL?: string;
|
|
41
|
+
headers?: Record<string, string>;
|
|
42
|
+
timeout?: number;
|
|
43
|
+
retry?: RetryConfig;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Network error type for retry logic
|
|
47
|
+
*/
|
|
48
|
+
export type NetworkError = Error & {
|
|
49
|
+
code?: string;
|
|
50
|
+
isNetworkError: true;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* HTTP error with status code and response data
|
|
54
|
+
*/
|
|
55
|
+
export type HttpError = Error & {
|
|
56
|
+
status?: number;
|
|
57
|
+
statusText?: string;
|
|
58
|
+
response?: HttpResponse<unknown>;
|
|
59
|
+
data?: unknown;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Type guard to check if an error is a network error
|
|
63
|
+
*/
|
|
64
|
+
export declare function isNetworkError(error: Error): error is NetworkError;
|
|
65
|
+
/**
|
|
66
|
+
* Type guard to check if an error is an HTTP error
|
|
67
|
+
*/
|
|
68
|
+
export declare function isHttpError(error: Error): error is HttpError;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom camelCase function that preserves emoji strings
|
|
3
|
+
*/
|
|
4
|
+
export declare function customCamelCase(input: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Converts object keys from snake_case to camelCase recursively
|
|
7
|
+
*/
|
|
8
|
+
export declare function camelCaseKeys<T>(obj: T): T;
|
|
9
|
+
/**
|
|
10
|
+
* Converts object keys from camelCase to snake_case recursively
|
|
11
|
+
*/
|
|
12
|
+
export declare function snakeCaseKeys<T>(obj: T): T;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HttpResponse, RetryConfig } from '../types/http';
|
|
2
|
+
/**
|
|
3
|
+
* Performs a fetch request with retry logic and timeout support
|
|
4
|
+
*/
|
|
5
|
+
export declare function fetchWithRetry<T = unknown>(args: {
|
|
6
|
+
url: string;
|
|
7
|
+
options?: RequestInit & {
|
|
8
|
+
timeout?: number;
|
|
9
|
+
};
|
|
10
|
+
retryConfig?: Partial<RetryConfig>;
|
|
11
|
+
}): Promise<HttpResponse<T>>;
|
package/package.json
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doist/todoist-api-typescript",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
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",
|
|
7
7
|
"homepage": "https://doist.github.io/todoist-api-typescript/",
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "dist/cjs/index.js",
|
|
11
|
+
"module": "dist/esm/index.js",
|
|
12
|
+
"types": "dist/types/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./dist/esm/index.js",
|
|
16
|
+
"require": "./dist/cjs/index.js",
|
|
17
|
+
"types": "./dist/types/index.d.ts"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
11
20
|
"sideEffects": false,
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=20.0.0"
|
|
23
|
+
},
|
|
12
24
|
"scripts": {
|
|
13
25
|
"clean": "rimraf dist",
|
|
14
26
|
"format-check": "npx prettier --check \"./**/*.{ts,tsx,json,md,yml,babelrc,html}\"",
|
|
@@ -18,15 +30,16 @@
|
|
|
18
30
|
"ts-compile-check": "npx tsc -p tsconfig.typecheck.json",
|
|
19
31
|
"audit": "npm audit --audit-level=moderate",
|
|
20
32
|
"test": "jest",
|
|
21
|
-
"build": "npx tsc -p tsconfig.json",
|
|
33
|
+
"build:cjs": "npx tsc -p tsconfig.cjs.json",
|
|
34
|
+
"build:esm": "npx tsc -p tsconfig.esm.json",
|
|
35
|
+
"build:fix-esm": "node scripts/fix-esm-imports.cjs",
|
|
36
|
+
"build:post": "echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
|
|
37
|
+
"build": "npm-run-all clean build:cjs build:esm build:fix-esm build:post",
|
|
22
38
|
"integrity-checks": "npm-run-all clean format-check lint-check test build",
|
|
23
39
|
"prepublishOnly": "npm run integrity-checks",
|
|
24
40
|
"prepare": "npm run build"
|
|
25
41
|
},
|
|
26
42
|
"dependencies": {
|
|
27
|
-
"axios": "^1.0.0",
|
|
28
|
-
"axios-case-converter": "^1.0.0",
|
|
29
|
-
"axios-retry": "^4.0.0",
|
|
30
43
|
"camelcase": "6.3.0",
|
|
31
44
|
"emoji-regex": "10.6.0",
|
|
32
45
|
"form-data": "4.0.4",
|
|
@@ -48,6 +61,7 @@
|
|
|
48
61
|
"husky": "9.1.7",
|
|
49
62
|
"jest": "30.1.3",
|
|
50
63
|
"lint-staged": "16.1.6",
|
|
64
|
+
"msw": "2.11.6",
|
|
51
65
|
"npm-run-all2": "8.0.4",
|
|
52
66
|
"prettier": "3.3.2",
|
|
53
67
|
"rimraf": "6.0.1",
|
|
@@ -70,7 +84,9 @@
|
|
|
70
84
|
"*.{ts,tsx,json,html,yml,yaml,md}": "prettier --check"
|
|
71
85
|
},
|
|
72
86
|
"files": [
|
|
73
|
-
"dist/**/*",
|
|
87
|
+
"dist/cjs/**/*",
|
|
88
|
+
"dist/esm/**/*",
|
|
89
|
+
"dist/types/**/*",
|
|
74
90
|
"!dist/**/*.test.js",
|
|
75
91
|
"!dist/**/*.test.d.ts"
|
|
76
92
|
]
|
package/dist/authentication.js
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.getAuthStateParameter = getAuthStateParameter;
|
|
40
|
-
exports.getAuthorizationUrl = getAuthorizationUrl;
|
|
41
|
-
exports.getAuthToken = getAuthToken;
|
|
42
|
-
exports.revokeAuthToken = revokeAuthToken;
|
|
43
|
-
exports.revokeToken = revokeToken;
|
|
44
|
-
var rest_client_1 = require("./rest-client");
|
|
45
|
-
var uuid_1 = require("uuid");
|
|
46
|
-
var types_1 = require("./types");
|
|
47
|
-
var endpoints_1 = require("./consts/endpoints");
|
|
48
|
-
/**
|
|
49
|
-
* Creates a Basic Authentication header value from client credentials.
|
|
50
|
-
* @param clientId - The OAuth client ID
|
|
51
|
-
* @param clientSecret - The OAuth client secret
|
|
52
|
-
* @returns The Basic Auth header value (without the 'Basic ' prefix)
|
|
53
|
-
*/
|
|
54
|
-
function createBasicAuthHeader(clientId, clientSecret) {
|
|
55
|
-
var credentials = "".concat(clientId, ":").concat(clientSecret);
|
|
56
|
-
return Buffer.from(credentials).toString('base64');
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Generates a random state parameter for OAuth2 authorization.
|
|
60
|
-
* The state parameter helps prevent CSRF attacks.
|
|
61
|
-
*
|
|
62
|
-
* @example
|
|
63
|
-
* ```typescript
|
|
64
|
-
* const state = getAuthStateParameter()
|
|
65
|
-
* // Store state in session
|
|
66
|
-
* const authUrl = getAuthorizationUrl(clientId, ['data:read'], state)
|
|
67
|
-
* ```
|
|
68
|
-
*
|
|
69
|
-
* @returns A random UUID v4 string
|
|
70
|
-
*/
|
|
71
|
-
function getAuthStateParameter() {
|
|
72
|
-
return (0, uuid_1.v4)();
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Generates the authorization URL for the OAuth2 flow.
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
|
-
* ```typescript
|
|
79
|
-
* const url = getAuthorizationUrl(
|
|
80
|
-
* 'your-client-id',
|
|
81
|
-
* ['data:read', 'task:add'],
|
|
82
|
-
* state
|
|
83
|
-
* )
|
|
84
|
-
* // Redirect user to url
|
|
85
|
-
* ```
|
|
86
|
-
*
|
|
87
|
-
* @returns The full authorization URL to redirect users to
|
|
88
|
-
* @see https://todoist.com/api/v1/docs#tag/Authorization/OAuth
|
|
89
|
-
*/
|
|
90
|
-
function getAuthorizationUrl(clientId, permissions, state, baseUrl) {
|
|
91
|
-
if (!(permissions === null || permissions === void 0 ? void 0 : permissions.length)) {
|
|
92
|
-
throw new Error('At least one scope value should be passed for permissions.');
|
|
93
|
-
}
|
|
94
|
-
var scope = permissions.join(',');
|
|
95
|
-
return "".concat((0, endpoints_1.getAuthBaseUri)(baseUrl)).concat(endpoints_1.ENDPOINT_AUTHORIZATION, "?client_id=").concat(clientId, "&scope=").concat(scope, "&state=").concat(state);
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Exchanges an authorization code for an access token.
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* ```typescript
|
|
102
|
-
* const { accessToken } = await getAuthToken({
|
|
103
|
-
* clientId: 'your-client-id',
|
|
104
|
-
* clientSecret: 'your-client-secret',
|
|
105
|
-
* code: authCode
|
|
106
|
-
* })
|
|
107
|
-
* ```
|
|
108
|
-
*
|
|
109
|
-
* @returns The access token response
|
|
110
|
-
* @throws {@link TodoistRequestError} If the token exchange fails
|
|
111
|
-
*/
|
|
112
|
-
function getAuthToken(args, baseUrl) {
|
|
113
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
114
|
-
var response;
|
|
115
|
-
var _a;
|
|
116
|
-
return __generator(this, function (_b) {
|
|
117
|
-
switch (_b.label) {
|
|
118
|
-
case 0: return [4 /*yield*/, (0, rest_client_1.request)({
|
|
119
|
-
httpMethod: 'POST',
|
|
120
|
-
baseUri: (0, endpoints_1.getAuthBaseUri)(baseUrl),
|
|
121
|
-
relativePath: endpoints_1.ENDPOINT_GET_TOKEN,
|
|
122
|
-
apiToken: undefined,
|
|
123
|
-
payload: args,
|
|
124
|
-
})];
|
|
125
|
-
case 1:
|
|
126
|
-
response = _b.sent();
|
|
127
|
-
if (response.status !== 200 || !((_a = response.data) === null || _a === void 0 ? void 0 : _a.accessToken)) {
|
|
128
|
-
throw new types_1.TodoistRequestError('Authentication token exchange failed.', response.status, response.data);
|
|
129
|
-
}
|
|
130
|
-
return [2 /*return*/, response.data];
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Revokes an access token, making it invalid for future use.
|
|
137
|
-
*
|
|
138
|
-
* @example
|
|
139
|
-
* ```typescript
|
|
140
|
-
* await revokeAuthToken({
|
|
141
|
-
* clientId: 'your-client-id',
|
|
142
|
-
* clientSecret: 'your-client-secret',
|
|
143
|
-
* accessToken: token
|
|
144
|
-
* })
|
|
145
|
-
* ```
|
|
146
|
-
*
|
|
147
|
-
* @deprecated Use {@link revokeToken} instead. This function uses a legacy endpoint that will be removed in a future version. The new function uses the RFC 7009 compliant endpoint.
|
|
148
|
-
* @returns True if revocation was successful
|
|
149
|
-
* @see https://todoist.com/api/v1/docs#tag/Authorization/operation/revoke_access_token_api_api_v1_access_tokens_delete
|
|
150
|
-
*/
|
|
151
|
-
function revokeAuthToken(args, baseUrl) {
|
|
152
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
153
|
-
var response;
|
|
154
|
-
return __generator(this, function (_a) {
|
|
155
|
-
switch (_a.label) {
|
|
156
|
-
case 0: return [4 /*yield*/, (0, rest_client_1.request)({
|
|
157
|
-
httpMethod: 'POST',
|
|
158
|
-
baseUri: (0, endpoints_1.getSyncBaseUri)(baseUrl),
|
|
159
|
-
relativePath: endpoints_1.ENDPOINT_REVOKE_TOKEN,
|
|
160
|
-
apiToken: undefined,
|
|
161
|
-
payload: args,
|
|
162
|
-
})];
|
|
163
|
-
case 1:
|
|
164
|
-
response = _a.sent();
|
|
165
|
-
return [2 /*return*/, (0, rest_client_1.isSuccess)(response)];
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Revokes a token using the RFC 7009 OAuth 2.0 Token Revocation standard.
|
|
172
|
-
*
|
|
173
|
-
* This function uses HTTP Basic Authentication with client credentials and follows
|
|
174
|
-
* the RFC 7009 specification for token revocation.
|
|
175
|
-
*
|
|
176
|
-
* @example
|
|
177
|
-
* ```typescript
|
|
178
|
-
* await revokeToken({
|
|
179
|
-
* clientId: 'your-client-id',
|
|
180
|
-
* clientSecret: 'your-client-secret',
|
|
181
|
-
* token: 'access-token-to-revoke'
|
|
182
|
-
* })
|
|
183
|
-
* ```
|
|
184
|
-
*
|
|
185
|
-
* @returns True if revocation was successful
|
|
186
|
-
* @see https://datatracker.ietf.org/doc/html/rfc7009
|
|
187
|
-
* @see https://todoist.com/api/v1/docs#tag/Authorization
|
|
188
|
-
*/
|
|
189
|
-
function revokeToken(args, baseUrl) {
|
|
190
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
191
|
-
var clientId, clientSecret, token, basicAuth, customHeaders, requestBody, response;
|
|
192
|
-
return __generator(this, function (_a) {
|
|
193
|
-
switch (_a.label) {
|
|
194
|
-
case 0:
|
|
195
|
-
clientId = args.clientId, clientSecret = args.clientSecret, token = args.token;
|
|
196
|
-
basicAuth = createBasicAuthHeader(clientId, clientSecret);
|
|
197
|
-
customHeaders = {
|
|
198
|
-
Authorization: "Basic ".concat(basicAuth),
|
|
199
|
-
};
|
|
200
|
-
requestBody = {
|
|
201
|
-
token: token,
|
|
202
|
-
token_type_hint: 'access_token',
|
|
203
|
-
};
|
|
204
|
-
return [4 /*yield*/, (0, rest_client_1.request)({
|
|
205
|
-
httpMethod: 'POST',
|
|
206
|
-
baseUri: (0, endpoints_1.getSyncBaseUri)(baseUrl),
|
|
207
|
-
relativePath: endpoints_1.ENDPOINT_REVOKE,
|
|
208
|
-
apiToken: undefined,
|
|
209
|
-
payload: requestBody,
|
|
210
|
-
requestId: undefined,
|
|
211
|
-
hasSyncCommands: false,
|
|
212
|
-
customHeaders: customHeaders,
|
|
213
|
-
})];
|
|
214
|
-
case 1:
|
|
215
|
-
response = _a.sent();
|
|
216
|
-
return [2 /*return*/, (0, rest_client_1.isSuccess)(response)];
|
|
217
|
-
}
|
|
218
|
-
});
|
|
219
|
-
});
|
|
220
|
-
}
|
package/dist/index.d.ts
DELETED