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
- Navigate to a sync rule's gate function settings
- Select the Code Editor tab
- The editor opens with your current gate function code (or the default "Pass All" template)
- Type definitions for
GateEventandGateResultare 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:
| Field | Type | Max Length | Description |
|---|---|---|---|
title | string | 500 chars | Replace the event title |
description | string | 5,000 chars | Replace the event description |
visibility | 'default' | 'public' | 'private' | -- | Change event visibility |
showAs | 'free' | 'busy' | -- | Change free/busy status |
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:
- CalendarPipe runs your function against a set of sample events
- Each event shows whether it was passed or blocked, along with any transforms applied
- Events that fail validation are highlighted with an error
Screenshot: Dry-run results showing passed, blocked, and transformed events
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
- Look up every available property in the Property Reference
- Start from a Template instead of writing from scratch
- Build conditions visually with the Visual Builder