Node.js · SDK + algoritmo

Gerador de CPF em Node.js

Duas rotas em Node/TypeScript: SDK oficial fakeforge-br (via npm) ou implementação local do mod-11 puro. Snippets pra Jest, Vitest, NestJS, Express e Fastify.

TL;DR

npm install fakeforge-br

import { FakeForge } from "fakeforge-br"
const cpfs = await new FakeForge().cpf(100)

Zero deps runtime. TypeScript nativo. Free 50/dia.

Rota 1: SDK oficial fakeforge-br

// npm install fakeforge-br
import { FakeForge } from "fakeforge-br"

const ff = new FakeForge()

// 1 CPF formatado
const [cpf] = await ff.cpf(1)
console.log(cpf) // "123.456.789-09"

// 1000 CPFs sem formatação
const cpfs = await ff.cpf(1000, false)

// Preset customer com TypeScript types
const pessoas = await ff.preset("customer", 10)
pessoas.forEach(p => {
  console.log(p.nome, p.cpf, p.email)
})

TypeScript types incluídos (interface FintechPresetItem, EcomPresetItem). Autocomplete no VS Code funciona out-of-box.

Rota 2: algoritmo mod-11 local (TypeScript)

// utils/cpf.ts
export function gerarCpf(formatado = true): string {
  const n: number[] = Array.from({ length: 9 }, () => Math.floor(Math.random() * 10))

  // Primeiro dígito verificador
  const s1 = n.reduce((acc, digit, i) => acc + digit * (10 - i), 0)
  let d1 = (s1 * 10) % 11
  d1 = d1 === 10 ? 0 : d1
  n.push(d1)

  // Segundo dígito verificador
  const s2 = n.reduce((acc, digit, i) => acc + digit * (11 - i), 0)
  let d2 = (s2 * 10) % 11
  d2 = d2 === 10 ? 0 : d2
  n.push(d2)

  if (formatado) {
    return `${n[0]}${n[1]}${n[2]}.${n[3]}${n[4]}${n[5]}.${n[6]}${n[7]}${n[8]}-${n[9]}${n[10]}`
  }
  return n.join("")
}

export function validarCpf(cpf: string): boolean {
  const d = cpf.replace(/\D/g, "").split("").map(Number)
  if (d.length !== 11 || new Set(d).size === 1) return false

  const s1 = d.slice(0, 9).reduce((acc, x, i) => acc + x * (10 - i), 0)
  let v1 = (s1 * 10) % 11
  v1 = v1 === 10 ? 0 : v1
  if (v1 !== d[9]) return false

  const s2 = d.slice(0, 10).reduce((acc, x, i) => acc + x * (11 - i), 0)
  let v2 = (s2 * 10) % 11
  v2 = v2 === 10 ? 0 : v2
  return v2 === d[10]
}

Uso em Jest

// tests/signup.test.ts
import { FakeForge } from "fakeforge-br"

const ff = new FakeForge()
let cpfs: string[]

beforeAll(async () => {
  cpfs = await ff.cpf(50)
})

test("signup aceita CPF válido", async () => {
  for (const cpf of cpfs.slice(0, 10)) {
    const res = await request(app).post("/signup").send({ cpf, email: "test@test.com" })
    expect(res.status).toBe(201)
  }
})

Uso em Vitest

// tests/customer.test.ts
import { describe, test, expect, beforeAll } from "vitest"
import { FakeForge } from "fakeforge-br"

const ff = new FakeForge()

describe("Customer model", () => {
  let customers: Array<{ nome: string; cpf: string; email: string }>

  beforeAll(async () => {
    customers = await ff.preset("customer", 100)
  })

  test("todos CPFs passam validação", () => {
    for (const c of customers) {
      expect(validarCpf(c.cpf)).toBe(true)
    }
  })
})

Uso em NestJS

// customer.seed.ts - seed via NestJS command
import { Command, CommandRunner } from "nest-commander"
import { FakeForge } from "fakeforge-br"
import { CustomerService } from "./customer.service"

@Command({ name: "seed:customers" })
export class CustomerSeedCommand extends CommandRunner {
  constructor(private readonly customers: CustomerService) { super() }

  async run(): Promise<void> {
    const ff = new FakeForge()
    const dados = await ff.preset("customer", 1000)
    await this.customers.bulkCreate(dados)
    console.log(`${dados.length} customers seeded`)
  }
}

Uso em Express

// routes/dev.ts - endpoint só em dev
import { Router } from "express"
import { FakeForge } from "fakeforge-br"

const router = Router()
const ff = new FakeForge()

router.get("/dev/fake-cpfs", async (req, res) => {
  if (process.env.NODE_ENV === "production") return res.sendStatus(404)
  const qty = Number(req.query.qty || 10)
  const cpfs = await ff.cpf(qty)
  res.json({ cpfs })
})

Próximos passos