CoreModule
O CoreModule é o núcleo da camada de API da soulsys plataforma. Ele reúne todos os recursos essenciais que sustentam o funcionamento da plataforma — autenticação, autorização, internacionalização, cache, geração de documentos, armazenamento de arquivos e utilitários compartilhados entre os demais módulos.
Por ser um módulo global (@Global()), o CoreModule pode ser importado uma única vez e seus serviços passam a estar disponíveis em toda a aplicação, garantindo padronização, reuso e simplicidade na criação de novas funcionalidades.
Além disso, ele exporta seus submódulos para projetos externos que utilizam @soulsys/api, permitindo que integrações, módulos complementares e soluções personalizadas aproveitem a mesma infraestrutura e boas práticas da plataforma.
Como Inicializar
Para iniciar uma aplicação utilizando os padrões da plataforma, importe o CoreModule no módulo raiz e utilize o helper bootstrap, responsável por configurar prefixos globais, CORS, validações, logger e o redirecionamento automático para HTTPS (quando habilitado).
import { Module } from "@nestjs/common"
import { CoreModule, bootstrap } from "@soulsys/api/core"
@Module({
imports: [CoreModule],
})
export class AppModule {}
// main.ts
bootstrap(AppModule)
Guardas Globais
Os guardas são registrados como APP_GUARD e funcionam em cascata.
AuthGuard: valida Bearer token (Authorization) ouauthTokenvia query string. Aceita token de usuário e token de sistema. Use@Public()para rotas que não exigem autenticação.CompanyGuard: lê o headersyscompany(id da empresa) e garante que o usuário pertence à empresa antes de colocá-la no contexto.RolesGuard: exige papéis informados em@Roles(...). Use a constanteSYS_ADMIN_ROLEpara rotas administrativas.I18NGuard: define o locale a partir desys_locale(query/body) e inicializa numeral/dayjs.LoggerGuard: habilitado somente quandoREQUEST_LOGGER=true; registra método, rota, status e tempo de resposta.
Contexto de Requisição
O ContextService guarda informações resolvidas pelos guardas.
import { Controller, Get } from "@nestjs/common"
import { ContextService } from "@soulsys/api/core"
@Controller("sales")
export class SalesController {
constructor(private ctx: ContextService) {}
@Get("current-context")
getContext() {
return {
user: this.ctx.user,
company: this.ctx.company,
}
}
}
Autenticação
O AuthModule oferece fluxo completo de login com ou sem OTP, recuperação de senha, convite e renovação de tokens.
POST /api/sys/auth/login: autentica comemailepassword. SeAUTH_OTP=true, retornaotp=truee envia código por e-mail; caso contrário já devolveuser,accessTokenerefreshToken.POST /api/sys/auth/otp: finaliza login comaccessTokentemporário eotp, retornando novos tokens.POST /api/sys/auth/refresh-access-token: gera novo access token a partir dorefreshToken.POST /api/sys/auth/password-recovery: envia link de redefinição usandoAUTH_PSW_UPDATE_URL.POST /api/sys/auth/user-invite: reenvia link de convite (token de redefinição).POST /api/sys/auth/check-passwordePOST /api/sys/auth/update-password: validam e aplicam a política de senha.GET /api/sys/auth/psw-policy: expõe a política configurada.
Exemplo de login com OTP habilitado:
POST /api/sys/auth/login
Content-Type: application/json
{
"email": "admin@soulsys.tech",
"password": "senhaSegura123"
}
// resposta
{
"otp": true,
"accessToken": "<token-temporario>"
}
POST /api/sys/auth/otp
{
"accessToken": "<token-temporario>",
"otp": "123456"
}
// resposta final
{
"user": { "...": "dados" },
"accessToken": "<jwt>",
"refreshToken": "<jwt>"
}
Tokens de sistema podem ser gerados via POST /api/sys/users/token (restrito a SYS_ADMIN_ROLE) para integrações server-to-server usando clientId e clientSecret.
Usuários
CRUD completo de usuários, associação a papéis e empresas e geração de tokens de sistema.
POST /api/sys/users(admin): cria usuários do tipopersonousystem.POST /api/sys/users/find(admin): paginação e filtros.GET /api/sys/users/:id: retorna usuário;:id = whoamitraz o usuário autenticado.POST /api/sys/users/update-profile: atualiza nome do usuário logado.POST /api/sys/users/token(admin): gera token de sistema comclientIdeclientSecret.
Exemplo de geração de token de sistema:
POST /api/sys/users/token
Authorization: Bearer <access-token-admin>
{
"clientId": "my-system",
"clientSecret": "super-secret"
}
// resposta
{ "token": "<jwt-de-sistema>" }
Papéis
POST /api/sys/roles(admin): cria papéis comcodeedescription.POST /api/sys/roles/find(admin): lista paginada.PATCH /api/sys/roles/:ideDELETE /api/sys/roles/:id: manutenção de papéis.
Use @Roles("meu_papel") para proteger rotas. A constante SYS_ADMIN_ROLE representa o papel administrador padrão criado no seed.
Empresas
POST /api/sys/companies(admin): cria empresa com dados cadastrais.POST /api/sys/companies/find(admin): filtros porname,shortName,city,cnpj.GET /api/sys/companies/:id/can-delete: verifica se há usuários associados.- Defina o cabeçalho
syscompany: <companyId>para vincular a requisição a uma empresa específica.
Internacionalização
O I18NService controla locale e formatos numéricos/data. Locale aceito: pt-br, en, es-us via sys_locale.
import { Controller, Get, Query } from "@nestjs/common"
import { I18NService, SYS_LOCALE } from "@soulsys/api/core"
@Controller("reports")
export class ReportController {
constructor(private i18n: I18NService) {}
@Get("totals")
totals(@Query("value") value: number, @Query("date") date: string) {
return {
currency: this.i18n.formatCurrency(value),
date: this.i18n.formatDate(date),
}
}
}
Assets
O AssetService resolve caminhos para templates internos e busca assets do web client, com cache em memória.
import { Controller, Get } from "@nestjs/common"
import { AssetService, assetPath } from "@soulsys/api/core"
@Controller("assets-demo")
export class AssetsDemoController {
constructor(private assets: AssetService) {}
@Get("template-path")
path() {
return assetPath("core/assets/templates/auth/otp/otp.pt-br.html")
}
@Get("web-logo")
async logo() {
const data = await this.assets.fetchFromWebClient("images/logo.png")
return { size: (data as ArrayBuffer).byteLength }
}
}
Envio via SMTP com Handlebars. Prefixa assunto com APP_NAME e permite desabilitar envios com SMTP_DISABLED.
import { Controller, Post, Body } from "@nestjs/common"
import { EmailService } from "@soulsys/api/core"
@Controller("notifications")
export class NotificationsController {
constructor(private email: EmailService) {}
@Post("welcome")
async sendWelcome(@Body("to") to: string) {
await this.email.send({
to,
subject: "Bem-vindo",
template: {
path: "core/assets/templates/auth/invitation/invitation.pt-br.html",
data: { appName: "Minha App", companyName: "Empresa" },
},
})
return { sent: true }
}
}
Construtor baseado em pdfkit que usa cor primária (WEB_CLIENT_PRIMARY_COLOR) e logo do web client.
import { Controller, Get, Res } from "@nestjs/common"
import { Response } from "express"
import { PdfService } from "@soulsys/api/core"
@Controller("docs")
export class DocsController {
constructor(private pdf: PdfService) {}
@Get("invoice")
async invoice(@Res() res: Response) {
const sysPdf = await this.pdf.createInstance().init({ hasFooter: true })
sysPdf.regularFont().text("Fatura #123", { align: "left" })
sysPdf.doc.end()
res.setHeader("Content-Type", "application/pdf")
sysPdf.doc.pipe(res)
}
}
Excel
Leitura e escrita de planilhas (write-excel-file e read-excel-file). Trabalha com Buffer ou base64.
import { Controller, Get, Post, Body } from "@nestjs/common"
import { ExcelService } from "@soulsys/api/core"
@Controller("excel")
export class ExcelController {
constructor(private excel: ExcelService) {}
@Get("sample")
async sample() {
const buffer = await this.excel.create([
[
{ value: "Nome", fontWeight: "bold" },
{ value: "Email", fontWeight: "bold" },
],
[{ value: "Alice" }, { value: "alice@soulsys.tech" }],
])
return { fileBase64: buffer.toString("base64") }
}
@Post("read")
async read(@Body("fileBase64") fileBase64: string) {
const rows = await this.excel.read({ fileAsBase64: fileBase64 })
return { rows }
}
}
Storage
Upload e download de arquivos binários via API. Os dados são persistidos no banco (tabela storage).
POST /api/sys/storage/upload(multipart, campofile): retorna metadata e URL de download.GET /api/sys/storage/:id: metadata com URL.GET /api/sys/storage/:id/download: conteúdo do arquivo.DELETE /api/sys/storage/:id: remove o arquivo.
Exemplo de upload (cURL):
curl -X POST http://localhost:3000/api/sys/storage/upload \
-H "Authorization: Bearer <token>" \
-F "file=@/caminho/arquivo.pdf"
Pontos de Entrada
Permite registrar callbacks por evento e invocá-los dinamicamente.
import { Injectable } from "@nestjs/common"
import { EntryPoint, EntryPointService } from "@soulsys/api/core"
@Injectable()
export class IntegrationListener {
@EntryPoint("customer.created")
onCustomerCreated(payload: any) {
// lógica customizada
}
}
// Em outro serviço
await this.entryPointService.discoverProviders()
await this.entryPointService.call("customer.created", { id: "123" })
HTTP
Classe base para padronizar integrações HTTP externas. Sobrescreva getApiUrl e getHeaders.
import { Injectable } from "@nestjs/common"
import { HttpService } from "@soulsys/api/core"
@Injectable()
export class CrmHttp extends HttpService {
async getHeaders() {
return {
Authorization: "Bearer " + process.env.CRM_TOKEN,
}
}
async getApiUrl(path: string) {
return `https://crm.example.com${path}`
}
}
// Uso
await this.crmHttp.post("/contacts", { name: "Cliente" })
Socket
SocketGateway inicializa o socket.io com CORS liberado e expõe o server em SocketService para emitir eventos.
import { Injectable } from "@nestjs/common"
import { SocketService } from "@soulsys/api/core"
@Injectable()
export class NotificationsEmitter {
constructor(private socket: SocketService) {}
notifyAll(event: string, data: any) {
this.socket.server?.emit(event, data)
}
}
Logger
LoggerService herda de @nestjs/common e prefixa logs com APP_NAME e versão (npm_package_version). O LoggerGuard pode registrar requisições automaticamente quando REQUEST_LOGGER=true.
Variáveis de Ambiente
Defina todas as variáveis no arquivo _plataforma/api/.env_.
Servidor
| Variável | Descrição |
|---|---|
| DEV_ENV | Ajusta comportamentos de desenvolvimento (ex.: limites de throttling). |
| PORT | Porta HTTP da API. |
| APP_NAME | Nome exibido em logs e e-mails. |
| COMPANY_NAME | Empresa responsável (usada em templates). |
| REQUEST_LOGGER | Ativa o LoggerGuard para registrar cada requisição. |
| ENSURE_HTTPS | Redireciona HTTP para HTTPS usando express-sslify. |
Banco de dados
| Variável | Descrição |
|---|---|
| DATABASE_URL | String de conexão utilizada pelo Prisma. |
Autenticação
| Variável | Descrição |
|---|---|
| AUTH_OTP | Habilita a etapa de OTP no login. |
| AUTH_ACCESS_TOKEN_MINUTES | Validade (minutos) do access token. |
| AUTH_REFRESH_TOKEN_DAYS | Validade (dias) do refresh token. |
| AUTH_PSW_MIN_LENGTH | Tamanho mínimo da senha. |
| AUTH_PSW_CHANGE_AFTER_DAYS | Dias para expiração da senha. |
| AUTH_PSW_MIXED_CHARS | Exige mistura de maiúsculas, minúsculas e caracteres especiais. |
| AUTH_PSW_UPDATE_URL | URL da página de redefinição de senha utilizada em e-mails. |
| AUTH_ROOT_EMAIL | E-mail do usuário admin criado no seed inicial. |
| AUTH_JWT_SECRET | Chave usada para assinar tokens JWT. |
Web Client
| Variável | Descrição |
|---|---|
| WEB_CLIENT_ASSETS_URL | URL base dos assets do frontend (usada para logo e templates). |
| WEB_CLIENT_PRIMARY_COLOR | Cor primária aplicada em PDFs e templates. |
| WEB_CLIENT_PRIMARY_COLOR_HOVER | Cor de hover complementar. |
SMTP
| Variável | Descrição |
|---|---|
| SMTP_SERVER | Host SMTP. |
| SMTP_PORT | Porta SMTP. |
| SMTP_SECURE | Se true, força TLS/SSL. |
| SMTP_LOGIN | Usuário de autenticação. |
| SMTP_PASSWORD | Senha ou token de autenticação. |
| SMTP_FROM | Remetente padrão dos e-mails. |
| SMTP_DISABLED | Desativa envios (útil para ambientes de teste). |
Com o CoreModule configurado, os demais módulos da plataforma podem focar apenas nas regras de negócio, reutilizando autenticação, armazenamento, internacionalização e utilitários já padronizados.