zeti-framework 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +244 -0
- package/dist/core/framework.d.ts +48 -0
- package/dist/core/framework.d.ts.map +1 -0
- package/dist/core/framework.js +236 -0
- package/dist/core/framework.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/scripts/generate-registry.d.ts +8 -0
- package/dist/scripts/generate-registry.d.ts.map +1 -0
- package/dist/scripts/generate-registry.js +34 -0
- package/dist/scripts/generate-registry.js.map +1 -0
- package/dist/scripts/generate-swagger-types.d.ts +6 -0
- package/dist/scripts/generate-swagger-types.d.ts.map +1 -0
- package/dist/scripts/generate-swagger-types.js +196 -0
- package/dist/scripts/generate-swagger-types.js.map +1 -0
- package/dist/scripts/index.d.ts +3 -0
- package/dist/scripts/index.d.ts.map +1 -0
- package/dist/scripts/index.js +3 -0
- package/dist/scripts/index.js.map +1 -0
- package/dist/swagger/generator.d.ts +14 -0
- package/dist/swagger/generator.d.ts.map +1 -0
- package/dist/swagger/generator.js +146 -0
- package/dist/swagger/generator.js.map +1 -0
- package/dist/swagger/index.d.ts +4 -0
- package/dist/swagger/index.d.ts.map +1 -0
- package/dist/swagger/index.js +4 -0
- package/dist/swagger/index.js.map +1 -0
- package/dist/swagger/registry.d.ts +8 -0
- package/dist/swagger/registry.d.ts.map +1 -0
- package/dist/swagger/registry.js +13 -0
- package/dist/swagger/registry.js.map +1 -0
- package/dist/swagger/zod-converter.d.ts +3 -0
- package/dist/swagger/zod-converter.d.ts.map +1 -0
- package/dist/swagger/zod-converter.js +48 -0
- package/dist/swagger/zod-converter.js.map +1 -0
- package/dist/tenants/index.d.ts +3 -0
- package/dist/tenants/index.d.ts.map +1 -0
- package/dist/tenants/index.js +3 -0
- package/dist/tenants/index.js.map +1 -0
- package/dist/tenants/manager.d.ts +24 -0
- package/dist/tenants/manager.d.ts.map +1 -0
- package/dist/tenants/manager.js +179 -0
- package/dist/tenants/manager.js.map +1 -0
- package/dist/tenants/metrics.d.ts +31 -0
- package/dist/tenants/metrics.d.ts.map +1 -0
- package/dist/tenants/metrics.js +51 -0
- package/dist/tenants/metrics.js.map +1 -0
- package/dist/types/config.d.ts +67 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +4 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/framework.d.ts +65 -0
- package/dist/types/framework.d.ts.map +1 -0
- package/dist/types/framework.js +2 -0
- package/dist/types/framework.js.map +1 -0
- package/dist/types/prisma.d.ts +37 -0
- package/dist/types/prisma.d.ts.map +1 -0
- package/dist/types/prisma.js +11 -0
- package/dist/types/prisma.js.map +1 -0
- package/dist/utils/error-handler.d.ts +31 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +102 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# @zeti/framework
|
|
2
|
+
|
|
3
|
+
Framework Hono com suporte a multi-tenancy, Prisma e Swagger automático.
|
|
4
|
+
|
|
5
|
+
## 🚀 Instalação
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @zeti/framework @prisma/client
|
|
9
|
+
# ou
|
|
10
|
+
pnpm add @zeti/framework @prisma/client
|
|
11
|
+
# ou
|
|
12
|
+
yarn add @zeti/framework @prisma/client
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 🔨 Build
|
|
16
|
+
|
|
17
|
+
A biblioteca usa TypeScript compiler padrão, funciona com qualquer gerenciador de pacotes:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Build
|
|
21
|
+
npm run build
|
|
22
|
+
|
|
23
|
+
# Desenvolvimento (watch mode)
|
|
24
|
+
npm run dev
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
> **Nota sobre Performance:** O uso de `tsc` ao invés de Bun não afeta a performance da biblioteca em runtime. O código JavaScript compilado é idêntico e roda com a mesma velocidade. A única diferença é no tempo de build durante desenvolvimento. Veja `PERFORMANCE.md` para mais detalhes.
|
|
28
|
+
|
|
29
|
+
## 📖 Uso Básico
|
|
30
|
+
|
|
31
|
+
### 1. Configuração
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// zeti.config.ts
|
|
35
|
+
import { defineZetiConfig } from '@zeti/framework';
|
|
36
|
+
import { PrismaClient } from '@prisma/client';
|
|
37
|
+
|
|
38
|
+
export default defineZetiConfig({
|
|
39
|
+
databases: {
|
|
40
|
+
connections: {
|
|
41
|
+
main: process.env.DATABASE_URL!,
|
|
42
|
+
mongo: process.env.MONGO_URL!,
|
|
43
|
+
},
|
|
44
|
+
cache: {
|
|
45
|
+
maxClients: 50,
|
|
46
|
+
ttl: 300000,
|
|
47
|
+
cleanupInterval: 60000,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
specialDatabases: {
|
|
51
|
+
analytics: process.env.ANALYTICS_DB_URL!,
|
|
52
|
+
},
|
|
53
|
+
prisma: {
|
|
54
|
+
adapter: 'pg',
|
|
55
|
+
logLevel: ['error'],
|
|
56
|
+
},
|
|
57
|
+
swagger: {
|
|
58
|
+
enabled: true,
|
|
59
|
+
title: 'My API',
|
|
60
|
+
version: '1.0.0',
|
|
61
|
+
servers: [{ url: 'http://localhost:3334' }],
|
|
62
|
+
},
|
|
63
|
+
errorHandler: {
|
|
64
|
+
// Opcional: customizar formatação de erros
|
|
65
|
+
formatError: (error, context) => {
|
|
66
|
+
// Sua lógica customizada
|
|
67
|
+
return { data: null, status: 500, message: 'Error' };
|
|
68
|
+
},
|
|
69
|
+
// Opcional: customizar logging
|
|
70
|
+
logError: (error, context) => {
|
|
71
|
+
console.error('Error:', error);
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
middlewares: {
|
|
75
|
+
global: [
|
|
76
|
+
// Middlewares globais
|
|
77
|
+
],
|
|
78
|
+
named: {
|
|
79
|
+
// Middlewares nomeados
|
|
80
|
+
auth: createAuthMiddleware({ jwtSecret: '...' }),
|
|
81
|
+
requireRole: (roles: string[]) => createRoleMiddleware(roles),
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 2. Inicialização
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// src/zeti/index.ts
|
|
91
|
+
import { createZetiApp } from '@zeti/framework';
|
|
92
|
+
import { PrismaClient } from '@prisma/client';
|
|
93
|
+
import config from '../../zeti.config';
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* IMPORTANTE: Passe o PrismaClient como generic para inferência de tipos
|
|
97
|
+
*
|
|
98
|
+
* Isso permite que TypeScript saiba todos os modelos do seu schema.prisma
|
|
99
|
+
* e forneça autocomplete completo em todas as rotas!
|
|
100
|
+
*/
|
|
101
|
+
const app = createZetiApp<PrismaClient>({
|
|
102
|
+
config,
|
|
103
|
+
prismaClient: PrismaClient,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
export const { get, post, put, del, patch } = app;
|
|
107
|
+
export const { honoApp } = app;
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 3. Criar Rotas
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// src/controllers/users/get.ts
|
|
114
|
+
import { get } from '../../zeti';
|
|
115
|
+
|
|
116
|
+
get('/users', {
|
|
117
|
+
middleware: {
|
|
118
|
+
use: ['auth'],
|
|
119
|
+
schema: (z) => ({
|
|
120
|
+
query: {
|
|
121
|
+
page: z.number().optional(),
|
|
122
|
+
},
|
|
123
|
+
}),
|
|
124
|
+
},
|
|
125
|
+
route: async ({ db, query, user }) => {
|
|
126
|
+
/**
|
|
127
|
+
* db é automaticamente tipado como PrismaClient do seu projeto!
|
|
128
|
+
*
|
|
129
|
+
* TypeScript sabe todos os modelos do seu schema.prisma:
|
|
130
|
+
* - db.user ✅
|
|
131
|
+
* - db.post ✅
|
|
132
|
+
* - etc...
|
|
133
|
+
*
|
|
134
|
+
* Autocomplete funciona perfeitamente!
|
|
135
|
+
*/
|
|
136
|
+
const users = await db.user.findMany({
|
|
137
|
+
skip: query.page ? (query.page - 1) * 10 : 0,
|
|
138
|
+
take: 10,
|
|
139
|
+
});
|
|
140
|
+
return { data: users };
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## 🔍 Como Funciona a Inferência de Tipos?
|
|
146
|
+
|
|
147
|
+
A biblioteca usa **TypeScript Generics** para propagar o tipo do `PrismaClient` do seu projeto para todas as rotas.
|
|
148
|
+
|
|
149
|
+
### Fluxo de Inferência
|
|
150
|
+
|
|
151
|
+
1. **Você passa o tipo:**
|
|
152
|
+
```typescript
|
|
153
|
+
const app = createZetiApp<PrismaClient>({ ... });
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
2. **Biblioteca propaga o tipo:**
|
|
157
|
+
```typescript
|
|
158
|
+
// Internamente
|
|
159
|
+
ZetiApp<TPrisma> → ZetiMethodOptions<..., TPrisma> → ZetiRouteProps<..., TPrisma>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
3. **Nas rotas, `db` é tipado automaticamente:**
|
|
163
|
+
```typescript
|
|
164
|
+
route: async ({ db }) => {
|
|
165
|
+
// db é PrismaClient do seu projeto!
|
|
166
|
+
await db.user.findMany(); // ✅ Autocomplete funciona!
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Veja `examples/type-inference-explained.md` para explicação detalhada.
|
|
171
|
+
|
|
172
|
+
## 🔧 Middlewares Customizados
|
|
173
|
+
|
|
174
|
+
A biblioteca não implementa lógica de negócio. Você define seus próprios middlewares:
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// src/middleware/auth.ts
|
|
178
|
+
import { Middleware } from 'hono';
|
|
179
|
+
|
|
180
|
+
export function createAuthMiddleware(config: {
|
|
181
|
+
jwtSecret: string;
|
|
182
|
+
}): Middleware {
|
|
183
|
+
return async (c, next) => {
|
|
184
|
+
// Sua lógica de autenticação
|
|
185
|
+
const user = await verifyToken(c.req.header('authorization'));
|
|
186
|
+
c.set('user', user);
|
|
187
|
+
await next();
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## 🔧 Scripts de Geração
|
|
193
|
+
|
|
194
|
+
A biblioteca inclui scripts para gerar automaticamente:
|
|
195
|
+
|
|
196
|
+
### 1. Registry de Controllers
|
|
197
|
+
|
|
198
|
+
Gera imports automáticos dos controllers:
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import { generateRegistry } from '@zeti/framework';
|
|
202
|
+
|
|
203
|
+
await generateRegistry({
|
|
204
|
+
controllersPath: './src/controllers',
|
|
205
|
+
indexPath: './src/zeti/index.ts',
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 2. Tipos do Swagger
|
|
210
|
+
|
|
211
|
+
Gera schemas Zod a partir dos tipos de retorno das rotas:
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
import { generateSwaggerTypes } from '@zeti/framework';
|
|
215
|
+
|
|
216
|
+
await generateSwaggerTypes({
|
|
217
|
+
controllersPath: './src/controllers',
|
|
218
|
+
outputPath: './src/zeti/swagger-schemas.generated.ts',
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Uso no package.json
|
|
223
|
+
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"scripts": {
|
|
227
|
+
"prebuild": "node --loader ts-node/esm scripts/generate-swagger.ts",
|
|
228
|
+
"build": "tsc"
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Veja `examples/scripts-usage.ts` para mais detalhes.
|
|
234
|
+
|
|
235
|
+
## 📚 Documentação Completa
|
|
236
|
+
|
|
237
|
+
- `examples/scripts-usage.ts` - Uso dos scripts de geração
|
|
238
|
+
- `examples/graceful-shutdown.ts` - Graceful shutdown
|
|
239
|
+
- `examples/database-config-example.ts` - Configuração de databases
|
|
240
|
+
- `examples/metrics-usage.ts` - Uso de métricas
|
|
241
|
+
|
|
242
|
+
## 📝 Licença
|
|
243
|
+
|
|
244
|
+
MIT
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import type { PrismaClientBase } from '../types/prisma';
|
|
3
|
+
import type { ZetiConfig } from '../types/config';
|
|
4
|
+
import type { ZetiMethodOptions, SchemaDefinition } from '../types/framework';
|
|
5
|
+
import { TenantManager } from '../tenants/manager';
|
|
6
|
+
import { SwaggerRegistry } from '../swagger/registry';
|
|
7
|
+
export interface ZetiApp<TPrisma extends PrismaClientBase = PrismaClientBase, TUser = any> {
|
|
8
|
+
get: <TPath extends string, TSchema extends SchemaDefinition = {}>(url: TPath, options: ZetiMethodOptions<TPath, TSchema, TPrisma, TUser>) => void;
|
|
9
|
+
post: <TPath extends string, TSchema extends SchemaDefinition = {}>(url: TPath, options: ZetiMethodOptions<TPath, TSchema, TPrisma, TUser>) => void;
|
|
10
|
+
put: <TPath extends string, TSchema extends SchemaDefinition = {}>(url: TPath, options: ZetiMethodOptions<TPath, TSchema, TPrisma, TUser>) => void;
|
|
11
|
+
del: <TPath extends string, TSchema extends SchemaDefinition = {}>(url: TPath, options: ZetiMethodOptions<TPath, TSchema, TPrisma, TUser>) => void;
|
|
12
|
+
patch: <TPath extends string, TSchema extends SchemaDefinition = {}>(url: TPath, options: ZetiMethodOptions<TPath, TSchema, TPrisma, TUser>) => void;
|
|
13
|
+
honoApp: Hono;
|
|
14
|
+
swaggerRegistry: SwaggerRegistry;
|
|
15
|
+
tenantManager: TenantManager;
|
|
16
|
+
shutdown: () => Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Cria uma instância do Zeti App
|
|
20
|
+
*
|
|
21
|
+
* @template TPrisma - Tipo do PrismaClient do projeto do usuário
|
|
22
|
+
* @template TUser - Tipo do usuário autenticado (opcional)
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import { PrismaClient } from '@prisma/client';
|
|
27
|
+
*
|
|
28
|
+
* const app = createZetiApp<PrismaClient>({
|
|
29
|
+
* config,
|
|
30
|
+
* prismaClient: PrismaClient,
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Agora todas as rotas terão db tipado como PrismaClient do usuário
|
|
34
|
+
* app.get('/users', {
|
|
35
|
+
* route: async ({ db }) => {
|
|
36
|
+
* // db é tipado como PrismaClient do usuário
|
|
37
|
+
* // Com todos os modelos do schema.prisma
|
|
38
|
+
* const users = await db.user.findMany();
|
|
39
|
+
* return { data: users };
|
|
40
|
+
* },
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function createZetiApp<TPrisma extends PrismaClientBase = PrismaClientBase, TUser = any>(options: {
|
|
45
|
+
config: ZetiConfig;
|
|
46
|
+
prismaClient: new (...args: any[]) => TPrisma;
|
|
47
|
+
}): ZetiApp<TPrisma, TUser>;
|
|
48
|
+
//# sourceMappingURL=framework.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework.d.ts","sourceRoot":"","sources":["../../src/core/framework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EACV,iBAAiB,EAEjB,gBAAgB,EAKjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAItD,MAAM,WAAW,OAAO,CACtB,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,EACnD,KAAK,GAAG,GAAG;IAEX,GAAG,EAAE,CAAC,KAAK,SAAS,MAAM,EAAE,OAAO,SAAS,gBAAgB,GAAG,EAAE,EAC/D,GAAG,EAAE,KAAK,EACV,OAAO,EAAE,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,KACvD,IAAI,CAAC;IAEV,IAAI,EAAE,CAAC,KAAK,SAAS,MAAM,EAAE,OAAO,SAAS,gBAAgB,GAAG,EAAE,EAChE,GAAG,EAAE,KAAK,EACV,OAAO,EAAE,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,KACvD,IAAI,CAAC;IAEV,GAAG,EAAE,CAAC,KAAK,SAAS,MAAM,EAAE,OAAO,SAAS,gBAAgB,GAAG,EAAE,EAC/D,GAAG,EAAE,KAAK,EACV,OAAO,EAAE,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,KACvD,IAAI,CAAC;IAEV,GAAG,EAAE,CAAC,KAAK,SAAS,MAAM,EAAE,OAAO,SAAS,gBAAgB,GAAG,EAAE,EAC/D,GAAG,EAAE,KAAK,EACV,OAAO,EAAE,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,KACvD,IAAI,CAAC;IAEV,KAAK,EAAE,CAAC,KAAK,SAAS,MAAM,EAAE,OAAO,SAAS,gBAAgB,GAAG,EAAE,EACjE,GAAG,EAAE,KAAK,EACV,OAAO,EAAE,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,KACvD,IAAI,CAAC;IAEV,OAAO,EAAE,IAAI,CAAC;IACd,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,aAAa,CAC3B,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,EACnD,KAAK,GAAG,GAAG,EACX,OAAO,EAAE;IACT,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC;CAC/C,GAAG,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CA4P1B"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { zValidator } from '@hono/zod-validator';
|
|
4
|
+
import { TenantManager } from '../tenants/manager';
|
|
5
|
+
import { SwaggerRegistry } from '../swagger/registry';
|
|
6
|
+
import { createErrorHandler } from '../utils/error-handler';
|
|
7
|
+
/**
|
|
8
|
+
* Cria uma instância do Zeti App
|
|
9
|
+
*
|
|
10
|
+
* @template TPrisma - Tipo do PrismaClient do projeto do usuário
|
|
11
|
+
* @template TUser - Tipo do usuário autenticado (opcional)
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { PrismaClient } from '@prisma/client';
|
|
16
|
+
*
|
|
17
|
+
* const app = createZetiApp<PrismaClient>({
|
|
18
|
+
* config,
|
|
19
|
+
* prismaClient: PrismaClient,
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Agora todas as rotas terão db tipado como PrismaClient do usuário
|
|
23
|
+
* app.get('/users', {
|
|
24
|
+
* route: async ({ db }) => {
|
|
25
|
+
* // db é tipado como PrismaClient do usuário
|
|
26
|
+
* // Com todos os modelos do schema.prisma
|
|
27
|
+
* const users = await db.user.findMany();
|
|
28
|
+
* return { data: users };
|
|
29
|
+
* },
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export function createZetiApp(options) {
|
|
34
|
+
const { config, prismaClient: PrismaClientClass } = options;
|
|
35
|
+
const honoApp = new Hono();
|
|
36
|
+
const tenantManager = new TenantManager(config.databases, config.prisma, config.specialDatabases);
|
|
37
|
+
const swaggerRegistry = new SwaggerRegistry();
|
|
38
|
+
if (config.errorHandler !== false) {
|
|
39
|
+
const errorHandlerConfig = typeof config.errorHandler === 'object' ? config.errorHandler : undefined;
|
|
40
|
+
honoApp.use('*', createErrorHandler(errorHandlerConfig));
|
|
41
|
+
}
|
|
42
|
+
const createMethod = (httpMethod) => {
|
|
43
|
+
return (url, options) => {
|
|
44
|
+
const middlewares = [];
|
|
45
|
+
if (config.middlewares?.global) {
|
|
46
|
+
middlewares.push(...config.middlewares.global);
|
|
47
|
+
}
|
|
48
|
+
let bodySchema = undefined;
|
|
49
|
+
let querySchema = undefined;
|
|
50
|
+
let responseSchema = undefined;
|
|
51
|
+
if (options.middleware?.schema) {
|
|
52
|
+
const schemaResult = options.middleware.schema(z);
|
|
53
|
+
if (schemaResult.body) {
|
|
54
|
+
bodySchema =
|
|
55
|
+
schemaResult.body instanceof z.ZodType
|
|
56
|
+
? schemaResult.body
|
|
57
|
+
: z.object(schemaResult.body);
|
|
58
|
+
middlewares.push(zValidator('json', bodySchema));
|
|
59
|
+
}
|
|
60
|
+
if (schemaResult.query) {
|
|
61
|
+
querySchema =
|
|
62
|
+
schemaResult.query instanceof z.ZodType
|
|
63
|
+
? schemaResult.query
|
|
64
|
+
: z.object(schemaResult.query);
|
|
65
|
+
middlewares.push(zValidator('query', querySchema));
|
|
66
|
+
}
|
|
67
|
+
if (schemaResult.response) {
|
|
68
|
+
responseSchema =
|
|
69
|
+
schemaResult.response instanceof z.ZodType
|
|
70
|
+
? schemaResult.response
|
|
71
|
+
: z.object(schemaResult.response);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (options.middleware?.use) {
|
|
75
|
+
for (const middlewareName of options.middleware.use) {
|
|
76
|
+
const [name, paramsString] = middlewareName.split(':');
|
|
77
|
+
const middlewareFactory = config.middlewares?.named?.[name];
|
|
78
|
+
if (!middlewareFactory) {
|
|
79
|
+
throw new Error(`Middleware '${name}' não encontrado`);
|
|
80
|
+
}
|
|
81
|
+
if (typeof middlewareFactory === 'function') {
|
|
82
|
+
if (paramsString) {
|
|
83
|
+
const params = paramsString.split(',').map((p) => p.trim());
|
|
84
|
+
const middleware = middlewareFactory(params);
|
|
85
|
+
middlewares.push(middleware);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const middleware = middlewareFactory();
|
|
89
|
+
middlewares.push(middleware);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
middlewares.push(middlewareFactory);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Verifica se tenant está habilitado na config
|
|
98
|
+
const tenantEnabled = config.tenant?.enabled !== false;
|
|
99
|
+
const tenantRequired = config.tenant?.required !== false;
|
|
100
|
+
const tenantHeaderName = config.tenant?.headerName || config.headers?.tenant || 'x-tenant';
|
|
101
|
+
// Só valida tenant se estiver habilitado e a rota não usar banco especial
|
|
102
|
+
if (tenantEnabled && tenantRequired && !options.middleware?.database) {
|
|
103
|
+
// Se a rota não desabilitou explicitamente o tenant
|
|
104
|
+
if (options.middleware?.tenant !== false) {
|
|
105
|
+
middlewares.push(async (c, next) => {
|
|
106
|
+
const tenantId = c.req.header(tenantHeaderName);
|
|
107
|
+
if (!tenantId) {
|
|
108
|
+
return c.json({
|
|
109
|
+
data: null,
|
|
110
|
+
status: 400,
|
|
111
|
+
message: `Header ${tenantHeaderName} é obrigatório`,
|
|
112
|
+
}, 400);
|
|
113
|
+
}
|
|
114
|
+
if (!tenantManager.isValidDatabase(tenantId)) {
|
|
115
|
+
const available = tenantManager.getAllDatabases().join(', ');
|
|
116
|
+
return c.json({
|
|
117
|
+
data: null,
|
|
118
|
+
status: 404,
|
|
119
|
+
message: `Database '${tenantId}' not found. Available: ${available || 'none'}`,
|
|
120
|
+
}, 404);
|
|
121
|
+
}
|
|
122
|
+
await next();
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
swaggerRegistry.register({
|
|
127
|
+
path: url,
|
|
128
|
+
method: httpMethod,
|
|
129
|
+
auth: options.middleware?.use?.includes('auth') || false,
|
|
130
|
+
bodySchema,
|
|
131
|
+
querySchema,
|
|
132
|
+
responseSchema,
|
|
133
|
+
});
|
|
134
|
+
if (config.hooks?.onRouteRegister) {
|
|
135
|
+
config.hooks.onRouteRegister({
|
|
136
|
+
path: url,
|
|
137
|
+
method: httpMethod,
|
|
138
|
+
auth: options.middleware?.use?.includes('auth') || false,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
honoApp.use(url, ...middlewares);
|
|
142
|
+
honoApp[httpMethod](url, async (c, next) => {
|
|
143
|
+
try {
|
|
144
|
+
if (config.hooks?.onRequest) {
|
|
145
|
+
await config.hooks.onRequest(c);
|
|
146
|
+
}
|
|
147
|
+
const timezone = c.req.header(config.headers?.timezone || 'timezone');
|
|
148
|
+
const tenantHeaderName = config.tenant?.headerName || config.headers?.tenant || 'x-tenant';
|
|
149
|
+
const tenantId = c.req.header(tenantHeaderName);
|
|
150
|
+
const specialDatabase = options.middleware?.database;
|
|
151
|
+
const context = Object.assign(c, {
|
|
152
|
+
ipAddress: c.req.header('x-forwarded-for')?.split(',')[0] ||
|
|
153
|
+
c.req.header('x-real-ip'),
|
|
154
|
+
userAgent: c.req.header('user-agent'),
|
|
155
|
+
timezone: timezone || 'UTC',
|
|
156
|
+
tenantId: tenantId || '',
|
|
157
|
+
});
|
|
158
|
+
const params = c.req.param();
|
|
159
|
+
const body = c.req.valid?.('json');
|
|
160
|
+
const query = c.req.valid?.('query');
|
|
161
|
+
const user = c.get('user');
|
|
162
|
+
let database;
|
|
163
|
+
// Se usar banco especial, pega ele
|
|
164
|
+
if (specialDatabase) {
|
|
165
|
+
database = tenantManager.getSpecialDatabase(specialDatabase);
|
|
166
|
+
}
|
|
167
|
+
// Se tenant está habilitado e foi fornecido, usa o tenant
|
|
168
|
+
else if (config.tenant?.enabled !== false && tenantId) {
|
|
169
|
+
database = (await tenantManager.getTenantDatabase(tenantId));
|
|
170
|
+
}
|
|
171
|
+
// Se tenant não está habilitado ou não foi fornecido, usa banco padrão
|
|
172
|
+
else {
|
|
173
|
+
const defaultDatabase = config.tenant?.defaultDatabase;
|
|
174
|
+
if (defaultDatabase) {
|
|
175
|
+
database = (await tenantManager.getTenantDatabase(defaultDatabase));
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// Tenta pegar o primeiro banco configurado
|
|
179
|
+
const allDatabases = tenantManager.getAllDatabases();
|
|
180
|
+
if (allDatabases.length > 0) {
|
|
181
|
+
database = (await tenantManager.getTenantDatabase(allDatabases[0]));
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
throw new Error('Nenhum banco de dados configurado');
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const result = await options.route({
|
|
189
|
+
context: context,
|
|
190
|
+
next,
|
|
191
|
+
params,
|
|
192
|
+
body,
|
|
193
|
+
query,
|
|
194
|
+
user,
|
|
195
|
+
db: database,
|
|
196
|
+
res: {
|
|
197
|
+
goneError: (params) => {
|
|
198
|
+
throw new Error(params.message);
|
|
199
|
+
},
|
|
200
|
+
unauthorizedError: (message) => {
|
|
201
|
+
throw new Error(message);
|
|
202
|
+
},
|
|
203
|
+
badRequestError: (message) => {
|
|
204
|
+
throw new Error(message);
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
let finalResult = result;
|
|
209
|
+
if (config.hooks?.onResponse) {
|
|
210
|
+
finalResult = config.hooks.onResponse(c, result);
|
|
211
|
+
}
|
|
212
|
+
return finalResult instanceof Response
|
|
213
|
+
? finalResult
|
|
214
|
+
: c.json(finalResult);
|
|
215
|
+
}
|
|
216
|
+
catch (err) {
|
|
217
|
+
throw err;
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
return {
|
|
223
|
+
get: createMethod('get'),
|
|
224
|
+
post: createMethod('post'),
|
|
225
|
+
put: createMethod('put'),
|
|
226
|
+
del: createMethod('delete'),
|
|
227
|
+
patch: createMethod('patch'),
|
|
228
|
+
honoApp,
|
|
229
|
+
swaggerRegistry,
|
|
230
|
+
tenantManager,
|
|
231
|
+
shutdown: async () => {
|
|
232
|
+
await tenantManager.shutdown();
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=framework.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework.js","sourceRoot":"","sources":["../../src/core/framework.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './core/framework';
|
|
2
|
+
export * from './types/config';
|
|
3
|
+
export * from './types/framework';
|
|
4
|
+
export * from './types/prisma';
|
|
5
|
+
export * from './tenants/manager';
|
|
6
|
+
export * from './tenants/metrics';
|
|
7
|
+
export * from './swagger/generator';
|
|
8
|
+
export * from './swagger/registry';
|
|
9
|
+
export * from './utils/error-handler';
|
|
10
|
+
export * from './scripts/generate-registry';
|
|
11
|
+
export * from './scripts/generate-swagger-types';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './core/framework';
|
|
2
|
+
export * from './types/config';
|
|
3
|
+
export * from './types/framework';
|
|
4
|
+
export * from './types/prisma';
|
|
5
|
+
export * from './tenants/manager';
|
|
6
|
+
export * from './tenants/metrics';
|
|
7
|
+
export * from './swagger/generator';
|
|
8
|
+
export * from './swagger/registry';
|
|
9
|
+
export * from './utils/error-handler';
|
|
10
|
+
export * from './scripts/generate-registry';
|
|
11
|
+
export * from './scripts/generate-swagger-types';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface GenerateRegistryOptions {
|
|
2
|
+
controllersPath: string;
|
|
3
|
+
indexPath: string;
|
|
4
|
+
startMarker?: string;
|
|
5
|
+
endMarker?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function generateRegistry(options: GenerateRegistryOptions): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=generate-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-registry.d.ts","sourceRoot":"","sources":["../../src/scripts/generate-registry.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,iBAmCtE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fg from 'fast-glob';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { dirname } from 'path';
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
export async function generateRegistry(options) {
|
|
9
|
+
const { controllersPath, indexPath, startMarker = '// @CONTROLLERS_START', endMarker = '// @CONTROLLERS_END', } = options;
|
|
10
|
+
const files = await fg('**/*.ts', { cwd: controllersPath });
|
|
11
|
+
const imports = [];
|
|
12
|
+
for (const file of files) {
|
|
13
|
+
if (file === 'index.ts' || file === 'registry.ts')
|
|
14
|
+
continue;
|
|
15
|
+
const relativePath = path.relative(path.dirname(indexPath), path.join(controllersPath, file));
|
|
16
|
+
const importPath = relativePath.replace(/\\/g, '/').replace(/\.ts$/, '');
|
|
17
|
+
imports.push(`import "${importPath.startsWith('.') ? importPath : './' + importPath}";`);
|
|
18
|
+
}
|
|
19
|
+
const indexContent = fs.existsSync(indexPath)
|
|
20
|
+
? fs.readFileSync(indexPath, 'utf-8')
|
|
21
|
+
: '';
|
|
22
|
+
const generatedBlock = `${startMarker}\n${imports.join('\n')}\n${endMarker}`;
|
|
23
|
+
let newContent;
|
|
24
|
+
if (indexContent.includes(startMarker)) {
|
|
25
|
+
const regex = new RegExp(`${startMarker}[\\s\\S]*?${endMarker}`, 'g');
|
|
26
|
+
newContent = indexContent.replace(regex, generatedBlock);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
newContent = indexContent + (indexContent ? '\n\n' : '') + generatedBlock;
|
|
30
|
+
}
|
|
31
|
+
fs.writeFileSync(indexPath, newContent);
|
|
32
|
+
console.log(`✅ Injected ${imports.length} controller imports into ${indexPath}`);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=generate-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-registry.js","sourceRoot":"","sources":["../../src/scripts/generate-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,WAAW,CAAC;AAC3B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAStC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAgC;IACrE,MAAM,EACJ,eAAe,EACf,SAAS,EACT,WAAW,GAAG,uBAAuB,EACrC,SAAS,GAAG,qBAAqB,GAClC,GAAG,OAAO,CAAC;IAEZ,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,eAAe,EAAE,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,aAAa;YAAE,SAAS;QAE5D,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9F,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACzE,OAAO,CAAC,IAAI,CAAC,WAAW,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,UAAU,IAAI,CAAC,CAAC;IAC3F,CAAC;IAED,MAAM,YAAY,GAAG,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAC3C,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC;QACrC,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,cAAc,GAAG,GAAG,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;IAE7E,IAAI,UAAkB,CAAC;IACvB,IAAI,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,GAAG,WAAW,aAAa,SAAS,EAAE,EAAE,GAAG,CAAC,CAAC;QACtE,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;IAC3D,CAAC;SAAM,CAAC;QACN,UAAU,GAAG,YAAY,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC;IAC5E,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,cAAc,OAAO,CAAC,MAAM,4BAA4B,SAAS,EAAE,CAAC,CAAC;AACnF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-swagger-types.d.ts","sourceRoot":"","sources":["../../src/scripts/generate-swagger-types.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,2BAA2B;IAC1C,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AASD,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,iBAgN9E"}
|