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 a rule as a gate function with the same editing experience as VS Code.

Code Editor with TypeScript autocompletion

Getting Started​

  1. Open a pipe from the Pipes page
  2. Select the Code Editor tab in the rule editor
  3. The editor opens with your rule's current 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 rule must define function rule(event) (or legacy function gate(event)) and accept a GateEvent parameter. It must return a GateResult object or a boolean.

function rule(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 rule(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 rule(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 rule(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
locationstring500 charsReplace the event location (empty string clears it).
visibility'default' | 'public' | 'private'--Change event visibility
showAs'free' | 'busy'--Change free/busy status
remindersfalse | number1–40320Alerts on the synced copy: false for none, a number for minutes of warning.
colorcolour name--Colour the synced copy (Google only).
preBufferMinutesinteger0–60Start the synced event earlier (pre-event buffer). Ignored for all-day events.
postBufferMinutesinteger0–60End the synced event later (post-event buffer). Ignored for all-day events.
tip

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

Formatting Your Code​

The editor toolbar includes a Prettify button that reformats your gate function — consistent indentation, quotes, spacing, and line wrapping — using the same Prettier style as the rest of CalendarPipe. Formatting runs entirely in your browser, so it's instant and never leaves your machine.

Your code is also prettified automatically whenever you run a test (or re-test), so the editor always lands on tidy code after a dry run.

note

If your code has a syntax error, formatting is skipped and your code is left untouched — fix the error, then prettify or test again.

Testing Before Saving​

The editor includes a Test Gate Function button that runs your gate function against sample events before you save. Save Gate Function stays disabled until a test has run. This helps catch errors early.

Test Gate Function button in the Code Editor toolbar

When you click Test Gate Function:

  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

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 rule(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 rule(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 rule(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 rule(event: GateEvent): GateResult {
if (event.hasAttendee('ceo@company.com')) {
return {
pass: true,
transform: {
title: 'Executive Meeting',
description: 'Details redacted',
location: '',
},
};
}
return { pass: true };
}

Filter by Duration​

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

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

Add a Buffer Around Meetings​

Pad every synced event with 15 minutes before and after so meetings never sit back-to-back on the target calendar:

function rule(event: GateEvent): GateResult {
return {
pass: true,
transform: {
preBufferMinutes: 15,
postBufferMinutes: 15,
},
};
}

Combine Multiple Conditions​

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

function rule(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: '',
location: '',
},
};
}

// Add prefix to all other events
return {
pass: true,
transform: {
title: `[Team] ${event.title}`,
},
};
}
  • Property Reference — every property and helper available on GateEvent.
  • Templates — start from a preset instead of writing from scratch.
  • Cookbook — copy-pasteable recipes for common patterns.