Reference

Configuration

Settings, schema generation, indexes and the optional role cache.

configureKit

Optional. Every default reproduces what the library did before these became settings, so a project that never calls it is unaffected. Values resolve when they are used, not at import, so calling it after dotenv still works.

configureKit({
  mountPath: '/api',                      // default: process.env.mountPath, then '/parse'
  masterKey: process.env.MASTER_KEY,      // default: process.env.masterKey
  adminRole: 'Owner',                     // default: 'SuperAdmin'
  allowAuthRoutes: false,                 // default: false
  excludedPointerClasses: ['Attachment'], // default: ['IMG', 'File']
});
masterKey is worth setting explicitly restrictRoutes compares against it to let privileged callers past the route restrictions. With nothing configured there is nothing to compare against, so a caller presenting a perfectly valid master key is refused — and nothing says why.

allowAuthRoutes

restrictRoutes closes Parse's generic REST API so clients go through the cloud functions you declared. Its auth endpoints are closed along with everything else, and the documented approach is to expose the ones you want yourself:

import {
  configureKit, Route, CloudFunction, createSchemaConfig, applyAllIndexes,
  applyMongoValidators, configureRoleCache, invalidateRoles,
} from 'parse-server-kit';

@Route(User)
class UserFunctions {
  // POST /api/users/logIn - your endpoint, so you can rate limit it,
  // lock accounts out, and log attempts.
  @CloudFunction({ methods: ['POST'] })
  static async logIn(req: Parse.Cloud.FunctionRequest) { ... }
}

That is the right default for a REST client you control, and the wrong one if your client is a Parse SDK. Parse.User.logIn() in the browser, on iOS or on Android calls /login directly and cannot be pointed at a cloud function, so those apps need this on:

configureKit({ allowAuthRoutes: true });

It opens exactly these, and only with the method that makes sense:

RouteMethodWhat it is
/loginGET, POSTLog in
/logoutPOSTEnd the session
/usersPOST onlySign up
/users/meGETThe current user
/sessions/meGETThe current session
/requestPasswordResetPOSTSend a reset email
/verificationEmailRequestPOSTResend verification
GET /users stays blocked either way POST /users signs somebody up; GET /users queries the whole user table. The method is part of the match, so turning this on never opens the second one. PUT /users/<id> stays blocked too — expose a profile-update cloud function instead.

Leaving it off is not a dead end: the 403 names the setting and suggests the cloud function alternative, so whichever route you meant to take is discoverable from the response.

createSchemaConfig

const schema = createSchemaConfig({ adminRole: 'Owner' });
// pass as the `schema` option to ParseServer
OptionDefaultEffect
adminRolefrom configureKitRole permitted to manage _Role
lockSchemasfalseReject new classes and fields
stricttrueCreate missing classes and fields at boot
recreateModifiedFieldsfalseDestructive — drops and recreates a field whose type changed
deleteExtraFieldsfalseDestructive — removes fields not in the schema
keepUnknownIndexestrueKeeps indexes the schema does not describe

keepUnknownIndexes defaults to true because applyAllIndexes creates indexes by talking to MongoDB directly, so parse-server's schema sync has never heard of them. Its own default removes indexes it cannot account for — taking your uniqueness constraints with it. Requires parse-server 8.3+.

Indexes

await applyAllIndexes(parseServer);       // after listen()
await applyMongoValidators(parseServer);
Declared asCreates
@ParseField({unique: true})Unique index — drops a conflicting non-unique one first
@ParseField({index: true | 1 | -1})B-tree, ascending or descending
@ParseField({geo: true})2dsphere
@ParseField({ttlSeconds: N})TTL
@ParseClass({compoundIndexes})Compound, optionally unique, sparse, partial or text

An index that already exists is reported, not treated as an error. If the adapter cannot be reached, the equivalent db.collection.createIndex(…) commands are printed so you can run them yourself. MongoDB permits only one text index per collection.

Role cache

Off by default. requireRoles and getUserRoles() each cost a database round-trip. Role membership rarely changes, so it caches well — but a revoked role keeps working until the entry expires, and that trade belongs to whoever runs the deployment.

configureRoleCache({ ttlMs: 30_000 });          // global
invalidateRoles(userId);                        // on grant or revoke
configureRoleCache(false);                      // off, and cleared

@CloudFunction({ requireRoles: ['Admin'], roleCacheMs: 0 })  // never cached

Wire invalidateRoles into your own grant and revoke paths and the TTL only ever covers changes made outside your code. Entries expire when read and the map is bounded by maxUsers; there is no timer.