jcc-express-mvc 1.9.6 → 1.9.8
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/final-documentation/Architecture Concept/Request-Lifecycle.md +4 -4
- package/final-documentation/Architecture Concept/Service-Container.md +4 -4
- package/final-documentation/Architecture Concept/Service-Provider.md +12 -6
- package/final-documentation/Database/Database-Introduction.md +12 -0
- package/final-documentation/Database/Migrations.md +1 -6
- package/final-documentation/Database/Prisma.md +278 -0
- package/final-documentation/Database/Query-Builder.md +1 -1
- package/final-documentation/Database/Seeding.md +1 -1
- package/final-documentation/Database/Sequelize.md +216 -41
- package/final-documentation/Database/Transactions.md +1 -1
- package/final-documentation/Database/TypeORM.md +332 -0
- package/final-documentation/Digging Deeper/Broadcasting.md +6 -9
- package/final-documentation/Digging Deeper/Cache.md +2 -2
- package/final-documentation/Digging Deeper/Carbon.md +3 -3
- package/final-documentation/Digging Deeper/Deferred-Functions.md +1 -14
- package/final-documentation/Digging Deeper/Events.md +1 -1
- package/final-documentation/Digging Deeper/File-Storage.md +4 -4
- package/final-documentation/Digging Deeper/HTTP-Client.md +1 -6
- package/final-documentation/Digging Deeper/Helpers.md +11 -6
- package/final-documentation/Digging Deeper/Logging.md +3 -4
- package/final-documentation/Digging Deeper/Mail.md +4 -4
- package/final-documentation/Digging Deeper/Monitor.md +6 -26
- package/final-documentation/Digging Deeper/Queues.md +9 -9
- package/final-documentation/Digging Deeper/Rate-Limiting.md +1 -1
- package/final-documentation/Digging Deeper/Strings.md +2 -4
- package/final-documentation/Getting-Started/Configuration.md +12 -9
- package/final-documentation/Getting-Started/Deployment.md +3 -3
- package/final-documentation/Getting-Started/Directory-structure.md +10 -10
- package/final-documentation/Getting-Started/Frontend.md +7 -7
- package/final-documentation/Getting-Started/Installation.md +10 -8
- package/final-documentation/JCC-Eloquent/Defining-Model.md +84 -11
- package/final-documentation/JCC-Eloquent/JCC-Eloquent-Introduction.md +1 -1
- package/final-documentation/JCC-Eloquent/Observer.md +276 -6
- package/final-documentation/JCC-Eloquent/Query-Builder.md +1 -1
- package/final-documentation/Packages/Cloudinary.md +1 -1
- package/final-documentation/Packages/JWT.md +2 -2
- package/final-documentation/Security/Authentication.md +6 -6
- package/final-documentation/Security/Authorization.md +3 -3
- package/final-documentation/Security/Email-Verification.md +2 -2
- package/final-documentation/Security/Encryption.md +1 -1
- package/final-documentation/Security/Hashing.md +1 -1
- package/final-documentation/Testing/Introduction.md +2 -2
- package/final-documentation/Testing/Testing-Overview.md +8 -8
- package/final-documentation/Testing/Unit-Testing.md +3 -36
- package/final-documentation/The Basics/API-Resources.md +117 -0
- package/final-documentation/The Basics/Artisan-Node.md +22 -1
- package/final-documentation/The Basics/Asset-bundling.md +1 -1
- package/final-documentation/The Basics/CSRF-protection.md +1 -1
- package/final-documentation/The Basics/Controllers.md +7 -7
- package/final-documentation/The Basics/Error-handling.md +28 -32
- package/final-documentation/The Basics/JCC-Blade.md +2 -2
- package/final-documentation/The Basics/Middleware.md +2 -2
- package/final-documentation/The Basics/Request.md +6 -5
- package/final-documentation/The Basics/Response.md +3 -3
- package/final-documentation/The Basics/Routing.md +7 -6
- package/final-documentation/The Basics/Session.md +8 -8
- package/final-documentation/The Basics/Validation.md +12 -14
- package/final-documentation/The Basics/Views.md +9 -14
- package/global.d.ts +2 -0
- package/lib/Application/ApplicationBuilder.d.ts.map +1 -1
- package/lib/Application/ApplicationBuilder.js +2 -0
- package/lib/Auth/AuthMiddleware.d.ts.map +1 -1
- package/lib/Auth/AuthMiddleware.js +6 -0
- package/lib/Command-Line/MakeCommand.d.ts.map +1 -1
- package/lib/Command-Line/MakeCommand.js +3 -1
- package/lib/Command-Line/files/Models.d.ts.map +1 -1
- package/lib/Command-Line/files/Models.js +16 -0
- package/lib/Config/Config.d.ts +1 -1
- package/lib/Config/Config.d.ts.map +1 -1
- package/lib/Container/index.d.ts.map +1 -1
- package/lib/Database/Database.d.ts +1 -1
- package/lib/Database/Database.d.ts.map +1 -1
- package/lib/Database/Database.js +13 -1
- package/lib/Database/DatabaseServiceProvider.d.ts.map +1 -1
- package/lib/Database/DatabaseServiceProvider.js +2 -1
- package/lib/Database/Drivers/Prisma/register.d.ts.map +1 -1
- package/lib/Database/Drivers/Prisma/register.js +4 -0
- package/lib/Database/Drivers/TypeORM/connection.d.ts +6 -0
- package/lib/Database/Drivers/TypeORM/connection.d.ts.map +1 -0
- package/lib/Database/Drivers/TypeORM/connection.js +45 -0
- package/lib/Database/Drivers/TypeORM/register.d.ts +7 -0
- package/lib/Database/Drivers/TypeORM/register.d.ts.map +1 -0
- package/lib/Database/Drivers/TypeORM/register.js +47 -0
- package/lib/Database/Drivers/TypeORM/types.d.ts +19 -0
- package/lib/Database/Drivers/TypeORM/types.d.ts.map +1 -0
- package/lib/Database/Drivers/TypeORM/types.js +2 -0
- package/lib/Database/Drivers/TypeORMDriver.d.ts +30 -0
- package/lib/Database/Drivers/TypeORMDriver.d.ts.map +1 -0
- package/lib/Database/Drivers/TypeORMDriver.js +81 -0
- package/lib/Database/TypeORMServiceProvider.d.ts +12 -0
- package/lib/Database/TypeORMServiceProvider.d.ts.map +1 -0
- package/lib/Database/TypeORMServiceProvider.js +45 -0
- package/lib/Database/index.d.ts +5 -0
- package/lib/Database/index.d.ts.map +1 -1
- package/lib/Database/index.js +18 -9
- package/lib/Database/isTypeORMOrm.d.ts +3 -0
- package/lib/Database/isTypeORMOrm.d.ts.map +1 -0
- package/lib/Database/isTypeORMOrm.js +7 -0
- package/lib/Database/type.d.ts +1 -1
- package/lib/Database/type.d.ts.map +1 -1
- package/lib/Global/helpers.d.ts.map +1 -1
- package/lib/Global/helpers.js +3 -0
- package/lib/Interface/index.d.ts +6 -0
- package/lib/Interface/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Event/Event.d.ts +1 -0
- package/lib/Jcc-eloquent/lib/Event/Event.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Event/Event.js +21 -10
- package/lib/Jcc-eloquent/lib/Event/ModelEvent.d.ts +3 -3
- package/lib/Jcc-eloquent/lib/Event/ModelEvent.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Event/ModelEvent.js +23 -22
- package/lib/Jcc-eloquent/lib/Model.d.ts +1 -1
- package/lib/Jcc-eloquent/lib/Model.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Model.js +6 -3
- package/lib/Middleware/index.js +1 -1
- package/lib/Monitor/MonitorServiceProvider.d.ts.map +1 -1
- package/lib/Monitor/MonitorServiceProvider.js +41 -31
- package/lib/Request/FormRequest.d.ts +6 -0
- package/lib/Request/FormRequest.d.ts.map +1 -1
- package/lib/Request/FormRequest.js +8 -0
- package/lib/Request/request.d.ts +6 -0
- package/lib/Request/request.d.ts.map +1 -1
- package/lib/Request/request.js +12 -1
- package/lib/util/index.d.ts +1 -0
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +45 -2
- package/package.json +1 -1
- package/lib/Passport/config.d.ts +0 -14
- package/lib/Passport/config.d.ts.map +0 -1
- package/lib/Passport/config.js +0 -93
|
@@ -59,7 +59,7 @@ Think of the stack as: framework defaults → your kernel `middlewares` (for exa
|
|
|
59
59
|
|
|
60
60
|
One of the most important bootstrap steps is loading service providers. Providers register bindings on the container (`register`) and run extra setup once registrations exist (`boot`).
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
During application bootstrap, the framework prepends `DatabaseServiceProvider`, registers your list from `bootstrap/providers.ts` (and may place `AuthServiceProvider` early), then appends `QueueServiceProvider`. That order matters so the database, auth, and queue subsystems are available where other code expects them.
|
|
63
63
|
|
|
64
64
|
Your own providers live under `app/Providers/` (for example `AppServiceProvider`) and are listed in `bootstrap/providers.ts`. Use `AppServiceProvider` (or additional providers) for container bindings, config-driven setup, and small bootstrap tasks—same idea as Laravel’s `AppServiceProvider`.
|
|
65
65
|
|
|
@@ -92,7 +92,7 @@ If the request fails a guard (for example user not authenticated), middleware ca
|
|
|
92
92
|
|
|
93
93
|
If the request passes all matched middleware, your route or controller runs and produces the response (JSON, Blade, Inertia, redirect, …).
|
|
94
94
|
|
|
95
|
-
Reference — framework middleware order (before kernel entries)
|
|
95
|
+
Reference — default framework middleware order (before kernel entries):
|
|
96
96
|
|
|
97
97
|
1. `express.json()`
|
|
98
98
|
2. `express.urlencoded({ extended: false })`
|
|
@@ -117,7 +117,7 @@ When your controller or closure finishes—by calling `res.send`, `res.json`, `r
|
|
|
117
117
|
|
|
118
118
|
The framework listens for `finish` on the response and clears the per-request `request` / `response` / `next` bindings on the container so the next request does not leak state.
|
|
119
119
|
|
|
120
|
-
If an error is passed to `next(error)` or thrown without being caught,
|
|
120
|
+
If an error is passed to `next(error)` or thrown without being caught, the framework error handler maps it to an HTTP response (status and body). See [Error handling](../The%20Basics/Error-handling.md).
|
|
121
121
|
|
|
122
122
|
---
|
|
123
123
|
|
|
@@ -132,6 +132,6 @@ Your `bootstrap/providers.ts` list is the counterpart to Laravel’s provider li
|
|
|
132
132
|
## Where to customize (quick reference)
|
|
133
133
|
|
|
134
134
|
- Global HTTP middleware — `app/Http/kernel.ts` → `middlewares` and `middlewareAliases`.
|
|
135
|
-
- Default Express stack —
|
|
135
|
+
- Default Express stack — framework global middleware + `app/Config` (CORS, rate limit, engine).
|
|
136
136
|
- Routes and API prefixes — `route/*.ts` and `bootstrap/app.ts` → `withRouting`.
|
|
137
137
|
- Container bindings and boot logic — `app/Providers/*` and `bootstrap/providers.ts`.
|
|
@@ -84,15 +84,15 @@ If resolution fails, you may need an explicit `bind` for that type or pass param
|
|
|
84
84
|
|
|
85
85
|
---
|
|
86
86
|
|
|
87
|
-
## Controllers and
|
|
87
|
+
## Controllers and method injection
|
|
88
88
|
|
|
89
|
-
For controller actions, the framework
|
|
89
|
+
For controller actions, the framework resolves method parameters from container metadata: FormRequest classes, models, route parameters, and services. Plain routes that use `(req, res) =>` do not need this—you still benefit from `view()` / `inertia()` because they read `response` from the container after it is bound.
|
|
90
90
|
|
|
91
91
|
---
|
|
92
92
|
|
|
93
93
|
## Global `app` and helpers
|
|
94
94
|
|
|
95
|
-
After
|
|
95
|
+
After the application boots, `globalThis.app` is the Application instance. Helpers like `env()`, `view()`, and `inertia()` use the container under the hood (for example `response` from `app.resolve("response")`).
|
|
96
96
|
|
|
97
97
|
Prefer constructor injection or explicit `app.resolve()` in providers and long-lived services; use globals where the framework already does (routes, Blade/Inertia helpers).
|
|
98
98
|
|
|
@@ -100,7 +100,7 @@ Prefer constructor injection or explicit `app.resolve()` in providers and long-l
|
|
|
100
100
|
|
|
101
101
|
## Comparison to Laravel (mental model)
|
|
102
102
|
|
|
103
|
-
- Container
|
|
103
|
+
- Container — Laravel: `Illuminate\Container\Container`. JCC: the framework service container (resolved via `app.resolve()` / `app.make()`).
|
|
104
104
|
- Application — Laravel’s `Application` extends the container. JCC: `Application` → `ExpressApplication` → `Container`.
|
|
105
105
|
- Registering services — Laravel: `AppServiceProvider::register`. JCC: same idea in `app/Providers/*` → `register()`.
|
|
106
106
|
- Resolving — Laravel: `app()`, `resolve()`. JCC: `app.resolve()`, `app.make()`.
|
|
@@ -15,7 +15,7 @@ A provider connects the framework to your app:
|
|
|
15
15
|
- Register container bindings (`bind`, `singleton`, `instance`) so other code can `resolve` them.
|
|
16
16
|
- Boot behavior that depends on those bindings (routes are not registered here—`RouteServiceProvider` loads route files during `app.run()`, but your `boot()` can use `Gate`, events, or other services already on the container).
|
|
17
17
|
|
|
18
|
-
The abstract base class
|
|
18
|
+
The abstract base class is **`ServiceProvider`**. Extend it from `jcc-express-mvc/Core/Provider`.
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
@@ -28,13 +28,17 @@ The abstract base class lives in `jcc-express-mvc` (`ServiceProvider`). Extend i
|
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
|
-
## Registration order (
|
|
31
|
+
## Registration order (bootstrap)
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
During `withProviders()`, the application builder does not use your array alone. It builds this chain:
|
|
34
34
|
|
|
35
|
-
1. `
|
|
36
|
-
2.
|
|
37
|
-
3. `
|
|
35
|
+
1. `LogServiceProvider`
|
|
36
|
+
2. `DatabaseServiceProvider` — Knex / Sequelize / Mongoose setup (skipped when `DB_ORM=prisma` or `DB_ORM=typeorm`).
|
|
37
|
+
3. `PrismaServiceProvider` — Prisma client singleton and graceful `$disconnect` (when configured).
|
|
38
|
+
4. `TypeORMServiceProvider` — TypeORM `DataSource` singleton and graceful shutdown (when configured).
|
|
39
|
+
5. `SessionServiceProvider`, `CacheServiceProvider`
|
|
40
|
+
6. 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.
|
|
41
|
+
7. `QueueServiceProvider` — Always last in the chain.
|
|
38
42
|
|
|
39
43
|
That order matters when one provider’s `register()` assumes another binding already exists.
|
|
40
44
|
|
|
@@ -98,6 +102,8 @@ export const providers = [AppServiceProvider];
|
|
|
98
102
|
## Framework providers you should know about
|
|
99
103
|
|
|
100
104
|
- `DatabaseServiceProvider` — Database / ORM wiring; runs before your list.
|
|
105
|
+
- `PrismaServiceProvider` — Registers `database.prisma.service` when configured.
|
|
106
|
+
- `TypeORMServiceProvider` — Registers `database.typeorm.dataSource` when configured.
|
|
101
107
|
- `AuthServiceProvider` (when included) — Intended to run early among your providers.
|
|
102
108
|
- `QueueServiceProvider` — Queue binding; runs after your list.
|
|
103
109
|
- `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,8 @@ 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
|
|
11
|
+
- **TypeORM** for decorator-based entities and `DataSource` repositories
|
|
10
12
|
|
|
11
13
|
In practice, most projects start with the default JCC stack, then switch ORM mode only when needed.
|
|
12
14
|
|
|
@@ -23,6 +25,10 @@ With the default JCC SQL path (`DB_ORM=jcc`), connection clients include:
|
|
|
23
25
|
|
|
24
26
|
For document databases, use `DB_ORM=mongoose` with your Mongo connection settings.
|
|
25
27
|
|
|
28
|
+
For Prisma, use `DB_ORM=prisma` and configure `DATABASE_URL` plus `database.prisma.service` — see [Prisma](./Prisma.md).
|
|
29
|
+
|
|
30
|
+
For TypeORM, use `DB_ORM=typeorm` and configure `database.typeorm.dataSource` — see [TypeORM](./TypeORM.md).
|
|
31
|
+
|
|
26
32
|
---
|
|
27
33
|
|
|
28
34
|
## Configuration
|
|
@@ -38,11 +44,15 @@ Minimal shape from `app/Config/database.ts`:
|
|
|
38
44
|
```typescript
|
|
39
45
|
export const database = {
|
|
40
46
|
orm: config.get("DB_ORM", "jcc"),
|
|
47
|
+
prisma: { service: PrismaService },
|
|
48
|
+
typeorm: { dataSource: TypeORMDataSource },
|
|
41
49
|
sequelize: { /* ... */ },
|
|
42
50
|
mongoose: { /* ... */ },
|
|
43
51
|
};
|
|
44
52
|
```
|
|
45
53
|
|
|
54
|
+
See [Prisma](./Prisma.md) and [TypeORM](./TypeORM.md) for full setup.
|
|
55
|
+
|
|
46
56
|
---
|
|
47
57
|
|
|
48
58
|
## SQLite configuration
|
|
@@ -68,6 +78,8 @@ The provider layer uses your env/config to decide connection behavior:
|
|
|
68
78
|
- `DB_ORM=jcc` -> JCC/Knex SQL flow
|
|
69
79
|
- `DB_ORM=sequelize` -> Sequelize connection path
|
|
70
80
|
- `DB_ORM=mongoose` -> Mongoose connection path
|
|
81
|
+
- `DB_ORM=prisma` -> Prisma client path (see [Prisma](./Prisma.md))
|
|
82
|
+
- `DB_ORM=typeorm` -> TypeORM DataSource path (see [TypeORM](./TypeORM.md))
|
|
71
83
|
|
|
72
84
|
Keep `DB_ORM` and `DB_CONNECTION` consistent (for example, do not pair `DB_ORM=mongoose` with SQL-only assumptions in your app code).
|
|
73
85
|
|
|
@@ -135,12 +135,7 @@ Common schema helpers seen in the current codebase:
|
|
|
135
135
|
|
|
136
136
|
---
|
|
137
137
|
|
|
138
|
-
## Full migration API
|
|
139
|
-
|
|
140
|
-
This list is taken from the current implementation in:
|
|
141
|
-
|
|
142
|
-
- `jcc-express-mvc/lib/Jcc-eloquent/lib/Schema/index.ts`
|
|
143
|
-
- `jcc-express-mvc/lib/Jcc-eloquent/lib/Schema/BluePrint/index.ts`
|
|
138
|
+
## Full migration API
|
|
144
139
|
|
|
145
140
|
### `Schema` methods
|
|
146
141
|
|
|
@@ -0,0 +1,278 @@
|
|
|
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 "jcc-express-mvc/lib/Database/Drivers/Prisma/adapters/mariadb";
|
|
133
|
+
import type { PrismaClientOptions } from "jcc-express-mvc/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/
|
|
164
|
+
postgres";
|
|
165
|
+
|
|
166
|
+
export const database = {
|
|
167
|
+
prisma: {
|
|
168
|
+
service: PrismaService,
|
|
169
|
+
adapter: () => createPostgresAdapter(),
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Fully custom** — pass any Prisma 7 adapter instance or factory:
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { PrismaPg } from "@prisma/adapter-pg";
|
|
178
|
+
import { Pool } from "pg";
|
|
179
|
+
|
|
180
|
+
prisma: {
|
|
181
|
+
service: PrismaService,
|
|
182
|
+
adapter: () => new PrismaPg(new Pool({ connectionString: process.env.DATABASE_URL })),
|
|
183
|
+
},
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
`database.prisma.adapter` takes precedence over `PRISMA_ADAPTER`. If neither is set, the framework passes no adapter and `PrismaService` decides.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Framework adapter helpers
|
|
191
|
+
|
|
192
|
+
Built-in adapter factories:
|
|
193
|
+
|
|
194
|
+
| Export | Use |
|
|
195
|
+
| --------------------------- | --------------------------------------------------- |
|
|
196
|
+
| `createPrismaAdapter(name)` | Build adapter for a named driver (`PRISMA_ADAPTER`) |
|
|
197
|
+
| `createMariaDbAdapter()` | MySQL / MariaDB |
|
|
198
|
+
| `createPostgresAdapter()` | PostgreSQL |
|
|
199
|
+
| `createSqliteAdapter()` | SQLite file |
|
|
200
|
+
| `createLibSqlAdapter()` | LibSQL / Turso |
|
|
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
|
+
When `DB_ORM=prisma` (or when `database.prisma.service` is set in `app/Config/database.ts`):
|
|
266
|
+
|
|
267
|
+
- Your `PrismaService` class is registered as a **singleton**.
|
|
268
|
+
- The client is available via constructor injection, `app.resolve("prisma")`, or the global `prisma()` helper.
|
|
269
|
+
- Knex / Sequelize / Mongoose setup is skipped so Prisma owns the database connection.
|
|
270
|
+
- The client disconnects gracefully on shutdown.
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Related
|
|
275
|
+
|
|
276
|
+
- [Database Introduction](./Database-Introduction.md)
|
|
277
|
+
- [ArtisanNode](../The%20Basics/Artisan-Node.md)
|
|
278
|
+
- [Service Provider](../Architecture%20Concept/Service-Provider.md)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Introduction
|
|
4
4
|
|
|
5
|
-
JCC Express MVC provides a fluent query builder through `DB.table(...)` and `DB.query()
|
|
5
|
+
JCC Express MVC provides a fluent query builder through `DB.table(...)` and `DB.query()`.
|
|
6
6
|
|
|
7
7
|
Use it for composable SQL queries without writing full raw SQL for every operation.
|
|
8
8
|
|