@ooneex/app 0.0.1 → 0.4.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 +410 -1
- package/dist/index.d.ts +16 -8
- package/dist/index.js +3 -3
- package/dist/index.js.map +9 -6
- package/package.json +34 -18
- package/dist/ooneex-app-0.0.1.tgz +0 -0
package/README.md
CHANGED
|
@@ -1 +1,410 @@
|
|
|
1
|
-
# @ooneex/
|
|
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
|
+

|
|
6
|
+

|
|
7
|
+

|
|
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,
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
3
|
-
`;await Bun.write(a
|
|
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=
|
|
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 {
|
|
6
|
-
"import
|
|
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": ";
|
|
11
|
-
"debugId": "
|
|
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
|
|
3
|
+
"description": "Core application framework for building modern web applications with Bun, providing routing, middleware, caching, logging, and more",
|
|
4
|
+
"version": "0.4.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
|
|
29
|
-
"publish:pack": "bun pm pack --destination ./dist",
|
|
30
|
-
"publish:dry": "bun publish --dry-run",
|
|
28
|
+
"npm:publish": "bun publish --tolerate-republish --access public",
|
|
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/
|
|
40
|
-
"@ooneex/
|
|
41
|
-
"@ooneex/
|
|
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/
|
|
44
|
-
"@ooneex/
|
|
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/
|
|
48
|
+
"@ooneex/validation": "0.0.1"
|
|
47
49
|
},
|
|
48
50
|
"devDependencies": {
|
|
49
|
-
"@ooneex/
|
|
50
|
-
"@ooneex/
|
|
51
|
-
"@ooneex/
|
|
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
|
-
"
|
|
62
|
+
"keywords": [
|
|
63
|
+
"application",
|
|
64
|
+
"bun",
|
|
65
|
+
"framework",
|
|
66
|
+
"ooneex",
|
|
67
|
+
"typescript",
|
|
68
|
+
"web-app"
|
|
69
|
+
]
|
|
54
70
|
}
|
|
Binary file
|