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.
- package/__tests__/MySqlSchemaBlueprint.test.d.ts +2 -0
- package/__tests__/MySqlSchemaBlueprint.test.d.ts.map +1 -0
- package/__tests__/MySqlSchemaBlueprint.test.js +55 -0
- package/__tests__/PostgresTranslator.test.d.ts +2 -0
- package/__tests__/PostgresTranslator.test.d.ts.map +1 -0
- package/__tests__/PostgresTranslator.test.js +82 -0
- package/__tests__/SQLiteTranslator.test.d.ts +2 -0
- package/__tests__/SQLiteTranslator.test.d.ts.map +1 -0
- package/__tests__/SQLiteTranslator.test.js +125 -0
- package/__tests__/SchemaAlterBlueprint.test.d.ts +2 -0
- package/__tests__/SchemaAlterBlueprint.test.d.ts.map +1 -0
- package/__tests__/SchemaAlterBlueprint.test.js +35 -0
- package/global.d.ts +3 -1
- package/index.d.ts +28 -3
- package/index.d.ts.map +1 -1
- package/index.js +33 -75
- package/lib/Application/Application.d.ts +1 -1
- package/lib/Application/Application.d.ts.map +1 -1
- package/lib/Application/Application.js +2 -2
- package/lib/Application/ApplicationBuilder.d.ts.map +1 -1
- package/lib/Application/ApplicationBuilder.js +9 -2
- package/lib/Auth/AuthMiddleware.d.ts.map +1 -1
- package/lib/Auth/AuthMiddleware.js +29 -12
- package/lib/Auth/index.d.ts +17 -3
- package/lib/Auth/index.d.ts.map +1 -1
- package/lib/Auth/index.js +128 -26
- package/lib/Auth/loginRateLimit.d.ts +6 -0
- package/lib/Auth/loginRateLimit.d.ts.map +1 -0
- package/lib/Auth/loginRateLimit.js +25 -0
- package/lib/Auth/refreshTokenStore.d.ts +24 -0
- package/lib/Auth/refreshTokenStore.d.ts.map +1 -0
- package/lib/Auth/refreshTokenStore.js +46 -0
- package/lib/Command-Line/DBCommand.d.ts.map +1 -1
- package/lib/Command-Line/DBCommand.js +9 -3
- package/lib/Command-Line/KeyGenerateCommand.d.ts +6 -0
- package/lib/Command-Line/KeyGenerateCommand.d.ts.map +1 -0
- package/lib/Command-Line/KeyGenerateCommand.js +47 -0
- package/lib/Command-Line/NodeArtisanCommand.d.ts +2 -0
- package/lib/Command-Line/NodeArtisanCommand.d.ts.map +1 -1
- package/lib/Command-Line/NodeArtisanCommand.js +20 -3
- package/lib/Command-Line/NodeTinker/Tinker.d.ts +5 -2
- package/lib/Command-Line/NodeTinker/Tinker.d.ts.map +1 -1
- package/lib/Command-Line/NodeTinker/Tinker.js +13 -3
- package/lib/Command-Line/WatchCommand.d.ts +29 -0
- package/lib/Command-Line/WatchCommand.d.ts.map +1 -0
- package/lib/Command-Line/WatchCommand.js +234 -0
- package/lib/Command-Line/files/Models.d.ts.map +1 -1
- package/lib/Command-Line/files/Models.js +41 -16
- package/lib/Console/Command.d.ts +18 -0
- package/lib/Console/Command.d.ts.map +1 -1
- package/lib/Console/Command.js +29 -0
- package/lib/Container/index.d.ts.map +1 -1
- package/lib/Container/index.js +21 -7
- package/lib/Database/Database.d.ts +2 -1
- package/lib/Database/Database.d.ts.map +1 -1
- package/lib/Database/Database.js +6 -5
- package/lib/Database/DatabaseServiceProvider.d.ts +0 -4
- package/lib/Database/DatabaseServiceProvider.d.ts.map +1 -1
- package/lib/Database/DatabaseServiceProvider.js +9 -56
- package/lib/Database/Drivers/MongooseDriver.d.ts +2 -0
- package/lib/Database/Drivers/MongooseDriver.d.ts.map +1 -1
- package/lib/Database/Drivers/MongooseDriver.js +11 -13
- package/lib/Database/Drivers/SequelizeDriver.d.ts +9 -1
- package/lib/Database/Drivers/SequelizeDriver.d.ts.map +1 -1
- package/lib/Database/Drivers/SequelizeDriver.js +43 -18
- package/lib/Error/SocialiteAuthError/SocialiteAuthError.d.ts +9 -0
- package/lib/Error/SocialiteAuthError/SocialiteAuthError.d.ts.map +1 -0
- package/lib/Error/SocialiteAuthError/SocialiteAuthError.js +17 -0
- package/lib/Global/helpers.d.ts.map +1 -1
- package/lib/Global/helpers.js +6 -4
- package/lib/Http/index.d.ts +3 -1
- package/lib/Http/index.d.ts.map +1 -1
- package/lib/Http/index.js +26 -5
- package/lib/Interface/index.d.ts +12 -3
- package/lib/Interface/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Builder.d.ts +12 -1
- package/lib/Jcc-eloquent/lib/Builder.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Builder.js +116 -4
- package/lib/Jcc-eloquent/lib/Interfaces/index.d.ts +37 -2
- package/lib/Jcc-eloquent/lib/Interfaces/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Migration.d.ts +6 -0
- package/lib/Jcc-eloquent/lib/Migration.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Migration.js +24 -2
- package/lib/Jcc-eloquent/lib/Model.d.ts +24 -7
- package/lib/Jcc-eloquent/lib/Model.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Model.js +35 -2
- package/lib/Jcc-eloquent/lib/QueryBuilder.d.ts +2 -1
- package/lib/Jcc-eloquent/lib/QueryBuilder.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/QueryBuilder.js +10 -1
- package/lib/Jcc-eloquent/lib/Rollback.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Rollback.js +9 -2
- package/lib/Jcc-eloquent/lib/Schema/BaseSchemaEntity/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Schema/BaseSchemaEntity/index.js +3 -3
- package/lib/Jcc-eloquent/lib/Schema/BluePrint/index.d.ts +6 -2
- package/lib/Jcc-eloquent/lib/Schema/BluePrint/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Schema/BluePrint/index.js +41 -12
- package/lib/Jcc-eloquent/lib/Schema/Translator/Sqlite.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Schema/Translator/Sqlite.js +21 -3
- package/lib/Jcc-eloquent/lib/Schema/Translator/postgres.d.ts +1 -0
- package/lib/Jcc-eloquent/lib/Schema/Translator/postgres.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Schema/Translator/postgres.js +70 -14
- package/lib/Jcc-eloquent/lib/Schema/index.d.ts +12 -0
- package/lib/Jcc-eloquent/lib/Schema/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Schema/index.js +27 -6
- package/lib/Jcc-eloquent/lib/utils/index.d.ts +13 -0
- package/lib/Jcc-eloquent/lib/utils/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/utils/index.js +62 -0
- package/lib/Middleware/index.d.ts.map +1 -1
- package/lib/Middleware/index.js +4 -7
- package/lib/Model/Sequelize.d.ts +3 -0
- package/lib/Model/Sequelize.d.ts.map +1 -0
- package/lib/Model/Sequelize.js +6 -0
- package/lib/Providers/SessionServiceProvider.d.ts +12 -0
- package/lib/Providers/SessionServiceProvider.d.ts.map +1 -0
- package/lib/Providers/SessionServiceProvider.js +47 -0
- package/lib/Queue/Controllers/QueueControllers.d.ts +4 -13
- package/lib/Queue/Controllers/QueueControllers.d.ts.map +1 -1
- package/lib/Queue/Controllers/QueueControllers.js +1 -16
- package/lib/Queue/Route/web.js +4 -1
- package/lib/Queue/index.d.ts +1 -0
- package/lib/Queue/index.d.ts.map +1 -1
- package/lib/Queue/index.js +3 -0
- package/lib/Queue/middleware/queueDashboardGuard.d.ts +7 -0
- package/lib/Queue/middleware/queueDashboardGuard.d.ts.map +1 -0
- package/lib/Queue/middleware/queueDashboardGuard.js +43 -0
- package/lib/Response/index.d.ts.map +1 -1
- package/lib/Response/index.js +6 -1
- package/lib/Routes/Route.d.ts +2 -2
- package/lib/Routes/Route.d.ts.map +1 -1
- package/lib/Routes/RouteBuilder.d.ts +2 -2
- package/lib/Routes/RouteBuilder.d.ts.map +1 -1
- package/lib/Security/CsrfMiddleware.d.ts.map +1 -1
- package/lib/Security/CsrfMiddleware.js +6 -4
- package/lib/Session/DatabaseSession.d.ts +9 -3
- package/lib/Session/DatabaseSession.d.ts.map +1 -1
- package/lib/Session/DatabaseSession.js +38 -36
- package/lib/Session/ExpressJccSession.d.ts +23 -0
- package/lib/Session/ExpressJccSession.d.ts.map +1 -0
- package/lib/Session/ExpressJccSession.js +110 -0
- package/lib/Session/RedisSession.d.ts +2 -2
- package/lib/Session/RedisSession.d.ts.map +1 -1
- package/lib/Session/RedisSession.js +19 -5
- package/lib/Session/SessionManager.d.ts +18 -4
- package/lib/Session/SessionManager.d.ts.map +1 -1
- package/lib/Session/SessionManager.js +53 -17
- package/lib/Socialite/AbstractProvider.d.ts +60 -0
- package/lib/Socialite/AbstractProvider.d.ts.map +1 -0
- package/lib/Socialite/AbstractProvider.js +136 -0
- package/lib/Socialite/Drivers/facebook/FacebookDriver.d.ts +9 -0
- package/lib/Socialite/Drivers/facebook/FacebookDriver.d.ts.map +1 -0
- package/lib/Socialite/Drivers/facebook/FacebookDriver.js +40 -0
- package/lib/Socialite/Drivers/facebook/FacebookProvider.d.ts +15 -0
- package/lib/Socialite/Drivers/facebook/FacebookProvider.d.ts.map +1 -0
- package/lib/Socialite/Drivers/facebook/FacebookProvider.js +28 -0
- package/lib/Socialite/Drivers/github/GitHubDriver.d.ts +9 -0
- package/lib/Socialite/Drivers/github/GitHubDriver.d.ts.map +1 -0
- package/lib/Socialite/Drivers/github/GitHubDriver.js +54 -0
- package/lib/Socialite/Drivers/github/GitHubProvider.d.ts +15 -0
- package/lib/Socialite/Drivers/github/GitHubProvider.d.ts.map +1 -0
- package/lib/Socialite/Drivers/github/GitHubProvider.js +28 -0
- package/lib/Socialite/Drivers/gitlab/GitLabDriver.d.ts +10 -0
- package/lib/Socialite/Drivers/gitlab/GitLabDriver.d.ts.map +1 -0
- package/lib/Socialite/Drivers/gitlab/GitLabDriver.js +37 -0
- package/lib/Socialite/Drivers/gitlab/GitLabProvider.d.ts +15 -0
- package/lib/Socialite/Drivers/gitlab/GitLabProvider.d.ts.map +1 -0
- package/lib/Socialite/Drivers/gitlab/GitLabProvider.js +28 -0
- package/lib/Socialite/Drivers/google/GoogleDriver.d.ts +9 -0
- package/lib/Socialite/Drivers/google/GoogleDriver.d.ts.map +1 -0
- package/lib/Socialite/Drivers/google/GoogleDriver.js +39 -0
- package/lib/Socialite/Drivers/google/GoogleProvider.d.ts +15 -0
- package/lib/Socialite/Drivers/google/GoogleProvider.d.ts.map +1 -0
- package/lib/Socialite/Drivers/google/GoogleProvider.js +28 -0
- package/lib/Socialite/Drivers/slack/SlackDriver.d.ts +9 -0
- package/lib/Socialite/Drivers/slack/SlackDriver.d.ts.map +1 -0
- package/lib/Socialite/Drivers/slack/SlackDriver.js +41 -0
- package/lib/Socialite/Drivers/slack/SlackProvider.d.ts +16 -0
- package/lib/Socialite/Drivers/slack/SlackProvider.d.ts.map +1 -0
- package/lib/Socialite/Drivers/slack/SlackProvider.js +37 -0
- package/lib/Socialite/Drivers/twitter/TwitterDriver.d.ts +9 -0
- package/lib/Socialite/Drivers/twitter/TwitterDriver.d.ts.map +1 -0
- package/lib/Socialite/Drivers/twitter/TwitterDriver.js +57 -0
- package/lib/Socialite/Drivers/twitter/TwitterProvider.d.ts +16 -0
- package/lib/Socialite/Drivers/twitter/TwitterProvider.d.ts.map +1 -0
- package/lib/Socialite/Drivers/twitter/TwitterProvider.js +38 -0
- package/lib/Socialite/SocialUser.d.ts +42 -0
- package/lib/Socialite/SocialUser.d.ts.map +1 -0
- package/lib/Socialite/SocialUser.js +116 -0
- package/lib/Socialite/Socialite.d.ts +13 -0
- package/lib/Socialite/Socialite.d.ts.map +1 -0
- package/lib/Socialite/Socialite.js +41 -0
- package/lib/Socialite/SocialiteProvider.d.ts +9 -0
- package/lib/Socialite/SocialiteProvider.d.ts.map +1 -0
- package/lib/Socialite/SocialiteProvider.js +15 -0
- package/lib/Socialite/config.d.ts +7 -0
- package/lib/Socialite/config.d.ts.map +1 -0
- package/lib/Socialite/config.js +44 -0
- package/lib/Socialite/constant.d.ts +18 -0
- package/lib/Socialite/constant.d.ts.map +1 -0
- package/lib/Socialite/constant.js +20 -0
- package/lib/Socialite/index.d.ts +13 -0
- package/lib/Socialite/index.d.ts.map +1 -0
- package/lib/Socialite/index.js +25 -0
- package/lib/Socialite/types.d.ts +13 -0
- package/lib/Socialite/types.d.ts.map +1 -0
- package/lib/Socialite/types.js +2 -0
- package/lib/Type/index.d.ts +1 -0
- package/lib/Type/index.d.ts.map +1 -1
- package/lib/Validation/Validator/CustomValidation.d.ts.map +1 -1
- package/lib/Validation/Validator/CustomValidation.js +2 -2
- package/lib/Validation/Validator/helper.d.ts.map +1 -1
- package/lib/Validation/Validator/helper.js +8 -1
- package/lib/util/index.d.ts +36 -1
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +123 -26
- package/package.json +1 -1
|
@@ -339,18 +339,33 @@ class Blueprint {
|
|
|
339
339
|
return this;
|
|
340
340
|
}
|
|
341
341
|
/**
|
|
342
|
-
* Adds an index
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
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;
|
|
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
|
-
|
|
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+`?(
|
|
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;
|
|
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
|
|
15
|
-
//
|
|
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
|
|
23
|
+
// Remove UNSIGNED keyword (PostgreSQL doesn't support unsigned types)
|
|
23
24
|
query = query.replace(/\s+UNSIGNED\b/gi, "");
|
|
24
|
-
// Replace remaining AUTO_INCREMENT (
|
|
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
|
-
//
|
|
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
|
-
|
|
56
|
-
//
|
|
57
|
-
|
|
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,
|
|
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;
|
|
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":"
|
|
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;
|
|
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"}
|
package/lib/Middleware/index.js
CHANGED
|
@@ -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
|
-
(
|
|
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 @@
|
|
|
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,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;
|