n8n-nodes-ticktick 1.0.1

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/LICENSE.md ADDED
@@ -0,0 +1,19 @@
1
+ Copyright 2022 n8n
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,196 @@
1
+ # n8n-nodes-ticktick
2
+
3
+
4
+ [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation platform.
5
+
6
+ This is an n8n community node. It lets you use TickTick in your n8n workflows.
7
+
8
+ TickTick is a comprehensive productivity app designed to help individuals and teams manage tasks, deadlines, and projects more efficiently. With its intuitive interface, TickTick allows users to easily create, organize, and prioritize tasks, set reminders, and track progress through various views such as lists, kanban boards, and calendars.
9
+
10
+ [Installation](#installation)
11
+ [Task Operations](#task-operations)
12
+ [Project Operations](#projectoperations)
13
+ [Credentials](#credentials)
14
+ [Compatibility](#compatibility)
15
+ [Known Issues](#known-issues)
16
+ [Resources](#resources)
17
+ [Version history](#version-history)
18
+
19
+ ## Installation
20
+
21
+ Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.
22
+
23
+ 1. Go to **Settings** > **Community Nodes.**
24
+ 2. Select **Install.**
25
+ 3. Find the node you want to install:
26
+
27
+ a.) Select **Browse**. n8n takes you to an npm search results page, showing all npm packages tagged with the keyword `n8n-community-node-package`.
28
+
29
+ b.) Browse the list of results. You can filter the results or add more keywords.
30
+
31
+ c.) Once you find the package you want, make a note of the package name. If you want to install a specific version, make a note of the version number as well.
32
+
33
+ d.) Return to n8n.
34
+
35
+ 4. Enter the npm package name, and version number if required.
36
+ 5. Agree to the risks of using community nodes: select I understand the risks of installing unverified code from a public source.
37
+ 6. Select Install. n8n installs the node, and returns to the Community Nodes list in Settings.
38
+
39
+ ## Task Operations
40
+
41
+ ### 1. Create a Task
42
+
43
+ Parameters:
44
+
45
+ - Task Title (required)
46
+ - Task Content
47
+ - Description of Checklist
48
+ - All day
49
+ - Start date
50
+ - Due date
51
+
52
+ >> use Additional Fields or JSON Parameters
53
+ >> Subtasks will be part of the next release
54
+
55
+ ### 2. Get Task By Project ID And Task ID
56
+
57
+ Parameters:
58
+
59
+ - Task identifier (required)
60
+ - Project identifier (required)
61
+
62
+ ### 3. Update a Task
63
+
64
+ Parameters:
65
+
66
+ - Task identifier (required)
67
+ - Project identifier (required)
68
+ - Task Title
69
+ - Task Content
70
+ - Description of Checklist
71
+ - All day
72
+ - Start date
73
+ - Due date
74
+
75
+ >> use Additional Fields or JSON Parameters
76
+
77
+ ### 4. Complete a Task
78
+
79
+ Parameters:
80
+
81
+ - Task identifier (required)
82
+ - Project identifier (required)
83
+
84
+ ### 5. Delete a Task
85
+
86
+ Parameters:
87
+
88
+ - Task identifier (required)
89
+ - Project identifier (required)
90
+
91
+ ## Project Operations
92
+
93
+ ### 1. Create a Project
94
+
95
+ Parameters:
96
+
97
+ - Name (required)
98
+ - Color
99
+ - View Mode (List, Kanban, Timeline)
100
+ - Kind (Task, Note)
101
+
102
+ >> use Additional Fields or JSON Parameters
103
+
104
+ ### 2. Get User Project
105
+
106
+ Empty Parameters
107
+
108
+ ### 3. Get Project by ID
109
+
110
+ Parameters:
111
+
112
+ - Project identifier (required)
113
+
114
+ ### 4. Get Project with Data
115
+
116
+ Parameters:
117
+
118
+ - Project identifier (required)
119
+
120
+ ### 5. Update a Project
121
+
122
+ Parameters:
123
+
124
+ - Project identifier (required)
125
+ - Name
126
+ - Color
127
+ - View Mode (List, Kanban, Timeline)
128
+ - Kind (Task, Note)
129
+
130
+ >> use Additional Fields or JSON Parameters
131
+
132
+ ### 6. Delete a Project
133
+
134
+ Parameters:
135
+
136
+ - Project identifier (required)
137
+
138
+ ## Credentials
139
+
140
+ 1. Add credential in your n8n instance and select **TickTick OAuth2 API**
141
+ 2. Visit: [TickTick Developer](https://developer.ticktick.com/)
142
+ 3. Manage Apps > New App
143
+ 4. Copy **Client ID** and **Client Secret** > Paste in n8n credential
144
+ 5. Allow connection
145
+ 6. Account connected
146
+
147
+ ## Compatibility
148
+
149
+ Tested successfully with:
150
+
151
+ - n8n Version: 1.32.2
152
+ - Node Version: 18.19.1
153
+ - npm Version: 10.5.0
154
+ - No extra packages required
155
+
156
+ ## Known Issues
157
+
158
+ ### Start date / Due date Parameter
159
+
160
+ Both parameters will be implemented correctly in the next release.
161
+ Until then, please refer to the TickTick API documentation for the correct input:
162
+
163
+ startDate Parameter:
164
+ Subtask start date time in "yyyy-MM-dd'T'HH:mm:ssZ"
165
+ Example : "2019-11-13T03:00:00+0000"
166
+
167
+ dueDate Parameter:
168
+ Task due date time in "yyyy-MM-dd'T'HH:mm:ssZ"
169
+ Example : "2019-11-13T03:00:00+0000"
170
+
171
+
172
+
173
+ ### TickTick API Response for Certain Requests
174
+
175
+ As of the current version of this project, it's important for users to be aware that the TickTick API has specific behaviors regarding the responses for certain operations. Notably:
176
+
177
+ - **No Content Responses**: For some operations, such as deleting a project or completing a task, the TickTick API returns an HTTP status code indicating success (e.g., `200 OK`) but does not include any response body. This means that while these operations can be successfully executed, the API does not provide additional data or confirmation in the response body.
178
+
179
+ - **Handling of API Responses**: This custom node has been designed to interpret HTTP status codes as indicators of the success or failure of an operation. Since no further details are provided by the API for certain requests, the node generates its own success messages for user feedback. Users should rely on these status codes and custom messages for confirmation of operation outcomes.
180
+
181
+ - **API Documentation Discrepancies**: Users may also encounter instances where the behavior of the TickTick API does not fully align with its documentation, particularly regarding the response data for certain requests. We recommend users to proceed with caution and validate the functionality through testing, especially for critical workflows.
182
+
183
+ This project's implementation takes these API characteristics into account, aiming to provide clear and useful feedback to users whenever possible. However, users are encouraged to conduct their own testing and verification to ensure the node meets their specific needs.
184
+
185
+ Future updates to the TickTick API may address these issues, and subsequent versions of this project will aim to incorporate any changes to enhance functionality and user experience.
186
+
187
+ ## Resources
188
+
189
+ - [n8n Website](https://n8n.io/)
190
+ - [n8n community nodes documentation](https://docs.n8n.io/integrations/community-nodes/)
191
+ - [TickTick Website](https://www.ticktick.com/)
192
+ - [TickTick Open API documentation](https://developer.ticktick.com/docs#/openapi)
193
+
194
+ ## Version history
195
+
196
+ - `1.0.0` Initial release
@@ -0,0 +1,8 @@
1
+ import { ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class TickTickOAuth2Api implements ICredentialType {
3
+ name: string;
4
+ extends: string[];
5
+ displayName: string;
6
+ documentationUrl: string;
7
+ properties: INodeProperties[];
8
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TickTickOAuth2Api = void 0;
4
+ class TickTickOAuth2Api {
5
+ constructor() {
6
+ this.name = 'tickTickOAuth2Api';
7
+ this.extends = ['oAuth2Api'];
8
+ this.displayName = 'TickTick OAuth2 API';
9
+ this.documentationUrl = 'https://developer.ticktick.com/api#/openapi';
10
+ this.properties = [
11
+ {
12
+ displayName: 'Grant Type',
13
+ name: 'grantType',
14
+ type: 'hidden',
15
+ default: 'pkce',
16
+ },
17
+ {
18
+ displayName: 'Authorization URL',
19
+ name: 'authUrl',
20
+ type: 'hidden',
21
+ default: 'https://ticktick.com/oauth/authorize',
22
+ required: true,
23
+ },
24
+ {
25
+ displayName: 'Access Token URL',
26
+ name: 'accessTokenUrl',
27
+ type: 'hidden',
28
+ default: 'https://ticktick.com/oauth/token',
29
+ required: true,
30
+ },
31
+ {
32
+ displayName: 'Client ID',
33
+ name: 'clientId',
34
+ type: 'string',
35
+ typeOptions: {
36
+ password: true,
37
+ },
38
+ default: '',
39
+ required: true,
40
+ },
41
+ {
42
+ displayName: 'Scope',
43
+ name: 'scope',
44
+ type: 'hidden',
45
+ default: ``,
46
+ },
47
+ {
48
+ displayName: 'Auth URI Query Parameters',
49
+ name: 'authQueryParameters',
50
+ type: 'hidden',
51
+ default: '',
52
+ },
53
+ {
54
+ displayName: 'Authentication',
55
+ name: 'authentication',
56
+ type: 'hidden',
57
+ default: 'header',
58
+ },
59
+ ];
60
+ }
61
+ }
62
+ exports.TickTickOAuth2Api = TickTickOAuth2Api;
63
+ //# sourceMappingURL=TickTickOAuth2Api.credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TickTickOAuth2Api.credentials.js","sourceRoot":"","sources":["../../credentials/TickTickOAuth2Api.credentials.ts"],"names":[],"mappings":";;;AAEA,MAAa,iBAAiB;IAA9B;QACC,SAAI,GAAG,mBAAmB,CAAC;QAC3B,YAAO,GAAG,CAAC,WAAW,CAAC,CAAC;QACxB,gBAAW,GAAG,qBAAqB,CAAC;QACpC,qBAAgB,GAAG,6CAA6C,CAAC;QAEjE,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,YAAY;gBACzB,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,MAAM;aACf;YACD;gBACC,WAAW,EAAE,mBAAmB;gBAChC,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,sCAAsC;gBAC/C,QAAQ,EAAE,IAAI;aACd;YACD;gBACC,WAAW,EAAE,kBAAkB;gBAC/B,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,kCAAkC;gBAC3C,QAAQ,EAAE,IAAI;aACd;YACD;gBACC,WAAW,EAAE,WAAW;gBACxB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE;oBACZ,QAAQ,EAAE,IAAI;iBACd;gBACD,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;aACd;YACD;gBACC,WAAW,EAAE,OAAO;gBACpB,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;aACX;YACD;gBACC,WAAW,EAAE,2BAA2B;gBACxC,IAAI,EAAE,qBAAqB;gBAC3B,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;aACX;YACD;gBACC,WAAW,EAAE,gBAAgB;gBAC7B,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,QAAQ;aACjB;SACD,CAAC;IACH,CAAC;CAAA;AAxDD,8CAwDC"}
@@ -0,0 +1,14 @@
1
+ import type { IExecuteFunctions, IHookFunctions, ILoadOptionsFunctions, IDataObject, IHttpRequestMethods } from 'n8n-workflow';
2
+ export declare function getProjects(this: ILoadOptionsFunctions): Promise<{
3
+ name: string;
4
+ value: string;
5
+ }[]>;
6
+ export declare function getTasks(this: ILoadOptionsFunctions, projectId: string): Promise<{
7
+ name: string;
8
+ value: string;
9
+ }[]>;
10
+ export declare function tickTickApiRequest(this: IExecuteFunctions | IHookFunctions | ILoadOptionsFunctions, method: IHttpRequestMethods, endpoint: string, body?: IDataObject, qs?: IDataObject): Promise<any>;
11
+ export declare const TimeZones: {
12
+ name: string;
13
+ value: string;
14
+ }[];
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimeZones = exports.tickTickApiRequest = exports.getTasks = exports.getProjects = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ async function getProjects() {
6
+ const endpoint = '/open/v1/project';
7
+ try {
8
+ const responseData = await tickTickApiRequest.call(this, 'GET', endpoint);
9
+ return responseData.map((project) => ({
10
+ name: project.name,
11
+ value: project.id,
12
+ }));
13
+ }
14
+ catch (error) {
15
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
16
+ }
17
+ }
18
+ exports.getProjects = getProjects;
19
+ async function getTasks(projectId) {
20
+ if (!projectId) {
21
+ return [];
22
+ }
23
+ const endpoint = `/open/v1/project/${projectId}/data`;
24
+ try {
25
+ const responseData = (await tickTickApiRequest.call(this, 'GET', endpoint));
26
+ const tasks = responseData.tasks;
27
+ return tasks.map((task) => ({
28
+ name: task.title,
29
+ value: task.id.toString(),
30
+ }));
31
+ }
32
+ catch (error) {
33
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
34
+ }
35
+ }
36
+ exports.getTasks = getTasks;
37
+ async function tickTickApiRequest(method, endpoint, body = {}, qs = {}) {
38
+ var _a;
39
+ const baseUrl = 'https://ticktick.com';
40
+ const options = {
41
+ method,
42
+ body,
43
+ qs,
44
+ url: `${baseUrl}${endpoint}`,
45
+ json: true,
46
+ };
47
+ try {
48
+ const responseData = await ((_a = this.helpers.requestOAuth2) === null || _a === void 0 ? void 0 : _a.call(this, 'tickTickOAuth2Api', options));
49
+ return responseData;
50
+ }
51
+ catch (error) {
52
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
53
+ }
54
+ }
55
+ exports.tickTickApiRequest = tickTickApiRequest;
56
+ exports.TimeZones = [
57
+ { name: 'UTC', value: 'UTC' },
58
+ { name: 'Europe/London', value: 'Europe/London' },
59
+ { name: 'Europe/Berlin', value: 'Europe/Berlin' },
60
+ { name: 'Europe/Moscow', value: 'Europe/Moscow' },
61
+ { name: 'Asia/Kolkata', value: 'Asia/Kolkata' },
62
+ { name: 'Asia/Shanghai', value: 'Asia/Shanghai' },
63
+ { name: 'Asia/Tokyo', value: 'Asia/Tokyo' },
64
+ { name: 'America/New_York', value: 'America/New_York' },
65
+ { name: 'America/Chicago', value: 'America/Chicago' },
66
+ { name: 'America/Denver', value: 'America/Denver' },
67
+ { name: 'America/Los_Angeles', value: 'America/Los_Angeles' },
68
+ { name: 'America/Sao_Paulo', value: 'America/Sao_Paulo' },
69
+ { name: 'Australia/Sydney', value: 'Australia/Sydney' },
70
+ { name: 'Pacific/Auckland', value: 'Pacific/Auckland' },
71
+ ];
72
+ //# sourceMappingURL=GenericFunctions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GenericFunctions.js","sourceRoot":"","sources":["../../../nodes/TickTick/GenericFunctions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, ILoadOptionsFunctions } from 'n8n-workflow';
2
+ export declare class TickTick implements INodeType {
3
+ methods: {
4
+ loadOptions: {
5
+ getProjects(this: ILoadOptionsFunctions): Promise<{
6
+ name: string;
7
+ value: string;
8
+ }[]>;
9
+ getTasks(this: ILoadOptionsFunctions): Promise<{
10
+ name: string;
11
+ value: string;
12
+ }[]>;
13
+ };
14
+ };
15
+ description: INodeTypeDescription;
16
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
17
+ }
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TickTick = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const GenericFunctions_1 = require("./GenericFunctions");
6
+ const descriptions_1 = require("./descriptions");
7
+ class TickTick {
8
+ constructor() {
9
+ this.methods = {
10
+ loadOptions: {
11
+ async getProjects() {
12
+ return await GenericFunctions_1.getProjects.call(this);
13
+ },
14
+ async getTasks() {
15
+ const projectId = this.getCurrentNodeParameter('projectId');
16
+ return await GenericFunctions_1.getTasks.call(this, projectId);
17
+ },
18
+ },
19
+ };
20
+ this.description = {
21
+ displayName: 'TickTick',
22
+ name: 'tickTick',
23
+ icon: 'file:ticktick.svg',
24
+ group: ['transform'],
25
+ subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
26
+ version: 1,
27
+ description: 'TickTick is a powerful task management application',
28
+ defaults: {
29
+ name: 'TickTick',
30
+ },
31
+ inputs: ['main'],
32
+ outputs: ['main'],
33
+ credentials: [
34
+ {
35
+ name: 'tickTickOAuth2Api',
36
+ required: true,
37
+ },
38
+ ],
39
+ properties: [
40
+ {
41
+ displayName: 'Resource',
42
+ name: 'resource',
43
+ type: 'options',
44
+ noDataExpression: true,
45
+ options: [
46
+ {
47
+ name: 'Task',
48
+ value: 'task',
49
+ },
50
+ {
51
+ name: 'Project',
52
+ value: 'project',
53
+ },
54
+ ],
55
+ default: 'task',
56
+ },
57
+ ...descriptions_1.taskOperations,
58
+ ...descriptions_1.taskFields,
59
+ ...descriptions_1.projectOperations,
60
+ ...descriptions_1.projectFields,
61
+ ],
62
+ };
63
+ }
64
+ async execute() {
65
+ const items = this.getInputData();
66
+ let responseData;
67
+ for (let i = 0; i < items.length; i++) {
68
+ const resource = this.getNodeParameter('resource', i);
69
+ const operation = this.getNodeParameter('operation', i);
70
+ if (resource === 'project') {
71
+ switch (operation) {
72
+ case 'create': {
73
+ const useJsonParameters = this.getNodeParameter('jsonParameters', i);
74
+ let body = {};
75
+ if (useJsonParameters) {
76
+ const jsonInput = this.getNodeParameter('additionalFieldsJson', i, '');
77
+ try {
78
+ if (jsonInput) {
79
+ body = JSON.parse(jsonInput);
80
+ }
81
+ else {
82
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'JSON input is empty.');
83
+ }
84
+ }
85
+ catch (error) {
86
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid JSON input: ${error.message}`);
87
+ }
88
+ }
89
+ else {
90
+ const additionalFields = this.getNodeParameter('additionalFields', i);
91
+ body = {
92
+ name: this.getNodeParameter('name', i),
93
+ viewMode: additionalFields.viewMode || 'list',
94
+ kind: additionalFields.kind || 'task',
95
+ color: additionalFields.color || undefined,
96
+ };
97
+ Object.keys(body).forEach((key) => body[key] === undefined && delete body[key]);
98
+ }
99
+ const endpoint = '/open/v1/project';
100
+ responseData = await GenericFunctions_1.tickTickApiRequest.call(this, 'POST', endpoint, body);
101
+ break;
102
+ }
103
+ case 'get': {
104
+ const projectId = this.getNodeParameter('projectId', i);
105
+ const projectData = this.getNodeParameter('projectData', i, false);
106
+ let endpoint = '/open/v1/project';
107
+ if (projectId) {
108
+ endpoint += `/${projectId}`;
109
+ if (projectData) {
110
+ endpoint += '/data';
111
+ }
112
+ }
113
+ responseData = await GenericFunctions_1.tickTickApiRequest.call(this, 'GET', endpoint);
114
+ break;
115
+ }
116
+ case 'update': {
117
+ let projectId = this.getNodeParameter('projectId', i, '');
118
+ const useJsonParameters = this.getNodeParameter('jsonParameters', i);
119
+ let body = {};
120
+ if (useJsonParameters) {
121
+ const jsonInput = this.getNodeParameter('additionalFieldsJson', i, '');
122
+ try {
123
+ if (jsonInput) {
124
+ body = JSON.parse(jsonInput);
125
+ projectId = body.projectId ? body.projectId : projectId;
126
+ if (!projectId) {
127
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Project ID must be provided within the JSON input');
128
+ }
129
+ delete body.projectId;
130
+ }
131
+ else {
132
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'JSON input is empty.');
133
+ }
134
+ }
135
+ catch (error) {
136
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid JSON input: ${error.message}`);
137
+ }
138
+ }
139
+ else {
140
+ const additionalFields = this.getNodeParameter('additionalFields', i);
141
+ body = {
142
+ name: additionalFields.name || undefined,
143
+ viewMode: additionalFields.viewMode || 'list',
144
+ kind: additionalFields.kind || 'task',
145
+ color: additionalFields.color || undefined,
146
+ };
147
+ Object.keys(body).forEach((key) => body[key] === undefined && delete body[key]);
148
+ }
149
+ if (!projectId) {
150
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Project ID is required');
151
+ }
152
+ const endpoint = `/open/v1/project/${projectId}`;
153
+ responseData = await GenericFunctions_1.tickTickApiRequest.call(this, 'POST', endpoint, body);
154
+ break;
155
+ }
156
+ case 'delete': {
157
+ const projectId = this.getNodeParameter('projectId', i);
158
+ const endpoint = `/open/v1/project/${projectId}`;
159
+ responseData = await GenericFunctions_1.tickTickApiRequest.call(this, 'DELETE', endpoint);
160
+ break;
161
+ }
162
+ default:
163
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The operation "${operation}" is not known!`);
164
+ }
165
+ }
166
+ else if (resource === 'task') {
167
+ switch (operation) {
168
+ case 'create': {
169
+ const useJsonParameters = this.getNodeParameter('jsonParameters', i);
170
+ let body;
171
+ if (useJsonParameters) {
172
+ const jsonInput = this.getNodeParameter('additionalFieldsJson', i, '');
173
+ try {
174
+ body = JSON.parse(jsonInput);
175
+ }
176
+ catch (error) {
177
+ const errorMessage = error instanceof Error
178
+ ? `Invalid JSON: ${error.message}`
179
+ : 'An unexpected error occurred.';
180
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage);
181
+ }
182
+ }
183
+ else {
184
+ const additionalFields = this.getNodeParameter('additionalFields', i);
185
+ body = {
186
+ title: this.getNodeParameter('title', i),
187
+ projectId: this.getNodeParameter('projectId', i),
188
+ content: additionalFields.content || undefined,
189
+ desc: additionalFields.desc || undefined,
190
+ isAllDay: additionalFields.isAllDay || false,
191
+ startDate: additionalFields.startDate || undefined,
192
+ dueDate: additionalFields.dueDate || undefined,
193
+ timeZone: additionalFields.timeZone || undefined,
194
+ priority: additionalFields.priority || 0,
195
+ };
196
+ }
197
+ Object.keys(body).forEach((key) => body[key] === undefined && delete body[key]);
198
+ const endpoint = '/open/v1/task';
199
+ responseData = await GenericFunctions_1.tickTickApiRequest.call(this, 'POST', endpoint, body);
200
+ break;
201
+ }
202
+ case 'get': {
203
+ const projectId = this.getNodeParameter('projectId', i);
204
+ const taskId = this.getNodeParameter('taskId', i);
205
+ const endpoint = `/open/v1/project/${projectId}/task/${taskId}`;
206
+ responseData = await GenericFunctions_1.tickTickApiRequest.call(this, 'GET', endpoint);
207
+ break;
208
+ }
209
+ case 'update': {
210
+ const useJsonParameters = this.getNodeParameter('jsonParameters', i);
211
+ let body;
212
+ if (useJsonParameters) {
213
+ const jsonInput = this.getNodeParameter('additionalFieldsJson', i, '');
214
+ try {
215
+ body = JSON.parse(jsonInput);
216
+ }
217
+ catch (error) {
218
+ const errorMessage = error instanceof Error
219
+ ? `Invalid JSON: ${error.message}`
220
+ : 'An unexpected error occurred during JSON parsing.';
221
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage);
222
+ }
223
+ }
224
+ else {
225
+ const additionalFields = this.getNodeParameter('additionalFields', i);
226
+ body = {
227
+ projectId: this.getNodeParameter('projectId', i),
228
+ title: this.getNodeParameter('title', i),
229
+ content: additionalFields.content || undefined,
230
+ desc: additionalFields.desc || undefined,
231
+ isAllDay: additionalFields.isAllDay || false,
232
+ startDate: additionalFields.startDate || undefined,
233
+ dueDate: additionalFields.dueDate || undefined,
234
+ timeZone: additionalFields.timeZone || undefined,
235
+ priority: additionalFields.priority || 0,
236
+ };
237
+ }
238
+ Object.keys(body).forEach((key) => body[key] === undefined && delete body[key]);
239
+ const taskId = this.getNodeParameter('taskId', i);
240
+ const endpoint = `/open/v1/task/${taskId}`;
241
+ responseData = await GenericFunctions_1.tickTickApiRequest.call(this, 'POST', endpoint, body);
242
+ break;
243
+ }
244
+ case 'complete': {
245
+ const projectId = this.getNodeParameter('projectId', i);
246
+ const taskId = this.getNodeParameter('taskId', i);
247
+ const endpoint = `/open/v1/project/${projectId}/task/${taskId}/complete`;
248
+ responseData = await GenericFunctions_1.tickTickApiRequest.call(this, 'POST', endpoint, {});
249
+ break;
250
+ }
251
+ case 'delete': {
252
+ const projectId = this.getNodeParameter('projectId', i);
253
+ const taskId = this.getNodeParameter('taskId', i);
254
+ const endpoint = `/open/v1/project/${projectId}/task/${taskId}`;
255
+ responseData = await GenericFunctions_1.tickTickApiRequest.call(this, 'DELETE', endpoint);
256
+ break;
257
+ }
258
+ }
259
+ }
260
+ else {
261
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
262
+ }
263
+ }
264
+ return [this.helpers.returnJsonArray(responseData)];
265
+ }
266
+ }
267
+ exports.TickTick = TickTick;
268
+ //# sourceMappingURL=TickTick.node.js.map