@bitblit/ratchet-aws-node-only 4.0.99-alpha → 4.0.102-alpha
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/dist/{types/athena → athena}/alb-athena-log-ratchet.d.ts +2 -2
- package/dist/{es/athena → athena}/alb-athena-log-ratchet.js +55 -52
- package/dist/athena/alb-athena-log-ratchet.spec.d.ts +1 -0
- package/dist/athena/alb-athena-log-ratchet.spec.js +25 -0
- package/dist/{es/athena → athena}/athena-ratchet.js +9 -6
- package/dist/athena/athena-ratchet.spec.d.ts +1 -0
- package/dist/athena/athena-ratchet.spec.js +27 -0
- package/dist/{types/build → build}/ratchet-aws-node-only-info.d.ts +1 -1
- package/dist/{types/cli → cli}/dynamo-exporter.d.ts +2 -2
- package/dist/{es/cli → cli}/dynamo-exporter.js +4 -4
- package/dist/{types/cli → cli}/ratchet-cli-handler.d.ts +2 -2
- package/dist/{es/cli → cli}/ratchet-cli-handler.js +4 -4
- package/dist/{es/cli → cli}/site-uploader/site-uploader.js +5 -2
- package/dist/{es/cli → cli}/start-instance-and-ssh.js +8 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mail/inbound/email-to-db-insert-processor.d.ts +10 -0
- package/dist/mail/inbound/email-to-db-insert-processor.js +89 -0
- package/dist/mail/inbound/inbound-email-ratchet.d.ts +10 -0
- package/dist/{es/mail → mail}/inbound/inbound-email-ratchet.js +16 -24
- package/dist/mail/inbound/inbound-email-ratchet.spec.d.ts +1 -0
- package/dist/mail/inbound/inbound-email-ratchet.spec.js +18 -0
- package/dist/mail/inbound/parsed-email-processor.d.ts +5 -0
- package/dist/mail/inbound/parsed-email-processor.js +1 -0
- package/dist/mail/inbound/sample-email-processor.d.ts +6 -0
- package/dist/mail/inbound/sample-email-processor.js +8 -0
- package/package.json +8 -10
- package/dist/cjs/athena/alb-athena-log-ratchet.js +0 -158
- package/dist/cjs/athena/athena-ratchet.js +0 -159
- package/dist/cjs/build/ratchet-aws-node-only-info.js +0 -18
- package/dist/cjs/cli/dynamo-exporter.js +0 -81
- package/dist/cjs/cli/ratchet-cli-handler.js +0 -19
- package/dist/cjs/cli/site-uploader/site-uploader.js +0 -117
- package/dist/cjs/cli/start-instance-and-ssh.js +0 -67
- package/dist/cjs/index.js +0 -11
- package/dist/cjs/mail/inbound/inbound-email-ratchet.js +0 -54
- package/dist/es/index.js +0 -8
- package/dist/tsconfig.cjs.tsbuildinfo +0 -1
- package/dist/tsconfig.es.tsbuildinfo +0 -1
- package/dist/tsconfig.types.tsbuildinfo +0 -1
- package/dist/types/index.d.ts +0 -11
- package/dist/types/mail/inbound/inbound-email-ratchet.d.ts +0 -18
- /package/dist/{types/athena → athena}/athena-ratchet.d.ts +0 -0
- /package/dist/{es/build → build}/ratchet-aws-node-only-info.js +0 -0
- /package/dist/{types/cli → cli}/site-uploader/site-uploader.d.ts +0 -0
- /package/dist/{types/cli → cli}/start-instance-and-ssh.d.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import { ReadStream } from 'fs';
|
|
3
|
-
import { AthenaRatchet } from './athena-ratchet';
|
|
3
|
+
import { AthenaRatchet } from './athena-ratchet.js';
|
|
4
4
|
import { S3Client } from '@aws-sdk/client-s3';
|
|
5
5
|
export declare class AlbAthenaLogRatchet {
|
|
6
6
|
private athena;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { readFileSync } from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { Logger } from '@bitblit/ratchet-common';
|
|
4
|
-
import { RequireRatchet } from '@bitblit/ratchet-common';
|
|
5
|
-
import { StringRatchet } from '@bitblit/ratchet-common';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { Logger } from '@bitblit/ratchet-common/dist/logger/logger.js';
|
|
4
|
+
import { RequireRatchet } from '@bitblit/ratchet-common/dist/lang/require-ratchet.js';
|
|
5
|
+
import { StringRatchet } from '@bitblit/ratchet-common/dist/lang/string-ratchet.js';
|
|
6
|
+
import { EsmRatchet } from '@bitblit/ratchet-common/dist/lang/esm-ratchet.js';
|
|
7
|
+
import { S3Ratchet } from '@bitblit/ratchet-aws/dist/s3/s3-ratchet.js';
|
|
8
|
+
import { CsvRatchet } from '@bitblit/ratchet-node-only/dist/csv/csv-ratchet.js';
|
|
8
9
|
export class AlbAthenaLogRatchet {
|
|
10
|
+
athena;
|
|
11
|
+
athenaTableName;
|
|
9
12
|
constructor(athena, athenaTableName) {
|
|
10
13
|
this.athena = athena;
|
|
11
14
|
this.athenaTableName = athenaTableName;
|
|
@@ -59,7 +62,7 @@ export class AlbAthenaLogRatchet {
|
|
|
59
62
|
Logger.info('Drop error : %j', err);
|
|
60
63
|
}
|
|
61
64
|
}
|
|
62
|
-
let tableCreateQry = readFileSync(path.join(
|
|
65
|
+
let tableCreateQry = readFileSync(path.join(EsmRatchet.fetchDirName(), '../static/albAthenaTableCreate.txt')).toString();
|
|
63
66
|
tableCreateQry = tableCreateQry.split('{{TABLE NAME}}').join(this.athenaTableName);
|
|
64
67
|
tableCreateQry = tableCreateQry.split('{{ALB_LOG_ROOT}}').join(rootPath);
|
|
65
68
|
Logger.info('Creating table with %s', tableCreateQry);
|
|
@@ -104,50 +107,50 @@ export class AlbAthenaLogRatchet {
|
|
|
104
107
|
const result = await this.athena.runQueryToFile(qrySt, null, outputFileName);
|
|
105
108
|
return result;
|
|
106
109
|
}
|
|
110
|
+
static CREATE_TABLE_STATEMENT = 'CREATE EXTERNAL TABLE IF NOT EXISTS `{{TABLE NAME}}`(\n' +
|
|
111
|
+
" `type` string COMMENT '',\n" +
|
|
112
|
+
" `time` string COMMENT '',\n" +
|
|
113
|
+
" `elb` string COMMENT '',\n" +
|
|
114
|
+
" `client_ip` string COMMENT '',\n" +
|
|
115
|
+
" `client_port` int COMMENT '',\n" +
|
|
116
|
+
" `target_ip` string COMMENT '',\n" +
|
|
117
|
+
" `target_port` int COMMENT '',\n" +
|
|
118
|
+
" `request_processing_time` double COMMENT '',\n" +
|
|
119
|
+
" `target_processing_time` double COMMENT '',\n" +
|
|
120
|
+
" `response_processing_time` double COMMENT '',\n" +
|
|
121
|
+
" `elb_status_code` string COMMENT '',\n" +
|
|
122
|
+
" `target_status_code` string COMMENT '',\n" +
|
|
123
|
+
" `received_bytes` bigint COMMENT '',\n" +
|
|
124
|
+
" `sent_bytes` bigint COMMENT '',\n" +
|
|
125
|
+
" `request_verb` string COMMENT '',\n" +
|
|
126
|
+
" `request_url` string COMMENT '',\n" +
|
|
127
|
+
" `request_proto` string COMMENT '',\n" +
|
|
128
|
+
" `user_agent` string COMMENT '',\n" +
|
|
129
|
+
" `ssl_cipher` string COMMENT '',\n" +
|
|
130
|
+
" `ssl_protocol` string COMMENT '',\n" +
|
|
131
|
+
" `target_group_arn` string COMMENT '',\n" +
|
|
132
|
+
" `trace_id` string COMMENT '',\n" +
|
|
133
|
+
" `domain_name` string COMMENT '',\n" +
|
|
134
|
+
" `chosen_cert_arn` string COMMENT '',\n" +
|
|
135
|
+
" `matched_rule_priority` string COMMENT '',\n" +
|
|
136
|
+
" `request_creation_time` string COMMENT '',\n" +
|
|
137
|
+
" `actions_executed` string COMMENT '',\n" +
|
|
138
|
+
" `redirect_url` string COMMENT '',\n" +
|
|
139
|
+
" `lambda_error_reason` string COMMENT '',\n" +
|
|
140
|
+
" `target_port_list` string COMMENT '',\n" +
|
|
141
|
+
" `target_status_code_list` string COMMENT '',\n" +
|
|
142
|
+
" `new_field` string COMMENT '')\n" +
|
|
143
|
+
'PARTITIONED BY (\n' +
|
|
144
|
+
' `date_utc_partition` string\n' +
|
|
145
|
+
')\n' +
|
|
146
|
+
'ROW FORMAT SERDE\n' +
|
|
147
|
+
" 'org.apache.hadoop.hive.serde2.RegexSerDe'\n" +
|
|
148
|
+
'WITH SERDEPROPERTIES (\n' +
|
|
149
|
+
' \'input.regex\'=\'([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \\"([^ ]*) ([^ ]*) (- |[^ ]*)\\" \\"([^\\"]*)\\" ([A-Z0-9-]+) ([A-Za-z0-9.-]*) ([^ ]*) \\"([^\\"]*)\\" \\"([^\\"]*)\\" \\"([^\\"]*)\\" ([-.0-9]*) ([^ ]*) \\"([^\\"]*)\\" \\"([^\\"]*)\\" \\"([^ ]*)\\" \\"([^s]+)\\" \\"([^s]+)\\"(.*)\')\n' +
|
|
150
|
+
'STORED AS INPUTFORMAT\n' +
|
|
151
|
+
" 'org.apache.hadoop.mapred.TextInputFormat'\n" +
|
|
152
|
+
'OUTPUTFORMAT\n' +
|
|
153
|
+
" 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'\n" +
|
|
154
|
+
'LOCATION\n' +
|
|
155
|
+
" '{{ALB_LOG_ROOT}}'\n";
|
|
107
156
|
}
|
|
108
|
-
AlbAthenaLogRatchet.CREATE_TABLE_STATEMENT = 'CREATE EXTERNAL TABLE IF NOT EXISTS `{{TABLE NAME}}`(\n' +
|
|
109
|
-
" `type` string COMMENT '',\n" +
|
|
110
|
-
" `time` string COMMENT '',\n" +
|
|
111
|
-
" `elb` string COMMENT '',\n" +
|
|
112
|
-
" `client_ip` string COMMENT '',\n" +
|
|
113
|
-
" `client_port` int COMMENT '',\n" +
|
|
114
|
-
" `target_ip` string COMMENT '',\n" +
|
|
115
|
-
" `target_port` int COMMENT '',\n" +
|
|
116
|
-
" `request_processing_time` double COMMENT '',\n" +
|
|
117
|
-
" `target_processing_time` double COMMENT '',\n" +
|
|
118
|
-
" `response_processing_time` double COMMENT '',\n" +
|
|
119
|
-
" `elb_status_code` string COMMENT '',\n" +
|
|
120
|
-
" `target_status_code` string COMMENT '',\n" +
|
|
121
|
-
" `received_bytes` bigint COMMENT '',\n" +
|
|
122
|
-
" `sent_bytes` bigint COMMENT '',\n" +
|
|
123
|
-
" `request_verb` string COMMENT '',\n" +
|
|
124
|
-
" `request_url` string COMMENT '',\n" +
|
|
125
|
-
" `request_proto` string COMMENT '',\n" +
|
|
126
|
-
" `user_agent` string COMMENT '',\n" +
|
|
127
|
-
" `ssl_cipher` string COMMENT '',\n" +
|
|
128
|
-
" `ssl_protocol` string COMMENT '',\n" +
|
|
129
|
-
" `target_group_arn` string COMMENT '',\n" +
|
|
130
|
-
" `trace_id` string COMMENT '',\n" +
|
|
131
|
-
" `domain_name` string COMMENT '',\n" +
|
|
132
|
-
" `chosen_cert_arn` string COMMENT '',\n" +
|
|
133
|
-
" `matched_rule_priority` string COMMENT '',\n" +
|
|
134
|
-
" `request_creation_time` string COMMENT '',\n" +
|
|
135
|
-
" `actions_executed` string COMMENT '',\n" +
|
|
136
|
-
" `redirect_url` string COMMENT '',\n" +
|
|
137
|
-
" `lambda_error_reason` string COMMENT '',\n" +
|
|
138
|
-
" `target_port_list` string COMMENT '',\n" +
|
|
139
|
-
" `target_status_code_list` string COMMENT '',\n" +
|
|
140
|
-
" `new_field` string COMMENT '')\n" +
|
|
141
|
-
'PARTITIONED BY (\n' +
|
|
142
|
-
' `date_utc_partition` string\n' +
|
|
143
|
-
')\n' +
|
|
144
|
-
'ROW FORMAT SERDE\n' +
|
|
145
|
-
" 'org.apache.hadoop.hive.serde2.RegexSerDe'\n" +
|
|
146
|
-
'WITH SERDEPROPERTIES (\n' +
|
|
147
|
-
' \'input.regex\'=\'([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \\"([^ ]*) ([^ ]*) (- |[^ ]*)\\" \\"([^\\"]*)\\" ([A-Z0-9-]+) ([A-Za-z0-9.-]*) ([^ ]*) \\"([^\\"]*)\\" \\"([^\\"]*)\\" \\"([^\\"]*)\\" ([-.0-9]*) ([^ ]*) \\"([^\\"]*)\\" \\"([^\\"]*)\\" \\"([^ ]*)\\" \\"([^s]+)\\" \\"([^s]+)\\"(.*)\')\n' +
|
|
148
|
-
'STORED AS INPUTFORMAT\n' +
|
|
149
|
-
" 'org.apache.hadoop.mapred.TextInputFormat'\n" +
|
|
150
|
-
'OUTPUTFORMAT\n' +
|
|
151
|
-
" 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'\n" +
|
|
152
|
-
'LOCATION\n' +
|
|
153
|
-
" '{{ALB_LOG_ROOT}}'\n";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AthenaRatchet } from './athena-ratchet.js';
|
|
2
|
+
import { Logger } from '@bitblit/ratchet-common/dist/logger/logger.js';
|
|
3
|
+
import { LoggerLevelName } from '@bitblit/ratchet-common/dist/logger/logger-level-name.js';
|
|
4
|
+
import { TimeZoneRatchet } from '@bitblit/ratchet-common/dist/lang/time-zone-ratchet.js';
|
|
5
|
+
import { AlbAthenaLogRatchet } from './alb-athena-log-ratchet.js';
|
|
6
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
7
|
+
import { AthenaClient } from '@aws-sdk/client-athena';
|
|
8
|
+
describe('#AlbAthenaLogRatchet', function () {
|
|
9
|
+
xit('should test a query', async () => {
|
|
10
|
+
Logger.setLevel(LoggerLevelName.debug);
|
|
11
|
+
const athena = new AthenaClient({ region: 'us-east-1' });
|
|
12
|
+
const s3 = new S3Client({ region: 'us-east-1' });
|
|
13
|
+
const outputDir = 's3://alb-log-bucket/temp';
|
|
14
|
+
const athRatchet = new AthenaRatchet(athena, s3, outputDir);
|
|
15
|
+
const srv = new AlbAthenaLogRatchet(athRatchet, 'alb_logs.log_table');
|
|
16
|
+
const qry = {
|
|
17
|
+
startTimeEpochMS: TimeZoneRatchet.PACIFIC.startOfTodayEpochMS(),
|
|
18
|
+
endTimeEpochMS: TimeZoneRatchet.PACIFIC.startOfTodayEpochMS() + 1000 * 60 * 10,
|
|
19
|
+
limit: 10,
|
|
20
|
+
};
|
|
21
|
+
const result = await srv.fetchAlbLogRecords(qry);
|
|
22
|
+
expect(result).toBeTruthy();
|
|
23
|
+
Logger.info('Got objects : %j', result);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { GetNamedQueryCommand, GetQueryExecutionCommand, ListNamedQueriesCommand, StartQueryExecutionCommand, } from '@aws-sdk/client-athena';
|
|
2
|
-
import { StringRatchet } from '@bitblit/ratchet-common';
|
|
3
|
-
import { Logger } from '@bitblit/ratchet-common';
|
|
4
|
-
import { StopWatch } from '@bitblit/ratchet-common';
|
|
5
|
-
import { PromiseRatchet } from '@bitblit/ratchet-common';
|
|
2
|
+
import { StringRatchet } from '@bitblit/ratchet-common/dist/lang/string-ratchet.js';
|
|
3
|
+
import { Logger } from '@bitblit/ratchet-common/dist/logger/logger.js';
|
|
4
|
+
import { StopWatch } from '@bitblit/ratchet-common/dist/lang/stop-watch.js';
|
|
5
|
+
import { PromiseRatchet } from '@bitblit/ratchet-common/dist/lang/promise-ratchet.js';
|
|
6
6
|
import { GetObjectCommand } from '@aws-sdk/client-s3';
|
|
7
7
|
import tmp from 'tmp';
|
|
8
8
|
import fs from 'fs';
|
|
9
|
-
import { CsvRatchet } from '@bitblit/ratchet-node-only';
|
|
10
|
-
import { RequireRatchet } from '@bitblit/ratchet-common';
|
|
9
|
+
import { CsvRatchet } from '@bitblit/ratchet-node-only/dist/csv/csv-ratchet.js';
|
|
10
|
+
import { RequireRatchet } from '@bitblit/ratchet-common/dist/lang/require-ratchet.js';
|
|
11
11
|
export class AthenaRatchet {
|
|
12
|
+
athena;
|
|
13
|
+
s3;
|
|
14
|
+
outputLocation;
|
|
12
15
|
constructor(athena, s3, outputLocation) {
|
|
13
16
|
this.athena = athena;
|
|
14
17
|
this.s3 = s3;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AthenaRatchet } from './athena-ratchet.js';
|
|
2
|
+
import { Logger } from '@bitblit/ratchet-common/dist/logger/logger.js';
|
|
3
|
+
import { AthenaClient, GetQueryExecutionCommand, StartQueryExecutionCommand, } from '@aws-sdk/client-athena';
|
|
4
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
5
|
+
import { mockClient } from 'aws-sdk-client-mock';
|
|
6
|
+
let mockAthena;
|
|
7
|
+
let mockS3;
|
|
8
|
+
describe('#AthenaRatchet', function () {
|
|
9
|
+
mockAthena = mockClient(AthenaClient);
|
|
10
|
+
mockS3 = mockClient(S3Client);
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
mockAthena.reset();
|
|
13
|
+
mockS3.reset();
|
|
14
|
+
});
|
|
15
|
+
xit('should test a query', async () => {
|
|
16
|
+
const outputDir = 's3://your-bucket/your-prefix';
|
|
17
|
+
const qry = 'select * from test limit 20000';
|
|
18
|
+
mockAthena.on(StartQueryExecutionCommand).resolves({ jobName: 'b' });
|
|
19
|
+
mockAthena.on(GetQueryExecutionCommand).resolves({
|
|
20
|
+
QueryExecution: { ResultConfiguration: { OutputLocation: 'test' }, Status: { State: 'SUCCEEDED' } },
|
|
21
|
+
});
|
|
22
|
+
const ratchet = new AthenaRatchet(mockAthena, mockS3, outputDir);
|
|
23
|
+
const result = await ratchet.runQueryToObjects(qry);
|
|
24
|
+
expect(result).toBeTruthy();
|
|
25
|
+
Logger.info('Got objects : %j', result);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BuildInformation } from '@bitblit/ratchet-common';
|
|
1
|
+
import { BuildInformation } from '@bitblit/ratchet-common/dist/build/build-information.js';
|
|
2
2
|
export declare class RatchetAwsNodeOnlyInfo {
|
|
3
3
|
private constructor();
|
|
4
4
|
static buildInformation(): BuildInformation;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import { WriteStream } from 'fs';
|
|
3
|
-
import { DynamoRatchet } from '@bitblit/ratchet-aws';
|
|
3
|
+
import { DynamoRatchet } from '@bitblit/ratchet-aws/dist/dynamodb/dynamo-ratchet.js';
|
|
4
4
|
import { QueryCommandInput, ScanCommandInput } from '@aws-sdk/client-dynamodb';
|
|
5
5
|
export declare class DynamoExporter {
|
|
6
6
|
private constructor();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { StringRatchet } from '@bitblit/ratchet-common';
|
|
2
|
-
import { Logger } from '@bitblit/ratchet-common';
|
|
3
|
-
import { PromiseRatchet } from '@bitblit/ratchet-common';
|
|
4
|
-
import { RequireRatchet } from '@bitblit/ratchet-common';
|
|
1
|
+
import { StringRatchet } from '@bitblit/ratchet-common/dist/lang/string-ratchet.js';
|
|
2
|
+
import { Logger } from '@bitblit/ratchet-common/dist/logger/logger.js';
|
|
3
|
+
import { PromiseRatchet } from '@bitblit/ratchet-common/dist/lang/promise-ratchet.js';
|
|
4
|
+
import { RequireRatchet } from '@bitblit/ratchet-common/dist/lang/require-ratchet.js';
|
|
5
5
|
import fs from 'fs';
|
|
6
6
|
import readline from 'readline';
|
|
7
7
|
export class DynamoExporter {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AbstractRatchetCliHandler } from '@bitblit/ratchet-node-only';
|
|
2
|
-
import { BuildInformation } from '@bitblit/ratchet-common/dist/
|
|
1
|
+
import { AbstractRatchetCliHandler } from '@bitblit/ratchet-node-only/dist/cli/abstract-ratchet-cli-handler.js';
|
|
2
|
+
import { BuildInformation } from '@bitblit/ratchet-common/dist/build/build-information.js';
|
|
3
3
|
export declare class RatchetCliHandler extends AbstractRatchetCliHandler {
|
|
4
4
|
fetchHandlerMap(): Record<string, any>;
|
|
5
5
|
fetchVersionInfo(): BuildInformation;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { AbstractRatchetCliHandler } from '@bitblit/ratchet-node-only';
|
|
2
|
-
import { SiteUploader } from './site-uploader/site-uploader';
|
|
3
|
-
import { StartInstanceAndSsh } from './start-instance-and-ssh';
|
|
4
|
-
import { RatchetAwsNodeOnlyInfo } from '../build/ratchet-aws-node-only-info';
|
|
1
|
+
import { AbstractRatchetCliHandler } from '@bitblit/ratchet-node-only/dist/cli/abstract-ratchet-cli-handler.js';
|
|
2
|
+
import { SiteUploader } from './site-uploader/site-uploader.js';
|
|
3
|
+
import { StartInstanceAndSsh } from './start-instance-and-ssh.js';
|
|
4
|
+
import { RatchetAwsNodeOnlyInfo } from '../build/ratchet-aws-node-only-info.js';
|
|
5
5
|
export class RatchetCliHandler extends AbstractRatchetCliHandler {
|
|
6
6
|
fetchHandlerMap() {
|
|
7
7
|
return {
|
|
@@ -3,11 +3,14 @@ import walk from 'walk';
|
|
|
3
3
|
import { S3Client } from '@aws-sdk/client-s3';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import mime from 'mime-types';
|
|
6
|
-
import { Logger } from '@bitblit/ratchet-common';
|
|
6
|
+
import { Logger } from '@bitblit/ratchet-common/dist/logger/logger.js';
|
|
7
7
|
import { Upload } from '@aws-sdk/lib-storage';
|
|
8
8
|
export class SiteUploader {
|
|
9
|
+
srcDir;
|
|
10
|
+
bucketName;
|
|
11
|
+
config;
|
|
12
|
+
s3 = new S3Client({ region: 'us-east-1' });
|
|
9
13
|
constructor(srcDir, bucketName, configFile) {
|
|
10
|
-
this.s3 = new S3Client({ region: 'us-east-1' });
|
|
11
14
|
this.srcDir = srcDir;
|
|
12
15
|
this.bucketName = bucketName;
|
|
13
16
|
this.config = JSON.parse(fs.readFileSync(configFile).toString('ascii'));
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import { Logger } from '@bitblit/ratchet-common';
|
|
2
|
-
import { Ec2Ratchet } from '@bitblit/ratchet-aws';
|
|
1
|
+
import { Logger } from '@bitblit/ratchet-common/dist/logger/logger.js';
|
|
2
|
+
import { Ec2Ratchet } from '@bitblit/ratchet-aws/dist/ec2/ec2-ratchet.js';
|
|
3
3
|
import { spawnSync } from 'child_process';
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import os from 'os';
|
|
6
6
|
import path from 'path';
|
|
7
7
|
export class StartInstanceAndSsh {
|
|
8
|
+
instanceId;
|
|
9
|
+
publicKeyFile;
|
|
10
|
+
instanceOsUser;
|
|
11
|
+
region;
|
|
12
|
+
availabilityZone;
|
|
13
|
+
ec2Ratchet;
|
|
8
14
|
constructor(instanceId, publicKeyFile = path.join(os.homedir(), '.ssh', 'id_rsa.pub'), instanceOsUser = 'ec2-user', region = 'us-east-1', availabilityZone = 'us-east-1a') {
|
|
9
15
|
this.instanceId = instanceId;
|
|
10
16
|
this.publicKeyFile = publicKeyFile;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ParsedEmailProcessor } from './parsed-email-processor.js';
|
|
2
|
+
import { ParsedMail } from 'mailparser';
|
|
3
|
+
export declare class EmailToDbInsertProcessor implements ParsedEmailProcessor<EmailToDbStatement[]> {
|
|
4
|
+
canProcess(mail: ParsedMail): boolean;
|
|
5
|
+
processEmail(msg: ParsedMail): Promise<EmailToDbStatement[]>;
|
|
6
|
+
}
|
|
7
|
+
export interface EmailToDbStatement {
|
|
8
|
+
statement: string;
|
|
9
|
+
params?: any[];
|
|
10
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { RequireRatchet } from '@bitblit/ratchet-common/dist/lang/require-ratchet.js';
|
|
2
|
+
import { Logger } from '@bitblit/ratchet-common/dist/logger/logger.js';
|
|
3
|
+
import { MultiStream } from '@bitblit/ratchet-common/dist/stream/multi-stream.js';
|
|
4
|
+
import unzipper from 'unzipper';
|
|
5
|
+
import { CsvRatchet } from '@bitblit/ratchet-node-only/dist/csv/csv-ratchet.js';
|
|
6
|
+
import { DateTime } from 'luxon';
|
|
7
|
+
export class EmailToDbInsertProcessor {
|
|
8
|
+
canProcess(mail) {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
async processEmail(msg) {
|
|
12
|
+
const rval = [];
|
|
13
|
+
try {
|
|
14
|
+
RequireRatchet.notNullOrUndefined(msg, 'msg');
|
|
15
|
+
Logger.info('Processing Broadsign reach inbound inventory email');
|
|
16
|
+
const data = msg.attachments[0].content;
|
|
17
|
+
Logger.info('Unzipping attachment');
|
|
18
|
+
const rs = new MultiStream(data);
|
|
19
|
+
let wBuf = null;
|
|
20
|
+
const prom = rs
|
|
21
|
+
.pipe(unzipper.Parse())
|
|
22
|
+
.on('entry', async (entry) => {
|
|
23
|
+
if (entry.path.toLowerCase().endsWith('csv')) {
|
|
24
|
+
wBuf = await entry.buffer();
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
Logger.info('Pass: %s', entry.path);
|
|
28
|
+
entry.autodrain();
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
.promise();
|
|
32
|
+
await prom;
|
|
33
|
+
const csvParsed = await CsvRatchet.stringParse(wBuf.toString(), (o) => o, {
|
|
34
|
+
columns: false,
|
|
35
|
+
skip_empty_lines: true,
|
|
36
|
+
});
|
|
37
|
+
if (csvParsed.length > 1) {
|
|
38
|
+
const dropTable = 'drop table if exists sample';
|
|
39
|
+
let createTable = 'create table sample (pump_date varchar(255),';
|
|
40
|
+
const colNames = csvParsed[0];
|
|
41
|
+
let insertPrefix = 'insert into sample (pump_date,';
|
|
42
|
+
let insertQ = '?,';
|
|
43
|
+
for (let i = 0; i < colNames.length; i++) {
|
|
44
|
+
if (i > 0) {
|
|
45
|
+
createTable += ', ';
|
|
46
|
+
insertPrefix += ', ';
|
|
47
|
+
insertQ += ', ';
|
|
48
|
+
}
|
|
49
|
+
const kOut = colNames[i].toLowerCase().split(' ').join('_');
|
|
50
|
+
insertPrefix += kOut;
|
|
51
|
+
insertQ += '?';
|
|
52
|
+
createTable += kOut + ' varchar(255)';
|
|
53
|
+
if (kOut === 'id') {
|
|
54
|
+
createTable += ' primary key';
|
|
55
|
+
}
|
|
56
|
+
else if (kOut === 'device_id') {
|
|
57
|
+
createTable += ' unique';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
createTable += ')';
|
|
61
|
+
insertPrefix += ') values ';
|
|
62
|
+
Logger.info('Recreating table');
|
|
63
|
+
const dropRes = rval.push({ statement: dropTable });
|
|
64
|
+
const createRes = rval.push({ statement: createTable });
|
|
65
|
+
const pumpDate = DateTime.utc().toISO();
|
|
66
|
+
let insertStmt = insertPrefix;
|
|
67
|
+
let insertParams = [];
|
|
68
|
+
for (let i = 1; i < csvParsed.length; i++) {
|
|
69
|
+
if (insertStmt > insertPrefix) {
|
|
70
|
+
insertStmt += ',';
|
|
71
|
+
}
|
|
72
|
+
insertStmt += '(' + insertQ + ')';
|
|
73
|
+
insertParams = insertParams.concat(pumpDate, csvParsed[i]);
|
|
74
|
+
if (i % 25 === 0 || i === csvParsed.length - 1) {
|
|
75
|
+
rval.push({ statement: insertStmt, params: insertParams });
|
|
76
|
+
insertStmt = insertPrefix;
|
|
77
|
+
insertParams = [];
|
|
78
|
+
Logger.info('Inserted %d of %d rows', i, csvParsed.length);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
Logger.info('Finished insertion of %d rows', csvParsed.length);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
Logger.error('Failure: %s : %j', err, rval, err);
|
|
86
|
+
}
|
|
87
|
+
return rval;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import { S3CacheRatchet } from '@bitblit/ratchet-aws/dist/s3/s3-cache-ratchet.js';
|
|
3
|
+
import { ParsedEmailProcessor } from './parsed-email-processor.js';
|
|
4
|
+
export declare class InboundEmailRatchet {
|
|
5
|
+
private cache;
|
|
6
|
+
private processors;
|
|
7
|
+
constructor(cache: S3CacheRatchet, processors: ParsedEmailProcessor<any>[]);
|
|
8
|
+
processEmailFromS3(key: string): Promise<boolean>;
|
|
9
|
+
processEmailFromBuffer(buf: Buffer): Promise<boolean>;
|
|
10
|
+
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { simpleParser } from 'mailparser';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { Logger } from '@bitblit/ratchet-common/dist/logger/logger.js';
|
|
3
|
+
import { RequireRatchet } from '@bitblit/ratchet-common/dist/lang/require-ratchet.js';
|
|
4
4
|
export class InboundEmailRatchet {
|
|
5
|
-
|
|
5
|
+
cache;
|
|
6
|
+
processors;
|
|
7
|
+
constructor(cache, processors) {
|
|
6
8
|
this.cache = cache;
|
|
9
|
+
this.processors = processors;
|
|
7
10
|
RequireRatchet.notNullOrUndefined(this.cache, 'cache');
|
|
8
11
|
RequireRatchet.notNullOrUndefined(this.cache.getDefaultBucket(), 'cache.defaultBucket');
|
|
9
12
|
}
|
|
@@ -23,27 +26,16 @@ export class InboundEmailRatchet {
|
|
|
23
26
|
RequireRatchet.notNullOrUndefined(buf, 'buf');
|
|
24
27
|
Logger.info('Processing inbound email - size %d bytes', buf.length);
|
|
25
28
|
const message = await simpleParser(buf);
|
|
26
|
-
Logger.info('Found mail from "%s" subject "%s" with %d attachments', message
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
Logger.info('Found mail from "%s" subject "%s" with %d attachments', message?.from?.text, message?.subject, message?.attachments?.length);
|
|
30
|
+
let procd = false;
|
|
31
|
+
for (let i = 0; i < this.processors.length && !procd; i++) {
|
|
32
|
+
if (this.processors[i].canProcess(message)) {
|
|
33
|
+
Logger.info('Processing message with processor %d', i);
|
|
34
|
+
const result = await this.processors[i].processEmail(message);
|
|
35
|
+
Logger.info('Result was : %j', result);
|
|
36
|
+
procd = true;
|
|
37
|
+
}
|
|
33
38
|
}
|
|
34
|
-
|
|
35
|
-
Logger.info('Unrecognized email - not processing');
|
|
36
|
-
}
|
|
37
|
-
return rval;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
export class MultiStream extends Readable {
|
|
41
|
-
constructor(object, options = {}) {
|
|
42
|
-
super(object instanceof Buffer || typeof object === 'string' ? options : { objectMode: true });
|
|
43
|
-
this._object = object;
|
|
44
|
-
}
|
|
45
|
-
_read() {
|
|
46
|
-
this.push(this._object);
|
|
47
|
-
this._object = null;
|
|
39
|
+
return procd;
|
|
48
40
|
}
|
|
49
41
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { InboundEmailRatchet } from './inbound-email-ratchet.js';
|
|
2
|
+
import { JestRatchet } from '@bitblit/ratchet-jest/dist/jest/jest-ratchet.js';
|
|
3
|
+
import { jest } from '@jest/globals';
|
|
4
|
+
import { SampleEmailProcessor } from './sample-email-processor.js';
|
|
5
|
+
let mockS3CR;
|
|
6
|
+
describe('#inboundEmailService', () => {
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
mockS3CR = JestRatchet.mock(jest.fn);
|
|
9
|
+
});
|
|
10
|
+
it('should process an email from S3', async () => {
|
|
11
|
+
mockS3CR.getDefaultBucket.mockReturnValueOnce('TEST-BUCKET');
|
|
12
|
+
mockS3CR.fileExists.mockResolvedValueOnce(true);
|
|
13
|
+
mockS3CR.fetchCacheFileAsString.mockResolvedValue('TEST');
|
|
14
|
+
const svc = new InboundEmailRatchet(mockS3CR, [new SampleEmailProcessor()]);
|
|
15
|
+
const res = await svc.processEmailFromS3('some-key');
|
|
16
|
+
expect(res).not.toBeUndefined();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ParsedEmailProcessor } from './parsed-email-processor.js';
|
|
2
|
+
import { ParsedMail } from 'mailparser';
|
|
3
|
+
export declare class SampleEmailProcessor implements ParsedEmailProcessor<string> {
|
|
4
|
+
canProcess(mail: ParsedMail): boolean;
|
|
5
|
+
processEmail(msg: ParsedMail): Promise<string>;
|
|
6
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitblit/ratchet-aws-node-only",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.102-alpha",
|
|
4
4
|
"description": "Common tools for use with AWS (Node only)",
|
|
5
5
|
"note-on-side-effects": "Technically the entries in 'bin' below might be side effects, but they are called explicitly",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"bin": {
|
|
8
8
|
"ratchet-aws-cli": "./includes/cli.js"
|
|
9
9
|
},
|
|
10
|
-
"
|
|
11
|
-
"module": "
|
|
12
|
-
"types": "./dist/types/index.d.ts",
|
|
10
|
+
"type": "module",
|
|
11
|
+
"module": "index.js",
|
|
13
12
|
"files": [
|
|
14
13
|
"dist/*",
|
|
15
14
|
"includes/*"
|
|
@@ -36,15 +35,13 @@
|
|
|
36
35
|
"scripts": {
|
|
37
36
|
"watch": "tsc-watch",
|
|
38
37
|
"clean": "shx rm -Rf dist",
|
|
39
|
-
"test": "jest",
|
|
38
|
+
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
|
|
40
39
|
"docs": "typedoc",
|
|
41
40
|
"lint": "eslint src/**/*.ts",
|
|
42
41
|
"lint-fix": "eslint --fix src/**/*.ts",
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"build
|
|
46
|
-
"build:es": "tsc -p tsconfig.es.json",
|
|
47
|
-
"build:types": "tsc -p tsconfig.types.json"
|
|
42
|
+
"__generate-barrels": "barrelsby -q --delete -d src -e .*\\.spec\\.ts",
|
|
43
|
+
"__build": "yarn run generate-barrels && tsc",
|
|
44
|
+
"build": "tsc"
|
|
48
45
|
},
|
|
49
46
|
"repository": {
|
|
50
47
|
"type": "git",
|
|
@@ -75,6 +72,7 @@
|
|
|
75
72
|
"mailparser": "3.6.4",
|
|
76
73
|
"mime-types": "2.1.35",
|
|
77
74
|
"tmp": "0.2.1",
|
|
75
|
+
"unzipper": "0.10.11",
|
|
78
76
|
"walk": "2.3.15"
|
|
79
77
|
},
|
|
80
78
|
"peerDependencies": {
|