@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.
- package/CHANGELOG.md +14 -0
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/icons.js +1 -1
- package/docs/assets/icons.svg +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Application.html +17 -17
- package/docs/classes/ConfigLoader.html +3 -3
- package/docs/classes/Database.html +2 -2
- package/docs/classes/DatabaseCastObject.html +2 -2
- package/docs/classes/DatabaseConnection.html +21 -21
- package/docs/classes/DatabaseQueryError.html +6 -6
- package/docs/classes/DeadLockError.html +6 -6
- package/docs/classes/DiskSpaceError.html +5 -5
- package/docs/classes/DropTemporaryTableQuery.html +7 -7
- package/docs/classes/DuplicateEntryError.html +5 -5
- package/docs/classes/EntityNotFoundError.html +5 -5
- package/docs/classes/ExpiredTokenError.html +5 -5
- package/docs/classes/ForbiddenError.html +44 -0
- package/docs/classes/GetMySQLVersion.html +7 -7
- package/docs/classes/Handler.html +2 -2
- package/docs/classes/IllegalStateError.html +5 -5
- package/docs/classes/InternalError.html +5 -5
- package/docs/classes/InvalidCredentialsError.html +5 -5
- package/docs/classes/InvalidValueError.html +5 -5
- package/docs/classes/LineString.html +2 -2
- package/docs/classes/LockWaitTimeoutError.html +6 -6
- package/docs/classes/ManagedDatabaseConnection.html +5 -5
- package/docs/classes/MetricStore.html +7 -0
- package/docs/classes/Middleware.html +2 -2
- package/docs/classes/MissingConfigError.html +5 -5
- package/docs/classes/MissingParameterError.html +5 -5
- package/docs/classes/MySQLConnection.html +25 -25
- package/docs/classes/MySQLDatabase.html +2 -2
- package/docs/classes/NotImplementedError.html +5 -5
- package/docs/classes/Point.html +2 -2
- package/docs/classes/Polygon.html +2 -2
- package/docs/classes/Query.html +7 -7
- package/docs/classes/RawError.html +5 -5
- package/docs/classes/RawQuery.html +7 -7
- package/docs/classes/Request.html +3 -3
- package/docs/classes/Response.html +2 -2
- package/docs/classes/ResponseData.html +3 -3
- package/docs/classes/ServiceProvider.html +2 -2
- package/docs/classes/ServiceResponse.html +2 -2
- package/docs/classes/SetSessionVariableQuery.html +7 -7
- package/docs/classes/StormError.html +5 -5
- package/docs/classes/TemporaryTableQuery.html +7 -7
- package/docs/classes/TimeoutError.html +5 -5
- package/docs/classes/Token.html +2 -2
- package/docs/classes/TokenManager.html +2 -2
- package/docs/classes/Transaction.html +2 -2
- package/docs/classes/UnauthorizedAccessError.html +5 -5
- package/docs/enums/ErrorCode.html +2 -2
- package/docs/enums/ExitCode.html +2 -2
- package/docs/enums/HTTPMethod.html +2 -2
- package/docs/enums/IsolationLevel.html +2 -2
- package/docs/enums/JWTError.html +2 -2
- package/docs/enums/StatusCode.html +2 -2
- package/docs/enums/TransactionAccessLevel.html +2 -2
- package/docs/functions/getInstance.html +1 -1
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +1 -1
- package/docs/interfaces/IAdditionalErrorDetails.html +1 -1
- package/docs/interfaces/ICloudwatchConfig.html +2 -2
- package/docs/interfaces/ICloudwatchCredentials.html +2 -2
- package/docs/interfaces/ICloudwatchStreamConfig.html +2 -2
- package/docs/interfaces/IConfig.html +3 -3
- package/docs/interfaces/IDatabaseConfig.html +2 -2
- package/docs/interfaces/IDatabaseConnection.html +5 -5
- package/docs/interfaces/IDatabasePosition.html +2 -2
- package/docs/interfaces/IErrorResponse.html +2 -2
- package/docs/interfaces/IFormData.html +2 -2
- package/docs/interfaces/IGetMySQLVersionResult.html +2 -2
- package/docs/interfaces/IGetMySQLVersionRow.html +2 -2
- package/docs/interfaces/IInsertQueryResult.html +2 -2
- package/docs/interfaces/IJWTVerifyOptions.html +2 -2
- package/docs/interfaces/IOKPacket.html +2 -2
- package/docs/interfaces/IParameterMap.html +1 -1
- package/docs/interfaces/IQueryable.html +2 -2
- package/docs/interfaces/IRequestResponse.html +2 -2
- package/docs/interfaces/ISetSessionVariableQueryInput.html +2 -2
- package/docs/interfaces/IStormCLIArgs.html +2 -2
- package/docs/interfaces/ITemporaryTableQueryInput.html +2 -2
- package/docs/interfaces/IUpdateQueryResult.html +2 -2
- package/docs/interfaces/formidable.FileJSON.html +1 -1
- package/docs/interfaces/formidable.Part.html +1 -1
- package/docs/types/IDeleteQueryResult.html +1 -1
- package/docs/types/IStoredProcedureResult.html +1 -1
- package/docs/types/TCoordinate.html +1 -1
- package/docs/types/TExpiresIn.html +1 -1
- package/docs/types/TSerializableResponse.html +1 -1
- package/docs/types/TSupportedResponsePrimitives.html +1 -1
- package/docs/types/TSupportedResponseTypes.html +1 -1
- package/lib/Application.d.ts +1 -0
- package/lib/Application.js +5 -0
- package/lib/Application.js.map +1 -1
- package/lib/ForbiddenError.d.ts +10 -0
- package/lib/ForbiddenError.js +39 -0
- package/lib/ForbiddenError.js.map +1 -0
- package/lib/JWTVerifyOptionsParser.d.ts +1 -1
- package/lib/JWTVerifyOptionsParser.js +1 -3
- package/lib/JWTVerifyOptionsParser.js.map +1 -1
- package/lib/MetricStore.d.ts +12 -0
- package/lib/MetricStore.js +49 -0
- package/lib/MetricStore.js.map +1 -0
- package/lib/MySQLConnection.js +11 -20
- package/lib/MySQLConnection.js.map +1 -1
- package/lib/MySQLDatabase.js +2 -0
- package/lib/MySQLDatabase.js.map +1 -1
- package/lib/Transaction.js +1 -1
- package/lib/Transaction.js.map +1 -1
- package/lib/api.d.ts +2 -0
- package/lib/api.js +6 -2
- package/lib/api.js.map +1 -1
- package/lib/handlers/HealthHandler.d.ts +13 -0
- package/lib/handlers/HealthHandler.js +22 -0
- package/lib/handlers/HealthHandler.js.map +1 -0
- package/package.json +5 -5
- package/src/Application.ts +6 -0
- package/src/ForbiddenError.ts +41 -0
- package/src/JWTVerifyOptionsParser.ts +1 -3
- package/src/MetricStore.ts +61 -0
- package/src/MySQLConnection.ts +12 -21
- package/src/MySQLDatabase.ts +2 -1
- package/src/Transaction.ts +1 -1
- package/src/api.ts +2 -0
- 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
|
+
}
|
package/src/MySQLConnection.ts
CHANGED
|
@@ -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
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
rollbackPromise = this.rollback();
|
|
352
|
+
|
|
353
|
+
if (forceClose) {
|
|
354
|
+
if (this.isTransaction()) {
|
|
355
|
+
try {
|
|
356
|
+
await this.rollback();
|
|
357
357
|
}
|
|
358
|
-
|
|
359
|
-
|
|
358
|
+
catch (ex) {
|
|
359
|
+
getInstance().getLogger().error(TAG, ex);
|
|
360
360
|
}
|
|
361
361
|
}
|
|
362
|
-
|
|
363
|
-
rollbackPromise = Promise.resolve();
|
|
364
|
-
}
|
|
362
|
+
}
|
|
365
363
|
|
|
366
|
-
|
|
367
|
-
|
|
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
|
}
|
package/src/MySQLDatabase.ts
CHANGED
|
@@ -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
|
package/src/Transaction.ts
CHANGED
|
@@ -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().
|
|
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
|
+
}
|