jcc-express-mvc 1.8.8 → 1.8.21

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 (215) hide show
  1. package/__tests__/MySqlSchemaBlueprint.test.d.ts +2 -0
  2. package/__tests__/MySqlSchemaBlueprint.test.d.ts.map +1 -0
  3. package/__tests__/MySqlSchemaBlueprint.test.js +55 -0
  4. package/__tests__/PostgresTranslator.test.d.ts +2 -0
  5. package/__tests__/PostgresTranslator.test.d.ts.map +1 -0
  6. package/__tests__/PostgresTranslator.test.js +82 -0
  7. package/__tests__/SQLiteTranslator.test.d.ts +2 -0
  8. package/__tests__/SQLiteTranslator.test.d.ts.map +1 -0
  9. package/__tests__/SQLiteTranslator.test.js +125 -0
  10. package/__tests__/SchemaAlterBlueprint.test.d.ts +2 -0
  11. package/__tests__/SchemaAlterBlueprint.test.d.ts.map +1 -0
  12. package/__tests__/SchemaAlterBlueprint.test.js +35 -0
  13. package/global.d.ts +3 -1
  14. package/index.d.ts +28 -3
  15. package/index.d.ts.map +1 -1
  16. package/index.js +33 -75
  17. package/lib/Application/Application.d.ts +1 -1
  18. package/lib/Application/Application.d.ts.map +1 -1
  19. package/lib/Application/Application.js +2 -2
  20. package/lib/Application/ApplicationBuilder.d.ts.map +1 -1
  21. package/lib/Application/ApplicationBuilder.js +9 -2
  22. package/lib/Auth/AuthMiddleware.d.ts.map +1 -1
  23. package/lib/Auth/AuthMiddleware.js +29 -12
  24. package/lib/Auth/index.d.ts +17 -3
  25. package/lib/Auth/index.d.ts.map +1 -1
  26. package/lib/Auth/index.js +128 -26
  27. package/lib/Auth/loginRateLimit.d.ts +6 -0
  28. package/lib/Auth/loginRateLimit.d.ts.map +1 -0
  29. package/lib/Auth/loginRateLimit.js +25 -0
  30. package/lib/Auth/refreshTokenStore.d.ts +24 -0
  31. package/lib/Auth/refreshTokenStore.d.ts.map +1 -0
  32. package/lib/Auth/refreshTokenStore.js +46 -0
  33. package/lib/Command-Line/DBCommand.d.ts.map +1 -1
  34. package/lib/Command-Line/DBCommand.js +9 -3
  35. package/lib/Command-Line/KeyGenerateCommand.d.ts +6 -0
  36. package/lib/Command-Line/KeyGenerateCommand.d.ts.map +1 -0
  37. package/lib/Command-Line/KeyGenerateCommand.js +47 -0
  38. package/lib/Command-Line/NodeArtisanCommand.d.ts +2 -0
  39. package/lib/Command-Line/NodeArtisanCommand.d.ts.map +1 -1
  40. package/lib/Command-Line/NodeArtisanCommand.js +20 -3
  41. package/lib/Command-Line/NodeTinker/Tinker.d.ts +5 -2
  42. package/lib/Command-Line/NodeTinker/Tinker.d.ts.map +1 -1
  43. package/lib/Command-Line/NodeTinker/Tinker.js +13 -3
  44. package/lib/Command-Line/WatchCommand.d.ts +29 -0
  45. package/lib/Command-Line/WatchCommand.d.ts.map +1 -0
  46. package/lib/Command-Line/WatchCommand.js +234 -0
  47. package/lib/Command-Line/files/Models.d.ts.map +1 -1
  48. package/lib/Command-Line/files/Models.js +41 -16
  49. package/lib/Console/Command.d.ts +18 -0
  50. package/lib/Console/Command.d.ts.map +1 -1
  51. package/lib/Console/Command.js +29 -0
  52. package/lib/Container/index.d.ts.map +1 -1
  53. package/lib/Container/index.js +21 -7
  54. package/lib/Database/Database.d.ts +2 -1
  55. package/lib/Database/Database.d.ts.map +1 -1
  56. package/lib/Database/Database.js +6 -5
  57. package/lib/Database/DatabaseServiceProvider.d.ts +0 -4
  58. package/lib/Database/DatabaseServiceProvider.d.ts.map +1 -1
  59. package/lib/Database/DatabaseServiceProvider.js +9 -56
  60. package/lib/Database/Drivers/MongooseDriver.d.ts +2 -0
  61. package/lib/Database/Drivers/MongooseDriver.d.ts.map +1 -1
  62. package/lib/Database/Drivers/MongooseDriver.js +11 -13
  63. package/lib/Database/Drivers/SequelizeDriver.d.ts +9 -1
  64. package/lib/Database/Drivers/SequelizeDriver.d.ts.map +1 -1
  65. package/lib/Database/Drivers/SequelizeDriver.js +43 -18
  66. package/lib/Error/SocialiteAuthError/SocialiteAuthError.d.ts +9 -0
  67. package/lib/Error/SocialiteAuthError/SocialiteAuthError.d.ts.map +1 -0
  68. package/lib/Error/SocialiteAuthError/SocialiteAuthError.js +17 -0
  69. package/lib/Global/helpers.d.ts.map +1 -1
  70. package/lib/Global/helpers.js +6 -4
  71. package/lib/Http/index.d.ts +3 -1
  72. package/lib/Http/index.d.ts.map +1 -1
  73. package/lib/Http/index.js +26 -5
  74. package/lib/Interface/index.d.ts +12 -3
  75. package/lib/Interface/index.d.ts.map +1 -1
  76. package/lib/Jcc-eloquent/lib/Builder.d.ts +12 -1
  77. package/lib/Jcc-eloquent/lib/Builder.d.ts.map +1 -1
  78. package/lib/Jcc-eloquent/lib/Builder.js +116 -4
  79. package/lib/Jcc-eloquent/lib/Interfaces/index.d.ts +37 -2
  80. package/lib/Jcc-eloquent/lib/Interfaces/index.d.ts.map +1 -1
  81. package/lib/Jcc-eloquent/lib/Migration.d.ts +6 -0
  82. package/lib/Jcc-eloquent/lib/Migration.d.ts.map +1 -1
  83. package/lib/Jcc-eloquent/lib/Migration.js +24 -2
  84. package/lib/Jcc-eloquent/lib/Model.d.ts +24 -7
  85. package/lib/Jcc-eloquent/lib/Model.d.ts.map +1 -1
  86. package/lib/Jcc-eloquent/lib/Model.js +35 -2
  87. package/lib/Jcc-eloquent/lib/QueryBuilder.d.ts +2 -1
  88. package/lib/Jcc-eloquent/lib/QueryBuilder.d.ts.map +1 -1
  89. package/lib/Jcc-eloquent/lib/QueryBuilder.js +10 -1
  90. package/lib/Jcc-eloquent/lib/Rollback.d.ts.map +1 -1
  91. package/lib/Jcc-eloquent/lib/Rollback.js +9 -2
  92. package/lib/Jcc-eloquent/lib/Schema/BaseSchemaEntity/index.d.ts.map +1 -1
  93. package/lib/Jcc-eloquent/lib/Schema/BaseSchemaEntity/index.js +3 -3
  94. package/lib/Jcc-eloquent/lib/Schema/BluePrint/index.d.ts +6 -2
  95. package/lib/Jcc-eloquent/lib/Schema/BluePrint/index.d.ts.map +1 -1
  96. package/lib/Jcc-eloquent/lib/Schema/BluePrint/index.js +41 -12
  97. package/lib/Jcc-eloquent/lib/Schema/Translator/Sqlite.d.ts.map +1 -1
  98. package/lib/Jcc-eloquent/lib/Schema/Translator/Sqlite.js +21 -3
  99. package/lib/Jcc-eloquent/lib/Schema/Translator/postgres.d.ts +1 -0
  100. package/lib/Jcc-eloquent/lib/Schema/Translator/postgres.d.ts.map +1 -1
  101. package/lib/Jcc-eloquent/lib/Schema/Translator/postgres.js +70 -14
  102. package/lib/Jcc-eloquent/lib/Schema/index.d.ts +12 -0
  103. package/lib/Jcc-eloquent/lib/Schema/index.d.ts.map +1 -1
  104. package/lib/Jcc-eloquent/lib/Schema/index.js +27 -6
  105. package/lib/Jcc-eloquent/lib/utils/index.d.ts +13 -0
  106. package/lib/Jcc-eloquent/lib/utils/index.d.ts.map +1 -1
  107. package/lib/Jcc-eloquent/lib/utils/index.js +62 -0
  108. package/lib/Middleware/index.d.ts.map +1 -1
  109. package/lib/Middleware/index.js +4 -7
  110. package/lib/Model/Sequelize.d.ts +3 -0
  111. package/lib/Model/Sequelize.d.ts.map +1 -0
  112. package/lib/Model/Sequelize.js +6 -0
  113. package/lib/Providers/SessionServiceProvider.d.ts +12 -0
  114. package/lib/Providers/SessionServiceProvider.d.ts.map +1 -0
  115. package/lib/Providers/SessionServiceProvider.js +47 -0
  116. package/lib/Queue/Controllers/QueueControllers.d.ts +4 -13
  117. package/lib/Queue/Controllers/QueueControllers.d.ts.map +1 -1
  118. package/lib/Queue/Controllers/QueueControllers.js +1 -16
  119. package/lib/Queue/Route/web.js +4 -1
  120. package/lib/Queue/index.d.ts +1 -0
  121. package/lib/Queue/index.d.ts.map +1 -1
  122. package/lib/Queue/index.js +3 -0
  123. package/lib/Queue/middleware/queueDashboardGuard.d.ts +7 -0
  124. package/lib/Queue/middleware/queueDashboardGuard.d.ts.map +1 -0
  125. package/lib/Queue/middleware/queueDashboardGuard.js +43 -0
  126. package/lib/Response/index.d.ts.map +1 -1
  127. package/lib/Response/index.js +6 -1
  128. package/lib/Routes/Route.d.ts +2 -2
  129. package/lib/Routes/Route.d.ts.map +1 -1
  130. package/lib/Routes/RouteBuilder.d.ts +2 -2
  131. package/lib/Routes/RouteBuilder.d.ts.map +1 -1
  132. package/lib/Security/CsrfMiddleware.d.ts.map +1 -1
  133. package/lib/Security/CsrfMiddleware.js +6 -4
  134. package/lib/Session/DatabaseSession.d.ts +9 -3
  135. package/lib/Session/DatabaseSession.d.ts.map +1 -1
  136. package/lib/Session/DatabaseSession.js +38 -36
  137. package/lib/Session/ExpressJccSession.d.ts +23 -0
  138. package/lib/Session/ExpressJccSession.d.ts.map +1 -0
  139. package/lib/Session/ExpressJccSession.js +110 -0
  140. package/lib/Session/RedisSession.d.ts +2 -2
  141. package/lib/Session/RedisSession.d.ts.map +1 -1
  142. package/lib/Session/RedisSession.js +19 -5
  143. package/lib/Session/SessionManager.d.ts +18 -4
  144. package/lib/Session/SessionManager.d.ts.map +1 -1
  145. package/lib/Session/SessionManager.js +53 -17
  146. package/lib/Socialite/AbstractProvider.d.ts +60 -0
  147. package/lib/Socialite/AbstractProvider.d.ts.map +1 -0
  148. package/lib/Socialite/AbstractProvider.js +136 -0
  149. package/lib/Socialite/Drivers/facebook/FacebookDriver.d.ts +9 -0
  150. package/lib/Socialite/Drivers/facebook/FacebookDriver.d.ts.map +1 -0
  151. package/lib/Socialite/Drivers/facebook/FacebookDriver.js +40 -0
  152. package/lib/Socialite/Drivers/facebook/FacebookProvider.d.ts +15 -0
  153. package/lib/Socialite/Drivers/facebook/FacebookProvider.d.ts.map +1 -0
  154. package/lib/Socialite/Drivers/facebook/FacebookProvider.js +28 -0
  155. package/lib/Socialite/Drivers/github/GitHubDriver.d.ts +9 -0
  156. package/lib/Socialite/Drivers/github/GitHubDriver.d.ts.map +1 -0
  157. package/lib/Socialite/Drivers/github/GitHubDriver.js +54 -0
  158. package/lib/Socialite/Drivers/github/GitHubProvider.d.ts +15 -0
  159. package/lib/Socialite/Drivers/github/GitHubProvider.d.ts.map +1 -0
  160. package/lib/Socialite/Drivers/github/GitHubProvider.js +28 -0
  161. package/lib/Socialite/Drivers/gitlab/GitLabDriver.d.ts +10 -0
  162. package/lib/Socialite/Drivers/gitlab/GitLabDriver.d.ts.map +1 -0
  163. package/lib/Socialite/Drivers/gitlab/GitLabDriver.js +37 -0
  164. package/lib/Socialite/Drivers/gitlab/GitLabProvider.d.ts +15 -0
  165. package/lib/Socialite/Drivers/gitlab/GitLabProvider.d.ts.map +1 -0
  166. package/lib/Socialite/Drivers/gitlab/GitLabProvider.js +28 -0
  167. package/lib/Socialite/Drivers/google/GoogleDriver.d.ts +9 -0
  168. package/lib/Socialite/Drivers/google/GoogleDriver.d.ts.map +1 -0
  169. package/lib/Socialite/Drivers/google/GoogleDriver.js +39 -0
  170. package/lib/Socialite/Drivers/google/GoogleProvider.d.ts +15 -0
  171. package/lib/Socialite/Drivers/google/GoogleProvider.d.ts.map +1 -0
  172. package/lib/Socialite/Drivers/google/GoogleProvider.js +28 -0
  173. package/lib/Socialite/Drivers/slack/SlackDriver.d.ts +9 -0
  174. package/lib/Socialite/Drivers/slack/SlackDriver.d.ts.map +1 -0
  175. package/lib/Socialite/Drivers/slack/SlackDriver.js +41 -0
  176. package/lib/Socialite/Drivers/slack/SlackProvider.d.ts +16 -0
  177. package/lib/Socialite/Drivers/slack/SlackProvider.d.ts.map +1 -0
  178. package/lib/Socialite/Drivers/slack/SlackProvider.js +37 -0
  179. package/lib/Socialite/Drivers/twitter/TwitterDriver.d.ts +9 -0
  180. package/lib/Socialite/Drivers/twitter/TwitterDriver.d.ts.map +1 -0
  181. package/lib/Socialite/Drivers/twitter/TwitterDriver.js +57 -0
  182. package/lib/Socialite/Drivers/twitter/TwitterProvider.d.ts +16 -0
  183. package/lib/Socialite/Drivers/twitter/TwitterProvider.d.ts.map +1 -0
  184. package/lib/Socialite/Drivers/twitter/TwitterProvider.js +38 -0
  185. package/lib/Socialite/SocialUser.d.ts +42 -0
  186. package/lib/Socialite/SocialUser.d.ts.map +1 -0
  187. package/lib/Socialite/SocialUser.js +116 -0
  188. package/lib/Socialite/Socialite.d.ts +13 -0
  189. package/lib/Socialite/Socialite.d.ts.map +1 -0
  190. package/lib/Socialite/Socialite.js +41 -0
  191. package/lib/Socialite/SocialiteProvider.d.ts +9 -0
  192. package/lib/Socialite/SocialiteProvider.d.ts.map +1 -0
  193. package/lib/Socialite/SocialiteProvider.js +15 -0
  194. package/lib/Socialite/config.d.ts +7 -0
  195. package/lib/Socialite/config.d.ts.map +1 -0
  196. package/lib/Socialite/config.js +44 -0
  197. package/lib/Socialite/constant.d.ts +18 -0
  198. package/lib/Socialite/constant.d.ts.map +1 -0
  199. package/lib/Socialite/constant.js +20 -0
  200. package/lib/Socialite/index.d.ts +13 -0
  201. package/lib/Socialite/index.d.ts.map +1 -0
  202. package/lib/Socialite/index.js +25 -0
  203. package/lib/Socialite/types.d.ts +13 -0
  204. package/lib/Socialite/types.d.ts.map +1 -0
  205. package/lib/Socialite/types.js +2 -0
  206. package/lib/Type/index.d.ts +1 -0
  207. package/lib/Type/index.d.ts.map +1 -1
  208. package/lib/Validation/Validator/CustomValidation.d.ts.map +1 -1
  209. package/lib/Validation/Validator/CustomValidation.js +2 -2
  210. package/lib/Validation/Validator/helper.d.ts.map +1 -1
  211. package/lib/Validation/Validator/helper.js +8 -1
  212. package/lib/util/index.d.ts +36 -1
  213. package/lib/util/index.d.ts.map +1 -1
  214. package/lib/util/index.js +123 -26
  215. package/package.json +1 -1
@@ -339,18 +339,33 @@ class Blueprint {
339
339
  return this;
340
340
  }
341
341
  /**
342
- * Adds an index to the column.
343
- */
344
- index(indexName) {
345
- if (typeof indexName === "string") {
346
- BaseSchemaEntity_1.BaseSchemaEntity.columns.push(`INDEX ${indexName} (${indexName})`);
347
- }
348
- else if (Array.isArray(indexName)) {
349
- BaseSchemaEntity_1.BaseSchemaEntity.columns.push(`INDEX ${this.tableName}_${indexName.join("_")} (${indexName.join(",")})`);
350
- }
351
- else {
352
- BaseSchemaEntity_1.BaseSchemaEntity.AddQueryToLastIndex(`INDEX`);
342
+ * Adds an index (Laravel-style):
343
+ * - index("email")
344
+ * - index(["email", "status"])
345
+ * - index("email", "idx_users_email")
346
+ */
347
+ index(columns, indexName) {
348
+ if (columns === undefined) {
349
+ // Chain style: table.integer("last_activity").index()
350
+ // Must be a table-level INDEX clause, not "INT NOT NULL INDEX" (invalid in MySQL).
351
+ if (BaseSchemaEntity_1.BaseSchemaEntity.columns.length === 0) {
352
+ throw new Error("index() chain requires a preceding column definition");
353
+ }
354
+ const lastCol = BaseSchemaEntity_1.BaseSchemaEntity.columns[BaseSchemaEntity_1.BaseSchemaEntity.columns.length - 1];
355
+ const colMatch = lastCol.match(/^(`?\w+`?)\s/);
356
+ const colName = colMatch ? colMatch[1].replace(/`/g, "") : "";
357
+ if (!colName) {
358
+ throw new Error("Could not parse column name for index()");
359
+ }
360
+ const table = this.tableName || "table";
361
+ const name = indexName || `idx_${table}_${colName}`;
362
+ BaseSchemaEntity_1.BaseSchemaEntity.columns.push(`INDEX ${name} (${colName})`);
363
+ return this;
353
364
  }
365
+ const columnList = Array.isArray(columns) ? columns : [columns];
366
+ const table = this.tableName || "table";
367
+ const name = indexName || `idx_${table}_${columnList.join("_")}`;
368
+ BaseSchemaEntity_1.BaseSchemaEntity.columns.push(`INDEX ${name} (${columnList.join(", ")})`);
354
369
  return this;
355
370
  }
356
371
  //start
@@ -372,7 +387,7 @@ class Blueprint {
372
387
  * Adds a SMALLINT column to the schema.
373
388
  */
374
389
  smallInteger(column) {
375
- BaseSchemaEntity_1.BaseSchemaEntity.columns.push(`${column}SMALLINT NOT NULL`);
390
+ BaseSchemaEntity_1.BaseSchemaEntity.columns.push(`${column} SMALLINT NOT NULL`);
376
391
  return this;
377
392
  }
378
393
  /**
@@ -584,8 +599,22 @@ class Blueprint {
584
599
  }
585
600
  /**
586
601
  * Makes the column unsigned.
602
+ * MySQL requires TYPE UNSIGNED NOT NULL — not TYPE NOT NULL UNSIGNED (append was invalid).
587
603
  */
588
604
  unsigned() {
605
+ if (BaseSchemaEntity_1.BaseSchemaEntity.columns.length === 0) {
606
+ throw new Error("No columns available to modify");
607
+ }
608
+ const lastIndex = BaseSchemaEntity_1.BaseSchemaEntity.columns.length - 1;
609
+ const col = BaseSchemaEntity_1.BaseSchemaEntity.columns[lastIndex];
610
+ if (/\bUNSIGNED\b/i.test(col)) {
611
+ return this;
612
+ }
613
+ const replaced = col.replace(/\b(INT|BIGINT|SMALLINT|MEDIUMINT|TINYINT)(\(\d+\))? NOT NULL\b/i, "$1$2 UNSIGNED NOT NULL");
614
+ if (replaced !== col) {
615
+ BaseSchemaEntity_1.BaseSchemaEntity.columns[lastIndex] = replaced;
616
+ return this;
617
+ }
589
618
  BaseSchemaEntity_1.BaseSchemaEntity.AddQueryToLastIndex("UNSIGNED");
590
619
  return this;
591
620
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Sqlite.d.ts","sourceRoot":"","sources":["../../../../../../jcc-express-mvc/lib/Jcc-eloquent/lib/Schema/Translator/Sqlite.ts"],"names":[],"mappings":"AAKA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,eAAe,CAoI5B;IAEF,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAuDzC;;;;OAIG;WACW,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IA6BjD;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAOnC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAsCnC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,0BAA0B;CAc1C"}
1
+ {"version":3,"file":"Sqlite.d.ts","sourceRoot":"","sources":["../../../../../../jcc-express-mvc/lib/Jcc-eloquent/lib/Schema/Translator/Sqlite.ts"],"names":[],"mappings":"AAKA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,eAAe,CAoI5B;IAEF,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAuDzC;;;;OAIG;WACW,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAkCjD;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAOnC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAsCnC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,0BAA0B;CA4C1C"}
@@ -81,7 +81,11 @@ class SQLiteTranslator {
81
81
  .replace(/,\s*\)/g, ")") // remove trailing commas in parentheses
82
82
  .replace(/\s+ON\s*,/g, ",") // clean up malformed ON clauses
83
83
  .replace(/\s+ON\s*\)/g, ")"); // clean up malformed ON clauses at end of parentheses
84
- return this.SQLiteFKFixer(sqliteSql);
84
+ // FK reordering is only relevant for CREATE TABLE statements.
85
+ if (/^\s*CREATE\s+TABLE\b/i.test(sqliteSql)) {
86
+ return this.SQLiteFKFixer(sqliteSql);
87
+ }
88
+ return sqliteSql;
85
89
  }
86
90
  /**
87
91
  * Converts MySQL CONCAT() function to SQLite concatenation operator ||
@@ -141,6 +145,20 @@ class SQLiteTranslator {
141
145
  "3. DROP old table\n" +
142
146
  "4. RENAME new table */\n" +
143
147
  "-- ALTER TABLE $1 attempted to modify column $2 to $3");
148
+ sql = sql.replace(/ALTER\s+TABLE\s+(\w+)\s+CHANGE\s+COLUMN\s+(\w+)\s+(\w+)\s+([^;]+)/gi, "/* SQLite doesn't support CHANGE COLUMN directly. Use: \n" +
149
+ "1. CREATE new table with desired schema\n" +
150
+ "2. INSERT data from old table\n" +
151
+ "3. DROP old table\n" +
152
+ "4. RENAME new table */\n" +
153
+ "-- ALTER TABLE $1 attempted to change column $2 to $3 $4");
154
+ sql = sql.replace(/ALTER\s+TABLE\s+(\w+)\s+DROP\s+COLUMN\s+(\w+)\s*;?/gi, "/* SQLite supports DROP COLUMN only in newer versions and with constraints caveats. " +
155
+ "Safer cross-version approach is table rebuild. */\n" +
156
+ "-- ALTER TABLE $1 attempted to drop column $2");
157
+ sql = sql.replace(/ALTER\s+TABLE\s+(\w+)\s+DROP\s+INDEX\s+(\w+)\s*;?/gi, "/* SQLite drops indexes with standalone DROP INDEX, not ALTER TABLE DROP INDEX. */\n" +
158
+ "DROP INDEX IF EXISTS $2;");
159
+ sql = sql.replace(/ALTER\s+TABLE\s+(\w+)\s+DROP\s+FOREIGN\s+KEY\s+(\w+)\s*;?/gi, "/* SQLite doesn't support dropping a foreign key constraint directly. " +
160
+ "Rebuild table without the constraint. */\n" +
161
+ "-- ALTER TABLE $1 attempted to drop foreign key $2");
144
162
  return sql;
145
163
  }
146
164
  }
@@ -188,9 +206,9 @@ SQLiteTranslator.conversionRules = [
188
206
  // Character set and collation
189
207
  { pattern: /CHARACTER\s+SET\s+\w+/gi, replacement: "" },
190
208
  { pattern: /COLLATE\s+\w+/gi, replacement: "" },
191
- // Key declarations
209
+ // Key declarations (single or multi-column)
192
210
  {
193
- pattern: /\bKEY\s+`?(\w+)`?\s+\(`?(\w+)`?\)/gi,
211
+ pattern: /\bKEY\s+`?([a-zA-Z0-9_]+)`?\s+\(([^)]+)\)/gi,
194
212
  replacement: "INDEX $1($2)",
195
213
  },
196
214
  // UNSIGNED attribute (not supported in SQLite)
@@ -5,6 +5,7 @@ export declare class PostgresTranslator {
5
5
  * @returns The PostgreSQL-compatible query string.
6
6
  */
7
7
  private static replaceQuestionMarks;
8
+ private static normalizeCommon;
8
9
  private static translateCreateTable;
9
10
  /**
10
11
  * Translates MySQL ALTER TABLE statements to PostgreSQL.
@@ -1 +1 @@
1
- {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../../../../jcc-express-mvc/lib/Jcc-eloquent/lib/Schema/Translator/postgres.ts"],"names":[],"mappings":"AAAA,qBAAa,kBAAkB;IAC7B;;;;OAIG;IAEH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAKnC,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAwDnC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAMlC;;;;OAIG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAaxC"}
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../../../../jcc-express-mvc/lib/Jcc-eloquent/lib/Schema/Translator/postgres.ts"],"names":[],"mappings":"AAAA,qBAAa,kBAAkB;IAC7B;;;;OAIG;IAEH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAKnC,OAAO,CAAC,MAAM,CAAC,eAAe;IA6D9B,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAcnC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAyElC;;;;OAIG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAaxC"}
@@ -11,17 +11,18 @@ class PostgresTranslator {
11
11
  let counter = 1;
12
12
  return query.replace(/\?/g, () => `$${counter++}`);
13
13
  }
14
- static translateCreateTable(query) {
15
- // Replace MySQL types with PostgreSQL equivalents
14
+ static normalizeCommon(query) {
15
+ // Remove MySQL identifier quoting.
16
+ query = query.replace(/`([^`]+)`/g, "$1");
16
17
  // Handle AUTO_INCREMENT columns first (order matters)
17
18
  query = query.replace(/\bBIGINT\s+UNSIGNED\s+AUTO_INCREMENT\b/gi, "BIGSERIAL");
18
19
  query = query.replace(/\bINT\s+UNSIGNED\s+AUTO_INCREMENT\b/gi, "SERIAL");
19
20
  query = query.replace(/\bBIGINT\s+AUTO_INCREMENT\b/gi, "BIGSERIAL");
20
21
  query = query.replace(/\bINT\s+AUTO_INCREMENT\b/gi, "SERIAL");
21
22
  query = query.replace(/\b(MEDIUMINT|SMALLINT)\s+AUTO_INCREMENT\b/gi, "SERIAL");
22
- // Remove UNSIGNED keyword (PostgreSQL doesn't have unsigned types)
23
+ // Remove UNSIGNED keyword (PostgreSQL doesn't support unsigned types)
23
24
  query = query.replace(/\s+UNSIGNED\b/gi, "");
24
- // Replace remaining AUTO_INCREMENT (shouldn't happen after above, but just in case)
25
+ // Replace remaining AUTO_INCREMENT (safety fallback)
25
26
  query = query.replace(/\s+AUTO_INCREMENT\b/gi, "");
26
27
  // Data type mappings
27
28
  query = query.replace(/\bTINYINT\b/gi, "SMALLINT");
@@ -30,20 +31,29 @@ class PostgresTranslator {
30
31
  query = query.replace(/\bBIGINT\b/gi, "BIGINT");
31
32
  query = query.replace(/\bFLOAT\b/gi, "REAL");
32
33
  query = query.replace(/\bDOUBLE\b/gi, "DOUBLE PRECISION");
33
- // BLOB and binary types
34
- query = query.replace(/\b(TINYBLOB|BLOB|MEDIUMBLOB|LONGBLOB|BINARY|VARBINARY)\b/gi, "BYTEA");
35
- // Date/time types
36
34
  query = query.replace(/\bDATETIME\b/gi, "TIMESTAMP");
37
- // Text types
38
35
  query = query.replace(/\b(TINYTEXT|MEDIUMTEXT|LONGTEXT)\b/gi, "TEXT");
36
+ query = query.replace(/\b(TINYBLOB|BLOB|MEDIUMBLOB|LONGBLOB|BINARY|VARBINARY)\b/gi, "BYTEA");
39
37
  // Remove MySQL-specific clauses
40
38
  query = query.replace(/\s+ON\s+UPDATE\s+CURRENT_TIMESTAMP\b/gi, "");
41
- // Handle ENGINE, CHARSET, etc. (remove MySQL-specific table options)
39
+ // MySQL unique-key syntax inside CREATE TABLE.
40
+ query = query.replace(/\bUNIQUE\s+KEY\s+([a-zA-Z0-9_]+)\s*\(([^)]+)\)/gi, "CONSTRAINT $1 UNIQUE ($2)");
41
+ // PostgreSQL BOOLEAN defaults must be TRUE/FALSE (not 1/0).
42
+ query = query.replace(/\bBOOLEAN\b([^,;]*?)\bDEFAULT\s+([01])\b/gi, (_match, between, bit) => `BOOLEAN${between}DEFAULT ${bit === "1" ? "TRUE" : "FALSE"}`);
43
+ // Table options not supported in PostgreSQL
42
44
  query = query.replace(/\s+ENGINE\s*=\s*\w+/gi, "");
43
45
  query = query.replace(/\s+DEFAULT\s+CHARSET\s*=\s*\w+/gi, "");
44
46
  query = query.replace(/\s+COLLATE\s*=\s*\w+/gi, "");
47
+ return query;
48
+ }
49
+ static translateCreateTable(query) {
50
+ query = this.normalizeCommon(query);
51
+ // MySQL inline non-unique index definitions are not valid in PostgreSQL CREATE TABLE.
52
+ // Remove these clauses to keep CREATE TABLE executable.
53
+ query = query.replace(/\s*,\s*(?:INDEX|KEY)\s+[a-zA-Z0-9_]+\s*\([^)]+\)/gi, "");
45
54
  // Clean up extra whitespace
46
55
  query = query.replace(/\s+/g, " ").trim();
56
+ query = query.replace(/,\s*\)/g, ")");
47
57
  return query;
48
58
  }
49
59
  /**
@@ -52,9 +62,55 @@ class PostgresTranslator {
52
62
  * @returns The PostgreSQL-compatible query string.
53
63
  */
54
64
  static translateAlterTable(query) {
55
- // Handle ALTER TABLE specific translations
56
- // This is a placeholder - you'd need to implement specific ALTER TABLE logic
57
- return this.translateCreateTable(query);
65
+ query = this.normalizeCommon(query);
66
+ // DROP FOREIGN KEY name -> DROP CONSTRAINT name
67
+ query = query.replace(/\bDROP\s+FOREIGN\s+KEY\s+([a-zA-Z0-9_]+)/gi, "DROP CONSTRAINT $1");
68
+ // DROP INDEX name -> DROP CONSTRAINT name (for unique/index-like constraints emitted by schema builder)
69
+ query = query.replace(/\bDROP\s+INDEX\s+([a-zA-Z0-9_]+)/gi, "DROP CONSTRAINT $1");
70
+ // CHANGE COLUMN old new TYPE ... -> RENAME + TYPE (+ null/default when present)
71
+ query = query.replace(/\bCHANGE\s+COLUMN\s+([a-zA-Z0-9_]+)\s+([a-zA-Z0-9_]+)\s+([A-Z]+(?:\([^)]+\))?)([^,;]*)/gi, (_match, oldCol, newCol, type, tail) => {
72
+ const ops = [
73
+ `RENAME COLUMN ${oldCol} TO ${newCol}`,
74
+ `ALTER COLUMN ${newCol} TYPE ${type}`,
75
+ ];
76
+ const t = String(tail || "");
77
+ if (/\bNOT\s+NULL\b/i.test(t)) {
78
+ ops.push(`ALTER COLUMN ${newCol} SET NOT NULL`);
79
+ }
80
+ else if (/\bNULL\b/i.test(t)) {
81
+ ops.push(`ALTER COLUMN ${newCol} DROP NOT NULL`);
82
+ }
83
+ const defaultMatch = t.match(/\bDEFAULT\s+([^\s,;]+)/i);
84
+ if (defaultMatch?.[1]) {
85
+ ops.push(`ALTER COLUMN ${newCol} SET DEFAULT ${defaultMatch[1]}`);
86
+ }
87
+ return ops.join(", ");
88
+ });
89
+ // MODIFY COLUMN col TYPE ... -> ALTER COLUMN statements (+ null/default when present)
90
+ query = query.replace(/\bMODIFY\s+COLUMN\s+([a-zA-Z0-9_]+)\s+([A-Z]+(?:\([^)]+\))?)([^,;]*)/gi, (_match, col, type, tail) => {
91
+ const ops = [`ALTER COLUMN ${col} TYPE ${type}`];
92
+ const t = String(tail || "");
93
+ if (/\bNOT\s+NULL\b/i.test(t)) {
94
+ ops.push(`ALTER COLUMN ${col} SET NOT NULL`);
95
+ }
96
+ else if (/\bNULL\b/i.test(t)) {
97
+ ops.push(`ALTER COLUMN ${col} DROP NOT NULL`);
98
+ }
99
+ const defaultMatch = t.match(/\bDEFAULT\s+([^\s,;]+)/i);
100
+ if (defaultMatch?.[1]) {
101
+ ops.push(`ALTER COLUMN ${col} SET DEFAULT ${defaultMatch[1]}`);
102
+ }
103
+ return ops.join(", ");
104
+ });
105
+ // AFTER/FIRST are MySQL-only column positioning hints.
106
+ query = query.replace(/\s+AFTER\s+[a-zA-Z0-9_]+/gi, "");
107
+ query = query.replace(/\s+FIRST\b/gi, "");
108
+ // Boolean defaults in ALTER statements as well.
109
+ query = query.replace(/\bALTER\s+COLUMN\s+([a-zA-Z0-9_]+)\s+SET\s+DEFAULT\s+([01])\b/gi, (_match, col, bit) => `ALTER COLUMN ${col} SET DEFAULT ${bit === "1" ? "TRUE" : "FALSE"}`);
110
+ // Clean up extra whitespace
111
+ query = query.replace(/\s+/g, " ").trim();
112
+ query = query.replace(/,\s*;/g, ";");
113
+ return query;
58
114
  }
59
115
  /**
60
116
  * Main translation method that handles both CREATE TABLE and ALTER TABLE statements.
@@ -70,8 +126,8 @@ class PostgresTranslator {
70
126
  else if (trimmedQuery.toUpperCase().startsWith("ALTER TABLE")) {
71
127
  return this.translateAlterTable(this.replaceQuestionMarks(trimmedQuery));
72
128
  }
73
- // For other query types, just replace question marks
74
- return this.replaceQuestionMarks(trimmedQuery);
129
+ // For other query types, replace placeholders and normalize identifier quoting.
130
+ return this.replaceQuestionMarks(trimmedQuery).replace(/`([^`]+)`/g, "$1");
75
131
  }
76
132
  }
77
133
  exports.PostgresTranslator = PostgresTranslator;
@@ -1,5 +1,17 @@
1
1
  import { Blueprint } from "./BluePrint";
2
2
  export declare class Schema {
3
+ /**
4
+ * SQL emitted by Schema.create/table/drop/… in order, so migrations can omit
5
+ * `return` and still run; multiple calls in one `up()`/`down()` are all kept.
6
+ */
7
+ private static generatedSqlBatch;
8
+ /** Clear before running a migration `up`/`down` to avoid stale SQL. */
9
+ static clearLastGeneratedSql(): void;
10
+ private static captureGeneratedSql;
11
+ /**
12
+ * All statements captured since {@link clearLastGeneratedSql}, then clears the batch.
13
+ */
14
+ static consumeAllGeneratedSql(): string[];
3
15
  /**
4
16
  * Creates a new table using a blueprint.
5
17
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../jcc-express-mvc/lib/Jcc-eloquent/lib/Schema/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAMxC,qBAAa,MAAM;IACjB;;OAEG;IACH,MAAM,CAAC,MAAM,CACX,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,GACvC,MAAM;IAiBT;;OAEG;IACH,MAAM,CAAC,KAAK,CACV,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,GACvC,MAAM;IAiBT;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAgB3C,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI9C;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAgB1C;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAgBtC;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM;IAe/C;;OAEG;WACU,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA0C1D;;OAEG;WACU,SAAS,CACpB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC;IAmDnB;;OAEG;WACU,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAmDpE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../jcc-express-mvc/lib/Jcc-eloquent/lib/Schema/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAMxC,qBAAa,MAAM;IACjB;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAgB;IAEhD,uEAAuE;IACvE,MAAM,CAAC,qBAAqB,IAAI,IAAI;IAIpC,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAKlC;;OAEG;IACH,MAAM,CAAC,sBAAsB,IAAI,MAAM,EAAE;IAMzC;;OAEG;IACH,MAAM,CAAC,MAAM,CACX,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,GACvC,MAAM;IAiBT;;OAEG;IACH,MAAM,CAAC,KAAK,CACV,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,GACvC,MAAM;IAiBT;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAkB3C,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI9C;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAgB1C;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAgBtC;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM;IAe/C;;OAEG;WACU,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA0C1D;;OAEG;WACU,SAAS,CACpB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC;IAmDnB;;OAEG;WACU,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAmDpE"}
@@ -8,6 +8,22 @@ const DB_1 = require("../DB");
8
8
  const Config_1 = require("../../../Config/Config");
9
9
  // dotenv.config({ path: `${appRootPath.path}/.env` });
10
10
  class Schema {
11
+ /** Clear before running a migration `up`/`down` to avoid stale SQL. */
12
+ static clearLastGeneratedSql() {
13
+ this.generatedSqlBatch = [];
14
+ }
15
+ static captureGeneratedSql(sql) {
16
+ this.generatedSqlBatch.push(sql);
17
+ return sql;
18
+ }
19
+ /**
20
+ * All statements captured since {@link clearLastGeneratedSql}, then clears the batch.
21
+ */
22
+ static consumeAllGeneratedSql() {
23
+ const out = [...this.generatedSqlBatch];
24
+ this.generatedSqlBatch = [];
25
+ return out;
26
+ }
11
27
  /**
12
28
  * Creates a new table using a blueprint.
13
29
  */
@@ -18,7 +34,7 @@ class Schema {
18
34
  }
19
35
  const blueprint = new BluePrint_1.Blueprint(tableName);
20
36
  callback(blueprint);
21
- return blueprint.toSQL("CREATE", tableName);
37
+ return this.captureGeneratedSql(blueprint.toSQL("CREATE", tableName));
22
38
  }
23
39
  catch (error) {
24
40
  throw new DatabaseError_1.DatabaseError(`Failed to create table '${tableName}': ${error.message}`, constant_1.SCHEMA_CREATE_ERROR);
@@ -34,7 +50,7 @@ class Schema {
34
50
  }
35
51
  const blueprint = new BluePrint_1.Blueprint(tableName);
36
52
  callback(blueprint);
37
- return blueprint.toSQL("ALTER", tableName);
53
+ return this.captureGeneratedSql(blueprint.toSQL("ALTER", tableName));
38
54
  }
39
55
  catch (error) {
40
56
  throw new DatabaseError_1.DatabaseError(`Failed to alter table '${tableName}': ${error.message}`, constant_1.SCHEMA_CREATE_ERROR);
@@ -49,7 +65,7 @@ class Schema {
49
65
  throw new Error("Table name cannot be empty");
50
66
  }
51
67
  const blueprint = new BluePrint_1.Blueprint(tableName);
52
- return blueprint.toSQL("DROP TABLE IF EXISTS", tableName);
68
+ return this.captureGeneratedSql(blueprint.toSQL("DROP TABLE IF EXISTS", tableName));
53
69
  }
54
70
  catch (error) {
55
71
  throw new DatabaseError_1.DatabaseError(`Failed to drop table '${tableName}': ${error.message}`, constant_1.SCHEMA_CREATE_ERROR);
@@ -67,7 +83,7 @@ class Schema {
67
83
  throw new Error("Table name cannot be empty");
68
84
  }
69
85
  const blueprint = new BluePrint_1.Blueprint(tableName);
70
- return blueprint.toSQL("TRUNCATE TABLE", tableName);
86
+ return this.captureGeneratedSql(blueprint.toSQL("TRUNCATE TABLE", tableName));
71
87
  }
72
88
  catch (error) {
73
89
  throw new DatabaseError_1.DatabaseError(`Failed to truncate table '${tableName}': ${error.message}`, constant_1.SCHEMA_CREATE_ERROR);
@@ -82,7 +98,7 @@ class Schema {
82
98
  throw new Error("Table name cannot be empty");
83
99
  }
84
100
  const blueprint = new BluePrint_1.Blueprint(tableName);
85
- return blueprint.toSQL("DROP TABLE", tableName);
101
+ return this.captureGeneratedSql(blueprint.toSQL("DROP TABLE", tableName));
86
102
  }
87
103
  catch (error) {
88
104
  throw new DatabaseError_1.DatabaseError(`Failed to drop table '${tableName}': ${error.message}`, constant_1.SCHEMA_CREATE_ERROR);
@@ -96,7 +112,7 @@ class Schema {
96
112
  if (!from || from.trim() === "" || !to || to.trim() === "") {
97
113
  throw new Error("Table names cannot be empty");
98
114
  }
99
- return `RENAME TABLE ${from} TO ${to};`;
115
+ return this.captureGeneratedSql(`RENAME TABLE ${from} TO ${to};`);
100
116
  }
101
117
  catch (error) {
102
118
  throw new DatabaseError_1.DatabaseError(`Failed to rename table from '${from}' to '${to}': ${error.message}`, constant_1.SCHEMA_CREATE_ERROR);
@@ -235,3 +251,8 @@ class Schema {
235
251
  }
236
252
  }
237
253
  exports.Schema = Schema;
254
+ /**
255
+ * SQL emitted by Schema.create/table/drop/… in order, so migrations can omit
256
+ * `return` and still run; multiple calls in one `up()`/`down()` are all kept.
257
+ */
258
+ Schema.generatedSqlBatch = [];
@@ -1,3 +1,4 @@
1
+ import type { Request } from "express";
1
2
  import { Model } from "../Model";
2
3
  export declare class Utils {
3
4
  /**
@@ -52,6 +53,15 @@ export declare class Utils {
52
53
  * - `active`: A boolean indicating if the link corresponds to the current page.
53
54
  */
54
55
  static generatePaginationLinks(path: string, currentPage: number, lastPage: number): Record<string, any>[];
56
+ /**
57
+ * Merge `request.query` with overrides into a full URL (pathname + search).
58
+ * Pass `null` / `undefined` in overrides to remove a query key.
59
+ */
60
+ static mergeRequestQuery(request: Request, overrides: Record<string, string | number | boolean | null | undefined>): string;
61
+ /** Encode a cursor column value for `?cursor=` (base64url JSON). */
62
+ static encodeCursorValue(value: unknown): string;
63
+ /** Decode `?cursor=` from {@link encodeCursorValue} or fall back to raw string / number. */
64
+ static decodeCursorValue(encoded: string): unknown;
55
65
  /**
56
66
  * Extracts and returns metadata and configurations for a given Model.
57
67
  * @param {any} Model - The model whose metadata needs to be extracted. This should follow the ORM's Model structure.
@@ -84,5 +94,8 @@ export declare class Utils {
84
94
  static getModelFile(modelType: string): Promise<typeof Model>;
85
95
  static formatDate(): string;
86
96
  static isClass(value: any): boolean;
97
+ static isPostgres(): boolean;
98
+ static isMysql(): boolean;
99
+ static isSqlite(): boolean;
87
100
  }
88
101
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../jcc-express-mvc/lib/Jcc-eloquent/lib/utils/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,qBAAa,KAAK;IAChB;;;;;OAKG;IACH,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAKrC;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIvC;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAQpC;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM;IAYrD,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG;IAkBjC;;;;;;OAMG;IACH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO;IAMzE;;;;;OAKG;IACH,MAAM,CAAC,oBAAoB,CACzB,cAAc,EAAE,MAAM,GAAG,MAAM,GAC9B,MAAM,GAAG,MAAM;IAUlB;;;;;;OAMG;IACH,MAAM,CAAC,uBAAuB,CAC5B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM;IAalB;;;;;OAKG;IACH,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE;;;;;;;IAenE;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAQxC;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM;IAmBhD;;;;OAIG;WACU,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,KAAK,CAAC;IAwDnE,MAAM,CAAC,UAAU;IAYjB,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO;CAMpC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../jcc-express-mvc/lib/Jcc-eloquent/lib/utils/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGvC,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAGjC,qBAAa,KAAK;IAChB;;;;;OAKG;IACH,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAKrC;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIvC;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAQpC;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM;IAYrD,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG;IAkBjC;;;;;;OAMG;IACH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO;IAMzE;;;;;OAKG;IACH,MAAM,CAAC,oBAAoB,CACzB,cAAc,EAAE,MAAM,GAAG,MAAM,GAC9B,MAAM,GAAG,MAAM;IAUlB;;;;;;OAMG;IACH,MAAM,CAAC,uBAAuB,CAC5B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM;IAalB;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CACtB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,GACtE,MAAM;IAmBT,oEAAoE;IACpE,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;IAOhD,4FAA4F;IAC5F,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAelD;;;;;OAKG;IACH,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE;;;;;;;IAenE;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAQxC;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM;IAmBhD;;;;OAIG;WACU,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,KAAK,CAAC;IAwDnE,MAAM,CAAC,UAAU;IAYjB,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO;IAOnC,MAAM,CAAC,UAAU,IAAI,OAAO;IAO5B,MAAM,CAAC,OAAO,IAAI,OAAO;IAOzB,MAAM,CAAC,QAAQ,IAAI,OAAO;CAO3B"}
@@ -41,6 +41,7 @@ const inflection = __importStar(require("inflection"));
41
41
  const DatabaseError_1 = require("../Error/DatabaseError");
42
42
  const app_root_path_1 = __importDefault(require("app-root-path"));
43
43
  const Model_1 = require("../Model");
44
+ const Config_1 = require("../../../Config/Config");
44
45
  class Utils {
45
46
  /**
46
47
  * Pluralizes a string.
@@ -153,6 +154,54 @@ class Utils {
153
154
  }
154
155
  return links;
155
156
  }
157
+ /**
158
+ * Merge `request.query` with overrides into a full URL (pathname + search).
159
+ * Pass `null` / `undefined` in overrides to remove a query key.
160
+ */
161
+ static mergeRequestQuery(request, overrides) {
162
+ const host = request.get("host") || "localhost";
163
+ const proto = (request.protocol || "http").replace(/:$/, "");
164
+ const pathname = request.path || "/";
165
+ const base = `${proto}://${host}${pathname}`;
166
+ const u = new URL(base);
167
+ const sp = u.searchParams;
168
+ for (const [k, v] of Object.entries(request.query)) {
169
+ if (v === undefined || v === null)
170
+ continue;
171
+ const val = Array.isArray(v) ? v[0] : v;
172
+ sp.set(k, String(val));
173
+ }
174
+ for (const [k, v] of Object.entries(overrides)) {
175
+ if (v === null || v === undefined)
176
+ sp.delete(k);
177
+ else
178
+ sp.set(k, String(v));
179
+ }
180
+ return u.toString();
181
+ }
182
+ /** Encode a cursor column value for `?cursor=` (base64url JSON). */
183
+ static encodeCursorValue(value) {
184
+ const v = value instanceof Date ? value.toISOString() : value;
185
+ const payload = JSON.stringify({ v });
186
+ return Buffer.from(payload, "utf8").toString("base64url");
187
+ }
188
+ /** Decode `?cursor=` from {@link encodeCursorValue} or fall back to raw string / number. */
189
+ static decodeCursorValue(encoded) {
190
+ if (encoded == null || encoded === "")
191
+ return undefined;
192
+ try {
193
+ const json = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
194
+ if (json && typeof json === "object" && "v" in json)
195
+ return json.v;
196
+ }
197
+ catch {
198
+ /* fall through */
199
+ }
200
+ const n = Number(encoded);
201
+ if (!Number.isNaN(n) && String(n) === String(encoded).trim())
202
+ return n;
203
+ return encoded;
204
+ }
156
205
  /**
157
206
  * Extracts and returns metadata and configurations for a given Model.
158
207
  * @param {any} Model - The model whose metadata needs to be extracted. This should follow the ORM's Model structure.
@@ -265,5 +314,18 @@ class Utils {
265
314
  return (typeof value === "function" &&
266
315
  /^\s*class\s+/.test(Function.prototype.toString.call(value)));
267
316
  }
317
+ static isPostgres() {
318
+ return (Config_1.config.get("DB_CONNECTION").toLowerCase() === "postgres" ||
319
+ Config_1.config.get("DB_ORM").toLowerCase() === "pg");
320
+ }
321
+ static isMysql() {
322
+ return (Config_1.config.get("DB_CONNECTION").toLowerCase() === "mysql" ||
323
+ Config_1.config.get("DB_ORM").toLowerCase() === "mysql2");
324
+ }
325
+ static isSqlite() {
326
+ return (Config_1.config.get("DB_CONNECTION").toLowerCase() === "sqlite" ||
327
+ Config_1.config.get("DB_ORM").toLowerCase() === "better-sqlite3" ||
328
+ Config_1.config.get("DB_ORM").toLowerCase() === "bun:sqlite");
329
+ }
268
330
  }
269
331
  exports.Utils = Utils;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Middleware/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAyB,EAEvB,cAAc,EACf,MAAM,SAAS,CAAC;AAcjB,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,GAAG,CAAc;gBAEb,GAAG,EAAE,WAAW;IAW5B,eAAe;IAWf,GAAG,CAAC,gBAAgB,EAAE,cAAc,EAAE;IAmCtC,OAAO,CAAC,yBAAyB;IAQjC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,UAAU;CAGnB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Middleware/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAyB,EAEvB,cAAc,EACf,MAAM,SAAS,CAAC;AAejB,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,GAAG,CAAc;gBAEb,GAAG,EAAE,WAAW;IAW5B,eAAe;IAWf,GAAG,CAAC,gBAAgB,EAAE,cAAc,EAAE;IA8BtC,OAAO,CAAC,yBAAyB;IASjC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,UAAU;CAGnB"}
@@ -11,10 +11,11 @@ const request_1 = require("../Request/request");
11
11
  const morgan_1 = __importDefault(require("morgan"));
12
12
  const Config_1 = require("../Config/Config");
13
13
  const express_rate_limit_1 = __importDefault(require("express-rate-limit"));
14
- const express_session_1 = __importDefault(require("express-session"));
15
14
  const cookie_parser_1 = __importDefault(require("cookie-parser"));
16
15
  const connect_flash_1 = __importDefault(require("connect-flash"));
17
16
  const express_fileupload_1 = __importDefault(require("express-fileupload"));
17
+ const ExpressJccSession_1 = require("../Session/ExpressJccSession");
18
+ const SessionManager_1 = require("../Session/SessionManager");
18
19
  class Middleware {
19
20
  //
20
21
  constructor(app) {
@@ -40,12 +41,7 @@ class Middleware {
40
41
  this.express.json(),
41
42
  this.express.urlencoded({ extended: false }),
42
43
  (0, cookie_parser_1.default)(),
43
- (0, express_session_1.default)({
44
- secret: process.env.SESSION_SECRET || "your_secret",
45
- resave: false,
46
- saveUninitialized: false,
47
- cookie: { secure: false },
48
- }),
44
+ this.app.resolve(SessionManager_1.SessionManager.name).getExpressMiddleware(),
49
45
  (0, connect_flash_1.default)(),
50
46
  (0, express_fileupload_1.default)(),
51
47
  (0, cors_1.default)(this.corsOption()),
@@ -68,6 +64,7 @@ class Middleware {
68
64
  }
69
65
  requestResponseMiddleware() {
70
66
  return (req, res, next) => {
67
+ req.jccSession = (0, ExpressJccSession_1.createExpressJccSession)(req);
71
68
  new Response_1.HttpResponse(req, res);
72
69
  new request_1.HttpRequest(req, res);
73
70
  next();
@@ -0,0 +1,3 @@
1
+ export declare class SequelizeModel {
2
+ }
3
+ //# sourceMappingURL=Sequelize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sequelize.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Model/Sequelize.ts"],"names":[],"mappings":"AAAA,qBAAa,cAAc;CAAG"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SequelizeModel = void 0;
4
+ class SequelizeModel {
5
+ }
6
+ exports.SequelizeModel = SequelizeModel;
@@ -0,0 +1,12 @@
1
+ import type { Application } from "../Application/Application";
2
+ import { ServiceProvider } from "./ServiceProvider";
3
+ /**
4
+ * Registers {@link SessionManager} from `app.config.session` (Laravel-style: driver, lifetime, stores).
5
+ * Used by {@link Middleware} to mount `express-session` with the correct store.
6
+ */
7
+ export declare class SessionServiceProvider extends ServiceProvider {
8
+ constructor(app: Application);
9
+ register(): void;
10
+ private mergeSessionConfig;
11
+ }
12
+ //# sourceMappingURL=SessionServiceProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionServiceProvider.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Providers/SessionServiceProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIpD;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,eAAe;gBAC7C,GAAG,EAAE,WAAW;IAI5B,QAAQ,IAAI,IAAI;IAMhB,OAAO,CAAC,kBAAkB;CA+B3B"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SessionServiceProvider = void 0;
4
+ const ServiceProvider_1 = require("./ServiceProvider");
5
+ const SessionManager_1 = require("../Session/SessionManager");
6
+ /**
7
+ * Registers {@link SessionManager} from `app.config.session` (Laravel-style: driver, lifetime, stores).
8
+ * Used by {@link Middleware} to mount `express-session` with the correct store.
9
+ */
10
+ class SessionServiceProvider extends ServiceProvider_1.ServiceProvider {
11
+ constructor(app) {
12
+ super(app);
13
+ }
14
+ register() {
15
+ this.app.singleton(SessionManager_1.SessionManager.name, () => {
16
+ return new SessionManager_1.SessionManager(this.mergeSessionConfig());
17
+ });
18
+ }
19
+ mergeSessionConfig() {
20
+ const raw = (this.app.config?.session ?? {});
21
+ const defaultLifetime = 120 * 60 * 1000;
22
+ const lifetimeMs = typeof raw.lifetime === "number" && raw.lifetime > 0
23
+ ? raw.lifetime
24
+ : defaultLifetime;
25
+ const cookieBase = raw.cookie ?? {
26
+ name: "connect.sid",
27
+ httpOnly: true,
28
+ secure: false,
29
+ sameSite: "lax",
30
+ maxAge: lifetimeMs,
31
+ };
32
+ const cookie = {
33
+ ...cookieBase,
34
+ maxAge: cookieBase.maxAge ?? lifetimeMs,
35
+ path: cookieBase.path ?? "/",
36
+ };
37
+ return {
38
+ driver: raw.driver ?? "file",
39
+ lifetime: lifetimeMs,
40
+ cookie,
41
+ files: raw.files,
42
+ database: raw.database,
43
+ redis: raw.redis,
44
+ };
45
+ }
46
+ }
47
+ exports.SessionServiceProvider = SessionServiceProvider;