Configuration
The Mongalayer class is the central entry point on the server side. It connects to MongoDB, holds your collection definitions (schemas + access rules), and executes operations.
Check out the AWS Lambda / Express examples in Quick start for how to integrate with your HTTP server.
Creating an instance
import { MongoClient } from "mongodb";
import { Mongalayer } from "@mongalayer/server";
const mongoClient = new MongoClient("mongodb://localhost:27017");
const layer = new Mongalayer(mongoClient, {
// Each key is a MongoDB collection name
users: {
schema: userSchema,
access: userAccess
},
projects: {
schema: projectSchema,
access: projectAccess
}
});
The first argument is a standard MongoDB MongoClient instance. The second argument is an object mapping collection names to their configuration, each containing:
schema— a Zod object schema describing the document structureaccess— an array of access definitions (see Access Control)
Options
You can pass an optional third argument to configure behavior:
const layer = new Mongalayer(mongoClient, collections, {
useSessions: true, // Enable MongoDB sessions (default: true)
debugging: false, // Enable debug logging (default: false)
accessDefaults: {
document: AccessPermissions.Read, // Default document permission
delete: false // Default delete permission
}
});
useSessions
When true, Mongalayer starts a MongoDB session for each operation. This is required for transactions and is enabled by default.
debugging
When true, Mongalayer logs debug information to the console and throws the original Zod/MongoDB errors instead of wrapping them. Useful during development.
You can also enable debugging via the MONGALAYER_DEBUG=1 environment variable.
accessDefaults
Default permissions applied when a document does not match any access role, or when a role doesn't explicitly define a permission:
| Property | Type | Default | Description |
|---|---|---|---|
document | AccessPermission | AccessPermissions.Read | Default document-level permission |
delete | boolean | false | Whether documents can be deleted by default |
Executing operations
Mongalayer provides two methods for executing operations:
execute(action, stringifiedPayload, accessPayload) => string
The primary method for HTTP integrations. Accepts a JSON-stringified payload and returns a JSON string result. Handles serialization of special types like Date and RegExp.
const payload = `{"filter":{},"options":{"limit":10}}`;
const result = await layer.execute(
{ database: "myapp", collection: "projects", operation: "find" },
payload,
{ user: { id: "user-123" } }
);
// result is a JSON string from a serialized object
executeRaw(action, payload, accessPayload) => object
For server-side use when you don't want to use serialization. Accepts and returns native JavaScript objects.
executeRaw, you must ensure that the payload is properly formatted and does not contain unsupported types. We advice you to use execute when using the client SDK.const payload = { filter: {}, options: { limit: 10 } };
const result = await layer.executeRaw(
{ database: "myapp", collection: "projects", operation: "find" },
payload,
{ user: { id: "user-123" } }
);
// result is already a JavaScript object
Action structure
Every operation requires an action object with three properties:
{
database: string, // MongoDB database name
collection: string, // Collection name (must match a key in your collections config)
operation: string // One of the supported operations
}
Supported operations
| Operation | Description |
|---|---|
findOne | Find a single document |
find | Find multiple documents |
findOneAndUpdate | Find and update a single document, returning the result |
aggregate | Run an aggregation pipeline |
insertOne | Insert a single document |
insertMany | Insert multiple documents |
updateOne | Update a single document |
updateMany | Update multiple documents |
deleteOne | Delete a single document |
deleteMany | Delete multiple documents |
Action payload validation
Mongalayer already validates the structure of the action structure when calling execute or executeRaw.
If necesarry the package also exports this validateAction function that you can use to validate the action structure separately:
import { validateAction } from "@mongalayer/server";
const action = { database: "myapp", collection: "projects", operation: "find" };
try {
validateAction(action);
// Action is valid, proceed with execution
} catch (error) {
// Handle invalid action error
}
Access payload
The third argument to execute / executeRaw is the access payload — a free-form object that becomes available in your access filters via the %% prefix.
// On the server, after verifying the user's JWT or session
const accessPayload = {
user: {
id: decodedToken.id,
roles: decodedToken.roles,
organizationId: decodedToken.org
}
};
await layer.execute(action, payload, accessPayload);
In your access definitions, you reference these values:
{
role: "member",
filter: {
organizationId: "%%user.organizationId"
}
}