@onivoro/server-aws-redshift 22.0.10 → 24.0.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/README.md +787 -0
- package/{dist/cjs/index.d.ts → index.ts} +2 -0
- package/jest.config.ts +11 -0
- package/package.json +10 -47
- package/project.json +23 -0
- package/{dist/esm/index.d.ts → src/index.ts} +2 -0
- package/src/lib/classes/server-aws-redshift-config.class.ts +4 -0
- package/src/lib/server-aws-redshift.module.ts +56 -0
- package/{dist/cjs/lib/services/redshift.service.js → src/lib/services/redshift.service.ts} +141 -84
- package/tsconfig.json +16 -0
- package/tsconfig.lib.json +8 -0
- package/tsconfig.spec.json +21 -0
- package/dist/cjs/index.js +0 -19
- package/dist/cjs/lib/classes/server-aws-redshift-config.class.d.ts +0 -6
- package/dist/cjs/lib/classes/server-aws-redshift-config.class.js +0 -10
- package/dist/cjs/lib/server-aws-redshift.module.d.ts +0 -4
- package/dist/cjs/lib/server-aws-redshift.module.js +0 -65
- package/dist/cjs/lib/services/redshift.service.d.ts +0 -43
- package/dist/esm/index.js +0 -19
- package/dist/esm/lib/classes/server-aws-redshift-config.class.d.ts +0 -6
- package/dist/esm/lib/classes/server-aws-redshift-config.class.js +0 -10
- package/dist/esm/lib/server-aws-redshift.module.d.ts +0 -4
- package/dist/esm/lib/server-aws-redshift.module.js +0 -65
- package/dist/esm/lib/services/redshift.service.d.ts +0 -43
- package/dist/esm/lib/services/redshift.service.js +0 -236
- package/dist/types/index.d.ts +0 -3
- package/dist/types/lib/classes/server-aws-redshift-config.class.d.ts +0 -6
- package/dist/types/lib/server-aws-redshift.module.d.ts +0 -4
- package/dist/types/lib/services/redshift.service.d.ts +0 -43
package/jest.config.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
export default {
|
|
3
|
+
displayName: 'lib-server-aws-redshift',
|
|
4
|
+
preset: '../../../jest.preset.js',
|
|
5
|
+
testEnvironment: 'node',
|
|
6
|
+
transform: {
|
|
7
|
+
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
|
|
8
|
+
},
|
|
9
|
+
moduleFileExtensions: ['ts', 'js', 'html'],
|
|
10
|
+
coverageDirectory: '../../../coverage/libs/server/aws-redshift',
|
|
11
|
+
};
|
package/package.json
CHANGED
|
@@ -1,49 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
],
|
|
13
|
-
"scripts": {
|
|
14
|
-
"onx": "onx",
|
|
15
|
-
"build": "onx Build",
|
|
16
|
-
"deploy": "onx Publish",
|
|
17
|
-
"test": "onx Test",
|
|
18
|
-
"update": "onx Update"
|
|
19
|
-
},
|
|
20
|
-
"exports": {
|
|
21
|
-
".": {
|
|
22
|
-
"types": "./dist/types/index.d.ts",
|
|
23
|
-
"require": "./dist/cjs/index.js",
|
|
24
|
-
"import": "./dist/esm/index.js",
|
|
25
|
-
"default": "./dist/esm/lib.js"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
"onx": {
|
|
29
|
-
"platform": "server",
|
|
30
|
-
"module": "commonjs"
|
|
31
|
-
},
|
|
32
|
-
"devDependencies": {
|
|
33
|
-
"@onivoro/cli": "^22.0.8",
|
|
34
|
-
"@types/jest": "*",
|
|
35
|
-
"@types/node": "22.8.1",
|
|
36
|
-
"typescript": "*"
|
|
37
|
-
},
|
|
38
|
-
"engines": {
|
|
39
|
-
"node": "22.10.0",
|
|
40
|
-
"npm": "10.9.0"
|
|
41
|
-
},
|
|
42
|
-
"dependencies": {
|
|
43
|
-
"@aws-sdk/client-redshift": "^3.699.0",
|
|
44
|
-
"@aws-sdk/client-redshift-data": "^3.709.0",
|
|
45
|
-
"@aws-sdk/client-redshift-serverless": "^3.709.0",
|
|
46
|
-
"@nestjs/common": "^10.4.6",
|
|
47
|
-
"@onivoro/server-common": "^22.0.3"
|
|
48
|
-
}
|
|
2
|
+
"name": "@onivoro/server-aws-redshift",
|
|
3
|
+
"version": "24.0.0",
|
|
4
|
+
"type": "commonjs",
|
|
5
|
+
"main": "./src/index.js",
|
|
6
|
+
"types": "./src/index.d.ts",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@onivoro/server-aws-credential-providers": "24.0.0",
|
|
9
|
+
"@onivoro/server-common": "24.0.0",
|
|
10
|
+
"tslib": "^2.3.0"
|
|
11
|
+
}
|
|
49
12
|
}
|
package/project.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lib-server-aws-redshift",
|
|
3
|
+
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
+
"sourceRoot": "libs/server/aws-redshift/src",
|
|
5
|
+
"projectType": "library",
|
|
6
|
+
"targets": {
|
|
7
|
+
"build": {
|
|
8
|
+
"executor": "@nx/js:tsc",
|
|
9
|
+
"outputs": ["{options.outputPath}"],
|
|
10
|
+
"options": {
|
|
11
|
+
"outputPath": "dist/libs/server/aws-redshift",
|
|
12
|
+
"main": "libs/server/aws-redshift/src/index.ts",
|
|
13
|
+
"tsConfig": "libs/server/aws-redshift/tsconfig.lib.json",
|
|
14
|
+
"assets": [
|
|
15
|
+
"libs/server/aws-redshift/README.md",
|
|
16
|
+
"libs/server/aws-redshift/package.json"
|
|
17
|
+
],
|
|
18
|
+
"declaration": true
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"tags": []
|
|
23
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { moduleFactory } from '@onivoro/server-common';
|
|
3
|
+
import { RedshiftDataClient, RedshiftDataClientConfig } from '@aws-sdk/client-redshift-data';
|
|
4
|
+
import { RedshiftDataService } from './services/redshift.service';
|
|
5
|
+
import { ServerAwsRedshiftDataConfig } from './classes/server-aws-redshift-config.class';
|
|
6
|
+
import { RedshiftServerlessClient } from '@aws-sdk/client-redshift-serverless';
|
|
7
|
+
import { RedshiftClient } from '@aws-sdk/client-redshift';
|
|
8
|
+
import { AwsCredentials, ServerAwsCredentialProvidersModule } from '@onivoro/server-aws-credential-providers';
|
|
9
|
+
|
|
10
|
+
let redshiftClient: RedshiftClient | null = null;
|
|
11
|
+
let redshiftDataClient: RedshiftDataClient | null = null;
|
|
12
|
+
let redshiftServerlessClient: RedshiftServerlessClient | null = null;
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@Module({})
|
|
16
|
+
export class ServerAwsRedshiftDataModule {
|
|
17
|
+
static configure(config: ServerAwsRedshiftDataConfig) {
|
|
18
|
+
return moduleFactory({
|
|
19
|
+
module: ServerAwsRedshiftDataModule,
|
|
20
|
+
imports: [ServerAwsCredentialProvidersModule.configure(config)],
|
|
21
|
+
providers: [
|
|
22
|
+
{
|
|
23
|
+
provide: RedshiftDataClient,
|
|
24
|
+
useFactory: (credentials: AwsCredentials) => redshiftDataClient
|
|
25
|
+
? redshiftDataClient
|
|
26
|
+
: redshiftDataClient = new RedshiftDataClient(from(config, credentials)),
|
|
27
|
+
inject: [AwsCredentials]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
provide: RedshiftServerlessClient,
|
|
31
|
+
useFactory: (credentials: AwsCredentials) => redshiftServerlessClient
|
|
32
|
+
? redshiftServerlessClient
|
|
33
|
+
: redshiftServerlessClient = new RedshiftServerlessClient(from(config, credentials)),
|
|
34
|
+
inject: [AwsCredentials]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
provide: RedshiftClient,
|
|
38
|
+
useFactory: (credentials: AwsCredentials) => redshiftClient
|
|
39
|
+
? redshiftClient
|
|
40
|
+
: redshiftClient = new RedshiftClient(from(config, credentials)),
|
|
41
|
+
inject: [AwsCredentials]
|
|
42
|
+
},
|
|
43
|
+
{ provide: ServerAwsRedshiftDataConfig, useValue: config },
|
|
44
|
+
RedshiftDataService
|
|
45
|
+
]
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function from(config: ServerAwsRedshiftDataConfig, credentials: AwsCredentials): RedshiftDataClientConfig {
|
|
51
|
+
return {
|
|
52
|
+
region: config.AWS_REGION,
|
|
53
|
+
logger: console,
|
|
54
|
+
credentials
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -1,204 +1,234 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const client_redshift_data_1 = require("@aws-sdk/client-redshift-data");
|
|
15
|
-
const client_redshift_serverless_1 = require("@aws-sdk/client-redshift-serverless");
|
|
16
|
-
const crypto_1 = require("crypto");
|
|
17
|
-
let RedshiftDataService = class RedshiftDataService {
|
|
18
|
-
redshiftDataClient;
|
|
19
|
-
redshiftServerlessClient;
|
|
20
|
-
constructor(redshiftDataClient, redshiftServerlessClient) {
|
|
21
|
-
this.redshiftDataClient = redshiftDataClient;
|
|
22
|
-
this.redshiftServerlessClient = redshiftServerlessClient;
|
|
23
|
-
}
|
|
24
|
-
async waitForStatement(statementId, maxAttempts = 10, delay = 1000) {
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { DescribeStatementCommand, ExecuteStatementCommand, GetStatementResultCommand, RedshiftDataClient } from "@aws-sdk/client-redshift-data";
|
|
3
|
+
import { GetWorkgroupCommand, GetWorkgroupCommandInput, RedshiftServerlessClient } from '@aws-sdk/client-redshift-serverless';
|
|
4
|
+
import { randomUUID } from 'crypto';
|
|
5
|
+
|
|
6
|
+
@Injectable()
|
|
7
|
+
export class RedshiftDataService {
|
|
8
|
+
constructor(
|
|
9
|
+
private redshiftDataClient: RedshiftDataClient,
|
|
10
|
+
private redshiftServerlessClient: RedshiftServerlessClient,
|
|
11
|
+
) { }
|
|
12
|
+
|
|
13
|
+
async waitForStatement(statementId: string, maxAttempts = 10, delay = 1000) {
|
|
25
14
|
let attempts = 0;
|
|
15
|
+
|
|
26
16
|
while (attempts < maxAttempts) {
|
|
27
|
-
const describeStatementCommand = new
|
|
17
|
+
const describeStatementCommand = new DescribeStatementCommand({
|
|
28
18
|
Id: statementId
|
|
29
19
|
});
|
|
20
|
+
|
|
30
21
|
const status = await this.redshiftDataClient.send(describeStatementCommand);
|
|
22
|
+
|
|
31
23
|
if (status.Status === 'FINISHED') {
|
|
32
24
|
return status.ResultRows;
|
|
33
25
|
}
|
|
26
|
+
|
|
34
27
|
if (status.Status === 'FAILED') {
|
|
35
28
|
throw new Error(`SQL statement failed: ${status.Error}`);
|
|
36
29
|
}
|
|
30
|
+
|
|
37
31
|
attempts++;
|
|
38
32
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
39
33
|
}
|
|
34
|
+
|
|
40
35
|
throw new Error('Timeout waiting for SQL statement to complete');
|
|
41
36
|
}
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
|
|
38
|
+
async verifyEndpointAccess(workgroupName: string) {
|
|
39
|
+
const workgroupResponse = await this.redshiftServerlessClient.send(
|
|
40
|
+
new GetWorkgroupCommand({ workgroupName })
|
|
41
|
+
);
|
|
42
|
+
|
|
44
43
|
if (!workgroupResponse?.workgroup?.endpoint?.address) {
|
|
45
44
|
console.error(`Could not retrieve endpoint for workgroupName "${workgroupName}"`);
|
|
45
|
+
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
48
|
+
|
|
48
49
|
return workgroupResponse;
|
|
49
50
|
}
|
|
50
|
-
|
|
51
|
+
|
|
52
|
+
async addIamUserToDatabaseGroup(_: { database: string, workgroupName: string, user: string, group: string }) {
|
|
51
53
|
try {
|
|
52
|
-
const groupResult = await this.redshiftDataClient.send(new
|
|
54
|
+
const groupResult = await this.redshiftDataClient.send(new ExecuteStatementCommand({
|
|
53
55
|
Database: _.database,
|
|
54
56
|
Sql: `ALTER GROUP ${_.group} ADD USER "${_.user}";`,
|
|
55
57
|
WorkgroupName: _.workgroupName
|
|
56
58
|
}));
|
|
57
|
-
|
|
59
|
+
|
|
60
|
+
await this.waitForStatement(groupResult.Id!);
|
|
61
|
+
|
|
58
62
|
console.log(`Added user "${_.user}" to group "${_.group}`);
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
63
|
+
} catch (error: any) {
|
|
61
64
|
console.warn({ detail: `Warning adding ${_.user} to group:`, error });
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
|
-
|
|
67
|
+
|
|
68
|
+
async createDatabaseUser(_: { database: string, workgroupName: string, user: string }): Promise<string> {
|
|
65
69
|
try {
|
|
66
|
-
|
|
70
|
+
|
|
71
|
+
const checkResult = await this.redshiftDataClient.send(new ExecuteStatementCommand({
|
|
67
72
|
Database: _.database,
|
|
68
73
|
Sql: `SELECT u.usename as username FROM pg_user u;`,
|
|
69
74
|
WorkgroupName: _.workgroupName
|
|
70
75
|
}));
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
|
|
77
|
+
await this.waitForStatement(checkResult.Id!);
|
|
78
|
+
|
|
79
|
+
const describeCommand = new DescribeStatementCommand({ Id: checkResult.Id });
|
|
73
80
|
const checkStatus = await this.redshiftDataClient.send(describeCommand);
|
|
81
|
+
|
|
74
82
|
if (!checkStatus.ResultRows) {
|
|
75
|
-
const placeholderPassword = `IAM_${
|
|
76
|
-
|
|
83
|
+
const placeholderPassword = `IAM_${randomUUID().replace(/-/g, '_')}`;
|
|
84
|
+
|
|
85
|
+
const createUserCommand = new ExecuteStatementCommand({
|
|
77
86
|
Database: _.database,
|
|
78
87
|
Sql: `CREATE USER ${_.user} PASSWORD '${placeholderPassword}';`,
|
|
79
88
|
WorkgroupName: _.workgroupName
|
|
80
89
|
});
|
|
90
|
+
|
|
81
91
|
const createResult = await this.redshiftDataClient.send(createUserCommand);
|
|
82
|
-
|
|
92
|
+
|
|
93
|
+
await this.waitForStatement(createResult.Id!);
|
|
94
|
+
|
|
83
95
|
console.log(`Created user: ${_.user}`);
|
|
96
|
+
|
|
84
97
|
return placeholderPassword;
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
98
|
+
} else {
|
|
87
99
|
console.log(`User "${_.user} already exists`);
|
|
100
|
+
|
|
88
101
|
return '';
|
|
89
102
|
}
|
|
90
|
-
|
|
91
|
-
catch (error) {
|
|
103
|
+
|
|
104
|
+
} catch (error: any) {
|
|
92
105
|
console.warn({ detail: `Warning creating user ${_.user}`, error });
|
|
93
106
|
throw error;
|
|
94
107
|
}
|
|
95
108
|
}
|
|
96
|
-
|
|
109
|
+
|
|
110
|
+
async grantUsageOnSchema(_: { database: string, workgroupName: string, schema: string, group: string }) {
|
|
111
|
+
|
|
97
112
|
try {
|
|
98
113
|
const setupStatements = [
|
|
99
114
|
`GRANT USAGE ON SCHEMA ${_.schema} TO GROUP ${_.group};`,
|
|
100
115
|
`GRANT SELECT ON ALL TABLES IN SCHEMA ${_.schema} TO GROUP ${_.group};`,
|
|
101
116
|
`ALTER DEFAULT PRIVILEGES IN SCHEMA ${_.schema} GRANT SELECT ON TABLES TO GROUP ${_.group};`,
|
|
102
117
|
];
|
|
118
|
+
|
|
103
119
|
for (const Sql of setupStatements) {
|
|
104
|
-
const executeStatementCommand = new
|
|
120
|
+
const executeStatementCommand = new ExecuteStatementCommand({
|
|
105
121
|
Database: _.database,
|
|
106
122
|
Sql,
|
|
107
123
|
WorkgroupName: _.workgroupName
|
|
108
124
|
});
|
|
125
|
+
|
|
109
126
|
try {
|
|
110
127
|
const result = await this.redshiftDataClient.send(executeStatementCommand);
|
|
111
|
-
await this.waitForStatement(result.Id);
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
catch (error) {
|
|
128
|
+
await this.waitForStatement(result.Id!);
|
|
129
|
+
} catch (error: any) {
|
|
115
130
|
console.warn({ Sql, error });
|
|
116
131
|
}
|
|
117
132
|
}
|
|
118
|
-
|
|
119
|
-
catch (error) {
|
|
133
|
+
|
|
134
|
+
} catch (error) {
|
|
120
135
|
console.error({ error });
|
|
121
136
|
throw error;
|
|
122
137
|
}
|
|
123
138
|
}
|
|
124
|
-
|
|
139
|
+
|
|
140
|
+
async createDbGroupFromIamGroupIfNotExists(_: { iamGroup: string, database: string, workgroupName: string }): Promise<any> {
|
|
141
|
+
|
|
125
142
|
try {
|
|
126
|
-
const checkResult = await this.redshiftDataClient.send(new
|
|
143
|
+
const checkResult = await this.redshiftDataClient.send(new ExecuteStatementCommand({
|
|
127
144
|
Database: _.database,
|
|
128
145
|
Sql: `SELECT 1 FROM pg_group WHERE groname = '${_.iamGroup}';`,
|
|
129
146
|
WorkgroupName: _.workgroupName
|
|
130
147
|
}));
|
|
131
|
-
|
|
132
|
-
|
|
148
|
+
|
|
149
|
+
await this.waitForStatement(checkResult.Id!);
|
|
150
|
+
|
|
151
|
+
const describeCommand = new DescribeStatementCommand({ Id: checkResult.Id });
|
|
133
152
|
const checkStatus = await this.redshiftDataClient.send(describeCommand);
|
|
153
|
+
|
|
134
154
|
if (!checkStatus.ResultRows) {
|
|
135
|
-
const createGroupCommand = new
|
|
155
|
+
const createGroupCommand = new ExecuteStatementCommand({
|
|
136
156
|
Database: _.database,
|
|
137
157
|
Sql: `CREATE GROUP ${_.iamGroup};`,
|
|
138
158
|
WorkgroupName: _.workgroupName
|
|
139
159
|
});
|
|
160
|
+
|
|
140
161
|
const createResult = await this.redshiftDataClient.send(createGroupCommand);
|
|
141
|
-
await this.waitForStatement(createResult.Id);
|
|
162
|
+
await this.waitForStatement(createResult.Id!);
|
|
142
163
|
console.log(`Created "${_.iamGroup}" group`);
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
164
|
+
} else {
|
|
145
165
|
console.log(`"${_.iamGroup}" group already exists`);
|
|
146
166
|
}
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
167
|
+
} catch (error: any) {
|
|
149
168
|
console.error({ error });
|
|
150
169
|
throw error;
|
|
151
170
|
}
|
|
152
171
|
}
|
|
153
|
-
|
|
154
|
-
|
|
172
|
+
|
|
173
|
+
async queryV1(_: { database: string, workgroupName: string }, Sql: string) {
|
|
174
|
+
const result = await this.redshiftDataClient.send(new ExecuteStatementCommand({
|
|
155
175
|
Database: _.database,
|
|
156
176
|
Sql,
|
|
157
177
|
WorkgroupName: _.workgroupName
|
|
158
178
|
}));
|
|
159
|
-
|
|
179
|
+
|
|
180
|
+
return await this.waitForStatement(result.Id!);
|
|
160
181
|
}
|
|
161
|
-
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
async query(_: { database: string, workgroupName: string }, Sql: string) {
|
|
162
185
|
try {
|
|
163
|
-
const executeCommand = new
|
|
186
|
+
const executeCommand = new ExecuteStatementCommand({
|
|
164
187
|
Database: _.database,
|
|
165
188
|
Sql,
|
|
166
|
-
WorkgroupName: _.workgroupName
|
|
189
|
+
WorkgroupName: _.workgroupName,
|
|
167
190
|
});
|
|
191
|
+
|
|
168
192
|
const { Id } = await this.redshiftDataClient.send(executeCommand);
|
|
193
|
+
|
|
169
194
|
if (!Id) {
|
|
170
195
|
throw new Error("Failed to get statement ID");
|
|
171
196
|
}
|
|
197
|
+
|
|
172
198
|
let status = "";
|
|
199
|
+
|
|
173
200
|
do {
|
|
174
|
-
const describeCommand = new
|
|
201
|
+
const describeCommand = new DescribeStatementCommand({ Id });
|
|
175
202
|
const { Status, Error: err } = await this.redshiftDataClient.send(describeCommand);
|
|
176
203
|
status = Status || "";
|
|
204
|
+
|
|
177
205
|
if (status === "FAILED") {
|
|
178
206
|
throw new Error(err);
|
|
179
207
|
}
|
|
208
|
+
|
|
180
209
|
if (status !== "FINISHED") {
|
|
181
210
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
182
211
|
}
|
|
183
212
|
} while (status !== "FINISHED");
|
|
213
|
+
|
|
184
214
|
try {
|
|
185
|
-
const getResultsCommand = new
|
|
215
|
+
const getResultsCommand = new GetStatementResultCommand({ Id });
|
|
186
216
|
const results = await this.redshiftDataClient.send(getResultsCommand);
|
|
217
|
+
|
|
187
218
|
const records = results.Records || [];
|
|
188
219
|
return records.map(record => {
|
|
189
220
|
return record.map(field => field.stringValue || field.longValue || field.doubleValue);
|
|
190
221
|
});
|
|
191
|
-
}
|
|
192
|
-
catch (error) {
|
|
222
|
+
} catch (error) {
|
|
193
223
|
return [];
|
|
194
224
|
}
|
|
195
|
-
}
|
|
196
|
-
catch (error) {
|
|
225
|
+
} catch (error) {
|
|
197
226
|
console.error({ detail: "Error executing query:", error });
|
|
198
227
|
throw error;
|
|
199
228
|
}
|
|
200
229
|
}
|
|
201
|
-
|
|
230
|
+
|
|
231
|
+
async getAssociatedIAmRolesByWorkgroup(_: { database: string, workgroupName: string }) {
|
|
202
232
|
try {
|
|
203
233
|
const query = `
|
|
204
234
|
SELECT
|
|
@@ -217,9 +247,9 @@ let RedshiftDataService = class RedshiftDataService {
|
|
|
217
247
|
)
|
|
218
248
|
ORDER BY g.groname, u.usename;
|
|
219
249
|
`;
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
catch (error) {
|
|
250
|
+
|
|
251
|
+
return await this.query(_, query)
|
|
252
|
+
} catch (error) {
|
|
223
253
|
if (error instanceof Error) {
|
|
224
254
|
console.error(`Error getting workgroup roles: ${error.message}`);
|
|
225
255
|
throw error;
|
|
@@ -227,10 +257,37 @@ let RedshiftDataService = class RedshiftDataService {
|
|
|
227
257
|
throw new Error('An unknown error occurred');
|
|
228
258
|
}
|
|
229
259
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
260
|
+
|
|
261
|
+
private async upsert<TValue>(_: { database: string, workgroupName: string }, value: TValue, tableQualifiers: { schema: string, table: string }) {
|
|
262
|
+
const { table, schema } = tableQualifiers;
|
|
263
|
+
// TODO: dynamically build out the select/insert clauses dynamically
|
|
264
|
+
// try {
|
|
265
|
+
// const upsertQuery = `
|
|
266
|
+
// WITH ${table}_x AS (SELECT '${value.user_id}' as user_id, '${value.profile_id}' as profile_id, '${value.email}' as email, '${value.date}' as date, '${value.weight}' as weight, '${value.source}' as source, '${value.created_at}' as created_at)
|
|
267
|
+
// UPDATE ${schema}.${table}
|
|
268
|
+
// SET
|
|
269
|
+
// patient = a.patient,
|
|
270
|
+
// data = a.data
|
|
271
|
+
// FROM ${table}_x AS a
|
|
272
|
+
// WHERE ${schema}.${table}.id = a.id;
|
|
273
|
+
|
|
274
|
+
// INSERT INTO ${schema}.${table} (
|
|
275
|
+
// id,
|
|
276
|
+
// patient,
|
|
277
|
+
// data
|
|
278
|
+
// )
|
|
279
|
+
// SELECT
|
|
280
|
+
// a.id,
|
|
281
|
+
// a.patient,
|
|
282
|
+
// a.data
|
|
283
|
+
// FROM ${table}_x AS a
|
|
284
|
+
// LEFT JOIN ${schema}.${table} AS b
|
|
285
|
+
// ON a.id = b.id
|
|
286
|
+
// WHERE b.id IS NULL;`;
|
|
287
|
+
|
|
288
|
+
// return await this.query(_, upsertQuery);
|
|
289
|
+
// } catch (error: any) {
|
|
290
|
+
// console.error({ error, detail: `"${schema}.${table}" upsert failed` });
|
|
291
|
+
// }
|
|
292
|
+
}
|
|
293
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../../tsconfig.server.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../../dist/out-tsc"
|
|
5
|
+
},
|
|
6
|
+
"files": [],
|
|
7
|
+
"include": [],
|
|
8
|
+
"references": [
|
|
9
|
+
{
|
|
10
|
+
"path": "./tsconfig.lib.json"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"path": "./tsconfig.spec.json"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"types": [
|
|
5
|
+
"jest",
|
|
6
|
+
"node"
|
|
7
|
+
]
|
|
8
|
+
},
|
|
9
|
+
"include": [
|
|
10
|
+
"jest.config.ts",
|
|
11
|
+
"**/*.test.ts",
|
|
12
|
+
"**/*.spec.ts",
|
|
13
|
+
"**/*.test.tsx",
|
|
14
|
+
"**/*.spec.tsx",
|
|
15
|
+
"**/*.test.js",
|
|
16
|
+
"**/*.spec.js",
|
|
17
|
+
"**/*.test.jsx",
|
|
18
|
+
"**/*.spec.jsx",
|
|
19
|
+
"**/*.d.ts"
|
|
20
|
+
]
|
|
21
|
+
}
|
package/dist/cjs/index.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./lib/classes/server-aws-redshift-config.class"), exports);
|
|
18
|
-
__exportStar(require("./lib/services/redshift.service"), exports);
|
|
19
|
-
__exportStar(require("./lib/server-aws-redshift.module"), exports);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ServerAwsRedshiftDataConfig = void 0;
|
|
4
|
-
class ServerAwsRedshiftDataConfig {
|
|
5
|
-
AWS_ACCESS_KEY_ID;
|
|
6
|
-
AWS_REGION;
|
|
7
|
-
AWS_SECRET_ACCESS_KEY;
|
|
8
|
-
NODE_ENV;
|
|
9
|
-
}
|
|
10
|
-
exports.ServerAwsRedshiftDataConfig = ServerAwsRedshiftDataConfig;
|