Something went wrong. Try again.
Cursor plugin specification and official plugins
Something went wrong. Try again.
2.8 kB · 102 lines
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103#!/usr/bin/env node
import { readFileSync, existsSync } from "fs";import { resolve, dirname } from "path";import { fileURLToPath } from "url";import Ajv from "ajv";import addFormats from "ajv-formats";
const __dirname = dirname(fileURLToPath(import.meta.url));const root = resolve(__dirname, "..");
function loadJSON(path) { return JSON.parse(readFileSync(path, "utf-8"));}
const marketplaceSchema = loadJSON( resolve(root, "schemas/marketplace.schema.json"));const pluginSchema = loadJSON(resolve(root, "schemas/plugin.schema.json"));
const ajv = new Ajv({ allErrors: true });addFormats(ajv);
const validateMarketplace = ajv.compile(marketplaceSchema);const validatePlugin = ajv.compile(pluginSchema);
let errors = 0;
function fail(message) { console.error(`ERROR: ${message}`); errors++;}
// 1. Validate marketplace.jsonconst marketplacePath = resolve(root, ".cursor-plugin/marketplace.json");
if (!existsSync(marketplacePath)) { fail(".cursor-plugin/marketplace.json not found"); process.exit(1);}
const marketplace = loadJSON(marketplacePath);
if (!validateMarketplace(marketplace)) { fail("marketplace.json schema validation failed:"); for (const err of validateMarketplace.errors) { console.error(` ${err.instancePath || "/"}: ${err.message}`); }}
// 2. Validate each pluginfor (const entry of marketplace.plugins ?? []) { const pluginDir = resolve(root, entry.source); const pluginJsonPath = resolve(pluginDir, ".cursor-plugin/plugin.json");
// Check source directory exists if (!existsSync(pluginDir)) { fail( `Plugin "${entry.name}": source directory "${entry.source}" does not exist` ); continue; }
// Check plugin.json exists if (!existsSync(pluginJsonPath)) { fail( `Plugin "${entry.name}": missing .cursor-plugin/plugin.json in "${entry.source}"` ); continue; }
const pluginJson = loadJSON(pluginJsonPath);
if (!validatePlugin(pluginJson)) { fail( `Plugin "${entry.name}": plugin.json schema validation failed (${entry.source}/.cursor-plugin/plugin.json):` ); for (const err of validatePlugin.errors) { const detail = err.keyword === "additionalProperties" ? `${err.message}: "${err.params.additionalProperty}"` : err.message; console.error(` ${err.instancePath || "/"}: ${detail}`); } }
// Check that marketplace name matches plugin name if (pluginJson.name && pluginJson.name !== entry.name) { fail( `Plugin "${entry.name}": marketplace name does not match plugin.json name "${pluginJson.name}"` ); }}
// 3. Report resultsif (errors > 0) { console.error(`\nValidation failed with ${errors} error(s).`); process.exit(1);} else { console.log("All plugins validated successfully."); process.exit(0);}