@ttoss/lambda-postgres-query 0.2.13 → 0.2.15
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/LICENSE +21 -674
- package/dist/cloudformation/index.d.mts +18 -0
- package/dist/cloudformation/index.d.ts +18 -0
- package/dist/cloudformation/index.js +224 -0
- package/dist/esm/cloudformation/index.js +182 -0
- package/dist/esm/index.js +56 -0
- package/dist/index.d.mts +21 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +101 -0
- package/package.json +6 -6
- package/src/cloudformation/createLambdaPostgresQueryTemplate.ts +0 -133
- package/src/cloudformation/index.ts +0 -2
- package/src/cloudformation/lambdaQueryHandler.ts +0 -39
- package/src/index.ts +0 -1
- package/src/query.ts +0 -76
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import type { CloudFormationTemplate } from '@ttoss/cloudformation';
|
|
2
|
-
|
|
3
|
-
export type { CloudFormationTemplate };
|
|
4
|
-
|
|
5
|
-
export const HANDLER_DEFAULT = 'handler.handler';
|
|
6
|
-
|
|
7
|
-
export const MEMORY_SIZE_DEFAULT = 128;
|
|
8
|
-
|
|
9
|
-
export const TIMEOUT_DEFAULT = 30;
|
|
10
|
-
|
|
11
|
-
export const createLambdaPostgresQueryTemplate = ({
|
|
12
|
-
handler = HANDLER_DEFAULT,
|
|
13
|
-
memorySize = 128,
|
|
14
|
-
timeout = 30,
|
|
15
|
-
}: {
|
|
16
|
-
handler?: string;
|
|
17
|
-
memorySize?: number;
|
|
18
|
-
timeout?: number;
|
|
19
|
-
} = {}): CloudFormationTemplate => {
|
|
20
|
-
return {
|
|
21
|
-
AWSTemplateFormatVersion: '2010-09-09',
|
|
22
|
-
Description: 'A Lambda function to query PostgreSQL.',
|
|
23
|
-
Parameters: {
|
|
24
|
-
DatabaseHost: {
|
|
25
|
-
Type: 'String',
|
|
26
|
-
Description: 'Database host.',
|
|
27
|
-
},
|
|
28
|
-
DatabaseHostReadOnly: {
|
|
29
|
-
Type: 'String',
|
|
30
|
-
Description: 'Database host read only.',
|
|
31
|
-
},
|
|
32
|
-
DatabaseName: {
|
|
33
|
-
Type: 'String',
|
|
34
|
-
Description: 'Database name.',
|
|
35
|
-
},
|
|
36
|
-
DatabaseUsername: {
|
|
37
|
-
Type: 'String',
|
|
38
|
-
Description: 'Database username.',
|
|
39
|
-
},
|
|
40
|
-
DatabasePassword: {
|
|
41
|
-
Type: 'String',
|
|
42
|
-
Description: 'Database password.',
|
|
43
|
-
},
|
|
44
|
-
DatabasePort: {
|
|
45
|
-
Type: 'String',
|
|
46
|
-
Default: '5432',
|
|
47
|
-
Description: 'Database port.',
|
|
48
|
-
},
|
|
49
|
-
LambdaS3Bucket: {
|
|
50
|
-
Type: 'String',
|
|
51
|
-
Description: 'The S3 bucket where the Lambda code is stored.',
|
|
52
|
-
},
|
|
53
|
-
LambdaS3Key: {
|
|
54
|
-
Type: 'String',
|
|
55
|
-
Description: 'The S3 key where the Lambda code is stored.',
|
|
56
|
-
},
|
|
57
|
-
LambdaS3ObjectVersion: {
|
|
58
|
-
Type: 'String',
|
|
59
|
-
Description: 'The S3 object version of the Lambda code.',
|
|
60
|
-
},
|
|
61
|
-
SecurityGroupIds: {
|
|
62
|
-
Description: 'Security Group IDs',
|
|
63
|
-
Type: 'List<AWS::EC2::SecurityGroup::Id>',
|
|
64
|
-
},
|
|
65
|
-
SubnetIds: {
|
|
66
|
-
Description: 'Subnet IDs',
|
|
67
|
-
Type: 'List<AWS::EC2::Subnet::Id>',
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
Resources: {
|
|
71
|
-
LambdaQueryExecutionRole: {
|
|
72
|
-
Type: 'AWS::IAM::Role',
|
|
73
|
-
Properties: {
|
|
74
|
-
AssumeRolePolicyDocument: {
|
|
75
|
-
Version: '2012-10-17',
|
|
76
|
-
Statement: [
|
|
77
|
-
{
|
|
78
|
-
Effect: 'Allow',
|
|
79
|
-
Principal: {
|
|
80
|
-
Service: 'lambda.amazonaws.com',
|
|
81
|
-
},
|
|
82
|
-
Action: 'sts:AssumeRole',
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
},
|
|
86
|
-
ManagedPolicyArns: [
|
|
87
|
-
'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole',
|
|
88
|
-
'arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole',
|
|
89
|
-
],
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
LambdaQueryFunction: {
|
|
93
|
-
Type: 'AWS::Lambda::Function',
|
|
94
|
-
Properties: {
|
|
95
|
-
Code: {
|
|
96
|
-
S3Bucket: { Ref: 'LambdaS3Bucket' },
|
|
97
|
-
S3Key: { Ref: 'LambdaS3Key' },
|
|
98
|
-
S3ObjectVersion: { Ref: 'LambdaS3ObjectVersion' },
|
|
99
|
-
},
|
|
100
|
-
MemorySize: memorySize,
|
|
101
|
-
Timeout: timeout,
|
|
102
|
-
Handler: handler,
|
|
103
|
-
Role: { 'Fn::GetAtt': ['LambdaQueryExecutionRole', 'Arn'] },
|
|
104
|
-
Runtime: 'nodejs20.x',
|
|
105
|
-
Environment: {
|
|
106
|
-
Variables: {
|
|
107
|
-
DATABASE_HOST: { Ref: 'DatabaseHost' },
|
|
108
|
-
DATABASE_HOST_READ_ONLY: { Ref: 'DatabaseHostReadOnly' },
|
|
109
|
-
DATABASE_NAME: { Ref: 'DatabaseName' },
|
|
110
|
-
DATABASE_USERNAME: { Ref: 'DatabaseUsername' },
|
|
111
|
-
DATABASE_PASSWORD: { Ref: 'DatabasePassword' },
|
|
112
|
-
DATABASE_PORT: { Ref: 'DatabasePort' },
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
VpcConfig: {
|
|
116
|
-
SecurityGroupIds: { Ref: 'SecurityGroupIds' },
|
|
117
|
-
SubnetIds: { Ref: 'SubnetIds' },
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
Outputs: {
|
|
123
|
-
LambdaPostgresQueryFunction: {
|
|
124
|
-
Description: 'Lambda function to query PostgreSQL.',
|
|
125
|
-
Value: { Ref: 'LambdaQueryFunction' },
|
|
126
|
-
},
|
|
127
|
-
LambdaPostgresQueryFunctionArn: {
|
|
128
|
-
Description: 'Lambda function to query PostgreSQL ARN.',
|
|
129
|
-
Value: { 'Fn::GetAtt': ['LambdaQueryFunction', 'Arn'] },
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
};
|
|
133
|
-
};
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/* eslint-disable turbo/no-undeclared-env-vars */
|
|
2
|
-
import { Client } from 'pg';
|
|
3
|
-
import type { Handler } from 'aws-lambda';
|
|
4
|
-
import type { QueryParams } from '../query';
|
|
5
|
-
|
|
6
|
-
const database = process.env.DATABASE_NAME;
|
|
7
|
-
const username = process.env.DATABASE_USERNAME;
|
|
8
|
-
const password = process.env.DATABASE_PASSWORD;
|
|
9
|
-
const host = process.env.DATABASE_HOST;
|
|
10
|
-
const hostReadOnly = process.env.DATABASE_HOST_READ_ONLY;
|
|
11
|
-
const port = process.env.DATABASE_PORT;
|
|
12
|
-
|
|
13
|
-
export const handler: Handler<QueryParams> = async (event) => {
|
|
14
|
-
try {
|
|
15
|
-
const client = new Client({
|
|
16
|
-
database,
|
|
17
|
-
user: username,
|
|
18
|
-
password,
|
|
19
|
-
host: event.readOnly && hostReadOnly ? hostReadOnly : host,
|
|
20
|
-
port: Number(port),
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
await client.connect();
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
const res = await client.query(event);
|
|
27
|
-
return res;
|
|
28
|
-
} finally {
|
|
29
|
-
await client.end();
|
|
30
|
-
}
|
|
31
|
-
} catch (error) {
|
|
32
|
-
// eslint-disable-next-line no-console
|
|
33
|
-
console.error('Error running query', {
|
|
34
|
-
error,
|
|
35
|
-
event,
|
|
36
|
-
});
|
|
37
|
-
throw error;
|
|
38
|
-
}
|
|
39
|
-
};
|
package/src/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './query';
|
package/src/query.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
InvokeCommand,
|
|
3
|
-
type InvokeCommandInput,
|
|
4
|
-
LambdaClient,
|
|
5
|
-
} from '@aws-sdk/client-lambda';
|
|
6
|
-
import camelcaseKeys from 'camelcase-keys';
|
|
7
|
-
import type { QueryConfig, QueryResult, QueryResultRow } from 'pg';
|
|
8
|
-
|
|
9
|
-
const lambdaClient = new LambdaClient();
|
|
10
|
-
|
|
11
|
-
const asciiDecoder = new TextDecoder('ascii');
|
|
12
|
-
|
|
13
|
-
export type QueryParams = {
|
|
14
|
-
readOnly?: boolean;
|
|
15
|
-
lambdaPostgresQueryFunction?: string;
|
|
16
|
-
} & QueryConfig;
|
|
17
|
-
|
|
18
|
-
export type LambdaError = {
|
|
19
|
-
errorType: 'Error';
|
|
20
|
-
errorMessage: string;
|
|
21
|
-
trace: string[];
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
|
-
export const query = async <Rows extends QueryResultRow = any>(
|
|
26
|
-
params: QueryParams | string
|
|
27
|
-
) => {
|
|
28
|
-
try {
|
|
29
|
-
const {
|
|
30
|
-
readOnly = true,
|
|
31
|
-
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
32
|
-
lambdaPostgresQueryFunction = process.env.LAMBDA_POSTGRES_QUERY_FUNCTION,
|
|
33
|
-
...pgParams
|
|
34
|
-
} = typeof params === 'string'
|
|
35
|
-
? {
|
|
36
|
-
text: params,
|
|
37
|
-
}
|
|
38
|
-
: params;
|
|
39
|
-
|
|
40
|
-
const input: InvokeCommandInput = {
|
|
41
|
-
FunctionName: lambdaPostgresQueryFunction,
|
|
42
|
-
Payload: JSON.stringify({ readOnly, ...pgParams }),
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const { Payload } = await lambdaClient.send(new InvokeCommand(input));
|
|
46
|
-
|
|
47
|
-
if (!Payload) {
|
|
48
|
-
// eslint-disable-next-line no-console
|
|
49
|
-
console.error('No payload returned from lambda query', { input });
|
|
50
|
-
throw new Error('No payload returned from lambda query');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const data = asciiDecoder.decode(Payload);
|
|
54
|
-
|
|
55
|
-
const result = JSON.parse(data) as QueryResult<Rows> | LambdaError;
|
|
56
|
-
|
|
57
|
-
if ('errorType' in result) {
|
|
58
|
-
throw result;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
...result,
|
|
63
|
-
rows: result.rows.map((row) => {
|
|
64
|
-
return {
|
|
65
|
-
...row,
|
|
66
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
|
-
...(camelcaseKeys(row, { deep: true }) as any),
|
|
68
|
-
};
|
|
69
|
-
}),
|
|
70
|
-
};
|
|
71
|
-
} catch (error) {
|
|
72
|
-
// eslint-disable-next-line no-console
|
|
73
|
-
console.error('Error invoking Lambda: ', error);
|
|
74
|
-
throw error;
|
|
75
|
-
}
|
|
76
|
-
};
|