ts-rails 1.0.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 +442 -0
- package/dist/app/channels/index.d.ts +2 -0
- package/dist/app/channels/index.d.ts.map +1 -0
- package/dist/app/channels/index.js +18 -0
- package/dist/app/channels/index.js.map +1 -0
- package/dist/app/channels/railsChannel.d.ts +11 -0
- package/dist/app/channels/railsChannel.d.ts.map +1 -0
- package/dist/app/channels/railsChannel.js +20 -0
- package/dist/app/channels/railsChannel.js.map +1 -0
- package/dist/app/controllers/controllerHelpers.d.ts +4 -0
- package/dist/app/controllers/controllerHelpers.d.ts.map +1 -0
- package/dist/app/controllers/controllerHelpers.js +55 -0
- package/dist/app/controllers/controllerHelpers.js.map +1 -0
- package/dist/app/controllers/decorators.d.ts +4 -0
- package/dist/app/controllers/decorators.d.ts.map +1 -0
- package/dist/app/controllers/decorators.js +23 -0
- package/dist/app/controllers/decorators.js.map +1 -0
- package/dist/app/controllers/index.d.ts +7 -0
- package/dist/app/controllers/index.d.ts.map +1 -0
- package/dist/app/controllers/index.js +23 -0
- package/dist/app/controllers/index.js.map +1 -0
- package/dist/app/controllers/pagination.d.ts +29 -0
- package/dist/app/controllers/pagination.d.ts.map +1 -0
- package/dist/app/controllers/pagination.js +28 -0
- package/dist/app/controllers/pagination.js.map +1 -0
- package/dist/app/controllers/railsController.d.ts +30 -0
- package/dist/app/controllers/railsController.d.ts.map +1 -0
- package/dist/app/controllers/railsController.js +32 -0
- package/dist/app/controllers/railsController.js.map +1 -0
- package/dist/app/controllers/response.d.ts +19 -0
- package/dist/app/controllers/response.d.ts.map +1 -0
- package/dist/app/controllers/response.js +26 -0
- package/dist/app/controllers/response.js.map +1 -0
- package/dist/app/controllers/strongParams.d.ts +18 -0
- package/dist/app/controllers/strongParams.d.ts.map +1 -0
- package/dist/app/controllers/strongParams.js +91 -0
- package/dist/app/controllers/strongParams.js.map +1 -0
- package/dist/app/index.d.ts +7 -0
- package/dist/app/index.d.ts.map +1 -0
- package/dist/app/index.js +23 -0
- package/dist/app/index.js.map +1 -0
- package/dist/app/jobs/index.d.ts +2 -0
- package/dist/app/jobs/index.d.ts.map +1 -0
- package/dist/app/jobs/index.js +18 -0
- package/dist/app/jobs/index.js.map +1 -0
- package/dist/app/jobs/railsJob.d.ts +8 -0
- package/dist/app/jobs/railsJob.d.ts.map +1 -0
- package/dist/app/jobs/railsJob.js +15 -0
- package/dist/app/jobs/railsJob.js.map +1 -0
- package/dist/app/mailers/index.d.ts +2 -0
- package/dist/app/mailers/index.d.ts.map +1 -0
- package/dist/app/mailers/index.js +18 -0
- package/dist/app/mailers/index.js.map +1 -0
- package/dist/app/mailers/railsMailer.d.ts +13 -0
- package/dist/app/mailers/railsMailer.d.ts.map +1 -0
- package/dist/app/mailers/railsMailer.js +19 -0
- package/dist/app/mailers/railsMailer.js.map +1 -0
- package/dist/app/middlewares/fileUploadValidation.d.ts +6 -0
- package/dist/app/middlewares/fileUploadValidation.d.ts.map +1 -0
- package/dist/app/middlewares/fileUploadValidation.js +21 -0
- package/dist/app/middlewares/fileUploadValidation.js.map +1 -0
- package/dist/app/middlewares/index.d.ts +2 -0
- package/dist/app/middlewares/index.d.ts.map +1 -0
- package/dist/app/middlewares/index.js +18 -0
- package/dist/app/middlewares/index.js.map +1 -0
- package/dist/app/views/index.d.ts +2 -0
- package/dist/app/views/index.d.ts.map +1 -0
- package/dist/app/views/index.js +18 -0
- package/dist/app/views/index.js.map +1 -0
- package/dist/app/views/viewHelpers.d.ts +7 -0
- package/dist/app/views/viewHelpers.d.ts.map +1 -0
- package/dist/app/views/viewHelpers.js +42 -0
- package/dist/app/views/viewHelpers.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +111 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/console.d.ts +2 -0
- package/dist/commands/console.d.ts.map +1 -0
- package/dist/commands/console.js +85 -0
- package/dist/commands/console.js.map +1 -0
- package/dist/commands/generate-concern.d.ts +2 -0
- package/dist/commands/generate-concern.d.ts.map +1 -0
- package/dist/commands/generate-concern.js +40 -0
- package/dist/commands/generate-concern.js.map +1 -0
- package/dist/commands/generate-controller.d.ts +2 -0
- package/dist/commands/generate-controller.d.ts.map +1 -0
- package/dist/commands/generate-controller.js +92 -0
- package/dist/commands/generate-controller.js.map +1 -0
- package/dist/commands/generate-factory.d.ts +2 -0
- package/dist/commands/generate-factory.d.ts.map +1 -0
- package/dist/commands/generate-factory.js +43 -0
- package/dist/commands/generate-factory.js.map +1 -0
- package/dist/commands/generate-job.d.ts +2 -0
- package/dist/commands/generate-job.d.ts.map +1 -0
- package/dist/commands/generate-job.js +41 -0
- package/dist/commands/generate-job.js.map +1 -0
- package/dist/commands/generate-mailer.d.ts +2 -0
- package/dist/commands/generate-mailer.d.ts.map +1 -0
- package/dist/commands/generate-mailer.js +46 -0
- package/dist/commands/generate-mailer.js.map +1 -0
- package/dist/commands/generate-model.d.ts +2 -0
- package/dist/commands/generate-model.d.ts.map +1 -0
- package/dist/commands/generate-model.js +53 -0
- package/dist/commands/generate-model.js.map +1 -0
- package/dist/commands/generate-resource.d.ts +2 -0
- package/dist/commands/generate-resource.d.ts.map +1 -0
- package/dist/commands/generate-resource.js +62 -0
- package/dist/commands/generate-resource.js.map +1 -0
- package/dist/commands/generate-scaffold.d.ts +2 -0
- package/dist/commands/generate-scaffold.d.ts.map +1 -0
- package/dist/commands/generate-scaffold.js +183 -0
- package/dist/commands/generate-scaffold.js.map +1 -0
- package/dist/commands/generate-service.d.ts +2 -0
- package/dist/commands/generate-service.d.ts.map +1 -0
- package/dist/commands/generate-service.js +49 -0
- package/dist/commands/generate-service.js.map +1 -0
- package/dist/commands/notes.d.ts +2 -0
- package/dist/commands/notes.d.ts.map +1 -0
- package/dist/commands/notes.js +58 -0
- package/dist/commands/notes.js.map +1 -0
- package/dist/commands/routes.d.ts +2 -0
- package/dist/commands/routes.d.ts.map +1 -0
- package/dist/commands/routes.js +76 -0
- package/dist/commands/routes.js.map +1 -0
- package/dist/configs/cache.d.ts +15 -0
- package/dist/configs/cache.d.ts.map +1 -0
- package/dist/configs/cache.js +27 -0
- package/dist/configs/cache.js.map +1 -0
- package/dist/configs/index.d.ts +6 -0
- package/dist/configs/index.d.ts.map +1 -0
- package/dist/configs/index.js +22 -0
- package/dist/configs/index.js.map +1 -0
- package/dist/configs/logger.d.ts +12 -0
- package/dist/configs/logger.d.ts.map +1 -0
- package/dist/configs/logger.js +23 -0
- package/dist/configs/logger.js.map +1 -0
- package/dist/configs/railsApplication.d.ts +54 -0
- package/dist/configs/railsApplication.d.ts.map +1 -0
- package/dist/configs/railsApplication.js +314 -0
- package/dist/configs/railsApplication.js.map +1 -0
- package/dist/configs/railsRoute.d.ts +71 -0
- package/dist/configs/railsRoute.d.ts.map +1 -0
- package/dist/configs/railsRoute.js +332 -0
- package/dist/configs/railsRoute.js.map +1 -0
- package/dist/configs/swagger/builder.d.ts +20 -0
- package/dist/configs/swagger/builder.d.ts.map +1 -0
- package/dist/configs/swagger/builder.js +81 -0
- package/dist/configs/swagger/builder.js.map +1 -0
- package/dist/configs/swagger/decorator.d.ts +23 -0
- package/dist/configs/swagger/decorator.d.ts.map +1 -0
- package/dist/configs/swagger/decorator.js +27 -0
- package/dist/configs/swagger/decorator.js.map +1 -0
- package/dist/configs/swagger/index.d.ts +5 -0
- package/dist/configs/swagger/index.d.ts.map +1 -0
- package/dist/configs/swagger/index.js +21 -0
- package/dist/configs/swagger/index.js.map +1 -0
- package/dist/configs/swagger/registry.d.ts +4 -0
- package/dist/configs/swagger/registry.d.ts.map +1 -0
- package/dist/configs/swagger/registry.js +22 -0
- package/dist/configs/swagger/registry.js.map +1 -0
- package/dist/configs/swagger/server.d.ts +3 -0
- package/dist/configs/swagger/server.d.ts.map +1 -0
- package/dist/configs/swagger/server.js +17 -0
- package/dist/configs/swagger/server.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +18 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/utils/errors.d.ts +22 -0
- package/dist/lib/utils/errors.d.ts.map +1 -0
- package/dist/lib/utils/errors.js +45 -0
- package/dist/lib/utils/errors.js.map +1 -0
- package/dist/lib/utils/index.d.ts +3 -0
- package/dist/lib/utils/index.d.ts.map +1 -0
- package/dist/lib/utils/index.js +19 -0
- package/dist/lib/utils/index.js.map +1 -0
- package/dist/lib/utils/security.d.ts +9 -0
- package/dist/lib/utils/security.d.ts.map +1 -0
- package/dist/lib/utils/security.js +14 -0
- package/dist/lib/utils/security.js.map +1 -0
- package/package.json +105 -0
package/README.md
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
# ts-rails 🚂
|
|
2
|
+
|
|
3
|
+
**The Core Engine for TS Rails.**
|
|
4
|
+
Hệ thống lõi cung cấp các tính năng mạnh mẽ tương tự Ruby on Rails cho hệ sinh thái Node.js, sử dụng TypeScript và Express.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 🌟 Tính năng nổi bật
|
|
9
|
+
|
|
10
|
+
- 🚀 **Application**: Tích hợp sâu vào lõi Express.
|
|
11
|
+
- 🛣 **Routing Siêu Tốc**: Hỗ trợ `resource()` và helper `action()` để định nghĩa route nhanh chóng.
|
|
12
|
+
- 🎮 **Controller Decorators**: Sử dụng `@BeforeAction`, `@AfterAction` để quản lý luồng xử lý (Filters).
|
|
13
|
+
- 🔌 **Real-time Channels**: Tích hợp Socket.IO thông qua `RailsChannel` (giống ActionCable).
|
|
14
|
+
- 📮 **Unified Mailers**: Interface gửi mail đồng nhất với hệ thống Adapter linh hoạt.
|
|
15
|
+
- 📝 **Auto Swagger**: Tự động tạo tài liệu OpenAPI dựa trên khai báo route và validators.
|
|
16
|
+
- 🔢 **Pagination & Response**: Chuẩn hóa dữ liệu trả về và hỗ trợ phân trang chuẩn mực.
|
|
17
|
+
- 🖼 **View Helpers**: Hỗ trợ mạnh mẽ cho Pug/EJS với định dạng tiền tệ, thời gian và Vite assets.
|
|
18
|
+
- 👷 **Background Jobs**: Định nghĩa job chạy nền đồng nhất cho cả BullMQ và AWS Lambda.
|
|
19
|
+
- 🛠 **CLI Scaffolding**: Bộ generator mạnh mẽ giúp tạo code nhanh chóng.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 📦 Cài đặt
|
|
24
|
+
|
|
25
|
+
Cài đặt thông qua các package manager yêu thích của bạn:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# npm
|
|
29
|
+
npm install ts-rails
|
|
30
|
+
|
|
31
|
+
# yarn
|
|
32
|
+
yarn add ts-rails
|
|
33
|
+
|
|
34
|
+
# pnpm
|
|
35
|
+
pnpm add ts-rails
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 🛠 Các thành phần chính
|
|
41
|
+
|
|
42
|
+
### 1. RailsApplication Core 🚂
|
|
43
|
+
|
|
44
|
+
`RailsApplication` là trái tim của hệ thống, quản lý toàn bộ vòng đời ứng dụng (Lifecycle), từ việc thiết lập cấu hình, nạp Initializers, quản lý Middleware cho đến khởi chạy Server và Socket.IO.
|
|
45
|
+
|
|
46
|
+
#### 1. Khởi tạo Application Class
|
|
47
|
+
|
|
48
|
+
Để bắt đầu, bạn cần kế thừa lớp `RailsApplication`. Đây là nơi bạn định nghĩa cách ứng dụng của mình khởi động.
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { RailsApplication } from "ts-rails";
|
|
52
|
+
import { Route } from "./routes";
|
|
53
|
+
|
|
54
|
+
export class Application extends RailsApplication {
|
|
55
|
+
constructor() {
|
|
56
|
+
super();
|
|
57
|
+
this.port = process.env.PORT || "8000";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Gắn Router vào Express
|
|
61
|
+
protected mountRoutes() {
|
|
62
|
+
this.app.use("/", Route.draw());
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Khởi tạo các dịch vụ cần thiết (Database, Redis, etc.)
|
|
66
|
+
public async initialize() {
|
|
67
|
+
this.setupAppMiddlewares();
|
|
68
|
+
await this.setupServices();
|
|
69
|
+
this.bootstrap(); // Thiết lập server HTTP và Socket.IO
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### 2. Middleware Factory Configuration
|
|
75
|
+
|
|
76
|
+
Framework cung cấp một `MiddlewareFactory` toàn cục để bạn có thể ghi đè hoặc bổ sung các middleware hệ thống (như Rate Limit, Request Logging) bằng logic tùy chỉnh của mình.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { RailsApplication, MiddlewareFactory } from "ts-rails";
|
|
80
|
+
import { rateLimitMiddleware } from "@middlewares/rateLimit.middleware";
|
|
81
|
+
import { requestIdMiddleware } from "@middlewares/requestId.middleware";
|
|
82
|
+
|
|
83
|
+
RailsApplication.middlewareFactory = {
|
|
84
|
+
rateLimit: rateLimitMiddleware,
|
|
85
|
+
requestId: () => requestIdMiddleware,
|
|
86
|
+
requestLogging: () => (req, res, next) => {
|
|
87
|
+
console.log(`${req.method} ${req.url}`);
|
|
88
|
+
next();
|
|
89
|
+
},
|
|
90
|
+
} as MiddlewareFactory;
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### 3. Quản lý Controller Concerns (Mixins)
|
|
94
|
+
|
|
95
|
+
Tương tự như Ruby on Rails, bạn có thể sử dụng `loadConcerns` để "nhúng" các hàm dùng chung vào Controller mà không cần kế thừa phức tạp.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { ApplicationController } from "@controllers/application.controller";
|
|
99
|
+
|
|
100
|
+
// Trong phương thức initialize() của Application class:
|
|
101
|
+
this.loadConcerns(
|
|
102
|
+
ApplicationController.prototype,
|
|
103
|
+
"app/controllers/concerns", // Đường dẫn tới thư mục chứa các file .ts concern
|
|
104
|
+
);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
_Ví dụ: Nếu bạn có file `rescuable.ts` trong thư mục concerns, các phương thức trong đó sẽ tự động xuất hiện trong `ApplicationController`._
|
|
108
|
+
|
|
109
|
+
#### 4. Socket.IO Channels
|
|
110
|
+
|
|
111
|
+
Đăng ký tất cả các lớp Channel để sử dụng tính năng Real-time:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import * as channels from "@channels";
|
|
115
|
+
|
|
116
|
+
RailsApplication.channelClasses = Object.values(channels);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### 5. Background Processing (BullMQ)
|
|
120
|
+
|
|
121
|
+
Framework hỗ trợ xử lý tác vụ chạy nền. Bạn có thể override `startBackgroundProcessor` để khởi chạy Worker:
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
protected startBackgroundProcessor() {
|
|
125
|
+
// Logic setup BullMQ Worker hoặc các trình xử lý hàng đợi khác
|
|
126
|
+
setupBullMQWorker();
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### 6. Vòng đời khởi chạy (Full Lifecycle)
|
|
131
|
+
|
|
132
|
+
Dưới đây là thứ tự chuẩn để chạy ứng dụng:
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
export class Application extends RailsApplication {
|
|
136
|
+
// ... các phương thức setupConfig, setupViewEngine ...
|
|
137
|
+
|
|
138
|
+
public async run() {
|
|
139
|
+
// 1. Chạy các Initializers (Logger, Mailer, Cache...)
|
|
140
|
+
initializeLogger();
|
|
141
|
+
initializeMailer();
|
|
142
|
+
|
|
143
|
+
// 2. Setup view engine & static files
|
|
144
|
+
this.app.set("view engine", "pug");
|
|
145
|
+
|
|
146
|
+
// 3. Khởi tạo hệ thống
|
|
147
|
+
await this.initialize();
|
|
148
|
+
|
|
149
|
+
// 4. Start Server
|
|
150
|
+
super.run();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const app = new Application();
|
|
155
|
+
app.run();
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
#### 📄 Ghi chú
|
|
159
|
+
|
|
160
|
+
Mọi cấu hình mặc định có thể được tùy chỉnh thông qua việc override các phương thức `protected` trong lớp `RailsApplication`.
|
|
161
|
+
|
|
162
|
+
### 2. Resourceful Routing & `action()`
|
|
163
|
+
|
|
164
|
+
Không còn phải khai báo từng route thủ công. Kết nối trực tiếp Route với Controller Class:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import { RailsRoute, action } from "ts-rails";
|
|
168
|
+
import { UsersController } from "../controllers/users.controller";
|
|
169
|
+
|
|
170
|
+
export class AppRoute extends RailsRoute {
|
|
171
|
+
draw(): void {
|
|
172
|
+
/ Tạo ra 7 routes tiêu chuẩn (index, show, create, update, destroy, ...)
|
|
173
|
+
this.resource("/users", UsersController, {
|
|
174
|
+
only: ["index", "show", "create"],
|
|
175
|
+
setPermissionFor: "USER_MANAGEMENT",
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Sử dụng helper action() cho các route tùy chỉnh
|
|
179
|
+
this.get("/profile", action(UsersController, "profile"));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 4. Strong Parameters & Validation
|
|
185
|
+
|
|
186
|
+
Thư viện hỗ trợ cơ chế bảo mật tham số đầu vào (Whitelist) kết hợp với `class-validator` để tự động kiểm tra và chuyển đổi kiểu dữ liệu.
|
|
187
|
+
|
|
188
|
+
#### Bước 1: Định nghĩa Validator Class
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { IsEmail, IsString, MinLength, IsOptional } from "class-validator";
|
|
192
|
+
|
|
193
|
+
export class CreateUserValidator {
|
|
194
|
+
@IsEmail({}, { message: "Email không hợp lệ" })
|
|
195
|
+
email: string;
|
|
196
|
+
|
|
197
|
+
@IsString()
|
|
198
|
+
@MinLength(3, { message: "Tên phải có ít nhất 3 ký tự" })
|
|
199
|
+
name: string;
|
|
200
|
+
|
|
201
|
+
@IsString()
|
|
202
|
+
@IsOptional()
|
|
203
|
+
bio?: string;
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### Bước 2: Sử dụng trong Controller
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
import { RailsController } from "ts-rails";
|
|
211
|
+
import { CreateUserValidator } from "../validators/user.validator";
|
|
212
|
+
|
|
213
|
+
export class UsersController extends RailsController {
|
|
214
|
+
async create() {
|
|
215
|
+
/**
|
|
216
|
+
* this.params(Validator) thực hiện:
|
|
217
|
+
* 1. Validate dữ liệu từ request body/query dựa trên class-validator.
|
|
218
|
+
* 2. Tự động trả về lỗi 422 nếu dữ liệu không hợp lệ.
|
|
219
|
+
* 3. .permit(...) whitelist các trường được phép nhận.
|
|
220
|
+
*/
|
|
221
|
+
const userParams = await this.params(CreateUserValidator).permit(
|
|
222
|
+
"email",
|
|
223
|
+
"name",
|
|
224
|
+
"bio",
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
// userParams đã được validate và lọc sạch
|
|
228
|
+
const user = await UserService.create(userParams);
|
|
229
|
+
return this.renderJson(user);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 5. Controller Filters & Decorators
|
|
235
|
+
|
|
236
|
+
Quản lý logic tiền xử lý và hậu xử lý cực kỳ dễ dàng:
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import { RailsController, BeforeAction, AfterAction } from "ts-rails";
|
|
240
|
+
|
|
241
|
+
@BeforeAction("authenticate", { except: ["index"] })
|
|
242
|
+
@AfterAction("logActivity", { only: ["create", "update"] })
|
|
243
|
+
export class UsersController extends RailsController {
|
|
244
|
+
async authenticate() {
|
|
245
|
+
if (!this.req.session.userId) return this.renderError(401, "Unauthorized");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ... logic xử lý các action khác
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### 6. File Upload Validation
|
|
253
|
+
|
|
254
|
+
Tích hợp sẵn middleware xử lý upload và kiểm tra ràng buộc file ngay trong cấu hình route.
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
this.resource("/products", ProductsController, {
|
|
258
|
+
upload: {
|
|
259
|
+
fields: [
|
|
260
|
+
{ name: "thumbnail", maxCount: 1 },
|
|
261
|
+
{ name: "gallery", maxCount: 5 },
|
|
262
|
+
],
|
|
263
|
+
limits: {
|
|
264
|
+
fileSize: 5 * 1024 * 1024, // Giới hạn 5MB cho mỗi file
|
|
265
|
+
},
|
|
266
|
+
fileFilter: (req, file, cb) => {
|
|
267
|
+
// Chỉ cho phép file ảnh
|
|
268
|
+
if (!file.mimetype.startsWith("image/")) {
|
|
269
|
+
return cb(new Error("Chỉ chấp nhận định dạng hình ảnh!"), false);
|
|
270
|
+
}
|
|
271
|
+
cb(null, true);
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### 7. Real-time Channels (Socket.IO)
|
|
278
|
+
|
|
279
|
+
Khai báo channel theo hướng đối tượng:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
import { RailsChannel } from "ts-rails";
|
|
283
|
+
|
|
284
|
+
export class ChatChannel extends RailsChannel {
|
|
285
|
+
subscribe() {
|
|
286
|
+
this.on("message", (data) => {
|
|
287
|
+
this.broadcast("room_1", { content: data });
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### 8. View Helpers (Time, Currency, Vite)
|
|
294
|
+
|
|
295
|
+
Cung cấp sẵn bộ `viewHelpers` để sử dụng trong các template engine:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
import { viewHelpers as h } from "ts-rails";
|
|
299
|
+
|
|
300
|
+
h.timeAgo(Date.now()); // "a few seconds ago"
|
|
301
|
+
h.numberToCurrency(50000); // "50.000 ₫"
|
|
302
|
+
h.assetPath("main.ts"); // Tự động nhận diện path từ Vite manifest
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### 9. Mailers & Custom Adapters
|
|
306
|
+
|
|
307
|
+
Hệ thống Mailer hoạt động theo mô hình Adapter, cho phép bạn linh hoạt thay đổi dịch vụ gửi mail mà không làm thay đổi code business.
|
|
308
|
+
|
|
309
|
+
#### Bước 1: Triển khai Adapter (Ví dụ: Gmail OAuth2)
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
import { MailerAdapter } from "ts-rails";
|
|
313
|
+
import { createTransport } from "nodemailer";
|
|
314
|
+
|
|
315
|
+
export class GmailOAuth2Adapter implements MailerAdapter {
|
|
316
|
+
async sendMail(options: any): Promise<void> {
|
|
317
|
+
const transporter = createTransport({
|
|
318
|
+
service: "gmail",
|
|
319
|
+
auth: {
|
|
320
|
+
type: "OAuth2",
|
|
321
|
+
user: process.env.EMAIL_FROM,
|
|
322
|
+
clientId: process.env.GOOGLE_CLIENT_ID,
|
|
323
|
+
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
|
324
|
+
refreshToken: process.env.GOOGLE_REFRESH_TOKEN,
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
await transporter.sendMail({
|
|
329
|
+
...options,
|
|
330
|
+
from: options.from || this.getDefaultFromAddress(),
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
getDefaultFromAddress(): string {
|
|
335
|
+
return `TS Rails App <${process.env.EMAIL_FROM}>`;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
#### Bước 2: Đăng ký Adapter trong Initializer
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
import { RailsApplication } from "ts-rails";
|
|
344
|
+
import { GmailOAuth2Adapter } from "./mail/gmail-oauth2.adapter";
|
|
345
|
+
|
|
346
|
+
// Cấu hình thường đặt trong configs/initializers/mailer.ts
|
|
347
|
+
RailsApplication.mailerAdapter = new GmailOAuth2Adapter();
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
#### Bước 3: Định nghĩa và sử dụng Mailer
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
import { RailsMailer } from "ts-rails";
|
|
354
|
+
|
|
355
|
+
export class UserMailer extends RailsMailer {
|
|
356
|
+
static async welcome(user: any) {
|
|
357
|
+
await this.deliver({
|
|
358
|
+
to: user.email,
|
|
359
|
+
subject: "Welcome to TS Rails!",
|
|
360
|
+
template: "mailers/welcome",
|
|
361
|
+
locals: { name: user.name },
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### 10. Pagination & Standardized Response
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
import { parsePagination, buildPaginatedResponse } from "ts-rails";
|
|
371
|
+
|
|
372
|
+
async index() {
|
|
373
|
+
const { page, perPage, skip } = parsePagination(this.req.query);
|
|
374
|
+
const [data, total] = await db.user.findManyAndCount({ skip, take: perPage });
|
|
375
|
+
|
|
376
|
+
return this.renderJson(buildPaginatedResponse(data, total, { page, perPage }));
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## ⚙️ Cấu hình & Tiện ích
|
|
383
|
+
|
|
384
|
+
### Swagger Configuration
|
|
385
|
+
|
|
386
|
+
Tự động quét và tạo tài liệu API:
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
this.resource("/api/users", UsersController, {
|
|
390
|
+
document: {
|
|
391
|
+
body: CreateUserValidator,
|
|
392
|
+
summary: "Tạo người dùng mới",
|
|
393
|
+
tags: ["User Management"],
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Logger & Cache
|
|
399
|
+
|
|
400
|
+
Sử dụng interface đồng nhất cho toàn hệ thống:
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
import { logger } from "ts-rails";
|
|
404
|
+
import { Cache } from "ts-rails";
|
|
405
|
+
|
|
406
|
+
logger.info("Server started");
|
|
407
|
+
await Cache.set("key", value, { ttl: 3600 });
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
## 💻 CLI Commands
|
|
413
|
+
|
|
414
|
+
Sử dụng command `rails` để sinh mã nguồn nhanh chóng theo chuẩn `field:type`.
|
|
415
|
+
|
|
416
|
+
**Cú pháp:**
|
|
417
|
+
`npx rails generate <loại> <TênModel> [field:type field:type ...]`
|
|
418
|
+
|
|
419
|
+
### Các lệnh chính:
|
|
420
|
+
|
|
421
|
+
| Lệnh | Mô tả | Ví dụ |
|
|
422
|
+
| :------------- | :-------------------------------------------- | :----------------------------------------------------------------- |
|
|
423
|
+
| `g scaffold` | Tạo trọn bộ: Model, Controller, Views, Routes | `npx rails g scaffold Product name:string price:integer desc:text` |
|
|
424
|
+
| `g resource` | Tạo API Resource (Controller + Model) | `npx rails g resource Order total:decimal status:string` |
|
|
425
|
+
| `g controller` | Tạo Controller mới | `npx rails g controller Admin/Dashboard` |
|
|
426
|
+
| `g service` | Tạo Service xử lý logic | `npx rails g service Payment` |
|
|
427
|
+
| `g mailer` | Tạo class Mailer | `npx rails g mailer Notification` |
|
|
428
|
+
| `g job` | Tạo Background Job | `npx rails g job SyncData` |
|
|
429
|
+
| `g channel` | Tạo Socket.IO Channel | `npx rails g channel Chat` |
|
|
430
|
+
|
|
431
|
+
**Các kiểu dữ liệu hỗ trợ:**
|
|
432
|
+
`string`, `text`, `integer`, `float`, `decimal`, `boolean`, `date`, `datetime`, `json`.
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## 📄 License
|
|
437
|
+
|
|
438
|
+
MIT
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
_Phát triển bởi Hoan Pham và cộng đồng._
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../app/channels/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./railsChannel"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../app/channels/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Socket, Server as SocketServer } from "socket.io";
|
|
2
|
+
export declare abstract class RailsChannel {
|
|
3
|
+
protected io: SocketServer;
|
|
4
|
+
protected socket: Socket;
|
|
5
|
+
constructor(io: SocketServer, socket: Socket);
|
|
6
|
+
abstract subscribe(): void;
|
|
7
|
+
protected join(room: string): void;
|
|
8
|
+
protected leave(room: string): void;
|
|
9
|
+
protected broadcastTo(room: string, event: string, ...data: any[]): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=railsChannel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"railsChannel.d.ts","sourceRoot":"","sources":["../../../app/channels/railsChannel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,WAAW,CAAC;AAE3D,8BAAsB,YAAY;IAChC,SAAS,CAAC,EAAE,EAAE,YAAY,CAAC;IAC3B,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEb,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM;IAc5C,QAAQ,CAAC,SAAS,IAAI,IAAI;IAM1B,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM;IAQ3B,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM;IAU5B,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;CAGlE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RailsChannel = void 0;
|
|
4
|
+
class RailsChannel {
|
|
5
|
+
constructor(io, socket) {
|
|
6
|
+
this.io = io;
|
|
7
|
+
this.socket = socket;
|
|
8
|
+
}
|
|
9
|
+
join(room) {
|
|
10
|
+
this.socket.join(room);
|
|
11
|
+
}
|
|
12
|
+
leave(room) {
|
|
13
|
+
this.socket.leave(room);
|
|
14
|
+
}
|
|
15
|
+
broadcastTo(room, event, ...data) {
|
|
16
|
+
this.io.to(room).emit(event, ...data);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.RailsChannel = RailsChannel;
|
|
20
|
+
//# sourceMappingURL=railsChannel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"railsChannel.js","sourceRoot":"","sources":["../../../app/channels/railsChannel.ts"],"names":[],"mappings":";;;AAEA,MAAsB,YAAY;IAIhC,YAAY,EAAgB,EAAE,MAAc;QAC1C,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAiBS,IAAI,CAAC,IAAY;QACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAMS,KAAK,CAAC,IAAY;QAC1B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAQS,WAAW,CAAC,IAAY,EAAE,KAAa,EAAE,GAAG,IAAW;QAC/D,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;IACxC,CAAC;CACF;AA7CD,oCA6CC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { RequestHandler } from "express";
|
|
2
|
+
export declare function action(Klass: new (...args: any[]) => any, actionName: string): RequestHandler;
|
|
3
|
+
export declare function action(Klass: new (...args: any[]) => any): RequestHandler;
|
|
4
|
+
//# sourceMappingURL=controllerHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controllerHelpers.d.ts","sourceRoot":"","sources":["../../../app/controllers/controllerHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,cAAc,EAAY,MAAM,SAAS,CAAC;AAS1E,wBAAgB,MAAM,CACpB,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAClC,UAAU,EAAE,MAAM,GACjB,cAAc,CAAC;AAClB,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,cAAc,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.action = action;
|
|
4
|
+
function action(Klass, actionName = "execute") {
|
|
5
|
+
return async (req, res, next) => {
|
|
6
|
+
const instance = new Klass();
|
|
7
|
+
instance.req = req;
|
|
8
|
+
instance.res = res;
|
|
9
|
+
try {
|
|
10
|
+
const beforeResult = await runFilters(Klass, instance, actionName, "beforeActions");
|
|
11
|
+
if (beforeResult === false) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
if (actionName === "execute" &&
|
|
16
|
+
typeof instance.execute === "function" &&
|
|
17
|
+
instance.execute.length >= 3) {
|
|
18
|
+
await instance.execute(req, res, next);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
await instance[actionName]();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
await runFilters(Klass, instance, actionName, "afterActions");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
next(error);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
async function runFilters(Klass, instance, actionName, filterType) {
|
|
34
|
+
const filters = Klass[filterType] || [];
|
|
35
|
+
for (const filter of filters) {
|
|
36
|
+
const handlerName = filter.handler;
|
|
37
|
+
const options = filter.options;
|
|
38
|
+
const only = options === null || options === void 0 ? void 0 : options.only;
|
|
39
|
+
const except = options === null || options === void 0 ? void 0 : options.except;
|
|
40
|
+
const shouldRun = actionName !== "execute" &&
|
|
41
|
+
((!only && !except) ||
|
|
42
|
+
(only && only.includes(actionName)) ||
|
|
43
|
+
(except && !except.includes(actionName)));
|
|
44
|
+
if (shouldRun) {
|
|
45
|
+
if (typeof instance[handlerName] !== "function") {
|
|
46
|
+
throw new Error(`Filter handler "${handlerName}" is not a valid method on ${Klass.name}`);
|
|
47
|
+
}
|
|
48
|
+
const result = await instance[handlerName]();
|
|
49
|
+
if (filterType === "beforeActions" && result === false)
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=controllerHelpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controllerHelpers.js","sourceRoot":"","sources":["../../../app/controllers/controllerHelpers.ts"],"names":[],"mappings":";;AAoBA,wBAyCC;AAzCD,SAAgB,MAAM,CACpB,KAAkC,EAClC,UAAU,GAAG,SAAS;IAEtB,OAAO,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QAC/D,MAAM,QAAQ,GAAG,IAAI,KAAK,EAAE,CAAC;QAC5B,QAAgB,CAAC,GAAG,GAAG,GAAG,CAAC;QAC3B,QAAgB,CAAC,GAAG,GAAG,GAAG,CAAC;QAE5B,IAAI,CAAC;YAEH,MAAM,YAAY,GAAG,MAAM,UAAU,CACnC,KAAK,EACL,QAAQ,EACR,UAAU,EACV,eAAe,CAChB,CAAC;YACF,IAAI,YAAY,KAAK,KAAK,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBAEH,IACE,UAAU,KAAK,SAAS;oBACxB,OAAO,QAAQ,CAAC,OAAO,KAAK,UAAU;oBACtC,QAAQ,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,EAC5B,CAAC;oBACD,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gBACzC,CAAC;qBAAM,CAAC;oBACN,MAAO,QAAgB,CAAC,UAAU,CAAC,EAAE,CAAC;gBACxC,CAAC;YACH,CAAC;oBAAS,CAAC;gBAGT,MAAM,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,KAAU,EACV,QAAa,EACb,UAAkB,EAClB,UAA4C;IAE5C,MAAM,OAAO,GACX,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAE1B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC;QACnC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAmD,CAAC;QAC3E,MAAM,IAAI,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,CAAC;QAC3B,MAAM,MAAM,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,CAAC;QAE/B,MAAM,SAAS,GACb,UAAU,KAAK,SAAS;YACxB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC;gBACjB,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;gBACnC,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAE9C,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,OAAQ,QAAgB,CAAC,WAAW,CAAC,KAAK,UAAU,EAAE,CAAC;gBACzD,MAAM,IAAI,KAAK,CACb,mBAAmB,WAAW,8BAA8B,KAAK,CAAC,IAAI,EAAE,CACzE,CAAC;YACJ,CAAC;YACD,MAAM,MAAM,GAAG,MAAO,QAAgB,CAAC,WAAW,CAAC,EAAE,CAAC;YACtD,IAAI,UAAU,KAAK,eAAe,IAAI,MAAM,KAAK,KAAK;gBAAE,OAAO,KAAK,CAAC;QACvE,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { AfterActionOptions, BeforeActionOptions } from "./railsController";
|
|
2
|
+
export declare function BeforeAction(handler: string, options?: BeforeActionOptions): (constructor: Function) => void;
|
|
3
|
+
export declare function AfterAction(handler: string, options?: AfterActionOptions): (constructor: Function) => void;
|
|
4
|
+
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../../app/controllers/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAM5E,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,IACxD,aAAa,QAAQ,UAQvC;AAMD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,IACtD,aAAa,QAAQ,UAQvC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BeforeAction = BeforeAction;
|
|
4
|
+
exports.AfterAction = AfterAction;
|
|
5
|
+
function BeforeAction(handler, options) {
|
|
6
|
+
return function (constructor) {
|
|
7
|
+
const target = constructor;
|
|
8
|
+
if (!Object.prototype.hasOwnProperty.call(target, "beforeActions")) {
|
|
9
|
+
target.beforeActions = [...(target.beforeActions || [])];
|
|
10
|
+
}
|
|
11
|
+
target.beforeActions.push({ handler, options });
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function AfterAction(handler, options) {
|
|
15
|
+
return function (constructor) {
|
|
16
|
+
const target = constructor;
|
|
17
|
+
if (!Object.prototype.hasOwnProperty.call(target, "afterActions")) {
|
|
18
|
+
target.afterActions = [...(target.afterActions || [])];
|
|
19
|
+
}
|
|
20
|
+
target.afterActions.push({ handler, options });
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=decorators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../../app/controllers/decorators.ts"],"names":[],"mappings":";;AAMA,oCASC;AAMD,kCASC;AAxBD,SAAgB,YAAY,CAAC,OAAe,EAAE,OAA6B;IACzE,OAAO,UAAU,WAAqB;QACpC,MAAM,MAAM,GAAG,WAAkB,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,CAAC;YAEnE,MAAM,CAAC,aAAa,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC;AACJ,CAAC;AAMD,SAAgB,WAAW,CAAC,OAAe,EAAE,OAA4B;IACvE,OAAO,UAAU,WAAqB;QACpC,MAAM,MAAM,GAAG,WAAkB,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,CAAC;YAElE,MAAM,CAAC,YAAY,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../app/controllers/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./controllerHelpers"), exports);
|
|
18
|
+
__exportStar(require("./decorators"), exports);
|
|
19
|
+
__exportStar(require("./pagination"), exports);
|
|
20
|
+
__exportStar(require("./railsController"), exports);
|
|
21
|
+
__exportStar(require("./response"), exports);
|
|
22
|
+
__exportStar(require("./strongParams"), exports);
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../app/controllers/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,sDAAoC;AACpC,+CAA6B;AAC7B,+CAA6B;AAC7B,oDAAkC;AAClC,6CAA2B;AAC3B,iDAA+B"}
|