@ooneex/app 0.0.1 → 0.3.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 CHANGED
@@ -1 +1,410 @@
1
- # @ooneex/router
1
+ # @ooneex/app
2
+
3
+ A core application framework for building modern web applications with Bun. This package provides a unified foundation for routing, middleware, caching, logging, database connections, file storage, and real-time WebSocket communication.
4
+
5
+ ![Bun](https://img.shields.io/badge/Bun-Compatible-orange?style=flat-square&logo=bun)
6
+ ![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue?style=flat-square&logo=typescript)
7
+ ![MIT License](https://img.shields.io/badge/License-MIT-yellow?style=flat-square)
8
+
9
+ ## Features
10
+
11
+ ✅ **HTTP Routing** - Decorator-based route definitions with parameter validation
12
+
13
+ ✅ **WebSocket Support** - Real-time bidirectional communication with pub/sub
14
+
15
+ ✅ **Middleware Pipeline** - Request/response processing with custom middleware
16
+
17
+ ✅ **Caching Integration** - Built-in cache support for Redis and filesystem
18
+
19
+ ✅ **Database Support** - TypeORM integration for PostgreSQL and SQLite
20
+
21
+ ✅ **File Storage** - Storage abstraction for local, Cloudflare R2, and Bunny CDN
22
+
23
+ ✅ **Logging** - Structured logging with terminal and SQLite outputs
24
+
25
+ ✅ **Cron Jobs** - Scheduled task execution with timezone support
26
+
27
+ ✅ **Analytics** - PostHog integration for user behavior tracking
28
+
29
+ ✅ **Email Services** - Nodemailer and Resend integration for transactional emails
30
+
31
+ ✅ **Static Files** - Serve static assets with configurable directories
32
+
33
+ ✅ **SPA Support** - Single-page application routing support
34
+
35
+ ## Installation
36
+
37
+ ### Bun
38
+ ```bash
39
+ bun add @ooneex/app
40
+ ```
41
+
42
+ ### pnpm
43
+ ```bash
44
+ pnpm add @ooneex/app
45
+ ```
46
+
47
+ ### Yarn
48
+ ```bash
49
+ yarn add @ooneex/app
50
+ ```
51
+
52
+ ### npm
53
+ ```bash
54
+ npm install @ooneex/app
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ ### Basic Application Setup
60
+
61
+ ```typescript
62
+ import { App } from '@ooneex/app';
63
+ import { AppEnv } from '@ooneex/app-env';
64
+ import { TerminalLogger } from '@ooneex/logger';
65
+ import { UserModule } from './modules/UserModule';
66
+
67
+ const app = new App({
68
+ modules: [UserModule],
69
+ loggers: [TerminalLogger],
70
+ env: new AppEnv('development'),
71
+ directories: {
72
+ cwd: process.cwd(),
73
+ static: 'public'
74
+ }
75
+ });
76
+
77
+ await app.run();
78
+ ```
79
+
80
+ ### With Full Configuration
81
+
82
+ ```typescript
83
+ import { App } from '@ooneex/app';
84
+ import { AppEnv } from '@ooneex/app-env';
85
+ import { TerminalLogger, SqliteLogger } from '@ooneex/logger';
86
+ import { RedisCache } from '@ooneex/cache';
87
+ import { PostHogAnalytics } from '@ooneex/analytics';
88
+ import { CloudflareStorage } from '@ooneex/storage';
89
+ import { TypeormPgDatabase } from '@ooneex/database';
90
+ import { ResendMailerAdapter } from '@ooneex/mailer';
91
+ import { AuthMiddleware } from './middleware/AuthMiddleware';
92
+ import { CleanupCron } from './cron/CleanupCron';
93
+ import { UserModule, ProductModule } from './modules';
94
+
95
+ const app = new App({
96
+ modules: [UserModule, ProductModule],
97
+ loggers: [TerminalLogger, SqliteLogger],
98
+ analytics: PostHogAnalytics,
99
+ cache: RedisCache,
100
+ storage: CloudflareStorage,
101
+ database: new TypeormPgDatabase(),
102
+ mailer: ResendMailerAdapter,
103
+ cronJobs: [CleanupCron],
104
+ middlewares: [AuthMiddleware],
105
+ env: new AppEnv(process.env.APP_ENV as 'development'),
106
+ directories: {
107
+ cwd: process.cwd(),
108
+ static: 'public'
109
+ }
110
+ });
111
+
112
+ await app.run();
113
+ ```
114
+
115
+ ### Environment Variables
116
+
117
+ ```bash
118
+ # Required
119
+ APP_ENV=development
120
+ PORT=3000
121
+ HOST_NAME=0.0.0.0
122
+
123
+ # Optional (based on services used)
124
+ OPENAI_API_KEY=your_openai_key
125
+ ANTHROPIC_API_KEY=your_anthropic_key
126
+ CACHE_REDIS_URL=redis://localhost:6379
127
+ DATABASE_URL=postgresql://user:pass@localhost:5432/db
128
+ ANALYTICS_POSTHOG_API_KEY=your_posthog_key
129
+ ```
130
+
131
+ ### Creating a Module
132
+
133
+ ```typescript
134
+ import { Route } from '@ooneex/routing';
135
+ import { UserController } from './UserController';
136
+ import { UserEntity } from './UserEntity';
137
+ import type { ModuleType } from '@ooneex/module';
138
+
139
+ export const UserModule: ModuleType = {
140
+ controllers: [UserController],
141
+ entities: [UserEntity]
142
+ };
143
+ ```
144
+
145
+ ### Creating a Controller
146
+
147
+ ```typescript
148
+ import { Route } from '@ooneex/routing';
149
+ import type { IController, ContextType } from '@ooneex/controller';
150
+ import type { IResponse } from '@ooneex/http-response';
151
+
152
+ @Route.http({
153
+ name: 'api.users.list',
154
+ path: '/api/users',
155
+ method: 'GET',
156
+ description: 'List all users'
157
+ })
158
+ class UserListController implements IController {
159
+ public async index(context: ContextType): Promise<IResponse> {
160
+ const users = await context.database?.open(UserEntity);
161
+
162
+ return context.response.json({
163
+ users: users || []
164
+ });
165
+ }
166
+ }
167
+ ```
168
+
169
+ ### WebSocket Routes
170
+
171
+ ```typescript
172
+ import { Route } from '@ooneex/routing';
173
+ import type { IController, ContextType } from '@ooneex/socket';
174
+
175
+ @Route.socket({
176
+ name: 'api.chat.connect',
177
+ path: '/ws/chat',
178
+ description: 'Real-time chat connection'
179
+ })
180
+ class ChatController implements IController {
181
+ public async index(context: ContextType): Promise<IResponse> {
182
+ await context.channel.subscribe();
183
+
184
+ return context.response.json({
185
+ connected: true
186
+ });
187
+ }
188
+ }
189
+ ```
190
+
191
+ ## API Reference
192
+
193
+ ### Classes
194
+
195
+ #### `App`
196
+
197
+ Main application class that bootstraps and runs your web application.
198
+
199
+ **Constructor:**
200
+ ```typescript
201
+ new App(config: AppConfigType)
202
+ ```
203
+
204
+ **Methods:**
205
+
206
+ ##### `init(): Promise<App>`
207
+
208
+ Initializes the application, validates environment variables, and prepares services.
209
+
210
+ **Returns:** Promise resolving to the App instance
211
+
212
+ ##### `run(): Promise<App>`
213
+
214
+ Starts the HTTP server and begins listening for requests.
215
+
216
+ **Returns:** Promise resolving to the App instance
217
+
218
+ **Example:**
219
+ ```typescript
220
+ const app = new App(config);
221
+ await app.init();
222
+ await app.run();
223
+ ```
224
+
225
+ ### Types
226
+
227
+ #### `AppConfigType`
228
+
229
+ ```typescript
230
+ type AppConfigType = {
231
+ modules: ModuleType[];
232
+ loggers: LoggerClassType[];
233
+ analytics?: AnalyticsClassType;
234
+ cache?: CacheClassType;
235
+ storage?: StorageClassType;
236
+ mailer?: MailerClassType;
237
+ rateLimiter?: RateLimiterClassType;
238
+ cronJobs?: CronClassType[];
239
+ database?: IDatabase | ITypeormDatabase;
240
+ env: IAppEnv;
241
+ directories: {
242
+ cwd: string;
243
+ static?: string;
244
+ };
245
+ spa?: Bun.HTMLBundle;
246
+ middlewares?: MiddlewareClassType[] | SocketMiddlewareClassType[];
247
+ };
248
+ ```
249
+
250
+ ### Functions
251
+
252
+ #### `generateRouteDoc()`
253
+
254
+ Generates API documentation from route definitions.
255
+
256
+ #### `generateRouteType()`
257
+
258
+ Generates TypeScript types from route definitions for type-safe API calls.
259
+
260
+ ## Advanced Usage
261
+
262
+ ### Single Page Application (SPA) Mode
263
+
264
+ ```typescript
265
+ import { App } from '@ooneex/app';
266
+
267
+ const app = new App({
268
+ // ... other config
269
+ spa: Bun.html('./dist/index.html')
270
+ });
271
+
272
+ await app.run();
273
+ ```
274
+
275
+ ### Custom Middleware
276
+
277
+ ```typescript
278
+ import { decorator } from '@ooneex/middleware';
279
+ import type { IMiddleware, ContextType } from '@ooneex/middleware';
280
+
281
+ @decorator.middleware()
282
+ class AuthMiddleware implements IMiddleware {
283
+ public async handle(context: ContextType): Promise<ContextType> {
284
+ const token = context.header.get('Authorization');
285
+
286
+ if (!token) {
287
+ context.response.exception('Unauthorized', { status: 401 });
288
+ return context;
289
+ }
290
+
291
+ // Validate token and set user
292
+ context.user = await this.validateToken(token);
293
+
294
+ return context;
295
+ }
296
+ }
297
+ ```
298
+
299
+ ### Cron Jobs
300
+
301
+ ```typescript
302
+ import { Cron, type CronTimeType } from '@ooneex/cron';
303
+ import type { TimeZoneType } from '@ooneex/country';
304
+
305
+ class CleanupCron extends Cron {
306
+ public getTime(): CronTimeType {
307
+ return 'every 1 hours';
308
+ }
309
+
310
+ public getTimeZone(): TimeZoneType | null {
311
+ return 'Europe/Paris';
312
+ }
313
+
314
+ public async job(): Promise<void> {
315
+ // Cleanup logic here
316
+ console.log('Running cleanup...');
317
+ }
318
+ }
319
+ ```
320
+
321
+ ### Accessing Services in Controllers
322
+
323
+ ```typescript
324
+ @Route.http({
325
+ name: 'api.products.create',
326
+ path: '/api/products',
327
+ method: 'POST',
328
+ description: 'Create a new product'
329
+ })
330
+ class ProductCreateController implements IController {
331
+ public async index(context: ContextType): Promise<IResponse> {
332
+ const { logger, cache, storage, database, mailer, analytics } = context;
333
+
334
+ // Use logger
335
+ logger.info('Creating product', { userId: context.user?.id });
336
+
337
+ // Use cache
338
+ await cache?.set('product:latest', context.payload);
339
+
340
+ // Use storage
341
+ const file = context.files['image'];
342
+ if (file) {
343
+ await storage?.putFile('products/image.jpg', file.path);
344
+ }
345
+
346
+ // Use analytics
347
+ analytics?.capture({
348
+ id: context.user?.id || 'anonymous',
349
+ event: 'product_created'
350
+ });
351
+
352
+ return context.response.json({ success: true });
353
+ }
354
+ }
355
+ ```
356
+
357
+ ### Error Handling
358
+
359
+ ```typescript
360
+ import { Exception } from '@ooneex/exception';
361
+ import { HttpStatus } from '@ooneex/http-status';
362
+
363
+ @Route.http({
364
+ name: 'api.users.show',
365
+ path: '/api/users/:id',
366
+ method: 'GET',
367
+ description: 'Get user by ID'
368
+ })
369
+ class UserShowController implements IController {
370
+ public async index(context: ContextType): Promise<IResponse> {
371
+ const { id } = context.params;
372
+
373
+ const user = await this.userRepository.findById(id);
374
+
375
+ if (!user) {
376
+ return context.response.notFound('User not found', {
377
+ data: { id }
378
+ });
379
+ }
380
+
381
+ return context.response.json({ user });
382
+ }
383
+ }
384
+ ```
385
+
386
+ ## License
387
+
388
+ This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
389
+
390
+ ## Contributing
391
+
392
+ Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
393
+
394
+ ### Development Setup
395
+
396
+ 1. Clone the repository
397
+ 2. Install dependencies: `bun install`
398
+ 3. Run tests: `bun run test`
399
+ 4. Build the project: `bun run build`
400
+
401
+ ### Guidelines
402
+
403
+ - Write tests for new features
404
+ - Follow the existing code style
405
+ - Update documentation for API changes
406
+ - Ensure all tests pass before submitting PR
407
+
408
+ ---
409
+
410
+ Made with ❤️ by the Ooneex team
package/dist/index.d.ts CHANGED
@@ -2,28 +2,36 @@ import { AnalyticsClassType } from "@ooneex/analytics";
2
2
  import { IAppEnv } from "@ooneex/app-env";
3
3
  import { CacheClassType } from "@ooneex/cache";
4
4
  import { CronClassType } from "@ooneex/cron";
5
- import { IDatabase, IRedisDatabaseAdapter, ITypeormDatabaseAdapter } from "@ooneex/database";
6
- import { JwtClassType } from "@ooneex/jwt";
5
+ import { IDatabase, ITypeormDatabase } from "@ooneex/database";
7
6
  import { LoggerClassType } from "@ooneex/logger";
8
7
  import { MailerClassType } from "@ooneex/mailer";
9
- import { PermissionClassType } from "@ooneex/permission";
8
+ import { MiddlewareClassType, SocketMiddlewareClassType } from "@ooneex/middleware";
9
+ import { ModuleType } from "@ooneex/module";
10
+ import { RateLimiterClassType } from "@ooneex/rate-limit";
10
11
  import { StorageClassType } from "@ooneex/storage";
11
12
  type AppConfigType = {
12
- logger: LoggerClassType[];
13
+ modules: ModuleType[];
14
+ loggers: LoggerClassType[];
13
15
  analytics?: AnalyticsClassType;
14
16
  cache?: CacheClassType;
15
- permission?: PermissionClassType;
16
17
  storage?: StorageClassType;
17
18
  mailer?: MailerClassType;
19
+ rateLimiter?: RateLimiterClassType;
18
20
  cronJobs?: CronClassType[];
19
- redis?: IRedisDatabaseAdapter;
20
- jwt?: JwtClassType;
21
- database?: IDatabase | ITypeormDatabaseAdapter;
21
+ database?: IDatabase | ITypeormDatabase;
22
22
  env: IAppEnv;
23
+ directories: {
24
+ cwd: string;
25
+ static?: string;
26
+ };
27
+ spa?: Bun.HTMLBundle;
28
+ middlewares?: MiddlewareClassType[] | SocketMiddlewareClassType[];
23
29
  };
24
30
  declare class App {
25
31
  private readonly config;
26
32
  constructor(config: AppConfigType);
33
+ init(): Promise<App>;
34
+ run(): Promise<App>;
27
35
  }
28
36
  import { RouteConfigType } from "@ooneex/routing";
29
37
  declare const generateRouteDoc: (config: RouteConfigType) => Promise<void>;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{container as o,EContainerScope as n}from"@ooneex/container";var T=(s,i)=>({error:(t,r)=>{s.forEach((a)=>{let e=i.get(a);if(e)e.error(t,r)})},warn:(t,r)=>{s.forEach((a)=>{let e=i.get(a);if(e)e.warn(t,r)})},info:(t,r)=>{s.forEach((a)=>{let e=i.get(a);if(e)e.info(t,r)})},debug:(t,r)=>{s.forEach((a)=>{let e=i.get(a);if(e)e.debug(t,r)})},log:(t,r)=>{s.forEach((a)=>{let e=i.get(a);if(e)e.log(t,r)})}});class C{config;constructor(s){this.config=s;let{logger:i,analytics:t,cache:r,storage:a,database:e,env:p,mailer:y,cronJobs:m,permission:c,redis:d,jwt:l}=this.config;if(i.forEach((g)=>{o.add(g,n.Singleton)}),o.addConstant("logger",T(i,o)),p)o.addConstant("app.env",p);if(t)o.add(t,n.Singleton),o.addAlias("analytics",t);if(l)o.add(l,n.Singleton),o.addAlias("jwt",l);if(r)o.add(r,n.Singleton),o.addAlias("cache",r);if(c)o.add(c,n.Singleton),o.addAlias("permission",c);if(a)o.add(a,n.Singleton),o.addAlias("storage",a);if(y)o.add(y,n.Singleton),o.addAlias("mailer",y);if(e)o.addConstant("database",e);if(d)o.addConstant("redis",d);if(m)m.forEach((g)=>{o.add(g,n.Singleton);let f=o.get(g);if(f.isActive())f.start()})}}import{join as x}from"path";import{routeConfigToJsonDoc as u}from"@ooneex/routing";var D=async(s)=>{let t=u(s),r=`${s.name}.json`,a=x(process.cwd(),"docs/routes",r);await Bun.write(a,JSON.stringify(t,null,2))};import{join as L}from"path";import{routeConfigToTypeString as S}from"@ooneex/routing";import{toPascalCase as E}from"@ooneex/utils";var N=async(s)=>{let t=S(s),r=`${s.name}.ts`,a=L(process.cwd(),"types/routes",r),p=`export type ${E(s.name)}RouteType = ${t};
3
- `;await Bun.write(a,p)};export{N as generateRouteType,D as generateRouteDoc,C as App};
2
+ import{container as d,EContainerScope as f}from"@ooneex/container";import{Exception as x}from"@ooneex/exception";import{HttpStatus as w}from"@ooneex/http-status";import{TerminalLogger as Q}from"@ooneex/logger";import{router as B}from"@ooneex/routing";import{AssertAppEnv as X,AssertHostname as Y,AssertPort as Z}from"@ooneex/validation/constraints";import{Environment as I}from"@ooneex/app-env";import{container as g}from"@ooneex/container";import{Exception as b}from"@ooneex/exception";import{HttpRequest as $}from"@ooneex/http-request";import{HttpResponse as O}from"@ooneex/http-response";import{HttpStatus as u}from"@ooneex/http-status";import{Role as V}from"@ooneex/role";import{type as j}from"@ooneex/validation";var C=(t,e)=>{if(t!==null&&typeof t==="object"&&"validate"in t&&typeof t.validate==="function"){let o=t.validate(e);if(!o.isValid)return o.message||"Validation failed"}else if(typeof t==="function"){let o=t(e);if(o instanceof j.errors)return o.summary}return null},S=async(t)=>{let{req:e,server:o}=t,r=o.requestIP(e)?.address??"unknown",n=new O,a={},i=null;if(e.headers.get("content-type")?.includes("application/json"))try{a=await e.json()}catch(l){}else try{i=await e.formData()}catch(l){}let p=new $(e,{params:e.params,payload:a,form:i,ip:r});return{logger:g.get("logger"),analytics:g.get("analytics"),cache:g.get("cache"),storage:g.get("storage"),mailer:g.get("mailer"),database:g.get("database"),app:{env:g.get("app.env")},response:n,request:p,params:p.params,payload:p.payload,queries:p.queries,method:p.method,header:p.header,files:p.files,ip:p.ip,host:p.host,language:p.language,user:null}},h=async(t,e,o)=>{if(e.params)for(let[s,r]of Object.entries(e.params)){let n=C(r,t.params[s]);if(n)return{message:`Invalid parameter "${s}": ${n}`,status:u.Code.BadRequest}}if(e.queries){let s=C(e.queries,t.queries);if(s)return{message:`Invalid query parameters: ${s}`,status:u.Code.BadRequest}}if(e.payload){let s=C(e.payload,t.payload);if(s)return{message:`Invalid payload: ${s}`,status:u.Code.BadRequest}}if(e.env&&e.env.length>0&&!e.env.includes(o))return{message:`Route "${e.name}" is not available in "${o}" environment`,status:u.Code.NotAcceptable};if(e.ip&&e.ip.length>0&&(!t.ip||!e.ip.includes(t.ip)))return{message:`Route "${e.name}" is not available for IP "${t.ip}"`,status:u.Code.NotAcceptable};if(e.host&&e.host.length>0&&!e.host.includes(t.host))return{message:`Route "${e.name}" is not available for host "${t.host}"`,status:u.Code.NotAcceptable};if(e.roles&&e.roles.length>0){if(!t.user||!t.user.roles||t.user.roles.length===0)return{message:`Route "${e.name}" requires authentication`,status:u.Code.Forbidden};let s=new V;if(!e.roles.some((n)=>t.user?.roles.some((a)=>s.hasRole(a,n))))return{message:`Route "${e.name}" is not accessible for user roles`,status:u.Code.NotAcceptable}}if(e.permission){let s=g.get(e.permission);if(s.setUserPermissions(t.user).build(),!await s.check())return{message:`Route "${e.name}" permission denied`,status:u.Code.Forbidden}}return null},E=(t,e)=>{if(t.response){let o=C(t.response,e);if(o)return{message:`Invalid response: ${o}`,status:u.Code.NotAcceptable}}return null},T=(t,e,o,s)=>{return t.response.exception(e,{status:o}).get(s)},F=async(t,e)=>{try{return[await t.index(e),null]}catch(o){if(o instanceof b)return[null,{message:o.message,status:o.status}];if(o instanceof Error)return[null,{message:o.message,status:u.Code.InternalServerError}];return[null,{message:"An unknown error occurred",status:u.Code.InternalServerError}]}},_=async(t,e)=>{let o=t.app.env.env||I.PRODUCTION,s=await h(t,e,o);if(s)return T(t,s.message,s.status,o);let r=g.get(e.controller),[n,a]=await F(r,t);if(a)return T(t,a.message,a.status,o);let i=E(e,n.getData());if(i)return T(t,i.message,i.status,o);return n.get(o)},J=async(t,e)=>{let o=t;for(let s of e)o=await g.get(s).handle(o);return o},P=(t,e=[])=>{let o={};for(let[s,r]of t){let n={};for(let a of r)n[a.method]=async(i,c)=>{let p=await S({req:i,server:c});try{p=await J(p,e)}catch(y){let l=p.app.env.env||I.PRODUCTION,m=y instanceof b?y.status:u.Code.InternalServerError;return T(p,y.message,m,l)}return _(p,a)};o[s]=n}return o};var k=(t,e)=>({error:(o,s)=>{t.forEach((r)=>{let n=e.get(r);if(n)n.error(o,s)})},warn:(o,s)=>{t.forEach((r)=>{let n=e.get(r);if(n)n.warn(o,s)})},info:(o,s)=>{t.forEach((r)=>{let n=e.get(r);if(n)n.info(o,s)})},debug:(o,s)=>{t.forEach((r)=>{let n=e.get(r);if(n)n.debug(o,s)})},log:(o,s)=>{t.forEach((r)=>{let n=e.get(r);if(n)n.log(o,s)})},success:(o,s)=>{t.forEach((r)=>{let n=e.get(r);if(n)n.success(o,s)})}});import{Environment as U}from"@ooneex/app-env";import{container as R}from"@ooneex/container";import{Exception as L}from"@ooneex/exception";import{HttpStatus as M}from"@ooneex/http-status";import{random as W}from"@ooneex/utils";var A=(t)=>{let e={};for(let[o,s]of t)e[o]=async(r,n)=>{let a=await S({req:r,server:n}),i=W.nanoid(30);R.addConstant(i,{context:a,route:s}),n.upgrade(r,{data:{id:i}});return};return e},G=async(t,e)=>{let o=t;for(let s of e)o=await R.get(s).handle(o);return o},v=(t,e,o)=>{return t.response.exception(e,{status:o}),t.channel.send(t.response)},q=async(t,e,o,s=[])=>{let{context:r,route:n}=R.getConstant(e.data.id),a=r.app.env.env||U.PRODUCTION;r.channel={send:async(l)=>{let m=await l.get(a).json();e.send(JSON.stringify(m))},close:(l,m)=>{e.close(l,m)},subscribe:async()=>{e.subscribe(n.name)},isSubscribed:()=>{return e.isSubscribed(n.name)},unsubscribe:async()=>{e.unsubscribe(n.name)},publish:async(l)=>{let m=await l.get(a).json();o.publish(n.name,m)}};let i=JSON.parse(t);r.queries=i.queries,r.payload=i.payload,r.language=i.language;try{r=await G(r,s)}catch(l){let m=l instanceof L?l.status:M.Code.InternalServerError;return v(r,l.message,m)}let c=await h(r,n,a);if(c)return v(r,c.message,c.status);let p=R.get(n.controller);try{r.response=await p.index(r)}catch(l){let m=l instanceof L?l.status:M.Code.InternalServerError,D=l instanceof Error?l.message:"An unknown error occurred";return v(r,D,m)}let y=E(n,r.response.getData());if(y)return v(r,y.message,y.status);return r.channel.send(r.response)};import{join as z}from"path";import{HttpStatus as K}from"@ooneex/http-status";var H=async(t)=>{let{req:e,cwd:o}=t,s=new URL(e.url).pathname,r=z(o,s),n=Bun.file(r);if(await n.exists())return new Response(n);return new Response("File not found",{status:K.Code.NotFound})};class N{config;constructor(t){this.config=t;let{loggers:e,cronJobs:o,analytics:s,cache:r,storage:n,database:a,env:i,mailer:c}=this.config;if(e.forEach((p)=>{d.add(p,f.Singleton),d.get(p).init()}),d.addConstant("logger",k(e,d)),o?.forEach((p)=>{d.add(p,f.Singleton),d.get(p).start()}),i)d.addConstant("app.env",i);if(s)d.add(s,f.Singleton),d.addAlias("analytics",s);if(r)d.add(r,f.Singleton),d.addAlias("cache",r);if(n)d.add(n,f.Singleton),d.addAlias("storage",n);if(c)d.add(c,f.Singleton),d.addAlias("mailer",c);if(a)d.addConstant("database",a)}async init(){let t=Bun.env.APP_ENV,e=Bun.env.PORT?Number.parseInt(Bun.env.PORT,10):3000,o=Bun.env.HOST_NAME??"",r=new X().validate(t);if(!r.isValid)throw new x(`Invalid APP_ENV: ${r.message}`,{status:w.Code.InternalServerError,data:{appEnv:t}});let a=new Z().validate(e);if(!a.isValid)throw new x(`Invalid PORT: ${a.message}`,{status:w.Code.InternalServerError,data:{port:Bun.env.PORT}});let c=new Y().validate(o);if(!c.isValid)throw new x(`Invalid HOST_NAME: ${c.message}`,{status:w.Code.InternalServerError,data:{hostname:o}});return this}async run(){try{await this.init()}catch(i){new Q().error(i),process.exit(1)}let t=d.get("app.env"),e=Bun.env.HOST_NAME||"0.0.0.0",{directories:o}=this.config,s=o.static,{middlewares:r=[]}=this.config,n={...P(B.getHttpRoutes(),r),...A(B.getSocketRoutes())};if(s){let i=s.replace(/^\/+|\/+$/g,"");n[`/${i}/*`]={GET:(c)=>H({req:c,cwd:o.cwd})}}let a=Bun.serve({port:Bun.env.PORT?Number.parseInt(Bun.env.PORT,10):3000,hostname:e,development:t.isLocal,routes:{...n,"/*":this.config.spa||new Response("Not Found",{status:w.Code.NotFound})},websocket:{perMessageDeflate:!0,async message(i,c){await q(c,i,a,r)},async close(i){d.removeConstant(i.data.id)}}});return this}}import{join as ee}from"path";import{routeConfigToJsonDoc as te}from"@ooneex/routing";var oe=async(t)=>{let o=te(t),s=`${t.name}.json`,r=ee(process.cwd(),"docs/routes",s);await Bun.write(r,JSON.stringify(o,null,2))};import{join as re}from"path";import{routeConfigToTypeString as se}from"@ooneex/routing";import{toPascalCase as ne}from"@ooneex/utils";var ae=async(t)=>{let o=se(t),s=`${t.name}.ts`,r=re(process.cwd(),"src/types/routes",s),a=`export type ${ne(t.name)}RouteType = ${o};
3
+ `;await Bun.write(r,a)};export{ae as generateRouteType,oe as generateRouteDoc,N as App};
4
4
 
5
- //# debugId=D7796269F0F59E7F64756E2164756E21
5
+ //# debugId=2EDF5B8BA53E4B9664756E2164756E21
package/dist/index.js.map CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["src/App.ts", "src/logger.ts", "src/generateRouteDoc.ts", "src/generateRouteType.ts"],
3
+ "sources": ["src/App.ts", "src/httpRouteUtils.ts", "src/logger.ts", "src/socketRouteUtils.ts", "src/staticHandler.ts", "src/generateRouteDoc.ts", "src/generateRouteType.ts"],
4
4
  "sourcesContent": [
5
- "import { container, EContainerScope } from \"@ooneex/container\";\nimport { logger as loggerFunc } from \"./logger\";\nimport type { AppConfigType } from \"./types\";\n\nexport class App {\n constructor(private readonly config: AppConfigType) {\n const { logger, analytics, cache, storage, database, env, mailer, cronJobs, permission, redis, jwt } = this.config;\n\n logger.forEach((log) => {\n container.add(log, EContainerScope.Singleton);\n });\n container.addConstant(\"logger\", loggerFunc(logger, container));\n\n if (env) {\n container.addConstant(\"app.env\", env);\n }\n\n if (analytics) {\n container.add(analytics, EContainerScope.Singleton);\n container.addAlias(\"analytics\", analytics);\n }\n\n if (jwt) {\n container.add(jwt, EContainerScope.Singleton);\n container.addAlias(\"jwt\", jwt);\n }\n\n if (cache) {\n container.add(cache, EContainerScope.Singleton);\n container.addAlias(\"cache\", cache);\n }\n\n if (permission) {\n container.add(permission, EContainerScope.Singleton);\n container.addAlias(\"permission\", permission);\n }\n\n if (storage) {\n container.add(storage, EContainerScope.Singleton);\n container.addAlias(\"storage\", storage);\n }\n\n if (mailer) {\n container.add(mailer, EContainerScope.Singleton);\n container.addAlias(\"mailer\", mailer);\n }\n\n if (database) {\n container.addConstant(\"database\", database);\n }\n\n if (redis) {\n container.addConstant(\"redis\", redis);\n }\n\n if (cronJobs) {\n cronJobs.forEach((cronJob) => {\n container.add(cronJob, EContainerScope.Singleton);\n const job = container.get(cronJob);\n if (job.isActive()) {\n job.start();\n }\n });\n }\n }\n}\n",
6
- "import type { IContainer } from \"@ooneex/container\";\nimport type { IException } from \"@ooneex/exception\";\nimport type { ILogger, LoggerClassType, LogsEntity } from \"@ooneex/logger\";\nimport type { ScalarType } from \"@ooneex/types\";\n\nexport const logger = (loggers: LoggerClassType[], container: IContainer) => ({\n error: (message: string | IException, data?: Record<string, ScalarType> & LogsEntity) => {\n loggers.forEach((logger) => {\n const log = container.get<ILogger<Record<string, ScalarType>> | ILogger<LogsEntity>>(logger);\n if (log) {\n log.error(message, data);\n }\n });\n },\n warn: (message: string, data?: Record<string, ScalarType> & LogsEntity) => {\n loggers.forEach((logger) => {\n const log = container.get<ILogger<Record<string, ScalarType>> | ILogger<LogsEntity>>(logger);\n if (log) {\n log.warn(message, data);\n }\n });\n },\n info: (message: string, data?: Record<string, ScalarType> & LogsEntity) => {\n loggers.forEach((logger) => {\n const log = container.get<ILogger<Record<string, ScalarType>> | ILogger<LogsEntity>>(logger);\n if (log) {\n log.info(message, data);\n }\n });\n },\n debug: (message: string, data?: Record<string, ScalarType> & LogsEntity) => {\n loggers.forEach((logger) => {\n const log = container.get<ILogger<Record<string, ScalarType>> | ILogger<LogsEntity>>(logger);\n if (log) {\n log.debug(message, data);\n }\n });\n },\n log: (message: string, data?: Record<string, ScalarType> & LogsEntity) => {\n loggers.forEach((logger) => {\n const log = container.get<ILogger<Record<string, ScalarType>> | ILogger<LogsEntity>>(logger);\n if (log) {\n log.log(message, data);\n }\n });\n },\n});\n",
5
+ "import type { IAppEnv } from \"@ooneex/app-env\";\nimport { container, EContainerScope } from \"@ooneex/container\";\nimport type { ICron } from \"@ooneex/cron\";\nimport { Exception, type IException } from \"@ooneex/exception\";\nimport { HttpStatus } from \"@ooneex/http-status\";\nimport { type ILogger, type LogsEntity, TerminalLogger } from \"@ooneex/logger\";\nimport type { MiddlewareClassType, SocketMiddlewareClassType } from \"@ooneex/middleware\";\nimport { router } from \"@ooneex/routing\";\nimport type { ScalarType } from \"@ooneex/types\";\nimport { AssertAppEnv, AssertHostname, AssertPort } from \"@ooneex/validation/constraints\";\nimport type { BunRequest, ServerWebSocket } from \"bun\";\nimport { formatHttpRoutes } from \"./httpRouteUtils\";\nimport { logger as loggerFunc } from \"./logger\";\nimport { formatSocketRoutes, socketRouteHandler } from \"./socketRouteUtils\";\nimport { staticHandler } from \"./staticHandler\";\nimport type { AppConfigType } from \"./types\";\n\nexport class App {\n constructor(private readonly config: AppConfigType) {\n const { loggers, cronJobs, analytics, cache, storage, database, env, mailer } = this.config;\n\n loggers.forEach((log) => {\n container.add(log, EContainerScope.Singleton);\n const logger = container.get<ILogger<Record<string, ScalarType>> | ILogger<LogsEntity>>(log);\n logger.init();\n });\n container.addConstant(\"logger\", loggerFunc(loggers, container));\n\n cronJobs?.forEach((cronJob) => {\n container.add(cronJob, EContainerScope.Singleton);\n const cron = container.get<ICron>(cronJob);\n cron.start();\n });\n\n if (env) {\n container.addConstant(\"app.env\", env);\n }\n\n if (analytics) {\n container.add(analytics, EContainerScope.Singleton);\n container.addAlias(\"analytics\", analytics);\n }\n\n if (cache) {\n container.add(cache, EContainerScope.Singleton);\n container.addAlias(\"cache\", cache);\n }\n\n if (storage) {\n container.add(storage, EContainerScope.Singleton);\n container.addAlias(\"storage\", storage);\n }\n\n if (mailer) {\n container.add(mailer, EContainerScope.Singleton);\n container.addAlias(\"mailer\", mailer);\n }\n\n if (database) {\n container.addConstant(\"database\", database);\n }\n }\n\n public async init(): Promise<App> {\n const appEnv = Bun.env.APP_ENV;\n const port = Bun.env.PORT ? Number.parseInt(Bun.env.PORT, 10) : 3000;\n const hostname = Bun.env.HOST_NAME ?? \"\";\n\n const appEnvValidator = new AssertAppEnv();\n const appEnvResult = appEnvValidator.validate(appEnv);\n if (!appEnvResult.isValid) {\n throw new Exception(`Invalid APP_ENV: ${appEnvResult.message}`, {\n status: HttpStatus.Code.InternalServerError,\n data: { appEnv },\n });\n }\n\n const portValidator = new AssertPort();\n const portResult = portValidator.validate(port);\n if (!portResult.isValid) {\n throw new Exception(`Invalid PORT: ${portResult.message}`, {\n status: HttpStatus.Code.InternalServerError,\n data: { port: Bun.env.PORT },\n });\n }\n\n const hostnameValidator = new AssertHostname();\n const hostnameResult = hostnameValidator.validate(hostname);\n if (!hostnameResult.isValid) {\n throw new Exception(`Invalid HOST_NAME: ${hostnameResult.message}`, {\n status: HttpStatus.Code.InternalServerError,\n data: { hostname },\n });\n }\n\n return this;\n }\n\n public async run(): Promise<App> {\n try {\n await this.init();\n } catch (error: unknown) {\n const logger = new TerminalLogger();\n logger.error(error as IException);\n process.exit(1);\n }\n\n const env = container.get<IAppEnv>(\"app.env\");\n const hostname = Bun.env.HOST_NAME || \"0.0.0.0\";\n const { directories } = this.config;\n const staticDir = directories.static;\n\n const { middlewares = [] } = this.config;\n\n const routes = {\n ...formatHttpRoutes(router.getHttpRoutes(), middlewares as MiddlewareClassType[]),\n ...formatSocketRoutes(router.getSocketRoutes()),\n };\n\n if (staticDir) {\n const trimmedStaticDir = staticDir.replace(/^\\/+|\\/+$/g, \"\");\n routes[`/${trimmedStaticDir}/*`] = {\n GET: (req: BunRequest) =>\n staticHandler({\n req,\n cwd: directories.cwd,\n }),\n };\n }\n\n const server = Bun.serve({\n port: Bun.env.PORT ? Number.parseInt(Bun.env.PORT, 10) : 3000,\n hostname,\n development: env.isLocal,\n routes: {\n ...routes,\n \"/*\": this.config.spa || new Response(\"Not Found\", { status: HttpStatus.Code.NotFound }),\n },\n websocket: {\n perMessageDeflate: true,\n async message(ws: ServerWebSocket<{ id: string }>, message: string) {\n await socketRouteHandler(message, ws, server, middlewares as SocketMiddlewareClassType[]);\n },\n async close(ws: ServerWebSocket<{ id: string }>) {\n container.removeConstant(ws.data.id);\n },\n },\n });\n\n return this;\n }\n}\n",
6
+ "import { Environment } from \"@ooneex/app-env\";\nimport { container } from \"@ooneex/container\";\nimport type { ContextType } from \"@ooneex/controller\";\nimport { Exception } from \"@ooneex/exception\";\nimport { HttpRequest } from \"@ooneex/http-request\";\nimport { HttpResponse, type IResponse } from \"@ooneex/http-response\";\nimport { HttpStatus, type StatusCodeType } from \"@ooneex/http-status\";\nimport type { IMiddleware, MiddlewareClassType } from \"@ooneex/middleware\";\nimport { Role } from \"@ooneex/role\";\nimport type { RouteConfigType } from \"@ooneex/routing\";\nimport { type AssertType, type IAssert, type } from \"@ooneex/validation\";\nimport type { BunRequest, Server } from \"bun\";\n\ntype HttpRouteHandler = (req: BunRequest, server: Server<unknown>) => Promise<Response>;\ntype HttpMethodHandlers = Partial<Record<string, HttpRouteHandler | Response>>;\ntype HttpRoutesMap = Record<string, HttpMethodHandlers>;\n\nexport const validateConstraint = (constraint: AssertType | IAssert, value: unknown): string | null => {\n if (\n constraint !== null &&\n typeof constraint === \"object\" &&\n \"validate\" in constraint &&\n typeof constraint.validate === \"function\"\n ) {\n const result = constraint.validate(value);\n if (!result.isValid) {\n return result.message || \"Validation failed\";\n }\n } else if (typeof constraint === \"function\") {\n const result = constraint(value);\n if (result instanceof type.errors) {\n return result.summary;\n }\n }\n\n return null;\n};\n\nexport const buildHttpContext = async (ctx: { req: BunRequest; server: Server<unknown> }): Promise<ContextType> => {\n const { req, server } = ctx;\n\n const address = server.requestIP(req);\n const ip = address?.address ?? \"unknown\";\n\n const response = new HttpResponse();\n\n let payload = {};\n let form: FormData | null = null;\n const contentType = req.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n try {\n payload = await req.json();\n } catch (_e) {}\n } else {\n try {\n form = await req.formData();\n } catch (_e) {}\n }\n\n const request = new HttpRequest(req, {\n params: req.params,\n payload,\n form,\n ip,\n });\n\n const context: ContextType = {\n logger: container.get(\"logger\"),\n analytics: container.get(\"analytics\"),\n cache: container.get(\"cache\"),\n storage: container.get(\"storage\"),\n mailer: container.get(\"mailer\"),\n database: container.get(\"database\"),\n app: {\n env: container.get(\"app.env\"),\n },\n response,\n request,\n params: request.params,\n payload: request.payload,\n queries: request.queries,\n method: request.method,\n header: request.header,\n files: request.files,\n ip: request.ip,\n host: request.host,\n language: request.language,\n user: null,\n };\n\n return context;\n};\n\ntype ControllerError = { message: string; status: StatusCodeType };\ntype RouteValidationError = { message: string; status: StatusCodeType };\n\nexport const validateRouteAccess = async (\n context: ContextType,\n route: RouteConfigType,\n currentEnv: Environment,\n): Promise<RouteValidationError | null> => {\n // Check params\n if (route.params) {\n for (const [paramName, constraint] of Object.entries(route.params)) {\n const error = validateConstraint(constraint, context.params[paramName]);\n if (error) {\n return {\n message: `Invalid parameter \"${paramName}\": ${error}`,\n status: HttpStatus.Code.BadRequest,\n };\n }\n }\n }\n\n // Check queries\n if (route.queries) {\n const error = validateConstraint(route.queries, context.queries);\n if (error) {\n return {\n message: `Invalid query parameters: ${error}`,\n status: HttpStatus.Code.BadRequest,\n };\n }\n }\n\n // Check payload\n if (route.payload) {\n const error = validateConstraint(route.payload, context.payload);\n if (error) {\n return {\n message: `Invalid payload: ${error}`,\n status: HttpStatus.Code.BadRequest,\n };\n }\n }\n\n // Check env\n if (route.env && route.env.length > 0 && !route.env.includes(currentEnv)) {\n return {\n message: `Route \"${route.name}\" is not available in \"${currentEnv}\" environment`,\n status: HttpStatus.Code.NotAcceptable,\n };\n }\n\n // Check ip\n if (route.ip && route.ip.length > 0 && (!context.ip || !route.ip.includes(context.ip))) {\n return {\n message: `Route \"${route.name}\" is not available for IP \"${context.ip}\"`,\n status: HttpStatus.Code.NotAcceptable,\n };\n }\n\n // Check host\n if (route.host && route.host.length > 0 && !route.host.includes(context.host)) {\n return {\n message: `Route \"${route.name}\" is not available for host \"${context.host}\"`,\n status: HttpStatus.Code.NotAcceptable,\n };\n }\n\n // Check roles\n if (route.roles && route.roles.length > 0) {\n if (!context.user || !context.user.roles || context.user.roles.length === 0) {\n return {\n message: `Route \"${route.name}\" requires authentication`,\n status: HttpStatus.Code.Forbidden,\n };\n }\n\n const role = new Role();\n const hasRequiredRole = route.roles.some((requiredRole) =>\n context.user?.roles.some((userRole) => role.hasRole(userRole, requiredRole)),\n );\n\n if (!hasRequiredRole) {\n return {\n message: `Route \"${route.name}\" is not accessible for user roles`,\n status: HttpStatus.Code.NotAcceptable,\n };\n }\n }\n\n // Check permission\n if (route.permission) {\n const permission = container.get(route.permission);\n permission.setUserPermissions(context.user).build();\n const hasPermission = await permission.check();\n if (!hasPermission) {\n return {\n message: `Route \"${route.name}\" permission denied`,\n status: HttpStatus.Code.Forbidden,\n };\n }\n }\n\n return null;\n};\n\nexport const validateResponse = (route: RouteConfigType, data: unknown): RouteValidationError | null => {\n if (route.response) {\n const error = validateConstraint(route.response, data);\n if (error) {\n return {\n message: `Invalid response: ${error}`,\n status: HttpStatus.Code.NotAcceptable,\n };\n }\n }\n return null;\n};\n\nconst buildExceptionResponse = (\n context: ContextType,\n message: string,\n status: StatusCodeType,\n env: Environment,\n): Response => {\n return context.response.exception(message, { status }).get(env);\n};\n\nconst executeController = async (\n controller: { index: (context: ContextType) => Promise<IResponse> | IResponse },\n context: ContextType,\n): Promise<[IResponse, null] | [null, ControllerError]> => {\n try {\n const response = await controller.index(context);\n return [response, null];\n } catch (error: unknown) {\n if (error instanceof Exception) {\n return [null, { message: error.message, status: error.status as StatusCodeType }];\n }\n if (error instanceof Error) {\n return [null, { message: error.message, status: HttpStatus.Code.InternalServerError }];\n }\n return [null, { message: \"An unknown error occurred\", status: HttpStatus.Code.InternalServerError }];\n }\n};\n\nexport const httpRouteHandler = async (context: ContextType, route: RouteConfigType): Promise<Response> => {\n const currentEnv = (context.app.env.env as Environment) || Environment.PRODUCTION;\n\n const validationError = await validateRouteAccess(context, route, currentEnv);\n if (validationError) {\n return buildExceptionResponse(context, validationError.message, validationError.status, currentEnv);\n }\n\n const controller = container.get(route.controller);\n\n const [response, controllerError] = await executeController(controller, context);\n if (controllerError) {\n return buildExceptionResponse(context, controllerError.message, controllerError.status, currentEnv);\n }\n\n const responseValidationError = validateResponse(route, response.getData());\n if (responseValidationError) {\n return buildExceptionResponse(context, responseValidationError.message, responseValidationError.status, currentEnv);\n }\n\n return response.get(currentEnv);\n};\n\nconst runMiddlewares = async (context: ContextType, middlewares: MiddlewareClassType[]): Promise<ContextType> => {\n let currentContext = context;\n\n for (const MiddlewareClass of middlewares) {\n const middleware = container.get<IMiddleware>(MiddlewareClass);\n currentContext = await middleware.handle(currentContext);\n }\n\n return currentContext;\n};\n\nexport const formatHttpRoutes = (\n httpRoutes: Map<string, RouteConfigType[]>,\n middlewares: MiddlewareClassType[] = [],\n): HttpRoutesMap => {\n const routes: HttpRoutesMap = {};\n\n for (const [path, routeConfigs] of httpRoutes) {\n const methodHandlers: Record<string, (req: BunRequest, server: Server<unknown>) => Promise<Response>> = {};\n\n for (const route of routeConfigs) {\n methodHandlers[route.method] = async (req: BunRequest, server: Server<unknown>) => {\n let context = await buildHttpContext({ req, server });\n\n try {\n context = await runMiddlewares(context, middlewares);\n } catch (error: unknown) {\n const env = (context.app.env.env as Environment) || Environment.PRODUCTION;\n const status = error instanceof Exception ? error.status : HttpStatus.Code.InternalServerError;\n return buildExceptionResponse(context, (error as Error).message, status, env);\n }\n\n return httpRouteHandler(context, route);\n };\n }\n\n routes[path] = methodHandlers;\n }\n\n return routes;\n};\n",
7
+ "import type { IContainer } from \"@ooneex/container\";\nimport type { IException } from \"@ooneex/exception\";\nimport type { ILogger, LoggerClassType, LogsEntity } from \"@ooneex/logger\";\nimport type { ScalarType } from \"@ooneex/types\";\n\nexport const logger = (loggers: LoggerClassType[], container: IContainer) => ({\n error: (message: string | IException, data?: Record<string, ScalarType> & LogsEntity) => {\n loggers.forEach((logger) => {\n const log = container.get<ILogger<Record<string, ScalarType>> | ILogger<LogsEntity>>(logger);\n if (log) {\n log.error(message, data);\n }\n });\n },\n warn: (message: string, data?: Record<string, ScalarType> & LogsEntity) => {\n loggers.forEach((logger) => {\n const log = container.get<ILogger<Record<string, ScalarType>> | ILogger<LogsEntity>>(logger);\n if (log) {\n log.warn(message, data);\n }\n });\n },\n info: (message: string, data?: Record<string, ScalarType> & LogsEntity) => {\n loggers.forEach((logger) => {\n const log = container.get<ILogger<Record<string, ScalarType>> | ILogger<LogsEntity>>(logger);\n if (log) {\n log.info(message, data);\n }\n });\n },\n debug: (message: string, data?: Record<string, ScalarType> & LogsEntity) => {\n loggers.forEach((logger) => {\n const log = container.get<ILogger<Record<string, ScalarType>> | ILogger<LogsEntity>>(logger);\n if (log) {\n log.debug(message, data);\n }\n });\n },\n log: (message: string, data?: Record<string, ScalarType> & LogsEntity) => {\n loggers.forEach((logger) => {\n const log = container.get<ILogger<Record<string, ScalarType>> | ILogger<LogsEntity>>(logger);\n if (log) {\n log.log(message, data);\n }\n });\n },\n success: (message: string, data?: Record<string, ScalarType> & LogsEntity) => {\n loggers.forEach((logger) => {\n const log = container.get<ILogger<Record<string, ScalarType>> | ILogger<LogsEntity>>(logger);\n if (log) {\n log.success(message, data);\n }\n });\n },\n});\n",
8
+ "import { Environment } from \"@ooneex/app-env\";\nimport { container } from \"@ooneex/container\";\nimport { Exception } from \"@ooneex/exception\";\nimport type { IResponse } from \"@ooneex/http-response\";\nimport { HttpStatus, type StatusCodeType } from \"@ooneex/http-status\";\nimport type { ISocketMiddleware, SocketMiddlewareClassType } from \"@ooneex/middleware\";\nimport type { RouteConfigType } from \"@ooneex/routing\";\nimport type { ContextType } from \"@ooneex/socket\";\nimport type { RequestDataType } from \"@ooneex/socket/client\";\nimport type { LocaleInfoType } from \"@ooneex/translation\";\nimport type { ScalarType } from \"@ooneex/types\";\nimport { random } from \"@ooneex/utils\";\nimport type { BunRequest, Server, ServerWebSocket } from \"bun\";\nimport { buildHttpContext, validateResponse, validateRouteAccess } from \"./httpRouteUtils\";\n\ntype SocketRouteHandler = (req: BunRequest, server: Server<unknown>) => Promise<undefined>;\ntype SocketRoutesMap = Record<string, SocketRouteHandler>;\n\nexport const formatSocketRoutes = (socketRoutes: Map<string, RouteConfigType>): SocketRoutesMap => {\n const routes: SocketRoutesMap = {};\n\n for (const [path, route] of socketRoutes) {\n routes[path] = async (req: BunRequest, server: Server<unknown>) => {\n const context = await buildHttpContext({ req, server });\n const id = random.nanoid(30);\n container.addConstant(id, { context, route });\n server.upgrade(req, { data: { id } });\n\n return undefined;\n };\n }\n\n return routes;\n};\n\nconst runMiddlewares = async (context: ContextType, middlewares: SocketMiddlewareClassType[]): Promise<ContextType> => {\n let currentContext = context;\n\n for (const MiddlewareClass of middlewares) {\n const middleware = container.get<ISocketMiddleware>(MiddlewareClass);\n currentContext = await middleware.handle(currentContext);\n }\n\n return currentContext;\n};\n\nconst sendException = (context: ContextType, message: string, status: StatusCodeType): Promise<void> => {\n context.response.exception(message, { status });\n return context.channel.send(context.response);\n};\n\nexport const socketRouteHandler = async (\n message: string,\n ws: ServerWebSocket<{ id: string }>,\n server: Server<{ id: string }>,\n middlewares: SocketMiddlewareClassType[] = [],\n): Promise<void> => {\n let { context, route } = container.getConstant<{ context: ContextType; route: RouteConfigType }>(ws.data.id);\n const currentEnv = (context.app.env.env as Environment) || Environment.PRODUCTION;\n\n context.channel = {\n send: async (response: IResponse): Promise<void> => {\n const data = await response.get(currentEnv).json();\n ws.send(JSON.stringify(data));\n },\n close: (code?: number, reason?: string): void => {\n ws.close(code, reason);\n },\n subscribe: async (): Promise<void> => {\n ws.subscribe(route.name);\n },\n isSubscribed: (): boolean => {\n return ws.isSubscribed(route.name);\n },\n unsubscribe: async (): Promise<void> => {\n ws.unsubscribe(route.name);\n },\n publish: async (response: IResponse): Promise<void> => {\n const data = await response.get(currentEnv).json();\n\n server.publish(route.name, data);\n },\n };\n\n const requestData = JSON.parse(message) as RequestDataType;\n context.queries = requestData.queries as Record<string, ScalarType>;\n context.payload = requestData.payload as Record<string, ScalarType>;\n context.language = requestData.language as LocaleInfoType;\n\n try {\n context = await runMiddlewares(context, middlewares);\n } catch (error: unknown) {\n const status = error instanceof Exception ? error.status : HttpStatus.Code.InternalServerError;\n return sendException(context, (error as Error).message, status);\n }\n\n const validationError = await validateRouteAccess(context, route, currentEnv);\n if (validationError) {\n return sendException(context, validationError.message, validationError.status);\n }\n\n const controller = container.get(route.controller);\n try {\n context.response = await controller.index(context);\n } catch (error: unknown) {\n const status = error instanceof Exception ? error.status : HttpStatus.Code.InternalServerError;\n const message = error instanceof Error ? error.message : \"An unknown error occurred\";\n return sendException(context, message, status);\n }\n\n const responseValidationError = validateResponse(route, context.response.getData());\n if (responseValidationError) {\n return sendException(context, responseValidationError.message, responseValidationError.status);\n }\n\n return context.channel.send(context.response);\n};\n",
9
+ "import { join } from \"node:path\";\nimport { HttpStatus } from \"@ooneex/http-status\";\nimport type { BunRequest } from \"bun\";\n\nexport const staticHandler = async (options: { req: BunRequest; cwd: string }): Promise<Response> => {\n const { req, cwd } = options;\n const path = new URL(req.url).pathname;\n\n const filePath = join(cwd, path);\n const file = Bun.file(filePath);\n if (await file.exists()) {\n return new Response(file);\n }\n\n return new Response(\"File not found\", {\n status: HttpStatus.Code.NotFound,\n });\n};\n",
7
10
  "import { join } from \"node:path\";\nimport type { RouteConfigType } from \"@ooneex/routing\";\nimport { routeConfigToJsonDoc } from \"@ooneex/routing\";\n\nexport const generateRouteDoc = async (config: RouteConfigType): Promise<void> => {\n const outputDir = \"docs/routes\";\n const jsonDoc = routeConfigToJsonDoc(config);\n const fileName = `${config.name}.json`;\n const filePath = join(process.cwd(), outputDir, fileName);\n\n await Bun.write(filePath, JSON.stringify(jsonDoc, null, 2));\n};\n",
8
- "import { join } from \"node:path\";\nimport type { RouteConfigType } from \"@ooneex/routing\";\nimport { routeConfigToTypeString } from \"@ooneex/routing\";\nimport { toPascalCase } from \"@ooneex/utils\";\n\nexport const generateRouteType = async (config: RouteConfigType): Promise<void> => {\n const outputDir = \"types/routes\";\n const typeString = routeConfigToTypeString(config);\n const fileName = `${config.name}.ts`;\n const filePath = join(process.cwd(), outputDir, fileName);\n\n const typeName = toPascalCase(config.name);\n\n const fileContent = `export type ${typeName}RouteType = ${typeString};\n`;\n\n await Bun.write(filePath, fileContent);\n};\n"
11
+ "import { join } from \"node:path\";\nimport type { RouteConfigType } from \"@ooneex/routing\";\nimport { routeConfigToTypeString } from \"@ooneex/routing\";\nimport { toPascalCase } from \"@ooneex/utils\";\n\nexport const generateRouteType = async (config: RouteConfigType): Promise<void> => {\n const outputDir = \"src/types/routes\";\n const typeString = routeConfigToTypeString(config);\n const fileName = `${config.name}.ts`;\n const filePath = join(process.cwd(), outputDir, fileName);\n\n const typeName = toPascalCase(config.name);\n\n const fileContent = `export type ${typeName}RouteType = ${typeString};\n`;\n\n await Bun.write(filePath, fileContent);\n};\n"
9
12
  ],
10
- "mappings": "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",
11
- "debugId": "D7796269F0F59E7F64756E2164756E21",
13
+ "mappings": "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",
14
+ "debugId": "2EDF5B8BA53E4B9664756E2164756E21",
12
15
  "names": []
13
16
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ooneex/app",
3
- "description": "",
4
- "version": "0.0.1",
3
+ "description": "Core application framework for building modern web applications with Bun, providing routing, middleware, caching, logging, and more",
4
+ "version": "0.3.0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -25,30 +25,46 @@
25
25
  "test": "bun test tests",
26
26
  "build": "bunup",
27
27
  "lint": "tsgo --noEmit && bunx biome lint",
28
- "publish:prod": "bun publish --tolerate-republish --access public",
29
- "publish:pack": "bun pm pack --destination ./dist",
30
- "publish:dry": "bun publish --dry-run",
28
+ "publish": "bun publish --access public || true",
31
29
  "dev": "bun run src/dev.ts"
32
30
  },
33
31
  "dependencies": {
32
+ "@ooneex/analytics": "0.0.1",
34
33
  "@ooneex/app-env": "0.0.1",
35
- "@ooneex/database": "0.0.1",
36
- "@ooneex/jwt": "0.0.1",
37
- "@ooneex/storage": "0.0.1",
38
34
  "@ooneex/cache": "0.0.1",
39
- "@ooneex/analytics": "0.0.1",
40
- "@ooneex/cron": "0.0.1",
41
- "@ooneex/container": "0.0.1",
35
+ "@ooneex/container": "0.0.2",
36
+ "@ooneex/database": "0.0.1",
37
+ "@ooneex/exception": "0.0.1",
38
+ "@ooneex/http-request": "0.0.1",
39
+ "@ooneex/http-response": "0.0.1",
40
+ "@ooneex/http-status": "0.0.1",
41
+ "@ooneex/logger": "0.0.1",
42
42
  "@ooneex/mailer": "0.0.1",
43
- "@ooneex/permission": "0.0.1",
44
- "@ooneex/routing": "0.0.1",
43
+ "@ooneex/rate-limit": "0.0.1",
44
+ "@ooneex/role": "0.0.1",
45
+ "@ooneex/routing": "0.0.2",
46
+ "@ooneex/storage": "0.0.1",
45
47
  "@ooneex/utils": "0.0.8",
46
- "@ooneex/logger": "0.0.1"
48
+ "@ooneex/validation": "0.0.1"
47
49
  },
48
50
  "devDependencies": {
49
- "@ooneex/types": "0.0.1",
50
- "@ooneex/role": "0.0.1",
51
- "@ooneex/validation": "0.0.1"
51
+ "@ooneex/controller": "0.0.1",
52
+ "@ooneex/cron": "0.0.1",
53
+ "@ooneex/middleware": "0.0.1",
54
+ "@ooneex/module": "0.0.1",
55
+ "@ooneex/socket": "0.0.1",
56
+ "@ooneex/translation": "0.0.1",
57
+ "@ooneex/types": "0.0.1"
58
+ },
59
+ "peerDependencies": {
60
+ "@tanstack/react-query": "^5.90.12"
52
61
  },
53
- "peerDependencies": {}
62
+ "keywords": [
63
+ "application",
64
+ "bun",
65
+ "framework",
66
+ "ooneex",
67
+ "typescript",
68
+ "web-app"
69
+ ]
54
70
  }
Binary file