jcc-express-mvc 1.9.6 → 1.9.7

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.
Files changed (73) hide show
  1. package/final-documentation/Architecture Concept/Service-Provider.md +3 -1
  2. package/final-documentation/Database/Database-Introduction.md +6 -0
  3. package/final-documentation/Database/Prisma.md +275 -0
  4. package/final-documentation/Database/TypeORM.md +240 -0
  5. package/final-documentation/Digging Deeper/Helpers.md +6 -0
  6. package/final-documentation/Getting-Started/Configuration.md +1 -1
  7. package/final-documentation/Getting-Started/Directory-structure.md +1 -1
  8. package/final-documentation/Security/Authentication.md +2 -2
  9. package/final-documentation/The Basics/API-Resources.md +121 -0
  10. package/final-documentation/The Basics/Artisan-Node.md +15 -0
  11. package/final-documentation/The Basics/Response.md +1 -1
  12. package/global.d.ts +2 -0
  13. package/lib/Application/ApplicationBuilder.d.ts.map +1 -1
  14. package/lib/Application/ApplicationBuilder.js +2 -0
  15. package/lib/Auth/AuthMiddleware.d.ts.map +1 -1
  16. package/lib/Auth/AuthMiddleware.js +6 -0
  17. package/lib/Command-Line/MakeCommand.d.ts.map +1 -1
  18. package/lib/Command-Line/MakeCommand.js +3 -1
  19. package/lib/Command-Line/files/Models.d.ts.map +1 -1
  20. package/lib/Command-Line/files/Models.js +16 -0
  21. package/lib/Config/Config.d.ts +1 -1
  22. package/lib/Config/Config.d.ts.map +1 -1
  23. package/lib/Container/index.d.ts.map +1 -1
  24. package/lib/Database/Database.d.ts +1 -1
  25. package/lib/Database/Database.d.ts.map +1 -1
  26. package/lib/Database/Database.js +13 -1
  27. package/lib/Database/DatabaseServiceProvider.d.ts.map +1 -1
  28. package/lib/Database/DatabaseServiceProvider.js +2 -1
  29. package/lib/Database/Drivers/Prisma/register.d.ts.map +1 -1
  30. package/lib/Database/Drivers/Prisma/register.js +4 -0
  31. package/lib/Database/Drivers/TypeORM/connection.d.ts +6 -0
  32. package/lib/Database/Drivers/TypeORM/connection.d.ts.map +1 -0
  33. package/lib/Database/Drivers/TypeORM/connection.js +45 -0
  34. package/lib/Database/Drivers/TypeORM/register.d.ts +7 -0
  35. package/lib/Database/Drivers/TypeORM/register.d.ts.map +1 -0
  36. package/lib/Database/Drivers/TypeORM/register.js +47 -0
  37. package/lib/Database/Drivers/TypeORM/types.d.ts +19 -0
  38. package/lib/Database/Drivers/TypeORM/types.d.ts.map +1 -0
  39. package/lib/Database/Drivers/TypeORM/types.js +2 -0
  40. package/lib/Database/Drivers/TypeORMDriver.d.ts +30 -0
  41. package/lib/Database/Drivers/TypeORMDriver.d.ts.map +1 -0
  42. package/lib/Database/Drivers/TypeORMDriver.js +81 -0
  43. package/lib/Database/TypeORMServiceProvider.d.ts +12 -0
  44. package/lib/Database/TypeORMServiceProvider.d.ts.map +1 -0
  45. package/lib/Database/TypeORMServiceProvider.js +45 -0
  46. package/lib/Database/index.d.ts +5 -0
  47. package/lib/Database/index.d.ts.map +1 -1
  48. package/lib/Database/index.js +18 -9
  49. package/lib/Database/isTypeORMOrm.d.ts +3 -0
  50. package/lib/Database/isTypeORMOrm.d.ts.map +1 -0
  51. package/lib/Database/isTypeORMOrm.js +7 -0
  52. package/lib/Database/type.d.ts +1 -1
  53. package/lib/Database/type.d.ts.map +1 -1
  54. package/lib/Global/helpers.d.ts.map +1 -1
  55. package/lib/Global/helpers.js +3 -0
  56. package/lib/Interface/index.d.ts +6 -0
  57. package/lib/Interface/index.d.ts.map +1 -1
  58. package/lib/Middleware/index.js +1 -1
  59. package/lib/Monitor/MonitorServiceProvider.d.ts.map +1 -1
  60. package/lib/Monitor/MonitorServiceProvider.js +41 -31
  61. package/lib/Request/FormRequest.d.ts +6 -0
  62. package/lib/Request/FormRequest.d.ts.map +1 -1
  63. package/lib/Request/FormRequest.js +8 -0
  64. package/lib/Request/request.d.ts +6 -0
  65. package/lib/Request/request.d.ts.map +1 -1
  66. package/lib/Request/request.js +12 -1
  67. package/lib/util/index.d.ts +1 -0
  68. package/lib/util/index.d.ts.map +1 -1
  69. package/lib/util/index.js +45 -2
  70. package/package.json +1 -1
  71. package/lib/Passport/config.d.ts +0 -14
  72. package/lib/Passport/config.d.ts.map +0 -1
  73. package/lib/Passport/config.js +0 -93
@@ -32,7 +32,8 @@ The abstract base class lives in `jcc-express-mvc` (`ServiceProvider`). Extend i
32
32
 
33
33
  In `withProviders()`, the builder does not use your array alone. It builds this chain:
34
34
 
35
- 1. `DatabaseServiceProvider` — Always first (database-related setup).
35
+ 1. `DatabaseServiceProvider` — Knex / Sequelize / Mongoose setup (skipped when `DB_ORM=prisma`).
36
+ 2. `PrismaServiceProvider` — Prisma client singleton and graceful `$disconnect`.
36
37
  2. Your providers from `bootstrap/providers.ts` — If `AuthServiceProvider` (framework) is in the list but not first, the builder moves it to the front of your list so auth is set up early.
37
38
  3. `QueueServiceProvider` — Always last in the chain.
38
39
 
@@ -98,6 +99,7 @@ export const providers = [AppServiceProvider];
98
99
  ## Framework providers you should know about
99
100
 
100
101
  - `DatabaseServiceProvider` — Database / ORM wiring; runs before your list.
102
+ - `PrismaServiceProvider` — Registers `database.prisma.service` when configured.
101
103
  - `AuthServiceProvider` (when included) — Intended to run early among your providers.
102
104
  - `QueueServiceProvider` — Queue binding; runs after your list.
103
105
  - `RouteServiceProvider` — Not in your `bootstrap/providers.ts` list by default; it is registered as a singleton on `Application` and `loadRoutes()` is invoked from `app.run()` to load `route/web`, `route/api`, etc.
@@ -7,6 +7,7 @@ Almost every real application needs a database. JCC Express MVC keeps this flexi
7
7
  - **JCC ORM (default)** for SQL with a Knex-backed query layer
8
8
  - **Sequelize** as an alternative SQL ORM
9
9
  - **Mongoose** for MongoDB document workflows
10
+ - **Prisma** for schema-first SQL with generated client and migrations
10
11
 
11
12
  In practice, most projects start with the default JCC stack, then switch ORM mode only when needed.
12
13
 
@@ -23,6 +24,8 @@ With the default JCC SQL path (`DB_ORM=jcc`), connection clients include:
23
24
 
24
25
  For document databases, use `DB_ORM=mongoose` with your Mongo connection settings.
25
26
 
27
+ For Prisma, use `DB_ORM=prisma` and configure `DATABASE_URL` plus `database.prisma.service` — see [Prisma](./Prisma.md).
28
+
26
29
  ---
27
30
 
28
31
  ## Configuration
@@ -38,11 +41,14 @@ Minimal shape from `app/Config/database.ts`:
38
41
  ```typescript
39
42
  export const database = {
40
43
  orm: config.get("DB_ORM", "jcc"),
44
+ prisma: { service: PrismaService },
41
45
  sequelize: { /* ... */ },
42
46
  mongoose: { /* ... */ },
43
47
  };
44
48
  ```
45
49
 
50
+ See [Prisma](./Prisma.md) for the full Prisma setup.
51
+
46
52
  ---
47
53
 
48
54
  ## SQLite configuration
@@ -0,0 +1,275 @@
1
+ # Prisma
2
+
3
+ ## Introduction
4
+
5
+ JCC Express MVC supports [Prisma](https://www.prisma.io/) as an ORM option via `DB_ORM=prisma`. Prisma uses its own schema (`prisma/schema.prisma`), migrations, and generated client — separate from JCC Eloquent models in `app/Models/`.
6
+
7
+ You can also use Prisma **alongside** JCC Eloquent by keeping `DB_ORM=jcc` and configuring `database.prisma.service` in `app/Config/database.ts` (the framework still registers a singleton Prisma client).
8
+
9
+ ---
10
+
11
+ ## Enable Prisma
12
+
13
+ ### Option A — Prisma as primary ORM
14
+
15
+ ```env
16
+ DB_ORM=prisma
17
+
18
+ DATABASE_URL="mysql://root:password@127.0.0.1:3306/your_database"
19
+ DATABASE_HOST=127.0.0.1
20
+ DATABASE_PORT=3306
21
+ DATABASE_USER=root
22
+ DATABASE_PASSWORD=password
23
+ DATABASE_NAME=your_database
24
+ ```
25
+
26
+ `DATABASE_URL` is used by the Prisma CLI (`prisma.config.ts`). **The framework does not pick a default runtime adapter.** You must configure one explicitly (see below).
27
+
28
+ Built-in adapter factories (install the matching package when using `PRISMA_ADAPTER` or `database.prisma.adapter`):
29
+
30
+ | `PRISMA_ADAPTER` | Package |
31
+ | ---------------- | --------------------------------------------------- |
32
+ | `mariadb` | `@prisma/adapter-mariadb` |
33
+ | `postgres` | `@prisma/adapter-pg` + `pg` |
34
+ | `sqlite` | `@prisma/adapter-better-sqlite3` + `better-sqlite3` |
35
+ | `libsql` | `@prisma/adapter-libsql` |
36
+
37
+ ```env
38
+ PRISMA_ADAPTER=mariadb
39
+ DATABASE_URL="mysql://root:password@127.0.0.1:3306/your_database"
40
+ ```
41
+
42
+ Or configure the adapter in `PrismaService` / `database.prisma.adapter` instead of `PRISMA_ADAPTER`.
43
+
44
+ ### Option B — Prisma alongside JCC Eloquent
45
+
46
+ Keep `DB_ORM=jcc` for Knex/JCC models and ensure `app/Config/database.ts` includes:
47
+
48
+ ```typescript
49
+ import { PrismaService } from "@/Services/PrismaService";
50
+
51
+ export const database = {
52
+ orm: config.get("DB_ORM", "jcc"),
53
+ prisma: {
54
+ service: PrismaService,
55
+ },
56
+ // ...
57
+ };
58
+ ```
59
+
60
+ `PrismaServiceProvider` registers the client whenever `database.prisma.service` is set.
61
+
62
+ ---
63
+
64
+ ## Required packages
65
+
66
+ ```bash
67
+ npm install @prisma/client @prisma/adapter-mariadb
68
+ npm install -D prisma
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Initialize Prisma (new projects)
74
+
75
+ After installing the packages, scaffold Prisma in your app **once** from the project root. Skip this step if `prisma/schema.prisma` already exists.
76
+
77
+ ```bash
78
+ bun --bun x prisma init --datasource-provider mysql --output ./generated/prisma
79
+ ```
80
+
81
+ Equivalent with `npx`:
82
+
83
+ ```bash
84
+ npx prisma init --datasource-provider mysql --output ./generated/prisma
85
+ ```
86
+
87
+ This creates:
88
+
89
+ | File | Purpose |
90
+ | ---------------------- | -------------------------------------------- |
91
+ | `prisma/schema.prisma` | Your Prisma schema |
92
+ | `prisma.config.ts` | CLI config (`DATABASE_URL`, migrations path) |
93
+
94
+ Use `./generated/prisma` as the client output — **not** `../src/generated/prisma`. JCC Express MVC imports the client from `generated/prisma/client` (see `PrismaService` below).
95
+
96
+ Set your database URL in `.env` before generating or migrating:
97
+
98
+ ```env
99
+ DATABASE_URL="mysql://root:password@127.0.0.1:3306/your_database"
100
+ ```
101
+
102
+ Then add `app/Services/PrismaService.ts` and wire `database.prisma.service` in `app/Config/database.ts` (see [App service class](#app-service-class)).
103
+
104
+ ---
105
+
106
+ ## Generate the client
107
+
108
+ Generate the client after `prisma init` and whenever the schema changes:
109
+
110
+ ```bash
111
+ bun artisanNode prisma:generate
112
+ # or
113
+ npm run prisma:generate
114
+ ```
115
+
116
+ The generated client is written to `generated/prisma/` (gitignored — run `prisma:generate` after clone/CI install).
117
+
118
+ Apply your first migration after generate:
119
+
120
+ ```bash
121
+ bun artisanNode prisma:migrate init
122
+ ```
123
+
124
+ ---
125
+
126
+ ## App service class
127
+
128
+ The framework only injects an adapter when you set `database.prisma.adapter` or `PRISMA_ADAPTER`. Otherwise `PrismaService` owns the adapter:
129
+
130
+ ```typescript
131
+ import { PrismaClient } from "generated/prisma/client";
132
+ import { createMariaDbAdapter } from "@framework/lib/Database/Drivers/Prisma/adapters/mariadb";
133
+ import type { PrismaClientOptions } from "@framework/lib/Database/Drivers/Prisma/types";
134
+
135
+ export class PrismaService extends PrismaClient {
136
+ constructor(options?: PrismaClientOptions) {
137
+ super({
138
+ adapter: options?.adapter ?? createMariaDbAdapter(), // your choice in the app
139
+ });
140
+ }
141
+ }
142
+ ```
143
+
144
+ When the framework **does** inject an adapter (`options.adapter`), it takes precedence over your fallback.
145
+
146
+ ---
147
+
148
+ ## Configuring an adapter
149
+
150
+ Choose one approach:
151
+
152
+ **1. In `PrismaService`** (app-owned — recommended when you want full control)
153
+
154
+ **2. `PRISMA_ADAPTER` env** — uses a built-in factory:
155
+
156
+ ```env
157
+ PRISMA_ADAPTER=postgres
158
+ ```
159
+
160
+ **3. `database.prisma.adapter` in app config:**
161
+
162
+ ```typescript
163
+ import { createPostgresAdapter } from "jcc-express-mvc/lib/Database/Drivers/Prisma/adapters/postgres";
164
+
165
+ export const database = {
166
+ prisma: {
167
+ service: PrismaService,
168
+ adapter: () => createPostgresAdapter(),
169
+ },
170
+ };
171
+ ```
172
+
173
+ **Fully custom** — pass any Prisma 7 adapter instance or factory:
174
+
175
+ ```typescript
176
+ import { PrismaPg } from "@prisma/adapter-pg";
177
+ import { Pool } from "pg";
178
+
179
+ prisma: {
180
+ service: PrismaService,
181
+ adapter: () => new PrismaPg(new Pool({ connectionString: process.env.DATABASE_URL })),
182
+ },
183
+ ```
184
+
185
+ `database.prisma.adapter` takes precedence over `PRISMA_ADAPTER`. If neither is set, the framework passes no adapter and `PrismaService` decides.
186
+
187
+ ---
188
+
189
+ ## Framework adapter helpers
190
+
191
+ | Export | Use |
192
+ | --------------------------- | --------------------------------------------------- |
193
+ | `resolvePrismaAdapter(app)` | Used by `PrismaServiceProvider` |
194
+ | `createPrismaAdapter(name)` | Build adapter for a named driver (`PRISMA_ADAPTER`) |
195
+ | `createMariaDbAdapter()` | MySQL / MariaDB |
196
+ | `createPostgresAdapter()` | PostgreSQL |
197
+ | `createSqliteAdapter()` | SQLite file |
198
+ | `createLibSqlAdapter()` | LibSQL / Turso |
199
+
200
+ Import from `jcc-express-mvc/lib/Database` or `jcc-express-mvc/lib/Database/Drivers/Prisma/connection`.
201
+
202
+ The framework registers `PrismaService` as a **singleton** and aliases `prisma` and `database.connection`.
203
+
204
+ ---
205
+
206
+ ## Using Prisma in controllers
207
+
208
+ **Constructor injection** (recommended):
209
+
210
+ ```typescript
211
+ import { Inject } from "jcc-express-mvc/Core/Dependency";
212
+ import { PrismaService } from "@/Services/PrismaService";
213
+
214
+ @Inject()
215
+ export class UsersController {
216
+ constructor(private readonly prisma: PrismaService) {}
217
+
218
+ async index() {
219
+ return await this.prisma.user.findMany();
220
+ }
221
+ }
222
+ ```
223
+
224
+ **Global helper**:
225
+
226
+ ```typescript
227
+ const users = await prisma().user.findMany();
228
+ ```
229
+
230
+ ---
231
+
232
+ ## Schema and migrations
233
+
234
+ Schema: `prisma/schema.prisma`
235
+ Migrations: `prisma/migrations/`
236
+ CLI config: `prisma.config.ts`
237
+
238
+ ```bash
239
+ # Create & apply a migration (development)
240
+ bun artisanNode prisma:migrate init
241
+
242
+ # Apply pending migrations (production)
243
+ bun artisanNode prisma:deploy
244
+
245
+ # Push schema without migration files (prototyping)
246
+ bun artisanNode prisma:push
247
+
248
+ # Open Prisma Studio
249
+ bun artisanNode prisma:studio
250
+ ```
251
+
252
+ Equivalent npm scripts: `prisma:generate`, `prisma:migrate`, `prisma:studio`.
253
+
254
+ ---
255
+
256
+ ## Framework wiring
257
+
258
+ | Piece | Location |
259
+ | ----------------------- | ------------------------------------------------------------ |
260
+ | `PrismaDriver` | `jcc-express-mvc/lib/Database/Drivers/PrismaDriver.ts` |
261
+ | Driver adapters | `jcc-express-mvc/lib/Database/Drivers/Prisma/adapters/` |
262
+ | `PrismaServiceProvider` | `jcc-express-mvc/lib/Database/PrismaServiceProvider.ts` |
263
+ | `Database` resolver | `jcc-express-mvc/lib/Database/Database.ts` (`DB_ORM=prisma`) |
264
+
265
+ `PrismaDriver` implements the same `DatabaseDriver` interface as `KnexDriver`, `SequelizeDriver`, and `MongooseDriver` (`connect`, `getConnection`, `disconnect`). Adapter selection lives under `Drivers/Prisma/`.
266
+
267
+ When `DB_ORM=prisma`, `DatabaseServiceProvider` skips Knex/Sequelize/Mongoose setup so only Prisma owns the connection.
268
+
269
+ ---
270
+
271
+ ## Related
272
+
273
+ - [Database Introduction](./Database-Introduction.md)
274
+ - [ArtisanNode](../The%20Basics/Artisan-Node.md)
275
+ - [Service Provider](../Architecture%20Concept/Service-Provider.md)
@@ -0,0 +1,240 @@
1
+ # TypeORM
2
+
3
+ ## Introduction
4
+
5
+ JCC Express MVC supports [TypeORM](https://typeorm.io/) as an ORM option via `DB_ORM=typeorm`. TypeORM uses decorator-based **entities** in `app/Entities/` — separate from JCC Eloquent models in `app/Model/` and Sequelize/Mongoose files in `app/Models/`.
6
+
7
+ You can also use TypeORM **alongside** JCC Eloquent by keeping `DB_ORM=jcc` and configuring `database.typeorm.dataSource` in `app/Config/database.ts` (the framework still registers a singleton `DataSource`).
8
+
9
+ ---
10
+
11
+ ## Enable TypeORM
12
+
13
+ ### Option A — TypeORM as primary ORM
14
+
15
+ ```env
16
+ DB_ORM=typeorm
17
+ DB_CONNECTION=mysql2
18
+ DB_HOST=127.0.0.1
19
+ DB_PORT=3306
20
+ DB_DATABASE=your_database
21
+ DB_USERNAME=root
22
+ DB_PASSWORD=password
23
+
24
+ # Development only — use migrations in production
25
+ TYPEORM_SYNCHRONIZE=false
26
+ TYPEORM_LOGGING=false
27
+ ```
28
+
29
+ `DB_CONNECTION` is mapped to a TypeORM driver:
30
+
31
+ | `DB_CONNECTION` | TypeORM type |
32
+ | ------------------------------ | ---------------- |
33
+ | `mysql2`, `mysql`, `mariadb` | `mysql` |
34
+ | `postgres`, `postgresql`, `pg` | `postgres` |
35
+ | `sqlite`, `better-sqlite3` | `better-sqlite3` |
36
+
37
+ ### Option B — TypeORM alongside JCC Eloquent
38
+
39
+ Keep `DB_ORM=jcc` for Knex/JCC models and ensure `app/Config/database.ts` includes:
40
+
41
+ ```typescript
42
+ import { TypeORMDataSource } from "@/Services/TypeORMDataSource";
43
+
44
+ export const database = {
45
+ orm: config.get("DB_ORM", "jcc"),
46
+ typeorm: {
47
+ dataSource: TypeORMDataSource,
48
+ autoloadEntities: true,
49
+ synchronize: false,
50
+ logging: false,
51
+ },
52
+ // ...
53
+ };
54
+ ```
55
+
56
+ `TypeORMServiceProvider` registers the client whenever `database.typeorm.dataSource` is set.
57
+
58
+ ---
59
+
60
+ ## Required packages
61
+
62
+ ```bash
63
+ npm install typeorm
64
+ ```
65
+
66
+ Install the driver for your database (already common in JCC apps):
67
+
68
+ ```bash
69
+ npm install mysql2 # MySQL / MariaDB
70
+ npm install pg # PostgreSQL
71
+ npm install better-sqlite3 # SQLite
72
+ ```
73
+
74
+ ---
75
+
76
+ ## App DataSource class
77
+
78
+ `app/Services/TypeORMDataSource.ts` extends TypeORM `DataSource` and reads connection settings from `DB_*` env vars:
79
+
80
+ ```typescript
81
+ import { DataSource } from "typeorm";
82
+ import { typeORMOptionsFromEnv } from "jcc-express-mvc/lib/Database/Drivers/TypeORM/connection";
83
+ import type { TypeORMDataSourceOptions } from "jcc-express-mvc/lib/Database/Drivers/TypeORM/types";
84
+
85
+ export class TypeORMDataSource extends DataSource {
86
+ constructor(options?: TypeORMDataSourceOptions) {
87
+ super(typeORMOptionsFromEnv(options));
88
+ }
89
+ }
90
+ ```
91
+
92
+ Wire it in `app/Config/database.ts`:
93
+
94
+ ```typescript
95
+ typeorm: {
96
+ dataSource: TypeORMDataSource,
97
+ autoloadEntities: true,
98
+ synchronize: config.get("TYPEORM_SYNCHRONIZE", "false") === "true",
99
+ logging: config.get("TYPEORM_LOGGING", "false") === "true",
100
+ },
101
+ ```
102
+
103
+ When the driver connects, it scans `app/Entities/` for `.ts`/`.js` files and registers exported entity classes (unless `autoloadEntities: false` or you pass `entities` explicitly).
104
+
105
+ ---
106
+
107
+ ## Define entities
108
+
109
+ Place entities in `app/Entities/`:
110
+
111
+ ```typescript
112
+ import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm";
113
+ import { Post } from "./Post";
114
+
115
+ @Entity({ name: "users" })
116
+ export class User {
117
+ @PrimaryGeneratedColumn()
118
+ id!: number;
119
+
120
+ @Column({ unique: true })
121
+ email!: string;
122
+
123
+ @Column({ nullable: true })
124
+ name?: string;
125
+
126
+ @Column({ select: false })
127
+ password!: string;
128
+
129
+ @OneToMany(() => Post, (post) => post.author)
130
+ posts!: Post[];
131
+ }
132
+ ```
133
+
134
+ Generate a new entity with ArtisanNode:
135
+
136
+ ```bash
137
+ bun artisanNode make:model Product
138
+ ```
139
+
140
+ When `DB_ORM=typeorm`, `make:model` scaffolds into `app/Entities/` with TypeORM decorators.
141
+
142
+ ---
143
+
144
+ ## Using TypeORM in controllers
145
+
146
+ **Constructor injection** (recommended):
147
+
148
+ ```typescript
149
+ import { Inject } from "jcc-express-mvc/Core/Dependency";
150
+ import { TypeORMDataSource } from "@/Services/TypeORMDataSource";
151
+ import { User } from "@/Entities/User";
152
+
153
+ @Inject()
154
+ export class UsersController {
155
+ constructor(private readonly db: TypeORMDataSource) {}
156
+
157
+ async index() {
158
+ return this.db.getRepository(User).find();
159
+ }
160
+
161
+ async show(id: number) {
162
+ return this.db.getRepository(User).findOne({
163
+ where: { id },
164
+ relations: { posts: true },
165
+ });
166
+ }
167
+ }
168
+ ```
169
+
170
+ **Global helper**:
171
+
172
+ ```typescript
173
+ import { User } from "@/Entities/User";
174
+
175
+ const users = await typeorm().getRepository(User).find();
176
+ ```
177
+
178
+ ---
179
+
180
+ ## Auth and route model binding
181
+
182
+ When `DB_ORM=typeorm`, framework helpers resolve users and route-bound models via TypeORM repositories:
183
+
184
+ - `findUserById`, `findUserForAuth`
185
+ - `resolveModelBinding`
186
+ - `AuthMiddleware` API auth lookup
187
+
188
+ `getModel("User")` loads from `app/Entities/User` instead of `app/Models/`.
189
+
190
+ ---
191
+
192
+ ## Migrations (TypeORM CLI)
193
+
194
+ Use the TypeORM CLI directly for migrations (not yet wrapped in ArtisanNode):
195
+
196
+ ```bash
197
+ # Generate a migration from entity changes
198
+ npx typeorm migration:generate -d app/Services/TypeORMDataSource.ts migrations/Init
199
+
200
+ # Run migrations
201
+ npx typeorm migration:run -d app/Services/TypeORMDataSource.ts
202
+ ```
203
+
204
+ For local prototyping only, `TYPEORM_SYNCHRONIZE=true` auto-syncs schema from entities. **Do not use synchronize in production.**
205
+
206
+ ---
207
+
208
+ ## Framework wiring
209
+
210
+ | Piece | Location |
211
+ | ------------------------ | ------------------------------------------------------------- |
212
+ | `TypeORMDriver` | `jcc-express-mvc/lib/Database/Drivers/TypeORMDriver.ts` |
213
+ | `TypeORMServiceProvider` | `jcc-express-mvc/lib/Database/TypeORMServiceProvider.ts` |
214
+ | Connection helpers | `jcc-express-mvc/lib/Database/Drivers/TypeORM/connection.ts` |
215
+ | `Database` resolver | `jcc-express-mvc/lib/Database/Database.ts` (`DB_ORM=typeorm`) |
216
+
217
+ `TypeORMDriver` implements the same `DatabaseDriver` interface as other drivers (`connect`, `getConnection`, `disconnect`).
218
+
219
+ When `DB_ORM=typeorm`, `DatabaseServiceProvider` skips Knex/Sequelize/Mongoose setup so only TypeORM owns the connection. Prisma and TypeORM do not register together when one is the primary `DB_ORM`.
220
+
221
+ The database **monitor** query collector is Knex-only; it is skipped automatically when `DB_ORM` is not `jcc`.
222
+
223
+ ---
224
+
225
+ ## Demo routes
226
+
227
+ This repo includes `TestTypeORMController` with routes under `/api/typeorm` when TypeORM is configured:
228
+
229
+ - `GET /api/typeorm` — list users with posts
230
+ - `POST /api/typeorm` — create sample user and post
231
+ - `GET /api/typeorm/:id` — show one user
232
+
233
+ ---
234
+
235
+ ## Related
236
+
237
+ - [Database Introduction](./Database-Introduction.md)
238
+ - [Configuration](../Getting-Started/Configuration.md)
239
+ - [Helpers](../Digging%20Deeper/Helpers.md)
240
+ - [Service Provider](../Architecture%20Concept/Service-Provider.md)
@@ -41,6 +41,12 @@ These depend on per-request container bindings, so they are request-lifecycle he
41
41
  - `can(user, ability, model?, ...args)`
42
42
  - `authorize(user, ability, ...args)`
43
43
 
44
+ ---
45
+
46
+ ## Database helpers
47
+
48
+ - `prisma()` -> registered Prisma client singleton (when `database.prisma.service` is configured or `DB_ORM=prisma`)
49
+
44
50
  Also available:
45
51
 
46
52
  - `bcrypt(value)`
@@ -33,7 +33,7 @@ Use a full URL for `APP_URL` in production (for example `https://example.com`).
33
33
 
34
34
  ### Database and ORM
35
35
 
36
- - `DB_ORM` — `jcc` (Knex / JCC Eloquent), `sequelize`, or `mongoose`.
36
+ - `DB_ORM` — `jcc` (Knex / JCC Eloquent), `sequelize`, `mongoose`, or `prisma`.
37
37
  - `DB_CONNECTION` — Driver for Knex (for example `mysql2`, `postgres`, `sqlite`, `better-sqlite3`).
38
38
  - `DB_HOST`, `DB_PORT`, `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD` — Connection details.
39
39
 
@@ -35,7 +35,7 @@ Other roots you may see in a mature repo include `design/` (schemas, design note
35
35
  ## `app/` — application code
36
36
 
37
37
  - `Config/` — Typed config modules merged in `app/Config/index.ts` (see [Configuration.md](./Configuration.md)).
38
- - `Http/` — `kernel.ts`, `Controllers/`, `ApiControllers/`, `Middlewares/`, `Requests/`.
38
+ - `Http/` — `kernel.ts`, `Controllers/`, `ApiControllers/`, `Middlewares/`, `Requests/`, `Resources/`.
39
39
  - `Models/` — Eloquent (or other ORM) models.
40
40
  - `Providers/` — Service providers (`AppServiceProvider`, queues, sockets, etc.).
41
41
  - `Console/Command/` — Custom `artisanNode` commands.
@@ -107,7 +107,7 @@ For stateless API clients, use `auth().apiAttempt()` to validate credentials and
107
107
 
108
108
  ```typescript
109
109
  Route.post("/api/login", async () => {
110
- const result = await auth().apiAttempt({ field: "email", table: "User" });
110
+ const result = await auth().apiAttempt({ field: "email", model: "User" });
111
111
 
112
112
  if (!result.success) {
113
113
  return response().status(401).json({ message: result.message });
@@ -129,7 +129,7 @@ Route.middleware(["apiAuth"]).get("/api/me", async (req) => {
129
129
  | Field | Default | Description |
130
130
  |---|---|---|
131
131
  | `field` | `"email"` | Request input key to match (`email`, `phone`, `username`, etc.) |
132
- | `table` | `"User"` | Model name resolved via `getModel()` |
132
+ | `model` | `"User"` | Model name resolved via `getModel()` |
133
133
 
134
134
  The request body must include the credential field and `password`. On success, returns `{ success: true, token, user, message }`. On failure, returns `{ success: false, token: null, user: null, message: "Invalid credentials" }`.
135
135