@breautek/storm 9.2.7 → 9.3.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.
Files changed (128) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/docs/assets/hierarchy.js +1 -1
  3. package/docs/assets/icons.js +1 -1
  4. package/docs/assets/icons.svg +1 -1
  5. package/docs/assets/navigation.js +1 -1
  6. package/docs/assets/search.js +1 -1
  7. package/docs/classes/Application.html +17 -17
  8. package/docs/classes/ConfigLoader.html +3 -3
  9. package/docs/classes/Database.html +2 -2
  10. package/docs/classes/DatabaseCastObject.html +2 -2
  11. package/docs/classes/DatabaseConnection.html +21 -21
  12. package/docs/classes/DatabaseQueryError.html +6 -6
  13. package/docs/classes/DeadLockError.html +6 -6
  14. package/docs/classes/DiskSpaceError.html +5 -5
  15. package/docs/classes/DropTemporaryTableQuery.html +7 -7
  16. package/docs/classes/DuplicateEntryError.html +5 -5
  17. package/docs/classes/EntityNotFoundError.html +5 -5
  18. package/docs/classes/ExpiredTokenError.html +5 -5
  19. package/docs/classes/ForbiddenError.html +44 -0
  20. package/docs/classes/GetMySQLVersion.html +7 -7
  21. package/docs/classes/Handler.html +2 -2
  22. package/docs/classes/IllegalStateError.html +5 -5
  23. package/docs/classes/InternalError.html +5 -5
  24. package/docs/classes/InvalidCredentialsError.html +5 -5
  25. package/docs/classes/InvalidValueError.html +5 -5
  26. package/docs/classes/LineString.html +2 -2
  27. package/docs/classes/LockWaitTimeoutError.html +6 -6
  28. package/docs/classes/ManagedDatabaseConnection.html +5 -5
  29. package/docs/classes/MetricStore.html +7 -0
  30. package/docs/classes/Middleware.html +2 -2
  31. package/docs/classes/MissingConfigError.html +5 -5
  32. package/docs/classes/MissingParameterError.html +5 -5
  33. package/docs/classes/MySQLConnection.html +25 -25
  34. package/docs/classes/MySQLDatabase.html +2 -2
  35. package/docs/classes/NotImplementedError.html +5 -5
  36. package/docs/classes/Point.html +2 -2
  37. package/docs/classes/Polygon.html +2 -2
  38. package/docs/classes/Query.html +7 -7
  39. package/docs/classes/RawError.html +5 -5
  40. package/docs/classes/RawQuery.html +7 -7
  41. package/docs/classes/Request.html +3 -3
  42. package/docs/classes/Response.html +2 -2
  43. package/docs/classes/ResponseData.html +3 -3
  44. package/docs/classes/ServiceProvider.html +2 -2
  45. package/docs/classes/ServiceResponse.html +2 -2
  46. package/docs/classes/SetSessionVariableQuery.html +7 -7
  47. package/docs/classes/StormError.html +5 -5
  48. package/docs/classes/TemporaryTableQuery.html +7 -7
  49. package/docs/classes/TimeoutError.html +5 -5
  50. package/docs/classes/Token.html +2 -2
  51. package/docs/classes/TokenManager.html +2 -2
  52. package/docs/classes/Transaction.html +2 -2
  53. package/docs/classes/UnauthorizedAccessError.html +5 -5
  54. package/docs/enums/ErrorCode.html +2 -2
  55. package/docs/enums/ExitCode.html +2 -2
  56. package/docs/enums/HTTPMethod.html +2 -2
  57. package/docs/enums/IsolationLevel.html +2 -2
  58. package/docs/enums/JWTError.html +2 -2
  59. package/docs/enums/StatusCode.html +2 -2
  60. package/docs/enums/TransactionAccessLevel.html +2 -2
  61. package/docs/functions/getInstance.html +1 -1
  62. package/docs/hierarchy.html +1 -1
  63. package/docs/index.html +1 -1
  64. package/docs/interfaces/IAdditionalErrorDetails.html +1 -1
  65. package/docs/interfaces/ICloudwatchConfig.html +2 -2
  66. package/docs/interfaces/ICloudwatchCredentials.html +2 -2
  67. package/docs/interfaces/ICloudwatchStreamConfig.html +2 -2
  68. package/docs/interfaces/IConfig.html +3 -3
  69. package/docs/interfaces/IDatabaseConfig.html +2 -2
  70. package/docs/interfaces/IDatabaseConnection.html +5 -5
  71. package/docs/interfaces/IDatabasePosition.html +2 -2
  72. package/docs/interfaces/IErrorResponse.html +2 -2
  73. package/docs/interfaces/IFormData.html +2 -2
  74. package/docs/interfaces/IGetMySQLVersionResult.html +2 -2
  75. package/docs/interfaces/IGetMySQLVersionRow.html +2 -2
  76. package/docs/interfaces/IInsertQueryResult.html +2 -2
  77. package/docs/interfaces/IJWTVerifyOptions.html +2 -2
  78. package/docs/interfaces/IOKPacket.html +2 -2
  79. package/docs/interfaces/IParameterMap.html +1 -1
  80. package/docs/interfaces/IQueryable.html +2 -2
  81. package/docs/interfaces/IRequestResponse.html +2 -2
  82. package/docs/interfaces/ISetSessionVariableQueryInput.html +2 -2
  83. package/docs/interfaces/IStormCLIArgs.html +2 -2
  84. package/docs/interfaces/ITemporaryTableQueryInput.html +2 -2
  85. package/docs/interfaces/IUpdateQueryResult.html +2 -2
  86. package/docs/interfaces/formidable.FileJSON.html +1 -1
  87. package/docs/interfaces/formidable.Part.html +1 -1
  88. package/docs/types/IDeleteQueryResult.html +1 -1
  89. package/docs/types/IStoredProcedureResult.html +1 -1
  90. package/docs/types/TCoordinate.html +1 -1
  91. package/docs/types/TExpiresIn.html +1 -1
  92. package/docs/types/TSerializableResponse.html +1 -1
  93. package/docs/types/TSupportedResponsePrimitives.html +1 -1
  94. package/docs/types/TSupportedResponseTypes.html +1 -1
  95. package/lib/Application.d.ts +1 -0
  96. package/lib/Application.js +5 -0
  97. package/lib/Application.js.map +1 -1
  98. package/lib/ForbiddenError.d.ts +10 -0
  99. package/lib/ForbiddenError.js +39 -0
  100. package/lib/ForbiddenError.js.map +1 -0
  101. package/lib/JWTVerifyOptionsParser.d.ts +1 -1
  102. package/lib/JWTVerifyOptionsParser.js +1 -3
  103. package/lib/JWTVerifyOptionsParser.js.map +1 -1
  104. package/lib/MetricStore.d.ts +12 -0
  105. package/lib/MetricStore.js +49 -0
  106. package/lib/MetricStore.js.map +1 -0
  107. package/lib/MySQLConnection.js +11 -20
  108. package/lib/MySQLConnection.js.map +1 -1
  109. package/lib/MySQLDatabase.js +2 -0
  110. package/lib/MySQLDatabase.js.map +1 -1
  111. package/lib/Transaction.js +1 -1
  112. package/lib/Transaction.js.map +1 -1
  113. package/lib/api.d.ts +2 -0
  114. package/lib/api.js +6 -2
  115. package/lib/api.js.map +1 -1
  116. package/lib/handlers/HealthHandler.d.ts +13 -0
  117. package/lib/handlers/HealthHandler.js +22 -0
  118. package/lib/handlers/HealthHandler.js.map +1 -0
  119. package/package.json +5 -5
  120. package/src/Application.ts +6 -0
  121. package/src/ForbiddenError.ts +41 -0
  122. package/src/JWTVerifyOptionsParser.ts +1 -3
  123. package/src/MetricStore.ts +61 -0
  124. package/src/MySQLConnection.ts +12 -21
  125. package/src/MySQLDatabase.ts +2 -1
  126. package/src/Transaction.ts +1 -1
  127. package/src/api.ts +2 -0
  128. package/src/handlers/HealthHandler.ts +37 -0
@@ -0,0 +1,41 @@
1
+ /*
2
+ Copyright 2017-2026 Norman Breau
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ import {StormError} from './StormError';
18
+ import {ErrorCode} from './ErrorCode';
19
+ import {StatusCode} from './StatusCode';
20
+
21
+ export class ForbiddenError extends StormError {
22
+ public constructor() {
23
+ super();
24
+ }
25
+
26
+ public getMessage(): string {
27
+ return `Access Denied.`;
28
+ }
29
+
30
+ public getCode(): ErrorCode {
31
+ return 0;
32
+ }
33
+
34
+ public getHTTPCode(): StatusCode {
35
+ return StatusCode.ERR_FORBIDDEN;
36
+ }
37
+
38
+ public override getLocaleCode(): string {
39
+ return '@breautek/storm/ForbiddenError/message';
40
+ }
41
+ }
@@ -17,9 +17,7 @@
17
17
  import {IJWTVerifyOptions} from './IJWTVerifyOptions';
18
18
 
19
19
  export class JWTVerifyOptionsParser {
20
- constructor() {
21
- throw new Error('JWTVerifyOptionsParser is an static class.');
22
- }
20
+ private constructor() {}
23
21
 
24
22
  // Parses IJWTVerifyOptions to jwt options
25
23
  public static parse(options: IJWTVerifyOptions): any {
@@ -0,0 +1,61 @@
1
+
2
+ export type TSupportedMetricStoreValues = string | number | boolean;
3
+
4
+ export class MetricStore {
5
+ private static $instance: MetricStore;
6
+
7
+ private $data: Record<string, TSupportedMetricStoreValues>;
8
+
9
+ private constructor() {
10
+ this.$data = {};
11
+ }
12
+
13
+ public static getInstance(): MetricStore {
14
+ if (!MetricStore.$instance) {
15
+ MetricStore.$instance = new MetricStore();
16
+ }
17
+
18
+ return MetricStore.$instance;
19
+ }
20
+
21
+ public purge(): void {
22
+ this.$data = {};
23
+ }
24
+
25
+ public set(key: string, value: TSupportedMetricStoreValues): void {
26
+ this.$data[key] = value;
27
+ }
28
+
29
+ public get(key: string): TSupportedMetricStoreValues | null {
30
+ let value: TSupportedMetricStoreValues = this.$data[key];
31
+ if (value === undefined) return null;
32
+ return value;
33
+ }
34
+
35
+ public increment(key: string): void {
36
+ let value: TSupportedMetricStoreValues = this.get(key);
37
+
38
+ if (!value) {
39
+ value = 0;
40
+ }
41
+
42
+ if (typeof value !== 'number') {
43
+ this.set(key, 0);
44
+ return;
45
+ }
46
+
47
+ value++;
48
+ this.set(key, value);
49
+ }
50
+
51
+ public decrement(key: string): void {
52
+ let value: TSupportedMetricStoreValues = this.get(key);
53
+ if (value === null || value === undefined || typeof value !== 'number') {
54
+ this.set(key, 0);
55
+ return;
56
+ }
57
+
58
+ value--;
59
+ this.set(key, value);
60
+ }
61
+ }
@@ -40,6 +40,7 @@ import { GetProcessList, IGetProcessListOutput } from './private/GetProcessList'
40
40
  import { GetMySQLVersion, IGetMySQLVersionResult } from './GetMySQLVersion';
41
41
  import { GetPrimaryPositionQuery } from './private/GetPrimaryPositionQuery';
42
42
  import { queryFormatter } from './mysql/queryFormatter';
43
+ import { MetricStore } from './MetricStore';
43
44
 
44
45
  const DEFAULT_HIGH_WATERMARK: number = 512; // in number of result objects
45
46
  const TAG: string = 'MySQLConnection';
@@ -342,35 +343,25 @@ export class MySQLConnection extends DatabaseConnection<MySQL.PoolConnection> {
342
343
  });
343
344
  }
344
345
 
345
- protected _close(forceClose: boolean): Promise<void> {
346
+ protected async _close(forceClose: boolean): Promise<void> {
346
347
  if (!forceClose && this.isTransaction()) {
347
348
  return Promise.reject(new Error('Cannot close a connection while there is an active transaction. Use commit or rollback first.'));
348
349
  }
349
350
 
350
351
  this.$opened = false;
351
-
352
- return new Promise<void>((resolve, reject) => {
353
- let rollbackPromise: Promise<void> = null;
354
- if (forceClose) {
355
- if (this.isTransaction()) {
356
- rollbackPromise = this.rollback();
352
+
353
+ if (forceClose) {
354
+ if (this.isTransaction()) {
355
+ try {
356
+ await this.rollback();
357
357
  }
358
- else {
359
- rollbackPromise = Promise.resolve();
358
+ catch (ex) {
359
+ getInstance().getLogger().error(TAG, ex);
360
360
  }
361
361
  }
362
- else {
363
- rollbackPromise = Promise.resolve();
364
- }
362
+ }
365
363
 
366
- rollbackPromise.then(() => {
367
- this.getAPI().release();
368
- resolve();
369
- }).catch((error: any) => {
370
- getInstance().getLogger().error(TAG, error);
371
- this.getAPI().release();
372
- resolve();
373
- });
374
- });
364
+ this.getAPI().release();
365
+ MetricStore.getInstance().decrement('mysql.active_connections');
375
366
  }
376
367
  }
@@ -21,6 +21,7 @@ import {getInstance} from './instance';
21
21
  import { IDatabasePosition } from './IDatabasePosition';
22
22
  import { ConnectionReplicationWaiter } from './private/ConnectionReplicationWaiter';
23
23
  import { ILogger } from '@arashi/interfaces';
24
+ import { MetricStore } from './MetricStore';
24
25
 
25
26
  const TAG: string = 'MySQLDatabase';
26
27
 
@@ -69,6 +70,7 @@ export class MySQLDatabase extends Database<MySQL.PoolOptions, MySQL.PoolConnect
69
70
  return;
70
71
  }
71
72
 
73
+ MetricStore.getInstance().increment('mysql.active_connections');
72
74
  resolve(new MySQLConnection(connection, instantationStack, !requireWriteAccess));
73
75
  });
74
76
  });
@@ -85,7 +87,6 @@ export class MySQLDatabase extends Database<MySQL.PoolOptions, MySQL.PoolConnect
85
87
  logger.trace(TAG, `Replication Enabled: ${conn.hasReplicationEnabled() ? 'true' : 'false'}`);
86
88
  logger.trace(TAG, `Connection Replicating: ${conn.isReplication() ? 'true' : 'false'}`);
87
89
 
88
-
89
90
  if (conn.hasReplicationEnabled() && conn.isReplication() && position && position.page && position.position) {
90
91
  logger.trace(TAG, 'Connection is waiting on Replication');
91
92
  // master connections will not wait on database positions
@@ -83,7 +83,7 @@ export class Transaction implements IQueryable<void> {
83
83
  let attemptCount: number = 0;
84
84
  do {
85
85
  attemptCount++;
86
- this.$application.getLogger().info(TAG, `Starting transaction attempt ${attemptCount} of ${this.$retryLimit === Infinity ? 'Infinity' : this.$retryLimit.toString()}`);
86
+ this.$application.getLogger().trace(TAG, `Starting transaction attempt ${attemptCount} of ${this.$retryLimit === Infinity ? 'Infinity' : this.$retryLimit.toString()}`);
87
87
  await connection.startTransaction(this.$isolationLevel, this.$accessLevel);
88
88
  try {
89
89
  await this.$executor(connection);
package/src/api.ts CHANGED
@@ -48,6 +48,7 @@ export {GetMySQLVersion, IGetMySQLVersionResult, IGetMySQLVersionRow} from './Ge
48
48
  // Errors
49
49
  export {ErrorCode} from './ErrorCode';
50
50
  export {RawError} from './RawError';
51
+ export {ForbiddenError} from './ForbiddenError';
51
52
  export {
52
53
  StormError,
53
54
  IErrorResponse,
@@ -104,6 +105,7 @@ export {TokenManager, TExpiresIn} from './TokenManager';
104
105
 
105
106
  // Utils
106
107
  export {ExitCode} from './ExitCode';
108
+ export {MetricStore} from './MetricStore';
107
109
 
108
110
  // Database Objects
109
111
  export {TCoordinate} from './TCoordinate';
@@ -0,0 +1,37 @@
1
+
2
+ import { IAuthTokenData } from '@arashi/token';
3
+ import { Application } from '../Application';
4
+ import {Handler} from '../Handler';
5
+ import { Request } from '../Request';
6
+ import { MetricStore } from '../MetricStore';
7
+ import { ForbiddenError } from '../ForbiddenError';
8
+
9
+ export interface IHealthHandlerMySQLStats {
10
+ activeConnections: number;
11
+ }
12
+
13
+ export interface IHealthHandlerOutput {
14
+ mysql: IHealthHandlerMySQLStats;
15
+ }
16
+
17
+ export class HealthHandler extends Handler<
18
+ Application,
19
+ void,
20
+ IHealthHandlerOutput
21
+ > {
22
+ protected override async _get(request: Request<void, IAuthTokenData>): Promise<IHealthHandlerOutput> {
23
+
24
+ if (request.getIP() !== '127.0.0.1') {
25
+ throw new ForbiddenError();
26
+ }
27
+
28
+ let metrics: MetricStore = MetricStore.getInstance();
29
+ let out: IHealthHandlerOutput = {
30
+ mysql: {
31
+ activeConnections: metrics.get('mysql.active_connections') as number
32
+ }
33
+ };
34
+
35
+ return out;
36
+ }
37
+ }