node-server-engine 2.2.0 → 2.3.1
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/README.md +2 -0
- package/dist/entities/ValidationError/ValidationError.js +10 -1
- package/dist/entities/ValidationError/ValidationError.js.map +1 -1
- package/dist/utils/dbMigration/dbMigration.js +15 -10
- package/dist/utils/dbMigration/dbMigration.js.map +1 -1
- package/dist/utils/dbMigration/migrateMetadataTable/migrateMetadataTable.js +9 -6
- package/dist/utils/dbMigration/migrateMetadataTable/migrateMetadataTable.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -238,6 +238,8 @@ The main function of the endpoint is called the **handler**. This function shoul
|
|
|
238
238
|
|
|
239
239
|
An endpoint usually has a **validator**. A validator is a schema that will be compared to the incoming request. The request will be denied if it contains illegal or malformed arguments. For more detail see the documentation of the underlying package [express-validator](https://express-validator.github.io/docs/schema-validation.html).
|
|
240
240
|
|
|
241
|
+
A request that fails validation is answered `400` with `errorCode: 'invalid-request'` and `details`, one entry per failed field: `{ field, location, message }` (the submitted values are not echoed back).
|
|
242
|
+
|
|
241
243
|
```javascript
|
|
242
244
|
import { Endpoint, EndpointMethod } from 'node-server-engine';
|
|
243
245
|
|
|
@@ -29,13 +29,22 @@ let ValidationError = exports.ValidationError = /*#__PURE__*/function (_WebError
|
|
|
29
29
|
...hint,
|
|
30
30
|
[error.type]: error.msg
|
|
31
31
|
}), {});
|
|
32
|
+
// Which fields failed and why, so a client can point at them. The submitted values are left out.
|
|
33
|
+
const details = errors.map(error => error.type === 'field' ? {
|
|
34
|
+
field: error.path,
|
|
35
|
+
location: error.location,
|
|
36
|
+
message: error.msg
|
|
37
|
+
} : {
|
|
38
|
+
message: error.msg
|
|
39
|
+
});
|
|
32
40
|
return _callSuper(this, ValidationError, [{
|
|
33
41
|
message: 'Request did not pass validation',
|
|
34
42
|
errorCode: 'invalid-request',
|
|
35
43
|
statusCode: 400,
|
|
36
44
|
severity: _const.LogSeverity.WARNING,
|
|
37
45
|
data: hint,
|
|
38
|
-
hint
|
|
46
|
+
hint,
|
|
47
|
+
details
|
|
39
48
|
}]);
|
|
40
49
|
}
|
|
41
50
|
(0, _inherits2.default)(ValidationError, _WebError);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValidationError.js","names":["_const","require","_EngineError","_WebError2","_callSuper","t","o","e","_getPrototypeOf2","default","_possibleConstructorReturn2","_isNativeReflectConstruct","Reflect","construct","constructor","apply","Boolean","prototype","valueOf","call","ValidationError","exports","_WebError","validationResult","_classCallCheck2","isEmpty","EngineError","message","errors","array","hint","reduce","error","type","msg","errorCode","statusCode","severity","LogSeverity","WARNING","data","_inherits2","_createClass2","WebError"],"sources":["../../../src/entities/ValidationError/ValidationError.ts"],"sourcesContent":["import {\n ValidationError as ExpressValidationError,\n Result\n} from 'express-validator';\nimport { LogSeverity } from 'const';\nimport { EngineError } from 'entities/EngineError';\nimport { WebError } from 'entities/WebError';\n\n/** Error class for request/message validation errors */\nexport class ValidationError extends WebError {\n /** Create an ValidationError this represents errors in parsing incoming messages/requests */\n public constructor(validationResult: Result<ExpressValidationError>) {\n if (validationResult.isEmpty())\n throw new EngineError({\n message:\n 'Attempted to create a validation error while validation was successful'\n });\n\n const errors = validationResult.array();\n // Hint that is sent to the client as logged as data\n const hint = errors.reduce(\n (hint, error) => ({ ...hint, [error.type]: error.msg as string }),\n {}\n );\n super({\n message: 'Request did not pass validation',\n errorCode: 'invalid-request',\n statusCode: 400,\n severity: LogSeverity.WARNING,\n data: hint,\n hint\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;AAIA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AACA,IAAAE,UAAA,GAAAF,OAAA;AAA6C,SAAAG,WAAAC,CAAA,EAAAC,CAAA,EAAAC,CAAA,WAAAD,CAAA,OAAAE,gBAAA,CAAAC,OAAA,EAAAH,CAAA,OAAAI,2BAAA,CAAAD,OAAA,EAAAJ,CAAA,EAAAM,yBAAA,KAAAC,OAAA,CAAAC,SAAA,CAAAP,CAAA,EAAAC,CAAA,YAAAC,gBAAA,CAAAC,OAAA,EAAAJ,CAAA,EAAAS,WAAA,IAAAR,CAAA,CAAAS,KAAA,CAAAV,CAAA,EAAAE,CAAA;AAAA,SAAAI,0BAAA,cAAAN,CAAA,IAAAW,OAAA,CAAAC,SAAA,CAAAC,OAAA,CAAAC,IAAA,CAAAP,OAAA,CAAAC,SAAA,CAAAG,OAAA,iCAAAX,CAAA,aAAAM,yBAAA,YAAAA,CAAA,aAAAN,CAAA;AAE7C;AAAA,IACae,eAAe,GAAAC,OAAA,CAAAD,eAAA,0BAAAE,SAAA;EAC1B;EACA,SAAAF,gBAAmBG,gBAAgD,EAAE;IAAA,IAAAC,gBAAA,CAAAf,OAAA,QAAAW,eAAA;IACnE,IAAIG,gBAAgB,CAACE,OAAO,CAAC,CAAC,EAC5B,MAAM,IAAIC,wBAAW,CAAC;MACpBC,OAAO,EACL;IACJ,CAAC,CAAC;IAEJ,MAAMC,MAAM,GAAGL,gBAAgB,CAACM,KAAK,CAAC,CAAC;IACvC;IACA,MAAMC,IAAI,GAAGF,MAAM,CAACG,MAAM,CACxB,CAACD,IAAI,EAAEE,KAAK,MAAM;MAAE,GAAGF,IAAI;MAAE,CAACE,KAAK,CAACC,IAAI,GAAGD,KAAK,CAACE;IAAc,CAAC,CAAC,EACjE,CAAC,CACH,CAAC;IAAC,OAAA9B,UAAA,OAAAgB,eAAA,GACI;MACJO,OAAO,EAAE,iCAAiC;
|
|
1
|
+
{"version":3,"file":"ValidationError.js","names":["_const","require","_EngineError","_WebError2","_callSuper","t","o","e","_getPrototypeOf2","default","_possibleConstructorReturn2","_isNativeReflectConstruct","Reflect","construct","constructor","apply","Boolean","prototype","valueOf","call","ValidationError","exports","_WebError","validationResult","_classCallCheck2","isEmpty","EngineError","message","errors","array","hint","reduce","error","type","msg","details","map","field","path","location","errorCode","statusCode","severity","LogSeverity","WARNING","data","_inherits2","_createClass2","WebError"],"sources":["../../../src/entities/ValidationError/ValidationError.ts"],"sourcesContent":["import {\n ValidationError as ExpressValidationError,\n Result\n} from 'express-validator';\nimport { LogSeverity } from 'const';\nimport { EngineError } from 'entities/EngineError';\nimport { WebError } from 'entities/WebError';\n\n/** Error class for request/message validation errors */\nexport class ValidationError extends WebError {\n /** Create an ValidationError this represents errors in parsing incoming messages/requests */\n public constructor(validationResult: Result<ExpressValidationError>) {\n if (validationResult.isEmpty())\n throw new EngineError({\n message:\n 'Attempted to create a validation error while validation was successful'\n });\n\n const errors = validationResult.array();\n // Hint that is sent to the client as logged as data\n const hint = errors.reduce(\n (hint, error) => ({ ...hint, [error.type]: error.msg as string }),\n {}\n );\n // Which fields failed and why, so a client can point at them. The submitted values are left out.\n const details = errors.map((error) =>\n error.type === 'field'\n ? {\n field: error.path,\n location: error.location,\n message: error.msg as string\n }\n : { message: error.msg as string }\n );\n super({\n message: 'Request did not pass validation',\n errorCode: 'invalid-request',\n statusCode: 400,\n severity: LogSeverity.WARNING,\n data: hint,\n hint,\n details\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;AAIA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AACA,IAAAE,UAAA,GAAAF,OAAA;AAA6C,SAAAG,WAAAC,CAAA,EAAAC,CAAA,EAAAC,CAAA,WAAAD,CAAA,OAAAE,gBAAA,CAAAC,OAAA,EAAAH,CAAA,OAAAI,2BAAA,CAAAD,OAAA,EAAAJ,CAAA,EAAAM,yBAAA,KAAAC,OAAA,CAAAC,SAAA,CAAAP,CAAA,EAAAC,CAAA,YAAAC,gBAAA,CAAAC,OAAA,EAAAJ,CAAA,EAAAS,WAAA,IAAAR,CAAA,CAAAS,KAAA,CAAAV,CAAA,EAAAE,CAAA;AAAA,SAAAI,0BAAA,cAAAN,CAAA,IAAAW,OAAA,CAAAC,SAAA,CAAAC,OAAA,CAAAC,IAAA,CAAAP,OAAA,CAAAC,SAAA,CAAAG,OAAA,iCAAAX,CAAA,aAAAM,yBAAA,YAAAA,CAAA,aAAAN,CAAA;AAE7C;AAAA,IACae,eAAe,GAAAC,OAAA,CAAAD,eAAA,0BAAAE,SAAA;EAC1B;EACA,SAAAF,gBAAmBG,gBAAgD,EAAE;IAAA,IAAAC,gBAAA,CAAAf,OAAA,QAAAW,eAAA;IACnE,IAAIG,gBAAgB,CAACE,OAAO,CAAC,CAAC,EAC5B,MAAM,IAAIC,wBAAW,CAAC;MACpBC,OAAO,EACL;IACJ,CAAC,CAAC;IAEJ,MAAMC,MAAM,GAAGL,gBAAgB,CAACM,KAAK,CAAC,CAAC;IACvC;IACA,MAAMC,IAAI,GAAGF,MAAM,CAACG,MAAM,CACxB,CAACD,IAAI,EAAEE,KAAK,MAAM;MAAE,GAAGF,IAAI;MAAE,CAACE,KAAK,CAACC,IAAI,GAAGD,KAAK,CAACE;IAAc,CAAC,CAAC,EACjE,CAAC,CACH,CAAC;IACD;IACA,MAAMC,OAAO,GAAGP,MAAM,CAACQ,GAAG,CAAEJ,KAAK,IAC/BA,KAAK,CAACC,IAAI,KAAK,OAAO,GAClB;MACEI,KAAK,EAAEL,KAAK,CAACM,IAAI;MACjBC,QAAQ,EAAEP,KAAK,CAACO,QAAQ;MACxBZ,OAAO,EAAEK,KAAK,CAACE;IACjB,CAAC,GACD;MAAEP,OAAO,EAAEK,KAAK,CAACE;IAAc,CACrC,CAAC;IAAC,OAAA9B,UAAA,OAAAgB,eAAA,GACI;MACJO,OAAO,EAAE,iCAAiC;MAC1Ca,SAAS,EAAE,iBAAiB;MAC5BC,UAAU,EAAE,GAAG;MACfC,QAAQ,EAAEC,kBAAW,CAACC,OAAO;MAC7BC,IAAI,EAAEf,IAAI;MACVA,IAAI;MACJK;IACF,CAAC;EACH;EAAC,IAAAW,UAAA,CAAArC,OAAA,EAAAW,eAAA,EAAAE,SAAA;EAAA,WAAAyB,aAAA,CAAAtC,OAAA,EAAAW,eAAA;AAAA,EAlCkC4B,mBAAQ","ignoreList":[]}
|
|
@@ -26,7 +26,10 @@ function getMigrationPaths() {
|
|
|
26
26
|
const prodDefaultPath = (0, _path.join)(process.cwd(), './dist/db/migrations');
|
|
27
27
|
const devDefaultPath = (0, _path.join)(process.cwd(), './src/db/migrations');
|
|
28
28
|
const isProduction = ['prod', 'production'].includes(process.env.NODE_ENV ?? '');
|
|
29
|
-
const path = [process.env.DB_MIGRATIONS_DIR, isProduction ? prodDefaultPath : devDefaultPath].filter(path => !!path && (0, _fs.existsSync)(path) && (0, _fs.lstatSync)(path).isDirectory())
|
|
29
|
+
const path = [process.env.DB_MIGRATIONS_DIR, isProduction ? prodDefaultPath : devDefaultPath].filter(path => !!path && (0, _fs.existsSync)(path) && (0, _fs.lstatSync)(path).isDirectory())
|
|
30
|
+
// Only the first one: running a second folder of the same migrations (src/ next to dist/) would load
|
|
31
|
+
// files this process cannot run, e.g. TypeScript sources from a built server
|
|
32
|
+
.slice(0, 1);
|
|
30
33
|
(0, _report.reportDebug)({
|
|
31
34
|
namespace,
|
|
32
35
|
message: 'Obtaining Umzug migration options',
|
|
@@ -103,8 +106,8 @@ async function runPendingMigrations() {
|
|
|
103
106
|
}) => {
|
|
104
107
|
const nameWithoutExtension = name.replace(/\.(ts|js)$/, '');
|
|
105
108
|
|
|
106
|
-
//
|
|
107
|
-
const
|
|
109
|
+
// Imported only when it runs: a migration already applied is never loaded
|
|
110
|
+
const load = () => (specifier => new Promise(r => r(`${specifier}`)).then(s => _interopRequireWildcard(require(s))))(path || '');
|
|
108
111
|
return {
|
|
109
112
|
name: nameWithoutExtension,
|
|
110
113
|
up: async () => {
|
|
@@ -112,11 +115,11 @@ async function runPendingMigrations() {
|
|
|
112
115
|
namespace,
|
|
113
116
|
message: `Running migration: ${nameWithoutExtension}`
|
|
114
117
|
});
|
|
115
|
-
const migration = await
|
|
118
|
+
const migration = await load();
|
|
116
119
|
return migration.up(context);
|
|
117
120
|
},
|
|
118
121
|
down: async () => {
|
|
119
|
-
const migration = await
|
|
122
|
+
const migration = await load();
|
|
120
123
|
return migration.down(context);
|
|
121
124
|
}
|
|
122
125
|
};
|
|
@@ -207,15 +210,17 @@ async function rollbackMigrations() {
|
|
|
207
210
|
}) => {
|
|
208
211
|
// Strip file extension to ensure consistent naming across .ts and .js files
|
|
209
212
|
const nameWithoutExtension = name.replace(/\.(ts|js)$/, '');
|
|
210
|
-
|
|
213
|
+
|
|
214
|
+
// Imported only when it runs: a migration already applied is never loaded
|
|
215
|
+
const load = () => (specifier => new Promise(r => r(`${specifier}`)).then(s => _interopRequireWildcard(require(s))))(path || '');
|
|
211
216
|
return {
|
|
212
217
|
name: nameWithoutExtension,
|
|
213
218
|
up: async () => {
|
|
214
|
-
const migration = await
|
|
219
|
+
const migration = await load();
|
|
215
220
|
return migration.up(context);
|
|
216
221
|
},
|
|
217
222
|
down: async () => {
|
|
218
|
-
const migration = await
|
|
223
|
+
const migration = await load();
|
|
219
224
|
return migration.down(context);
|
|
220
225
|
}
|
|
221
226
|
};
|
|
@@ -249,7 +254,7 @@ async function testRecreateDB(options = {}) {
|
|
|
249
254
|
if (!_Sequelize.sequelize) throw new _EngineError.EngineError({
|
|
250
255
|
message: 'Sequelize is not initialized'
|
|
251
256
|
});
|
|
252
|
-
await _Sequelize.sequelize.query(`DROP SCHEMA public${
|
|
257
|
+
await _Sequelize.sequelize.query(`DROP SCHEMA public${_Sequelize.sequelize.getDialect() === 'postgres' ? ' CASCADE' : ''}`);
|
|
253
258
|
await _Sequelize.sequelize.query(`CREATE SCHEMA public`);
|
|
254
259
|
if (!options.clean) await runPendingMigrations();
|
|
255
260
|
}
|
|
@@ -273,7 +278,7 @@ function clearDbTransaction(sequelize, options) {
|
|
|
273
278
|
// We ignore the migration metadata schema
|
|
274
279
|
if (!options.includeMetadata && model === 'sequelizeMeta') continue;
|
|
275
280
|
const table = sequelize.models[model].tableName;
|
|
276
|
-
await sequelize.query(`TRUNCATE ${table}${
|
|
281
|
+
await sequelize.query(`TRUNCATE ${table}${sequelize.getDialect() === 'postgres' ? ' CASCADE' : ''};`, {
|
|
277
282
|
raw: true,
|
|
278
283
|
transaction: t
|
|
279
284
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dbMigration.js","names":["_fs","require","_path","_umzug","_migrateMetadataTable","_models","_EngineError","_Sequelize","_report","_semverCompare","cache","_interopRequireWildcard","e","t","__esModule","r","c","a","Object","defineProperty","n","__proto__","default","WeakMap","has","get","set","hasOwnProperty","call","getOwnPropertyDescriptor","namespace","getMigrationPaths","prodDefaultPath","join","process","cwd","devDefaultPath","isProduction","includes","env","NODE_ENV","path","DB_MIGRATIONS_DIR","filter","existsSync","lstatSync","isDirectory","reportDebug","message","data","prodPath","devPath","customPath","map","p","getMigrationExtension","directory","hasTypeScript","readdirSync","some","file","endsWith","runPendingMigrations","sequelize","EngineError","sqlHost","SQL_HOST","sqlDb","SQL_DB","sqlUser","SQL_USER","nodeEnv","migrateMetadataTable","migrationPaths","length","migrator","Umzug","migrations","glob","resolve","name","context","nameWithoutExtension","replace","migrationPromise","specifier","Promise","then","s","up","migration","down","getQueryInterface","storage","SequelizeStorage","logger","console","reportInfo","error","Error","String","stack","undefined","rollbackMigrations","BUILD_ID","SequelizeMeta","findAll","order","raw","rollbackUntil","find","version","semverCompare","buildId","to","testRecreateDB","options","query","SQL_TYPE","clean","testClearDB","transaction","clearDbTransaction","model","keys","models","includeMetadata","table","tableName"],"sources":["../../../src/utils/dbMigration/dbMigration.ts"],"sourcesContent":["import { existsSync, lstatSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { Sequelize, Transaction } from 'sequelize';\nimport { Umzug, SequelizeStorage } from 'umzug';\nimport { ClearDbOptions, RecreateDbOptions } from './dbMigration.types';\nimport { migrateMetadataTable } from './migrateMetadataTable';\nimport { SequelizeMeta } from 'db/models';\nimport { EngineError } from 'entities/EngineError';\nimport { sequelize } from 'entities/Sequelize';\nimport { reportDebug, reportInfo } from 'utils/report';\nimport { semverCompare } from 'utils/semverCompare';\n\nconst namespace = 'engine:utils:dbMigration';\n\nexport function getMigrationPaths(): Array<string> | undefined {\n // We look between possibilities for the first directory that exists and matches our expectations\n // First a user specified one, then the production default, then the development default\n const prodDefaultPath = join(process.cwd(), './dist/db/migrations');\n const devDefaultPath = join(process.cwd(), './src/db/migrations');\n const isProduction = ['prod', 'production'].includes(\n process.env.NODE_ENV ?? ''\n );\n const path = [\n process.env.DB_MIGRATIONS_DIR,\n isProduction ? prodDefaultPath : devDefaultPath\n ].filter(\n (path): path is string =>\n !!path && existsSync(path) && lstatSync(path).isDirectory()\n );\n reportDebug({\n namespace,\n message: 'Obtaining Umzug migration options',\n data: {\n path,\n prodPath: prodDefaultPath,\n devPath: devDefaultPath,\n customPath: process.env.DB_MIGRATIONS_DIR\n }\n });\n return path.map((p) => `${p}/*.${getMigrationExtension(p)}`);\n}\n\n/**\n * Detect whether a migration folder holds TypeScript sources or compiled JavaScript,\n * so migrations are found regardless of the NODE_ENV value\n */\nfunction getMigrationExtension(directory: string): 'ts' | 'js' {\n const hasTypeScript = readdirSync(directory).some(\n (file) => file.endsWith('.ts') && !file.endsWith('.d.ts')\n );\n return hasTypeScript ? 'ts' : 'js';\n}\n\n/** Run all the non-executed migrations one by one */\nexport async function runPendingMigrations(): Promise<void> {\n if (!sequelize)\n throw new EngineError({ message: 'Sequelize is not initialized' });\n\n try {\n reportDebug({\n namespace,\n message: 'Starting migration process',\n data: {\n sqlHost: process.env.SQL_HOST,\n sqlDb: process.env.SQL_DB,\n sqlUser: process.env.SQL_USER,\n nodeEnv: process.env.NODE_ENV\n }\n });\n\n // First make sure that the metadata table is up to date\n reportDebug({\n namespace,\n message: 'Migrating metadata table'\n });\n await migrateMetadataTable(sequelize);\n\n const migrationPaths = getMigrationPaths();\n\n if (!migrationPaths || migrationPaths.length <= 0) {\n reportDebug({\n namespace,\n message: 'No valid migration paths found.',\n data: { migrationPaths }\n });\n return;\n }\n\n // Process migrations sequentially to avoid race conditions\n for (const path of migrationPaths) {\n reportDebug({\n namespace,\n message: 'Processing migration path',\n data: { path }\n });\n\n const migrator = new Umzug({\n migrations: {\n glob: path,\n resolve: ({ name, path, context }) => {\n const nameWithoutExtension = name.replace(/\\.(ts|js)$/, '');\n\n // Use dynamic import for better TypeScript/ES module support\n const migrationPromise = import(path || '');\n return {\n name: nameWithoutExtension,\n up: async () => {\n reportDebug({\n namespace,\n message: `Running migration: ${nameWithoutExtension}`\n });\n const migration = await migrationPromise;\n return migration.up(context);\n },\n down: async () => {\n const migration = await migrationPromise;\n return migration.down(context);\n }\n };\n }\n },\n context: sequelize.getQueryInterface(),\n storage: new SequelizeStorage({ sequelize }),\n logger: console\n });\n\n reportDebug({\n namespace,\n message: 'Starting pending database migrations',\n data: { path }\n });\n\n await migrator.up();\n\n reportInfo({\n message: 'Database migration completed successfully',\n data: { path }\n });\n }\n } catch (error) {\n reportDebug({\n namespace,\n message: 'Migration failed with error',\n data: {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n sqlHost: process.env.SQL_HOST,\n sqlDb: process.env.SQL_DB\n }\n });\n throw error;\n }\n}\n\n/** Rollback all migrations up to a specified target version */\nexport async function rollbackMigrations(): Promise<void> {\n if (!sequelize)\n throw new EngineError({ message: 'Sequelize is not initialized' });\n if (!process.env.BUILD_ID)\n throw new EngineError({ message: 'BUILD_ID is not defined' });\n\n // Fetch executed migrations in ascending order\n const migrations = await SequelizeMeta.findAll({\n order: [['name', 'ASC']],\n raw: true\n });\n const rollbackUntil = migrations.find(\n (migration) =>\n migration.version &&\n semverCompare(migration.version, process.env.BUILD_ID as string) === 1\n );\n\n if (!rollbackUntil) {\n reportDebug({\n namespace,\n message: 'No rollback target found for the current BUILD_ID.',\n data: { buildId: process.env.BUILD_ID }\n });\n return;\n }\n\n const migrationPaths = getMigrationPaths();\n\n if (!migrationPaths || migrationPaths.length <= 0) {\n reportDebug({\n namespace,\n message: 'No valid migration paths found for rollback.',\n data: { migrationPaths }\n });\n return;\n }\n\n // Process rollback migrations sequentially\n for (const path of migrationPaths) {\n const migrator = new Umzug({\n migrations: {\n glob: path,\n resolve: ({ name, path, context }) => {\n // Strip file extension to ensure consistent naming across .ts and .js files\n const nameWithoutExtension = name.replace(/\\.(ts|js)$/, '');\n\n const migrationPromise = import(path || '');\n return {\n name: nameWithoutExtension,\n up: async () => {\n const migration = await migrationPromise;\n return migration.up(context);\n },\n down: async () => {\n const migration = await migrationPromise;\n return migration.down(context);\n }\n };\n }\n },\n context: sequelize.getQueryInterface(),\n storage: new SequelizeStorage({ sequelize }),\n logger: console\n });\n\n reportDebug({\n namespace,\n message: `Rolling back migrations up to: ${rollbackUntil.name}`,\n data: { path }\n });\n\n await migrator.down({ to: rollbackUntil.name });\n }\n}\n\n/**\n * Recreate the whole database\n * Quick way to make sure that we are working on a clean database\n * /!\\ Should only be used when running tests\n */\nexport async function testRecreateDB(\n options: RecreateDbOptions = {}\n): Promise<void> {\n if (!sequelize)\n throw new EngineError({ message: 'Sequelize is not initialized' });\n await sequelize.query(\n `DROP SCHEMA public${process.env.SQL_TYPE === 'postgres' ? ' CASCADE' : ''}`\n );\n await sequelize.query(`CREATE SCHEMA public`);\n if (!options.clean) await runPendingMigrations();\n}\n\n/**\n * Empty all the schemas in the database\n * Quick way to flush the database data while keep the structure\n * /!\\ Should only be used when running tests\n */\nexport async function testClearDB(options: ClearDbOptions = {}): Promise<void> {\n if (!sequelize)\n throw new EngineError({ message: 'Sequelize is not initialized' });\n await sequelize.transaction(clearDbTransaction(sequelize, options));\n}\n\n/** DB clearing transaction */\nfunction clearDbTransaction(sequelize: Sequelize, options: ClearDbOptions) {\n return async (t: Transaction): Promise<void> => {\n for (const model of Object.keys(sequelize.models)) {\n // We ignore the migration metadata schema\n if (!options.includeMetadata && model === 'sequelizeMeta') continue;\n const table = sequelize.models[model].tableName;\n await sequelize.query(\n `TRUNCATE ${table}${process.env.SQL_TYPE === 'postgres' ? ' CASCADE' : ''};`,\n {\n raw: true,\n transaction: t\n }\n );\n }\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"dbMigration.js","names":["_fs","require","_path","_umzug","_migrateMetadataTable","_models","_EngineError","_Sequelize","_report","_semverCompare","cache","_interopRequireWildcard","e","t","__esModule","r","c","a","Object","defineProperty","n","__proto__","default","WeakMap","has","get","set","hasOwnProperty","call","getOwnPropertyDescriptor","namespace","getMigrationPaths","prodDefaultPath","join","process","cwd","devDefaultPath","isProduction","includes","env","NODE_ENV","path","DB_MIGRATIONS_DIR","filter","existsSync","lstatSync","isDirectory","slice","reportDebug","message","data","prodPath","devPath","customPath","map","p","getMigrationExtension","directory","hasTypeScript","readdirSync","some","file","endsWith","runPendingMigrations","sequelize","EngineError","sqlHost","SQL_HOST","sqlDb","SQL_DB","sqlUser","SQL_USER","nodeEnv","migrateMetadataTable","migrationPaths","length","migrator","Umzug","migrations","glob","resolve","name","context","nameWithoutExtension","replace","load","specifier","Promise","then","s","up","migration","down","getQueryInterface","storage","SequelizeStorage","logger","console","reportInfo","error","Error","String","stack","undefined","rollbackMigrations","BUILD_ID","SequelizeMeta","findAll","order","raw","rollbackUntil","find","version","semverCompare","buildId","to","testRecreateDB","options","query","getDialect","clean","testClearDB","transaction","clearDbTransaction","model","keys","models","includeMetadata","table","tableName"],"sources":["../../../src/utils/dbMigration/dbMigration.ts"],"sourcesContent":["import { existsSync, lstatSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { Sequelize, Transaction } from 'sequelize';\nimport { Umzug, SequelizeStorage } from 'umzug';\nimport { ClearDbOptions, RecreateDbOptions } from './dbMigration.types';\nimport { migrateMetadataTable } from './migrateMetadataTable';\nimport { SequelizeMeta } from 'db/models';\nimport { EngineError } from 'entities/EngineError';\nimport { sequelize } from 'entities/Sequelize';\nimport { reportDebug, reportInfo } from 'utils/report';\nimport { semverCompare } from 'utils/semverCompare';\n\nconst namespace = 'engine:utils:dbMigration';\n\nexport function getMigrationPaths(): Array<string> | undefined {\n // We look between possibilities for the first directory that exists and matches our expectations\n // First a user specified one, then the production default, then the development default\n const prodDefaultPath = join(process.cwd(), './dist/db/migrations');\n const devDefaultPath = join(process.cwd(), './src/db/migrations');\n const isProduction = ['prod', 'production'].includes(\n process.env.NODE_ENV ?? ''\n );\n const path = [\n process.env.DB_MIGRATIONS_DIR,\n isProduction ? prodDefaultPath : devDefaultPath\n ]\n .filter(\n (path): path is string =>\n !!path && existsSync(path) && lstatSync(path).isDirectory()\n )\n // Only the first one: running a second folder of the same migrations (src/ next to dist/) would load\n // files this process cannot run, e.g. TypeScript sources from a built server\n .slice(0, 1);\n reportDebug({\n namespace,\n message: 'Obtaining Umzug migration options',\n data: {\n path,\n prodPath: prodDefaultPath,\n devPath: devDefaultPath,\n customPath: process.env.DB_MIGRATIONS_DIR\n }\n });\n return path.map((p) => `${p}/*.${getMigrationExtension(p)}`);\n}\n\n/**\n * Detect whether a migration folder holds TypeScript sources or compiled JavaScript,\n * so migrations are found regardless of the NODE_ENV value\n */\nfunction getMigrationExtension(directory: string): 'ts' | 'js' {\n const hasTypeScript = readdirSync(directory).some(\n (file) => file.endsWith('.ts') && !file.endsWith('.d.ts')\n );\n return hasTypeScript ? 'ts' : 'js';\n}\n\n/** Run all the non-executed migrations one by one */\nexport async function runPendingMigrations(): Promise<void> {\n if (!sequelize)\n throw new EngineError({ message: 'Sequelize is not initialized' });\n\n try {\n reportDebug({\n namespace,\n message: 'Starting migration process',\n data: {\n sqlHost: process.env.SQL_HOST,\n sqlDb: process.env.SQL_DB,\n sqlUser: process.env.SQL_USER,\n nodeEnv: process.env.NODE_ENV\n }\n });\n\n // First make sure that the metadata table is up to date\n reportDebug({\n namespace,\n message: 'Migrating metadata table'\n });\n await migrateMetadataTable(sequelize);\n\n const migrationPaths = getMigrationPaths();\n\n if (!migrationPaths || migrationPaths.length <= 0) {\n reportDebug({\n namespace,\n message: 'No valid migration paths found.',\n data: { migrationPaths }\n });\n return;\n }\n\n // Process migrations sequentially to avoid race conditions\n for (const path of migrationPaths) {\n reportDebug({\n namespace,\n message: 'Processing migration path',\n data: { path }\n });\n\n const migrator = new Umzug({\n migrations: {\n glob: path,\n resolve: ({ name, path, context }) => {\n const nameWithoutExtension = name.replace(/\\.(ts|js)$/, '');\n\n // Imported only when it runs: a migration already applied is never loaded\n const load = (): Promise<{\n up: (context: unknown) => Promise<unknown>;\n down: (context: unknown) => Promise<unknown>;\n }> => import(path || '');\n return {\n name: nameWithoutExtension,\n up: async () => {\n reportDebug({\n namespace,\n message: `Running migration: ${nameWithoutExtension}`\n });\n const migration = await load();\n return migration.up(context);\n },\n down: async () => {\n const migration = await load();\n return migration.down(context);\n }\n };\n }\n },\n context: sequelize.getQueryInterface(),\n storage: new SequelizeStorage({ sequelize }),\n logger: console\n });\n\n reportDebug({\n namespace,\n message: 'Starting pending database migrations',\n data: { path }\n });\n\n await migrator.up();\n\n reportInfo({\n message: 'Database migration completed successfully',\n data: { path }\n });\n }\n } catch (error) {\n reportDebug({\n namespace,\n message: 'Migration failed with error',\n data: {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n sqlHost: process.env.SQL_HOST,\n sqlDb: process.env.SQL_DB\n }\n });\n throw error;\n }\n}\n\n/** Rollback all migrations up to a specified target version */\nexport async function rollbackMigrations(): Promise<void> {\n if (!sequelize)\n throw new EngineError({ message: 'Sequelize is not initialized' });\n if (!process.env.BUILD_ID)\n throw new EngineError({ message: 'BUILD_ID is not defined' });\n\n // Fetch executed migrations in ascending order\n const migrations = await SequelizeMeta.findAll({\n order: [['name', 'ASC']],\n raw: true\n });\n const rollbackUntil = migrations.find(\n (migration) =>\n migration.version &&\n semverCompare(migration.version, process.env.BUILD_ID as string) === 1\n );\n\n if (!rollbackUntil) {\n reportDebug({\n namespace,\n message: 'No rollback target found for the current BUILD_ID.',\n data: { buildId: process.env.BUILD_ID }\n });\n return;\n }\n\n const migrationPaths = getMigrationPaths();\n\n if (!migrationPaths || migrationPaths.length <= 0) {\n reportDebug({\n namespace,\n message: 'No valid migration paths found for rollback.',\n data: { migrationPaths }\n });\n return;\n }\n\n // Process rollback migrations sequentially\n for (const path of migrationPaths) {\n const migrator = new Umzug({\n migrations: {\n glob: path,\n resolve: ({ name, path, context }) => {\n // Strip file extension to ensure consistent naming across .ts and .js files\n const nameWithoutExtension = name.replace(/\\.(ts|js)$/, '');\n\n // Imported only when it runs: a migration already applied is never loaded\n const load = (): Promise<{\n up: (context: unknown) => Promise<unknown>;\n down: (context: unknown) => Promise<unknown>;\n }> => import(path || '');\n return {\n name: nameWithoutExtension,\n up: async () => {\n const migration = await load();\n return migration.up(context);\n },\n down: async () => {\n const migration = await load();\n return migration.down(context);\n }\n };\n }\n },\n context: sequelize.getQueryInterface(),\n storage: new SequelizeStorage({ sequelize }),\n logger: console\n });\n\n reportDebug({\n namespace,\n message: `Rolling back migrations up to: ${rollbackUntil.name}`,\n data: { path }\n });\n\n await migrator.down({ to: rollbackUntil.name });\n }\n}\n\n/**\n * Recreate the whole database\n * Quick way to make sure that we are working on a clean database\n * /!\\ Should only be used when running tests\n */\nexport async function testRecreateDB(\n options: RecreateDbOptions = {}\n): Promise<void> {\n if (!sequelize)\n throw new EngineError({ message: 'Sequelize is not initialized' });\n await sequelize.query(\n `DROP SCHEMA public${sequelize.getDialect() === 'postgres' ? ' CASCADE' : ''}`\n );\n await sequelize.query(`CREATE SCHEMA public`);\n if (!options.clean) await runPendingMigrations();\n}\n\n/**\n * Empty all the schemas in the database\n * Quick way to flush the database data while keep the structure\n * /!\\ Should only be used when running tests\n */\nexport async function testClearDB(options: ClearDbOptions = {}): Promise<void> {\n if (!sequelize)\n throw new EngineError({ message: 'Sequelize is not initialized' });\n await sequelize.transaction(clearDbTransaction(sequelize, options));\n}\n\n/** DB clearing transaction */\nfunction clearDbTransaction(sequelize: Sequelize, options: ClearDbOptions) {\n return async (t: Transaction): Promise<void> => {\n for (const model of Object.keys(sequelize.models)) {\n // We ignore the migration metadata schema\n if (!options.includeMetadata && model === 'sequelizeMeta') continue;\n const table = sequelize.models[model].tableName;\n await sequelize.query(\n `TRUNCATE ${table}${sequelize.getDialect() === 'postgres' ? ' CASCADE' : ''};`,\n {\n raw: true,\n transaction: t\n }\n );\n }\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -41,12 +41,15 @@ async function migrateMetadataTable(sequelize) {
|
|
|
41
41
|
namespace,
|
|
42
42
|
message: 'Executing metadata migration routine'
|
|
43
43
|
});
|
|
44
|
-
|
|
44
|
+
|
|
45
|
+
// The dialect actually connected (tests use SQLite whatever SQL_TYPE says)
|
|
46
|
+
const sqlType = sequelize.getDialect();
|
|
47
|
+
const query = listTablesQuery(sqlType);
|
|
45
48
|
(0, _report.reportDebug)({
|
|
46
49
|
namespace,
|
|
47
50
|
message: 'Checking for existing metadata tables',
|
|
48
51
|
data: {
|
|
49
|
-
sqlType:
|
|
52
|
+
sqlType: sqlType
|
|
50
53
|
}
|
|
51
54
|
});
|
|
52
55
|
|
|
@@ -65,7 +68,7 @@ async function migrateMetadataTable(sequelize) {
|
|
|
65
68
|
|
|
66
69
|
// Define SQL for creating the table based on the database type
|
|
67
70
|
let createTableQuery = '';
|
|
68
|
-
switch (
|
|
71
|
+
switch (sqlType) {
|
|
69
72
|
case 'mysql':
|
|
70
73
|
case 'postgres':
|
|
71
74
|
case 'sqlite':
|
|
@@ -95,7 +98,7 @@ async function migrateMetadataTable(sequelize) {
|
|
|
95
98
|
namespace,
|
|
96
99
|
message: 'Creating sequelize_meta table',
|
|
97
100
|
data: {
|
|
98
|
-
sqlType:
|
|
101
|
+
sqlType: sqlType
|
|
99
102
|
}
|
|
100
103
|
});
|
|
101
104
|
await sequelize.query(createTableQuery, {
|
|
@@ -118,7 +121,7 @@ async function migrateMetadataTable(sequelize) {
|
|
|
118
121
|
const insertQuery = `
|
|
119
122
|
INSERT INTO sequelize_meta (name, version, createdAt, updatedAt) VALUES
|
|
120
123
|
${migrations.map(migration => {
|
|
121
|
-
switch (
|
|
124
|
+
switch (sqlType) {
|
|
122
125
|
case 'mysql':
|
|
123
126
|
case 'postgres':
|
|
124
127
|
return `('${migration.name}', NULL, NOW(), NOW())`;
|
|
@@ -143,7 +146,7 @@ async function migrateMetadataTable(sequelize) {
|
|
|
143
146
|
data: {
|
|
144
147
|
error: error instanceof Error ? error.message : String(error),
|
|
145
148
|
stack: error instanceof Error ? error.stack : undefined,
|
|
146
|
-
sqlType:
|
|
149
|
+
sqlType: sequelize.getDialect(),
|
|
147
150
|
sqlHost: process.env.SQL_HOST
|
|
148
151
|
}
|
|
149
152
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrateMetadataTable.js","names":["_sequelize","require","_report","namespace","listTablesQuery","sqlType","getTableName","row","Array","isArray","Object","values","undefined","migrateMetadataTable","sequelize","reportDebug","message","
|
|
1
|
+
{"version":3,"file":"migrateMetadataTable.js","names":["_sequelize","require","_report","namespace","listTablesQuery","sqlType","getTableName","row","Array","isArray","Object","values","undefined","migrateMetadataTable","sequelize","reportDebug","message","getDialect","query","data","tables","type","QueryTypes","SELECT","tableNames","map","hasCustomSequelizeMeta","includes","hasLegacySequelizeMeta","createTableQuery","Error","RAW","migrations","insertQuery","migration","name","join","INSERT","error","reportError","String","stack","sqlHost","process","env","SQL_HOST"],"sources":["../../../../src/utils/dbMigration/migrateMetadataTable/migrateMetadataTable.ts"],"sourcesContent":["import { Sequelize, QueryTypes } from 'sequelize';\nimport { SequelizeMeta } from 'db/models';\nimport { reportDebug, reportError } from 'utils/report';\n\nconst namespace = 'engine:utils:dbMigration';\n\n/** List the tables of the current database (not of every database on the server) */\nfunction listTablesQuery(sqlType?: string): string {\n switch (sqlType) {\n case 'sqlite':\n return `SELECT name AS table_name FROM sqlite_master WHERE type = 'table'`;\n case 'mysql':\n return `SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE()`;\n case 'postgres':\n return `SELECT table_name FROM information_schema.tables WHERE table_schema = current_schema()`;\n default:\n return `SELECT table_name FROM information_schema.tables`;\n }\n}\n\n/** Extract the table name from a result row, whatever shape the driver returns */\nfunction getTableName(row: unknown): string | undefined {\n if (typeof row === 'string') return row;\n if (Array.isArray(row)) return getTableName(row[0]);\n if (row && typeof row === 'object')\n return getTableName(Object.values(row)[0]);\n return undefined;\n}\n\n/**\n * Run migrations on the metadata table\n * The table containing the migrations metadata cannot be handled through migrations\n * Therefore, we use a more classic approach with this function and pure SQL queries\n */\nexport async function migrateMetadataTable(\n sequelize: Sequelize\n): Promise<void> {\n try {\n reportDebug({ namespace, message: 'Executing metadata migration routine' });\n\n // The dialect actually connected (tests use SQLite whatever SQL_TYPE says)\n const sqlType = sequelize.getDialect();\n const query = listTablesQuery(sqlType);\n\n reportDebug({\n namespace,\n message: 'Checking for existing metadata tables',\n data: { sqlType: sqlType }\n });\n\n // We check if we have a custom sequelize_meta table yet\n const tables = await sequelize.query<Record<string, unknown>>(query, {\n type: QueryTypes.SELECT\n });\n const tableNames = tables.map(getTableName);\n\n const hasCustomSequelizeMeta = tableNames.includes('sequelize_meta');\n const hasLegacySequelizeMeta = tableNames.includes('SequelizeMeta');\n if (!hasCustomSequelizeMeta) {\n reportDebug({\n namespace,\n message: 'No metadata table found, creating new one'\n });\n\n // Define SQL for creating the table based on the database type\n let createTableQuery = '';\n\n switch (sqlType) {\n case 'mysql':\n case 'postgres':\n case 'sqlite':\n createTableQuery = `\n CREATE TABLE sequelize_meta (\n name VARCHAR(100) PRIMARY KEY,\n version VARCHAR(25),\n createdAt TIMESTAMP NOT NULL,\n updatedAt TIMESTAMP NOT NULL\n )`;\n break;\n case 'mssql':\n createTableQuery = `\n CREATE TABLE sequelize_meta (\n name VARCHAR(100) PRIMARY KEY,\n version VARCHAR(25),\n createdAt DATETIME NOT NULL,\n updatedAt DATETIME NOT NULL\n )`;\n break;\n default:\n throw new Error('Unsupported SQL type');\n }\n\n // Create the new sequelize_meta table if it does not exist\n reportDebug({\n namespace,\n message: 'Creating sequelize_meta table',\n data: { sqlType: sqlType }\n });\n await sequelize.query(createTableQuery, { type: QueryTypes.RAW });\n reportDebug({\n namespace,\n message: 'sequelize_meta table created successfully'\n });\n\n // Migrate the data from the old table to the new one if needed\n if (hasLegacySequelizeMeta) {\n reportDebug({\n namespace,\n message: 'Legacy metadata table found, migrating data'\n });\n\n const migrations = await sequelize.query<SequelizeMeta>(\n 'SELECT name FROM SequelizeMeta ORDER BY name',\n {\n type: QueryTypes.SELECT\n }\n );\n\n const insertQuery = `\n INSERT INTO sequelize_meta (name, version, createdAt, updatedAt) VALUES\n ${migrations\n .map((migration) => {\n switch (sqlType) {\n case 'mysql':\n case 'postgres':\n return `('${migration.name}', NULL, NOW(), NOW())`;\n case 'sqlite':\n return `('${migration.name}', NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`;\n case 'mssql':\n return `('${migration.name}', NULL, GETDATE(), GETDATE())`;\n default:\n throw new Error('Unsupported SQL type');\n }\n })\n .join(',')}\n `;\n\n await sequelize.query(insertQuery, { type: QueryTypes.INSERT });\n }\n }\n } catch (error) {\n reportError({\n namespace,\n message: 'Error in metadata migration',\n data: {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n sqlType: sequelize.getDialect(),\n sqlHost: process.env.SQL_HOST\n }\n });\n throw error;\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-server-engine",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"description": "Framework used to develop backend services. This package ships with a lot of features to standardize the creation of services, letting you focus on the business logic.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|