@fluidware-it/mysql2-client 0.4.0 → 0.6.0

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.
@@ -1,4 +1,5 @@
1
1
  import { ConnectionOptions } from 'mysql2';
2
2
  export declare const USE_READ_COMMITTED_ISOLATION: boolean;
3
3
  export declare function getMysqlConnectionOptions(prefix?: string): ConnectionOptions;
4
+ export declare function setMysqlConnectionOptions(prefix: string, options: ConnectionOptions): void;
4
5
  //# sourceMappingURL=config.d.ts.map
@@ -35,6 +35,7 @@ export function getMysqlConnectionOptions(prefix) {
35
35
  var DB_HOST = EnvParse.envString("FW_".concat(prefix, "DB_HOST"), 'localhost');
36
36
  var DB_PORT = EnvParse.envInt("FW_".concat(prefix, "DB_PORT"), 3306);
37
37
  var DB_NAME = EnvParse.envString("FW_".concat(prefix, "DB_NAME"), DB_USER);
38
+ // FW_${prefix}DB_CONN_OPTIONS: JSON string with connection options See https://github.com/mysqljs/mysql#connection-options for all possible options
38
39
  var DB_CONN_OPTIONS = EnvParse.envJSON("FW_".concat(prefix, "DB_CONN_OPTIONS"), {});
39
40
  var dbPassword = getDbPassword(DB_PASSWORD_FILE, DB_PASSWORD);
40
41
  var dbOptions = {
@@ -45,11 +46,13 @@ export function getMysqlConnectionOptions(prefix) {
45
46
  database: DB_NAME
46
47
  };
47
48
  if (Object.keys(DB_CONN_OPTIONS).length > 0) {
48
- // See https://github.com/mysqljs/mysql#connection-options for all possible options
49
49
  Object.assign(dbOptions, DB_CONN_OPTIONS);
50
50
  }
51
51
  memoizedOptions[prefix] = dbOptions;
52
52
  }
53
53
  return memoizedOptions[prefix];
54
54
  }
55
+ export function setMysqlConnectionOptions(prefix, options) {
56
+ memoizedOptions[prefix] = options;
57
+ }
55
58
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAGzB,MAAM,CAAC,IAAM,4BAA4B,GAAG,QAAQ,CAAC,OAAO,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;AAE1G,SAAS,aAAa,CAAC,gBAAwB,EAAE,WAAmB;IAClE,IAAI,gBAAgB,EAAE;QACpB,OAAO,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;KAClD;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,IAAM,eAAe,GAA4C,EAAE,CAAC;AAEpE,MAAM,UAAU,yBAAyB,CAAC,MAAW;IAAX,uBAAA,EAAA,WAAW;IACnD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;QAC5B,IAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,aAAM,MAAM,gBAAa,EAAE,EAAE,CAAC,CAAC;QACtE,IAAM,gBAAgB,GAAG,QAAQ,CAAC,SAAS,CAAC,aAAM,MAAM,qBAAkB,EAAE,EAAE,CAAC,CAAC;QAEhF,IAAI,CAAC,WAAW,IAAI,CAAC,gBAAgB,EAAE;YACrC,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;SAC1E;QAED,IAAM,OAAO,GAAG,QAAQ,CAAC,iBAAiB,CAAC,aAAM,MAAM,YAAS,CAAC,CAAC;QAClE,IAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,aAAM,MAAM,YAAS,EAAE,WAAW,CAAC,CAAC;QACvE,IAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,aAAM,MAAM,YAAS,EAAE,IAAI,CAAC,CAAC;QAC7D,IAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,aAAM,MAAM,YAAS,EAAE,OAAO,CAAC,CAAC;QACnE,IAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,aAAM,MAAM,oBAAiB,EAAE,EAAE,CAAC,CAAC;QAE5E,IAAM,UAAU,GAAG,aAAa,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;QAChE,IAAM,SAAS,GAAG;YAChB,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,OAAO;SAClB,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YAC3C,mFAAmF;YACnF,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;SAC3C;QACD,eAAe,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;KACrC;IACD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EnvParse } from '@fluidware-it/saddlebag';\nimport * as fs from 'fs';\nimport { ConnectionOptions } from 'mysql2';\n\nexport const USE_READ_COMMITTED_ISOLATION = EnvParse.envBool('FW_DB_USE_READ_COMMITTED_ISOLATION', false);\n\nfunction getDbPassword(DB_PASSWORD_FILE: string, DB_PASSWORD: string): string {\n if (DB_PASSWORD_FILE) {\n return fs.readFileSync(DB_PASSWORD_FILE, 'utf8');\n }\n return DB_PASSWORD;\n}\n\nconst memoizedOptions: { [prefix: string]: ConnectionOptions } = {};\n\nexport function getMysqlConnectionOptions(prefix = ''): ConnectionOptions {\n if (!memoizedOptions[prefix]) {\n const DB_PASSWORD = EnvParse.envString(`FW_${prefix}DB_PASSWORD`, '');\n const DB_PASSWORD_FILE = EnvParse.envString(`FW_${prefix}DB_PASSWORD_FILE`, '');\n\n if (!DB_PASSWORD && !DB_PASSWORD_FILE) {\n throw new Error('FW_DB_PASSWORD or FW_DB_PASSWORD_FILE env is required');\n }\n\n const DB_USER = EnvParse.envStringRequired(`FW_${prefix}DB_USER`);\n const DB_HOST = EnvParse.envString(`FW_${prefix}DB_HOST`, 'localhost');\n const DB_PORT = EnvParse.envInt(`FW_${prefix}DB_PORT`, 3306);\n const DB_NAME = EnvParse.envString(`FW_${prefix}DB_NAME`, DB_USER);\n const DB_CONN_OPTIONS = EnvParse.envJSON(`FW_${prefix}DB_CONN_OPTIONS`, {});\n\n const dbPassword = getDbPassword(DB_PASSWORD_FILE, DB_PASSWORD);\n const dbOptions = {\n host: DB_HOST,\n port: DB_PORT,\n user: DB_USER,\n password: dbPassword,\n database: DB_NAME\n };\n if (Object.keys(DB_CONN_OPTIONS).length > 0) {\n // See https://github.com/mysqljs/mysql#connection-options for all possible options\n Object.assign(dbOptions, DB_CONN_OPTIONS);\n }\n memoizedOptions[prefix] = dbOptions;\n }\n return memoizedOptions[prefix];\n}\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAGzB,MAAM,CAAC,IAAM,4BAA4B,GAAG,QAAQ,CAAC,OAAO,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;AAE1G,SAAS,aAAa,CAAC,gBAAwB,EAAE,WAAmB;IAClE,IAAI,gBAAgB,EAAE;QACpB,OAAO,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;KAClD;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,IAAM,eAAe,GAA4C,EAAE,CAAC;AAEpE,MAAM,UAAU,yBAAyB,CAAC,MAAW;IAAX,uBAAA,EAAA,WAAW;IACnD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;QAC5B,IAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,aAAM,MAAM,gBAAa,EAAE,EAAE,CAAC,CAAC;QACtE,IAAM,gBAAgB,GAAG,QAAQ,CAAC,SAAS,CAAC,aAAM,MAAM,qBAAkB,EAAE,EAAE,CAAC,CAAC;QAEhF,IAAI,CAAC,WAAW,IAAI,CAAC,gBAAgB,EAAE;YACrC,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;SAC1E;QAED,IAAM,OAAO,GAAG,QAAQ,CAAC,iBAAiB,CAAC,aAAM,MAAM,YAAS,CAAC,CAAC;QAClE,IAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,aAAM,MAAM,YAAS,EAAE,WAAW,CAAC,CAAC;QACvE,IAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,aAAM,MAAM,YAAS,EAAE,IAAI,CAAC,CAAC;QAC7D,IAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,aAAM,MAAM,YAAS,EAAE,OAAO,CAAC,CAAC;QACnE,oJAAoJ;QACpJ,IAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,aAAM,MAAM,oBAAiB,EAAE,EAAE,CAAC,CAAC;QAE5E,IAAM,UAAU,GAAG,aAAa,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;QAChE,IAAM,SAAS,GAAG;YAChB,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,OAAO;SAClB,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YAC3C,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;SAC3C;QACD,eAAe,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;KACrC;IACD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAc,EAAE,OAA0B;IAClF,eAAe,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;AACpC,CAAC","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EnvParse } from '@fluidware-it/saddlebag';\nimport * as fs from 'fs';\nimport { ConnectionOptions } from 'mysql2';\n\nexport const USE_READ_COMMITTED_ISOLATION = EnvParse.envBool('FW_DB_USE_READ_COMMITTED_ISOLATION', false);\n\nfunction getDbPassword(DB_PASSWORD_FILE: string, DB_PASSWORD: string): string {\n if (DB_PASSWORD_FILE) {\n return fs.readFileSync(DB_PASSWORD_FILE, 'utf8');\n }\n return DB_PASSWORD;\n}\n\nconst memoizedOptions: { [prefix: string]: ConnectionOptions } = {};\n\nexport function getMysqlConnectionOptions(prefix = ''): ConnectionOptions {\n if (!memoizedOptions[prefix]) {\n const DB_PASSWORD = EnvParse.envString(`FW_${prefix}DB_PASSWORD`, '');\n const DB_PASSWORD_FILE = EnvParse.envString(`FW_${prefix}DB_PASSWORD_FILE`, '');\n\n if (!DB_PASSWORD && !DB_PASSWORD_FILE) {\n throw new Error('FW_DB_PASSWORD or FW_DB_PASSWORD_FILE env is required');\n }\n\n const DB_USER = EnvParse.envStringRequired(`FW_${prefix}DB_USER`);\n const DB_HOST = EnvParse.envString(`FW_${prefix}DB_HOST`, 'localhost');\n const DB_PORT = EnvParse.envInt(`FW_${prefix}DB_PORT`, 3306);\n const DB_NAME = EnvParse.envString(`FW_${prefix}DB_NAME`, DB_USER);\n // FW_${prefix}DB_CONN_OPTIONS: JSON string with connection options See https://github.com/mysqljs/mysql#connection-options for all possible options\n const DB_CONN_OPTIONS = EnvParse.envJSON(`FW_${prefix}DB_CONN_OPTIONS`, {});\n\n const dbPassword = getDbPassword(DB_PASSWORD_FILE, DB_PASSWORD);\n const dbOptions = {\n host: DB_HOST,\n port: DB_PORT,\n user: DB_USER,\n password: dbPassword,\n database: DB_NAME\n };\n if (Object.keys(DB_CONN_OPTIONS).length > 0) {\n Object.assign(dbOptions, DB_CONN_OPTIONS);\n }\n memoizedOptions[prefix] = dbOptions;\n }\n return memoizedOptions[prefix];\n}\n\nexport function setMysqlConnectionOptions(prefix: string, options: ConnectionOptions) {\n memoizedOptions[prefix] = options;\n}\n"]}
@@ -8,7 +8,7 @@ interface ConnectionWrap extends Connection {
8
8
  }
9
9
  export declare class DbClient {
10
10
  private connection?;
11
- private connectionOptions;
11
+ private readonly connectionOptions;
12
12
  constructor(connectionOptionsOrPrefix?: ConnectionOptions | string);
13
13
  open(): Promise<void>;
14
14
  getConnection(): ConnectionWrap | undefined;
@@ -17,9 +17,9 @@ export declare class DbClient {
17
17
  commit(closeTransaction?: boolean): Promise<void>;
18
18
  rollback(closeTransaction?: boolean): Promise<void>;
19
19
  all(sql: string, phs?: (string | number | boolean | null)[]): Promise<RowDataPacket[]>;
20
- get(sql: string, phs?: (string | number | boolean | null)[]): Promise<RowDataPacket>;
20
+ get(sql: string, phs?: (string | number | boolean | null)[]): Promise<RowDataPacket | null>;
21
21
  insert(sql: string, phs?: (string | number | boolean | null)[]): Promise<number>;
22
- update(sql: string, phs?: (string | number | boolean | null)[]): Promise<number>;
22
+ update(sql: string, phs?: (string | number | boolean | null)[], returnChangedRows?: boolean): Promise<number>;
23
23
  delete(sql: string, phs?: (string | number | boolean | null)[]): Promise<number>;
24
24
  run(sql: string, phs?: (string | number | boolean | null)[]): Promise<[import("mysql2/typings/mysql/lib/protocol/packets/OkPacket").OkPacket | RowDataPacket[] | ProcedureCallPacket | ResultSetHeader[] | RowDataPacket[][] | import("mysql2/typings/mysql/lib/protocol/packets/OkPacket").OkPacket[], FieldPacket[]]>;
25
25
  }
@@ -228,8 +228,10 @@ var DbClient = /** @class */ (function () {
228
228
  case 1:
229
229
  res = _a.sent();
230
230
  if (res.rows.length > 1)
231
- throw new Error('get returned more than one row');
232
- return [2 /*return*/, res.rows[0]];
231
+ throw new Error('get() returned more than one row');
232
+ if (res.rows.length === 1)
233
+ return [2 /*return*/, res.rows[0]];
234
+ return [2 /*return*/, null];
233
235
  }
234
236
  });
235
237
  });
@@ -251,7 +253,8 @@ var DbClient = /** @class */ (function () {
251
253
  });
252
254
  });
253
255
  };
254
- DbClient.prototype.update = function (sql, phs) {
256
+ DbClient.prototype.update = function (sql, phs, returnChangedRows) {
257
+ if (returnChangedRows === void 0) { returnChangedRows = false; }
255
258
  return __awaiter(this, void 0, void 0, function () {
256
259
  var res;
257
260
  return __generator(this, function (_a) {
@@ -263,7 +266,7 @@ var DbClient = /** @class */ (function () {
263
266
  return [4 /*yield*/, this.connection.run(sql, phs)];
264
267
  case 1:
265
268
  res = _a.sent();
266
- return [2 /*return*/, res.rows.affectedRows];
269
+ return [2 /*return*/, returnChangedRows ? res.rows.changedRows : res.rows.affectedRows];
267
270
  }
268
271
  });
269
272
  });
@@ -1 +1 @@
1
- {"version":3,"file":"dbClient.js","sourceRoot":"","sources":["../../src/dbClient.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createConnection,\n Connection,\n RowDataPacket,\n ResultSetHeader,\n ProcedureCallPacket,\n FieldPacket\n} from 'mysql2/promise';\nimport { getMysqlConnectionOptions, USE_READ_COMMITTED_ISOLATION } from './config';\nimport { ConnectionOptions } from 'mysql2';\n\ninterface ConnectionWrap extends Connection {\n run<T extends ResultSetHeader | ResultSetHeader[] | RowDataPacket[] | RowDataPacket[][] | ProcedureCallPacket>(\n sql: string,\n phs?: (string | number | boolean | null)[]\n ): Promise<{\n rows: T;\n cols: FieldPacket[];\n }>;\n}\n\nexport class DbClient {\n private connection?: ConnectionWrap;\n private connectionOptions: ConnectionOptions;\n\n constructor(connectionOptionsOrPrefix?: ConnectionOptions | string) {\n if (connectionOptionsOrPrefix) {\n if (typeof connectionOptionsOrPrefix === 'string') {\n this.connectionOptions = getMysqlConnectionOptions(connectionOptionsOrPrefix);\n } else {\n this.connectionOptions = connectionOptionsOrPrefix;\n }\n } else {\n this.connectionOptions = getMysqlConnectionOptions('');\n }\n }\n\n async open() {\n this.connection = (await createConnection(this.connectionOptions)) as ConnectionWrap;\n this.connection.run = async <\n T extends ResultSetHeader | ResultSetHeader[] | RowDataPacket[] | RowDataPacket[][] | ProcedureCallPacket\n >(\n sql: string,\n phs?: (string | number | boolean | null)[]\n ): Promise<{ rows: T; cols: FieldPacket[] }> => {\n if (!this.connection) {\n throw new Error('run() called but no connection available');\n }\n const [rows, cols] = await this.connection.execute<T>(sql, phs);\n return {\n rows,\n cols\n };\n };\n }\n\n getConnection(): ConnectionWrap | undefined {\n return this.connection;\n }\n\n async close() {\n if (this.connection) {\n await this.connection.end();\n }\n }\n\n async startTransaction() {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n if (USE_READ_COMMITTED_ISOLATION) {\n await this.connection.execute(\"SET SESSION tx_isolation='read-committed'\");\n }\n await this.connection.execute('SET AUTOCOMMIT=0');\n }\n\n async commit(closeTransaction = true) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n await this.connection.execute('COMMIT');\n if (closeTransaction) {\n await this.connection.execute('SET AUTOCOMMIT=1');\n }\n }\n\n async rollback(closeTransaction = true) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n\n await this.connection.execute('ROLLBACK');\n if (closeTransaction) {\n await this.connection.execute('SET AUTOCOMMIT=1');\n }\n }\n\n async all(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<RowDataPacket[]>(sql, phs);\n return res.rows;\n }\n\n async get(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<RowDataPacket[]>(sql, phs);\n if (res.rows.length > 1) throw new Error('get returned more than one row');\n return res.rows[0];\n }\n\n async insert(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.insertId || res.rows.affectedRows;\n }\n\n async update(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.affectedRows;\n }\n\n async delete(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.affectedRows;\n }\n\n async run(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n return this.connection.execute(sql, phs);\n }\n}\n"]}
1
+ {"version":3,"file":"dbClient.js","sourceRoot":"","sources":["../../src/dbClient.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createConnection,\n Connection,\n RowDataPacket,\n ResultSetHeader,\n ProcedureCallPacket,\n FieldPacket\n} from 'mysql2/promise';\nimport { getMysqlConnectionOptions, USE_READ_COMMITTED_ISOLATION } from './config';\nimport { ConnectionOptions } from 'mysql2';\n\ninterface ConnectionWrap extends Connection {\n run<T extends ResultSetHeader | ResultSetHeader[] | RowDataPacket[] | RowDataPacket[][] | ProcedureCallPacket>(\n sql: string,\n phs?: (string | number | boolean | null)[]\n ): Promise<{\n rows: T;\n cols: FieldPacket[];\n }>;\n}\n\nexport class DbClient {\n private connection?: ConnectionWrap;\n private readonly connectionOptions: ConnectionOptions;\n\n constructor(connectionOptionsOrPrefix?: ConnectionOptions | string) {\n if (connectionOptionsOrPrefix) {\n if (typeof connectionOptionsOrPrefix === 'string') {\n this.connectionOptions = getMysqlConnectionOptions(connectionOptionsOrPrefix);\n } else {\n this.connectionOptions = connectionOptionsOrPrefix;\n }\n } else {\n this.connectionOptions = getMysqlConnectionOptions('');\n }\n }\n\n async open() {\n this.connection = (await createConnection(this.connectionOptions)) as ConnectionWrap;\n this.connection.run = async <\n T extends ResultSetHeader | ResultSetHeader[] | RowDataPacket[] | RowDataPacket[][] | ProcedureCallPacket\n >(\n sql: string,\n phs?: (string | number | boolean | null)[]\n ): Promise<{ rows: T; cols: FieldPacket[] }> => {\n if (!this.connection) {\n throw new Error('run() called but no connection available');\n }\n const [rows, cols] = await this.connection.execute<T>(sql, phs);\n return {\n rows,\n cols\n };\n };\n }\n\n getConnection(): ConnectionWrap | undefined {\n return this.connection;\n }\n\n async close() {\n if (this.connection) {\n await this.connection.end();\n }\n }\n\n async startTransaction() {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n if (USE_READ_COMMITTED_ISOLATION) {\n await this.connection.execute(\"SET SESSION tx_isolation='read-committed'\");\n }\n await this.connection.execute('SET AUTOCOMMIT=0');\n }\n\n async commit(closeTransaction = true) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n await this.connection.execute('COMMIT');\n if (closeTransaction) {\n await this.connection.execute('SET AUTOCOMMIT=1');\n }\n }\n\n async rollback(closeTransaction = true) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n\n await this.connection.execute('ROLLBACK');\n if (closeTransaction) {\n await this.connection.execute('SET AUTOCOMMIT=1');\n }\n }\n\n async all(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<RowDataPacket[]>(sql, phs);\n return res.rows;\n }\n\n async get(sql: string, phs?: (string | number | boolean | null)[]): Promise<RowDataPacket | null> {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<RowDataPacket[]>(sql, phs);\n if (res.rows.length > 1) throw new Error('get() returned more than one row');\n if (res.rows.length === 1) return res.rows[0];\n return null;\n }\n\n async insert(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.insertId || res.rows.affectedRows;\n }\n\n async update(sql: string, phs?: (string | number | boolean | null)[], returnChangedRows = false) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return returnChangedRows ? res.rows.changedRows : res.rows.affectedRows;\n }\n\n async delete(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.affectedRows;\n }\n\n async run(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n return this.connection.execute(sql, phs);\n }\n}\n"]}
@@ -182,6 +182,9 @@ var UpgradeManager = /** @class */ (function () {
182
182
  return [4 /*yield*/, this.client.get(sqlCheck)];
183
183
  case 3:
184
184
  row = _a.sent();
185
+ if (!row) {
186
+ return [2 /*return*/, false];
187
+ }
185
188
  this.logger.debug('Versions: %s vs %s', row.value, targetVersion);
186
189
  if (!(row.value === targetVersion)) return [3 /*break*/, 5];
187
190
  this.logger.debug('versions are equal, rollback');
@@ -1 +1 @@
1
- {"version":3,"file":"upgradeManager.js","sourceRoot":"","sources":["../../src/upgradeManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { setTimeout } from 'node:timers/promises';\nimport { getLogger } from '@fluidware-it/saddlebag';\nimport { DbClient } from './dbClient';\nimport { Logger } from 'pino';\n\nexport type UpgradeManagerConfig = {\n version_table_suffix?: string;\n};\n\nexport class UpgradeManager {\n private version_table: string;\n private client: DbClient;\n private logger: Logger;\n private _default_version_table = '_version';\n\n constructor(opts?: UpgradeManagerConfig) {\n this.version_table = this._default_version_table + (opts?.version_table_suffix || '');\n this.logger = getLogger().child({ component: 'mysql-migrator' });\n this.client = new DbClient();\n }\n\n private async loadCurrentVersion(targetVersion: number) {\n try {\n const row = await this.getCurrentVersion(targetVersion);\n if (row === false) {\n return -999;\n } else if (row === true) {\n this.logger.info('Check db: same version %s', targetVersion);\n await this.client.close();\n return true;\n } else if (row) {\n return row.value;\n }\n } catch (e) {\n this.logger.error(`Failed to read current version: ${e.message}`);\n throw e;\n }\n }\n\n private async createDb() {\n try {\n return this.createVersionTable();\n } catch (e) {\n if (e.code === '23505') {\n await this.client.close();\n await setTimeout(2000);\n return -1;\n } else {\n this.logger.error(`Unable to create ${this.version_table} table: [${e.code}] ${e.message}`);\n throw e;\n }\n }\n }\n\n private async _checkDb(\n currentVersion: number,\n targetVersion: number,\n onSchemaInit: (dbClient: DbClient) => Promise<void>,\n onSchemaUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n try {\n if (currentVersion === 0) {\n await this.initDb(targetVersion, onSchemaInit);\n this.logger.info('Db created');\n return true;\n }\n if (targetVersion === currentVersion) {\n return true;\n }\n if (targetVersion > currentVersion) {\n await this.upgradeDb(currentVersion, targetVersion, onSchemaUpgrade);\n this.logger.info('Db updated to ', targetVersion);\n return true;\n }\n } catch (e) {\n this.logger.error('\\n');\n this.logger.error('\\n');\n this.logger.error(' !!!!!!!! FATAL ERROR !!!!!!!!');\n this.logger.error('\\n');\n this.logger.error('checkDb failed %s', e.message);\n this.logger.error('\\n');\n this.logger.error(' !!!!!!!! FATAL ERROR !!!!!!!!');\n this.logger.error('\\n');\n this.logger.error('\\n');\n this.logger.error(e.stack);\n throw e;\n } finally {\n await this.client.close();\n }\n return true;\n }\n\n private async getCurrentVersion(targetVersion: number) {\n const sqlCheck = `select value from ${this.version_table} for update`;\n await this.client.startTransaction();\n let row;\n try {\n row = await this.client.get(sqlCheck);\n this.logger.debug('Versions: %s vs %s', row.value, targetVersion);\n if (row.value === targetVersion) {\n this.logger.debug('versions are equal, rollback');\n await this.client.rollback();\n return true;\n }\n return row;\n } catch (e) {\n await this.client.rollback();\n if (e.code === 'ER_NO_SUCH_TABLE') {\n return false;\n }\n this.logger.error('Ooops: %s', e.message, e.code);\n throw e;\n }\n }\n\n private async createVersionTable() {\n const sqlCreateTable = `create table ${this.version_table} (value INTEGER PRIMARY KEY)`;\n try {\n await this.client.run(sqlCreateTable);\n } catch (e) {\n await this.client.rollback();\n throw e;\n }\n try {\n const sqlInsertVersionZero = `insert into ${this.version_table} values (-1)`;\n await this.client.insert(sqlInsertVersionZero);\n await this.client.get(`select value from ${this.version_table} for update`);\n } catch (e) {\n this.logger.error('Unable to insert -1 version in %s table: [%s] %s', this.version_table, e.code, e.message);\n throw e;\n }\n return 0;\n }\n\n private async updateVersion(targetVersion: number) {\n const sql = `update ${this.version_table} set value = ?`;\n await this.client.update(sql, [targetVersion]);\n await this.client.commit();\n }\n\n private async initDb(targetVersion: number, onInit: (dbClient: DbClient) => Promise<void>) {\n const dbConn = new DbClient();\n try {\n await dbConn.open();\n await onInit(dbConn);\n await this.updateVersion(targetVersion);\n } finally {\n if (dbConn) {\n await dbConn.close();\n }\n }\n }\n\n private async upgradeDb(\n fromVersion: number,\n targetVersion: number,\n onUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n await onUpgrade(this.client, fromVersion);\n await this.updateVersion(targetVersion);\n }\n\n async checkDb(\n targetVersion: number,\n onSchemaInit: (dbClient: DbClient) => Promise<void>,\n onSchemaUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n await this.client.open();\n let currentVersion = await this.loadCurrentVersion(targetVersion);\n if (currentVersion === true) {\n return true;\n }\n this.logger.info('Check db: currentVersion %s targetVersion %s', currentVersion, targetVersion);\n\n if (currentVersion === -999) {\n currentVersion = await this.createDb();\n if (currentVersion < 0) {\n await this.checkDb(targetVersion, onSchemaInit, onSchemaUpgrade);\n return;\n }\n } else if (currentVersion < 0) {\n this.logger.error('Db in initialization, exiting ');\n throw new Error('Db in initialization, do not proceed');\n }\n return this._checkDb(currentVersion, targetVersion, onSchemaInit, onSchemaUpgrade);\n }\n}\n"]}
1
+ {"version":3,"file":"upgradeManager.js","sourceRoot":"","sources":["../../src/upgradeManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { setTimeout } from 'node:timers/promises';\nimport { getLogger } from '@fluidware-it/saddlebag';\nimport { DbClient } from './dbClient';\nimport { Logger } from 'pino';\n\nexport type UpgradeManagerConfig = {\n version_table_suffix?: string;\n};\n\nexport class UpgradeManager {\n private version_table: string;\n private client: DbClient;\n private logger: Logger;\n private _default_version_table = '_version';\n\n constructor(opts?: UpgradeManagerConfig) {\n this.version_table = this._default_version_table + (opts?.version_table_suffix || '');\n this.logger = getLogger().child({ component: 'mysql-migrator' });\n this.client = new DbClient();\n }\n\n private async loadCurrentVersion(targetVersion: number) {\n try {\n const row = await this.getCurrentVersion(targetVersion);\n if (row === false) {\n return -999;\n } else if (row === true) {\n this.logger.info('Check db: same version %s', targetVersion);\n await this.client.close();\n return true;\n } else if (row) {\n return row.value;\n }\n } catch (e) {\n this.logger.error(`Failed to read current version: ${e.message}`);\n throw e;\n }\n }\n\n private async createDb() {\n try {\n return this.createVersionTable();\n } catch (e) {\n if (e.code === '23505') {\n await this.client.close();\n await setTimeout(2000);\n return -1;\n } else {\n this.logger.error(`Unable to create ${this.version_table} table: [${e.code}] ${e.message}`);\n throw e;\n }\n }\n }\n\n private async _checkDb(\n currentVersion: number,\n targetVersion: number,\n onSchemaInit: (dbClient: DbClient) => Promise<void>,\n onSchemaUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n try {\n if (currentVersion === 0) {\n await this.initDb(targetVersion, onSchemaInit);\n this.logger.info('Db created');\n return true;\n }\n if (targetVersion === currentVersion) {\n return true;\n }\n if (targetVersion > currentVersion) {\n await this.upgradeDb(currentVersion, targetVersion, onSchemaUpgrade);\n this.logger.info('Db updated to ', targetVersion);\n return true;\n }\n } catch (e) {\n this.logger.error('\\n');\n this.logger.error('\\n');\n this.logger.error(' !!!!!!!! FATAL ERROR !!!!!!!!');\n this.logger.error('\\n');\n this.logger.error('checkDb failed %s', e.message);\n this.logger.error('\\n');\n this.logger.error(' !!!!!!!! FATAL ERROR !!!!!!!!');\n this.logger.error('\\n');\n this.logger.error('\\n');\n this.logger.error(e.stack);\n throw e;\n } finally {\n await this.client.close();\n }\n return true;\n }\n\n private async getCurrentVersion(targetVersion: number) {\n const sqlCheck = `select value from ${this.version_table} for update`;\n await this.client.startTransaction();\n let row;\n try {\n row = await this.client.get(sqlCheck);\n if (!row) {\n return false;\n }\n this.logger.debug('Versions: %s vs %s', row.value, targetVersion);\n if (row.value === targetVersion) {\n this.logger.debug('versions are equal, rollback');\n await this.client.rollback();\n return true;\n }\n return row;\n } catch (e) {\n await this.client.rollback();\n if (e.code === 'ER_NO_SUCH_TABLE') {\n return false;\n }\n this.logger.error('Ooops: %s', e.message, e.code);\n throw e;\n }\n }\n\n private async createVersionTable() {\n const sqlCreateTable = `create table ${this.version_table} (value INTEGER PRIMARY KEY)`;\n try {\n await this.client.run(sqlCreateTable);\n } catch (e) {\n await this.client.rollback();\n throw e;\n }\n try {\n const sqlInsertVersionZero = `insert into ${this.version_table} values (-1)`;\n await this.client.insert(sqlInsertVersionZero);\n await this.client.get(`select value from ${this.version_table} for update`);\n } catch (e) {\n this.logger.error('Unable to insert -1 version in %s table: [%s] %s', this.version_table, e.code, e.message);\n throw e;\n }\n return 0;\n }\n\n private async updateVersion(targetVersion: number) {\n const sql = `update ${this.version_table} set value = ?`;\n await this.client.update(sql, [targetVersion]);\n await this.client.commit();\n }\n\n private async initDb(targetVersion: number, onInit: (dbClient: DbClient) => Promise<void>) {\n const dbConn = new DbClient();\n try {\n await dbConn.open();\n await onInit(dbConn);\n await this.updateVersion(targetVersion);\n } finally {\n if (dbConn) {\n await dbConn.close();\n }\n }\n }\n\n private async upgradeDb(\n fromVersion: number,\n targetVersion: number,\n onUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n await onUpgrade(this.client, fromVersion);\n await this.updateVersion(targetVersion);\n }\n\n async checkDb(\n targetVersion: number,\n onSchemaInit: (dbClient: DbClient) => Promise<void>,\n onSchemaUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n await this.client.open();\n let currentVersion = await this.loadCurrentVersion(targetVersion);\n if (currentVersion === true) {\n return true;\n }\n this.logger.info('Check db: currentVersion %s targetVersion %s', currentVersion, targetVersion);\n\n if (currentVersion === -999) {\n currentVersion = await this.createDb();\n if (currentVersion < 0) {\n await this.checkDb(targetVersion, onSchemaInit, onSchemaUpgrade);\n return;\n }\n } else if (currentVersion < 0) {\n this.logger.error('Db in initialization, exiting ');\n throw new Error('Db in initialization, do not proceed');\n }\n return this._checkDb(currentVersion, targetVersion, onSchemaInit, onSchemaUpgrade);\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { ConnectionOptions } from 'mysql2';
2
2
  export declare const USE_READ_COMMITTED_ISOLATION: boolean;
3
3
  export declare function getMysqlConnectionOptions(prefix?: string): ConnectionOptions;
4
+ export declare function setMysqlConnectionOptions(prefix: string, options: ConnectionOptions): void;
4
5
  //# sourceMappingURL=config.d.ts.map
@@ -34,6 +34,7 @@ export function getMysqlConnectionOptions(prefix = '') {
34
34
  const DB_HOST = EnvParse.envString(`FW_${prefix}DB_HOST`, 'localhost');
35
35
  const DB_PORT = EnvParse.envInt(`FW_${prefix}DB_PORT`, 3306);
36
36
  const DB_NAME = EnvParse.envString(`FW_${prefix}DB_NAME`, DB_USER);
37
+ // FW_${prefix}DB_CONN_OPTIONS: JSON string with connection options See https://github.com/mysqljs/mysql#connection-options for all possible options
37
38
  const DB_CONN_OPTIONS = EnvParse.envJSON(`FW_${prefix}DB_CONN_OPTIONS`, {});
38
39
  const dbPassword = getDbPassword(DB_PASSWORD_FILE, DB_PASSWORD);
39
40
  const dbOptions = {
@@ -44,11 +45,13 @@ export function getMysqlConnectionOptions(prefix = '') {
44
45
  database: DB_NAME
45
46
  };
46
47
  if (Object.keys(DB_CONN_OPTIONS).length > 0) {
47
- // See https://github.com/mysqljs/mysql#connection-options for all possible options
48
48
  Object.assign(dbOptions, DB_CONN_OPTIONS);
49
49
  }
50
50
  memoizedOptions[prefix] = dbOptions;
51
51
  }
52
52
  return memoizedOptions[prefix];
53
53
  }
54
+ export function setMysqlConnectionOptions(prefix, options) {
55
+ memoizedOptions[prefix] = options;
56
+ }
54
57
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAGzB,MAAM,CAAC,MAAM,4BAA4B,GAAG,QAAQ,CAAC,OAAO,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;AAE1G,SAAS,aAAa,CAAC,gBAAwB,EAAE,WAAmB;IAClE,IAAI,gBAAgB,EAAE;QACpB,OAAO,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;KAClD;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,eAAe,GAA4C,EAAE,CAAC;AAEpE,MAAM,UAAU,yBAAyB,CAAC,MAAM,GAAG,EAAE;IACnD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;QAC5B,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,aAAa,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,gBAAgB,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,kBAAkB,EAAE,EAAE,CAAC,CAAC;QAEhF,IAAI,CAAC,WAAW,IAAI,CAAC,gBAAgB,EAAE;YACrC,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;SAC1E;QAED,MAAM,OAAO,GAAG,QAAQ,CAAC,iBAAiB,CAAC,MAAM,MAAM,SAAS,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,SAAS,EAAE,WAAW,CAAC,CAAC;QACvE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,MAAM,SAAS,EAAE,IAAI,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,SAAS,EAAE,OAAO,CAAC,CAAC;QACnE,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,MAAM,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAE5E,MAAM,UAAU,GAAG,aAAa,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;QAChE,MAAM,SAAS,GAAG;YAChB,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,OAAO;SAClB,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YAC3C,mFAAmF;YACnF,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;SAC3C;QACD,eAAe,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;KACrC;IACD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EnvParse } from '@fluidware-it/saddlebag';\nimport * as fs from 'fs';\nimport { ConnectionOptions } from 'mysql2';\n\nexport const USE_READ_COMMITTED_ISOLATION = EnvParse.envBool('FW_DB_USE_READ_COMMITTED_ISOLATION', false);\n\nfunction getDbPassword(DB_PASSWORD_FILE: string, DB_PASSWORD: string): string {\n if (DB_PASSWORD_FILE) {\n return fs.readFileSync(DB_PASSWORD_FILE, 'utf8');\n }\n return DB_PASSWORD;\n}\n\nconst memoizedOptions: { [prefix: string]: ConnectionOptions } = {};\n\nexport function getMysqlConnectionOptions(prefix = ''): ConnectionOptions {\n if (!memoizedOptions[prefix]) {\n const DB_PASSWORD = EnvParse.envString(`FW_${prefix}DB_PASSWORD`, '');\n const DB_PASSWORD_FILE = EnvParse.envString(`FW_${prefix}DB_PASSWORD_FILE`, '');\n\n if (!DB_PASSWORD && !DB_PASSWORD_FILE) {\n throw new Error('FW_DB_PASSWORD or FW_DB_PASSWORD_FILE env is required');\n }\n\n const DB_USER = EnvParse.envStringRequired(`FW_${prefix}DB_USER`);\n const DB_HOST = EnvParse.envString(`FW_${prefix}DB_HOST`, 'localhost');\n const DB_PORT = EnvParse.envInt(`FW_${prefix}DB_PORT`, 3306);\n const DB_NAME = EnvParse.envString(`FW_${prefix}DB_NAME`, DB_USER);\n const DB_CONN_OPTIONS = EnvParse.envJSON(`FW_${prefix}DB_CONN_OPTIONS`, {});\n\n const dbPassword = getDbPassword(DB_PASSWORD_FILE, DB_PASSWORD);\n const dbOptions = {\n host: DB_HOST,\n port: DB_PORT,\n user: DB_USER,\n password: dbPassword,\n database: DB_NAME\n };\n if (Object.keys(DB_CONN_OPTIONS).length > 0) {\n // See https://github.com/mysqljs/mysql#connection-options for all possible options\n Object.assign(dbOptions, DB_CONN_OPTIONS);\n }\n memoizedOptions[prefix] = dbOptions;\n }\n return memoizedOptions[prefix];\n}\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAGzB,MAAM,CAAC,MAAM,4BAA4B,GAAG,QAAQ,CAAC,OAAO,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;AAE1G,SAAS,aAAa,CAAC,gBAAwB,EAAE,WAAmB;IAClE,IAAI,gBAAgB,EAAE;QACpB,OAAO,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;KAClD;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,eAAe,GAA4C,EAAE,CAAC;AAEpE,MAAM,UAAU,yBAAyB,CAAC,MAAM,GAAG,EAAE;IACnD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;QAC5B,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,aAAa,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,gBAAgB,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,kBAAkB,EAAE,EAAE,CAAC,CAAC;QAEhF,IAAI,CAAC,WAAW,IAAI,CAAC,gBAAgB,EAAE;YACrC,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;SAC1E;QAED,MAAM,OAAO,GAAG,QAAQ,CAAC,iBAAiB,CAAC,MAAM,MAAM,SAAS,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,SAAS,EAAE,WAAW,CAAC,CAAC;QACvE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,MAAM,SAAS,EAAE,IAAI,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,SAAS,EAAE,OAAO,CAAC,CAAC;QACnE,oJAAoJ;QACpJ,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,MAAM,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAE5E,MAAM,UAAU,GAAG,aAAa,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;QAChE,MAAM,SAAS,GAAG;YAChB,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,OAAO;SAClB,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YAC3C,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;SAC3C;QACD,eAAe,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;KACrC;IACD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAc,EAAE,OAA0B;IAClF,eAAe,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;AACpC,CAAC","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EnvParse } from '@fluidware-it/saddlebag';\nimport * as fs from 'fs';\nimport { ConnectionOptions } from 'mysql2';\n\nexport const USE_READ_COMMITTED_ISOLATION = EnvParse.envBool('FW_DB_USE_READ_COMMITTED_ISOLATION', false);\n\nfunction getDbPassword(DB_PASSWORD_FILE: string, DB_PASSWORD: string): string {\n if (DB_PASSWORD_FILE) {\n return fs.readFileSync(DB_PASSWORD_FILE, 'utf8');\n }\n return DB_PASSWORD;\n}\n\nconst memoizedOptions: { [prefix: string]: ConnectionOptions } = {};\n\nexport function getMysqlConnectionOptions(prefix = ''): ConnectionOptions {\n if (!memoizedOptions[prefix]) {\n const DB_PASSWORD = EnvParse.envString(`FW_${prefix}DB_PASSWORD`, '');\n const DB_PASSWORD_FILE = EnvParse.envString(`FW_${prefix}DB_PASSWORD_FILE`, '');\n\n if (!DB_PASSWORD && !DB_PASSWORD_FILE) {\n throw new Error('FW_DB_PASSWORD or FW_DB_PASSWORD_FILE env is required');\n }\n\n const DB_USER = EnvParse.envStringRequired(`FW_${prefix}DB_USER`);\n const DB_HOST = EnvParse.envString(`FW_${prefix}DB_HOST`, 'localhost');\n const DB_PORT = EnvParse.envInt(`FW_${prefix}DB_PORT`, 3306);\n const DB_NAME = EnvParse.envString(`FW_${prefix}DB_NAME`, DB_USER);\n // FW_${prefix}DB_CONN_OPTIONS: JSON string with connection options See https://github.com/mysqljs/mysql#connection-options for all possible options\n const DB_CONN_OPTIONS = EnvParse.envJSON(`FW_${prefix}DB_CONN_OPTIONS`, {});\n\n const dbPassword = getDbPassword(DB_PASSWORD_FILE, DB_PASSWORD);\n const dbOptions = {\n host: DB_HOST,\n port: DB_PORT,\n user: DB_USER,\n password: dbPassword,\n database: DB_NAME\n };\n if (Object.keys(DB_CONN_OPTIONS).length > 0) {\n Object.assign(dbOptions, DB_CONN_OPTIONS);\n }\n memoizedOptions[prefix] = dbOptions;\n }\n return memoizedOptions[prefix];\n}\n\nexport function setMysqlConnectionOptions(prefix: string, options: ConnectionOptions) {\n memoizedOptions[prefix] = options;\n}\n"]}
@@ -8,7 +8,7 @@ interface ConnectionWrap extends Connection {
8
8
  }
9
9
  export declare class DbClient {
10
10
  private connection?;
11
- private connectionOptions;
11
+ private readonly connectionOptions;
12
12
  constructor(connectionOptionsOrPrefix?: ConnectionOptions | string);
13
13
  open(): Promise<void>;
14
14
  getConnection(): ConnectionWrap | undefined;
@@ -17,9 +17,9 @@ export declare class DbClient {
17
17
  commit(closeTransaction?: boolean): Promise<void>;
18
18
  rollback(closeTransaction?: boolean): Promise<void>;
19
19
  all(sql: string, phs?: (string | number | boolean | null)[]): Promise<RowDataPacket[]>;
20
- get(sql: string, phs?: (string | number | boolean | null)[]): Promise<RowDataPacket>;
20
+ get(sql: string, phs?: (string | number | boolean | null)[]): Promise<RowDataPacket | null>;
21
21
  insert(sql: string, phs?: (string | number | boolean | null)[]): Promise<number>;
22
- update(sql: string, phs?: (string | number | boolean | null)[]): Promise<number>;
22
+ update(sql: string, phs?: (string | number | boolean | null)[], returnChangedRows?: boolean): Promise<number>;
23
23
  delete(sql: string, phs?: (string | number | boolean | null)[]): Promise<number>;
24
24
  run(sql: string, phs?: (string | number | boolean | null)[]): Promise<[import("mysql2/typings/mysql/lib/protocol/packets/OkPacket").OkPacket | RowDataPacket[] | ProcedureCallPacket | ResultSetHeader[] | RowDataPacket[][] | import("mysql2/typings/mysql/lib/protocol/packets/OkPacket").OkPacket[], FieldPacket[]]>;
25
25
  }
@@ -90,8 +90,10 @@ export class DbClient {
90
90
  }
91
91
  const res = await this.connection.run(sql, phs);
92
92
  if (res.rows.length > 1)
93
- throw new Error('get returned more than one row');
94
- return res.rows[0];
93
+ throw new Error('get() returned more than one row');
94
+ if (res.rows.length === 1)
95
+ return res.rows[0];
96
+ return null;
95
97
  }
96
98
  async insert(sql, phs) {
97
99
  if (!this.connection) {
@@ -100,12 +102,12 @@ export class DbClient {
100
102
  const res = await this.connection.run(sql, phs);
101
103
  return res.rows.insertId || res.rows.affectedRows;
102
104
  }
103
- async update(sql, phs) {
105
+ async update(sql, phs, returnChangedRows = false) {
104
106
  if (!this.connection) {
105
107
  throw new Error('no connection available');
106
108
  }
107
109
  const res = await this.connection.run(sql, phs);
108
- return res.rows.affectedRows;
110
+ return returnChangedRows ? res.rows.changedRows : res.rows.affectedRows;
109
111
  }
110
112
  async delete(sql, phs) {
111
113
  if (!this.connection) {
@@ -1 +1 @@
1
- {"version":3,"file":"dbClient.js","sourceRoot":"","sources":["../../src/dbClient.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createConnection,\n Connection,\n RowDataPacket,\n ResultSetHeader,\n ProcedureCallPacket,\n FieldPacket\n} from 'mysql2/promise';\nimport { getMysqlConnectionOptions, USE_READ_COMMITTED_ISOLATION } from './config';\nimport { ConnectionOptions } from 'mysql2';\n\ninterface ConnectionWrap extends Connection {\n run<T extends ResultSetHeader | ResultSetHeader[] | RowDataPacket[] | RowDataPacket[][] | ProcedureCallPacket>(\n sql: string,\n phs?: (string | number | boolean | null)[]\n ): Promise<{\n rows: T;\n cols: FieldPacket[];\n }>;\n}\n\nexport class DbClient {\n private connection?: ConnectionWrap;\n private connectionOptions: ConnectionOptions;\n\n constructor(connectionOptionsOrPrefix?: ConnectionOptions | string) {\n if (connectionOptionsOrPrefix) {\n if (typeof connectionOptionsOrPrefix === 'string') {\n this.connectionOptions = getMysqlConnectionOptions(connectionOptionsOrPrefix);\n } else {\n this.connectionOptions = connectionOptionsOrPrefix;\n }\n } else {\n this.connectionOptions = getMysqlConnectionOptions('');\n }\n }\n\n async open() {\n this.connection = (await createConnection(this.connectionOptions)) as ConnectionWrap;\n this.connection.run = async <\n T extends ResultSetHeader | ResultSetHeader[] | RowDataPacket[] | RowDataPacket[][] | ProcedureCallPacket\n >(\n sql: string,\n phs?: (string | number | boolean | null)[]\n ): Promise<{ rows: T; cols: FieldPacket[] }> => {\n if (!this.connection) {\n throw new Error('run() called but no connection available');\n }\n const [rows, cols] = await this.connection.execute<T>(sql, phs);\n return {\n rows,\n cols\n };\n };\n }\n\n getConnection(): ConnectionWrap | undefined {\n return this.connection;\n }\n\n async close() {\n if (this.connection) {\n await this.connection.end();\n }\n }\n\n async startTransaction() {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n if (USE_READ_COMMITTED_ISOLATION) {\n await this.connection.execute(\"SET SESSION tx_isolation='read-committed'\");\n }\n await this.connection.execute('SET AUTOCOMMIT=0');\n }\n\n async commit(closeTransaction = true) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n await this.connection.execute('COMMIT');\n if (closeTransaction) {\n await this.connection.execute('SET AUTOCOMMIT=1');\n }\n }\n\n async rollback(closeTransaction = true) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n\n await this.connection.execute('ROLLBACK');\n if (closeTransaction) {\n await this.connection.execute('SET AUTOCOMMIT=1');\n }\n }\n\n async all(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<RowDataPacket[]>(sql, phs);\n return res.rows;\n }\n\n async get(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<RowDataPacket[]>(sql, phs);\n if (res.rows.length > 1) throw new Error('get returned more than one row');\n return res.rows[0];\n }\n\n async insert(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.insertId || res.rows.affectedRows;\n }\n\n async update(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.affectedRows;\n }\n\n async delete(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.affectedRows;\n }\n\n async run(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n return this.connection.execute(sql, phs);\n }\n}\n"]}
1
+ {"version":3,"file":"dbClient.js","sourceRoot":"","sources":["../../src/dbClient.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createConnection,\n Connection,\n RowDataPacket,\n ResultSetHeader,\n ProcedureCallPacket,\n FieldPacket\n} from 'mysql2/promise';\nimport { getMysqlConnectionOptions, USE_READ_COMMITTED_ISOLATION } from './config';\nimport { ConnectionOptions } from 'mysql2';\n\ninterface ConnectionWrap extends Connection {\n run<T extends ResultSetHeader | ResultSetHeader[] | RowDataPacket[] | RowDataPacket[][] | ProcedureCallPacket>(\n sql: string,\n phs?: (string | number | boolean | null)[]\n ): Promise<{\n rows: T;\n cols: FieldPacket[];\n }>;\n}\n\nexport class DbClient {\n private connection?: ConnectionWrap;\n private readonly connectionOptions: ConnectionOptions;\n\n constructor(connectionOptionsOrPrefix?: ConnectionOptions | string) {\n if (connectionOptionsOrPrefix) {\n if (typeof connectionOptionsOrPrefix === 'string') {\n this.connectionOptions = getMysqlConnectionOptions(connectionOptionsOrPrefix);\n } else {\n this.connectionOptions = connectionOptionsOrPrefix;\n }\n } else {\n this.connectionOptions = getMysqlConnectionOptions('');\n }\n }\n\n async open() {\n this.connection = (await createConnection(this.connectionOptions)) as ConnectionWrap;\n this.connection.run = async <\n T extends ResultSetHeader | ResultSetHeader[] | RowDataPacket[] | RowDataPacket[][] | ProcedureCallPacket\n >(\n sql: string,\n phs?: (string | number | boolean | null)[]\n ): Promise<{ rows: T; cols: FieldPacket[] }> => {\n if (!this.connection) {\n throw new Error('run() called but no connection available');\n }\n const [rows, cols] = await this.connection.execute<T>(sql, phs);\n return {\n rows,\n cols\n };\n };\n }\n\n getConnection(): ConnectionWrap | undefined {\n return this.connection;\n }\n\n async close() {\n if (this.connection) {\n await this.connection.end();\n }\n }\n\n async startTransaction() {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n if (USE_READ_COMMITTED_ISOLATION) {\n await this.connection.execute(\"SET SESSION tx_isolation='read-committed'\");\n }\n await this.connection.execute('SET AUTOCOMMIT=0');\n }\n\n async commit(closeTransaction = true) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n await this.connection.execute('COMMIT');\n if (closeTransaction) {\n await this.connection.execute('SET AUTOCOMMIT=1');\n }\n }\n\n async rollback(closeTransaction = true) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n\n await this.connection.execute('ROLLBACK');\n if (closeTransaction) {\n await this.connection.execute('SET AUTOCOMMIT=1');\n }\n }\n\n async all(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<RowDataPacket[]>(sql, phs);\n return res.rows;\n }\n\n async get(sql: string, phs?: (string | number | boolean | null)[]): Promise<RowDataPacket | null> {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<RowDataPacket[]>(sql, phs);\n if (res.rows.length > 1) throw new Error('get() returned more than one row');\n if (res.rows.length === 1) return res.rows[0];\n return null;\n }\n\n async insert(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.insertId || res.rows.affectedRows;\n }\n\n async update(sql: string, phs?: (string | number | boolean | null)[], returnChangedRows = false) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return returnChangedRows ? res.rows.changedRows : res.rows.affectedRows;\n }\n\n async delete(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.affectedRows;\n }\n\n async run(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n return this.connection.execute(sql, phs);\n }\n}\n"]}
@@ -99,6 +99,9 @@ export class UpgradeManager {
99
99
  let row;
100
100
  try {
101
101
  row = await this.client.get(sqlCheck);
102
+ if (!row) {
103
+ return false;
104
+ }
102
105
  this.logger.debug('Versions: %s vs %s', row.value, targetVersion);
103
106
  if (row.value === targetVersion) {
104
107
  this.logger.debug('versions are equal, rollback');
@@ -1 +1 @@
1
- {"version":3,"file":"upgradeManager.js","sourceRoot":"","sources":["../../src/upgradeManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { setTimeout } from 'node:timers/promises';\nimport { getLogger } from '@fluidware-it/saddlebag';\nimport { DbClient } from './dbClient';\nimport { Logger } from 'pino';\n\nexport type UpgradeManagerConfig = {\n version_table_suffix?: string;\n};\n\nexport class UpgradeManager {\n private version_table: string;\n private client: DbClient;\n private logger: Logger;\n private _default_version_table = '_version';\n\n constructor(opts?: UpgradeManagerConfig) {\n this.version_table = this._default_version_table + (opts?.version_table_suffix || '');\n this.logger = getLogger().child({ component: 'mysql-migrator' });\n this.client = new DbClient();\n }\n\n private async loadCurrentVersion(targetVersion: number) {\n try {\n const row = await this.getCurrentVersion(targetVersion);\n if (row === false) {\n return -999;\n } else if (row === true) {\n this.logger.info('Check db: same version %s', targetVersion);\n await this.client.close();\n return true;\n } else if (row) {\n return row.value;\n }\n } catch (e) {\n this.logger.error(`Failed to read current version: ${e.message}`);\n throw e;\n }\n }\n\n private async createDb() {\n try {\n return this.createVersionTable();\n } catch (e) {\n if (e.code === '23505') {\n await this.client.close();\n await setTimeout(2000);\n return -1;\n } else {\n this.logger.error(`Unable to create ${this.version_table} table: [${e.code}] ${e.message}`);\n throw e;\n }\n }\n }\n\n private async _checkDb(\n currentVersion: number,\n targetVersion: number,\n onSchemaInit: (dbClient: DbClient) => Promise<void>,\n onSchemaUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n try {\n if (currentVersion === 0) {\n await this.initDb(targetVersion, onSchemaInit);\n this.logger.info('Db created');\n return true;\n }\n if (targetVersion === currentVersion) {\n return true;\n }\n if (targetVersion > currentVersion) {\n await this.upgradeDb(currentVersion, targetVersion, onSchemaUpgrade);\n this.logger.info('Db updated to ', targetVersion);\n return true;\n }\n } catch (e) {\n this.logger.error('\\n');\n this.logger.error('\\n');\n this.logger.error(' !!!!!!!! FATAL ERROR !!!!!!!!');\n this.logger.error('\\n');\n this.logger.error('checkDb failed %s', e.message);\n this.logger.error('\\n');\n this.logger.error(' !!!!!!!! FATAL ERROR !!!!!!!!');\n this.logger.error('\\n');\n this.logger.error('\\n');\n this.logger.error(e.stack);\n throw e;\n } finally {\n await this.client.close();\n }\n return true;\n }\n\n private async getCurrentVersion(targetVersion: number) {\n const sqlCheck = `select value from ${this.version_table} for update`;\n await this.client.startTransaction();\n let row;\n try {\n row = await this.client.get(sqlCheck);\n this.logger.debug('Versions: %s vs %s', row.value, targetVersion);\n if (row.value === targetVersion) {\n this.logger.debug('versions are equal, rollback');\n await this.client.rollback();\n return true;\n }\n return row;\n } catch (e) {\n await this.client.rollback();\n if (e.code === 'ER_NO_SUCH_TABLE') {\n return false;\n }\n this.logger.error('Ooops: %s', e.message, e.code);\n throw e;\n }\n }\n\n private async createVersionTable() {\n const sqlCreateTable = `create table ${this.version_table} (value INTEGER PRIMARY KEY)`;\n try {\n await this.client.run(sqlCreateTable);\n } catch (e) {\n await this.client.rollback();\n throw e;\n }\n try {\n const sqlInsertVersionZero = `insert into ${this.version_table} values (-1)`;\n await this.client.insert(sqlInsertVersionZero);\n await this.client.get(`select value from ${this.version_table} for update`);\n } catch (e) {\n this.logger.error('Unable to insert -1 version in %s table: [%s] %s', this.version_table, e.code, e.message);\n throw e;\n }\n return 0;\n }\n\n private async updateVersion(targetVersion: number) {\n const sql = `update ${this.version_table} set value = ?`;\n await this.client.update(sql, [targetVersion]);\n await this.client.commit();\n }\n\n private async initDb(targetVersion: number, onInit: (dbClient: DbClient) => Promise<void>) {\n const dbConn = new DbClient();\n try {\n await dbConn.open();\n await onInit(dbConn);\n await this.updateVersion(targetVersion);\n } finally {\n if (dbConn) {\n await dbConn.close();\n }\n }\n }\n\n private async upgradeDb(\n fromVersion: number,\n targetVersion: number,\n onUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n await onUpgrade(this.client, fromVersion);\n await this.updateVersion(targetVersion);\n }\n\n async checkDb(\n targetVersion: number,\n onSchemaInit: (dbClient: DbClient) => Promise<void>,\n onSchemaUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n await this.client.open();\n let currentVersion = await this.loadCurrentVersion(targetVersion);\n if (currentVersion === true) {\n return true;\n }\n this.logger.info('Check db: currentVersion %s targetVersion %s', currentVersion, targetVersion);\n\n if (currentVersion === -999) {\n currentVersion = await this.createDb();\n if (currentVersion < 0) {\n await this.checkDb(targetVersion, onSchemaInit, onSchemaUpgrade);\n return;\n }\n } else if (currentVersion < 0) {\n this.logger.error('Db in initialization, exiting ');\n throw new Error('Db in initialization, do not proceed');\n }\n return this._checkDb(currentVersion, targetVersion, onSchemaInit, onSchemaUpgrade);\n }\n}\n"]}
1
+ {"version":3,"file":"upgradeManager.js","sourceRoot":"","sources":["../../src/upgradeManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { setTimeout } from 'node:timers/promises';\nimport { getLogger } from '@fluidware-it/saddlebag';\nimport { DbClient } from './dbClient';\nimport { Logger } from 'pino';\n\nexport type UpgradeManagerConfig = {\n version_table_suffix?: string;\n};\n\nexport class UpgradeManager {\n private version_table: string;\n private client: DbClient;\n private logger: Logger;\n private _default_version_table = '_version';\n\n constructor(opts?: UpgradeManagerConfig) {\n this.version_table = this._default_version_table + (opts?.version_table_suffix || '');\n this.logger = getLogger().child({ component: 'mysql-migrator' });\n this.client = new DbClient();\n }\n\n private async loadCurrentVersion(targetVersion: number) {\n try {\n const row = await this.getCurrentVersion(targetVersion);\n if (row === false) {\n return -999;\n } else if (row === true) {\n this.logger.info('Check db: same version %s', targetVersion);\n await this.client.close();\n return true;\n } else if (row) {\n return row.value;\n }\n } catch (e) {\n this.logger.error(`Failed to read current version: ${e.message}`);\n throw e;\n }\n }\n\n private async createDb() {\n try {\n return this.createVersionTable();\n } catch (e) {\n if (e.code === '23505') {\n await this.client.close();\n await setTimeout(2000);\n return -1;\n } else {\n this.logger.error(`Unable to create ${this.version_table} table: [${e.code}] ${e.message}`);\n throw e;\n }\n }\n }\n\n private async _checkDb(\n currentVersion: number,\n targetVersion: number,\n onSchemaInit: (dbClient: DbClient) => Promise<void>,\n onSchemaUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n try {\n if (currentVersion === 0) {\n await this.initDb(targetVersion, onSchemaInit);\n this.logger.info('Db created');\n return true;\n }\n if (targetVersion === currentVersion) {\n return true;\n }\n if (targetVersion > currentVersion) {\n await this.upgradeDb(currentVersion, targetVersion, onSchemaUpgrade);\n this.logger.info('Db updated to ', targetVersion);\n return true;\n }\n } catch (e) {\n this.logger.error('\\n');\n this.logger.error('\\n');\n this.logger.error(' !!!!!!!! FATAL ERROR !!!!!!!!');\n this.logger.error('\\n');\n this.logger.error('checkDb failed %s', e.message);\n this.logger.error('\\n');\n this.logger.error(' !!!!!!!! FATAL ERROR !!!!!!!!');\n this.logger.error('\\n');\n this.logger.error('\\n');\n this.logger.error(e.stack);\n throw e;\n } finally {\n await this.client.close();\n }\n return true;\n }\n\n private async getCurrentVersion(targetVersion: number) {\n const sqlCheck = `select value from ${this.version_table} for update`;\n await this.client.startTransaction();\n let row;\n try {\n row = await this.client.get(sqlCheck);\n if (!row) {\n return false;\n }\n this.logger.debug('Versions: %s vs %s', row.value, targetVersion);\n if (row.value === targetVersion) {\n this.logger.debug('versions are equal, rollback');\n await this.client.rollback();\n return true;\n }\n return row;\n } catch (e) {\n await this.client.rollback();\n if (e.code === 'ER_NO_SUCH_TABLE') {\n return false;\n }\n this.logger.error('Ooops: %s', e.message, e.code);\n throw e;\n }\n }\n\n private async createVersionTable() {\n const sqlCreateTable = `create table ${this.version_table} (value INTEGER PRIMARY KEY)`;\n try {\n await this.client.run(sqlCreateTable);\n } catch (e) {\n await this.client.rollback();\n throw e;\n }\n try {\n const sqlInsertVersionZero = `insert into ${this.version_table} values (-1)`;\n await this.client.insert(sqlInsertVersionZero);\n await this.client.get(`select value from ${this.version_table} for update`);\n } catch (e) {\n this.logger.error('Unable to insert -1 version in %s table: [%s] %s', this.version_table, e.code, e.message);\n throw e;\n }\n return 0;\n }\n\n private async updateVersion(targetVersion: number) {\n const sql = `update ${this.version_table} set value = ?`;\n await this.client.update(sql, [targetVersion]);\n await this.client.commit();\n }\n\n private async initDb(targetVersion: number, onInit: (dbClient: DbClient) => Promise<void>) {\n const dbConn = new DbClient();\n try {\n await dbConn.open();\n await onInit(dbConn);\n await this.updateVersion(targetVersion);\n } finally {\n if (dbConn) {\n await dbConn.close();\n }\n }\n }\n\n private async upgradeDb(\n fromVersion: number,\n targetVersion: number,\n onUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n await onUpgrade(this.client, fromVersion);\n await this.updateVersion(targetVersion);\n }\n\n async checkDb(\n targetVersion: number,\n onSchemaInit: (dbClient: DbClient) => Promise<void>,\n onSchemaUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n await this.client.open();\n let currentVersion = await this.loadCurrentVersion(targetVersion);\n if (currentVersion === true) {\n return true;\n }\n this.logger.info('Check db: currentVersion %s targetVersion %s', currentVersion, targetVersion);\n\n if (currentVersion === -999) {\n currentVersion = await this.createDb();\n if (currentVersion < 0) {\n await this.checkDb(targetVersion, onSchemaInit, onSchemaUpgrade);\n return;\n }\n } else if (currentVersion < 0) {\n this.logger.error('Db in initialization, exiting ');\n throw new Error('Db in initialization, do not proceed');\n }\n return this._checkDb(currentVersion, targetVersion, onSchemaInit, onSchemaUpgrade);\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { ConnectionOptions } from 'mysql2';
2
2
  export declare const USE_READ_COMMITTED_ISOLATION: boolean;
3
3
  export declare function getMysqlConnectionOptions(prefix?: string): ConnectionOptions;
4
+ export declare function setMysqlConnectionOptions(prefix: string, options: ConnectionOptions): void;
4
5
  //# sourceMappingURL=config.d.ts.map
@@ -15,7 +15,7 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.getMysqlConnectionOptions = exports.USE_READ_COMMITTED_ISOLATION = void 0;
18
+ exports.setMysqlConnectionOptions = exports.getMysqlConnectionOptions = exports.USE_READ_COMMITTED_ISOLATION = void 0;
19
19
  const saddlebag_1 = require("@fluidware-it/saddlebag");
20
20
  const fs = require("fs");
21
21
  exports.USE_READ_COMMITTED_ISOLATION = saddlebag_1.EnvParse.envBool('FW_DB_USE_READ_COMMITTED_ISOLATION', false);
@@ -37,6 +37,7 @@ function getMysqlConnectionOptions(prefix = '') {
37
37
  const DB_HOST = saddlebag_1.EnvParse.envString(`FW_${prefix}DB_HOST`, 'localhost');
38
38
  const DB_PORT = saddlebag_1.EnvParse.envInt(`FW_${prefix}DB_PORT`, 3306);
39
39
  const DB_NAME = saddlebag_1.EnvParse.envString(`FW_${prefix}DB_NAME`, DB_USER);
40
+ // FW_${prefix}DB_CONN_OPTIONS: JSON string with connection options See https://github.com/mysqljs/mysql#connection-options for all possible options
40
41
  const DB_CONN_OPTIONS = saddlebag_1.EnvParse.envJSON(`FW_${prefix}DB_CONN_OPTIONS`, {});
41
42
  const dbPassword = getDbPassword(DB_PASSWORD_FILE, DB_PASSWORD);
42
43
  const dbOptions = {
@@ -47,7 +48,6 @@ function getMysqlConnectionOptions(prefix = '') {
47
48
  database: DB_NAME
48
49
  };
49
50
  if (Object.keys(DB_CONN_OPTIONS).length > 0) {
50
- // See https://github.com/mysqljs/mysql#connection-options for all possible options
51
51
  Object.assign(dbOptions, DB_CONN_OPTIONS);
52
52
  }
53
53
  memoizedOptions[prefix] = dbOptions;
@@ -55,4 +55,8 @@ function getMysqlConnectionOptions(prefix = '') {
55
55
  return memoizedOptions[prefix];
56
56
  }
57
57
  exports.getMysqlConnectionOptions = getMysqlConnectionOptions;
58
+ function setMysqlConnectionOptions(prefix, options) {
59
+ memoizedOptions[prefix] = options;
60
+ }
61
+ exports.setMysqlConnectionOptions = setMysqlConnectionOptions;
58
62
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAEH,uDAAmD;AACnD,yBAAyB;AAGZ,QAAA,4BAA4B,GAAG,oBAAQ,CAAC,OAAO,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;AAE1G,SAAS,aAAa,CAAC,gBAAwB,EAAE,WAAmB;IAClE,IAAI,gBAAgB,EAAE;QACpB,OAAO,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;KAClD;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,eAAe,GAA4C,EAAE,CAAC;AAEpE,SAAgB,yBAAyB,CAAC,MAAM,GAAG,EAAE;IACnD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;QAC5B,MAAM,WAAW,GAAG,oBAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,aAAa,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,gBAAgB,GAAG,oBAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,kBAAkB,EAAE,EAAE,CAAC,CAAC;QAEhF,IAAI,CAAC,WAAW,IAAI,CAAC,gBAAgB,EAAE;YACrC,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;SAC1E;QAED,MAAM,OAAO,GAAG,oBAAQ,CAAC,iBAAiB,CAAC,MAAM,MAAM,SAAS,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,oBAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,SAAS,EAAE,WAAW,CAAC,CAAC;QACvE,MAAM,OAAO,GAAG,oBAAQ,CAAC,MAAM,CAAC,MAAM,MAAM,SAAS,EAAE,IAAI,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,oBAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,SAAS,EAAE,OAAO,CAAC,CAAC;QACnE,MAAM,eAAe,GAAG,oBAAQ,CAAC,OAAO,CAAC,MAAM,MAAM,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAE5E,MAAM,UAAU,GAAG,aAAa,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;QAChE,MAAM,SAAS,GAAG;YAChB,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,OAAO;SAClB,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YAC3C,mFAAmF;YACnF,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;SAC3C;QACD,eAAe,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;KACrC;IACD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AA9BD,8DA8BC","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EnvParse } from '@fluidware-it/saddlebag';\nimport * as fs from 'fs';\nimport { ConnectionOptions } from 'mysql2';\n\nexport const USE_READ_COMMITTED_ISOLATION = EnvParse.envBool('FW_DB_USE_READ_COMMITTED_ISOLATION', false);\n\nfunction getDbPassword(DB_PASSWORD_FILE: string, DB_PASSWORD: string): string {\n if (DB_PASSWORD_FILE) {\n return fs.readFileSync(DB_PASSWORD_FILE, 'utf8');\n }\n return DB_PASSWORD;\n}\n\nconst memoizedOptions: { [prefix: string]: ConnectionOptions } = {};\n\nexport function getMysqlConnectionOptions(prefix = ''): ConnectionOptions {\n if (!memoizedOptions[prefix]) {\n const DB_PASSWORD = EnvParse.envString(`FW_${prefix}DB_PASSWORD`, '');\n const DB_PASSWORD_FILE = EnvParse.envString(`FW_${prefix}DB_PASSWORD_FILE`, '');\n\n if (!DB_PASSWORD && !DB_PASSWORD_FILE) {\n throw new Error('FW_DB_PASSWORD or FW_DB_PASSWORD_FILE env is required');\n }\n\n const DB_USER = EnvParse.envStringRequired(`FW_${prefix}DB_USER`);\n const DB_HOST = EnvParse.envString(`FW_${prefix}DB_HOST`, 'localhost');\n const DB_PORT = EnvParse.envInt(`FW_${prefix}DB_PORT`, 3306);\n const DB_NAME = EnvParse.envString(`FW_${prefix}DB_NAME`, DB_USER);\n const DB_CONN_OPTIONS = EnvParse.envJSON(`FW_${prefix}DB_CONN_OPTIONS`, {});\n\n const dbPassword = getDbPassword(DB_PASSWORD_FILE, DB_PASSWORD);\n const dbOptions = {\n host: DB_HOST,\n port: DB_PORT,\n user: DB_USER,\n password: dbPassword,\n database: DB_NAME\n };\n if (Object.keys(DB_CONN_OPTIONS).length > 0) {\n // See https://github.com/mysqljs/mysql#connection-options for all possible options\n Object.assign(dbOptions, DB_CONN_OPTIONS);\n }\n memoizedOptions[prefix] = dbOptions;\n }\n return memoizedOptions[prefix];\n}\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAEH,uDAAmD;AACnD,yBAAyB;AAGZ,QAAA,4BAA4B,GAAG,oBAAQ,CAAC,OAAO,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;AAE1G,SAAS,aAAa,CAAC,gBAAwB,EAAE,WAAmB;IAClE,IAAI,gBAAgB,EAAE;QACpB,OAAO,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;KAClD;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,eAAe,GAA4C,EAAE,CAAC;AAEpE,SAAgB,yBAAyB,CAAC,MAAM,GAAG,EAAE;IACnD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;QAC5B,MAAM,WAAW,GAAG,oBAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,aAAa,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,gBAAgB,GAAG,oBAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,kBAAkB,EAAE,EAAE,CAAC,CAAC;QAEhF,IAAI,CAAC,WAAW,IAAI,CAAC,gBAAgB,EAAE;YACrC,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;SAC1E;QAED,MAAM,OAAO,GAAG,oBAAQ,CAAC,iBAAiB,CAAC,MAAM,MAAM,SAAS,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,oBAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,SAAS,EAAE,WAAW,CAAC,CAAC;QACvE,MAAM,OAAO,GAAG,oBAAQ,CAAC,MAAM,CAAC,MAAM,MAAM,SAAS,EAAE,IAAI,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,oBAAQ,CAAC,SAAS,CAAC,MAAM,MAAM,SAAS,EAAE,OAAO,CAAC,CAAC;QACnE,oJAAoJ;QACpJ,MAAM,eAAe,GAAG,oBAAQ,CAAC,OAAO,CAAC,MAAM,MAAM,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAE5E,MAAM,UAAU,GAAG,aAAa,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;QAChE,MAAM,SAAS,GAAG;YAChB,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,OAAO;SAClB,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YAC3C,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;SAC3C;QACD,eAAe,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;KACrC;IACD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AA9BD,8DA8BC;AAED,SAAgB,yBAAyB,CAAC,MAAc,EAAE,OAA0B;IAClF,eAAe,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;AACpC,CAAC;AAFD,8DAEC","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EnvParse } from '@fluidware-it/saddlebag';\nimport * as fs from 'fs';\nimport { ConnectionOptions } from 'mysql2';\n\nexport const USE_READ_COMMITTED_ISOLATION = EnvParse.envBool('FW_DB_USE_READ_COMMITTED_ISOLATION', false);\n\nfunction getDbPassword(DB_PASSWORD_FILE: string, DB_PASSWORD: string): string {\n if (DB_PASSWORD_FILE) {\n return fs.readFileSync(DB_PASSWORD_FILE, 'utf8');\n }\n return DB_PASSWORD;\n}\n\nconst memoizedOptions: { [prefix: string]: ConnectionOptions } = {};\n\nexport function getMysqlConnectionOptions(prefix = ''): ConnectionOptions {\n if (!memoizedOptions[prefix]) {\n const DB_PASSWORD = EnvParse.envString(`FW_${prefix}DB_PASSWORD`, '');\n const DB_PASSWORD_FILE = EnvParse.envString(`FW_${prefix}DB_PASSWORD_FILE`, '');\n\n if (!DB_PASSWORD && !DB_PASSWORD_FILE) {\n throw new Error('FW_DB_PASSWORD or FW_DB_PASSWORD_FILE env is required');\n }\n\n const DB_USER = EnvParse.envStringRequired(`FW_${prefix}DB_USER`);\n const DB_HOST = EnvParse.envString(`FW_${prefix}DB_HOST`, 'localhost');\n const DB_PORT = EnvParse.envInt(`FW_${prefix}DB_PORT`, 3306);\n const DB_NAME = EnvParse.envString(`FW_${prefix}DB_NAME`, DB_USER);\n // FW_${prefix}DB_CONN_OPTIONS: JSON string with connection options See https://github.com/mysqljs/mysql#connection-options for all possible options\n const DB_CONN_OPTIONS = EnvParse.envJSON(`FW_${prefix}DB_CONN_OPTIONS`, {});\n\n const dbPassword = getDbPassword(DB_PASSWORD_FILE, DB_PASSWORD);\n const dbOptions = {\n host: DB_HOST,\n port: DB_PORT,\n user: DB_USER,\n password: dbPassword,\n database: DB_NAME\n };\n if (Object.keys(DB_CONN_OPTIONS).length > 0) {\n Object.assign(dbOptions, DB_CONN_OPTIONS);\n }\n memoizedOptions[prefix] = dbOptions;\n }\n return memoizedOptions[prefix];\n}\n\nexport function setMysqlConnectionOptions(prefix: string, options: ConnectionOptions) {\n memoizedOptions[prefix] = options;\n}\n"]}
@@ -8,7 +8,7 @@ interface ConnectionWrap extends Connection {
8
8
  }
9
9
  export declare class DbClient {
10
10
  private connection?;
11
- private connectionOptions;
11
+ private readonly connectionOptions;
12
12
  constructor(connectionOptionsOrPrefix?: ConnectionOptions | string);
13
13
  open(): Promise<void>;
14
14
  getConnection(): ConnectionWrap | undefined;
@@ -17,9 +17,9 @@ export declare class DbClient {
17
17
  commit(closeTransaction?: boolean): Promise<void>;
18
18
  rollback(closeTransaction?: boolean): Promise<void>;
19
19
  all(sql: string, phs?: (string | number | boolean | null)[]): Promise<RowDataPacket[]>;
20
- get(sql: string, phs?: (string | number | boolean | null)[]): Promise<RowDataPacket>;
20
+ get(sql: string, phs?: (string | number | boolean | null)[]): Promise<RowDataPacket | null>;
21
21
  insert(sql: string, phs?: (string | number | boolean | null)[]): Promise<number>;
22
- update(sql: string, phs?: (string | number | boolean | null)[]): Promise<number>;
22
+ update(sql: string, phs?: (string | number | boolean | null)[], returnChangedRows?: boolean): Promise<number>;
23
23
  delete(sql: string, phs?: (string | number | boolean | null)[]): Promise<number>;
24
24
  run(sql: string, phs?: (string | number | boolean | null)[]): Promise<[import("mysql2/typings/mysql/lib/protocol/packets/OkPacket").OkPacket | RowDataPacket[] | ProcedureCallPacket | ResultSetHeader[] | RowDataPacket[][] | import("mysql2/typings/mysql/lib/protocol/packets/OkPacket").OkPacket[], FieldPacket[]]>;
25
25
  }
@@ -93,8 +93,10 @@ class DbClient {
93
93
  }
94
94
  const res = await this.connection.run(sql, phs);
95
95
  if (res.rows.length > 1)
96
- throw new Error('get returned more than one row');
97
- return res.rows[0];
96
+ throw new Error('get() returned more than one row');
97
+ if (res.rows.length === 1)
98
+ return res.rows[0];
99
+ return null;
98
100
  }
99
101
  async insert(sql, phs) {
100
102
  if (!this.connection) {
@@ -103,12 +105,12 @@ class DbClient {
103
105
  const res = await this.connection.run(sql, phs);
104
106
  return res.rows.insertId || res.rows.affectedRows;
105
107
  }
106
- async update(sql, phs) {
108
+ async update(sql, phs, returnChangedRows = false) {
107
109
  if (!this.connection) {
108
110
  throw new Error('no connection available');
109
111
  }
110
112
  const res = await this.connection.run(sql, phs);
111
- return res.rows.affectedRows;
113
+ return returnChangedRows ? res.rows.changedRows : res.rows.affectedRows;
112
114
  }
113
115
  async delete(sql, phs) {
114
116
  if (!this.connection) {
@@ -1 +1 @@
1
- {"version":3,"file":"dbClient.js","sourceRoot":"","sources":["../../src/dbClient.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createConnection,\n Connection,\n RowDataPacket,\n ResultSetHeader,\n ProcedureCallPacket,\n FieldPacket\n} from 'mysql2/promise';\nimport { getMysqlConnectionOptions, USE_READ_COMMITTED_ISOLATION } from './config';\nimport { ConnectionOptions } from 'mysql2';\n\ninterface ConnectionWrap extends Connection {\n run<T extends ResultSetHeader | ResultSetHeader[] | RowDataPacket[] | RowDataPacket[][] | ProcedureCallPacket>(\n sql: string,\n phs?: (string | number | boolean | null)[]\n ): Promise<{\n rows: T;\n cols: FieldPacket[];\n }>;\n}\n\nexport class DbClient {\n private connection?: ConnectionWrap;\n private connectionOptions: ConnectionOptions;\n\n constructor(connectionOptionsOrPrefix?: ConnectionOptions | string) {\n if (connectionOptionsOrPrefix) {\n if (typeof connectionOptionsOrPrefix === 'string') {\n this.connectionOptions = getMysqlConnectionOptions(connectionOptionsOrPrefix);\n } else {\n this.connectionOptions = connectionOptionsOrPrefix;\n }\n } else {\n this.connectionOptions = getMysqlConnectionOptions('');\n }\n }\n\n async open() {\n this.connection = (await createConnection(this.connectionOptions)) as ConnectionWrap;\n this.connection.run = async <\n T extends ResultSetHeader | ResultSetHeader[] | RowDataPacket[] | RowDataPacket[][] | ProcedureCallPacket\n >(\n sql: string,\n phs?: (string | number | boolean | null)[]\n ): Promise<{ rows: T; cols: FieldPacket[] }> => {\n if (!this.connection) {\n throw new Error('run() called but no connection available');\n }\n const [rows, cols] = await this.connection.execute<T>(sql, phs);\n return {\n rows,\n cols\n };\n };\n }\n\n getConnection(): ConnectionWrap | undefined {\n return this.connection;\n }\n\n async close() {\n if (this.connection) {\n await this.connection.end();\n }\n }\n\n async startTransaction() {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n if (USE_READ_COMMITTED_ISOLATION) {\n await this.connection.execute(\"SET SESSION tx_isolation='read-committed'\");\n }\n await this.connection.execute('SET AUTOCOMMIT=0');\n }\n\n async commit(closeTransaction = true) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n await this.connection.execute('COMMIT');\n if (closeTransaction) {\n await this.connection.execute('SET AUTOCOMMIT=1');\n }\n }\n\n async rollback(closeTransaction = true) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n\n await this.connection.execute('ROLLBACK');\n if (closeTransaction) {\n await this.connection.execute('SET AUTOCOMMIT=1');\n }\n }\n\n async all(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<RowDataPacket[]>(sql, phs);\n return res.rows;\n }\n\n async get(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<RowDataPacket[]>(sql, phs);\n if (res.rows.length > 1) throw new Error('get returned more than one row');\n return res.rows[0];\n }\n\n async insert(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.insertId || res.rows.affectedRows;\n }\n\n async update(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.affectedRows;\n }\n\n async delete(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.affectedRows;\n }\n\n async run(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n return this.connection.execute(sql, phs);\n }\n}\n"]}
1
+ {"version":3,"file":"dbClient.js","sourceRoot":"","sources":["../../src/dbClient.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createConnection,\n Connection,\n RowDataPacket,\n ResultSetHeader,\n ProcedureCallPacket,\n FieldPacket\n} from 'mysql2/promise';\nimport { getMysqlConnectionOptions, USE_READ_COMMITTED_ISOLATION } from './config';\nimport { ConnectionOptions } from 'mysql2';\n\ninterface ConnectionWrap extends Connection {\n run<T extends ResultSetHeader | ResultSetHeader[] | RowDataPacket[] | RowDataPacket[][] | ProcedureCallPacket>(\n sql: string,\n phs?: (string | number | boolean | null)[]\n ): Promise<{\n rows: T;\n cols: FieldPacket[];\n }>;\n}\n\nexport class DbClient {\n private connection?: ConnectionWrap;\n private readonly connectionOptions: ConnectionOptions;\n\n constructor(connectionOptionsOrPrefix?: ConnectionOptions | string) {\n if (connectionOptionsOrPrefix) {\n if (typeof connectionOptionsOrPrefix === 'string') {\n this.connectionOptions = getMysqlConnectionOptions(connectionOptionsOrPrefix);\n } else {\n this.connectionOptions = connectionOptionsOrPrefix;\n }\n } else {\n this.connectionOptions = getMysqlConnectionOptions('');\n }\n }\n\n async open() {\n this.connection = (await createConnection(this.connectionOptions)) as ConnectionWrap;\n this.connection.run = async <\n T extends ResultSetHeader | ResultSetHeader[] | RowDataPacket[] | RowDataPacket[][] | ProcedureCallPacket\n >(\n sql: string,\n phs?: (string | number | boolean | null)[]\n ): Promise<{ rows: T; cols: FieldPacket[] }> => {\n if (!this.connection) {\n throw new Error('run() called but no connection available');\n }\n const [rows, cols] = await this.connection.execute<T>(sql, phs);\n return {\n rows,\n cols\n };\n };\n }\n\n getConnection(): ConnectionWrap | undefined {\n return this.connection;\n }\n\n async close() {\n if (this.connection) {\n await this.connection.end();\n }\n }\n\n async startTransaction() {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n if (USE_READ_COMMITTED_ISOLATION) {\n await this.connection.execute(\"SET SESSION tx_isolation='read-committed'\");\n }\n await this.connection.execute('SET AUTOCOMMIT=0');\n }\n\n async commit(closeTransaction = true) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n await this.connection.execute('COMMIT');\n if (closeTransaction) {\n await this.connection.execute('SET AUTOCOMMIT=1');\n }\n }\n\n async rollback(closeTransaction = true) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n\n await this.connection.execute('ROLLBACK');\n if (closeTransaction) {\n await this.connection.execute('SET AUTOCOMMIT=1');\n }\n }\n\n async all(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<RowDataPacket[]>(sql, phs);\n return res.rows;\n }\n\n async get(sql: string, phs?: (string | number | boolean | null)[]): Promise<RowDataPacket | null> {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<RowDataPacket[]>(sql, phs);\n if (res.rows.length > 1) throw new Error('get() returned more than one row');\n if (res.rows.length === 1) return res.rows[0];\n return null;\n }\n\n async insert(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.insertId || res.rows.affectedRows;\n }\n\n async update(sql: string, phs?: (string | number | boolean | null)[], returnChangedRows = false) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return returnChangedRows ? res.rows.changedRows : res.rows.affectedRows;\n }\n\n async delete(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n const res = await this.connection.run<ResultSetHeader>(sql, phs);\n return res.rows.affectedRows;\n }\n\n async run(sql: string, phs?: (string | number | boolean | null)[]) {\n if (!this.connection) {\n throw new Error('no connection available');\n }\n return this.connection.execute(sql, phs);\n }\n}\n"]}
@@ -102,6 +102,9 @@ class UpgradeManager {
102
102
  let row;
103
103
  try {
104
104
  row = await this.client.get(sqlCheck);
105
+ if (!row) {
106
+ return false;
107
+ }
105
108
  this.logger.debug('Versions: %s vs %s', row.value, targetVersion);
106
109
  if (row.value === targetVersion) {
107
110
  this.logger.debug('versions are equal, rollback');
@@ -1 +1 @@
1
- {"version":3,"file":"upgradeManager.js","sourceRoot":"","sources":["../../src/upgradeManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { setTimeout } from 'node:timers/promises';\nimport { getLogger } from '@fluidware-it/saddlebag';\nimport { DbClient } from './dbClient';\nimport { Logger } from 'pino';\n\nexport type UpgradeManagerConfig = {\n version_table_suffix?: string;\n};\n\nexport class UpgradeManager {\n private version_table: string;\n private client: DbClient;\n private logger: Logger;\n private _default_version_table = '_version';\n\n constructor(opts?: UpgradeManagerConfig) {\n this.version_table = this._default_version_table + (opts?.version_table_suffix || '');\n this.logger = getLogger().child({ component: 'mysql-migrator' });\n this.client = new DbClient();\n }\n\n private async loadCurrentVersion(targetVersion: number) {\n try {\n const row = await this.getCurrentVersion(targetVersion);\n if (row === false) {\n return -999;\n } else if (row === true) {\n this.logger.info('Check db: same version %s', targetVersion);\n await this.client.close();\n return true;\n } else if (row) {\n return row.value;\n }\n } catch (e) {\n this.logger.error(`Failed to read current version: ${e.message}`);\n throw e;\n }\n }\n\n private async createDb() {\n try {\n return this.createVersionTable();\n } catch (e) {\n if (e.code === '23505') {\n await this.client.close();\n await setTimeout(2000);\n return -1;\n } else {\n this.logger.error(`Unable to create ${this.version_table} table: [${e.code}] ${e.message}`);\n throw e;\n }\n }\n }\n\n private async _checkDb(\n currentVersion: number,\n targetVersion: number,\n onSchemaInit: (dbClient: DbClient) => Promise<void>,\n onSchemaUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n try {\n if (currentVersion === 0) {\n await this.initDb(targetVersion, onSchemaInit);\n this.logger.info('Db created');\n return true;\n }\n if (targetVersion === currentVersion) {\n return true;\n }\n if (targetVersion > currentVersion) {\n await this.upgradeDb(currentVersion, targetVersion, onSchemaUpgrade);\n this.logger.info('Db updated to ', targetVersion);\n return true;\n }\n } catch (e) {\n this.logger.error('\\n');\n this.logger.error('\\n');\n this.logger.error(' !!!!!!!! FATAL ERROR !!!!!!!!');\n this.logger.error('\\n');\n this.logger.error('checkDb failed %s', e.message);\n this.logger.error('\\n');\n this.logger.error(' !!!!!!!! FATAL ERROR !!!!!!!!');\n this.logger.error('\\n');\n this.logger.error('\\n');\n this.logger.error(e.stack);\n throw e;\n } finally {\n await this.client.close();\n }\n return true;\n }\n\n private async getCurrentVersion(targetVersion: number) {\n const sqlCheck = `select value from ${this.version_table} for update`;\n await this.client.startTransaction();\n let row;\n try {\n row = await this.client.get(sqlCheck);\n this.logger.debug('Versions: %s vs %s', row.value, targetVersion);\n if (row.value === targetVersion) {\n this.logger.debug('versions are equal, rollback');\n await this.client.rollback();\n return true;\n }\n return row;\n } catch (e) {\n await this.client.rollback();\n if (e.code === 'ER_NO_SUCH_TABLE') {\n return false;\n }\n this.logger.error('Ooops: %s', e.message, e.code);\n throw e;\n }\n }\n\n private async createVersionTable() {\n const sqlCreateTable = `create table ${this.version_table} (value INTEGER PRIMARY KEY)`;\n try {\n await this.client.run(sqlCreateTable);\n } catch (e) {\n await this.client.rollback();\n throw e;\n }\n try {\n const sqlInsertVersionZero = `insert into ${this.version_table} values (-1)`;\n await this.client.insert(sqlInsertVersionZero);\n await this.client.get(`select value from ${this.version_table} for update`);\n } catch (e) {\n this.logger.error('Unable to insert -1 version in %s table: [%s] %s', this.version_table, e.code, e.message);\n throw e;\n }\n return 0;\n }\n\n private async updateVersion(targetVersion: number) {\n const sql = `update ${this.version_table} set value = ?`;\n await this.client.update(sql, [targetVersion]);\n await this.client.commit();\n }\n\n private async initDb(targetVersion: number, onInit: (dbClient: DbClient) => Promise<void>) {\n const dbConn = new DbClient();\n try {\n await dbConn.open();\n await onInit(dbConn);\n await this.updateVersion(targetVersion);\n } finally {\n if (dbConn) {\n await dbConn.close();\n }\n }\n }\n\n private async upgradeDb(\n fromVersion: number,\n targetVersion: number,\n onUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n await onUpgrade(this.client, fromVersion);\n await this.updateVersion(targetVersion);\n }\n\n async checkDb(\n targetVersion: number,\n onSchemaInit: (dbClient: DbClient) => Promise<void>,\n onSchemaUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n await this.client.open();\n let currentVersion = await this.loadCurrentVersion(targetVersion);\n if (currentVersion === true) {\n return true;\n }\n this.logger.info('Check db: currentVersion %s targetVersion %s', currentVersion, targetVersion);\n\n if (currentVersion === -999) {\n currentVersion = await this.createDb();\n if (currentVersion < 0) {\n await this.checkDb(targetVersion, onSchemaInit, onSchemaUpgrade);\n return;\n }\n } else if (currentVersion < 0) {\n this.logger.error('Db in initialization, exiting ');\n throw new Error('Db in initialization, do not proceed');\n }\n return this._checkDb(currentVersion, targetVersion, onSchemaInit, onSchemaUpgrade);\n }\n}\n"]}
1
+ {"version":3,"file":"upgradeManager.js","sourceRoot":"","sources":["../../src/upgradeManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Fluidware srl\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { setTimeout } from 'node:timers/promises';\nimport { getLogger } from '@fluidware-it/saddlebag';\nimport { DbClient } from './dbClient';\nimport { Logger } from 'pino';\n\nexport type UpgradeManagerConfig = {\n version_table_suffix?: string;\n};\n\nexport class UpgradeManager {\n private version_table: string;\n private client: DbClient;\n private logger: Logger;\n private _default_version_table = '_version';\n\n constructor(opts?: UpgradeManagerConfig) {\n this.version_table = this._default_version_table + (opts?.version_table_suffix || '');\n this.logger = getLogger().child({ component: 'mysql-migrator' });\n this.client = new DbClient();\n }\n\n private async loadCurrentVersion(targetVersion: number) {\n try {\n const row = await this.getCurrentVersion(targetVersion);\n if (row === false) {\n return -999;\n } else if (row === true) {\n this.logger.info('Check db: same version %s', targetVersion);\n await this.client.close();\n return true;\n } else if (row) {\n return row.value;\n }\n } catch (e) {\n this.logger.error(`Failed to read current version: ${e.message}`);\n throw e;\n }\n }\n\n private async createDb() {\n try {\n return this.createVersionTable();\n } catch (e) {\n if (e.code === '23505') {\n await this.client.close();\n await setTimeout(2000);\n return -1;\n } else {\n this.logger.error(`Unable to create ${this.version_table} table: [${e.code}] ${e.message}`);\n throw e;\n }\n }\n }\n\n private async _checkDb(\n currentVersion: number,\n targetVersion: number,\n onSchemaInit: (dbClient: DbClient) => Promise<void>,\n onSchemaUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n try {\n if (currentVersion === 0) {\n await this.initDb(targetVersion, onSchemaInit);\n this.logger.info('Db created');\n return true;\n }\n if (targetVersion === currentVersion) {\n return true;\n }\n if (targetVersion > currentVersion) {\n await this.upgradeDb(currentVersion, targetVersion, onSchemaUpgrade);\n this.logger.info('Db updated to ', targetVersion);\n return true;\n }\n } catch (e) {\n this.logger.error('\\n');\n this.logger.error('\\n');\n this.logger.error(' !!!!!!!! FATAL ERROR !!!!!!!!');\n this.logger.error('\\n');\n this.logger.error('checkDb failed %s', e.message);\n this.logger.error('\\n');\n this.logger.error(' !!!!!!!! FATAL ERROR !!!!!!!!');\n this.logger.error('\\n');\n this.logger.error('\\n');\n this.logger.error(e.stack);\n throw e;\n } finally {\n await this.client.close();\n }\n return true;\n }\n\n private async getCurrentVersion(targetVersion: number) {\n const sqlCheck = `select value from ${this.version_table} for update`;\n await this.client.startTransaction();\n let row;\n try {\n row = await this.client.get(sqlCheck);\n if (!row) {\n return false;\n }\n this.logger.debug('Versions: %s vs %s', row.value, targetVersion);\n if (row.value === targetVersion) {\n this.logger.debug('versions are equal, rollback');\n await this.client.rollback();\n return true;\n }\n return row;\n } catch (e) {\n await this.client.rollback();\n if (e.code === 'ER_NO_SUCH_TABLE') {\n return false;\n }\n this.logger.error('Ooops: %s', e.message, e.code);\n throw e;\n }\n }\n\n private async createVersionTable() {\n const sqlCreateTable = `create table ${this.version_table} (value INTEGER PRIMARY KEY)`;\n try {\n await this.client.run(sqlCreateTable);\n } catch (e) {\n await this.client.rollback();\n throw e;\n }\n try {\n const sqlInsertVersionZero = `insert into ${this.version_table} values (-1)`;\n await this.client.insert(sqlInsertVersionZero);\n await this.client.get(`select value from ${this.version_table} for update`);\n } catch (e) {\n this.logger.error('Unable to insert -1 version in %s table: [%s] %s', this.version_table, e.code, e.message);\n throw e;\n }\n return 0;\n }\n\n private async updateVersion(targetVersion: number) {\n const sql = `update ${this.version_table} set value = ?`;\n await this.client.update(sql, [targetVersion]);\n await this.client.commit();\n }\n\n private async initDb(targetVersion: number, onInit: (dbClient: DbClient) => Promise<void>) {\n const dbConn = new DbClient();\n try {\n await dbConn.open();\n await onInit(dbConn);\n await this.updateVersion(targetVersion);\n } finally {\n if (dbConn) {\n await dbConn.close();\n }\n }\n }\n\n private async upgradeDb(\n fromVersion: number,\n targetVersion: number,\n onUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n await onUpgrade(this.client, fromVersion);\n await this.updateVersion(targetVersion);\n }\n\n async checkDb(\n targetVersion: number,\n onSchemaInit: (dbClient: DbClient) => Promise<void>,\n onSchemaUpgrade: (dbClient: DbClient, from: number) => Promise<void>\n ) {\n await this.client.open();\n let currentVersion = await this.loadCurrentVersion(targetVersion);\n if (currentVersion === true) {\n return true;\n }\n this.logger.info('Check db: currentVersion %s targetVersion %s', currentVersion, targetVersion);\n\n if (currentVersion === -999) {\n currentVersion = await this.createDb();\n if (currentVersion < 0) {\n await this.checkDb(targetVersion, onSchemaInit, onSchemaUpgrade);\n return;\n }\n } else if (currentVersion < 0) {\n this.logger.error('Db in initialization, exiting ');\n throw new Error('Db in initialization, do not proceed');\n }\n return this._checkDb(currentVersion, targetVersion, onSchemaInit, onSchemaUpgrade);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidware-it/mysql2-client",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "main": "build/src/index.js",
5
5
  "module": "build/esm/index.js",
6
6
  "esnext": "build/esnext/index.js",
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@fluidware-it/saddlebag": "^0.1.1",
27
- "mysql2": "^3.6.2"
27
+ "mysql2": "^3.9.2"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/jest": "^29.5.6",