@elizaos/capacitor-calendar 2.0.11-beta.7
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/ElizaosCapacitorCalendar.podspec +18 -0
- package/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/esm/definitions.d.ts +93 -0
- package/dist/esm/definitions.d.ts.map +1 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +8 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/macos-bridge-policy.d.ts +9 -0
- package/dist/esm/macos-bridge-policy.d.ts.map +1 -0
- package/dist/esm/macos-bridge-policy.js +22 -0
- package/dist/esm/macos-bridge-policy.js.map +1 -0
- package/dist/esm/web.d.ts +12 -0
- package/dist/esm/web.d.ts.map +1 -0
- package/dist/esm/web.js +34 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +73 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +76 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/CalendarPlugin/CalendarPlugin.swift +560 -0
- package/package.json +74 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'ElizaosCapacitorCalendar'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license'] || { :type => 'MIT' }
|
|
10
|
+
s.homepage = 'https://elizaos.ai'
|
|
11
|
+
s.authors = { 'elizaOS' => 'dev@elizaos.ai' }
|
|
12
|
+
s.source = { :git => 'https://github.com/elizaOS/eliza.git', :tag => s.version.to_s }
|
|
13
|
+
s.source_files = 'ios/Sources/**/*.{swift,h,m}'
|
|
14
|
+
s.ios.deployment_target = '15.0'
|
|
15
|
+
s.dependency 'Capacitor'
|
|
16
|
+
s.swift_version = '5.9'
|
|
17
|
+
s.frameworks = 'EventKit', 'UIKit'
|
|
18
|
+
end
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shaw Walters and elizaOS Contributors
|
|
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,77 @@
|
|
|
1
|
+
# @elizaos/capacitor-calendar
|
|
2
|
+
|
|
3
|
+
Reads and writes Apple Calendar events through EventKit, for elizaOS iOS apps and macOS desktop runtimes.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
This package provides a Capacitor native-bridge plugin (`AppleCalendar`) that gives elizaOS apps running on iOS (or macOS via the Electrobun desktop shell with the EventKit dylib) full read/write access to the device's calendar store. On web/browser targets every method returns a graceful `not_supported` error.
|
|
8
|
+
|
|
9
|
+
## Capabilities
|
|
10
|
+
|
|
11
|
+
| Operation | Method |
|
|
12
|
+
|-----------|--------|
|
|
13
|
+
| Check EventKit permission state | `AppleCalendar.checkPermissions()` |
|
|
14
|
+
| Request calendar access from the user | `AppleCalendar.requestPermissions()` |
|
|
15
|
+
| List all calendars | `AppleCalendar.listCalendars()` |
|
|
16
|
+
| Fetch events in a time window | `AppleCalendar.listEvents({ timeMin, timeMax, calendarId? })` |
|
|
17
|
+
| Create a new event | `AppleCalendar.createEvent(input)` |
|
|
18
|
+
| Update an existing event | `AppleCalendar.updateEvent({ eventId, ...input })` |
|
|
19
|
+
| Delete an event | `AppleCalendar.deleteEvent({ eventId })` |
|
|
20
|
+
|
|
21
|
+
All methods return a Promise. Results include an `ok: boolean` field; failures include `error` and `message` string fields.
|
|
22
|
+
|
|
23
|
+
## Limitations
|
|
24
|
+
|
|
25
|
+
- **Attendees are not supported.** EventKit does not permit third-party apps to set event invitees. Passing `attendees` to `createEvent` or `updateEvent` returns `error: "unsupported_feature"`.
|
|
26
|
+
- **macOS desktop** uses the Electrobun EventKit dylib, not this Capacitor plugin.
|
|
27
|
+
- **Browser/web** targets receive `{ ok: false, error: "not_supported" }` from every method.
|
|
28
|
+
- iOS 17+ requires full-access authorization (`requestFullAccessToEvents`). `writeOnly` authorization is treated as `restricted`.
|
|
29
|
+
|
|
30
|
+
## Required platform setup
|
|
31
|
+
|
|
32
|
+
### iOS
|
|
33
|
+
|
|
34
|
+
Add the plugin to your Capacitor iOS project:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install @elizaos/capacitor-calendar
|
|
38
|
+
npx cap sync ios
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Add the `NSCalendarsFullAccessUsageDescription` key to `Info.plist` explaining why calendar access is needed. Without this key the system will deny access.
|
|
42
|
+
|
|
43
|
+
The native pod (`ElizaosCapacitorCalendar`) requires iOS 15.0+ and Swift 5.9+.
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { AppleCalendar } from "@elizaos/capacitor-calendar";
|
|
49
|
+
|
|
50
|
+
// Check and request permission
|
|
51
|
+
const status = await AppleCalendar.checkPermissions();
|
|
52
|
+
if (status.calendar !== "granted") {
|
|
53
|
+
await AppleCalendar.requestPermissions();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// List events for the next 7 days
|
|
57
|
+
const now = new Date();
|
|
58
|
+
const nextWeek = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
|
|
59
|
+
const result = await AppleCalendar.listEvents({
|
|
60
|
+
timeMin: now.toISOString(),
|
|
61
|
+
timeMax: nextWeek.toISOString(),
|
|
62
|
+
});
|
|
63
|
+
if (result.ok) {
|
|
64
|
+
console.log(result.events);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Create an event
|
|
68
|
+
const created = await AppleCalendar.createEvent({
|
|
69
|
+
title: "Team sync",
|
|
70
|
+
startAt: "2026-06-01T10:00:00.000Z",
|
|
71
|
+
endAt: "2026-06-01T11:00:00.000Z",
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Config / Env Vars
|
|
76
|
+
|
|
77
|
+
None. This package reads no environment variables. Authorization is granted at the OS level by the user.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export type AppleCalendarPermissionState = "granted" | "denied" | "prompt" | "restricted";
|
|
2
|
+
export interface AppleCalendarPermissionStatus {
|
|
3
|
+
calendar: AppleCalendarPermissionState;
|
|
4
|
+
canRequest: boolean;
|
|
5
|
+
reason?: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface AppleCalendarSummary {
|
|
8
|
+
calendarId: string;
|
|
9
|
+
summary: string;
|
|
10
|
+
description: string | null;
|
|
11
|
+
primary: boolean;
|
|
12
|
+
accessRole: string;
|
|
13
|
+
backgroundColor: string | null;
|
|
14
|
+
foregroundColor: string | null;
|
|
15
|
+
timeZone: string | null;
|
|
16
|
+
selected: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface AppleCalendarAttendee {
|
|
19
|
+
email: string | null;
|
|
20
|
+
displayName: string | null;
|
|
21
|
+
responseStatus: string | null;
|
|
22
|
+
self: boolean;
|
|
23
|
+
organizer: boolean;
|
|
24
|
+
optional: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface AppleCalendarEvent {
|
|
27
|
+
id: string;
|
|
28
|
+
externalId: string;
|
|
29
|
+
calendarId: string;
|
|
30
|
+
calendarSummary: string;
|
|
31
|
+
title: string;
|
|
32
|
+
description: string;
|
|
33
|
+
location: string;
|
|
34
|
+
status: string;
|
|
35
|
+
startAt: string;
|
|
36
|
+
endAt: string;
|
|
37
|
+
isAllDay: boolean;
|
|
38
|
+
timezone: string | null;
|
|
39
|
+
htmlLink: string | null;
|
|
40
|
+
conferenceLink: string | null;
|
|
41
|
+
organizer: Record<string, unknown> | null;
|
|
42
|
+
attendees: AppleCalendarAttendee[];
|
|
43
|
+
}
|
|
44
|
+
export interface AppleCalendarBaseResult {
|
|
45
|
+
ok: boolean;
|
|
46
|
+
error?: string;
|
|
47
|
+
message?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface AppleCalendarListResult extends AppleCalendarBaseResult {
|
|
50
|
+
calendars?: AppleCalendarSummary[];
|
|
51
|
+
}
|
|
52
|
+
export interface AppleCalendarEventsResult extends AppleCalendarBaseResult {
|
|
53
|
+
events?: AppleCalendarEvent[];
|
|
54
|
+
}
|
|
55
|
+
export interface AppleCalendarEventResult extends AppleCalendarBaseResult {
|
|
56
|
+
event?: AppleCalendarEvent;
|
|
57
|
+
}
|
|
58
|
+
export interface AppleCalendarListEventsOptions {
|
|
59
|
+
calendarId?: string | null;
|
|
60
|
+
timeMin: string;
|
|
61
|
+
timeMax: string;
|
|
62
|
+
}
|
|
63
|
+
export interface AppleCalendarEventInput {
|
|
64
|
+
calendarId?: string;
|
|
65
|
+
title?: string;
|
|
66
|
+
description?: string;
|
|
67
|
+
location?: string;
|
|
68
|
+
startAt?: string;
|
|
69
|
+
endAt?: string;
|
|
70
|
+
timeZone?: string;
|
|
71
|
+
isAllDay?: boolean;
|
|
72
|
+
attendees?: Array<{
|
|
73
|
+
email: string;
|
|
74
|
+
displayName?: string;
|
|
75
|
+
optional?: boolean;
|
|
76
|
+
}>;
|
|
77
|
+
}
|
|
78
|
+
export interface AppleCalendarUpdateEventInput extends AppleCalendarEventInput {
|
|
79
|
+
eventId: string;
|
|
80
|
+
}
|
|
81
|
+
export interface AppleCalendarDeleteEventInput {
|
|
82
|
+
eventId: string;
|
|
83
|
+
}
|
|
84
|
+
export interface AppleCalendarPlugin {
|
|
85
|
+
checkPermissions(): Promise<AppleCalendarPermissionStatus>;
|
|
86
|
+
requestPermissions(): Promise<AppleCalendarPermissionStatus>;
|
|
87
|
+
listCalendars(): Promise<AppleCalendarListResult>;
|
|
88
|
+
listEvents(options: AppleCalendarListEventsOptions): Promise<AppleCalendarEventsResult>;
|
|
89
|
+
createEvent(input: AppleCalendarEventInput): Promise<AppleCalendarEventResult>;
|
|
90
|
+
updateEvent(input: AppleCalendarUpdateEventInput): Promise<AppleCalendarEventResult>;
|
|
91
|
+
deleteEvent(input: AppleCalendarDeleteEventInput): Promise<AppleCalendarBaseResult>;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=definitions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AAItC,eAAO,MAAM,aAAa,qBAKzB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { registerPlugin } from "@capacitor/core";
|
|
2
|
+
export * from "./definitions";
|
|
3
|
+
export * from "./macos-bridge-policy";
|
|
4
|
+
const loadWeb = () => import("./web").then((m) => new m.AppleCalendarWeb());
|
|
5
|
+
export const AppleCalendar = registerPlugin("AppleCalendar", {
|
|
6
|
+
web: loadWeb,
|
|
7
|
+
});
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AAEtC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC;AAE5E,MAAM,CAAC,MAAM,aAAa,GAAG,cAAc,CACzC,eAAe,EACf;IACE,GAAG,EAAE,OAAO;CACb,CACF,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface AppleCalendarMacosBridgeCandidate {
|
|
2
|
+
label: string;
|
|
3
|
+
path: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME = "libMacWindowEffects.dylib";
|
|
6
|
+
export declare function appleCalendarMacosBridgeCandidates(args?: {
|
|
7
|
+
envDylibPath?: string | null;
|
|
8
|
+
}): AppleCalendarMacosBridgeCandidate[];
|
|
9
|
+
//# sourceMappingURL=macos-bridge-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"macos-bridge-policy.d.ts","sourceRoot":"","sources":["../../src/macos-bridge-policy.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iCAAiC;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,0CAA0C,8BAC1B,CAAC;AAE9B,wBAAgB,kCAAkC,CAAC,IAAI,CAAC,EAAE;IACxD,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,GAAG,iCAAiC,EAAE,CAmBtC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME = "libMacWindowEffects.dylib";
|
|
2
|
+
export function appleCalendarMacosBridgeCandidates(args) {
|
|
3
|
+
return [
|
|
4
|
+
{
|
|
5
|
+
label: "ELIZA_NATIVE_PERMISSIONS_DYLIB",
|
|
6
|
+
path: args?.envDylibPath ?? "",
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
label: "packaged Apple permissions bridge",
|
|
10
|
+
path: `../../../../../../../${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
label: "packaged Apple permissions bridge",
|
|
14
|
+
path: `../../../../../../${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
label: "local Apple permissions bridge",
|
|
18
|
+
path: `../../../../packages/app-core/platforms/electrobun/src/${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,
|
|
19
|
+
},
|
|
20
|
+
].filter((candidate) => candidate.path.trim().length > 0);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=macos-bridge-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"macos-bridge-policy.js","sourceRoot":"","sources":["../../src/macos-bridge-policy.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,0CAA0C,GACrD,2BAA2B,CAAC;AAE9B,MAAM,UAAU,kCAAkC,CAAC,IAElD;IACC,OAAO;QACL;YACE,KAAK,EAAE,gCAAgC;YACvC,IAAI,EAAE,IAAI,EAAE,YAAY,IAAI,EAAE;SAC/B;QACD;YACE,KAAK,EAAE,mCAAmC;YAC1C,IAAI,EAAE,wBAAwB,0CAA0C,EAAE;SAC3E;QACD;YACE,KAAK,EAAE,mCAAmC;YAC1C,IAAI,EAAE,qBAAqB,0CAA0C,EAAE;SACxE;QACD;YACE,KAAK,EAAE,gCAAgC;YACvC,IAAI,EAAE,0DAA0D,0CAA0C,EAAE;SAC7G;KACF,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { WebPlugin } from "@capacitor/core";
|
|
2
|
+
import type { AppleCalendarBaseResult, AppleCalendarEventInput, AppleCalendarEventResult, AppleCalendarEventsResult, AppleCalendarListEventsOptions, AppleCalendarListResult, AppleCalendarPermissionStatus, AppleCalendarPlugin, AppleCalendarUpdateEventInput } from "./definitions";
|
|
3
|
+
export declare class AppleCalendarWeb extends WebPlugin implements AppleCalendarPlugin {
|
|
4
|
+
checkPermissions(): Promise<AppleCalendarPermissionStatus>;
|
|
5
|
+
requestPermissions(): Promise<AppleCalendarPermissionStatus>;
|
|
6
|
+
listCalendars(): Promise<AppleCalendarListResult>;
|
|
7
|
+
listEvents(_options: AppleCalendarListEventsOptions): Promise<AppleCalendarEventsResult>;
|
|
8
|
+
createEvent(_input: AppleCalendarEventInput): Promise<AppleCalendarEventResult>;
|
|
9
|
+
updateEvent(_input: AppleCalendarUpdateEventInput): Promise<AppleCalendarEventResult>;
|
|
10
|
+
deleteEvent(_input: Parameters<AppleCalendarPlugin["deleteEvent"]>[0]): Promise<AppleCalendarBaseResult>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EACV,uBAAuB,EACvB,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,EAC9B,uBAAuB,EACvB,6BAA6B,EAC7B,mBAAmB,EACnB,6BAA6B,EAC9B,MAAM,eAAe,CAAC;AASvB,qBAAa,gBAAiB,SAAQ,SAAU,YAAW,mBAAmB;IACtE,gBAAgB,IAAI,OAAO,CAAC,6BAA6B,CAAC;IAQ1D,kBAAkB,IAAI,OAAO,CAAC,6BAA6B,CAAC;IAI5D,aAAa,IAAI,OAAO,CAAC,uBAAuB,CAAC;IAIjD,UAAU,CACd,QAAQ,EAAE,8BAA8B,GACvC,OAAO,CAAC,yBAAyB,CAAC;IAI/B,WAAW,CACf,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,wBAAwB,CAAC;IAI9B,WAAW,CACf,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,wBAAwB,CAAC;IAI9B,WAAW,CACf,MAAM,EAAE,UAAU,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GACxD,OAAO,CAAC,uBAAuB,CAAC;CAGpC"}
|
package/dist/esm/web.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { WebPlugin } from "@capacitor/core";
|
|
2
|
+
const unsupported = {
|
|
3
|
+
ok: false,
|
|
4
|
+
error: "not_supported",
|
|
5
|
+
message: "Apple Calendar is only available through the native iOS app or macOS desktop runtime.",
|
|
6
|
+
};
|
|
7
|
+
export class AppleCalendarWeb extends WebPlugin {
|
|
8
|
+
async checkPermissions() {
|
|
9
|
+
return {
|
|
10
|
+
calendar: "restricted",
|
|
11
|
+
canRequest: false,
|
|
12
|
+
reason: unsupported.message,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
async requestPermissions() {
|
|
16
|
+
return this.checkPermissions();
|
|
17
|
+
}
|
|
18
|
+
async listCalendars() {
|
|
19
|
+
return { ...unsupported };
|
|
20
|
+
}
|
|
21
|
+
async listEvents(_options) {
|
|
22
|
+
return { ...unsupported };
|
|
23
|
+
}
|
|
24
|
+
async createEvent(_input) {
|
|
25
|
+
return { ...unsupported };
|
|
26
|
+
}
|
|
27
|
+
async updateEvent(_input) {
|
|
28
|
+
return { ...unsupported };
|
|
29
|
+
}
|
|
30
|
+
async deleteEvent(_input) {
|
|
31
|
+
return { ...unsupported };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAa5C,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,KAAK;IACT,KAAK,EAAE,eAAe;IACtB,OAAO,EACL,uFAAuF;CACjF,CAAC;AAEX,MAAM,OAAO,gBAAiB,SAAQ,SAAS;IAC7C,KAAK,CAAC,gBAAgB;QACpB,OAAO;YACL,QAAQ,EAAE,YAAY;YACtB,UAAU,EAAE,KAAK;YACjB,MAAM,EAAE,WAAW,CAAC,OAAO;SAC5B,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,OAAO,IAAI,CAAC,gBAAgB,EAAE,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,UAAU,CACd,QAAwC;QAExC,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,WAAW,CACf,MAA+B;QAE/B,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,WAAW,CACf,MAAqC;QAErC,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,WAAW,CACf,MAAyD;QAEzD,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@capacitor/core');
|
|
4
|
+
|
|
5
|
+
const APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME = "libMacWindowEffects.dylib";
|
|
6
|
+
function appleCalendarMacosBridgeCandidates(args) {
|
|
7
|
+
return [
|
|
8
|
+
{
|
|
9
|
+
label: "ELIZA_NATIVE_PERMISSIONS_DYLIB",
|
|
10
|
+
path: args?.envDylibPath ?? "",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
label: "packaged Apple permissions bridge",
|
|
14
|
+
path: `../../../../../../../${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
label: "packaged Apple permissions bridge",
|
|
18
|
+
path: `../../../../../../${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
label: "local Apple permissions bridge",
|
|
22
|
+
path: `../../../../packages/app-core/platforms/electrobun/src/${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,
|
|
23
|
+
},
|
|
24
|
+
].filter((candidate) => candidate.path.trim().length > 0);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const loadWeb = () => Promise.resolve().then(function () { return web; }).then((m) => new m.AppleCalendarWeb());
|
|
28
|
+
const AppleCalendar = core.registerPlugin("AppleCalendar", {
|
|
29
|
+
web: loadWeb,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const unsupported = {
|
|
33
|
+
ok: false,
|
|
34
|
+
error: "not_supported",
|
|
35
|
+
message: "Apple Calendar is only available through the native iOS app or macOS desktop runtime.",
|
|
36
|
+
};
|
|
37
|
+
class AppleCalendarWeb extends core.WebPlugin {
|
|
38
|
+
async checkPermissions() {
|
|
39
|
+
return {
|
|
40
|
+
calendar: "restricted",
|
|
41
|
+
canRequest: false,
|
|
42
|
+
reason: unsupported.message,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async requestPermissions() {
|
|
46
|
+
return this.checkPermissions();
|
|
47
|
+
}
|
|
48
|
+
async listCalendars() {
|
|
49
|
+
return { ...unsupported };
|
|
50
|
+
}
|
|
51
|
+
async listEvents(_options) {
|
|
52
|
+
return { ...unsupported };
|
|
53
|
+
}
|
|
54
|
+
async createEvent(_input) {
|
|
55
|
+
return { ...unsupported };
|
|
56
|
+
}
|
|
57
|
+
async updateEvent(_input) {
|
|
58
|
+
return { ...unsupported };
|
|
59
|
+
}
|
|
60
|
+
async deleteEvent(_input) {
|
|
61
|
+
return { ...unsupported };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
66
|
+
__proto__: null,
|
|
67
|
+
AppleCalendarWeb: AppleCalendarWeb
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
exports.APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME = APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME;
|
|
71
|
+
exports.AppleCalendar = AppleCalendar;
|
|
72
|
+
exports.appleCalendarMacosBridgeCandidates = appleCalendarMacosBridgeCandidates;
|
|
73
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/macos-bridge-policy.js","esm/index.js","esm/web.js"],"sourcesContent":["export const APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME = \"libMacWindowEffects.dylib\";\nexport function appleCalendarMacosBridgeCandidates(args) {\n return [\n {\n label: \"ELIZA_NATIVE_PERMISSIONS_DYLIB\",\n path: args?.envDylibPath ?? \"\",\n },\n {\n label: \"packaged Apple permissions bridge\",\n path: `../../../../../../../${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,\n },\n {\n label: \"packaged Apple permissions bridge\",\n path: `../../../../../../${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,\n },\n {\n label: \"local Apple permissions bridge\",\n path: `../../../../packages/app-core/platforms/electrobun/src/${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,\n },\n ].filter((candidate) => candidate.path.trim().length > 0);\n}\n//# sourceMappingURL=macos-bridge-policy.js.map","import { registerPlugin } from \"@capacitor/core\";\nexport * from \"./definitions\";\nexport * from \"./macos-bridge-policy\";\nconst loadWeb = () => import(\"./web\").then((m) => new m.AppleCalendarWeb());\nexport const AppleCalendar = registerPlugin(\"AppleCalendar\", {\n web: loadWeb,\n});\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nconst unsupported = {\n ok: false,\n error: \"not_supported\",\n message: \"Apple Calendar is only available through the native iOS app or macOS desktop runtime.\",\n};\nexport class AppleCalendarWeb extends WebPlugin {\n async checkPermissions() {\n return {\n calendar: \"restricted\",\n canRequest: false,\n reason: unsupported.message,\n };\n }\n async requestPermissions() {\n return this.checkPermissions();\n }\n async listCalendars() {\n return { ...unsupported };\n }\n async listEvents(_options) {\n return { ...unsupported };\n }\n async createEvent(_input) {\n return { ...unsupported };\n }\n async updateEvent(_input) {\n return { ...unsupported };\n }\n async deleteEvent(_input) {\n return { ...unsupported };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AAAY,MAAC,0CAA0C,GAAG;AACnD,SAAS,kCAAkC,CAAC,IAAI,EAAE;AACzD,IAAI,OAAO;AACX,QAAQ;AACR,YAAY,KAAK,EAAE,gCAAgC;AACnD,YAAY,IAAI,EAAE,IAAI,EAAE,YAAY,IAAI,EAAE;AAC1C,SAAS;AACT,QAAQ;AACR,YAAY,KAAK,EAAE,mCAAmC;AACtD,YAAY,IAAI,EAAE,CAAC,qBAAqB,EAAE,0CAA0C,CAAC,CAAC;AACtF,SAAS;AACT,QAAQ;AACR,YAAY,KAAK,EAAE,mCAAmC;AACtD,YAAY,IAAI,EAAE,CAAC,kBAAkB,EAAE,0CAA0C,CAAC,CAAC;AACnF,SAAS;AACT,QAAQ;AACR,YAAY,KAAK,EAAE,gCAAgC;AACnD,YAAY,IAAI,EAAE,CAAC,uDAAuD,EAAE,0CAA0C,CAAC,CAAC;AACxH,SAAS;AACT,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAC7D;;ACjBA,MAAM,OAAO,GAAG,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,gBAAgB,EAAE,CAAC;AAC/D,MAAC,aAAa,GAAGA,mBAAc,CAAC,eAAe,EAAE;AAC7D,IAAI,GAAG,EAAE,OAAO;AAChB,CAAC;;ACLD,MAAM,WAAW,GAAG;AACpB,IAAI,EAAE,EAAE,KAAK;AACb,IAAI,KAAK,EAAE,eAAe;AAC1B,IAAI,OAAO,EAAE,uFAAuF;AACpG,CAAC;AACM,MAAM,gBAAgB,SAASC,cAAS,CAAC;AAChD,IAAI,MAAM,gBAAgB,GAAG;AAC7B,QAAQ,OAAO;AACf,YAAY,QAAQ,EAAE,YAAY;AAClC,YAAY,UAAU,EAAE,KAAK;AAC7B,YAAY,MAAM,EAAE,WAAW,CAAC,OAAO;AACvC,SAAS;AACT,IAAI;AACJ,IAAI,MAAM,kBAAkB,GAAG;AAC/B,QAAQ,OAAO,IAAI,CAAC,gBAAgB,EAAE;AACtC,IAAI;AACJ,IAAI,MAAM,aAAa,GAAG;AAC1B,QAAQ,OAAO,EAAE,GAAG,WAAW,EAAE;AACjC,IAAI;AACJ,IAAI,MAAM,UAAU,CAAC,QAAQ,EAAE;AAC/B,QAAQ,OAAO,EAAE,GAAG,WAAW,EAAE;AACjC,IAAI;AACJ,IAAI,MAAM,WAAW,CAAC,MAAM,EAAE;AAC9B,QAAQ,OAAO,EAAE,GAAG,WAAW,EAAE;AACjC,IAAI;AACJ,IAAI,MAAM,WAAW,CAAC,MAAM,EAAE;AAC9B,QAAQ,OAAO,EAAE,GAAG,WAAW,EAAE;AACjC,IAAI;AACJ,IAAI,MAAM,WAAW,CAAC,MAAM,EAAE;AAC9B,QAAQ,OAAO,EAAE,GAAG,WAAW,EAAE;AACjC,IAAI;AACJ;;;;;;;;;;;"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
var capacitorAppleCalendar = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME = "libMacWindowEffects.dylib";
|
|
5
|
+
function appleCalendarMacosBridgeCandidates(args) {
|
|
6
|
+
return [
|
|
7
|
+
{
|
|
8
|
+
label: "ELIZA_NATIVE_PERMISSIONS_DYLIB",
|
|
9
|
+
path: args?.envDylibPath ?? "",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
label: "packaged Apple permissions bridge",
|
|
13
|
+
path: `../../../../../../../${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
label: "packaged Apple permissions bridge",
|
|
17
|
+
path: `../../../../../../${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
label: "local Apple permissions bridge",
|
|
21
|
+
path: `../../../../packages/app-core/platforms/electrobun/src/${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,
|
|
22
|
+
},
|
|
23
|
+
].filter((candidate) => candidate.path.trim().length > 0);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const loadWeb = () => Promise.resolve().then(function () { return web; }).then((m) => new m.AppleCalendarWeb());
|
|
27
|
+
const AppleCalendar = core.registerPlugin("AppleCalendar", {
|
|
28
|
+
web: loadWeb,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const unsupported = {
|
|
32
|
+
ok: false,
|
|
33
|
+
error: "not_supported",
|
|
34
|
+
message: "Apple Calendar is only available through the native iOS app or macOS desktop runtime.",
|
|
35
|
+
};
|
|
36
|
+
class AppleCalendarWeb extends core.WebPlugin {
|
|
37
|
+
async checkPermissions() {
|
|
38
|
+
return {
|
|
39
|
+
calendar: "restricted",
|
|
40
|
+
canRequest: false,
|
|
41
|
+
reason: unsupported.message,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async requestPermissions() {
|
|
45
|
+
return this.checkPermissions();
|
|
46
|
+
}
|
|
47
|
+
async listCalendars() {
|
|
48
|
+
return { ...unsupported };
|
|
49
|
+
}
|
|
50
|
+
async listEvents(_options) {
|
|
51
|
+
return { ...unsupported };
|
|
52
|
+
}
|
|
53
|
+
async createEvent(_input) {
|
|
54
|
+
return { ...unsupported };
|
|
55
|
+
}
|
|
56
|
+
async updateEvent(_input) {
|
|
57
|
+
return { ...unsupported };
|
|
58
|
+
}
|
|
59
|
+
async deleteEvent(_input) {
|
|
60
|
+
return { ...unsupported };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
65
|
+
__proto__: null,
|
|
66
|
+
AppleCalendarWeb: AppleCalendarWeb
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
exports.APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME = APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME;
|
|
70
|
+
exports.AppleCalendar = AppleCalendar;
|
|
71
|
+
exports.appleCalendarMacosBridgeCandidates = appleCalendarMacosBridgeCandidates;
|
|
72
|
+
|
|
73
|
+
return exports;
|
|
74
|
+
|
|
75
|
+
})({}, capacitorExports);
|
|
76
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/macos-bridge-policy.js","esm/index.js","esm/web.js"],"sourcesContent":["export const APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME = \"libMacWindowEffects.dylib\";\nexport function appleCalendarMacosBridgeCandidates(args) {\n return [\n {\n label: \"ELIZA_NATIVE_PERMISSIONS_DYLIB\",\n path: args?.envDylibPath ?? \"\",\n },\n {\n label: \"packaged Apple permissions bridge\",\n path: `../../../../../../../${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,\n },\n {\n label: \"packaged Apple permissions bridge\",\n path: `../../../../../../${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,\n },\n {\n label: \"local Apple permissions bridge\",\n path: `../../../../packages/app-core/platforms/electrobun/src/${APPLE_CALENDAR_MACOS_BRIDGE_DYLIB_BASENAME}`,\n },\n ].filter((candidate) => candidate.path.trim().length > 0);\n}\n//# sourceMappingURL=macos-bridge-policy.js.map","import { registerPlugin } from \"@capacitor/core\";\nexport * from \"./definitions\";\nexport * from \"./macos-bridge-policy\";\nconst loadWeb = () => import(\"./web\").then((m) => new m.AppleCalendarWeb());\nexport const AppleCalendar = registerPlugin(\"AppleCalendar\", {\n web: loadWeb,\n});\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nconst unsupported = {\n ok: false,\n error: \"not_supported\",\n message: \"Apple Calendar is only available through the native iOS app or macOS desktop runtime.\",\n};\nexport class AppleCalendarWeb extends WebPlugin {\n async checkPermissions() {\n return {\n calendar: \"restricted\",\n canRequest: false,\n reason: unsupported.message,\n };\n }\n async requestPermissions() {\n return this.checkPermissions();\n }\n async listCalendars() {\n return { ...unsupported };\n }\n async listEvents(_options) {\n return { ...unsupported };\n }\n async createEvent(_input) {\n return { ...unsupported };\n }\n async updateEvent(_input) {\n return { ...unsupported };\n }\n async deleteEvent(_input) {\n return { ...unsupported };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AAAY,UAAC,0CAA0C,GAAG;IACnD,SAAS,kCAAkC,CAAC,IAAI,EAAE;IACzD,IAAI,OAAO;IACX,QAAQ;IACR,YAAY,KAAK,EAAE,gCAAgC;IACnD,YAAY,IAAI,EAAE,IAAI,EAAE,YAAY,IAAI,EAAE;IAC1C,SAAS;IACT,QAAQ;IACR,YAAY,KAAK,EAAE,mCAAmC;IACtD,YAAY,IAAI,EAAE,CAAC,qBAAqB,EAAE,0CAA0C,CAAC,CAAC;IACtF,SAAS;IACT,QAAQ;IACR,YAAY,KAAK,EAAE,mCAAmC;IACtD,YAAY,IAAI,EAAE,CAAC,kBAAkB,EAAE,0CAA0C,CAAC,CAAC;IACnF,SAAS;IACT,QAAQ;IACR,YAAY,KAAK,EAAE,gCAAgC;IACnD,YAAY,IAAI,EAAE,CAAC,uDAAuD,EAAE,0CAA0C,CAAC,CAAC;IACxH,SAAS;IACT,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7D;;ICjBA,MAAM,OAAO,GAAG,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,gBAAgB,EAAE,CAAC;AAC/D,UAAC,aAAa,GAAGA,mBAAc,CAAC,eAAe,EAAE;IAC7D,IAAI,GAAG,EAAE,OAAO;IAChB,CAAC;;ICLD,MAAM,WAAW,GAAG;IACpB,IAAI,EAAE,EAAE,KAAK;IACb,IAAI,KAAK,EAAE,eAAe;IAC1B,IAAI,OAAO,EAAE,uFAAuF;IACpG,CAAC;IACM,MAAM,gBAAgB,SAASC,cAAS,CAAC;IAChD,IAAI,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,OAAO;IACf,YAAY,QAAQ,EAAE,YAAY;IAClC,YAAY,UAAU,EAAE,KAAK;IAC7B,YAAY,MAAM,EAAE,WAAW,CAAC,OAAO;IACvC,SAAS;IACT,IAAI;IACJ,IAAI,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,OAAO,IAAI,CAAC,gBAAgB,EAAE;IACtC,IAAI;IACJ,IAAI,MAAM,aAAa,GAAG;IAC1B,QAAQ,OAAO,EAAE,GAAG,WAAW,EAAE;IACjC,IAAI;IACJ,IAAI,MAAM,UAAU,CAAC,QAAQ,EAAE;IAC/B,QAAQ,OAAO,EAAE,GAAG,WAAW,EAAE;IACjC,IAAI;IACJ,IAAI,MAAM,WAAW,CAAC,MAAM,EAAE;IAC9B,QAAQ,OAAO,EAAE,GAAG,WAAW,EAAE;IACjC,IAAI;IACJ,IAAI,MAAM,WAAW,CAAC,MAAM,EAAE;IAC9B,QAAQ,OAAO,EAAE,GAAG,WAAW,EAAE;IACjC,IAAI;IACJ,IAAI,MAAM,WAAW,CAAC,MAAM,EAAE;IAC9B,QAAQ,OAAO,EAAE,GAAG,WAAW,EAAE;IACjC,IAAI;IACJ;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
import EventKit
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
6
|
+
@objc(AppleCalendarPlugin)
|
|
7
|
+
public class AppleCalendarPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
8
|
+
public let identifier = "AppleCalendarPlugin"
|
|
9
|
+
public let jsName = "AppleCalendar"
|
|
10
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
11
|
+
CAPPluginMethod(name: "checkPermissions", returnType: CAPPluginReturnPromise),
|
|
12
|
+
CAPPluginMethod(name: "requestPermissions", returnType: CAPPluginReturnPromise),
|
|
13
|
+
CAPPluginMethod(name: "listCalendars", returnType: CAPPluginReturnPromise),
|
|
14
|
+
CAPPluginMethod(name: "listEvents", returnType: CAPPluginReturnPromise),
|
|
15
|
+
CAPPluginMethod(name: "createEvent", returnType: CAPPluginReturnPromise),
|
|
16
|
+
CAPPluginMethod(name: "updateEvent", returnType: CAPPluginReturnPromise),
|
|
17
|
+
CAPPluginMethod(name: "deleteEvent", returnType: CAPPluginReturnPromise),
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
private let eventStore = EKEventStore()
|
|
21
|
+
private let maxTitleLength = 512
|
|
22
|
+
private let maxDescriptionLength = 20000
|
|
23
|
+
private let maxLocationLength = 1024
|
|
24
|
+
private let unsupportedRecurrenceFields = [
|
|
25
|
+
"recurrence",
|
|
26
|
+
"recurrenceRule",
|
|
27
|
+
"recurrenceRules",
|
|
28
|
+
"rrule",
|
|
29
|
+
]
|
|
30
|
+
private lazy var isoWithFractionalSeconds: ISO8601DateFormatter = {
|
|
31
|
+
let formatter = ISO8601DateFormatter()
|
|
32
|
+
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
|
|
33
|
+
return formatter
|
|
34
|
+
}()
|
|
35
|
+
private lazy var isoWithoutFractionalSeconds: ISO8601DateFormatter = {
|
|
36
|
+
let formatter = ISO8601DateFormatter()
|
|
37
|
+
formatter.formatOptions = [.withInternetDateTime]
|
|
38
|
+
return formatter
|
|
39
|
+
}()
|
|
40
|
+
|
|
41
|
+
@objc public override func checkPermissions(_ call: CAPPluginCall) {
|
|
42
|
+
call.resolve(permissionResult())
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@objc public override func requestPermissions(_ call: CAPPluginCall) {
|
|
46
|
+
let status = EKEventStore.authorizationStatus(for: .event)
|
|
47
|
+
if isGranted(status) || isDeniedOrRestricted(status) {
|
|
48
|
+
call.resolve(permissionResult())
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if #available(iOS 17.0, *) {
|
|
53
|
+
eventStore.requestFullAccessToEvents { [weak self] _, error in
|
|
54
|
+
DispatchQueue.main.async {
|
|
55
|
+
var result = self?.permissionResult() ?? [
|
|
56
|
+
"calendar": "restricted",
|
|
57
|
+
"canRequest": false,
|
|
58
|
+
]
|
|
59
|
+
if let error {
|
|
60
|
+
result["reason"] = error.localizedDescription
|
|
61
|
+
}
|
|
62
|
+
call.resolve(result)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
eventStore.requestAccess(to: .event) { [weak self] _, error in
|
|
67
|
+
DispatchQueue.main.async {
|
|
68
|
+
var result = self?.permissionResult() ?? [
|
|
69
|
+
"calendar": "restricted",
|
|
70
|
+
"canRequest": false,
|
|
71
|
+
]
|
|
72
|
+
if let error {
|
|
73
|
+
result["reason"] = error.localizedDescription
|
|
74
|
+
}
|
|
75
|
+
call.resolve(result)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@objc func listCalendars(_ call: CAPPluginCall) {
|
|
82
|
+
guard hasFullAccess() else {
|
|
83
|
+
call.resolve(permissionError())
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
let defaultCalendar = eventStore.defaultCalendarForNewEvents
|
|
87
|
+
let calendars = eventStore.calendars(for: .event).map {
|
|
88
|
+
calendarJson($0, defaultCalendar: defaultCalendar)
|
|
89
|
+
}
|
|
90
|
+
call.resolve(["ok": true, "calendars": calendars])
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@objc func listEvents(_ call: CAPPluginCall) {
|
|
94
|
+
guard hasFullAccess() else {
|
|
95
|
+
call.resolve(permissionError())
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
guard let timeMin = parseDate(call.getString("timeMin") ?? ""),
|
|
99
|
+
let timeMax = parseDate(call.getString("timeMax") ?? ""),
|
|
100
|
+
timeMax > timeMin
|
|
101
|
+
else {
|
|
102
|
+
call.resolve(nativeError("Calendar event window is invalid."))
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let requestedCalendarId = (call.getString("calendarId") ?? "")
|
|
107
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
108
|
+
var calendars: [EKCalendar]? = nil
|
|
109
|
+
if !requestedCalendarId.isEmpty && requestedCalendarId != "all" {
|
|
110
|
+
guard let calendar = calendar(withIdentifier: requestedCalendarId, requireWritable: false) else {
|
|
111
|
+
call.resolve([
|
|
112
|
+
"ok": false,
|
|
113
|
+
"error": "not_found",
|
|
114
|
+
"message": "Apple Calendar was not found.",
|
|
115
|
+
])
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
calendars = [calendar]
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
let predicate = eventStore.predicateForEvents(
|
|
122
|
+
withStart: timeMin,
|
|
123
|
+
end: timeMax,
|
|
124
|
+
calendars: calendars
|
|
125
|
+
)
|
|
126
|
+
let events = eventStore.events(matching: predicate)
|
|
127
|
+
.sorted { $0.startDate < $1.startDate }
|
|
128
|
+
.map(eventJson)
|
|
129
|
+
call.resolve(["ok": true, "events": events])
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@objc func createEvent(_ call: CAPPluginCall) {
|
|
133
|
+
guard hasFullAccess() else {
|
|
134
|
+
call.resolve(permissionError())
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
let event = EKEvent(eventStore: eventStore)
|
|
138
|
+
if let error = applyEventPayload(call, to: event, requireTitle: true) {
|
|
139
|
+
call.resolve(error)
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
do {
|
|
143
|
+
try eventStore.save(event, span: .thisEvent, commit: true)
|
|
144
|
+
call.resolve(["ok": true, "event": eventJson(event)])
|
|
145
|
+
} catch {
|
|
146
|
+
call.resolve(nativeError("Failed to create Apple Calendar event: \(error.localizedDescription)"))
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@objc func updateEvent(_ call: CAPPluginCall) {
|
|
151
|
+
guard hasFullAccess() else {
|
|
152
|
+
call.resolve(permissionError())
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
guard let eventId = nonEmptyString(call.getString("eventId")) else {
|
|
156
|
+
call.resolve(nativeError("Calendar event id is required."))
|
|
157
|
+
return
|
|
158
|
+
}
|
|
159
|
+
guard let item = eventStore.calendarItem(withIdentifier: eventId) as? EKEvent else {
|
|
160
|
+
call.resolve([
|
|
161
|
+
"ok": false,
|
|
162
|
+
"error": "not_found",
|
|
163
|
+
"message": "Apple Calendar event was not found.",
|
|
164
|
+
])
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
guard item.calendar.allowsContentModifications else {
|
|
168
|
+
call.resolve(nativeError("Apple Calendar event is not writable."))
|
|
169
|
+
return
|
|
170
|
+
}
|
|
171
|
+
if let error = applyEventPayload(call, to: item, requireTitle: false) {
|
|
172
|
+
call.resolve(error)
|
|
173
|
+
return
|
|
174
|
+
}
|
|
175
|
+
do {
|
|
176
|
+
try eventStore.save(item, span: .thisEvent, commit: true)
|
|
177
|
+
call.resolve(["ok": true, "event": eventJson(item)])
|
|
178
|
+
} catch {
|
|
179
|
+
call.resolve(nativeError("Failed to update Apple Calendar event: \(error.localizedDescription)"))
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@objc func deleteEvent(_ call: CAPPluginCall) {
|
|
184
|
+
guard hasFullAccess() else {
|
|
185
|
+
call.resolve(permissionError())
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
guard let eventId = nonEmptyString(call.getString("eventId")) else {
|
|
189
|
+
call.resolve(nativeError("Calendar event id is required."))
|
|
190
|
+
return
|
|
191
|
+
}
|
|
192
|
+
guard let event = eventStore.calendarItem(withIdentifier: eventId) as? EKEvent else {
|
|
193
|
+
call.resolve([
|
|
194
|
+
"ok": false,
|
|
195
|
+
"error": "not_found",
|
|
196
|
+
"message": "Apple Calendar event was not found.",
|
|
197
|
+
])
|
|
198
|
+
return
|
|
199
|
+
}
|
|
200
|
+
do {
|
|
201
|
+
try eventStore.remove(event, span: .thisEvent, commit: true)
|
|
202
|
+
call.resolve(["ok": true])
|
|
203
|
+
} catch {
|
|
204
|
+
call.resolve(nativeError("Failed to delete Apple Calendar event: \(error.localizedDescription)"))
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private func permissionResult() -> [String: Any] {
|
|
209
|
+
let status = EKEventStore.authorizationStatus(for: .event)
|
|
210
|
+
return [
|
|
211
|
+
"calendar": permissionString(status),
|
|
212
|
+
"canRequest": permissionString(status) == "prompt",
|
|
213
|
+
"reason": NSNull(),
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private func permissionString(_ status: EKAuthorizationStatus) -> String {
|
|
218
|
+
if isGranted(status) {
|
|
219
|
+
return "granted"
|
|
220
|
+
}
|
|
221
|
+
if isDenied(status) {
|
|
222
|
+
return "denied"
|
|
223
|
+
}
|
|
224
|
+
if isRestricted(status) {
|
|
225
|
+
return "restricted"
|
|
226
|
+
}
|
|
227
|
+
return "prompt"
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private func hasFullAccess() -> Bool {
|
|
231
|
+
isGranted(EKEventStore.authorizationStatus(for: .event))
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private func isGranted(_ status: EKAuthorizationStatus) -> Bool {
|
|
235
|
+
if #available(iOS 17.0, *) {
|
|
236
|
+
if status == .fullAccess {
|
|
237
|
+
return true
|
|
238
|
+
}
|
|
239
|
+
if status == .writeOnly {
|
|
240
|
+
return false
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return status == .authorized
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private func isDenied(_ status: EKAuthorizationStatus) -> Bool {
|
|
247
|
+
status == .denied
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
private func isRestricted(_ status: EKAuthorizationStatus) -> Bool {
|
|
251
|
+
if #available(iOS 17.0, *), status == .writeOnly {
|
|
252
|
+
return true
|
|
253
|
+
}
|
|
254
|
+
return status == .restricted
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private func isDeniedOrRestricted(_ status: EKAuthorizationStatus) -> Bool {
|
|
258
|
+
isDenied(status) || isRestricted(status)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private func permissionError() -> [String: Any] {
|
|
262
|
+
[
|
|
263
|
+
"ok": false,
|
|
264
|
+
"error": "permission",
|
|
265
|
+
"message": "Apple Calendar access has not been granted.",
|
|
266
|
+
]
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private func nativeError(_ message: String) -> [String: Any] {
|
|
270
|
+
[
|
|
271
|
+
"ok": false,
|
|
272
|
+
"error": "native_error",
|
|
273
|
+
"message": message,
|
|
274
|
+
]
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private func nonEmptyString(_ value: String?) -> String? {
|
|
278
|
+
guard let trimmed = value?.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
279
|
+
!trimmed.isEmpty
|
|
280
|
+
else {
|
|
281
|
+
return nil
|
|
282
|
+
}
|
|
283
|
+
return trimmed
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private func parseDate(_ value: String) -> Date? {
|
|
287
|
+
guard !value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
|
|
288
|
+
return nil
|
|
289
|
+
}
|
|
290
|
+
if let date = isoWithFractionalSeconds.date(from: value) {
|
|
291
|
+
return date
|
|
292
|
+
}
|
|
293
|
+
return isoWithoutFractionalSeconds.date(from: value)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
private func textValue(
|
|
297
|
+
_ call: CAPPluginCall,
|
|
298
|
+
key: String,
|
|
299
|
+
maxLength: Int,
|
|
300
|
+
required: Bool
|
|
301
|
+
) -> (value: String?, error: [String: Any]?) {
|
|
302
|
+
let rawValue = call.options[key]
|
|
303
|
+
if rawValue == nil || rawValue is NSNull {
|
|
304
|
+
if required {
|
|
305
|
+
return (nil, nativeError("Calendar event \(key) is required."))
|
|
306
|
+
}
|
|
307
|
+
return (nil, nil)
|
|
308
|
+
}
|
|
309
|
+
guard rawValue is String else {
|
|
310
|
+
return (nil, nativeError("Calendar event \(key) must be a string."))
|
|
311
|
+
}
|
|
312
|
+
guard let value = call.getString(key) else {
|
|
313
|
+
if required {
|
|
314
|
+
return (nil, nativeError("Calendar event \(key) is required."))
|
|
315
|
+
}
|
|
316
|
+
return (nil, nil)
|
|
317
|
+
}
|
|
318
|
+
guard value.count <= maxLength else {
|
|
319
|
+
return (nil, nativeError("Calendar event \(key) is too long."))
|
|
320
|
+
}
|
|
321
|
+
return (value, nil)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
private func isoString(_ date: Date?) -> String {
|
|
325
|
+
guard let date else { return "" }
|
|
326
|
+
return isoWithFractionalSeconds.string(from: date)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
private func calendar(withIdentifier identifier: String, requireWritable: Bool) -> EKCalendar? {
|
|
330
|
+
if identifier.isEmpty || identifier == "primary" {
|
|
331
|
+
if let calendar = eventStore.defaultCalendarForNewEvents,
|
|
332
|
+
!requireWritable || calendar.allowsContentModifications
|
|
333
|
+
{
|
|
334
|
+
return calendar
|
|
335
|
+
}
|
|
336
|
+
if requireWritable {
|
|
337
|
+
return eventStore.calendars(for: .event)
|
|
338
|
+
.first(where: { $0.allowsContentModifications })
|
|
339
|
+
}
|
|
340
|
+
return eventStore.defaultCalendarForNewEvents
|
|
341
|
+
}
|
|
342
|
+
guard let calendar = eventStore.calendars(for: .event)
|
|
343
|
+
.first(where: { $0.calendarIdentifier == identifier })
|
|
344
|
+
else {
|
|
345
|
+
return nil
|
|
346
|
+
}
|
|
347
|
+
if requireWritable && !calendar.allowsContentModifications {
|
|
348
|
+
return nil
|
|
349
|
+
}
|
|
350
|
+
return calendar
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
private func calendarJson(_ calendar: EKCalendar, defaultCalendar: EKCalendar?) -> [String: Any] {
|
|
354
|
+
let color = UIColor(cgColor: calendar.cgColor)
|
|
355
|
+
let components = color.resolvedColor(with: UITraitCollection.current).cgColor.components ?? []
|
|
356
|
+
let red = components.indices.contains(0) ? components[0] : 0
|
|
357
|
+
let green = components.indices.contains(1) ? components[1] : red
|
|
358
|
+
let blue = components.indices.contains(2) ? components[2] : red
|
|
359
|
+
let hex = String(
|
|
360
|
+
format: "#%02X%02X%02X",
|
|
361
|
+
Int(max(0, min(1, red)) * 255),
|
|
362
|
+
Int(max(0, min(1, green)) * 255),
|
|
363
|
+
Int(max(0, min(1, blue)) * 255)
|
|
364
|
+
)
|
|
365
|
+
return [
|
|
366
|
+
"calendarId": calendar.calendarIdentifier,
|
|
367
|
+
"summary": calendar.title,
|
|
368
|
+
"description": calendar.source.title,
|
|
369
|
+
"primary": calendar.calendarIdentifier == defaultCalendar?.calendarIdentifier,
|
|
370
|
+
"accessRole": calendar.allowsContentModifications ? "writer" : "reader",
|
|
371
|
+
"backgroundColor": hex,
|
|
372
|
+
"foregroundColor": NSNull(),
|
|
373
|
+
"timeZone": TimeZone.current.identifier,
|
|
374
|
+
"selected": true,
|
|
375
|
+
]
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
private func participantEmail(_ participant: EKParticipant) -> String? {
|
|
379
|
+
guard participant.url.scheme?.lowercased() == "mailto" else {
|
|
380
|
+
return nil
|
|
381
|
+
}
|
|
382
|
+
let raw = participant.url.absoluteString
|
|
383
|
+
let prefix = "mailto:"
|
|
384
|
+
guard raw.lowercased().hasPrefix(prefix) else {
|
|
385
|
+
return nil
|
|
386
|
+
}
|
|
387
|
+
let address = String(raw.dropFirst(prefix.count))
|
|
388
|
+
return address.removingPercentEncoding ?? address
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
private func participantStatus(_ status: EKParticipantStatus) -> String {
|
|
392
|
+
switch status {
|
|
393
|
+
case .unknown: return "unknown"
|
|
394
|
+
case .pending: return "pending"
|
|
395
|
+
case .accepted: return "accepted"
|
|
396
|
+
case .declined: return "declined"
|
|
397
|
+
case .tentative: return "tentative"
|
|
398
|
+
case .delegated: return "delegated"
|
|
399
|
+
case .completed: return "completed"
|
|
400
|
+
case .inProcess: return "in_process"
|
|
401
|
+
@unknown default: return "unknown"
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
private func participantJson(_ participant: EKParticipant) -> [String: Any] {
|
|
406
|
+
[
|
|
407
|
+
"email": participantEmail(participant) ?? NSNull(),
|
|
408
|
+
"displayName": participant.name ?? NSNull(),
|
|
409
|
+
"responseStatus": participantStatus(participant.participantStatus),
|
|
410
|
+
"self": participant.isCurrentUser,
|
|
411
|
+
"organizer": participant.participantRole == .chair,
|
|
412
|
+
"optional": participant.participantRole == .optional,
|
|
413
|
+
]
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
private func eventStatus(_ status: EKEventStatus) -> String {
|
|
417
|
+
switch status {
|
|
418
|
+
case .none: return "none"
|
|
419
|
+
case .confirmed: return "confirmed"
|
|
420
|
+
case .tentative: return "tentative"
|
|
421
|
+
case .canceled: return "cancelled"
|
|
422
|
+
@unknown default: return "unknown"
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
private func eventJson(_ event: EKEvent) -> [String: Any] {
|
|
427
|
+
let identifier = event.calendarItemIdentifier
|
|
428
|
+
return [
|
|
429
|
+
"id": identifier,
|
|
430
|
+
"externalId": identifier,
|
|
431
|
+
"calendarId": event.calendar.calendarIdentifier,
|
|
432
|
+
"calendarSummary": event.calendar.title,
|
|
433
|
+
"title": event.title?.isEmpty == false ? event.title as Any : "(untitled)",
|
|
434
|
+
"description": event.notes ?? "",
|
|
435
|
+
"location": event.location ?? "",
|
|
436
|
+
"status": eventStatus(event.status),
|
|
437
|
+
"startAt": isoString(event.startDate),
|
|
438
|
+
"endAt": isoString(event.endDate),
|
|
439
|
+
"isAllDay": event.isAllDay,
|
|
440
|
+
"timezone": event.timeZone?.identifier ?? NSNull(),
|
|
441
|
+
"htmlLink": NSNull(),
|
|
442
|
+
"conferenceLink": NSNull(),
|
|
443
|
+
"organizer": event.organizer.map(participantJson) ?? NSNull(),
|
|
444
|
+
"attendees": event.attendees?.map(participantJson) ?? [],
|
|
445
|
+
]
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
private func applyEventPayload(
|
|
449
|
+
_ call: CAPPluginCall,
|
|
450
|
+
to event: EKEvent,
|
|
451
|
+
requireTitle: Bool
|
|
452
|
+
) -> [String: Any]? {
|
|
453
|
+
for key in unsupportedRecurrenceFields where call.options.keys.contains(key) {
|
|
454
|
+
return [
|
|
455
|
+
"ok": false,
|
|
456
|
+
"error": "unsupported_feature",
|
|
457
|
+
"message": "Apple Calendar recurrence editing is not supported by this bridge.",
|
|
458
|
+
]
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if call.options.keys.contains("attendees") {
|
|
462
|
+
guard let attendees = call.options["attendees"] as? [Any] else {
|
|
463
|
+
return nativeError("Calendar event attendees must be an array.")
|
|
464
|
+
}
|
|
465
|
+
if !attendees.isEmpty {
|
|
466
|
+
return [
|
|
467
|
+
"ok": false,
|
|
468
|
+
"error": "unsupported_feature",
|
|
469
|
+
"message": "Apple Calendar does not allow this app to create or edit event invitees through EventKit. Remove attendees or use Google Calendar for invited meetings.",
|
|
470
|
+
]
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if call.options.keys.contains("title") || requireTitle {
|
|
475
|
+
let titleResult = textValue(
|
|
476
|
+
call,
|
|
477
|
+
key: "title",
|
|
478
|
+
maxLength: maxTitleLength,
|
|
479
|
+
required: true
|
|
480
|
+
)
|
|
481
|
+
if let error = titleResult.error {
|
|
482
|
+
return error
|
|
483
|
+
}
|
|
484
|
+
guard let title = nonEmptyString(titleResult.value) else {
|
|
485
|
+
return nativeError("Calendar event title is required.")
|
|
486
|
+
}
|
|
487
|
+
event.title = title
|
|
488
|
+
}
|
|
489
|
+
if call.options.keys.contains("description") {
|
|
490
|
+
let descriptionResult = textValue(
|
|
491
|
+
call,
|
|
492
|
+
key: "description",
|
|
493
|
+
maxLength: maxDescriptionLength,
|
|
494
|
+
required: false
|
|
495
|
+
)
|
|
496
|
+
if let error = descriptionResult.error {
|
|
497
|
+
return error
|
|
498
|
+
}
|
|
499
|
+
event.notes = descriptionResult.value
|
|
500
|
+
}
|
|
501
|
+
if call.options.keys.contains("location") {
|
|
502
|
+
let locationResult = textValue(
|
|
503
|
+
call,
|
|
504
|
+
key: "location",
|
|
505
|
+
maxLength: maxLocationLength,
|
|
506
|
+
required: false
|
|
507
|
+
)
|
|
508
|
+
if let error = locationResult.error {
|
|
509
|
+
return error
|
|
510
|
+
}
|
|
511
|
+
event.location = locationResult.value
|
|
512
|
+
}
|
|
513
|
+
if call.options.keys.contains("timeZone") {
|
|
514
|
+
guard let timeZoneName = nonEmptyString(call.getString("timeZone")) else {
|
|
515
|
+
return nativeError("Calendar event timeZone is invalid.")
|
|
516
|
+
}
|
|
517
|
+
guard let timeZone = TimeZone(identifier: timeZoneName) else {
|
|
518
|
+
return nativeError("Calendar event timeZone is invalid.")
|
|
519
|
+
}
|
|
520
|
+
event.timeZone = timeZone
|
|
521
|
+
}
|
|
522
|
+
if call.options.keys.contains("calendarId") {
|
|
523
|
+
guard let calendar = calendar(
|
|
524
|
+
withIdentifier: call.getString("calendarId") ?? "",
|
|
525
|
+
requireWritable: true
|
|
526
|
+
) else {
|
|
527
|
+
return nativeError("The selected Apple Calendar is not writable or was not found.")
|
|
528
|
+
}
|
|
529
|
+
event.calendar = calendar
|
|
530
|
+
}
|
|
531
|
+
if call.options.keys.contains("isAllDay") {
|
|
532
|
+
event.isAllDay = call.getBool("isAllDay") ?? false
|
|
533
|
+
}
|
|
534
|
+
if call.options.keys.contains("startAt") {
|
|
535
|
+
guard let start = parseDate(call.getString("startAt") ?? "") else {
|
|
536
|
+
return nativeError("Calendar event startAt is invalid.")
|
|
537
|
+
}
|
|
538
|
+
event.startDate = start
|
|
539
|
+
}
|
|
540
|
+
if call.options.keys.contains("endAt") {
|
|
541
|
+
guard let end = parseDate(call.getString("endAt") ?? "") else {
|
|
542
|
+
return nativeError("Calendar event endAt is invalid.")
|
|
543
|
+
}
|
|
544
|
+
event.endDate = end
|
|
545
|
+
}
|
|
546
|
+
guard event.startDate != nil, event.endDate != nil else {
|
|
547
|
+
return nativeError("Calendar event startAt and endAt are required.")
|
|
548
|
+
}
|
|
549
|
+
guard event.endDate > event.startDate else {
|
|
550
|
+
return nativeError("Calendar event endAt must be later than startAt.")
|
|
551
|
+
}
|
|
552
|
+
if event.calendar == nil {
|
|
553
|
+
guard let calendar = calendar(withIdentifier: "primary", requireWritable: true) else {
|
|
554
|
+
return nativeError("No writable Apple Calendar is available.")
|
|
555
|
+
}
|
|
556
|
+
event.calendar = calendar
|
|
557
|
+
}
|
|
558
|
+
return nil
|
|
559
|
+
}
|
|
560
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elizaos/capacitor-calendar",
|
|
3
|
+
"version": "2.0.11-beta.7",
|
|
4
|
+
"description": "Reads and writes Apple Calendar events through EventKit.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"calendar",
|
|
7
|
+
"eventkit",
|
|
8
|
+
"ios",
|
|
9
|
+
"permissions"
|
|
10
|
+
],
|
|
11
|
+
"main": "./dist/plugin.cjs.js",
|
|
12
|
+
"module": "./dist/esm/index.js",
|
|
13
|
+
"types": "./dist/esm/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/esm/index.d.ts",
|
|
17
|
+
"bun": "./src/index.ts",
|
|
18
|
+
"development": "./src/index.ts",
|
|
19
|
+
"import": "./dist/esm/index.js",
|
|
20
|
+
"require": "./dist/plugin.cjs.js"
|
|
21
|
+
},
|
|
22
|
+
"./package.json": "./package.json"
|
|
23
|
+
},
|
|
24
|
+
"unpkg": "dist/plugin.js",
|
|
25
|
+
"files": [
|
|
26
|
+
"dist/",
|
|
27
|
+
"ios/Sources/",
|
|
28
|
+
"*.podspec",
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"author": "elizaOS",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/elizaOS/eliza.git"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "node ../../packages/scripts/with-package-build-lock.mjs plugins/plugin-native-calendar -- bun run build:unlocked",
|
|
39
|
+
"clean": "node ../../packages/scripts/rm-path-recursive.mjs dist",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"prepublishOnly": "bun run build",
|
|
42
|
+
"build:unlocked": "bun run clean && tsc && bunx rollup -c rollup.config.mjs"
|
|
43
|
+
},
|
|
44
|
+
"capacitor": {
|
|
45
|
+
"ios": {
|
|
46
|
+
"src": "ios",
|
|
47
|
+
"podName": "ElizaosCapacitorCalendar"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@capacitor/core": "^8.3.1",
|
|
52
|
+
"rollup": "^4.60.2",
|
|
53
|
+
"typescript": "^6.0.3"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"@capacitor/core": "^8.3.1"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
},
|
|
61
|
+
"elizaos": {
|
|
62
|
+
"platforms": [
|
|
63
|
+
"browser",
|
|
64
|
+
"node"
|
|
65
|
+
],
|
|
66
|
+
"runtime": "both",
|
|
67
|
+
"platformDetails": {
|
|
68
|
+
"browser": "Graceful unsupported fallback.",
|
|
69
|
+
"ios": true,
|
|
70
|
+
"node": "macOS uses the Electrobun EventKit dylib instead."
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"gitHead": "cdbc876f793d96073d7eb0d09715a031ce0cd32e"
|
|
74
|
+
}
|