Skip to content

Authoring a plugin

A plugin teaches calendaryjs a new event type (a recurrence rule), and can optionally enrich each day with extra data or register named formulas. Anyone can publish one — official and community plugins use the exact same shape.

The fastest path is the official template:

Terminal window
# copy templates/calendaryjs-plugin out of the calendaryjs repo, then:
npm install
npm test

Or scaffold by hand: a plugin is just a package that depends on calendaryjs as a peer dependency and exports a factory returning a CalendaryPlugin.

import type { CalendaryPlugin } from "calendaryjs";
export function myPlugin(): CalendaryPlugin {
return {
name: "calendaryjs-plugin-my-thing",
version: "0.1.0",
eventTypes: {
"my-thing": {
// narrow the unknown event to your shape
validate(event): boolean {
const e = event as Record<string, unknown>;
return e.type === "my-thing" && typeof e.id === "string";
},
// return the Gregorian date(s) this event falls on in `year`
generate(event, year): Date[] {
const e = event as { month: number; day: number };
return [new Date(year, e.month - 1, e.day)];
},
},
},
};
}

Use it:

import { calendary } from "calendaryjs";
import { myPlugin } from "calendaryjs-plugin-my-thing";
const cal = calendary().use(myPlugin());
cal.addGroup({
id: "g",
events: [{ type: "my-thing", id: "x", month: 6, day: 1 }],
});

To attach data to every CalendarDay (like a lunar or Hijri date), register a day enricher in install() and augment the CalendarDay type:

declare module "calendaryjs" {
interface CalendarDay {
myInfo?: { foo: string };
}
}
// inside the plugin:
install(calendary) {
calendary.registerDayEnricher({
name: "my-thing",
priority: 10,
enrich: (day) => ({ ...day, myInfo: { foo: "bar" } }),
});
}

This is what makes your plugin show up in the plugins directory:

  • Package name: calendaryjs-plugin-<name> (e.g. calendaryjs-plugin-fiscal-year).
  • Keyword: add "calendaryjs-plugin" to package.json keywords. The directory crawls npm for this keyword — no registration step.
  • Peer dependency: "calendaryjs": ">=0.1.0" (your plugin works with whatever version the user already installed).
{
"name": "calendaryjs-plugin-fiscal-year",
"keywords": ["calendaryjs-plugin", "calendar", "fiscal"],
"peerDependencies": { "calendaryjs": ">=0.1.0" },
}
Terminal window
npm publish

That’s it — no scope, no custom CLI, no registry to sign up for. Within a day the plugins directory picks it up via the calendaryjs-plugin keyword, alongside its npm download count.

See Plugins for how plugins are loaded and discovered.