@forcecalendar/core 2.0.0 → 2.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.
@@ -374,7 +374,7 @@ export class Event {
374
374
  * @returns {boolean} True if event spans multiple days
375
375
  */
376
376
  get isMultiDay() {
377
- if (!this._cache.hasOwnProperty('isMultiDay')) {
377
+ if (!Object.prototype.hasOwnProperty.call(this._cache, 'isMultiDay')) {
378
378
  const startDay = this.start.toDateString();
379
379
  const endDay = this.end.toDateString();
380
380
  this._cache.isMultiDay = startDay !== endDay;
@@ -417,10 +417,10 @@ export class Event {
417
417
  dayEnd.setHours(23, 59, 59, 999);
418
418
 
419
419
  return this.start <= dayEnd && this.end >= dayStart;
420
- } else {
420
+ }
421
421
  // Single day event: check if it's on the same day
422
422
  return startString === dateString;
423
- }
423
+
424
424
  }
425
425
 
426
426
  /**
@@ -436,9 +436,9 @@ export class Event {
436
436
  } else if (otherEvent && otherEvent.start && otherEvent.end) {
437
437
  // Allow checking against time ranges
438
438
  return !(this.end <= otherEvent.start || this.start >= otherEvent.end);
439
- } else {
439
+ }
440
440
  throw new Error('Parameter must be an Event instance or have start/end properties');
441
- }
441
+
442
442
  }
443
443
 
444
444
  /**
@@ -226,12 +226,12 @@ export class EventStore {
226
226
  }
227
227
 
228
228
  // Filter by all-day events
229
- if (filters.hasOwnProperty('allDay')) {
229
+ if (Object.prototype.hasOwnProperty.call(filters, 'allDay')) {
230
230
  results = results.filter(event => event.allDay === filters.allDay);
231
231
  }
232
232
 
233
233
  // Filter by recurring
234
- if (filters.hasOwnProperty('recurring')) {
234
+ if (Object.prototype.hasOwnProperty.call(filters, 'recurring')) {
235
235
  results = results.filter(event => event.recurring === filters.recurring);
236
236
  }
237
237
 
@@ -250,7 +250,7 @@ export class EventStore {
250
250
  }
251
251
 
252
252
  // Filter by having attendees
253
- if (filters.hasOwnProperty('hasAttendees')) {
253
+ if (Object.prototype.hasOwnProperty.call(filters, 'hasAttendees')) {
254
254
  results = results.filter(event => filters.hasAttendees ? event.hasAttendees : !event.hasAttendees);
255
255
  }
256
256
 
@@ -40,7 +40,7 @@ export class RecurrenceEngine {
40
40
  let lastOffset = tzManager.getTimezoneOffset(currentDate, eventTimezone);
41
41
 
42
42
  // Track last date to detect infinite loop (date not advancing)
43
- let lastDateTimestamp = null;
43
+ const lastDateTimestamp = null;
44
44
  let stuckCount = 0;
45
45
  const maxStuckIterations = 3;
46
46
 
@@ -267,11 +267,11 @@ export class RecurrenceEngine {
267
267
  return Math.abs(exceptionDate.getTime() - dateTime) < 1000; // Within 1 second
268
268
  }
269
269
  return exceptionDate.toDateString() === dateStr;
270
- } else {
270
+ }
271
271
  // Simple date exception
272
272
  const exceptionDate = exDate instanceof Date ? exDate : new Date(exDate);
273
273
  return exceptionDate.toDateString() === dateStr;
274
- }
274
+
275
275
  });
276
276
  }
277
277
 
@@ -327,9 +327,9 @@ export class RecurrenceEngine {
327
327
 
328
328
  if (dateStr.endsWith('Z')) {
329
329
  return new Date(Date.UTC(year, month, day, hour, minute, second));
330
- } else {
330
+ }
331
331
  return new Date(year, month, day, hour, minute, second);
332
- }
332
+
333
333
  }
334
334
 
335
335
  // Fallback to standard date parsing
@@ -609,7 +609,7 @@ export class RecurrenceEngineV2 {
609
609
  */
610
610
  clearEventCache(eventId) {
611
611
  for (const key of this.occurrenceCache.keys()) {
612
- if (key.startsWith(eventId + '_')) {
612
+ if (key.startsWith(`${eventId }_`)) {
613
613
  this.occurrenceCache.delete(key);
614
614
  }
615
615
  }
@@ -39,7 +39,7 @@ export class ICSParser {
39
39
  let inEvent = false;
40
40
  let inAlarm = false;
41
41
 
42
- for (let line of lines) {
42
+ for (const line of lines) {
43
43
  // Skip empty lines
44
44
  if (!line.trim()) continue;
45
45
 
@@ -248,7 +248,7 @@ export class ICSParser {
248
248
  event.category = value.split(',')[0]; // Take first category
249
249
  break;
250
250
 
251
- case 'STATUS':
251
+ case 'STATUS': {
252
252
  const statusMap = {
253
253
  'TENTATIVE': 'tentative',
254
254
  'CONFIRMED': 'confirmed',
@@ -256,6 +256,7 @@ export class ICSParser {
256
256
  };
257
257
  event.status = statusMap[value] || 'confirmed';
258
258
  break;
259
+ }
259
260
 
260
261
  case 'TRANSP':
261
262
  event.showAs = value === 'TRANSPARENT' ? 'free' : 'busy';
@@ -265,7 +266,7 @@ export class ICSParser {
265
266
  event.organizer = value.replace('mailto:', '');
266
267
  break;
267
268
 
268
- case 'ATTENDEE':
269
+ case 'ATTENDEE': {
269
270
  if (!event.attendees) event.attendees = [];
270
271
  const email = value.replace('mailto:', '');
271
272
  event.attendees.push({
@@ -273,6 +274,7 @@ export class ICSParser {
273
274
  name: email.split('@')[0] // Use email prefix as name
274
275
  });
275
276
  break;
277
+ }
276
278
 
277
279
  case 'RRULE':
278
280
  event.recurrence = value;
@@ -308,10 +310,10 @@ export class ICSParser {
308
310
  if (dateString.endsWith('Z')) {
309
311
  // UTC time
310
312
  return new Date(Date.UTC(year, month, day, hour, minute, second));
311
- } else {
313
+ }
312
314
  // Local time
313
315
  return new Date(year, month, day, hour, minute, second);
314
- }
316
+
315
317
  }
316
318
 
317
319
  /**
@@ -365,7 +367,7 @@ export class ICSParser {
365
367
  // Continuation lines (with space prefix)
366
368
  while (remaining.length > 0) {
367
369
  const chunk = remaining.substr(0, this.maxLineLength - 1);
368
- folded.push(' ' + chunk);
370
+ folded.push(` ${ chunk}`);
369
371
  remaining = remaining.substr(chunk.length);
370
372
  }
371
373
 
@@ -288,7 +288,7 @@ export class EventSearch {
288
288
  const events = this.eventStore.getAllEvents();
289
289
 
290
290
  for (const event of events) {
291
- const value = event[field] || (includeEmpty ? '(No ' + field + ')' : null);
291
+ const value = event[field] || (includeEmpty ? `(No ${ field })` : null);
292
292
  if (value === null) continue;
293
293
 
294
294
  if (!groups.has(value)) {
@@ -343,13 +343,13 @@ export class TimezoneManager {
343
343
  if (!tzString) return 'UTC';
344
344
 
345
345
  // Check if it's already an IANA identifier
346
- if (this.database.timezones.hasOwnProperty(tzString)) {
346
+ if (Object.prototype.hasOwnProperty.call(this.database.timezones, tzString)) {
347
347
  return tzString;
348
348
  }
349
349
 
350
350
  // Check abbreviations
351
351
  const upperTz = tzString.toUpperCase();
352
- if (this.database.abbreviations && this.database.abbreviations.hasOwnProperty(upperTz)) {
352
+ if (this.database.abbreviations && Object.prototype.hasOwnProperty.call(this.database.abbreviations, upperTz)) {
353
353
  return this.database.abbreviations[upperTz];
354
354
  }
355
355
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forcecalendar/core",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "description": "A modern, lightweight, framework-agnostic calendar engine optimized for Salesforce",
@@ -11,7 +11,12 @@
11
11
  "scripts": {
12
12
  "test": "node tests/run-all.js",
13
13
  "test:ics": "node tests/integration/test-ics.js",
14
- "test:search": "node tests/integration/test-search.js"
14
+ "test:search": "node tests/integration/test-search.js",
15
+ "lint": "eslint core/ --ext .js",
16
+ "lint:fix": "eslint core/ --ext .js --fix",
17
+ "format": "prettier --write \"core/**/*.js\"",
18
+ "format:check": "prettier --check \"core/**/*.js\"",
19
+ "quality": "npm run lint && npm run format:check"
15
20
  },
16
21
  "exports": {
17
22
  ".": "./core/index.js",