TypeScript wrapper for modulink-js providing full type safety and IntelliSense support while maintaining 100% API compatibility.
ModuLink TypeScript is a zero-overhead TypeScript wrapper that adds comprehensive type definitions to the modulink-js library. It provides the same powerful composable function chains and multi-level middleware system with the added benefits of TypeScript's compile-time safety and enhanced developer experience.
- ✅ Full TypeScript Support - Complete type definitions with generics
- ✅ Zero Runtime Overhead - Pure type layer over modulink-js
- ✅ 100% API Compatibility - Identical to modulink-js API
- ✅ IntelliSense & Autocomplete - Rich IDE support
- ✅ Compile-time Safety - Catch errors before runtime
- ✅ Generic Context Types - Custom context object types
- ✅ Comprehensive Test Coverage - Full test suite included
npm install modulink-ts
import { chain, createContext } from 'modulink-ts';
import type { Context, Link } from 'modulink-ts';
// Define your context type
interface UserContext extends Context {
userId?: string;
userData?: {
name: string;
email: string;
};
processed?: boolean;
}
// Create type-safe links
const fetchUser: Link<UserContext> = async (ctx) => {
// TypeScript knows ctx has userId, userData, etc.
const userData = await getUserById(ctx.userId);
return { ...ctx, userData };
};
const processUser: Link<UserContext> = (ctx) => {
// Full IntelliSense support
console.log(\`Processing user: \${ctx.userData?.name}\`);
return { ...ctx, processed: true };
};
// Create and execute chain
const userChain = chain(fetchUser, processUser);
const result = await userChain({ userId: '123' });
console.log(result.processed); // TypeScript knows this exists
import type { Ctx, HttpContext, CronContext } from 'modulink-ts';
// Base enhanced context with metadata
interface MyContext extends Ctx {
customField: string;
}
// HTTP-specific context
interface ApiContext extends HttpContext {
apiKey: string;
requestId: string;
}
import type { Link } from 'modulink-ts';
// Strongly typed link functions
const validateInput: Link<ApiContext> = (ctx) => {
if (!ctx.apiKey) {
throw new Error('API key required');
}
return ctx;
};
const logRequest: Link<ApiContext> = (ctx) => {
console.log(\`Request \${ctx.requestId} from \${ctx.method} \${ctx.url}\`);
return ctx;
};
import { chain } from 'modulink-ts';
import type { Middleware } from 'modulink-ts';
const timingMiddleware: Middleware<MyContext> = (ctx) => {
const startTime = Date.now();
return {
...ctx,
timings: { ...ctx.timings, startTime }
};
};
const myChain = chain(validateInput, processData)
.use(timingMiddleware)
.onInput(logRequest)
.onOutput(logResponse);
interface OrderProcessingContext extends Context {
orderId: string;
order?: Order;
inventory?: InventoryItem[];
payment?: PaymentResult;
shipping?: ShippingResult;
completed?: boolean;
}
const validateOrder: Link<OrderProcessingContext> = async (ctx) => {
const order = await getOrder(ctx.orderId);
if (!order) {
throw new Error(\`Order \${ctx.orderId} not found\`);
}
return { ...ctx, order };
};
const checkInventory: Link<OrderProcessingContext> = async (ctx) => {
const inventory = await checkInventoryForOrder(ctx.order!);
return { ...ctx, inventory };
};
const processPayment: Link<OrderProcessingContext> = async (ctx) => {
const payment = await processOrderPayment(ctx.order!);
return { ...ctx, payment };
};
const orderChain = chain(
validateOrder,
checkInventory,
processPayment
);
import { when, transform, parallel, retry } from 'modulink-ts';
// Conditional execution
const conditionalProcessing = when(
(ctx: OrderProcessingContext) => ctx.order?.total > 100,
applyDiscount
);
// Data transformation
const addMetadata = transform((ctx: OrderProcessingContext) => ({
...ctx,
metadata: {
processedAt: new Date().toISOString(),
version: '1.0'
}
}));
// Parallel execution
const parallelValidation = parallel(
validateUser,
validatePayment,
validateInventory
);
// Retry with error handling
const reliableApiCall = retry(callExternalApi, 3, 1000);
import { errorHandler } from 'modulink-ts';
const handleOrderErrors = errorHandler((error: any, ctx: OrderProcessingContext) => {
console.error(\`Order processing failed: \${error.message}\`);
return {
...ctx,
error: {
message: error.message,
orderId: ctx.orderId,
timestamp: new Date().toISOString()
}
};
});
const orderChain = chain(validateOrder, processOrder)
.use(handleOrderErrors);
-
Context
- Base context interface -
Ctx
- Enhanced context with ModuLink metadata -
HttpContext
,CronContext
,CliContext
,MessageContext
- Specialized contexts -
Link<T>
- Function that processes context -
Middleware<T>
- Middleware function type -
Chain<T>
- Async chain function -
EnhancedChain<T>
- Chain with middleware API
-
chain(...links)
- Create a new chain -
createModuLink(app?)
- Create ModuLink instance -
createContext(data?)
- Create basic context -
createHttpContext(data?)
- Create HTTP context -
when(condition, thenChain)
- Conditional execution -
transform(transformer)
- Data transformation -
parallel(...links)
- Parallel execution -
retry(chain, maxRetries?, delayMs?)
- Retry logic
ModuLink TypeScript is a pure TypeScript wrapper around modulink-js:
- Runtime: Uses modulink-js as a dependency
- Types: Adds comprehensive TypeScript definitions
- API: 100% compatible with modulink-js API
- Performance: Zero runtime overhead
- Maintenance: Single source of truth in modulink-js
This approach ensures:
- JavaScript users can stay on modulink-js
- TypeScript users get full type safety
- Bug fixes and features implemented once
- Easy migration path between packages
Migrating from modulink-js to modulink-ts is straightforward:
-
Install:
npm install modulink-ts
-
Update imports: Change
modulink-js
tomodulink-ts
- Add types: Optionally add TypeScript interfaces for your contexts
- No code changes: Your existing logic works unchanged
// Before (modulink-js)
import { chain } from 'modulink-js';
// After (modulink-ts)
import { chain } from 'modulink-ts';
import type { Context, Link } from 'modulink-ts';
# Clone the repository
git clone https://github.com/JoshuaWink/modulink-ts.git
cd modulink-ts
# Install dependencies
npm install
# Build the project
npm run build
# Run tests
npm test
# Watch mode for development
npm run dev
Contributions are welcome! Please see the contributing guidelines for details.
Licensed under the Apache License, Version 2.0. See LICENSE for details.
- modulink-js - Core JavaScript implementation
- modulink-py - Python implementation
- 📖 Documentation
- 🐛 Issues
- 💬 Discussions