Skip to main content

Code Editor

The Code Editor is a Monaco-based TypeScript editor built into CalendarPipe. It provides full autocompletion for GateEvent and GateResult types, letting you write gate functions with the same editing experience as VS Code.

Screenshot: Code Editor with TypeScript autocompletion

Getting Started

  1. Navigate to a sync rule's gate function settings
  2. Select the Code Editor tab
  3. The editor opens with your current gate function code (or the default "Pass All" template)
  4. Type definitions for GateEvent and GateResult are injected automatically -- you get full autocompletion as you type

Function Signature

Every gate function must be named gate and accept a GateEvent parameter. It must return a GateResult object or a boolean.

function gate(event: GateEvent): GateResult | boolean {
// Your logic here
return { pass: true };
}

The event parameter contains all properties of the calendar event being synced. See the Property Reference for the full list of available properties and methods.

Returning Results

Gate functions support three return patterns:

1. Simple Boolean

The simplest approach -- return true to pass or false to block:

function gate(event: GateEvent): boolean {
return event.isWeekday;
}

2. GateResult with Reason

Return an object with pass and an optional reason (max 200 characters). The reason appears in sync logs when an event is blocked:

function gate(event: GateEvent): GateResult {
if (event.matches('confidential')) {
return { pass: false, reason: 'Blocked confidential event' };
}
return { pass: true };
}

3. GateResult with Transform

Return a transform object to modify event properties on the synced copy. The original event on the source calendar is never changed:

function gate(event: GateEvent): GateResult {
return {
pass: true,
transform: {
title: `[Work] ${event.title}`,
showAs: 'free'
}
};
}

Transform Options

When passing events, you can override these properties on the synced copy:

FieldTypeMax LengthDescription
titlestring500 charsReplace the event title
descriptionstring5,000 charsReplace the event description
visibility'default' | 'public' | 'private'--Change event visibility
showAs'free' | 'busy'--Change free/busy status
tip

Transforms only apply to the synced copy on the target calendar. The original event is never modified.

Testing Before Saving

The editor includes a Test button that runs your gate function against sample events before you save. This helps catch errors early.

Screenshot: Test button in the Code Editor toolbar

When you click Test:

  1. CalendarPipe runs your function against a set of sample events
  2. Each event shows whether it was passed or blocked, along with any transforms applied
  3. Events that fail validation are highlighted with an error

Screenshot: Dry-run results showing passed, blocked, and transformed events

info

Always test your gate function before saving, especially after making changes. The test run uses real events from your source calendar so you can see exactly how your function behaves.

Common Examples

All examples below are complete, copy-pasteable gate functions.

Block Events Matching a Keyword

Block any event with "internal" in the title or description:

function gate(event: GateEvent): GateResult {
if (event.matches('internal')) {
return { pass: false, reason: 'Blocked internal event' };
}
return { pass: true };
}

Prefix All Event Titles

Add a "[SYNCED]" prefix to every event title:

function gate(event: GateEvent): GateResult {
return {
pass: true,
transform: {
title: `[SYNCED] ${event.title}`
}
};
}

Block Events Outside Business Hours

Only sync events that occur during business hours (9 AM - 5 PM, weekdays):

function gate(event: GateEvent): GateResult {
if (!event.isWeekday) {
return { pass: false, reason: 'Weekend event' };
}
if (event.hour < 9 || event.hour >= 17) {
return { pass: false, reason: 'Outside business hours' };
}
return { pass: true };
}

Redact Events from Specific Attendees

Pass all events, but redact details when a specific person is an attendee:

function gate(event: GateEvent): GateResult {
if (event.hasAttendee('ceo@company.com')) {
return {
pass: true,
transform: {
title: 'Executive Meeting',
description: 'Details redacted'
}
};
}
return { pass: true };
}

Filter by Duration

Only sync meetings that are 30 minutes or longer, block quick check-ins:

function gate(event: GateEvent): GateResult {
if (event.durationMinutes < 30) {
return { pass: false, reason: 'Too short' };
}
return { pass: true };
}

Combine Multiple Conditions

Block personal events, redact 1:1 meetings, and add a prefix to everything else:

function gate(event: GateEvent): GateResult {
// Block personal events entirely
if (event.matches('personal')) {
return { pass: false, reason: 'Personal event' };
}

// Redact 1:1 meetings for privacy
if (event.attendeeCount <= 2) {
return {
pass: true,
transform: {
title: 'Meeting',
description: ''
}
};
}

// Add prefix to all other events
return {
pass: true,
transform: {
title: `[Team] ${event.title}`
}
};
}

Next Steps