Zero-Cost Abstractions
for TypeScript

Write once, deploy anywhere. TypeFire transforms your code into platform-optimized implementations with zero runtime overhead through revolutionary compile-time meta-programming.

TypeFire Source
import { server } from '@typefire/http';
import { db } from '@typefire/db';
import { Email, Min } from '@typefire/types';

server()
    .post('/users', async (body: {
        name: string,
        email: Email,
        age: number & Min<0>
    }) => {
        const user = await db.users.create(body);
        return { success: true, user };
    })
    .serve()
Optimized Bun Output
import { Database } from 'bun:sqlite';

const db = new Database('app.db');

Bun.serve({
  port: 3000,
  async fetch(req) {
    if (req.method === 'POST' && 
        new URL(req.url).pathname === '/users') {
      
      const body = await req.json();
      
      // Compile-time generated validation
      if (typeof body.name !== 'string' || !body.name.trim()) {
        return Response.json({ error: 'Invalid name' }, { status: 400 });
      }
      if (typeof body.email !== 'string' || !body.email.includes('@')) {
        return Response.json({ error: 'Invalid email' }, { status: 400 });
      }
      if (typeof body.age !== 'number' || body.age < 0) {
        return Response.json({ error: 'Invalid age' }, { status: 400 });
      }

      // Raw SQL with compile-time optimization
      const user = db.query(`
        INSERT INTO users (name, email, age) 
        VALUES (?1, ?2, ?3) 
        RETURNING id, name, email, age
      `).get(body.name, body.email, body.age);

      return Response.json({ success: true, user });
    }
    
    return new Response('Not Found', { status: 404 });
  }
});
TypeFire
Compiled

The Journey to TypeFire

2016

I deployed my first production function on AWS Lambda in 2016. Immediately, I was hooked on the promise of Function-as-a-Service (FaaS): atomic scaling, granular observability, and zero downtime updates. It erased the shared-resource risks and complex versioning challenges that came with traditional monolithic deployments. Small, low-traffic services became trivial to manage.

But Lambda had an Achilles' heel: cold starts. Your entire function needed loading upon first use, and with Lambda billing tied closely to memory and CPU usage, heavy bundles meant heavy costs. JavaScript was notorious here, while hand-crafted functions could be mere kilobytes, standard bundled deployments often ballooned into megabytes.

2019

I began exploring dependency reduction techniques in deployments, striving for a better balance of developer experience and optimized bundle sizes. My initial efforts revolved around Webpack, Rollup, and Babel transformations.

2020

I released my first transformed application leveraging Babel to rewrite ASTs (Abstract Syntax Trees), seamlessly hydrating serverless API facades. Around this time, inspired by C#'s LINQ, I crafted auto-sql, translating expressive JavaScript array methods directly into optimized SQL queries using the TypeScript compiler. Building upon that, I developed auto-serverless, embedding static dependency injection right into serverless deployments.

The Bloom Era

Driven by these experiments, I set out to generalize the approach. This became bloom, a framework that introduced cascading plugin transforms, allowing plugins to modify the behavior and code generation of subsequent plugins by directly manipulating their ASTs. Another breakthrough was the use of tagged types in TypeScript, enabling compile-time enforcement of data governance rules for sensitive information like PII and PCI.

Yet, the ambitious bloom was shelved temporarily due to competing demands. It seemed too bold, perhaps ahead of its time.

2023

Then, in 2023, Bun emerged, reigniting my excitement. I quickly prototyped a dependency injection transform integrated effortlessly into Bun's esbuild pipeline. This was the spark for `bloom v2`, now named TypeFire.

Today

I'm excited to announce that TypeFire 1.0 is nearing its release as an open-source framework and its potential is thrilling.

Historically, JavaScript development has been weighed down by runtime overhead. Even with modern advancements like Zod for validation, lighter frameworks like Hono, and compiled UI approaches, JavaScript applications remain bloated.

TypeFire changes that. It introduces a new model for JavaScript: one where your code is treated as data and evaluated at compile-time to generate highly optimized, platform-specific output.

What does that unlock?

  • Validators that compile to minimal, blazing-fast functions indistinguishable from handcrafted code.
  • Type-safe APIs that automatically generate OpenAPI specs, runtime validation, and type inference with zero duplication.
  • SQL queries authored as expressive, composable JavaScript that compile to raw SQL with full optimization.
  • Reactive UI components that compile into framework-free DOM manipulations or into React, Web Components, or anything else.
  • Business logic that compiles differently depending on your target (Node, Workers, Lambda, Deno) with no runtime branching or adapter layers.

It's not just a build step. It's a way to collapse the abstraction gap between DX and performance, turning TypeScript into a living language.

TypeFire transforms JavaScript development into a magical experience, delivering unmatched developer ergonomics without sacrificing performance. Unlike traditional macros, TypeFire harnesses standard, fully type-checked TypeScript, allowing limitless macro extensions and playful experimentation with types.

If you're intrigued, join our early access list, or follow along as we redefine what's possible with JavaScript. And if you're a developer eager to contribute, let's connect. Reach out to [email protected].

See the Magic

One codebase, multiple optimized outputs

TypeFire Source

import { db } from '@typefire/database';

// Universal database query
const getActiveUsers = () => {
  return db.users
    .where(u => u.active === true)
    .where(u => u.createdAt > daysAgo(30))
    .select(u => ({ id: u.id, name: u.name }));
};
→ PostgreSQL
const getActiveUsers = () => {
  return pool.query(
    `SELECT id, name FROM users 
     WHERE active = true 
     AND created_at > NOW() - INTERVAL '30 days'`
  ).then(r => r.rows);
};
→ SQLite/D1
const getActiveUsers = () => {
  return db.prepare(
    `SELECT id, name FROM users 
     WHERE active = 1 
     AND created_at > datetime('now', '-30 days')`
  ).all();
};
→ AWS DynamoDB
const getActiveUsers = () => {
  const thirtyDaysAgo = new Date();
  thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
  
  return dynamoClient.query({
    TableName: 'users',
    KeyConditionExpression: 'active = :active AND createdAt > :date',
    ExpressionAttributeValues: {
      ':active': true,
      ':date': thirtyDaysAgo.toISOString()
    }
  }).promise().then(r => r.Items);
};

TypeFire Source

import { middleware } from '@typefire/http';

const authMiddleware = middleware()
  .withAuth('jwt')
  .withRateLimit({ max: 100, window: '15m' })
  .withCors({ origin: '*' });
→ Express.js
const authMiddleware = [
  cors({ origin: '*' }),
  rateLimit({
    windowMs: 15 * 60 * 1000,
    max: 100
  }),
  passport.authenticate('jwt', { session: false })
];
→ Cloudflare Workers
const authMiddleware = async (request, env) => {
  // Built-in CORS handling
  if (request.method === 'OPTIONS') {
    return new Response(null, { headers: corsHeaders });
  }
  
  // Native Cloudflare rate limiting
  const { success } = await env.RATE_LIMITER.limit({
    key: request.headers.get('CF-Connecting-IP')
  });
  
  // JWT verification with crypto API
  const token = request.headers.get('Authorization');
  await crypto.subtle.verify('RS256', publicKey, signature, payload);
};

TypeFire Source

import { validate } from '@typefire/validation';

const UserSchema = {
  id: validate.number().positive(),
  email: validate.string().email(),
  age: validate.number().min(18).max(120),
  roles: validate.array(validate.string())
};

const createUser = validate(UserSchema, async (data) => {
  return db.users.create(data);
});
→ Runtime Validation
const createUser = async (data) => {
  // Compile-time generated validation
  if (typeof data.id !== 'number' || data.id <= 0) {
    throw new ValidationError('id must be positive');
  }
  if (!data.email || !/^[^@]+@[^@]+$/.test(data.email)) {
    throw new ValidationError('invalid email');
  }
  if (data.age < 18 || data.age > 120) {
    throw new ValidationError('age must be 18-120');
  }
  
  return db.users.create(data);
};
→ JSON Schema
{
  "type": "object",
  "required": ["id", "email", "age", "roles"],
  "properties": {
    "id": { "type": "number", "minimum": 1 },
    "email": { "type": "string", "format": "email" },
    "age": { "type": "number", "minimum": 18, "maximum": 120 },
    "roles": {
      "type": "array",
      "items": { "type": "string" }
    }
  }
}