npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ministerjs/server

v3.7.0

Published

Pacote de integração backend para o MinisterJS. Fornece endpoints REST auto-gerados via controllers NestJS, um repositório baseado em Prisma com hooks de ciclo de vida, mapeamento de campos, soft delete e um sistema de schema de entidades com validação.

Readme

@ministerjs/server

Pacote de integração backend para o MinisterJS. Fornece endpoints REST auto-gerados via controllers NestJS, um repositório baseado em Prisma com hooks de ciclo de vida, mapeamento de campos, soft delete e um sistema de schema de entidades com validação.

Instalação

pnpm add @ministerjs/server

Dependências peer:

pnpm add @ministerjs/resource @ministerjs/utils @nestjs/common @prisma/client class-validator nestjs-form-data

Início Rápido

1. Defina um Schema de Entidade

import { field, buildEntitySchema } from "@ministerjs/server/entity";
import { IsEmail } from "class-validator";

const UserSchema = buildEntitySchema("user", {
  primaryKey: "id",
  fields: {
    id: field("string").build(),
    name: field("string").searchable().requireInCreate().build(),
    email: field("string")
      .searchable()
      .requireInCreate()
      .validate(IsEmail())
      .build(),
    role: field("string").optional().build(),
  },
  parents: [],
  children: { orders: "user_id" },
});

2. Crie um Repositório

import { PrismaRepository } from "@ministerjs/server/prisma";

const userRepository = new PrismaRepository({
  prisma,
  schema: UserSchema,
  softDelete: true, // opcional
});

3. Crie um Controller

import { NestJsTableController } from "@ministerjs/server/nestjs";
import { Controller } from "@nestjs/common";

@Controller("users")
class UsersController extends NestJsTableController {
  constructor() {
    super(userRepository, {
      schema: UserSchema,
      hooks: {
        beforeCreate: ({ body }) => {
          body.role = body.role ?? "user";
        },
        afterCreate: ({ data }) => {
          console.log("Usuário criado:", data.id);
        },
      },
    });
  }
}

Isso gera automaticamente os seguintes endpoints:

| Método | Rota | Descrição | |--------|--------------|-----------------------------------------------| | GET | /users | Listar com paginação, busca, filtros e ordenação | | GET | /users/:id | Buscar por ID com parents e children | | POST | /users | Criar com validação | | PUT | /users/:id | Atualizar com validação | | DELETE | /users/:id | Deletar (soft ou hard) |

Exports do Pacote

import { field, buildEntitySchema } from "@ministerjs/server/entity";
import { NestJsTableController, NestJsItemController, parseListQuery } from "@ministerjs/server/nestjs";
import { PrismaRepository } from "@ministerjs/server/prisma";

| Entry Point | Conteúdo | |-------------|----------| | @ministerjs/server/entity | field(), buildEntitySchema(), tipos do schema | | @ministerjs/server/nestjs | NestJsTableController, NestJsItemController, parseListQuery | | @ministerjs/server/prisma | PrismaRepository, utilitários de field mapping, specifications |

Schema de Entidade

O builder field() define metadados a nível de campo:

field("string")
  .searchable()              // Incluir na busca textual
  .requireInCreate()         // Obrigatório no POST
  .optionalInUpdate()        // Opcional no PUT
  .validate(IsEmail())       // Decorator do class-validator
  .getter(e => e.name?.toUpperCase())  // Transformar na leitura
  .setter(e => e.name?.toLowerCase())  // Transformar na escrita
  .build()

Validação suporta tanto decorators do class-validator quanto ObjectValidator customizados:

const emailUnico = {
  validate: async (target, prop, { request }) => {
    const existente = await userRepo.getByProperty("email", target[prop]);
    if (existente) throw new Error("Email já está em uso");
  },
};

field("string").validate(IsEmail(), emailUnico).build();

PrismaRepository

Repositório completo com operações CRUD tipadas:

const repo = new PrismaRepository({
  prisma,             // Instância do PrismaClient
  schema,             // Schema de entidade via buildEntitySchema()
  softDelete: false,  // Habilitar soft delete (padrão: false)
  fieldMapping: {},   // Mapeamento de nomes de campos (opcional)
  logger: console,    // Logger customizado (opcional)
  defaultResultsPerPage: 25,
});

Operações de Leitura

await repo.get(id);
await repo.getByProperty("email", "[email protected]");
await repo.getByProperties({ name: "John", role: "admin" });
await repo.list({ page: 1, resultsPerPage: 10, search: "john", sort, filters });
await repo.listWithCursor({ cursor: lastId, take: 20 }); // Paginação por cursor
await repo.count();

Operações de Escrita

await repo.create({ name: "John", email: "[email protected]" });
await repo.createMany([{ name: "A" }, { name: "B" }]); // Criação em lote
await repo.update(id, { name: "Jane" });
await repo.updateProperty(id, "role", "admin");
await repo.updatePropertyMany("role", [{ id: "1", role: "admin" }, { id: "2", role: "user" }]);
await repo.delete(id);

Relacionamentos

await repo.getParent(orderId, "user");
await repo.listParents(orderId);
await repo.getChildren(userId, "orders");
await repo.listChildren(userId);
await repo.countChildren(userId, "orders");

Hooks de Ciclo de Vida

Ambos os controllers suportam hooks em cada ponto do ciclo de vida:

Hooks do NestJsTableController

CREATE:  beforeValidateCreate -> [validação] -> beforeCreate -> [BD] -> afterCreate
SHOW:    beforeShow -> [BD + relações] -> afterShow
LIST:    beforeList -> [consulta BD] -> afterList
UPDATE:  beforeValidateUpdate -> [validação] -> beforeUpdate -> [BD] -> afterUpdate
DELETE:  beforeDelete -> [BD] -> afterDelete

Registro de Hooks

// Via construtor
new NestJsTableController(repo, {
  schema,
  hooks: {
    beforeCreate: ({ body, request }) => { /* ... */ },
    afterDelete: ({ id, data }) => { /* ... */ },
  },
});

// Via addHook (múltiplos handlers, chamados em ordem)
controller.addHook("beforeCreate", handler1, handler2);

// Via bindHook (um handler para múltiplos eventos)
controller.bindHook(auditLogger, "beforeCreate", "beforeUpdate", "beforeDelete");

Guias

Desenvolvimento

pnpm --filter @ministerjs/server test        # Executar testes
pnpm --filter @ministerjs/server build       # Build (lint + types + bundle)
pnpm --filter @ministerjs/server build:types # Gerar declarações de tipos
pnpm --filter @ministerjs/server dev         # Modo watch