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.
Files changed (190) hide show
  1. package/final-documentation/Architecture Concept/Request-Lifecycle.md +137 -0
  2. package/final-documentation/Architecture Concept/Service-Container.md +134 -0
  3. package/final-documentation/Architecture Concept/Service-Provider.md +105 -0
  4. package/final-documentation/Database/Database-Introduction.md +240 -0
  5. package/final-documentation/Database/Migrations.md +319 -0
  6. package/final-documentation/Database/Mongoose.md +125 -0
  7. package/final-documentation/Database/Query-Builder.md +181 -0
  8. package/final-documentation/Database/Seeding.md +93 -0
  9. package/final-documentation/Database/Sequelize.md +147 -0
  10. package/final-documentation/Database/Transactions.md +81 -0
  11. package/final-documentation/Digging Deeper/Broadcasting.md +145 -0
  12. package/final-documentation/Digging Deeper/Cache.md +154 -0
  13. package/final-documentation/Digging Deeper/Carbon.md +220 -0
  14. package/final-documentation/Digging Deeper/Deferred-Functions.md +139 -0
  15. package/final-documentation/Digging Deeper/Events.md +123 -0
  16. package/final-documentation/Digging Deeper/File-Storage.md +160 -0
  17. package/final-documentation/Digging Deeper/HTTP-Client.md +112 -0
  18. package/final-documentation/Digging Deeper/Helpers.md +111 -0
  19. package/final-documentation/Digging Deeper/Logging.md +199 -0
  20. package/final-documentation/Digging Deeper/Mail.md +118 -0
  21. package/final-documentation/Digging Deeper/Monitor.md +871 -0
  22. package/final-documentation/Digging Deeper/Queues.md +175 -0
  23. package/final-documentation/Digging Deeper/Rate-Limiting.md +83 -0
  24. package/final-documentation/Digging Deeper/Strings.md +115 -0
  25. package/final-documentation/Digging Deeper/Task-Scheduling.md +411 -0
  26. package/final-documentation/Getting-Started/Configuration.md +104 -0
  27. package/final-documentation/Getting-Started/Deployment.md +191 -0
  28. package/final-documentation/Getting-Started/Directory-structure.md +121 -0
  29. package/final-documentation/Getting-Started/Frontend.md +183 -0
  30. package/final-documentation/Getting-Started/Installation.md +309 -0
  31. package/final-documentation/Getting-Started/Introduction.md +27 -0
  32. package/final-documentation/JCC-Eloquent/Defining-Model.md +297 -0
  33. package/final-documentation/JCC-Eloquent/JCC-Eloquent-Introduction.md +134 -0
  34. package/final-documentation/JCC-Eloquent/Mutators.md +95 -0
  35. package/final-documentation/JCC-Eloquent/Observer.md +10 -0
  36. package/final-documentation/JCC-Eloquent/Pagination.md +137 -0
  37. package/final-documentation/JCC-Eloquent/Query-Builder.md +346 -0
  38. package/final-documentation/JCC-Eloquent/Relationships.md +113 -0
  39. package/final-documentation/JCC-Eloquent/Retrieving-Models.md +146 -0
  40. package/final-documentation/JCC-Eloquent/Scopes.md +88 -0
  41. package/final-documentation/JCC-Eloquent/SoftDelete.md +92 -0
  42. package/final-documentation/Packages/Cloudinary.md +85 -0
  43. package/final-documentation/Packages/JWT.md +91 -0
  44. package/final-documentation/Packages/Socialite.md +153 -0
  45. package/final-documentation/Security/Authentication.md +132 -0
  46. package/final-documentation/Security/Authorization.md +117 -0
  47. package/final-documentation/Security/Email-Verification.md +80 -0
  48. package/final-documentation/Security/Encryption.md +105 -0
  49. package/final-documentation/Security/Hashing.md +84 -0
  50. package/final-documentation/Testing/Database-Testing.md +109 -0
  51. package/final-documentation/Testing/Feature-Testing.md +249 -0
  52. package/final-documentation/Testing/Introduction.md +101 -0
  53. package/final-documentation/Testing/Testing-Overview.md +63 -0
  54. package/final-documentation/Testing/Unit-Testing.md +118 -0
  55. package/final-documentation/The Basics/Artisan-Node.md +123 -0
  56. package/final-documentation/The Basics/Asset-bundling.md +113 -0
  57. package/final-documentation/The Basics/CSRF-protection.md +142 -0
  58. package/final-documentation/The Basics/Controllers.md +96 -0
  59. package/final-documentation/The Basics/Error-handling.md +102 -0
  60. package/final-documentation/The Basics/JCC-Blade.md +330 -0
  61. package/final-documentation/The Basics/Middleware.md +174 -0
  62. package/final-documentation/The Basics/Request.md +178 -0
  63. package/final-documentation/The Basics/Response.md +58 -0
  64. package/final-documentation/The Basics/Routing.md +322 -0
  65. package/final-documentation/The Basics/Session.md +97 -0
  66. package/final-documentation/The Basics/Validation.md +235 -0
  67. package/final-documentation/The Basics/Views.md +87 -0
  68. package/lib/Auth/AuthMiddleware.d.ts.map +1 -1
  69. package/lib/Auth/AuthMiddleware.js +13 -6
  70. package/lib/Cache/index.d.ts +2 -0
  71. package/lib/Cache/index.d.ts.map +1 -1
  72. package/lib/Cache/index.js +101 -6
  73. package/lib/Command-Line/NodeArtisanCommand.d.ts +5 -0
  74. package/lib/Command-Line/NodeArtisanCommand.d.ts.map +1 -1
  75. package/lib/Command-Line/NodeArtisanCommand.js +52 -1
  76. package/lib/Command-Line/WatchCommand.d.ts +12 -2
  77. package/lib/Command-Line/WatchCommand.d.ts.map +1 -1
  78. package/lib/Command-Line/WatchCommand.js +186 -45
  79. package/lib/Error/AppErrorHandler.d.ts.map +1 -1
  80. package/lib/Error/AppErrorHandler.js +4 -0
  81. package/lib/Error/ModelExceptions/ModelTokenError.d.ts +4 -0
  82. package/lib/Error/ModelExceptions/ModelTokenError.d.ts.map +1 -0
  83. package/lib/Error/ModelExceptions/ModelTokenError.js +10 -0
  84. package/lib/Http/index.d.ts +3 -0
  85. package/lib/Http/index.d.ts.map +1 -1
  86. package/lib/Http/index.js +46 -10
  87. package/lib/Jcc-eloquent/lib/Model.d.ts +2 -0
  88. package/lib/Jcc-eloquent/lib/Model.d.ts.map +1 -1
  89. package/lib/Jcc-eloquent/lib/Model.js +13 -1
  90. package/lib/Mail/Manager.d.ts +2 -0
  91. package/lib/Mail/Manager.d.ts.map +1 -1
  92. package/lib/Mail/Manager.js +39 -2
  93. package/lib/Monitor/Collectors/CacheCollector.d.ts +2 -4
  94. package/lib/Monitor/Collectors/CacheCollector.d.ts.map +1 -1
  95. package/lib/Monitor/Collectors/CacheCollector.js +4 -63
  96. package/lib/Monitor/Collectors/CommandCollector.d.ts +3 -4
  97. package/lib/Monitor/Collectors/CommandCollector.d.ts.map +1 -1
  98. package/lib/Monitor/Collectors/CommandCollector.js +3 -4
  99. package/lib/Monitor/Collectors/DatabaseCollector.d.ts +2 -0
  100. package/lib/Monitor/Collectors/DatabaseCollector.d.ts.map +1 -1
  101. package/lib/Monitor/Collectors/DatabaseCollector.js +8 -1
  102. package/lib/Monitor/Collectors/MailCollector.d.ts +2 -4
  103. package/lib/Monitor/Collectors/MailCollector.d.ts.map +1 -1
  104. package/lib/Monitor/Collectors/MailCollector.js +5 -58
  105. package/lib/Monitor/Collectors/OutgoingRequestCollector.d.ts +3 -4
  106. package/lib/Monitor/Collectors/OutgoingRequestCollector.d.ts.map +1 -1
  107. package/lib/Monitor/Collectors/OutgoingRequestCollector.js +6 -8
  108. package/lib/Monitor/Collectors/ScheduleCollector.d.ts +2 -3
  109. package/lib/Monitor/Collectors/ScheduleCollector.d.ts.map +1 -1
  110. package/lib/Monitor/Collectors/ScheduleCollector.js +2 -3
  111. package/lib/Monitor/Controllers/MonitorController.d.ts +1 -0
  112. package/lib/Monitor/Controllers/MonitorController.d.ts.map +1 -1
  113. package/lib/Monitor/Controllers/MonitorController.js +15 -8
  114. package/lib/Monitor/MonitorManager.d.ts +10 -1
  115. package/lib/Monitor/MonitorManager.d.ts.map +1 -1
  116. package/lib/Monitor/MonitorManager.js +39 -1
  117. package/lib/Monitor/MonitorServiceProvider.d.ts.map +1 -1
  118. package/lib/Monitor/MonitorServiceProvider.js +3 -1
  119. package/lib/Monitor/Views/{cache.blade.html → JSBlade/cache.blade.html} +1 -1
  120. package/lib/Monitor/Views/{commands.blade.html → JSBlade/commands.blade.html} +2 -2
  121. package/lib/Monitor/Views/{mail.blade.html → JSBlade/mail.blade.html} +1 -1
  122. package/lib/Monitor/Views/{outgoing.blade.html → JSBlade/outgoing.blade.html} +1 -1
  123. package/lib/Monitor/Views/{queries.blade.html → JSBlade/queries.blade.html} +6 -0
  124. package/lib/Monitor/Views/{requests.blade.html → JSBlade/requests.blade.html} +13 -3
  125. package/lib/Monitor/Views/{scheduled.blade.html → JSBlade/scheduled.blade.html} +1 -1
  126. package/lib/Monitor/Views/React/Cache.jsx +29 -0
  127. package/lib/Monitor/Views/React/Commands.jsx +28 -0
  128. package/lib/Monitor/Views/React/Dashboard.jsx +72 -0
  129. package/lib/Monitor/Views/React/Exceptions.jsx +38 -0
  130. package/lib/Monitor/Views/React/Jobs.jsx +29 -0
  131. package/lib/Monitor/Views/React/Logs.jsx +54 -0
  132. package/lib/Monitor/Views/React/Mail.jsx +29 -0
  133. package/lib/Monitor/Views/React/MonitorLayout.jsx +94 -0
  134. package/lib/Monitor/Views/React/Notifications.jsx +28 -0
  135. package/lib/Monitor/Views/React/Outgoing.jsx +28 -0
  136. package/lib/Monitor/Views/React/Queries.jsx +70 -0
  137. package/lib/Monitor/Views/React/Requests.jsx +34 -0
  138. package/lib/Monitor/Views/React/Scheduled.jsx +28 -0
  139. package/lib/Monitor/Views/React/Sidebar.jsx +108 -0
  140. package/lib/Monitor/Views/React/ui.jsx +176 -0
  141. package/lib/Monitor/Views/React/useTheme.js +69 -0
  142. package/lib/Monitor/Views/Vue/Cache.vue +38 -0
  143. package/lib/Monitor/Views/Vue/Commands.vue +37 -0
  144. package/lib/Monitor/Views/Vue/Dashboard.vue +87 -0
  145. package/lib/Monitor/Views/Vue/DataTable.vue +116 -0
  146. package/lib/Monitor/Views/Vue/EmptyState.vue +18 -0
  147. package/lib/Monitor/Views/Vue/Exceptions.vue +43 -0
  148. package/lib/Monitor/Views/Vue/Jobs.vue +38 -0
  149. package/lib/Monitor/Views/Vue/Logs.vue +58 -0
  150. package/lib/Monitor/Views/Vue/Mail.vue +38 -0
  151. package/lib/Monitor/Views/Vue/MethodBadge.vue +8 -0
  152. package/lib/Monitor/Views/Vue/MonitorLayout.vue +80 -0
  153. package/lib/Monitor/Views/Vue/Notifications.vue +37 -0
  154. package/lib/Monitor/Views/Vue/Outgoing.vue +38 -0
  155. package/lib/Monitor/Views/Vue/Panel.vue +18 -0
  156. package/lib/Monitor/Views/Vue/Queries.vue +68 -0
  157. package/lib/Monitor/Views/Vue/Requests.vue +49 -0
  158. package/lib/Monitor/Views/Vue/Scheduled.vue +37 -0
  159. package/lib/Monitor/Views/Vue/Sidebar.vue +98 -0
  160. package/lib/Monitor/Views/Vue/StateBadge.vue +25 -0
  161. package/lib/Monitor/Views/Vue/StatusBadge.vue +17 -0
  162. package/lib/Monitor/Views/Vue/format.js +31 -0
  163. package/lib/Monitor/Views/Vue/useTheme.js +71 -0
  164. package/lib/Monitor/index.d.ts +1 -0
  165. package/lib/Monitor/index.d.ts.map +1 -1
  166. package/lib/Monitor/index.js +1 -0
  167. package/lib/Monitor/types.d.ts +3 -1
  168. package/lib/Monitor/types.d.ts.map +1 -1
  169. package/lib/Monitor/types.js +13 -2
  170. package/lib/Queue/Queue.d.ts +4 -0
  171. package/lib/Queue/Queue.d.ts.map +1 -1
  172. package/lib/Queue/Queue.js +55 -0
  173. package/lib/Schedule/Scheduler.d.ts +2 -0
  174. package/lib/Schedule/Scheduler.d.ts.map +1 -1
  175. package/lib/Schedule/Scheduler.js +28 -1
  176. package/lib/Server/index.d.ts +2 -0
  177. package/lib/Server/index.d.ts.map +1 -1
  178. package/lib/Server/index.js +12 -1
  179. package/lib/Templating-engine/engineHelper.d.ts +2 -2
  180. package/lib/Templating-engine/engineHelper.d.ts.map +1 -1
  181. package/lib/Templating-engine/engineHelper.js +5 -2
  182. package/package.json +1 -1
  183. /package/lib/Monitor/Views/{dashboard.blade.html → JSBlade/dashboard.blade.html} +0 -0
  184. /package/lib/Monitor/Views/{exceptions.blade.html → JSBlade/exceptions.blade.html} +0 -0
  185. /package/lib/Monitor/Views/{jobs.blade.html → JSBlade/jobs.blade.html} +0 -0
  186. /package/lib/Monitor/Views/{logs.blade.html → JSBlade/logs.blade.html} +0 -0
  187. /package/lib/Monitor/Views/{notifications.blade.html → JSBlade/notifications.blade.html} +0 -0
  188. /package/lib/Monitor/Views/{partials → JSBlade/partials}/empty-state.blade.html +0 -0
  189. /package/lib/Monitor/Views/{partials → JSBlade/partials}/sidebar.blade.html +0 -0
  190. /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.