@laylzj777/my-apple-apple-eventkit 1.1.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 (123) hide show
  1. package/CHANGELOG.md +575 -0
  2. package/LICENSE +21 -0
  3. package/README.md +304 -0
  4. package/README.zh-CN.md +270 -0
  5. package/bin/event +0 -0
  6. package/bin/event-disclaim +0 -0
  7. package/dist/bin/apple-calendar.d.ts +6 -0
  8. package/dist/bin/apple-calendar.js +8 -0
  9. package/dist/bin/apple-calendar.js.map +1 -0
  10. package/dist/bin/apple-reminders.d.ts +7 -0
  11. package/dist/bin/apple-reminders.js +9 -0
  12. package/dist/bin/apple-reminders.js.map +1 -0
  13. package/dist/bootstrap.d.ts +11 -0
  14. package/dist/bootstrap.js +44 -0
  15. package/dist/bootstrap.js.map +1 -0
  16. package/dist/index.d.ts +10 -0
  17. package/dist/index.js +12 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/server/handlers.d.ts +12 -0
  20. package/dist/server/handlers.js +58 -0
  21. package/dist/server/handlers.js.map +1 -0
  22. package/dist/server/mode.d.ts +19 -0
  23. package/dist/server/mode.js +47 -0
  24. package/dist/server/mode.js.map +1 -0
  25. package/dist/server/promptAbstractions.d.ts +61 -0
  26. package/dist/server/promptAbstractions.js +140 -0
  27. package/dist/server/promptAbstractions.js.map +1 -0
  28. package/dist/server/prompts.d.ts +13 -0
  29. package/dist/server/prompts.js +461 -0
  30. package/dist/server/prompts.js.map +1 -0
  31. package/dist/server/server.d.ts +61 -0
  32. package/dist/server/server.js +112 -0
  33. package/dist/server/server.js.map +1 -0
  34. package/dist/tools/definitions.d.ts +9 -0
  35. package/dist/tools/definitions.js +272 -0
  36. package/dist/tools/definitions.js.map +1 -0
  37. package/dist/tools/handlers/calendarHandlers.d.ts +11 -0
  38. package/dist/tools/handlers/calendarHandlers.js +151 -0
  39. package/dist/tools/handlers/calendarHandlers.js.map +1 -0
  40. package/dist/tools/handlers/formatters.d.ts +24 -0
  41. package/dist/tools/handlers/formatters.js +105 -0
  42. package/dist/tools/handlers/formatters.js.map +1 -0
  43. package/dist/tools/handlers/index.d.ts +8 -0
  44. package/dist/tools/handlers/index.js +9 -0
  45. package/dist/tools/handlers/index.js.map +1 -0
  46. package/dist/tools/handlers/listHandlers.d.ts +10 -0
  47. package/dist/tools/handlers/listHandlers.js +47 -0
  48. package/dist/tools/handlers/listHandlers.js.map +1 -0
  49. package/dist/tools/handlers/reminderHandlers.d.ts +10 -0
  50. package/dist/tools/handlers/reminderHandlers.js +219 -0
  51. package/dist/tools/handlers/reminderHandlers.js.map +1 -0
  52. package/dist/tools/handlers/shared.d.ts +28 -0
  53. package/dist/tools/handlers/shared.js +57 -0
  54. package/dist/tools/handlers/shared.js.map +1 -0
  55. package/dist/tools/handlers/subtaskHandlers.d.ts +12 -0
  56. package/dist/tools/handlers/subtaskHandlers.js +113 -0
  57. package/dist/tools/handlers/subtaskHandlers.js.map +1 -0
  58. package/dist/tools/index.d.ts +10 -0
  59. package/dist/tools/index.js +74 -0
  60. package/dist/tools/index.js.map +1 -0
  61. package/dist/types/index.d.ts +263 -0
  62. package/dist/types/index.js +42 -0
  63. package/dist/types/index.js.map +1 -0
  64. package/dist/types/prompts.d.ts +88 -0
  65. package/dist/types/prompts.js +6 -0
  66. package/dist/types/prompts.js.map +1 -0
  67. package/dist/types/repository.d.ts +197 -0
  68. package/dist/types/repository.js +14 -0
  69. package/dist/types/repository.js.map +1 -0
  70. package/dist/utils/binaryValidator.d.ts +52 -0
  71. package/dist/utils/binaryValidator.js +185 -0
  72. package/dist/utils/binaryValidator.js.map +1 -0
  73. package/dist/utils/calendarRepository.d.ts +49 -0
  74. package/dist/utils/calendarRepository.js +226 -0
  75. package/dist/utils/calendarRepository.js.map +1 -0
  76. package/dist/utils/constants.d.ts +79 -0
  77. package/dist/utils/constants.js +80 -0
  78. package/dist/utils/constants.js.map +1 -0
  79. package/dist/utils/dateFiltering.d.ts +41 -0
  80. package/dist/utils/dateFiltering.js +129 -0
  81. package/dist/utils/dateFiltering.js.map +1 -0
  82. package/dist/utils/dateUtils.d.ts +27 -0
  83. package/dist/utils/dateUtils.js +71 -0
  84. package/dist/utils/dateUtils.js.map +1 -0
  85. package/dist/utils/errorHandling.d.ts +27 -0
  86. package/dist/utils/errorHandling.js +88 -0
  87. package/dist/utils/errorHandling.js.map +1 -0
  88. package/dist/utils/eventCli.d.ts +40 -0
  89. package/dist/utils/eventCli.js +294 -0
  90. package/dist/utils/eventCli.js.map +1 -0
  91. package/dist/utils/helpers.d.ts +35 -0
  92. package/dist/utils/helpers.js +61 -0
  93. package/dist/utils/helpers.js.map +1 -0
  94. package/dist/utils/looseDateParser.d.ts +19 -0
  95. package/dist/utils/looseDateParser.js +149 -0
  96. package/dist/utils/looseDateParser.js.map +1 -0
  97. package/dist/utils/projectUtils.d.ts +13 -0
  98. package/dist/utils/projectUtils.js +92 -0
  99. package/dist/utils/projectUtils.js.map +1 -0
  100. package/dist/utils/reminderDateParser.d.ts +8 -0
  101. package/dist/utils/reminderDateParser.js +89 -0
  102. package/dist/utils/reminderDateParser.js.map +1 -0
  103. package/dist/utils/reminderRepository.d.ts +33 -0
  104. package/dist/utils/reminderRepository.js +262 -0
  105. package/dist/utils/reminderRepository.js.map +1 -0
  106. package/dist/utils/subtaskUtils.d.ts +103 -0
  107. package/dist/utils/subtaskUtils.js +253 -0
  108. package/dist/utils/subtaskUtils.js.map +1 -0
  109. package/dist/utils/tagUtils.d.ts +58 -0
  110. package/dist/utils/tagUtils.js +177 -0
  111. package/dist/utils/tagUtils.js.map +1 -0
  112. package/dist/utils/timeHelpers.d.ts +40 -0
  113. package/dist/utils/timeHelpers.js +136 -0
  114. package/dist/utils/timeHelpers.js.map +1 -0
  115. package/dist/validation/schemas.d.ts +385 -0
  116. package/dist/validation/schemas.js +579 -0
  117. package/dist/validation/schemas.js.map +1 -0
  118. package/package.json +96 -0
  119. package/scripts/build-event.mjs +513 -0
  120. package/scripts/disclaim.c +69 -0
  121. package/scripts/event-Info.plist +29 -0
  122. package/scripts/event.entitlements +10 -0
  123. package/scripts/postinstall.mjs +91 -0
@@ -0,0 +1,41 @@
1
+ /**
2
+ * dateFiltering.ts
3
+ * Reusable utilities for filtering reminders by date criteria
4
+ */
5
+ import type { Reminder } from '../types/index.js';
6
+ import type { ReminderJSON } from '../types/repository.js';
7
+ /**
8
+ * Date range filters for reminders
9
+ */
10
+ export type DateFilter = 'today' | 'tomorrow' | 'this-week' | 'overdue' | 'no-date';
11
+ /**
12
+ * Priority filter values (string names that map to EventKit integers)
13
+ */
14
+ export type PriorityFilter = 'high' | 'medium' | 'low' | 'none';
15
+ /**
16
+ * Filters for reminder search operations
17
+ */
18
+ export interface ReminderFilters {
19
+ showCompleted?: boolean;
20
+ search?: string;
21
+ dueWithin?: DateFilter;
22
+ list?: string;
23
+ priority?: PriorityFilter;
24
+ recurring?: boolean;
25
+ locationBased?: boolean;
26
+ tags?: string[];
27
+ }
28
+ /**
29
+ * Narrows the raw `event` JSON response by the filter predicates that don't
30
+ * require `mapReminder`'s notes-field regex scans. Used by the repository to
31
+ * skip mapping reminders that the caller will discard anyway.
32
+ *
33
+ * Notes-dependent filters (tags, full-text search) and date-window filters
34
+ * stay in {@link applyReminderFilters} for now — date parsing per reminder is
35
+ * not free, and tag filtering needs the mapped form.
36
+ */
37
+ export declare function prefilterReminderJsons(reminders: ReminderJSON[], filters: ReminderFilters): ReminderJSON[];
38
+ /**
39
+ * Applies multiple filters to a list of reminders
40
+ */
41
+ export declare function applyReminderFilters(reminders: Reminder[], filters: ReminderFilters): Reminder[];
@@ -0,0 +1,129 @@
1
+ /**
2
+ * dateFiltering.ts
3
+ * Reusable utilities for filtering reminders by date criteria
4
+ */
5
+ import { getTodayStart, getTomorrowStart, getWeekEnd, getWeekStart, } from './dateUtils.js';
6
+ import { parseReminderDueDate } from './reminderDateParser.js';
7
+ import { hasAllTags } from './tagUtils.js';
8
+ /**
9
+ * Creates standardized date boundaries for filtering operations
10
+ */
11
+ function createDateBoundaries() {
12
+ const today = getTodayStart();
13
+ const tomorrow = getTomorrowStart();
14
+ const dayAfterTomorrow = getTomorrowStart();
15
+ dayAfterTomorrow.setDate(dayAfterTomorrow.getDate() + 1);
16
+ const weekStart = getWeekStart();
17
+ const weekEnd = getWeekEnd();
18
+ return { today, tomorrow, dayAfterTomorrow, weekStart, weekEnd };
19
+ }
20
+ /**
21
+ * Filters reminders based on due date criteria
22
+ */
23
+ function filterRemindersByDate(reminders, filter) {
24
+ if (filter === 'no-date') {
25
+ return reminders.filter((reminder) => !reminder.dueDate);
26
+ }
27
+ const { today, tomorrow, dayAfterTomorrow, weekStart, weekEnd } = createDateBoundaries();
28
+ return reminders.filter((reminder) => {
29
+ if (!reminder.dueDate)
30
+ return false;
31
+ const dueDate = parseReminderDueDate(reminder.dueDate);
32
+ if (!dueDate)
33
+ return false;
34
+ switch (filter) {
35
+ case 'overdue':
36
+ return dueDate.getTime() < today.getTime();
37
+ case 'today':
38
+ return (dueDate.getTime() >= today.getTime() &&
39
+ dueDate.getTime() < tomorrow.getTime());
40
+ case 'tomorrow':
41
+ return (dueDate.getTime() >= tomorrow.getTime() &&
42
+ dueDate.getTime() < dayAfterTomorrow.getTime());
43
+ case 'this-week':
44
+ return (dueDate.getTime() >= weekStart.getTime() &&
45
+ dueDate.getTime() < weekEnd.getTime());
46
+ default:
47
+ return true;
48
+ }
49
+ });
50
+ }
51
+ /**
52
+ * Maps priority filter strings to EventKit integer values
53
+ */
54
+ const PRIORITY_FILTER_MAP = {
55
+ none: 0,
56
+ high: 1,
57
+ medium: 5,
58
+ low: 9,
59
+ };
60
+ /**
61
+ * Narrows the raw `event` JSON response by the filter predicates that don't
62
+ * require `mapReminder`'s notes-field regex scans. Used by the repository to
63
+ * skip mapping reminders that the caller will discard anyway.
64
+ *
65
+ * Notes-dependent filters (tags, full-text search) and date-window filters
66
+ * stay in {@link applyReminderFilters} for now — date parsing per reminder is
67
+ * not free, and tag filtering needs the mapped form.
68
+ */
69
+ export function prefilterReminderJsons(reminders, filters) {
70
+ let result = reminders;
71
+ if (filters.priority) {
72
+ const target = PRIORITY_FILTER_MAP[filters.priority];
73
+ result = result.filter((reminder) => reminder.priority === target);
74
+ }
75
+ if (filters.recurring) {
76
+ result = result.filter((reminder) => (reminder.recurrenceRules?.length ?? 0) > 0);
77
+ }
78
+ if (filters.locationBased) {
79
+ result = result.filter((reminder) => reminder.locationTrigger != null ||
80
+ (reminder.alarms?.some((alarm) => alarm?.locationTrigger != null &&
81
+ alarm.locationTrigger.proximity !== 'none') ??
82
+ false));
83
+ }
84
+ return result;
85
+ }
86
+ /**
87
+ * Applies multiple filters to a list of reminders
88
+ */
89
+ export function applyReminderFilters(reminders, filters) {
90
+ let filteredReminders = [...reminders];
91
+ // Filter by completion status
92
+ if (filters.showCompleted !== undefined) {
93
+ filteredReminders = filteredReminders.filter((reminder) => filters.showCompleted || !reminder.isCompleted);
94
+ }
95
+ // Filter by list
96
+ if (filters.list) {
97
+ filteredReminders = filteredReminders.filter((reminder) => reminder.list === filters.list);
98
+ }
99
+ // Filter by search term
100
+ if (filters.search) {
101
+ const searchLower = filters.search.toLowerCase();
102
+ filteredReminders = filteredReminders.filter((reminder) => reminder.title.toLowerCase().includes(searchLower) ||
103
+ reminder.notes?.toLowerCase().includes(searchLower));
104
+ }
105
+ // Filter by due date
106
+ if (filters.dueWithin) {
107
+ filteredReminders = filterRemindersByDate(filteredReminders, filters.dueWithin);
108
+ }
109
+ // Filter by priority
110
+ if (filters.priority) {
111
+ const priorityValue = PRIORITY_FILTER_MAP[filters.priority];
112
+ filteredReminders = filteredReminders.filter((reminder) => reminder.priority === priorityValue);
113
+ }
114
+ // Filter by recurring status
115
+ if (filters.recurring !== undefined && filters.recurring) {
116
+ filteredReminders = filteredReminders.filter((reminder) => (reminder.recurrenceRules?.length ?? 0) > 0);
117
+ }
118
+ // Filter by location-based status
119
+ if (filters.locationBased !== undefined && filters.locationBased) {
120
+ filteredReminders = filteredReminders.filter((reminder) => reminder.locationTrigger !== undefined);
121
+ }
122
+ // Filter by tags (must have ALL specified tags)
123
+ if (filters.tags && filters.tags.length > 0) {
124
+ const { tags } = filters;
125
+ filteredReminders = filteredReminders.filter((reminder) => hasAllTags(reminder.tags, tags));
126
+ }
127
+ return filteredReminders;
128
+ }
129
+ //# sourceMappingURL=dateFiltering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dateFiltering.js","sourceRoot":"","sources":["../../src/utils/dateFiltering.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * dateUtils.ts
3
+ * Shared date calculation utilities
4
+ */
5
+ /**
6
+ * Creates a date object representing the start of today (midnight)
7
+ */
8
+ export declare function getTodayStart(): Date;
9
+ /**
10
+ * Creates a date object representing the start of tomorrow (midnight)
11
+ */
12
+ export declare function getTomorrowStart(): Date;
13
+ /**
14
+ * Creates a date object representing the start of the current calendar week.
15
+ * Uses Intl.Locale.weekInfo for locale-aware week start when available.
16
+ * Falls back to Sunday for environments without Intl.Locale support.
17
+ */
18
+ export declare function getWeekStart(): Date;
19
+ /**
20
+ * Creates a date object representing the end of the current calendar week
21
+ * (start of next week). Matches Swift's Calendar.current.dateInterval(of: .weekOfYear).
22
+ */
23
+ export declare function getWeekEnd(): Date;
24
+ /**
25
+ * Creates a date object representing the start of a specific date (midnight)
26
+ */
27
+ export declare function getDateStart(date: Date): Date;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * dateUtils.ts
3
+ * Shared date calculation utilities
4
+ */
5
+ /**
6
+ * Creates a date object representing the start of today (midnight)
7
+ */
8
+ export function getTodayStart() {
9
+ const now = new Date();
10
+ return new Date(now.getFullYear(), now.getMonth(), now.getDate());
11
+ }
12
+ /**
13
+ * Creates a date object representing the start of tomorrow (midnight)
14
+ */
15
+ export function getTomorrowStart() {
16
+ const today = getTodayStart();
17
+ const tomorrow = new Date(today);
18
+ tomorrow.setDate(tomorrow.getDate() + 1);
19
+ return tomorrow;
20
+ }
21
+ /**
22
+ * Gets the first day of the week for the current locale using Intl.Locale API.
23
+ * @returns 0-6 where 0=Sunday, 1=Monday, ..., 6=Saturday
24
+ */
25
+ function getLocaleFirstDay() {
26
+ try {
27
+ // Get the default locale from the system
28
+ const defaultLocale = Intl.DateTimeFormat().resolvedOptions().locale || 'en-US';
29
+ const locale = new Intl.Locale(defaultLocale);
30
+ const weekInfo = locale.weekInfo;
31
+ if (weekInfo?.firstDay !== undefined) {
32
+ // Intl returns 1-7 where 1=Monday, 7=Sunday
33
+ // Convert to JS format 0-6 where 0=Sunday
34
+ return weekInfo.firstDay === 7 ? 0 : weekInfo.firstDay;
35
+ }
36
+ }
37
+ catch {
38
+ // Fallback to Sunday if Intl.Locale is unavailable
39
+ }
40
+ return 0; // Default: Sunday
41
+ }
42
+ /**
43
+ * Creates a date object representing the start of the current calendar week.
44
+ * Uses Intl.Locale.weekInfo for locale-aware week start when available.
45
+ * Falls back to Sunday for environments without Intl.Locale support.
46
+ */
47
+ export function getWeekStart() {
48
+ const today = getTodayStart();
49
+ const dayOfWeek = today.getDay(); // 0=Sunday, 6=Saturday
50
+ const firstDay = getLocaleFirstDay();
51
+ const weekStart = new Date(today);
52
+ weekStart.setDate(today.getDate() - ((dayOfWeek - firstDay + 7) % 7));
53
+ return weekStart;
54
+ }
55
+ /**
56
+ * Creates a date object representing the end of the current calendar week
57
+ * (start of next week). Matches Swift's Calendar.current.dateInterval(of: .weekOfYear).
58
+ */
59
+ export function getWeekEnd() {
60
+ const weekStart = getWeekStart();
61
+ const weekEnd = new Date(weekStart);
62
+ weekEnd.setDate(weekStart.getDate() + 7);
63
+ return weekEnd;
64
+ }
65
+ /**
66
+ * Creates a date object representing the start of a specific date (midnight)
67
+ */
68
+ export function getDateStart(date) {
69
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
70
+ }
71
+ //# sourceMappingURL=dateUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dateUtils.js","sourceRoot":"","sources":["../../src/utils/dateUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;AACpE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACzC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB;IACxB,IAAI,CAAC;QACH,yCAAyC;QACzC,MAAM,aAAa,GACjB,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,MAAM,IAAI,OAAO,CAAC;QAC5D,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC9C,MAAM,QAAQ,GACZ,MACD,CAAC,QAAQ,CAAC;QACX,IAAI,QAAQ,EAAE,QAAQ,KAAK,SAAS,EAAE,CAAC;YACrC,4CAA4C;YAC5C,0CAA0C;YAC1C,OAAO,QAAQ,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACzD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,mDAAmD;IACrD,CAAC;IACD,OAAO,CAAC,CAAC,CAAC,kBAAkB;AAC9B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,uBAAuB;IACzD,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,SAAS,GAAG,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACtE,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;IACpC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACzC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;AACvE,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * errorHandling.ts
3
+ * Centralized error handling utilities for consistent error responses
4
+ */
5
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
6
+ /**
7
+ * Custom error class for user-facing CLI failures (e.g., not found, invalid
8
+ * input). Lives in this leaf module so it's importable from both repository
9
+ * and handler layers without circular imports.
10
+ */
11
+ export declare class CliUserError extends Error {
12
+ constructor(message: string);
13
+ }
14
+ /**
15
+ * Determines if the application is running in development mode.
16
+ * Development mode is enabled when:
17
+ * - NODE_ENV is set to 'development', OR
18
+ * - DEBUG environment variable is set to any truthy value
19
+ *
20
+ * This allows detailed error messages to be shown in development
21
+ * while keeping production error messages generic for security.
22
+ */
23
+ export declare function isDevelopmentMode(): boolean;
24
+ /**
25
+ * Utility for handling async operations with consistent error handling
26
+ */
27
+ export declare function handleAsyncOperation(operation: () => Promise<string>, operationName: string): Promise<CallToolResult>;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * errorHandling.ts
3
+ * Centralized error handling utilities for consistent error responses
4
+ */
5
+ import { ValidationError } from '../validation/schemas.js';
6
+ const USER_ACTIONABLE_PERMISSION_PATTERNS = [
7
+ /permission denied/i,
8
+ /permission is write-only/i,
9
+ /access denied/i,
10
+ /not authorized.*(calendar|reminders)/i,
11
+ /System Settings > Privacy & Security/i,
12
+ /full calendar access/i,
13
+ /full reminder access/i,
14
+ // The disclaim shim's own spawn failures (`event-disclaim: …`) are
15
+ // classified upstream in eventCli.ts as CliUserError; no broad
16
+ // subprocess/responsible-process patterns here — they would leak
17
+ // unrelated internal errors past production sanitization.
18
+ ];
19
+ function isUserActionablePermissionError(message) {
20
+ return USER_ACTIONABLE_PERMISSION_PATTERNS.some((pattern) => pattern.test(message));
21
+ }
22
+ /**
23
+ * Custom error class for user-facing CLI failures (e.g., not found, invalid
24
+ * input). Lives in this leaf module so it's importable from both repository
25
+ * and handler layers without circular imports.
26
+ */
27
+ export class CliUserError extends Error {
28
+ constructor(message) {
29
+ super(message);
30
+ this.name = 'CliUserError';
31
+ }
32
+ }
33
+ /**
34
+ * Determines if the application is running in development mode.
35
+ * Development mode is enabled when:
36
+ * - NODE_ENV is set to 'development', OR
37
+ * - DEBUG environment variable is set to any truthy value
38
+ *
39
+ * This allows detailed error messages to be shown in development
40
+ * while keeping production error messages generic for security.
41
+ */
42
+ export function isDevelopmentMode() {
43
+ return (process.env.NODE_ENV === 'development' ||
44
+ (!!process.env.DEBUG && process.env.DEBUG !== ''));
45
+ }
46
+ /**
47
+ * Creates a descriptive error message, showing validation details in dev mode.
48
+ */
49
+ function createErrorMessage(operation, error) {
50
+ const message = error instanceof Error ? error.message : 'System error occurred';
51
+ const isDev = isDevelopmentMode();
52
+ // For validation and CLI user errors, always return the detailed message.
53
+ if (error instanceof ValidationError || error instanceof CliUserError) {
54
+ return message;
55
+ }
56
+ // Permission failures are user-actionable and should stay visible in production.
57
+ if (isUserActionablePermissionError(message)) {
58
+ return `Failed to ${operation}: ${message}`;
59
+ }
60
+ // For other errors, be generic in production.
61
+ return isDev
62
+ ? `Failed to ${operation}: ${message}`
63
+ : `Failed to ${operation}: System error occurred`;
64
+ }
65
+ /**
66
+ * Utility for handling async operations with consistent error handling
67
+ */
68
+ export async function handleAsyncOperation(operation, operationName) {
69
+ try {
70
+ const result = await operation();
71
+ return {
72
+ content: [{ type: 'text', text: result }],
73
+ isError: false,
74
+ };
75
+ }
76
+ catch (error) {
77
+ return {
78
+ content: [
79
+ {
80
+ type: 'text',
81
+ text: createErrorMessage(operationName, error),
82
+ },
83
+ ],
84
+ isError: true,
85
+ };
86
+ }
87
+ }
88
+ //# sourceMappingURL=errorHandling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorHandling.js","sourceRoot":"","sources":["../../src/utils/errorHandling.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE3D,MAAM,mCAAmC,GAAG;IAC1C,oBAAoB;IACpB,2BAA2B;IAC3B,gBAAgB;IAChB,uCAAuC;IACvC,uCAAuC;IACvC,uBAAuB;IACvB,uBAAuB;IACvB,mEAAmE;IACnE,+DAA+D;IAC/D,iEAAiE;IACjE,0DAA0D;CAClD,CAAC;AAEX,SAAS,+BAA+B,CAAC,OAAe;IACtD,OAAO,mCAAmC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAC1D,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CACtB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;QACtC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC,CAClD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,SAAiB,EAAE,KAAc;IAC3D,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;IACnE,MAAM,KAAK,GAAG,iBAAiB,EAAE,CAAC;IAElC,0EAA0E;IAC1E,IAAI,KAAK,YAAY,eAAe,IAAI,KAAK,YAAY,YAAY,EAAE,CAAC;QACtE,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,iFAAiF;IACjF,IAAI,+BAA+B,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,OAAO,aAAa,SAAS,KAAK,OAAO,EAAE,CAAC;IAC9C,CAAC;IAED,8CAA8C;IAC9C,OAAO,KAAK;QACV,CAAC,CAAC,aAAa,SAAS,KAAK,OAAO,EAAE;QACtC,CAAC,CAAC,aAAa,SAAS,yBAAyB,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,SAAgC,EAChC,aAAqB;IAErB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YACzC,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,kBAAkB,CAAC,aAAa,EAAE,KAAK,CAAC;iBAC/C;aACF;YACD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @fileoverview `event` CLI execution wrapper
3
+ * @module utils/eventCli
4
+ * @description Spawns the vendored `event` Swift binary (FradSer/event) and
5
+ * translates its stdout / stderr / exit code into JSON results, plain-text
6
+ * results, or domain-specific errors. `event` outputs raw JSON to stdout and
7
+ * writes `Error: <message>` to stderr with a non-zero exit code on failure.
8
+ */
9
+ /** Clears the cached binary path (for testing). */
10
+ export declare function clearEventBinaryPathCache(): void;
11
+ export type PermissionDomain = 'reminders' | 'calendars';
12
+ /** Custom error class for permission-related failures from the `event` CLI. */
13
+ export declare class CliPermissionError extends Error {
14
+ readonly domain: PermissionDomain;
15
+ constructor(message: string, domain: PermissionDomain);
16
+ }
17
+ /**
18
+ * Executes the `event` binary and parses its stdout as raw JSON.
19
+ *
20
+ * @template T - Expected JSON type emitted by `event`
21
+ * @param args - Full argv (including subcommand and `--json` where supported)
22
+ * @returns Parsed JSON value
23
+ * @throws {CliPermissionError} on EventKit permission failure (domain-typed)
24
+ * @throws {CliUserError} on application errors surfaced by `event` (Not found,
25
+ * Invalid input, ArgumentParser usage errors)
26
+ * @throws {Error} when stdout is empty or unparseable
27
+ *
28
+ * @security
29
+ * - Uses `execFile` (not `exec`) so shell metacharacters in argv are inert.
30
+ * - Argv is passed as an array; each token is delivered to the binary verbatim
31
+ * via `execve()`, preventing argument-boundary injection.
32
+ * - Binary path is validated against an allowlist tied to the project root.
33
+ */
34
+ export declare function executeEventCliJson<T>(args: string[]): Promise<T>;
35
+ /**
36
+ * Executes the `event` binary and returns its trimmed stdout as plain text.
37
+ * Used for commands that emit a success message instead of JSON (e.g.
38
+ * `event reminders delete` returns "Reminder deleted successfully").
39
+ */
40
+ export declare function executeEventCliPlain(args: string[]): Promise<string>;