jcc-express-mvc 1.9.2 → 1.9.4
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 +137 -0
- package/final-documentation/Architecture Concept/Service-Container.md +134 -0
- package/final-documentation/Architecture Concept/Service-Provider.md +105 -0
- package/final-documentation/Database/Database-Introduction.md +240 -0
- package/final-documentation/Database/Migrations.md +319 -0
- package/final-documentation/Database/Mongoose.md +125 -0
- package/final-documentation/Database/Query-Builder.md +181 -0
- package/final-documentation/Database/Seeding.md +93 -0
- package/final-documentation/Database/Sequelize.md +147 -0
- package/final-documentation/Database/Transactions.md +81 -0
- package/final-documentation/Digging Deeper/Broadcasting.md +145 -0
- package/final-documentation/Digging Deeper/Cache.md +154 -0
- package/final-documentation/Digging Deeper/Carbon.md +220 -0
- package/final-documentation/Digging Deeper/Deferred-Functions.md +139 -0
- package/final-documentation/Digging Deeper/Events.md +123 -0
- package/final-documentation/Digging Deeper/File-Storage.md +160 -0
- package/final-documentation/Digging Deeper/HTTP-Client.md +112 -0
- package/final-documentation/Digging Deeper/Helpers.md +111 -0
- package/final-documentation/Digging Deeper/Logging.md +199 -0
- package/final-documentation/Digging Deeper/Mail.md +118 -0
- package/final-documentation/Digging Deeper/Monitor.md +871 -0
- package/final-documentation/Digging Deeper/Queues.md +175 -0
- package/final-documentation/Digging Deeper/Rate-Limiting.md +83 -0
- package/final-documentation/Digging Deeper/Strings.md +115 -0
- package/final-documentation/Digging Deeper/Task-Scheduling.md +411 -0
- package/final-documentation/Getting-Started/Configuration.md +104 -0
- package/final-documentation/Getting-Started/Deployment.md +191 -0
- package/final-documentation/Getting-Started/Directory-structure.md +121 -0
- package/final-documentation/Getting-Started/Frontend.md +183 -0
- package/final-documentation/Getting-Started/Installation.md +309 -0
- package/final-documentation/Getting-Started/Introduction.md +27 -0
- package/final-documentation/JCC-Eloquent/Defining-Model.md +297 -0
- package/final-documentation/JCC-Eloquent/JCC-Eloquent-Introduction.md +134 -0
- package/final-documentation/JCC-Eloquent/Mutators.md +95 -0
- package/final-documentation/JCC-Eloquent/Observer.md +10 -0
- package/final-documentation/JCC-Eloquent/Pagination.md +137 -0
- package/final-documentation/JCC-Eloquent/Query-Builder.md +346 -0
- package/final-documentation/JCC-Eloquent/Relationships.md +113 -0
- package/final-documentation/JCC-Eloquent/Retrieving-Models.md +146 -0
- package/final-documentation/JCC-Eloquent/Scopes.md +88 -0
- package/final-documentation/JCC-Eloquent/SoftDelete.md +92 -0
- package/final-documentation/Packages/Cloudinary.md +85 -0
- package/final-documentation/Packages/JWT.md +91 -0
- package/final-documentation/Packages/Socialite.md +153 -0
- package/final-documentation/Security/Authentication.md +132 -0
- package/final-documentation/Security/Authorization.md +117 -0
- package/final-documentation/Security/Email-Verification.md +80 -0
- package/final-documentation/Security/Encryption.md +105 -0
- package/final-documentation/Security/Hashing.md +84 -0
- package/final-documentation/Testing/Database-Testing.md +109 -0
- package/final-documentation/Testing/Feature-Testing.md +249 -0
- package/final-documentation/Testing/Introduction.md +101 -0
- package/final-documentation/Testing/Testing-Overview.md +63 -0
- package/final-documentation/Testing/Unit-Testing.md +118 -0
- package/final-documentation/The Basics/Artisan-Node.md +123 -0
- package/final-documentation/The Basics/Asset-bundling.md +113 -0
- package/final-documentation/The Basics/CSRF-protection.md +142 -0
- package/final-documentation/The Basics/Controllers.md +96 -0
- package/final-documentation/The Basics/Error-handling.md +102 -0
- package/final-documentation/The Basics/JCC-Blade.md +330 -0
- package/final-documentation/The Basics/Middleware.md +174 -0
- package/final-documentation/The Basics/Request.md +178 -0
- package/final-documentation/The Basics/Response.md +58 -0
- package/final-documentation/The Basics/Routing.md +322 -0
- package/final-documentation/The Basics/Session.md +97 -0
- package/final-documentation/The Basics/Validation.md +235 -0
- package/final-documentation/The Basics/Views.md +87 -0
- package/lib/Auth/AuthMiddleware.d.ts.map +1 -1
- package/lib/Auth/AuthMiddleware.js +13 -6
- package/lib/Cache/index.d.ts +2 -0
- package/lib/Cache/index.d.ts.map +1 -1
- package/lib/Cache/index.js +101 -6
- package/lib/Command-Line/NodeArtisanCommand.d.ts +5 -0
- package/lib/Command-Line/NodeArtisanCommand.d.ts.map +1 -1
- package/lib/Command-Line/NodeArtisanCommand.js +52 -1
- package/lib/Command-Line/WatchCommand.d.ts +12 -2
- package/lib/Command-Line/WatchCommand.d.ts.map +1 -1
- package/lib/Command-Line/WatchCommand.js +186 -45
- package/lib/Error/AppErrorHandler.d.ts.map +1 -1
- package/lib/Error/AppErrorHandler.js +4 -0
- package/lib/Error/ModelExceptions/ModelTokenError.d.ts +4 -0
- package/lib/Error/ModelExceptions/ModelTokenError.d.ts.map +1 -0
- package/lib/Error/ModelExceptions/ModelTokenError.js +10 -0
- package/lib/Http/index.d.ts +3 -0
- package/lib/Http/index.d.ts.map +1 -1
- package/lib/Http/index.js +46 -10
- package/lib/Jcc-eloquent/lib/Model.d.ts +2 -0
- package/lib/Jcc-eloquent/lib/Model.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Model.js +13 -1
- package/lib/Mail/Manager.d.ts +2 -0
- package/lib/Mail/Manager.d.ts.map +1 -1
- package/lib/Mail/Manager.js +39 -2
- package/lib/Monitor/Collectors/CacheCollector.d.ts +2 -4
- package/lib/Monitor/Collectors/CacheCollector.d.ts.map +1 -1
- package/lib/Monitor/Collectors/CacheCollector.js +4 -63
- package/lib/Monitor/Collectors/CommandCollector.d.ts +3 -4
- package/lib/Monitor/Collectors/CommandCollector.d.ts.map +1 -1
- package/lib/Monitor/Collectors/CommandCollector.js +3 -4
- package/lib/Monitor/Collectors/DatabaseCollector.d.ts +2 -0
- package/lib/Monitor/Collectors/DatabaseCollector.d.ts.map +1 -1
- package/lib/Monitor/Collectors/DatabaseCollector.js +8 -1
- package/lib/Monitor/Collectors/MailCollector.d.ts +2 -4
- package/lib/Monitor/Collectors/MailCollector.d.ts.map +1 -1
- package/lib/Monitor/Collectors/MailCollector.js +5 -58
- package/lib/Monitor/Collectors/OutgoingRequestCollector.d.ts +3 -4
- package/lib/Monitor/Collectors/OutgoingRequestCollector.d.ts.map +1 -1
- package/lib/Monitor/Collectors/OutgoingRequestCollector.js +6 -8
- package/lib/Monitor/Collectors/ScheduleCollector.d.ts +2 -3
- package/lib/Monitor/Collectors/ScheduleCollector.d.ts.map +1 -1
- package/lib/Monitor/Collectors/ScheduleCollector.js +2 -3
- package/lib/Monitor/Controllers/MonitorController.d.ts +1 -0
- package/lib/Monitor/Controllers/MonitorController.d.ts.map +1 -1
- package/lib/Monitor/Controllers/MonitorController.js +15 -8
- package/lib/Monitor/MonitorManager.d.ts +10 -1
- package/lib/Monitor/MonitorManager.d.ts.map +1 -1
- package/lib/Monitor/MonitorManager.js +39 -1
- package/lib/Monitor/MonitorServiceProvider.d.ts.map +1 -1
- package/lib/Monitor/MonitorServiceProvider.js +3 -1
- package/lib/Monitor/Views/{cache.blade.html → JSBlade/cache.blade.html} +1 -1
- package/lib/Monitor/Views/{commands.blade.html → JSBlade/commands.blade.html} +2 -2
- package/lib/Monitor/Views/{mail.blade.html → JSBlade/mail.blade.html} +1 -1
- package/lib/Monitor/Views/{outgoing.blade.html → JSBlade/outgoing.blade.html} +1 -1
- package/lib/Monitor/Views/{queries.blade.html → JSBlade/queries.blade.html} +6 -0
- package/lib/Monitor/Views/{requests.blade.html → JSBlade/requests.blade.html} +13 -3
- package/lib/Monitor/Views/{scheduled.blade.html → JSBlade/scheduled.blade.html} +1 -1
- package/lib/Monitor/Views/React/Cache.jsx +29 -0
- package/lib/Monitor/Views/React/Commands.jsx +28 -0
- package/lib/Monitor/Views/React/Dashboard.jsx +72 -0
- package/lib/Monitor/Views/React/Exceptions.jsx +38 -0
- package/lib/Monitor/Views/React/Jobs.jsx +29 -0
- package/lib/Monitor/Views/React/Logs.jsx +54 -0
- package/lib/Monitor/Views/React/Mail.jsx +29 -0
- package/lib/Monitor/Views/React/MonitorLayout.jsx +94 -0
- package/lib/Monitor/Views/React/Notifications.jsx +28 -0
- package/lib/Monitor/Views/React/Outgoing.jsx +28 -0
- package/lib/Monitor/Views/React/Queries.jsx +70 -0
- package/lib/Monitor/Views/React/Requests.jsx +34 -0
- package/lib/Monitor/Views/React/Scheduled.jsx +28 -0
- package/lib/Monitor/Views/React/Sidebar.jsx +108 -0
- package/lib/Monitor/Views/React/ui.jsx +176 -0
- package/lib/Monitor/Views/React/useTheme.js +69 -0
- package/lib/Monitor/Views/Vue/Cache.vue +38 -0
- package/lib/Monitor/Views/Vue/Commands.vue +37 -0
- package/lib/Monitor/Views/Vue/Dashboard.vue +87 -0
- package/lib/Monitor/Views/Vue/DataTable.vue +116 -0
- package/lib/Monitor/Views/Vue/EmptyState.vue +18 -0
- package/lib/Monitor/Views/Vue/Exceptions.vue +43 -0
- package/lib/Monitor/Views/Vue/Jobs.vue +38 -0
- package/lib/Monitor/Views/Vue/Logs.vue +58 -0
- package/lib/Monitor/Views/Vue/Mail.vue +38 -0
- package/lib/Monitor/Views/Vue/MethodBadge.vue +8 -0
- package/lib/Monitor/Views/Vue/MonitorLayout.vue +80 -0
- package/lib/Monitor/Views/Vue/Notifications.vue +37 -0
- package/lib/Monitor/Views/Vue/Outgoing.vue +38 -0
- package/lib/Monitor/Views/Vue/Panel.vue +18 -0
- package/lib/Monitor/Views/Vue/Queries.vue +68 -0
- package/lib/Monitor/Views/Vue/Requests.vue +49 -0
- package/lib/Monitor/Views/Vue/Scheduled.vue +37 -0
- package/lib/Monitor/Views/Vue/Sidebar.vue +98 -0
- package/lib/Monitor/Views/Vue/StateBadge.vue +25 -0
- package/lib/Monitor/Views/Vue/StatusBadge.vue +17 -0
- package/lib/Monitor/Views/Vue/format.js +31 -0
- package/lib/Monitor/Views/Vue/useTheme.js +71 -0
- package/lib/Monitor/index.d.ts +1 -0
- package/lib/Monitor/index.d.ts.map +1 -1
- package/lib/Monitor/index.js +1 -0
- package/lib/Monitor/types.d.ts +3 -1
- package/lib/Monitor/types.d.ts.map +1 -1
- package/lib/Monitor/types.js +13 -2
- package/lib/Queue/Queue.d.ts +4 -0
- package/lib/Queue/Queue.d.ts.map +1 -1
- package/lib/Queue/Queue.js +55 -0
- package/lib/Schedule/Scheduler.d.ts +2 -0
- package/lib/Schedule/Scheduler.d.ts.map +1 -1
- package/lib/Schedule/Scheduler.js +28 -1
- package/lib/Server/index.d.ts +2 -0
- package/lib/Server/index.d.ts.map +1 -1
- package/lib/Server/index.js +12 -1
- package/lib/Templating-engine/engineHelper.d.ts +2 -2
- package/lib/Templating-engine/engineHelper.d.ts.map +1 -1
- package/lib/Templating-engine/engineHelper.js +5 -2
- package/package.json +1 -1
- /package/lib/Monitor/Views/{dashboard.blade.html → JSBlade/dashboard.blade.html} +0 -0
- /package/lib/Monitor/Views/{exceptions.blade.html → JSBlade/exceptions.blade.html} +0 -0
- /package/lib/Monitor/Views/{jobs.blade.html → JSBlade/jobs.blade.html} +0 -0
- /package/lib/Monitor/Views/{logs.blade.html → JSBlade/logs.blade.html} +0 -0
- /package/lib/Monitor/Views/{notifications.blade.html → JSBlade/notifications.blade.html} +0 -0
- /package/lib/Monitor/Views/{partials → JSBlade/partials}/empty-state.blade.html +0 -0
- /package/lib/Monitor/Views/{partials → JSBlade/partials}/sidebar.blade.html +0 -0
- /package/lib/Monitor/Views/{partials → JSBlade/partials}/top-header.blade.html +0 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# Migrations
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
Migrations are version-controlled schema changes for your database. In JCC Express MVC, migrations are generated and executed through `artisanNode`.
|
|
6
|
+
|
|
7
|
+
Migration files live in `database/migrations`.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Generate a migration
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bun artisanNode make:migration create_users_table
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This creates a timestamped migration file in `database/migrations`.
|
|
18
|
+
|
|
19
|
+
You can also generate queue-related tables:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
bun artisanNode make:queue-table
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Typical migration structure
|
|
28
|
+
|
|
29
|
+
A migration defines schema changes in `up`/`down` style methods (depending on your migration template in this project).
|
|
30
|
+
|
|
31
|
+
Common operations include:
|
|
32
|
+
|
|
33
|
+
- creating tables
|
|
34
|
+
- adding/removing columns
|
|
35
|
+
- indexes/constraints
|
|
36
|
+
- dropping tables
|
|
37
|
+
|
|
38
|
+
Keep each migration focused on one schema change.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Migration schema examples
|
|
43
|
+
|
|
44
|
+
### Create table schema
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { Schema } from "jcc-express-mvc/Eloquent";
|
|
48
|
+
|
|
49
|
+
export class Migration {
|
|
50
|
+
up() {
|
|
51
|
+
return Schema.create("posts", (table) => {
|
|
52
|
+
table.id();
|
|
53
|
+
table.string("title");
|
|
54
|
+
table.string("slug").unique();
|
|
55
|
+
table.text("excerpt").nullable();
|
|
56
|
+
table.longText("content");
|
|
57
|
+
table.boolean("is_published", false);
|
|
58
|
+
table.integer("sort_order").unsigned().default(0);
|
|
59
|
+
table.json("meta").nullable();
|
|
60
|
+
table.date("published_at").nullable();
|
|
61
|
+
table.timestamps();
|
|
62
|
+
table.softDeletes();
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
down() {
|
|
67
|
+
return Schema.dropTable("posts");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Foreign keys and composite unique
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { Schema } from "jcc-express-mvc/Eloquent";
|
|
76
|
+
|
|
77
|
+
export class Migration {
|
|
78
|
+
up() {
|
|
79
|
+
return Schema.create("post_comments", (table) => {
|
|
80
|
+
table.id();
|
|
81
|
+
table.foreignId("post_id").references("id").on("posts");
|
|
82
|
+
table.foreignId("user_id").references("id").on("users");
|
|
83
|
+
table.text("body");
|
|
84
|
+
table.timestamps();
|
|
85
|
+
|
|
86
|
+
table.compositeUnique(
|
|
87
|
+
["post_id", "user_id", "created_at"],
|
|
88
|
+
"uk_post_comments_post_user_created"
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
down() {
|
|
94
|
+
return Schema.dropTable("post_comments");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Alter existing table
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { Schema } from "jcc-express-mvc/Eloquent";
|
|
103
|
+
|
|
104
|
+
export class Migration {
|
|
105
|
+
up() {
|
|
106
|
+
return Schema.table("users", (table) => {
|
|
107
|
+
table.string("phone").nullable();
|
|
108
|
+
table.boolean("is_verified", false);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
down() {
|
|
113
|
+
return Schema.table("users", (table) => {
|
|
114
|
+
table.dropColumns("phone", "is_verified");
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Common schema helpers seen in the current codebase:
|
|
121
|
+
|
|
122
|
+
- `id()`
|
|
123
|
+
- `string()`
|
|
124
|
+
- `text()`
|
|
125
|
+
- `longText()`
|
|
126
|
+
- `integer()`, `smallInteger()`, `unsignedBigInteger()`
|
|
127
|
+
- `boolean()`
|
|
128
|
+
- `json()`
|
|
129
|
+
- `date()`
|
|
130
|
+
- `timestamps()`
|
|
131
|
+
- `softDeletes()`
|
|
132
|
+
- `foreignId(...).references(...).on(...)`
|
|
133
|
+
- `foreign(...).references(...).on(...)`
|
|
134
|
+
- `compositeUnique(columns, indexName)`
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Full migration API (current source)
|
|
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`
|
|
144
|
+
|
|
145
|
+
### `Schema` methods
|
|
146
|
+
|
|
147
|
+
- `create(tableName, callback)`
|
|
148
|
+
- `table(tableName, callback)`
|
|
149
|
+
- `dropTable(tableName)`
|
|
150
|
+
- `dropIfExists(tableName)`
|
|
151
|
+
- `truncate(tableName)`
|
|
152
|
+
- `drop(tableName)`
|
|
153
|
+
- `rename(from, to)`
|
|
154
|
+
- `hasTable(tableName)`
|
|
155
|
+
- `hasColumn(tableName, columnName)`
|
|
156
|
+
|
|
157
|
+
### `Blueprint` column types
|
|
158
|
+
|
|
159
|
+
- `id()`
|
|
160
|
+
- `unsignedBigInteger(column)`
|
|
161
|
+
- `string(column, length?)`
|
|
162
|
+
- `integer(column)`
|
|
163
|
+
- `bigInteger(column)`
|
|
164
|
+
- `tinyInteger(column, size?)`
|
|
165
|
+
- `smallInteger(column)`
|
|
166
|
+
- `mediumInteger(column)`
|
|
167
|
+
- `unsignedSmallInteger(column)`
|
|
168
|
+
- `unsignedMediumInteger(column)`
|
|
169
|
+
- `unsignedInteger(column)`
|
|
170
|
+
- `unsignedTinyInteger(column)`
|
|
171
|
+
- `char(column, length?)`
|
|
172
|
+
- `text(column)`
|
|
173
|
+
- `mediumText(column)`
|
|
174
|
+
- `longText(column)`
|
|
175
|
+
- `tinyText(column)`
|
|
176
|
+
- `binary(column, size?)`
|
|
177
|
+
- `blob(column)`
|
|
178
|
+
- `tinyBlob(column)`
|
|
179
|
+
- `mediumBlob(column)`
|
|
180
|
+
- `longBlob(column)`
|
|
181
|
+
- `dateTime(column)`
|
|
182
|
+
- `date(column)`
|
|
183
|
+
- `timestamp(column)`
|
|
184
|
+
- `time(column)`
|
|
185
|
+
- `year(column)`
|
|
186
|
+
- `enum(column, values?)`
|
|
187
|
+
- `boolean(column, defaultValue?)`
|
|
188
|
+
- `float(column, total?, places?)`
|
|
189
|
+
- `double(column, total?, places?)`
|
|
190
|
+
- `decimal(column, total?, places?)`
|
|
191
|
+
- `json(column)`
|
|
192
|
+
- `jsonb(column)`
|
|
193
|
+
- `uuid(column)`
|
|
194
|
+
- `set(column, values?)`
|
|
195
|
+
- `foreignId(column)`
|
|
196
|
+
- `uuidPrimaryKey(column?)`
|
|
197
|
+
- `ulid(column)`
|
|
198
|
+
- `ulidPrimaryKey(column?)`
|
|
199
|
+
- `ipAddress(column)`
|
|
200
|
+
- `macAddress(column)`
|
|
201
|
+
- `geometry(column)`
|
|
202
|
+
- `point(column)`
|
|
203
|
+
- `polygon(column)`
|
|
204
|
+
- `lineString(column)`
|
|
205
|
+
|
|
206
|
+
### `Blueprint` relationships and morphs
|
|
207
|
+
|
|
208
|
+
- `foreign(column)`
|
|
209
|
+
- `references(column)`
|
|
210
|
+
- `on(table)`
|
|
211
|
+
- `foreignIdFor(model, column?, table?)`
|
|
212
|
+
- `constrained(table, column?)`
|
|
213
|
+
- `morphs(column)`
|
|
214
|
+
- `nullableMorphs(column)`
|
|
215
|
+
- `uuidMorphs(column)`
|
|
216
|
+
- `nullableUuidMorphs(column)`
|
|
217
|
+
- `dropMorphs(column)`
|
|
218
|
+
|
|
219
|
+
### `Blueprint` modifiers and column controls
|
|
220
|
+
|
|
221
|
+
- `default(value)`
|
|
222
|
+
- `nullable()`
|
|
223
|
+
- `unique()`
|
|
224
|
+
- `change()`
|
|
225
|
+
- `after(column)`
|
|
226
|
+
- `first()`
|
|
227
|
+
- `autoIncrement()`
|
|
228
|
+
- `unsigned()`
|
|
229
|
+
- `useCurrent()`
|
|
230
|
+
- `useCurrentOnUpdate()`
|
|
231
|
+
- `storedAs(expression)`
|
|
232
|
+
- `virtualAs(expression)`
|
|
233
|
+
- `charset(charset)`
|
|
234
|
+
- `collation(collation)`
|
|
235
|
+
- `check(expression)`
|
|
236
|
+
- `renameColumn(from, to)`
|
|
237
|
+
- `dropColumns(...columns)`
|
|
238
|
+
|
|
239
|
+
### `Blueprint` indexes and constraints
|
|
240
|
+
|
|
241
|
+
- `index(indexNameOrColumns?)`
|
|
242
|
+
- `dropIndex(indexName)`
|
|
243
|
+
- `dropUnique(indexName)`
|
|
244
|
+
- `dropForeign(indexName)`
|
|
245
|
+
- `dropPrimary()`
|
|
246
|
+
- `fulltext(columns)`
|
|
247
|
+
- `spatialIndex(columns)`
|
|
248
|
+
- `compositeIndex(columns, indexName?)`
|
|
249
|
+
- `compositeUnique(columns, indexName?)`
|
|
250
|
+
|
|
251
|
+
### `Blueprint` timestamps, soft deletes, and token helpers
|
|
252
|
+
|
|
253
|
+
- `timestamps(createdAt?, updatedAt?)`
|
|
254
|
+
- `nullableTimestamps()`
|
|
255
|
+
- `softDeletes(column?)`
|
|
256
|
+
- `dropTimestamps()`
|
|
257
|
+
- `dropSoftDeletes(column?)`
|
|
258
|
+
- `rememberToken()`
|
|
259
|
+
- `dropRememberToken()`
|
|
260
|
+
|
|
261
|
+
### `Blueprint` table-level options
|
|
262
|
+
|
|
263
|
+
- `engine(engine)`
|
|
264
|
+
- `tableCharset(charset)`
|
|
265
|
+
- `tableCollation(collation)`
|
|
266
|
+
- `comment(comment)`
|
|
267
|
+
- `temporary()`
|
|
268
|
+
- `toSQL(actionType?, tableName)`
|
|
269
|
+
|
|
270
|
+
### Foreign key action helpers
|
|
271
|
+
|
|
272
|
+
- `cascade()`
|
|
273
|
+
- `onDelete(action?)`
|
|
274
|
+
- `onUpdate(action?)`
|
|
275
|
+
- `cascadeOnDelete()`
|
|
276
|
+
- `cascadeOnUpdate()`
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Run migrations
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
bun artisanNode migrate
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Runs all pending migrations.
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Rollback and reset
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
bun artisanNode migrate:rollback
|
|
294
|
+
bun artisanNode migrate:rollback step=2
|
|
295
|
+
bun artisanNode migrate:reset
|
|
296
|
+
bun artisanNode migrate:fresh
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
- `migrate:rollback` -> rolls back the last batch (or given steps)
|
|
300
|
+
- `migrate:reset` -> rolls back all migrations
|
|
301
|
+
- `migrate:fresh` -> drops all tables, then reruns migrations
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Best practices
|
|
306
|
+
|
|
307
|
+
- Keep migrations small and reviewable.
|
|
308
|
+
- Never edit old migrations that already ran in shared environments; add a new migration instead.
|
|
309
|
+
- Test rollback paths for critical schema changes.
|
|
310
|
+
- Run migrations in CI/CD before app starts serving traffic.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Summary
|
|
315
|
+
|
|
316
|
+
- Generate with `make:migration`.
|
|
317
|
+
- Apply with `migrate`.
|
|
318
|
+
- Revert with rollback/reset/fresh commands.
|
|
319
|
+
- Keep migration history append-only and environment-safe.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Mongoose
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
JCC Express MVC supports MongoDB through a Mongoose driver (`MongooseDriver`) selected by database config/env.
|
|
6
|
+
|
|
7
|
+
When enabled, the framework resolves and registers the Mongoose connection as:
|
|
8
|
+
|
|
9
|
+
- `database.connection`
|
|
10
|
+
- `mongoose`
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Enable Mongoose
|
|
15
|
+
|
|
16
|
+
Set env values for mongo mode:
|
|
17
|
+
|
|
18
|
+
```env
|
|
19
|
+
DB_ORM=mongoose
|
|
20
|
+
DB_CONNECTION=mongodb
|
|
21
|
+
DB_HOST=127.0.0.1
|
|
22
|
+
DB_PORT=27017
|
|
23
|
+
DB_DATABASE=your_db
|
|
24
|
+
DB_USERNAME=
|
|
25
|
+
DB_PASSWORD=
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`app/Config/database.ts` includes the expected `mongoose` block:
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
mongoose: {
|
|
32
|
+
host,
|
|
33
|
+
port,
|
|
34
|
+
database,
|
|
35
|
+
username,
|
|
36
|
+
password,
|
|
37
|
+
options: {},
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Required packages
|
|
44
|
+
|
|
45
|
+
Install Mongoose:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install mongoose
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Generate models (recommended)
|
|
54
|
+
|
|
55
|
+
Do not manually write model files. Use ArtisanNode:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
bun artisanNode make:model User
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Keep your Mongo-oriented model definitions in `app/Models` so the project structure stays consistent.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Mongoose model example
|
|
66
|
+
|
|
67
|
+
In Mongoose mode, a model file can follow this shape:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import mongoose, { HydratedDocument, InferSchemaType, Schema } from "mongoose";
|
|
71
|
+
|
|
72
|
+
const UserSchema = new Schema(
|
|
73
|
+
{
|
|
74
|
+
name: { type: String, required: true },
|
|
75
|
+
email: { type: String, unique: true, required: true },
|
|
76
|
+
password: { type: String, required: true },
|
|
77
|
+
},
|
|
78
|
+
{ timestamps: true },
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
export const User = mongoose.model("User", UserSchema);
|
|
82
|
+
export type User = HydratedDocument<InferSchemaType<typeof UserSchema>>;
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The exported model name `User` is important in this project for route model binding conventions.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Connection behavior
|
|
90
|
+
|
|
91
|
+
From `MongooseDriver`:
|
|
92
|
+
|
|
93
|
+
- builds URI as `mongodb://[username:password@]host:port/database`
|
|
94
|
+
- runs `mongoose.connect(uri, options)`
|
|
95
|
+
- keeps a shared connection reference for the app lifecycle
|
|
96
|
+
|
|
97
|
+
Disconnect path uses `mongoose.disconnect()`.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Access the Mongoose connection
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
const mongooseConn = app.resolve("mongoose");
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The instance is registered by `DatabaseServiceProvider`.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Notes
|
|
112
|
+
|
|
113
|
+
- Driver selection is triggered by `DB_ORM=mongoose` or `DB_CONNECTION=mongodb`.
|
|
114
|
+
- If host/database are missing, URI construction fails and connect throws.
|
|
115
|
+
- Keep Mongo-specific schema/model logic separate from SQL/JCC query-builder code paths.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Summary
|
|
120
|
+
|
|
121
|
+
- Set `DB_ORM=mongoose`.
|
|
122
|
+
- Configure the `mongoose` section in `app/Config/database.ts`.
|
|
123
|
+
- Install `mongoose`.
|
|
124
|
+
- Generate models with `bun artisanNode make:model User`.
|
|
125
|
+
- Resolve connection via `app.resolve("mongoose")`.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Query Builder
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
JCC Express MVC provides a fluent query builder through `DB.table(...)` and `DB.query()` (`jcc-express-mvc/lib/Jcc-eloquent/lib/Builder.ts`).
|
|
6
|
+
|
|
7
|
+
Use it for composable SQL queries without writing full raw SQL for every operation.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Starting queries
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
const q1 = DB.table("users");
|
|
15
|
+
const q2 = DB.query().from("users");
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Select columns:
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
const rows = await DB.table("users").select("id", "name", "email").get();
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Read methods
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
const all = await DB.table("users").get();
|
|
30
|
+
const first = await DB.table("users").where("id", 1).first();
|
|
31
|
+
const found = await DB.table("users").find(1);
|
|
32
|
+
|
|
33
|
+
const exists = await DB.table("users").where("email", email).exists();
|
|
34
|
+
const notExists = await DB.table("users").where("email", email).doesntExist();
|
|
35
|
+
const oneValue = await DB.table("users").where("id", 1).value("email");
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Where clauses
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
const rows = await DB.table("users")
|
|
44
|
+
.where("active", true)
|
|
45
|
+
.where("age", ">", 18)
|
|
46
|
+
.orWhere("role", "admin")
|
|
47
|
+
.whereNull("deleted_at")
|
|
48
|
+
.get();
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Other common filters:
|
|
52
|
+
|
|
53
|
+
- `whereNot(...)`, `orWhereNot(...)`
|
|
54
|
+
- `whereNotNull(...)`
|
|
55
|
+
- `whereIn(...)`
|
|
56
|
+
- `whereBetween(...)`, `whereNotBetween(...)`
|
|
57
|
+
- `whereDate(...)`, `whereMonth(...)`, `whereDay(...)`, `whereYear(...)`, `whereTime(...)`
|
|
58
|
+
- `whereLike(...)`, `orWhereLike(...)`
|
|
59
|
+
- `whereRaw(...)`, `orWhereRaw(...)`
|
|
60
|
+
- `whereColumn(...)`, `orWhereColumn(...)`, `whereNotColumn(...)`
|
|
61
|
+
- `whereJson(...)`, `orWhereJson(...)`
|
|
62
|
+
- `whereExists(...)`, `orWhereExists(...)`
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Ordering, grouping, and having
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
const report = await DB.table("orders")
|
|
70
|
+
.select("status")
|
|
71
|
+
.select(DB.raw("count(*) as total"))
|
|
72
|
+
.groupBy("status")
|
|
73
|
+
.having("status", "!=", "cancelled")
|
|
74
|
+
.orderBy("total", "desc")
|
|
75
|
+
.get();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Also available:
|
|
79
|
+
|
|
80
|
+
- `latest(column?)`, `older(column?)`
|
|
81
|
+
- `orderByRaw(...)`
|
|
82
|
+
- `groupByRaw(...)`
|
|
83
|
+
- `havingIn(...)`, `havingNotIn(...)`
|
|
84
|
+
- `havingNull(...)`, `havingNotNull(...)`
|
|
85
|
+
- `havingBetween(...)`, `havingNotBetween(...)`
|
|
86
|
+
- `havingRaw(...)`
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Joins
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
const rows = await DB.table("posts")
|
|
94
|
+
.join("users", "posts.user_id", "=", "users.id")
|
|
95
|
+
.leftJoin("comments", "comments.post_id", "=", "posts.id")
|
|
96
|
+
.select("posts.*", "users.name as author")
|
|
97
|
+
.get();
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Join variants:
|
|
101
|
+
|
|
102
|
+
- `innerJoin(...)`
|
|
103
|
+
- `leftJoin(...)`
|
|
104
|
+
- `rightJoin(...)`
|
|
105
|
+
- `leftOuterJoin(...)`
|
|
106
|
+
- `rightOuterJoin(...)`
|
|
107
|
+
- `fullOuterJoin(...)`
|
|
108
|
+
- `joinRaw(...)`
|
|
109
|
+
- subquery joins: `joinSub(...)`, `leftJoinSub(...)`, `rightJoinSub(...)`, `crossJoinSub(...)`
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Write methods
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
await DB.table("users").insert({ name: "Abdou", email: "abdou@example.com" });
|
|
117
|
+
|
|
118
|
+
await DB.table("users").where("id", 1).update({ name: "Abdou J" });
|
|
119
|
+
await DB.table("users").where("id", 1).updateQuietly({ name: "No Events" });
|
|
120
|
+
|
|
121
|
+
await DB.table("users").where("id", 1).delete();
|
|
122
|
+
await DB.table("users").where("id", 1).deleteQuietly();
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Counters and JSON updates:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
await DB.table("users").where("id", 1).increment("login_count", 1);
|
|
129
|
+
await DB.table("users").where("id", 1).decrement("credits", 2);
|
|
130
|
+
await DB.table("users").where("id", 1).updateJson("profile->theme", "dark");
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Aggregates and pagination
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
const total = await DB.table("users").count("id");
|
|
139
|
+
const maxScore = await DB.table("users").max("score");
|
|
140
|
+
const minScore = await DB.table("users").min("score");
|
|
141
|
+
const sumScore = await DB.table("users").sum("score");
|
|
142
|
+
const avgScore = await DB.table("users").avg("score");
|
|
143
|
+
|
|
144
|
+
const page = await DB.table("users").orderBy("id", "desc").paginate(1, 15);
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Pagination returns a page payload (data + metadata) from builder internals.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Raw SQL and transactions
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
const rows = await DB.runQuery("select * from users where active = ?", [1]);
|
|
155
|
+
const rawExpr = DB.raw("count(*) as total");
|
|
156
|
+
|
|
157
|
+
await DB.transaction(async () => {
|
|
158
|
+
await DB.table("wallets").where("id", 1).decrement("balance", 100);
|
|
159
|
+
await DB.table("wallets").where("id", 2).increment("balance", 100);
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Utility methods
|
|
166
|
+
|
|
167
|
+
- `clone()` -> duplicate a query
|
|
168
|
+
- `toSQL()` / `toSqlCode()` -> inspect generated SQL
|
|
169
|
+
- `offset(...)`, `limit(...)`
|
|
170
|
+
- `distinct(...)`
|
|
171
|
+
- `pluck(...)`
|
|
172
|
+
- `union(...)`, `unionAll(...)`
|
|
173
|
+
- `truncate()`
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Summary
|
|
178
|
+
|
|
179
|
+
- Use `DB.table(...)` for most query-builder workflows.
|
|
180
|
+
- Chain filters/joins/groups, then finalize with `get`, `first`, `insert`, `update`, `delete`, etc.
|
|
181
|
+
- Use `runQuery` / `raw` for advanced SQL and `DB.transaction(...)` for atomic operations.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Seeding
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
Seeders populate your database with initial or test data (roles, admin users, fixtures, demo content).
|
|
6
|
+
|
|
7
|
+
Seeders live in `database/seeders` and are executed through `artisanNode`.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Generate a seeder
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bun artisanNode make:seeder UserSeeder
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This creates a new seeder class in `database/seeders`.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Write seeder data
|
|
22
|
+
|
|
23
|
+
Typical seeder pattern:
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { DB } from "jcc-express-mvc/lib/Jcc-eloquent";
|
|
27
|
+
|
|
28
|
+
export class UserSeeder {
|
|
29
|
+
async run() {
|
|
30
|
+
await DB.table("users").insert([
|
|
31
|
+
{ name: "Admin", email: "admin@example.com" },
|
|
32
|
+
{ name: "Editor", email: "editor@example.com" },
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Use framework helpers for sensitive values when needed:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
const password = await bcrypt("secret");
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Run seeders
|
|
47
|
+
|
|
48
|
+
Run default seeding flow (this executes `DatabaseSeeder` in `database/seeders`):
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
bun artisanNode db:seed
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Run a specific seeder class:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
bun artisanNode db:seed class=UserSeeder
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Common workflows
|
|
63
|
+
|
|
64
|
+
### Fresh database + seed
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
bun artisanNode migrate:fresh
|
|
68
|
+
bun artisanNode db:seed
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Queue table + seed app data
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
bun artisanNode make:-table
|
|
75
|
+
bun artisanNode migrate
|
|
76
|
+
bun artisanNode db:seed
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Best practices
|
|
82
|
+
|
|
83
|
+
- Make seeders idempotent where possible (safe to rerun).
|
|
84
|
+
- Keep production seeders minimal (required baseline data only).
|
|
85
|
+
- Separate large demo/test fixtures from critical app bootstrap data.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Summary
|
|
90
|
+
|
|
91
|
+
- Create seeders with `make:seeder`.
|
|
92
|
+
- Execute with `db:seed`.
|
|
93
|
+
- Combine with migrations for repeatable environment setup.
|