Guide

Endpoints & routing

The method name is the route. No route table, no controller to keep in sync.

@Route

import {
  Route, CloudFunction, catchError, setupSwagger,
} from 'parse-server-kit';

@Route(Product)          // -> /api/products/*
@Route('menu-items')     // -> /api/menu-items/*

The prefix is the kebab-case plural of the JavaScript class name. Each method becomes /{prefix}/{methodName}, matched against the class's real method list — so there is no string parsing and no collision between getProduct and getProductCategory.

createProduct  ->  POST /api/products/createProduct
listProducts   ->  GET  /api/products/listProducts

Rename the method and the route follows. Both static and prototype method names are captured.

@CloudFunction

@CloudFunction({
  methods: ['POST'],
  description: 'Create a product',
  validation: { requireUser: true, fields: { name: { required: true } } },
  requireRoles: ['Admin'],
  rateLimit: { windowMs: 60000, max: 30 },
  swagger: { tags: ['Products'] },
})
static async createProduct(req: Parse.Cloud.FunctionRequest) { … }
OptionEffect
methodsAllowed HTTP verbs. A mismatch answers 405
requiresAuthRefuses a caller with no session before your body runs. The master key passes — the system is not an anonymous caller
validationParse's own validator — requireUser, fields, and so on
requireRolesChecked before your body runs
requireAllRolestrue demands every listed role; default is any
roleCacheMsPer-endpoint override of the role cache; 0 never caches
rateLimitPer-function limit, enforced on the entity route and on a direct /functions/{name} call. Per process — N instances means N times the limit
customErrorMessageReplaces the default refusal text
swaggersummary, description, tags, responses

@ProtectedCloudFunction is the same decorator with methods: ['POST'] and requireUser already applied.

GET parameters arrive as strings The middleware merges the query string into the body, so declare them as {type: String} and convert: Number(req.params.limit), req.params.active === 'true'.

Error handling

const [err, saved] = await catchError(product.save(null, { sessionToken }));
if (err) throw err;

catchError is the convention throughout the library: it turns a rejected promise into a tuple rather than a try/catch around every await.

OpenAPI

Every endpoint appears in the generated document with its real route, derived from @Route — no annotations needed. GET and HEAD emit query parameters; everything else emits a JSON requestBody, because a browser cannot send a body on a GET. Security schemes are derived from requireUser, requireMaster and requireRoles.

setupSwagger(app, { title: 'My API', version: '1.0.0' });
// UI at /api-docs, document always at /api-docs/json

Without swagger-ui-express installed the browser page is skipped with a warning; the document still serves.