ts-rails 1.0.9 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +449 -0
- package/README.md +311 -288
- package/README.vi.md +449 -0
- package/dist/cli.js +61 -18
- package/dist/cli.js.map +1 -1
- package/dist/commands/console.js +7 -7
- package/dist/commands/console.js.map +1 -1
- package/dist/commands/generate-channel.d.ts +2 -0
- package/dist/commands/generate-channel.d.ts.map +1 -0
- package/dist/commands/generate-channel.js +58 -0
- package/dist/commands/generate-channel.js.map +1 -0
- package/dist/commands/generate-concern.js +2 -1
- package/dist/commands/generate-concern.js.map +1 -1
- package/dist/commands/generate-controller.js +12 -11
- package/dist/commands/generate-controller.js.map +1 -1
- package/dist/commands/generate-factory.js +2 -1
- package/dist/commands/generate-factory.js.map +1 -1
- package/dist/commands/generate-job.js +14 -8
- package/dist/commands/generate-job.js.map +1 -1
- package/dist/commands/generate-mailer.js +24 -15
- package/dist/commands/generate-mailer.js.map +1 -1
- package/dist/commands/generate-model.js +2 -1
- package/dist/commands/generate-model.js.map +1 -1
- package/dist/commands/generate-resource.js +21 -17
- package/dist/commands/generate-resource.js.map +1 -1
- package/dist/commands/generate-scaffold.js +22 -34
- package/dist/commands/generate-scaffold.js.map +1 -1
- package/dist/commands/generate-service.js +26 -23
- package/dist/commands/generate-service.js.map +1 -1
- package/dist/commands/generate-test.d.ts +2 -0
- package/dist/commands/generate-test.d.ts.map +1 -0
- package/dist/commands/generate-test.js +94 -0
- package/dist/commands/generate-test.js.map +1 -0
- package/dist/commands/generatorHelpers.d.ts +21 -0
- package/dist/commands/generatorHelpers.d.ts.map +1 -0
- package/dist/commands/generatorHelpers.js +84 -0
- package/dist/commands/generatorHelpers.js.map +1 -0
- package/dist/commands/notes.js +3 -2
- package/dist/commands/notes.js.map +1 -1
- package/dist/commands/resolveRailsAppRoot.d.ts +2 -0
- package/dist/commands/resolveRailsAppRoot.d.ts.map +1 -0
- package/dist/commands/resolveRailsAppRoot.js +41 -0
- package/dist/commands/resolveRailsAppRoot.js.map +1 -0
- package/dist/commands/routes.js +93 -47
- package/dist/commands/routes.js.map +1 -1
- package/dist/commands/testAnalyzer.d.ts +22 -0
- package/dist/commands/testAnalyzer.d.ts.map +1 -0
- package/dist/commands/testAnalyzer.js +190 -0
- package/dist/commands/testAnalyzer.js.map +1 -0
- package/package.json +3 -1
package/README.ja.md
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
# ts-rails
|
|
2
|
+
|
|
3
|
+
**TypeScript と Express 向けの Rails スタイルアプリケーション層** — ルーティング、コントローラ、ジェネレータ、リアルタイムチャネル、メーラー、バックグラウンドジョブ、および Irwin エコシステム向けの共通ユーティリティ。
|
|
4
|
+
|
|
5
|
+
| 言語 | ドキュメント |
|
|
6
|
+
|------|----------------|
|
|
7
|
+
| English | [README.md](./README.md) |
|
|
8
|
+
| Tiếng Việt | [README.vi.md](./README.vi.md) |
|
|
9
|
+
| **日本語**(本書) | [README.ja.md](./README.ja.md) |
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 目次
|
|
14
|
+
|
|
15
|
+
1. [概要](#概要)
|
|
16
|
+
2. [インストール](#インストール)
|
|
17
|
+
3. [想定プロジェクト構成](#想定プロジェクト構成)
|
|
18
|
+
4. [ランタイムライブラリ](#ランタイムライブラリ)
|
|
19
|
+
5. [サブパス export](#サブパス-export)
|
|
20
|
+
6. [CLI](#cli)
|
|
21
|
+
7. [ジェネレータ一覧](#ジェネレータ一覧)
|
|
22
|
+
8. [関連プロジェクト](#関連プロジェクト)
|
|
23
|
+
9. [ライセンス](#ライセンス)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 概要
|
|
28
|
+
|
|
29
|
+
`ts-rails` は **アプリ内フレームワーク**(プロジェクト全体のスキャフォールドツールではありません)。アプリケーションは次のように構成します。
|
|
30
|
+
|
|
31
|
+
- HTTP と Socket.IO のライフサイクル用に `RailsApplication` を継承する。
|
|
32
|
+
- `RailsRoute` でルートを宣言する(`resource()`、`action()`、権限、Swagger メタデータ)。
|
|
33
|
+
- ベースクラスの上にコントローラ、サービス、ジョブ、メーラー、チャネルを実装する。
|
|
34
|
+
|
|
35
|
+
| 領域 | 主な API |
|
|
36
|
+
|------|----------|
|
|
37
|
+
| Application | `RailsApplication`、`MiddlewareFactory`、`loadConcerns`、`bootstrap()`、`getRoutes()` |
|
|
38
|
+
| Routing | `RailsRoute`、`RestActions`、`action()`、`resource()` |
|
|
39
|
+
| Controller | `RailsController`、`@BeforeAction`、`@AfterAction`、ストロングパラメータ、`ApiResponse` |
|
|
40
|
+
| Real-time | `RailsChannel`、`channelClasses` による登録 |
|
|
41
|
+
| Mail | `RailsMailer`、`MailerAdapter` |
|
|
42
|
+
| Job | `RailsJob`、`JobAdapter`、`performLater()` |
|
|
43
|
+
| API ドキュメント | ルートの `document` から Swagger レジストリ |
|
|
44
|
+
| ユーティリティ | `logger`、`Cache`、ページネーション、ビューヘルパー、`AppError` 階層 |
|
|
45
|
+
|
|
46
|
+
**新規プロジェクト**や機能パック(`auth`、`admin` など)は **[irwin-cli](../irwin-cli/PLAN.md)**(計画中)を使用してください。本パッケージは **既存アプリ内のランタイムとジェネレータ** に焦点を当てます。
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## インストール
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm install ts-rails
|
|
54
|
+
# または
|
|
55
|
+
yarn add ts-rails
|
|
56
|
+
# または
|
|
57
|
+
pnpm add ts-rails
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### ピア依存関係
|
|
61
|
+
|
|
62
|
+
アプリで実際に使うピアをインストールしてください(コアには Express が必須。他は機能に応じて):
|
|
63
|
+
|
|
64
|
+
| パッケージ | 用途 |
|
|
65
|
+
|------------|------|
|
|
66
|
+
| `express` | HTTP サーバー |
|
|
67
|
+
| `reflect-metadata`、`class-validator`、`class-transformer` | ストロングパラメータ / バリデーション |
|
|
68
|
+
| `cookie-parser`、`method-override` | 標準ミドルウェア |
|
|
69
|
+
| `socket.io` | チャネル |
|
|
70
|
+
| `nodemailer` | メーラー |
|
|
71
|
+
| `swagger-ui-express` | Swagger UI(アプリ側) |
|
|
72
|
+
| `dayjs` | ビューヘルパー `timeAgo` |
|
|
73
|
+
| `pluralize` | CLI ジェネレータ |
|
|
74
|
+
| `http-errors` | 404 / エラー処理 |
|
|
75
|
+
|
|
76
|
+
### CLI はローカルで実行
|
|
77
|
+
|
|
78
|
+
`rails` バイナリは本パッケージに含まれます。**アプリルートからローカルインストール経由で実行**してください(Windows でパスに空白がある場合、グローバル実行は失敗しやすいです):
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
pnpm exec rails routes
|
|
82
|
+
pnpm exec rails g controller Posts
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
CLI は `app/controllers` が見つかるまで親ディレクトリをたどってアプリルートを解決します(`INIT_CWD`、`PNPM_SCRIPT_SRC_DIR`、`npm_config_local_prefix` も参照)。
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 想定プロジェクト構成
|
|
90
|
+
|
|
91
|
+
ジェネレータと規約は Irwin スタイルのツリーを前提とします:
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
your-app/
|
|
95
|
+
├── app/
|
|
96
|
+
│ ├── controllers/ # CLI ルート検出に必須
|
|
97
|
+
│ ├── views/
|
|
98
|
+
│ ├── services/
|
|
99
|
+
│ ├── jobs/
|
|
100
|
+
│ ├── mailers/
|
|
101
|
+
│ └── channels/
|
|
102
|
+
├── configs/
|
|
103
|
+
│ ├── application.ts # RailsApplication を継承
|
|
104
|
+
│ ├── routes/ # *.route.ts(app/ 外)
|
|
105
|
+
│ └── db/schema.prisma # `g model` 用
|
|
106
|
+
└── __tests__/ # `g test` の出力 (*.test.ts)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## ランタイムライブラリ
|
|
112
|
+
|
|
113
|
+
### RailsApplication
|
|
114
|
+
|
|
115
|
+
`RailsApplication` は Express アプリ、標準ミドルウェア、ルートマウント、エラーハンドラ、HTTP サーバー、Socket.IO を管理します。
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { RailsApplication } from "ts-rails";
|
|
119
|
+
import { Route } from "./configs/routes";
|
|
120
|
+
|
|
121
|
+
export class Application extends RailsApplication {
|
|
122
|
+
constructor() {
|
|
123
|
+
super();
|
|
124
|
+
this.port = process.env.PORT ?? "8000";
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
protected mountRoutes() {
|
|
128
|
+
this.app.use("/", Route.draw());
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
public async initialize() {
|
|
132
|
+
// DB、セッション、メーラー、キャッシュなど
|
|
133
|
+
this.bootstrap();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**静的設定**(`bootstrap()` の前に設定):
|
|
139
|
+
|
|
140
|
+
| プロパティ | 目的 |
|
|
141
|
+
|------------|------|
|
|
142
|
+
| `middlewareFactory` | `requestId`、`requestLogging`、`rateLimit`(必須) |
|
|
143
|
+
| `sessionMiddleware` | 任意。Socket.IO 認証チェーン用 |
|
|
144
|
+
| `mailerAdapter` | アプリ全体のメール送信 |
|
|
145
|
+
| `jobAdapter` | キュー(BullMQ など) |
|
|
146
|
+
| `jobClasses` | 登録ジョブクラス |
|
|
147
|
+
| `channelClasses` | Socket.IO チャネルクラス |
|
|
148
|
+
| `cacheStore` | アプリ全体キャッシュ |
|
|
149
|
+
| `loggerAdapter` | ロギング |
|
|
150
|
+
| `hasher` | パスワードハッシュ(`Security`) |
|
|
151
|
+
|
|
152
|
+
**ライフサイクル**(`bootstrap()` の順序):
|
|
153
|
+
|
|
154
|
+
1. `setupStandardMiddlewares()` — JSON、Cookie、method override、`res.locals.h` 注入
|
|
155
|
+
2. `mountRoutes()` — サブクラスでオーバーライド
|
|
156
|
+
3. `getRoutes()` — イントロスペクション + Swagger パス登録
|
|
157
|
+
4. `setupSwagger()` — アプリでオーバーライド
|
|
158
|
+
5. `setupErrorHandlers()` — 404 + グローバル(`AppError`、API と HTML)
|
|
159
|
+
6. `startBackgroundProcessor()` — ワーカー用(Lambda / `IRWIN_CONSOLE` ではスキップ)
|
|
160
|
+
|
|
161
|
+
**Concerns** — コントローラプロトタイプに共通メソッドを混ぜ込む:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
this.loadConcerns(ApplicationController.prototype, "app/controllers/concerns");
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### ルーティング(`RailsRoute`)
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { RailsRoute, action, RestActions } from "ts-rails";
|
|
171
|
+
import { UsersController } from "@controllers/users.controller";
|
|
172
|
+
|
|
173
|
+
export class AppRoute extends RailsRoute {
|
|
174
|
+
draw() {
|
|
175
|
+
this.resource("/users", UsersController, {
|
|
176
|
+
only: [RestActions.Index, RestActions.Show, RestActions.Create],
|
|
177
|
+
setPermissionFor: "USER_MANAGEMENT",
|
|
178
|
+
document: {
|
|
179
|
+
tags: ["Users"],
|
|
180
|
+
summary: "ユーザー CRUD",
|
|
181
|
+
body: CreateUserValidator,
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
this.get("/profile", action(UsersController, "profile"));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
- **`resource()`** — REST 7 アクション(`only` / `except`、RBAC、`document` で OpenAPI)。
|
|
191
|
+
- **`action(Controller, "methodName")`** — コントローラメソッドをバインド(`@BeforeAction` / `@AfterAction` を実行)。
|
|
192
|
+
- **ファイルアップロード** — ルートに `upload` オプション(multer、制限、`fileFilter`)。
|
|
193
|
+
|
|
194
|
+
権限は `RailsRoute.permissionFactory` と `RailsRoute.actionPermissionMap` で接続します。
|
|
195
|
+
|
|
196
|
+
### コントローラ(`RailsController`)
|
|
197
|
+
|
|
198
|
+
| メソッド / プロパティ | 説明 |
|
|
199
|
+
|----------------------|------|
|
|
200
|
+
| `this.params(Validator).permit(...)` | params/query/body をマージ、`class-validator`、ホワイトリスト |
|
|
201
|
+
| `this.render(view, locals)` | Pug/EJS ビュー |
|
|
202
|
+
| `this.renderJson(data, status?)` | `ApiResponse` 経由の JSON |
|
|
203
|
+
| `this.redirect(path)` | HTTP リダイレクト |
|
|
204
|
+
| `this.flash(type, message)` | フラッシュミドルウェアが必要 |
|
|
205
|
+
| `this.io` | `req.app.get("io")` の Socket.IO |
|
|
206
|
+
| `this.t(key, options?)` | `res.locals.t` の i18n |
|
|
207
|
+
|
|
208
|
+
**フィルタ**(クラスデコレータ):
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
import { RailsController, BeforeAction, AfterAction } from "ts-rails";
|
|
212
|
+
|
|
213
|
+
@BeforeAction("authenticate", { except: ["index"] })
|
|
214
|
+
@AfterAction("logActivity", { only: ["create", "update"] })
|
|
215
|
+
export class UsersController extends RailsController {
|
|
216
|
+
async authenticate() {
|
|
217
|
+
if (!this.req.session?.userId) {
|
|
218
|
+
this.res.status(401).json({ success: false, message: "Unauthorized" });
|
|
219
|
+
return false; // チェーン停止
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### ストロングパラメータ
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
export class CreateUserValidator {
|
|
229
|
+
@IsEmail()
|
|
230
|
+
email: string;
|
|
231
|
+
|
|
232
|
+
@IsString()
|
|
233
|
+
@MinLength(3)
|
|
234
|
+
name: string;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async create() {
|
|
238
|
+
const attrs = await this.params(CreateUserValidator).permit("email", "name");
|
|
239
|
+
// 不正入力 → 422 UnprocessableEntityError
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### API レスポンスとページネーション
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
import { parsePagination, buildPaginatedResponse } from "ts-rails/pagination";
|
|
247
|
+
|
|
248
|
+
async index() {
|
|
249
|
+
const { page, perPage, skip } = parsePagination(this.req.query);
|
|
250
|
+
const [rows, total] = await fetchPage(skip, perPage);
|
|
251
|
+
return this.renderJson(buildPaginatedResponse(rows, total, { page, perPage }));
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### HTTP エラー
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
import {
|
|
259
|
+
BadRequestError,
|
|
260
|
+
UnauthorizedError,
|
|
261
|
+
ForbiddenError,
|
|
262
|
+
NotFoundError,
|
|
263
|
+
UnprocessableEntityError,
|
|
264
|
+
} from "ts-rails/errors";
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
`RailsApplication` のエラーミドルウェアが処理します(`/api/*` は JSON、それ以外は HTML エラービュー)。
|
|
268
|
+
|
|
269
|
+
### リアルタイムチャネル(`RailsChannel`)
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
import { RailsChannel } from "ts-rails";
|
|
273
|
+
|
|
274
|
+
export class ChatChannel extends RailsChannel {
|
|
275
|
+
subscribe() {
|
|
276
|
+
this.socket.on("message", (data) => {
|
|
277
|
+
this.broadcastTo("room_1", "message", data);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
登録例:
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
import * as channels from "@channels";
|
|
287
|
+
RailsApplication.channelClasses = Object.values(channels);
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### メーラー(`RailsMailer`)
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
export class UserMailer extends RailsMailer {
|
|
294
|
+
static async welcome(user: { email: string; name: string }) {
|
|
295
|
+
await this.deliver({
|
|
296
|
+
to: user.email,
|
|
297
|
+
subject: "ようこそ",
|
|
298
|
+
html: `<p>こんにちは ${user.name}</p>`,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
`RailsApplication.mailerAdapter` を設定するか、`ApplicationMailer` で `getTransporter()` をオーバーライドします。
|
|
305
|
+
|
|
306
|
+
### バックグラウンドジョブ(`RailsJob`)
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
export class SyncDataJob extends RailsJob {
|
|
310
|
+
async perform(payload: unknown) {
|
|
311
|
+
// 処理
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
await SyncDataJob.performLater({ id: 1 });
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
非同期キューには `RailsApplication.jobAdapter` を設定。生成ジョブは `ApplicationJob` を継承し、`static cron` で `node-cron` に対応可能。
|
|
319
|
+
|
|
320
|
+
### ビューヘルパー
|
|
321
|
+
|
|
322
|
+
テンプレートでは `h`(`res.locals.h`)として利用:
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
import { viewHelpers as h } from "ts-rails";
|
|
326
|
+
|
|
327
|
+
h.timeAgo(new Date());
|
|
328
|
+
h.numberToCurrency(50000, "VND");
|
|
329
|
+
h.truncate("長い文字列", 20);
|
|
330
|
+
h.assetPath("javascripts/main.ts"); // 本番は Vite manifest
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Swagger
|
|
334
|
+
|
|
335
|
+
ルートの `document` で OpenAPI パスを登録。アプリの `setupSwagger()` で `setupSwaggerUI` を使用。`document.body` の Validator クラスは `class-validator` メタデータから JSON Schema にマップされます。
|
|
336
|
+
|
|
337
|
+
### ロガーとキャッシュ
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
import { logger } from "ts-rails/logger";
|
|
341
|
+
import { Cache } from "ts-rails/cache";
|
|
342
|
+
|
|
343
|
+
logger.info("起動しました");
|
|
344
|
+
await Cache.set("key", value, { ttl: 3600 });
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
初期化で `RailsApplication.loggerAdapter` と `RailsApplication.cacheStore` を設定します。
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## サブパス export
|
|
352
|
+
|
|
353
|
+
| import | モジュール |
|
|
354
|
+
|--------|------------|
|
|
355
|
+
| `ts-rails` | 公開 API 一式 |
|
|
356
|
+
| `ts-rails/logger` | ロガー |
|
|
357
|
+
| `ts-rails/cache` | キャッシュ |
|
|
358
|
+
| `ts-rails/errors` | HTTP エラークラス |
|
|
359
|
+
| `ts-rails/pagination` | `parsePagination`、`buildPaginatedResponse` |
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## CLI
|
|
364
|
+
|
|
365
|
+
コマンド名: **`rails`**。エイリアス: `g` → `generate`、`c` → `console`、`r` → `routes`、`n` → `notes`。
|
|
366
|
+
|
|
367
|
+
| コマンド | 説明 |
|
|
368
|
+
|----------|------|
|
|
369
|
+
| `rails g <type> <name> [fields...]` | ジェネレータ実行(`cwd` = アプリルート) |
|
|
370
|
+
| `rails routes` | ルート一覧(`configs/application` を読み込み) |
|
|
371
|
+
| `rails console` | アプリコンテキスト付き REPL(`IRWIN_CONSOLE=1`) |
|
|
372
|
+
| `rails notes` | `TODO` / `FIXME` / `OPTIMIZE` コメント一覧(`bin/rails notes` と同様) |
|
|
373
|
+
|
|
374
|
+
### `rails notes`
|
|
375
|
+
|
|
376
|
+
**`app/`**、**`configs/`**、**`lib/`**、**`__tests__/`** 内の `.ts` / `.js` / `.pug` を走査し、タグごとに色分けしてパスと行番号を表示します。
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
pnpm exec rails notes
|
|
380
|
+
pnpm exec rails n
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### ジェネレータ構文
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
pnpm exec rails g <type> <Name> [field:type ...] [--api]
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
**名前空間:** `Admin/User`、`admin/user`、`Admin:User` → `app/.../admin/`、`configs/routes/admin/`。
|
|
390
|
+
|
|
391
|
+
**フィールド型:**
|
|
392
|
+
`string`、`text`、`integer`、`int`、`float`、`decimal`、`boolean`、`date`、`datetime`、`json`。
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## ジェネレータ一覧
|
|
397
|
+
|
|
398
|
+
| type | 生成物 |
|
|
399
|
+
|------|--------|
|
|
400
|
+
| `scaffold` | コントローラ、Pug ビュー(`--api` 除く)、`configs/routes/` のルート |
|
|
401
|
+
| `resource` | API 向けコントローラ + ルート |
|
|
402
|
+
| `controller` | コントローラのみ |
|
|
403
|
+
| `service` | `ApplicationService` / `{Namespace}Service` を継承する `*.service.ts` |
|
|
404
|
+
| `model` | `configs/db/schema.prisma` に Prisma モデル追加 |
|
|
405
|
+
| `mailer` | `ApplicationMailer` を継承 |
|
|
406
|
+
| `job` | `ApplicationJob` を継承(`static cron`、`perform`) |
|
|
407
|
+
| `channel` | `ApplicationChannel` を継承 |
|
|
408
|
+
| `factory` | テスト用ファクトリ stub |
|
|
409
|
+
| `concern` | `app/controllers/concerns/` の mixin |
|
|
410
|
+
| `test` | ソースから Jest stub(public メソッドごとに `it.todo`) |
|
|
411
|
+
|
|
412
|
+
### 例
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
pnpm exec rails g scaffold Product name:string price:decimal description:text
|
|
416
|
+
pnpm exec rails g resource Order total:decimal status:string --api
|
|
417
|
+
pnpm exec rails g controller Admin/Dashboard
|
|
418
|
+
pnpm exec rails g service Payment/Process
|
|
419
|
+
pnpm exec rails g mailer UserNotification
|
|
420
|
+
pnpm exec rails g job SyncInventory
|
|
421
|
+
pnpm exec rails g channel Chat
|
|
422
|
+
pnpm exec rails g model Category name:string
|
|
423
|
+
pnpm exec rails g factory User
|
|
424
|
+
pnpm exec rails g concern Timestampable
|
|
425
|
+
pnpm exec rails g test app/controllers/home.controller.ts
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
**注意:**
|
|
429
|
+
|
|
430
|
+
- ルートは **`configs/routes/`** に出力(`app/routes` ではない)。
|
|
431
|
+
- サービスは必要に応じて名前空間の基底クラスを自動作成。
|
|
432
|
+
- `g scaffold` は隣接 `*.spec.ts` を生成しない。`g test` を使用。
|
|
433
|
+
- 生成コードのリダイレクトはテンプレートリテラルで正しいパスを使用。
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## 関連プロジェクト
|
|
438
|
+
|
|
439
|
+
| リポジトリ | 役割 |
|
|
440
|
+
|------------|------|
|
|
441
|
+
| [irwin-framework](../irwin-framework/) | 全機能のリファレンスアプリ |
|
|
442
|
+
| [irwin-cli](../irwin-cli/) | `irwin new`、`irwin add`(計画) |
|
|
443
|
+
| **ts-rails**(本リポジトリ) | アプリ内ランタイム + `rails g` / `routes` / `console` / `notes` |
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## ライセンス
|
|
448
|
+
|
|
449
|
+
MIT — Hoan Pham およびコントリビューターにより開発。
|