The Node.js ecosystem is a powerhouse, built on the shoulders of the npm registry—a vast repository of open-source packages that can solve nearly any problem you can imagine. From data validation to complex image manipulation, there's likely a package for it. At function.do, we believe you shouldn't have to abandon these powerful tools to embrace the simplicity of serverless APIs.
Our core philosophy is to remove friction between your logic and a production-ready API. A huge part of that is enabling you to use the libraries and dependencies you already know and love.
The great news? If you know how to use a package.json file, you already know how to manage dependencies in function.do. It's that simple.
There are no proprietary configuration files to learn or complex bundling steps to perform. We integrate directly with the standard, battle-tested Node.js workflow. When you deploy a function, our platform looks for a package.json file in the same directory. If it finds one, it automatically and securely installs the packages listed in your dependencies.
Here’s the simple, step-by-step workflow:
You focus on the what (your function's logic and its tools), and we handle the how (the infrastructure, scaling, and security).
Let's build a practical, atomic function. A common use case for an API endpoint is to accept user data, validate it, and then process it. We'll use the popular library zod for robust schema validation.
First, let's set up our project directory:
/create-user
├── index.ts
└── package.json
Next, our package.json will declare zod as a dependency:
{
"name": "create-user-function",
"version": "1.0.0",
"description": "A function to validate and create a new user.",
"dependencies": {
"zod": "^3.22.4"
}
}
Now, let's write the function logic in index.ts. This function will define a user schema, parse the incoming request body, and return either a success message or a detailed error.
import { Fn } from '@do-are/sdk';
import { z } from 'zod';
// 1. Define the validation schema using Zod
const UserSchema = z.object({
email: z.string().email({ message: "Invalid email address" }),
username: z.string().min(3, { message: "Username must be at least 3 characters long" }),
});
/**
* @description Validates new user data against a schema.
* @param { email: string, username: string } - The user data to validate.
* @returns { { success: boolean, data?: any, errors?: any } } - The validation result.
*/
export const validateUser: Fn = async (input) => {
// 2. Use safeParse to prevent throwing an error on validation failure
const validationResult = UserSchema.safeParse(input);
// 3. Return a successful response or the structured errors
if (!validationResult.success) {
// This provides a clear, actionable error response for the API consumer.
return {
success: false,
errors: validationResult.error.flatten().fieldErrors,
};
}
// On success, return the validated data.
// In a real-world scenario, you might call another function here to save the user.
return {
success: true,
data: validationResult.data,
};
};
// When deployed, this function becomes available at:
// POST https://your-name.function.do/validateUser
// BODY { "email": "hello@example.com", "username": "world" }
That's it! When you deploy this directory, function.do creates a scalable, serverless API endpoint that performs this validation. You didn't configure a server, set up an API gateway, or manage a build pipeline. You just wrote logic and declared its dependencies.
This dependency model is fundamental to creating composable functions. Your validateUser function could use a package like axios to call another function.do endpoint—perhaps one named saveUserToDatabase—to complete a workflow.
By breaking down complex backends into simple, single-purpose, and independently deployable units, you can build, scale, and maintain systems more effectively. Each function is an atomic building block, and with access to the entire npm ecosystem, those blocks can be incredibly powerful.
Q: Do I need to commit my node_modules folder?
A: No, and you shouldn't! Just like in a standard project, you only need to commit your package.json and package-lock.json files. Our platform performs a clean npm install in the cloud during deployment.
Q: Are only dependencies installed, or devDependencies too?
A: To keep your functions lean, fast, and secure, we only install packages listed in the dependencies section. devDependencies are ignored in the production environment.
Q: Are there any limitations on the types of packages I can use?
A: The vast majority of npm packages that run in a standard Node.js environment work seamlessly on function.do. Packages that rely on native C++ addons or specific system binaries may require extra consideration, a common factor across most Function as a Service (FaaS) platforms.
Stop wrestling with boilerplate and infrastructure. Bring your code, bring your favorite libraries, and let function.do turn them into a secure, scalable, and ready-to-use API.
Deploy Functions. Get APIs. Dive in and build your first function in minutes.