Pure transformations
DuploJS favors pure, non-mutating functions so a transformation can be read as input, intent, output.
MODULAR TYPESCRIPT
DuploJS gives TypeScript projects a set of composable bricks for shaping data, validating boundaries and keeping application flows explicit.
Why DuploJS exists
TypeScript gives structure to JavaScript, but production systems also need pure transformations, explicit contracts, runtime validation and composable patterns. DuploJS brings these missing bricks into one coherent ecosystem.
DuploJS favors pure, non-mutating functions so a transformation can be read as input, intent, output.
Validation lives at runtime boundaries and stays aligned with the types your code consumes.
Business meaning is carried by typed contracts, not left as comments beside generic values.
THE ECOSYSTEM
DuploJS brings together a rich ecosystem of focused packages, all shaped by the same functional foundation. From utilities to HTTP, server, form, auth and testing, every package follows the same type-driven logic and consistent development model.
$npm i @duplojs/utils
The shared foundation behind the ecosystem, bringing typed composition, safe transformations, data parsing, explicit errors, immutable operations and more.
Server primitives built for predictable backends, covering file handling, commands, environment configuration, typed results and more.
Declare HTTP contracts once and keep routing, validation, clients, documentation and transport logic aligned by design.
WITH VS WITHOUT
Compare common TypeScript patterns with DuploJS alternatives designed for robustness, explicit intent and predictable behavior.
Represent fetch failures explicitly instead of hiding them in thrown errors.
// No obligation to handle errors
const response = await fetch("http://example.com/api/users");
const body = await response.json();
try {
const response = await fetch("http://example.com/api/posts");
const body = await response.json();
} catch (error: unknown) {
console.log(error);
}import { createHttpClient } from "@duplojs/http/client";
import { E } from "@duplojs/utils";
const client = createHttpClient({ baseUrl: "http://example.com" });
// Covers all cases exhaustively
const result = E.matchInformation(
await client.get("/api/users"),
{
response: ({ body }) => {
// Do something with the body
},
"request-error": ({ error }) => {
// Do something with the error
},
},
);Once the intent is explicit and the behavior is predictable, the structure of your codebase becomes the answer.
Clean architecture
DuploJS helps separate business rules, application flows and infrastructure details into explicit, readable layers. Explore each layer and see how the code stays predictable from domain to runtime.
Define business concepts and rules without depending on external tools.
import { C, DPE, E } from "@duplojs/utils";
import { Client } from "./client";
export namespace Book {
export const Id = C.createNewType("BookId", DPE.string(), C.Uuid);
export type Id = C.GetNewType<typeof Id>;
export const Name = C.createNewType("BookName", DPE.string());
export type Name = C.GetNewType<typeof Name>;
export const Entity = C.createEntity(
"Book",
({ nullable }) => ({
id: Id,
name: Name,
currentBorrowerId: nullable(Client.Id),
}),
);
export type Entity = C.GetEntity<typeof Entity>;
const Borrow = C.createFlag<
Entity,
"Borrow",
{ currentBorrowerId: Client.Id }
>("Borrow");
export const getCurrentBorrower = Borrow.getValue;
export type Borrow = C.GetFlag<typeof Borrow>;
const Available = C.createFlag<Entity, "Available">("Available");
export type Available = C.GetFlag<typeof Available>;
export function isBorrowed<T extends Entity>(book: T) {
if (book.currentBorrowerId !== null) {
return E.result(
"book-is-borrow",
Borrow.append(
book,
{ currentBorrowerId: book.currentBorrowerId },
),
);
}
return E.result("book-is-available", Available.append(book));
}
}Community
Follow the project, join discussions, watch new content, and help shape the ecosystem around TypeScript-first backend development.
Open source channels for builders who want to follow, discuss and contribute.