n8n-nodes-caldav-pro 1.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/LICENSE +21 -0
- package/README.md +313 -0
- package/dist/credentials/CalDavApi.credentials.d.ts +9 -0
- package/dist/credentials/CalDavApi.credentials.js +70 -0
- package/dist/credentials/CalDavApi.credentials.js.map +1 -0
- package/dist/nodes/CalDav/CalDav.node.d.ts +5 -0
- package/dist/nodes/CalDav/CalDav.node.js +96 -0
- package/dist/nodes/CalDav/CalDav.node.js.map +1 -0
- package/dist/nodes/CalDav/CalDavTool.node.d.ts +6 -0
- package/dist/nodes/CalDav/CalDavTool.node.js +155 -0
- package/dist/nodes/CalDav/CalDavTool.node.js.map +1 -0
- package/dist/nodes/CalDav/descriptions/SharedDescriptions.d.ts +11 -0
- package/dist/nodes/CalDav/descriptions/SharedDescriptions.js +232 -0
- package/dist/nodes/CalDav/descriptions/SharedDescriptions.js.map +1 -0
- package/dist/nodes/CalDav/helpers/CalDavClient.d.ts +40 -0
- package/dist/nodes/CalDav/helpers/CalDavClient.js +246 -0
- package/dist/nodes/CalDav/helpers/CalDavClient.js.map +1 -0
- package/dist/nodes/CalDav/helpers/ICal.d.ts +48 -0
- package/dist/nodes/CalDav/helpers/ICal.js +216 -0
- package/dist/nodes/CalDav/helpers/ICal.js.map +1 -0
- package/dist/nodes/CalDav/helpers/Operations.d.ts +14 -0
- package/dist/nodes/CalDav/helpers/Operations.js +425 -0
- package/dist/nodes/CalDav/helpers/Operations.js.map +1 -0
- package/dist/nodes/CalDav/helpers/Recurrence.d.ts +29 -0
- package/dist/nodes/CalDav/helpers/Recurrence.js +204 -0
- package/dist/nodes/CalDav/helpers/Recurrence.js.map +1 -0
- package/dist/nodes/CalDav/helpers/Timezone.d.ts +11 -0
- package/dist/nodes/CalDav/helpers/Timezone.js +142 -0
- package/dist/nodes/CalDav/helpers/Timezone.js.map +1 -0
- package/dist/nodes/CalDav/helpers/Utils.d.ts +17 -0
- package/dist/nodes/CalDav/helpers/Utils.js +129 -0
- package/dist/nodes/CalDav/helpers/Utils.js.map +1 -0
- package/dist/nodes/CalDav/icons/caldav.svg +10 -0
- package/dist/package.json +76 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/index.js +3 -0
- package/package.json +76 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 n8n Community
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# n8n-nodes-caldav-pro
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/) [](LICENSE)
|
|
4
|
+
|
|
5
|
+
Two n8n community nodes for working with any CalDAV calendar server:
|
|
6
|
+
|
|
7
|
+
- **CalDAV** – standard node for workflows (triggers, schedulers, HTTP, etc.).
|
|
8
|
+
- **CalDAV Tool** – AI-Agent tool variant with `$fromAI()` support, tolerant
|
|
9
|
+
parameter casing, and error-as-JSON default behaviour.
|
|
10
|
+
|
|
11
|
+
Tested against Infomaniak kMeet/Calendar, Nextcloud, Apple iCloud, Radicale,
|
|
12
|
+
Baikal, SOGo and generic RFC 4791 servers.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
| Operation | Standard | AI Tool | Notes |
|
|
19
|
+
|------------------|:--------:|:-------:|-------|
|
|
20
|
+
| Get Events | ✅ | ✅ | Single date or date range. Recurring events are expanded. Empty result = empty array (never an error). |
|
|
21
|
+
| Create Event | ✅ | ✅ | VTIMEZONE, VALARM, RRULE. |
|
|
22
|
+
| Update Event | ✅ | ✅ | Partial update by UID (If-Match / ETag). |
|
|
23
|
+
| Delete Event | ✅ | ✅ | By UID. 404 = `deleted:false` (no throw). |
|
|
24
|
+
| Get Free/Busy | ✅ | ✅ | Free-busy REPORT with automatic fallback to calendar-query. |
|
|
25
|
+
|
|
26
|
+
Additional guarantees:
|
|
27
|
+
|
|
28
|
+
- **Timezones:** pulled from `this.getTimezone()`. VTIMEZONE is generated
|
|
29
|
+
dynamically with proper DAYLIGHT + STANDARD components and correct DST
|
|
30
|
+
rules for Europe, North America, Australia, New Zealand, Chile.
|
|
31
|
+
`DTSTART;TZID=Europe/Berlin:20260414T120000` – never UTC literals for
|
|
32
|
+
timed events.
|
|
33
|
+
- **RFC 5545 compliance:** CRLF line endings, line folding at 75 octets,
|
|
34
|
+
escape sequences in TEXT properties, UTC DTSTAMP/CREATED/LAST-MODIFIED.
|
|
35
|
+
- **Security:** UID sanitization (`/[^\w\-.@]/g → '_'`), path-traversal
|
|
36
|
+
guard, XML-safe response parsing, no credential or body logging.
|
|
37
|
+
- **AI-friendly:** every enum is a free-form string with allowed values in
|
|
38
|
+
the description, and parameters accept camelCase, snake_case, UPPER_CASE
|
|
39
|
+
and kebab-case interchangeably.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
### From the n8n UI (self-hosted)
|
|
46
|
+
|
|
47
|
+
`Settings → Community Nodes → Install` and enter:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
n8n-nodes-caldav-pro
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### From npm (CLI install)
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm install n8n-nodes-caldav-pro
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
In Docker:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
docker exec -u 0 -it n8n \
|
|
63
|
+
npm install -g n8n-nodes-caldav-pro
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The two nodes show up in the palette as **CalDAV** and **CalDAV Tool**.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Credentials setup
|
|
71
|
+
|
|
72
|
+
The same credential type (`CalDAV API`) is used by both nodes.
|
|
73
|
+
|
|
74
|
+
| Field | Value |
|
|
75
|
+
|--------------|-------|
|
|
76
|
+
| Server URL | Full CalDAV collection URL (must end with `/`) |
|
|
77
|
+
| Username | Your account username |
|
|
78
|
+
| Password | Account or app-specific password |
|
|
79
|
+
|
|
80
|
+
The connection test runs a `PROPFIND` against the collection URL.
|
|
81
|
+
|
|
82
|
+
### Infomaniak example
|
|
83
|
+
|
|
84
|
+
1. Log into [Infomaniak mail.infomaniak.com](https://mail.infomaniak.com) and
|
|
85
|
+
open **Calendar → ⚙ Settings → Synchronize → CalDAV**.
|
|
86
|
+
2. Copy the CalDAV URL. It looks like:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
https://caldav.infomaniak.com/calendar/<user-id>/<calendar-id>/
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
3. Under **Security settings → Application passwords**, create an
|
|
93
|
+
app password for n8n.
|
|
94
|
+
4. In n8n create a new `CalDAV API` credential with:
|
|
95
|
+
- **Server URL:** paste the CalDAV URL above (keep the trailing `/`).
|
|
96
|
+
- **Username:** your Infomaniak login (email).
|
|
97
|
+
- **Password:** the app password.
|
|
98
|
+
|
|
99
|
+
### Nextcloud
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
https://cloud.example.com/remote.php/dav/calendars/<user>/<calendar-id>/
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Use an app-token rather than your main password (Settings → Security →
|
|
106
|
+
Devices & sessions).
|
|
107
|
+
|
|
108
|
+
### Apple iCloud
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
https://caldav.icloud.com/<principal-id>/calendars/<calendar-id>/
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Requires an **app-specific password**.
|
|
115
|
+
|
|
116
|
+
### Radicale / Baikal / SOGo
|
|
117
|
+
|
|
118
|
+
Use the calendar collection URL that the server admin gave you.
|
|
119
|
+
Radicale default layout: `https://host/<user>/<calendar>/`.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## AI Agent setup (CalDAV Tool)
|
|
124
|
+
|
|
125
|
+
Drop the **CalDAV Tool** node into an **AI Agent** subtree. Nothing else is
|
|
126
|
+
required – every field can be supplied by the model via `$fromAI()`.
|
|
127
|
+
|
|
128
|
+
### Suggested system prompt
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
You are a scheduling assistant. You can use the "caldav" tool to read,
|
|
132
|
+
create, update and delete events on the user's calendar, and to check
|
|
133
|
+
free/busy for specific time windows.
|
|
134
|
+
|
|
135
|
+
Rules:
|
|
136
|
+
- All datetimes MUST be ISO-8601 with a timezone offset, e.g.
|
|
137
|
+
"2026-04-14T12:00:00+02:00". Never emit "Z" for local events.
|
|
138
|
+
- Before creating an event, call getFreeBusy for the requested window.
|
|
139
|
+
If the window is busy, propose the next free slot instead.
|
|
140
|
+
- For recurring events: set Recurring_Event to true and fill in
|
|
141
|
+
Recurrence_Frequency (DAILY/WEEKLY/MONTHLY/YEARLY), Recurrence_Interval,
|
|
142
|
+
Recurrence_End_Type (count/until/never), Recurrence_Count or
|
|
143
|
+
Recurrence_Until, and Recurrence_By_Day when relevant
|
|
144
|
+
(e.g. "MO,WE,FR").
|
|
145
|
+
- If the tool returns {success:false, error:...}, tell the user what went
|
|
146
|
+
wrong and ask for a correction; do not retry identical input.
|
|
147
|
+
- Today's date: {{$today}}. User timezone: {{$now.zoneName}}.
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### End-to-end example: "Schedule a meeting with Jane next Tuesday 3pm"
|
|
151
|
+
|
|
152
|
+
1. Agent calls `caldav` with:
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"operation": "getFreeBusy",
|
|
156
|
+
"Start_Date": "2026-04-21T15:00:00+02:00",
|
|
157
|
+
"End_Date": "2026-04-21T16:00:00+02:00"
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
Response: `{ success: true, isBusy: false, free: [...], busy: [] }`.
|
|
161
|
+
|
|
162
|
+
2. Agent calls `caldav` with:
|
|
163
|
+
```json
|
|
164
|
+
{
|
|
165
|
+
"operation": "createEvent",
|
|
166
|
+
"Event_Title": "Meeting with Jane",
|
|
167
|
+
"Start_Date_and_Time": "2026-04-21T15:00:00+02:00",
|
|
168
|
+
"End_Date_and_Time": "2026-04-21T16:00:00+02:00",
|
|
169
|
+
"Location": "Office",
|
|
170
|
+
"Reminder": 15
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
Response:
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"success": true,
|
|
177
|
+
"operation": "createEvent",
|
|
178
|
+
"uid": "c4b1c9de-...@n8n-caldav",
|
|
179
|
+
"etag": "\"f00\"",
|
|
180
|
+
"timezone": "Europe/Berlin",
|
|
181
|
+
"event": { ... }
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Operations
|
|
188
|
+
|
|
189
|
+
### Get Events
|
|
190
|
+
|
|
191
|
+
Inputs (all optional; at least one date must be resolvable):
|
|
192
|
+
|
|
193
|
+
| Field | Type | Description |
|
|
194
|
+
|--------------|--------|-------------|
|
|
195
|
+
| Date | string | Single day as `YYYY-MM-DD`. |
|
|
196
|
+
| Start Date | string | Range start (ISO-8601). |
|
|
197
|
+
| End Date | string | Range end (ISO-8601). |
|
|
198
|
+
|
|
199
|
+
Output (never throws on empty):
|
|
200
|
+
|
|
201
|
+
```json
|
|
202
|
+
{
|
|
203
|
+
"success": true,
|
|
204
|
+
"operation": "getEvents",
|
|
205
|
+
"rangeStart": "2026-04-14T00:00:00.000Z",
|
|
206
|
+
"rangeEnd": "2026-04-15T00:00:00.000Z",
|
|
207
|
+
"count": 2,
|
|
208
|
+
"events": [
|
|
209
|
+
{
|
|
210
|
+
"uid": "...",
|
|
211
|
+
"summary": "Standup",
|
|
212
|
+
"start": "2026-04-14T07:00:00.000Z",
|
|
213
|
+
"end": "2026-04-14T07:15:00.000Z",
|
|
214
|
+
"allDay": false,
|
|
215
|
+
"recurring": true,
|
|
216
|
+
"rrule": "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR"
|
|
217
|
+
}
|
|
218
|
+
]
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Create Event
|
|
223
|
+
|
|
224
|
+
| Field | Type | Notes |
|
|
225
|
+
|-----------------------|---------|-------|
|
|
226
|
+
| UID (optional) | string | Empty → UUID generated. |
|
|
227
|
+
| Event_Title | string | **required**. |
|
|
228
|
+
| Start_Date_and_Time | string | **required** – ISO-8601 with offset. |
|
|
229
|
+
| End_Date_and_Time | string | Default start + 1h. |
|
|
230
|
+
| Location | string | |
|
|
231
|
+
| Description | string | |
|
|
232
|
+
| All_Day_Event | boolean | If true, emits `DTSTART;VALUE=DATE:YYYYMMDD`. |
|
|
233
|
+
| Reminder | number | Minutes before start. 0 → no VALARM. |
|
|
234
|
+
| Recurring_Event | boolean | Enables RRULE. |
|
|
235
|
+
| Recurrence_Frequency | string | `DAILY` / `WEEKLY` / `MONTHLY` / `YEARLY`. |
|
|
236
|
+
| Recurrence_Interval | number | Default `1`. |
|
|
237
|
+
| Recurrence_End_Type | string | `count` / `until` / `never`. |
|
|
238
|
+
| Recurrence_Count | number | When `end_type=count`. |
|
|
239
|
+
| Recurrence_Until | string | When `end_type=until`. |
|
|
240
|
+
| Recurrence_By_Day | string | Comma-separated BYDAY tokens: `MO,TU,WE,TH,FR,SA,SU` (ordinals allowed: `2MO`, `-1FR`). |
|
|
241
|
+
|
|
242
|
+
### Update Event
|
|
243
|
+
|
|
244
|
+
All fields optional except **UID**. Omitted fields keep their existing
|
|
245
|
+
values. Uses `If-Match` with the current ETag.
|
|
246
|
+
|
|
247
|
+
### Delete Event
|
|
248
|
+
|
|
249
|
+
| Field | Type |
|
|
250
|
+
|-------|--------|
|
|
251
|
+
| UID | string (required) |
|
|
252
|
+
|
|
253
|
+
HTTP 404 → `deleted:false` (no error thrown).
|
|
254
|
+
|
|
255
|
+
### Get Free/Busy
|
|
256
|
+
|
|
257
|
+
| Field | Type |
|
|
258
|
+
|--------------|--------|
|
|
259
|
+
| Start_Date | string (required) |
|
|
260
|
+
| End_Date | string (required) |
|
|
261
|
+
|
|
262
|
+
Output:
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"success": true,
|
|
267
|
+
"operation": "getFreeBusy",
|
|
268
|
+
"method": "freebusy-query",
|
|
269
|
+
"rangeStart": "2026-04-14T08:00:00.000Z",
|
|
270
|
+
"rangeEnd": "2026-04-14T18:00:00.000Z",
|
|
271
|
+
"busy": [ { "start": "...", "end": "..." } ],
|
|
272
|
+
"free": [ { "start": "...", "end": "..." } ],
|
|
273
|
+
"isBusy": true
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Error handling
|
|
280
|
+
|
|
281
|
+
Both nodes return structured JSON on failure (and on success):
|
|
282
|
+
|
|
283
|
+
```json
|
|
284
|
+
{
|
|
285
|
+
"success": false,
|
|
286
|
+
"error": "CalDAV PUT failed: HTTP 412 Precondition Failed",
|
|
287
|
+
"operation": "updateEvent",
|
|
288
|
+
"timestamp": "2026-04-19T10:12:34.567Z"
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
- **CalDAV Tool** defaults to `returnError` (the Agent never aborts on a
|
|
293
|
+
tool error). Switch to `throwError` to propagate the error.
|
|
294
|
+
- **CalDAV** throws by default. Enable "Continue On Fail" in the node
|
|
295
|
+
settings to get the JSON error payload instead.
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Development
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
npm install
|
|
303
|
+
npm run build # tsc + gulp (icons)
|
|
304
|
+
npm run lint # eslint
|
|
305
|
+
npm test # jest (all suites)
|
|
306
|
+
npm run pack # builds + emits n8n-nodes-caldav-pro-1.0.0.tgz
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## License
|
|
312
|
+
|
|
313
|
+
MIT – see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
export declare class CalDavApi implements ICredentialType {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
documentationUrl: string;
|
|
6
|
+
properties: INodeProperties[];
|
|
7
|
+
authenticate: IAuthenticateGeneric;
|
|
8
|
+
test: ICredentialTestRequest;
|
|
9
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CalDavApi = void 0;
|
|
4
|
+
class CalDavApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'calDavApi';
|
|
7
|
+
this.displayName = 'CalDAV API';
|
|
8
|
+
this.documentationUrl = 'https://github.com/n8n-community/n8n-nodes-caldav-pro';
|
|
9
|
+
this.properties = [
|
|
10
|
+
{
|
|
11
|
+
displayName: 'Server URL',
|
|
12
|
+
name: 'serverUrl',
|
|
13
|
+
type: 'string',
|
|
14
|
+
default: '',
|
|
15
|
+
required: true,
|
|
16
|
+
placeholder: 'https://caldav.infomaniak.com/calendar/<user>/<calendar-id>/',
|
|
17
|
+
description: 'Full URL of the CalDAV calendar collection. Must end with a trailing slash. Examples:\n' +
|
|
18
|
+
'- Infomaniak: https://caldav.infomaniak.com/calendar/<user>/<calendar-id>/\n' +
|
|
19
|
+
'- Nextcloud: https://cloud.example.com/remote.php/dav/calendars/<user>/<calendar>/\n' +
|
|
20
|
+
'- iCloud: https://caldav.icloud.com/<principal-id>/calendars/<calendar>/\n' +
|
|
21
|
+
'- Radicale/Baikal/SOGo: use the calendar collection URL',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
displayName: 'Username',
|
|
25
|
+
name: 'username',
|
|
26
|
+
type: 'string',
|
|
27
|
+
default: '',
|
|
28
|
+
required: true,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
displayName: 'Password',
|
|
32
|
+
name: 'password',
|
|
33
|
+
type: 'string',
|
|
34
|
+
typeOptions: {
|
|
35
|
+
password: true,
|
|
36
|
+
},
|
|
37
|
+
default: '',
|
|
38
|
+
required: true,
|
|
39
|
+
description: 'Account password or app-specific password (recommended for Infomaniak / iCloud / Google).',
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
this.authenticate = {
|
|
43
|
+
type: 'generic',
|
|
44
|
+
properties: {
|
|
45
|
+
auth: {
|
|
46
|
+
username: '={{ $credentials.username }}',
|
|
47
|
+
password: '={{ $credentials.password }}',
|
|
48
|
+
},
|
|
49
|
+
headers: {
|
|
50
|
+
'User-Agent': 'n8n-nodes-caldav-pro/1.0.0',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
this.test = {
|
|
55
|
+
request: {
|
|
56
|
+
baseURL: '={{ $credentials.serverUrl }}',
|
|
57
|
+
url: '',
|
|
58
|
+
method: 'PROPFIND',
|
|
59
|
+
headers: {
|
|
60
|
+
Depth: '0',
|
|
61
|
+
'Content-Type': 'application/xml; charset=utf-8',
|
|
62
|
+
},
|
|
63
|
+
body: '<?xml version="1.0" encoding="utf-8" ?>' +
|
|
64
|
+
'<d:propfind xmlns:d="DAV:"><d:prop><d:resourcetype/><d:displayname/></d:prop></d:propfind>',
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.CalDavApi = CalDavApi;
|
|
70
|
+
//# sourceMappingURL=CalDavApi.credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CalDavApi.credentials.js","sourceRoot":"","sources":["../../credentials/CalDavApi.credentials.ts"],"names":[],"mappings":";;;AAOA,MAAa,SAAS;IAAtB;QACC,SAAI,GAAG,WAAW,CAAC;QACnB,gBAAW,GAAG,YAAY,CAAC;QAC3B,qBAAgB,GAAG,uDAAuD,CAAC;QAE3E,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,YAAY;gBACzB,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,8DAA8D;gBAC3E,WAAW,EACV,yFAAyF;oBACzF,8EAA8E;oBAC9E,sFAAsF;oBACtF,4EAA4E;oBAC5E,yDAAyD;aAC1D;YACD;gBACC,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;aACd;YACD;gBACC,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE;oBACZ,QAAQ,EAAE,IAAI;iBACd;gBACD,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EACV,2FAA2F;aAC5F;SACD,CAAC;QAEF,iBAAY,GAAyB;YACpC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACX,IAAI,EAAE;oBACL,QAAQ,EAAE,8BAA8B;oBACxC,QAAQ,EAAE,8BAA8B;iBACxC;gBACD,OAAO,EAAE;oBACR,YAAY,EAAE,4BAA4B;iBAC1C;aACD;SACD,CAAC;QAKF,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,OAAO,EAAE,+BAA+B;gBACxC,GAAG,EAAE,EAAE;gBACP,MAAM,EAAE,UAAyD;gBACjE,OAAO,EAAE;oBACR,KAAK,EAAE,GAAG;oBACV,cAAc,EAAE,gCAAgC;iBAChD;gBACD,IAAI,EACH,yCAAyC;oBACzC,4FAA4F;aAC7F;SACD,CAAC;IACH,CAAC;CAAA;AAvED,8BAuEC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CalDav = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const Operations_1 = require("./helpers/Operations");
|
|
6
|
+
const Utils_1 = require("./helpers/Utils");
|
|
7
|
+
const SharedDescriptions_1 = require("./descriptions/SharedDescriptions");
|
|
8
|
+
class CalDav {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.description = {
|
|
11
|
+
displayName: 'CalDAV',
|
|
12
|
+
name: 'caldav',
|
|
13
|
+
icon: 'file:icons/caldav.svg',
|
|
14
|
+
group: ['transform'],
|
|
15
|
+
version: 1,
|
|
16
|
+
subtitle: '={{$parameter["operation"]}}',
|
|
17
|
+
description: 'Read and write events on a CalDAV calendar (Infomaniak, Nextcloud, iCloud, Radicale, Baikal, SOGo).',
|
|
18
|
+
defaults: { name: 'CalDAV' },
|
|
19
|
+
inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
20
|
+
outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
21
|
+
credentials: [{ name: 'calDavApi', required: true }],
|
|
22
|
+
properties: (0, SharedDescriptions_1.buildCalDavProperties)({ asTool: false }),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
async execute() {
|
|
26
|
+
const items = this.getInputData();
|
|
27
|
+
const results = [];
|
|
28
|
+
const credentials = (await this.getCredentials('calDavApi'));
|
|
29
|
+
const tzid = this.getTimezone() || 'UTC';
|
|
30
|
+
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
|
31
|
+
try {
|
|
32
|
+
const operation = this.getNodeParameter('operation', itemIndex);
|
|
33
|
+
const params = collectParams(this, itemIndex);
|
|
34
|
+
const normalized = (0, Utils_1.normalizeParams)(params);
|
|
35
|
+
const output = await (0, Operations_1.runOperation)(this, credentials, operation, normalized, tzid);
|
|
36
|
+
results.push({ json: output, pairedItem: { item: itemIndex } });
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
const operation = (() => {
|
|
40
|
+
try {
|
|
41
|
+
return this.getNodeParameter('operation', itemIndex);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return 'unknown';
|
|
45
|
+
}
|
|
46
|
+
})();
|
|
47
|
+
if (this.continueOnFail()) {
|
|
48
|
+
results.push({
|
|
49
|
+
json: (0, Utils_1.buildErrorPayload)(error, operation),
|
|
50
|
+
pairedItem: { item: itemIndex },
|
|
51
|
+
});
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (error instanceof n8n_workflow_1.NodeOperationError)
|
|
55
|
+
throw error;
|
|
56
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return [results];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.CalDav = CalDav;
|
|
63
|
+
function collectParams(ctx, itemIndex) {
|
|
64
|
+
const fields = [
|
|
65
|
+
'date',
|
|
66
|
+
'startDate',
|
|
67
|
+
'endDate',
|
|
68
|
+
'uid',
|
|
69
|
+
'eventTitle',
|
|
70
|
+
'startDateAndTime',
|
|
71
|
+
'endDateAndTime',
|
|
72
|
+
'location',
|
|
73
|
+
'description',
|
|
74
|
+
'allDayEvent',
|
|
75
|
+
'reminder',
|
|
76
|
+
'recurringEvent',
|
|
77
|
+
'recurrenceFrequency',
|
|
78
|
+
'recurrenceInterval',
|
|
79
|
+
'recurrenceEndType',
|
|
80
|
+
'recurrenceCount',
|
|
81
|
+
'recurrenceUntil',
|
|
82
|
+
'recurrenceByDay',
|
|
83
|
+
];
|
|
84
|
+
const out = {};
|
|
85
|
+
for (const f of fields) {
|
|
86
|
+
try {
|
|
87
|
+
const v = ctx.getNodeParameter(f, itemIndex, undefined);
|
|
88
|
+
if (v !== undefined && v !== '')
|
|
89
|
+
out[f] = v;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=CalDav.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CalDav.node.js","sourceRoot":"","sources":["../../../nodes/CalDav/CalDav.node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, ISupplyDataFunctions, SupplyData } from 'n8n-workflow';
|
|
2
|
+
export declare class CalDavTool implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData>;
|
|
5
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
6
|
+
}
|