n8n-nodes-caldav-pro 1.0.3 → 2.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.
Files changed (47) hide show
  1. package/README.md +125 -252
  2. package/dist/credentials/CalDavApi.credentials.d.ts +1 -1
  3. package/dist/credentials/CalDavApi.credentials.js +23 -11
  4. package/dist/credentials/CalDavApi.credentials.js.map +1 -1
  5. package/dist/nodes/CalDav/CalDav.node.d.ts +8 -1
  6. package/dist/nodes/CalDav/CalDav.node.js +496 -53
  7. package/dist/nodes/CalDav/CalDav.node.js.map +1 -1
  8. package/dist/nodes/CalDav/CalendarDescription.d.ts +3 -0
  9. package/dist/nodes/CalDav/CalendarDescription.js +25 -0
  10. package/dist/nodes/CalDav/CalendarDescription.js.map +1 -0
  11. package/dist/nodes/CalDav/EventDescription.d.ts +3 -0
  12. package/dist/nodes/CalDav/EventDescription.js +297 -0
  13. package/dist/nodes/CalDav/EventDescription.js.map +1 -0
  14. package/dist/nodes/CalDav/GenericFunctions.d.ts +135 -0
  15. package/dist/nodes/CalDav/GenericFunctions.js +951 -0
  16. package/dist/nodes/CalDav/GenericFunctions.js.map +1 -0
  17. package/dist/nodes/CalDav/caldav.svg +10 -0
  18. package/dist/package.json +5 -19
  19. package/dist/tsconfig.tsbuildinfo +1 -1
  20. package/package.json +5 -19
  21. package/dist/nodes/CalDav/CalDavTool.node.d.ts +0 -6
  22. package/dist/nodes/CalDav/CalDavTool.node.js +0 -255
  23. package/dist/nodes/CalDav/CalDavTool.node.js.map +0 -1
  24. package/dist/nodes/CalDav/descriptions/SharedDescriptions.d.ts +0 -11
  25. package/dist/nodes/CalDav/descriptions/SharedDescriptions.js +0 -232
  26. package/dist/nodes/CalDav/descriptions/SharedDescriptions.js.map +0 -1
  27. package/dist/nodes/CalDav/helpers/AgentInput.d.ts +0 -2
  28. package/dist/nodes/CalDav/helpers/AgentInput.js +0 -159
  29. package/dist/nodes/CalDav/helpers/AgentInput.js.map +0 -1
  30. package/dist/nodes/CalDav/helpers/CalDavClient.d.ts +0 -40
  31. package/dist/nodes/CalDav/helpers/CalDavClient.js +0 -246
  32. package/dist/nodes/CalDav/helpers/CalDavClient.js.map +0 -1
  33. package/dist/nodes/CalDav/helpers/ICal.d.ts +0 -48
  34. package/dist/nodes/CalDav/helpers/ICal.js +0 -216
  35. package/dist/nodes/CalDav/helpers/ICal.js.map +0 -1
  36. package/dist/nodes/CalDav/helpers/Operations.d.ts +0 -14
  37. package/dist/nodes/CalDav/helpers/Operations.js +0 -425
  38. package/dist/nodes/CalDav/helpers/Operations.js.map +0 -1
  39. package/dist/nodes/CalDav/helpers/Recurrence.d.ts +0 -29
  40. package/dist/nodes/CalDav/helpers/Recurrence.js +0 -204
  41. package/dist/nodes/CalDav/helpers/Recurrence.js.map +0 -1
  42. package/dist/nodes/CalDav/helpers/Timezone.d.ts +0 -11
  43. package/dist/nodes/CalDav/helpers/Timezone.js +0 -142
  44. package/dist/nodes/CalDav/helpers/Timezone.js.map +0 -1
  45. package/dist/nodes/CalDav/helpers/Utils.d.ts +0 -17
  46. package/dist/nodes/CalDav/helpers/Utils.js +0 -129
  47. package/dist/nodes/CalDav/helpers/Utils.js.map +0 -1
package/README.md CHANGED
@@ -1,313 +1,186 @@
1
1
  # n8n-nodes-caldav-pro
2
2
 
3
- [![npm](https://img.shields.io/badge/n8n-community%20node-FF6D5A.svg)](https://www.npmjs.com/) [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
3
+ A community node for n8n that connects to **CalDAV calendar servers** — Infomaniak, Nextcloud, iCloud, Radicale, Baikal, SOGo, and any RFC 4791-compliant server.
4
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.
5
+ **Version 2.0.0** — single unified node with native AI Agent support (`usableAsTool: true`).
13
6
 
14
7
  ---
15
8
 
16
9
  ## Features
17
10
 
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.
11
+ - **Resource/Operation pattern** — Calendar: Get All | Event: Create, Get, Get All, Update, Delete
12
+ - **Native AI Agent support** — expose directly to Claude, GPT-4, or any LLM tool via n8n's AI Agent node without extra wiring
13
+ - **Calendar dropdown** — pick your calendar from a dynamic list (auto-discovered from your server)
14
+ - **Recurring events** — DAILY, WEEKLY (with day-of-week), MONTHLY, YEARLY; COUNT or UNTIL end types
15
+ - **Reminders** — VALARM blocks with configurable lead time
16
+ - **All-day events** — full DATE-only support
17
+ - **Zero external dependencies** — pure TypeScript, only `n8n-workflow` as peer dependency
40
18
 
41
19
  ---
42
20
 
43
21
  ## Installation
44
22
 
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)
23
+ ### Community Nodes panel (recommended)
54
24
 
55
- ```bash
56
- npm install n8n-nodes-caldav-pro
57
- ```
25
+ 1. Open n8n → **Settings** → **Community Nodes**
26
+ 2. Click **Install a community node**
27
+ 3. Enter: `n8n-nodes-caldav-pro`
28
+ 4. Click **Install**
58
29
 
59
- In Docker:
30
+ ### Manual (tgz)
60
31
 
61
32
  ```bash
62
- docker exec -u 0 -it n8n \
63
- npm install -g n8n-nodes-caldav-pro
33
+ # In your n8n data directory
34
+ npm install /path/to/n8n-nodes-caldav-pro-2.0.0.tgz
64
35
  ```
65
36
 
66
- The two nodes show up in the palette as **CalDAV** and **CalDAV Tool**.
37
+ Then restart n8n.
67
38
 
68
39
  ---
69
40
 
70
- ## Credentials setup
41
+ ## Infomaniak Quickstart
71
42
 
72
- The same credential type (`CalDAV API`) is used by both nodes.
43
+ ### 1 — Create an App Password (required for 2FA accounts)
73
44
 
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 |
45
+ 1. Go to [manager.infomaniak.com](https://manager.infomaniak.com) → **Security** → **App passwords**
46
+ 2. Create a new password — label it "n8n CalDAV"
47
+ 3. Copy the generated password (you won't see it again)
79
48
 
80
- The connection test runs a `PROPFIND` against the collection URL.
49
+ ### 2 — Find your short username
81
50
 
82
- ### Infomaniak example
51
+ 1. Go to [config.infomaniak.com](https://config.infomaniak.com)
52
+ 2. Your CalDAV username is the **short name** shown there — e.g., `DK03456` — **not your email address**
83
53
 
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:
54
+ ### 3 — Set up credentials in n8n
87
55
 
88
- ```
89
- https://caldav.infomaniak.com/calendar/<user-id>/<calendar-id>/
90
- ```
56
+ 1. In n8n, go to **Credentials** → **New** → search for **CalDAV**
57
+ 2. Fill in:
58
+ - **Server URL**: `https://sync.infomaniak.com/` (default, no change needed)
59
+ - **Username**: your short name, e.g. `DK03456`
60
+ - **Password**: the App password from step 1
61
+ 3. Click **Test** — you should see "Connection successful"
91
62
 
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.
63
+ ### 4 — Create your first event
98
64
 
99
- ### Nextcloud
65
+ 1. Add a **CalDAV** node to your workflow
66
+ 2. Set **Resource** → `Event`, **Operation** → `Create`
67
+ 3. Pick your calendar from the **Calendar** dropdown
68
+ 4. Fill in Title, Start, End — click **Execute**
100
69
 
101
- ```
102
- https://cloud.example.com/remote.php/dav/calendars/<user>/<calendar-id>/
103
- ```
70
+ ---
104
71
 
105
- Use an app-token rather than your main password (Settings → Security →
106
- Devices & sessions).
72
+ ## AI Agent Usage
107
73
 
108
- ### Apple iCloud
74
+ This node is registered with `usableAsTool: true`, so n8n's AI Agent node can call it directly without any wrapper.
109
75
 
110
- ```
111
- https://caldav.icloud.com/<principal-id>/calendars/<calendar-id>/
112
- ```
76
+ ### Wiring it up
113
77
 
114
- Requires an **app-specific password**.
78
+ 1. Add an **AI Agent** node to your workflow
79
+ 2. In the agent's **Tools** section, add the **CalDAV** node
80
+ 3. The agent will automatically discover all available operations and parameters
115
81
 
116
- ### Radicale / Baikal / SOGo
82
+ ### Example system prompt
117
83
 
118
- Use the calendar collection URL that the server admin gave you.
119
- Radicale default layout: `https://host/<user>/<calendar>/`.
84
+ ```
85
+ You are a scheduling assistant. You have access to a CalDAV calendar tool.
120
86
 
121
- ---
87
+ When the user asks to create, read, update, or delete calendar events, use the CalDAV tool.
122
88
 
123
- ## AI Agent setup (CalDAV Tool)
89
+ Guidelines:
90
+ - Always confirm event details (title, date/time, calendar) before creating
91
+ - When listing events, default to the next 7 days unless the user specifies otherwise
92
+ - For recurring events, confirm the frequency and end condition
93
+ - Times should be provided in ISO 8601 format with timezone offset, e.g. 2026-04-20T14:00:00+02:00
94
+ - If the user doesn't specify a calendar, use the first available calendar
124
95
 
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()`.
96
+ Today's date: {{$now.toISO()}}
97
+ ```
127
98
 
128
- ### Suggested system prompt
99
+ ### Parameter flexibility for LLMs
129
100
 
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
- ```
101
+ The node accepts parameters in camelCase, snake_case, or UPPER_CASE — so LLMs don't need to match exact field names:
149
102
 
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
- ```
103
+ | Canonical | Also accepted |
104
+ |---|---|
105
+ | `eventTitle` | `event_title`, `EVENT_TITLE` |
106
+ | `startDateAndTime` | `start_date_and_time`, `START_DATE_AND_TIME` |
107
+ | `calendarUrl` | `calendar_url`, `CALENDAR_URL` |
108
+ | `recurringEvent` | `recurring_event` |
184
109
 
185
110
  ---
186
111
 
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
- ```
112
+ ## Node Reference
113
+
114
+ ### Calendar resource
115
+
116
+ | Operation | Description |
117
+ |---|---|
118
+ | Get All | List all calendars on the server |
119
+
120
+ ### Event resource
121
+
122
+ | Operation | Description |
123
+ |---|---|
124
+ | Create | Create a new calendar event |
125
+ | Get | Retrieve a single event by UID |
126
+ | Get All | List events within a date range |
127
+ | Update | Modify an existing event |
128
+ | Delete | Remove an event |
129
+
130
+ ### Key fields
131
+
132
+ | Field | Operations | Notes |
133
+ |---|---|---|
134
+ | Calendar | All event ops | Dynamic dropdown, auto-populated |
135
+ | UID | Get, Update, Delete (required) | Unique event identifier |
136
+ | Title | Create (required) | Event summary/title |
137
+ | Start Date & Time | Create (required) | ISO 8601, e.g. `2026-04-20T14:00:00+02:00` |
138
+ | End Date & Time | Create | Defaults to 1 hour after start |
139
+ | Location | Create, Update | Free text |
140
+ | Description | Create, Update | Free text |
141
+ | All Day Event | Create, Update | Toggle — uses DATE values |
142
+ | Reminder (minutes before) | Create, Update | 0 = at event time |
143
+ | Recurring Event | Create, Update | Toggle to enable recurrence |
144
+ | Recurrence Frequency | Create (recurring) | DAILY / WEEKLY / MONTHLY / YEARLY |
145
+ | Recurrence Interval | Create (recurring) | e.g. 2 = every 2 weeks |
146
+ | Recurrence Days | Create (WEEKLY) | MO, TU, WE, TH, FR, SA, SU |
147
+ | Recurrence End Type | Create (recurring) | Never / After N occurrences / Until date |
148
+ | Time Min / Max | Get All | Filter window (defaults: today / +30 days) |
149
+ | Return All | Get All | If off, capped by Max Results |
150
+ | Max Results | Get All | Default 50 |
276
151
 
277
152
  ---
278
153
 
279
- ## Error handling
154
+ ## Credentials
280
155
 
281
- Both nodes return structured JSON on failure (and on success):
156
+ | Field | Default | Notes |
157
+ |---|---|---|
158
+ | Server URL | `https://sync.infomaniak.com/` | Trailing slash required |
159
+ | Username | — | Short name (e.g. `DK03456`), not email |
160
+ | Password | — | App password if 2FA is enabled |
282
161
 
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
- ```
162
+ The credential test performs a `PROPFIND` against `/.well-known/caldav`. A 207 Multi-Status or 301 redirect is treated as success.
163
+
164
+ ---
291
165
 
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.
166
+ ## Tested with
167
+
168
+ - **Infomaniak kSuite** (sync.infomaniak.com) — primary target
169
+ - **Nextcloud** (self-hosted)
170
+ - **Radicale** (self-hosted)
296
171
 
297
172
  ---
298
173
 
299
- ## Development
174
+ ## Known Limitations
300
175
 
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
- ```
176
+ - **iCloud** requires an app-specific password and uses `caldav.icloud.com` as server URL — discovery works but is slower
177
+ - **Recurring event updates** modify the master event (all occurrences), not individual instances (RECURRENCE-ID is not yet supported)
178
+ - **Attendees / RSVP** are not yet supported
179
+ - **Free/busy queries** are not yet supported
180
+ - The node queries calendar data by time range; very large calendars (10 000+ events) may be slow on Get All
308
181
 
309
182
  ---
310
183
 
311
184
  ## License
312
185
 
313
- MIT – see [LICENSE](LICENSE).
186
+ MIT
@@ -1,4 +1,4 @@
1
- import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
1
+ import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
2
  export declare class CalDavApi implements ICredentialType {
3
3
  name: string;
4
4
  displayName: string;
@@ -11,14 +11,16 @@ class CalDavApi {
11
11
  displayName: 'Server URL',
12
12
  name: 'serverUrl',
13
13
  type: 'string',
14
- default: '',
14
+ default: 'https://sync.infomaniak.com/',
15
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',
16
+ placeholder: 'https://sync.infomaniak.com/',
17
+ description: 'Base URL of the CalDAV server — NOT the individual calendar URL. ' +
18
+ 'The node discovers calendar collections automatically.\n\n' +
19
+ 'Examples:\n' +
20
+ '• Infomaniak: https://sync.infomaniak.com/\n' +
21
+ '• Nextcloud: https://cloud.example.com/\n' +
22
+ '• iCloud: https://caldav.icloud.com/\n' +
23
+ '• Radicale / Baikal / SOGo: your server root URL',
22
24
  },
23
25
  {
24
26
  displayName: 'Username',
@@ -26,6 +28,10 @@ class CalDavApi {
26
28
  type: 'string',
27
29
  default: '',
28
30
  required: true,
31
+ placeholder: 'dk03456',
32
+ description: 'CalDAV username. For Infomaniak this is your short account name (e.g. dk03456), ' +
33
+ 'NOT your email address. ' +
34
+ 'Find it at https://config.infomaniak.com/ under Account → Username.',
29
35
  },
30
36
  {
31
37
  displayName: 'Password',
@@ -36,7 +42,10 @@ class CalDavApi {
36
42
  },
37
43
  default: '',
38
44
  required: true,
39
- description: 'Account password or app-specific password (recommended for Infomaniak / iCloud / Google).',
45
+ description: 'Account password or app-specific password. ' +
46
+ 'If 2FA is enabled on your Infomaniak account, you must create an app password at ' +
47
+ 'https://manager.infomaniak.com → Security → Application passwords. ' +
48
+ 'Using your main password with 2FA enabled will return HTTP 401.',
40
49
  },
41
50
  ];
42
51
  this.authenticate = {
@@ -47,21 +56,24 @@ class CalDavApi {
47
56
  password: '={{ $credentials.password }}',
48
57
  },
49
58
  headers: {
50
- 'User-Agent': 'n8n-nodes-caldav-pro/1.0.3',
59
+ 'User-Agent': 'n8n-nodes-caldav-pro/2.0.0',
51
60
  },
52
61
  },
53
62
  };
54
63
  this.test = {
55
64
  request: {
56
65
  baseURL: '={{ $credentials.serverUrl }}',
57
- url: '',
66
+ url: '/.well-known/caldav',
58
67
  method: 'PROPFIND',
59
68
  headers: {
60
69
  Depth: '0',
61
70
  'Content-Type': 'application/xml; charset=utf-8',
62
71
  },
63
72
  body: '<?xml version="1.0" encoding="utf-8" ?>' +
64
- '<d:propfind xmlns:d="DAV:"><d:prop><d:resourcetype/><d:displayname/></d:prop></d:propfind>',
73
+ '<d:propfind xmlns:d="DAV:">' +
74
+ '<d:prop><d:resourcetype/><d:displayname/></d:prop>' +
75
+ '</d:propfind>',
76
+ ignoreHttpStatusErrors: true,
65
77
  },
66
78
  };
67
79
  }
@@ -1 +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"}
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,8BAA8B;gBACvC,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,8BAA8B;gBAC3C,WAAW,EACV,mEAAmE;oBACnE,4DAA4D;oBAC5D,aAAa;oBACb,8CAA8C;oBAC9C,2CAA2C;oBAC3C,wCAAwC;oBACxC,kDAAkD;aACnD;YACD;gBACC,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,SAAS;gBACtB,WAAW,EACV,kFAAkF;oBAClF,0BAA0B;oBAC1B,qEAAqE;aACtE;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,6CAA6C;oBAC7C,mFAAmF;oBACnF,qEAAqE;oBACrE,iEAAiE;aAClE;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;QAYF,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,OAAO,EAAE,+BAA+B;gBACxC,GAAG,EAAE,qBAAqB;gBAC1B,MAAM,EAAE,UAAyD;gBACjE,OAAO,EAAE;oBACR,KAAK,EAAE,GAAG;oBACV,cAAc,EAAE,gCAAgC;iBAChD;gBACD,IAAI,EACH,yCAAyC;oBACzC,6BAA6B;oBAC7B,oDAAoD;oBACpD,eAAe;gBAChB,sBAAsB,EAAE,IAAI;aAC5B;SACD,CAAC;IACH,CAAC;CAAA;AA3FD,8BA2FC"}
@@ -1,5 +1,12 @@
1
- import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
1
+ import type { IExecuteFunctions, ILoadOptionsFunctions, INodeExecutionData, INodePropertyOptions, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ import { generateUid } from './GenericFunctions';
2
3
  export declare class CalDav implements INodeType {
3
4
  description: INodeTypeDescription;
5
+ methods: {
6
+ loadOptions: {
7
+ getCalendars(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
8
+ };
9
+ };
4
10
  execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
11
  }
12
+ export { generateUid };