@prismatic-io/components-aws-redshift 0.0.0-stage → 0.1.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.
@@ -0,0 +1,1139 @@
1
+ let _prismatic_io_spectral = require("@prismatic-io/spectral");
2
+ let _aws_sdk_client_sts = require("@aws-sdk/client-sts");
3
+ let _aws_sdk_client_redshift_data = require("@aws-sdk/client-redshift-data");
4
+ let _prismatic_io_spectral_http = require("@prismatic-io/spectral/http");
5
+ let aws4 = require("aws4");
6
+ //#region ../../packages/aws-utils/dist/connection/assumeRole.js
7
+ var __awaiter$3 = function(thisArg, _arguments, P, generator) {
8
+ function adopt(value) {
9
+ return value instanceof P ? value : new P(function(resolve) {
10
+ resolve(value);
11
+ });
12
+ }
13
+ return new (P || (P = Promise))(function(resolve, reject) {
14
+ function fulfilled(value) {
15
+ try {
16
+ step(generator.next(value));
17
+ } catch (e) {
18
+ reject(e);
19
+ }
20
+ }
21
+ function rejected(value) {
22
+ try {
23
+ step(generator["throw"](value));
24
+ } catch (e) {
25
+ reject(e);
26
+ }
27
+ }
28
+ function step(result) {
29
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
30
+ }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ const assumeRole = (region, accessKeyId, secretAccessKey, roleArn, externalId) => __awaiter$3(void 0, void 0, void 0, function* () {
35
+ const { Credentials: { AccessKeyId, SecretAccessKey, SessionToken } } = yield new _aws_sdk_client_sts.STSClient(Object.assign(Object.assign({}, region.length > 0 && { region }), { credentials: {
36
+ accessKeyId,
37
+ secretAccessKey
38
+ } })).send(new _aws_sdk_client_sts.AssumeRoleCommand({
39
+ RoleArn: _prismatic_io_spectral.util.types.toString(roleArn),
40
+ RoleSessionName: "integration-session",
41
+ ExternalId: externalId
42
+ }));
43
+ return {
44
+ accessKeyId: AccessKeyId,
45
+ secretAccessKey: SecretAccessKey,
46
+ sessionToken: SessionToken
47
+ };
48
+ });
49
+ //#endregion
50
+ //#region ../../packages/aws-utils/dist/connection/assumeRoleConnection.js
51
+ const assumeRoleConnection = {
52
+ key: "awsAssumeRole",
53
+ display: {
54
+ label: "AWS Role ARN",
55
+ description: "Connect to AWS using an assumed role"
56
+ },
57
+ inputs: {
58
+ roleARN: {
59
+ label: "Role ARN",
60
+ placeholder: "arn:aws:iam::OtherAccount-ID:role/assumed-role-name",
61
+ type: "string",
62
+ required: true,
63
+ shown: true,
64
+ comments: "An AWS IAM Role ARN",
65
+ example: "arn:aws:iam::OtherAccount-ID:role/assumed-role-name"
66
+ },
67
+ accessKeyId: {
68
+ label: "Access Key ID",
69
+ placeholder: "Access Key ID",
70
+ type: "string",
71
+ required: true,
72
+ shown: true,
73
+ comments: "An AWS IAM Access Key ID",
74
+ example: "AKIAIOSFODNN7EXAMPLE"
75
+ },
76
+ secretAccessKey: {
77
+ label: "Secret Access Key",
78
+ placeholder: "Secret Access Key",
79
+ type: "password",
80
+ required: true,
81
+ shown: true,
82
+ comments: "An AWS IAM Secret Access Key",
83
+ example: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
84
+ },
85
+ externalId: {
86
+ label: "External ID",
87
+ placeholder: "shared-common-secret",
88
+ type: "string",
89
+ required: false,
90
+ shown: true,
91
+ comments: "Provides enhanced security measures to the connection. Optional, but recommended. Please check [AWS docs](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_third-party.html#id_roles_third-party_external-id) for more information.",
92
+ example: "shared-common-secret"
93
+ }
94
+ }
95
+ };
96
+ //#endregion
97
+ //#region ../../packages/aws-utils/dist/helpers/misc.js
98
+ const toTrimmedString = (value) => _prismatic_io_spectral.util.types.toString(value).trim();
99
+ const toOptionalString$1 = (value) => value ? _prismatic_io_spectral.util.types.toString(value) : void 0;
100
+ //#endregion
101
+ //#region ../../packages/aws-utils/dist/helpers/getCredentials.js
102
+ const getCredentials = (connection) => {
103
+ return {
104
+ accessKeyId: toTrimmedString(connection.fields.accessKeyId),
105
+ secretAccessKey: toTrimmedString(connection.fields.secretAccessKey)
106
+ };
107
+ };
108
+ //#endregion
109
+ //#region ../../packages/aws-utils/dist/helpers/validateConnection.js
110
+ const validateConnection$1 = (connection, validConnectionKeys) => {
111
+ if (![assumeRoleConnection.key, ...validConnectionKeys].includes(connection.key)) throw new _prismatic_io_spectral.ConnectionError(connection, `Unsupported connection method ${connection.key}.`);
112
+ };
113
+ //#endregion
114
+ //#region ../../packages/aws-utils/dist/client/getClientParams.js
115
+ var __awaiter$2 = function(thisArg, _arguments, P, generator) {
116
+ function adopt(value) {
117
+ return value instanceof P ? value : new P(function(resolve) {
118
+ resolve(value);
119
+ });
120
+ }
121
+ return new (P || (P = Promise))(function(resolve, reject) {
122
+ function fulfilled(value) {
123
+ try {
124
+ step(generator.next(value));
125
+ } catch (e) {
126
+ reject(e);
127
+ }
128
+ }
129
+ function rejected(value) {
130
+ try {
131
+ step(generator["throw"](value));
132
+ } catch (e) {
133
+ reject(e);
134
+ }
135
+ }
136
+ function step(result) {
137
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
138
+ }
139
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
140
+ });
141
+ };
142
+ const getClientParams = (_a) => __awaiter$2(void 0, [_a], void 0, function* ({ awsRegion, awsConnection, validConnectionKeys, dynamicAccessKeyId, dynamicSecretAccessKey, dynamicSessionToken }) {
143
+ var _b;
144
+ let shouldAssumeRole = false;
145
+ if (awsConnection) {
146
+ validateConnection$1(awsConnection, validConnectionKeys);
147
+ if (dynamicAccessKeyId || dynamicSecretAccessKey) throw new Error("Please specify either a connection or dynamic access key and secret inputs.");
148
+ shouldAssumeRole = awsConnection.key === assumeRoleConnection.key;
149
+ }
150
+ if (!awsConnection && (!dynamicAccessKeyId || !dynamicSecretAccessKey)) throw new Error("You must specify either a connection input or dynamic access key and secret inputs.");
151
+ const { accessKeyId, secretAccessKey } = awsConnection ? getCredentials(awsConnection) : {
152
+ accessKeyId: dynamicAccessKeyId,
153
+ secretAccessKey: dynamicSecretAccessKey
154
+ };
155
+ const credentials = shouldAssumeRole ? yield assumeRole(awsRegion, accessKeyId, secretAccessKey, toTrimmedString(awsConnection.fields.roleARN), toOptionalString$1((_b = awsConnection.fields) === null || _b === void 0 ? void 0 : _b.externalId)) : {
156
+ accessKeyId,
157
+ secretAccessKey,
158
+ sessionToken: dynamicSessionToken
159
+ };
160
+ return {
161
+ region: awsRegion.length > 0 ? awsRegion : void 0,
162
+ credentials
163
+ };
164
+ });
165
+ //#endregion
166
+ //#region ../../packages/aws-utils/dist/data/awsRegions.js
167
+ const awsRegions = [
168
+ "af-south-1",
169
+ "ap-east-1",
170
+ "ap-east-2",
171
+ "ap-northeast-1",
172
+ "ap-northeast-2",
173
+ "ap-northeast-3",
174
+ "ap-south-1",
175
+ "ap-south-2",
176
+ "ap-southeast-1",
177
+ "ap-southeast-2",
178
+ "ap-southeast-3",
179
+ "ap-southeast-4",
180
+ "ap-southeast-5",
181
+ "ap-southeast-6",
182
+ "ap-southeast-7",
183
+ "ca-central-1",
184
+ "ca-west-1",
185
+ "eu-central-1",
186
+ "eu-central-2",
187
+ "eu-north-1",
188
+ "eu-south-1",
189
+ "eu-south-2",
190
+ "eu-west-1",
191
+ "eu-west-2",
192
+ "eu-west-3",
193
+ "il-central-1",
194
+ "me-central-1",
195
+ "me-south-1",
196
+ "mx-central-1",
197
+ "sa-east-1",
198
+ "us-east-1",
199
+ "us-east-2",
200
+ "us-gov-east-1",
201
+ "us-gov-west-1",
202
+ "us-west-1",
203
+ "us-west-2"
204
+ ];
205
+ //#endregion
206
+ //#region ../../packages/aws-utils/dist/dataSources/selectRegion.js
207
+ var __awaiter$1 = function(thisArg, _arguments, P, generator) {
208
+ function adopt(value) {
209
+ return value instanceof P ? value : new P(function(resolve) {
210
+ resolve(value);
211
+ });
212
+ }
213
+ return new (P || (P = Promise))(function(resolve, reject) {
214
+ function fulfilled(value) {
215
+ try {
216
+ step(generator.next(value));
217
+ } catch (e) {
218
+ reject(e);
219
+ }
220
+ }
221
+ function rejected(value) {
222
+ try {
223
+ step(generator["throw"](value));
224
+ } catch (e) {
225
+ reject(e);
226
+ }
227
+ }
228
+ function step(result) {
229
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
230
+ }
231
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
232
+ });
233
+ };
234
+ const selectRegion = (0, _prismatic_io_spectral.dataSource)({
235
+ display: {
236
+ label: "Select AWS Region",
237
+ description: "Select an AWS region"
238
+ },
239
+ dataSourceType: "picklist",
240
+ perform: () => __awaiter$1(void 0, void 0, void 0, function* () {
241
+ return Promise.resolve({ result: awsRegions.map((region) => ({
242
+ label: region,
243
+ key: region
244
+ })) });
245
+ }),
246
+ inputs: {}
247
+ });
248
+ //#endregion
249
+ //#region ../../packages/aws-utils/dist/helpers/pagination.js
250
+ var __awaiter = function(thisArg, _arguments, P, generator) {
251
+ function adopt(value) {
252
+ return value instanceof P ? value : new P(function(resolve) {
253
+ resolve(value);
254
+ });
255
+ }
256
+ return new (P || (P = Promise))(function(resolve, reject) {
257
+ function fulfilled(value) {
258
+ try {
259
+ step(generator.next(value));
260
+ } catch (e) {
261
+ reject(e);
262
+ }
263
+ }
264
+ function rejected(value) {
265
+ try {
266
+ step(generator["throw"](value));
267
+ } catch (e) {
268
+ reject(e);
269
+ }
270
+ }
271
+ function step(result) {
272
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
273
+ }
274
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
275
+ });
276
+ };
277
+ const paginateAwsResults = (options) => __awaiter(void 0, void 0, void 0, function* () {
278
+ const { createCommand, client, itemsKey } = options;
279
+ const allItems = [];
280
+ let nextToken;
281
+ let lastResponse;
282
+ do {
283
+ const command = createCommand(nextToken);
284
+ const response = yield client.send(command);
285
+ lastResponse = response;
286
+ const record = response;
287
+ const items = record[itemsKey];
288
+ allItems.push(...Array.isArray(items) ? items : []);
289
+ nextToken = record.NextToken;
290
+ } while (nextToken);
291
+ return {
292
+ allItems,
293
+ lastResponse
294
+ };
295
+ });
296
+ //#endregion
297
+ //#region ../../packages/aws-utils/dist/inputs/awsRegion.js
298
+ const awsRegion$1 = (0, _prismatic_io_spectral.input)({
299
+ label: "AWS Region",
300
+ placeholder: "AWS Region",
301
+ type: "string",
302
+ required: false,
303
+ comments: "AWS provides services in multiple regions, like us-west-2 or eu-west-1.",
304
+ example: "us-east-1",
305
+ dataSource: "selectRegion",
306
+ clean: _prismatic_io_spectral.util.types.toString
307
+ });
308
+ (0, _prismatic_io_spectral.input)({
309
+ label: "Connection",
310
+ type: "connection",
311
+ required: false
312
+ });
313
+ (0, _prismatic_io_spectral.input)({
314
+ label: "Dynamic Access Key ID",
315
+ type: "string",
316
+ required: false,
317
+ clean: _prismatic_io_spectral.util.types.toString,
318
+ comments: "Use this input to authenticate with AWS if you are using a dynamically-generated access key. Otherwise, use the connection to enter a static access key ID."
319
+ });
320
+ (0, _prismatic_io_spectral.input)({
321
+ label: "Dynamic Secret Access Key",
322
+ type: "password",
323
+ required: false,
324
+ clean: _prismatic_io_spectral.util.types.toString,
325
+ comments: "Use this input to authenticate with AWS if you are using a dynamically-generated secret access key. Otherwise, use the connection to enter a static secret access key."
326
+ });
327
+ (0, _prismatic_io_spectral.input)({
328
+ label: "Dynamic Session Token",
329
+ type: "password",
330
+ required: false,
331
+ clean: (value) => _prismatic_io_spectral.util.types.toString(value) || void 0,
332
+ comments: "Use this input to authenticate with AWS if you are using a OPTIONAL dynamically-generated session token."
333
+ });
334
+ //#endregion
335
+ //#region src/connections/index.ts
336
+ const accessKeySecretPair = (0, _prismatic_io_spectral.connection)({
337
+ key: "awsAccessKeySecret",
338
+ display: {
339
+ label: "Access Key and Secret",
340
+ description: "Authenticate requests to AWS using an Access Key and Secret Key."
341
+ },
342
+ inputs: {
343
+ accessKeyId: {
344
+ label: "Access Key ID",
345
+ type: "string",
346
+ required: true,
347
+ comments: "The AWS Access Key ID used to authenticate requests to the Redshift Data API.",
348
+ example: "AKIAIOSFODNN7EXAMPLE",
349
+ placeholder: "Enter the AWS Access Key ID"
350
+ },
351
+ secretAccessKey: {
352
+ label: "Secret Access Key",
353
+ type: "password",
354
+ required: true,
355
+ comments: "The AWS Secret Access Key paired with the Access Key ID for request signing.",
356
+ example: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
357
+ }
358
+ }
359
+ });
360
+ var connections_default = [accessKeySecretPair, assumeRoleConnection];
361
+ //#endregion
362
+ //#region src/util/index.ts
363
+ const toOptionalString = (value) => value ? _prismatic_io_spectral.util.types.toString(value) : void 0;
364
+ const toOptionalResultFormatString = (value) => value ? _prismatic_io_spectral.util.types.toString(value) : void 0;
365
+ const cleanSqlParameters = (sqlParameters) => Array.isArray(sqlParameters) && sqlParameters.length > 0 ? sqlParameters.map(({ name, value }) => ({
366
+ name,
367
+ value
368
+ })) : void 0;
369
+ const toOptionalNumber = (value) => value ? _prismatic_io_spectral.util.types.toNumber(value) : void 0;
370
+ const connectionKeys = [accessKeySecretPair.key, assumeRoleConnection.key];
371
+ const validateConnection = (connection) => {
372
+ if (!connectionKeys.includes(connection.key)) throw new _prismatic_io_spectral.ConnectionError(connection, `Unsupported connection method ${connection.key}. Supported methods: ${connectionKeys.join(", ")}`);
373
+ };
374
+ const getAllStatements = async ({ client, databaseName, workgroupName, clusterIdentifier, status, statementName }) => {
375
+ const { allItems, lastResponse } = await paginateAwsResults({
376
+ client,
377
+ createCommand: (token) => new _aws_sdk_client_redshift_data.ListStatementsCommand({
378
+ Database: databaseName,
379
+ WorkgroupName: workgroupName,
380
+ ClusterIdentifier: clusterIdentifier,
381
+ Status: status,
382
+ StatementName: statementName,
383
+ MaxResults: 100,
384
+ NextToken: token
385
+ }),
386
+ itemsKey: "Statements"
387
+ });
388
+ return {
389
+ allStatements: allItems,
390
+ lastResponse
391
+ };
392
+ };
393
+ //#endregion
394
+ //#region src/client.ts
395
+ const createRedshiftClient = async (connection, region, debug) => {
396
+ validateConnection(connection);
397
+ try {
398
+ const { region: awsRegion, credentials } = await getClientParams({
399
+ awsConnection: connection,
400
+ awsRegion: region,
401
+ validConnectionKeys: connectionKeys,
402
+ dynamicAccessKeyId: "",
403
+ dynamicSecretAccessKey: "",
404
+ dynamicSessionToken: void 0
405
+ });
406
+ const client = new _aws_sdk_client_redshift_data.RedshiftDataClient({
407
+ region: awsRegion,
408
+ credentials
409
+ });
410
+ if (debug) client.middlewareStack.add((next, context) => async (args) => {
411
+ console.log("Request:", {
412
+ input: args.input,
413
+ commandName: context.commandName
414
+ });
415
+ try {
416
+ const result = await next(args);
417
+ console.log("Response:", result.output);
418
+ return result;
419
+ } catch (error) {
420
+ console.error("Error:", error);
421
+ throw error;
422
+ }
423
+ }, {
424
+ step: "initialize",
425
+ name: "logRequestResponseMiddleware"
426
+ });
427
+ return client;
428
+ } catch (error) {
429
+ throw new _prismatic_io_spectral.ConnectionError(connection, `Failed to create AWS Redshift Data API client: ${error.message}`);
430
+ }
431
+ };
432
+ const getRedshiftDataApiClient = async (connection, region, debug) => {
433
+ validateConnection(connection);
434
+ const { region: awsRegion, credentials } = await getClientParams({
435
+ awsConnection: connection,
436
+ awsRegion: region,
437
+ validConnectionKeys: connectionKeys,
438
+ dynamicAccessKeyId: "",
439
+ dynamicSecretAccessKey: "",
440
+ dynamicSessionToken: void 0
441
+ });
442
+ const host = `redshift-data.${awsRegion}.amazonaws.com`;
443
+ return {
444
+ client: (0, _prismatic_io_spectral_http.createClient)({
445
+ baseUrl: `https://${host}`,
446
+ debug
447
+ }),
448
+ credentials,
449
+ host
450
+ };
451
+ };
452
+ //#endregion
453
+ //#region src/inputs/common.ts
454
+ const awsRegion = (0, _prismatic_io_spectral.input)({
455
+ ...awsRegion$1,
456
+ required: true
457
+ });
458
+ const awsConnection = (0, _prismatic_io_spectral.input)({
459
+ label: "AWS Connection",
460
+ type: "connection",
461
+ required: true,
462
+ comments: "Select the AWS connection to use for Redshift Data API access."
463
+ });
464
+ const databaseName = (0, _prismatic_io_spectral.input)({
465
+ label: "Database Name",
466
+ type: "string",
467
+ required: true,
468
+ comments: "The name of the database to connect to. This parameter is required when authenticating using either Secrets Manager or temporary credentials.",
469
+ example: "analytics",
470
+ placeholder: "Enter the database name",
471
+ clean: _prismatic_io_spectral.util.types.toString
472
+ });
473
+ const clusterIdentifier = (0, _prismatic_io_spectral.input)({
474
+ label: "Cluster Identifier",
475
+ type: "string",
476
+ required: false,
477
+ comments: "The identifier of the Redshift cluster. Required for cluster connections using either Secrets Manager or temporary credentials.",
478
+ example: "my-redshift-cluster",
479
+ placeholder: "Enter the cluster identifier",
480
+ clean: toOptionalString
481
+ });
482
+ const workgroupName = (0, _prismatic_io_spectral.input)({
483
+ label: "Workgroup Name",
484
+ type: "string",
485
+ required: false,
486
+ comments: "The name of the Redshift serverless workgroup. This parameter is required when connecting to a serverless workgroup and authenticating using either Secrets Manager or temporary credentials.",
487
+ example: "my-workgroup",
488
+ placeholder: "Enter the workgroup name",
489
+ clean: toOptionalString
490
+ });
491
+ const statementId = (0, _prismatic_io_spectral.input)({
492
+ label: "Statement ID",
493
+ type: "string",
494
+ required: true,
495
+ comments: "The unique identifier of the executed SQL statement returned by the Redshift Data API.",
496
+ example: "12345678-1234-1234-1234-123456789012",
497
+ placeholder: "Enter the statement ID",
498
+ clean: _prismatic_io_spectral.util.types.toString
499
+ });
500
+ const fetchAll = (0, _prismatic_io_spectral.input)({
501
+ label: "Fetch All",
502
+ type: "boolean",
503
+ comments: "When enabled, automatically fetches all pages of results. Next Token and Max Results inputs are ignored when this is enabled.",
504
+ required: false,
505
+ default: "false",
506
+ clean: _prismatic_io_spectral.util.types.toBool
507
+ });
508
+ const statementName = (0, _prismatic_io_spectral.input)({
509
+ label: "Statement Name",
510
+ type: "string",
511
+ required: false,
512
+ comments: "A descriptive label assigned to the SQL statement to help identify it when listing or filtering statements later.",
513
+ example: "GetActiveUsers",
514
+ placeholder: "Enter the statement name",
515
+ clean: toOptionalString
516
+ });
517
+ //#endregion
518
+ //#region src/constants.ts
519
+ const RESULT_FORMAT_OPTIONS = [{
520
+ label: "JSON",
521
+ value: "JSON"
522
+ }, {
523
+ label: "CSV",
524
+ value: "CSV"
525
+ }];
526
+ const STATUS_OPTIONS = [
527
+ {
528
+ label: "ALL",
529
+ value: "ALL"
530
+ },
531
+ {
532
+ label: "ABORTED",
533
+ value: "ABORTED"
534
+ },
535
+ {
536
+ label: "FAILED",
537
+ value: "FAILED"
538
+ },
539
+ {
540
+ label: "FINISHED",
541
+ value: "FINISHED"
542
+ },
543
+ {
544
+ label: "PICKED",
545
+ value: "PICKED"
546
+ },
547
+ {
548
+ label: "STARTED",
549
+ value: "STARTED"
550
+ },
551
+ {
552
+ label: "SUBMITTED",
553
+ value: "SUBMITTED"
554
+ }
555
+ ];
556
+ const RAW_REQUEST_ACTION_OPTIONS = [
557
+ {
558
+ label: "BatchExecuteStatement",
559
+ value: "RedshiftData.BatchExecuteStatement"
560
+ },
561
+ {
562
+ label: "CancelStatement",
563
+ value: "RedshiftData.CancelStatement"
564
+ },
565
+ {
566
+ label: "DescribeStatement",
567
+ value: "RedshiftData.DescribeStatement"
568
+ },
569
+ {
570
+ label: "DescribeTable",
571
+ value: "RedshiftData.DescribeTable"
572
+ },
573
+ {
574
+ label: "ExecuteStatement",
575
+ value: "RedshiftData.ExecuteStatement"
576
+ },
577
+ {
578
+ label: "GetStatementResult",
579
+ value: "RedshiftData.GetStatementResult"
580
+ },
581
+ {
582
+ label: "GetStatementResultV2",
583
+ value: "RedshiftData.GetStatementResultV2"
584
+ },
585
+ {
586
+ label: "ListDatabases",
587
+ value: "RedshiftData.ListDatabases"
588
+ },
589
+ {
590
+ label: "ListSchemas",
591
+ value: "RedshiftData.ListSchemas"
592
+ },
593
+ {
594
+ label: "ListStatements",
595
+ value: "RedshiftData.ListStatements"
596
+ },
597
+ {
598
+ label: "ListTables",
599
+ value: "RedshiftData.ListTables"
600
+ }
601
+ ];
602
+ //#endregion
603
+ //#region src/inputs/statement.ts
604
+ const databaseUser = (0, _prismatic_io_spectral.input)({
605
+ label: "Database User",
606
+ type: "string",
607
+ required: false,
608
+ comments: "The database user name. This parameter is required when connecting to a cluster as a database user and authenticating using temporary credentials.",
609
+ example: "admin",
610
+ placeholder: "Enter the database user",
611
+ clean: toOptionalString
612
+ });
613
+ const secretArn = (0, _prismatic_io_spectral.input)({
614
+ label: "Secret ARN",
615
+ type: "string",
616
+ required: false,
617
+ comments: "The ARN of the AWS Secrets Manager secret containing database credentials. Required when authenticating using Secrets Manager.",
618
+ example: "arn:aws:secretsmanager:us-east-1:123456789012:secret:redshift-credentials",
619
+ placeholder: "Enter the secret ARN",
620
+ clean: toOptionalString
621
+ });
622
+ const sqlStatement = (0, _prismatic_io_spectral.input)({
623
+ label: "SQL Statement",
624
+ type: "code",
625
+ language: "sql",
626
+ required: true,
627
+ comments: "The SQL statement to run against the Redshift database. Supports DML (INSERT, UPDATE, DELETE), DDL (CREATE, DROP, ALTER), and query (SELECT) statements.",
628
+ example: "SELECT * FROM users WHERE status = :status",
629
+ placeholder: "SELECT * FROM users WHERE status = :status",
630
+ clean: _prismatic_io_spectral.util.types.toString
631
+ });
632
+ const sqlParameters = (0, _prismatic_io_spectral.input)({
633
+ label: "SQL Parameters",
634
+ type: "string",
635
+ collection: "keyvaluelist",
636
+ required: false,
637
+ comments: "Named parameters that are substituted into the SQL statement at runtime using the colon-prefixed placeholder syntax (e.g., :status).",
638
+ example: "status: active, limit: 100",
639
+ clean: cleanSqlParameters
640
+ });
641
+ const resultFormat = (0, _prismatic_io_spectral.input)({
642
+ label: "Result Format",
643
+ type: "string",
644
+ required: false,
645
+ default: "JSON",
646
+ comments: "The format for query results (JSON or CSV).",
647
+ example: "JSON",
648
+ placeholder: "Enter the result format",
649
+ model: RESULT_FORMAT_OPTIONS,
650
+ clean: toOptionalResultFormatString
651
+ });
652
+ const sessionId = (0, _prismatic_io_spectral.input)({
653
+ label: "Session ID",
654
+ type: "string",
655
+ required: false,
656
+ comments: "The ID of an existing session to reuse for statement execution, enabling multiple statements to share temporary tables and transaction state.",
657
+ example: "session-12345678",
658
+ placeholder: "Enter the session ID",
659
+ clean: toOptionalString
660
+ });
661
+ const sessionKeepAliveSeconds = (0, _prismatic_io_spectral.input)({
662
+ label: "Session Keep Alive (seconds)",
663
+ type: "string",
664
+ required: false,
665
+ comments: "Number of seconds to keep the session alive after query completion (max 24 hours).",
666
+ example: "3600",
667
+ placeholder: "Enter the keep alive duration in seconds",
668
+ clean: toOptionalNumber
669
+ });
670
+ const clientToken = (0, _prismatic_io_spectral.input)({
671
+ label: "Client Token",
672
+ type: "string",
673
+ required: false,
674
+ comments: "Unique identifier to ensure idempotency of the request.",
675
+ example: "client-token-123",
676
+ placeholder: "Enter the client token",
677
+ clean: toOptionalString
678
+ });
679
+ const getStatementResult$1 = (0, _prismatic_io_spectral.input)({
680
+ label: "Get Statement Result",
681
+ type: "boolean",
682
+ required: false,
683
+ comments: "When true, waits for the statement to finish executing and returns its result set. Only SELECT statements produce result rows. <strong>Note:</strong> long-running statements may cause a timeout.",
684
+ example: "true",
685
+ default: "true",
686
+ clean: _prismatic_io_spectral.util.types.toBool
687
+ });
688
+ const nextToken = (0, _prismatic_io_spectral.input)({
689
+ label: "Next Token",
690
+ type: "string",
691
+ required: false,
692
+ comments: "The pagination token returned from a previous list request, used to retrieve the next page of results.",
693
+ example: "AQICAHi2k9rFZ...",
694
+ placeholder: "Enter the next token",
695
+ clean: toOptionalString
696
+ });
697
+ const status = (0, _prismatic_io_spectral.input)({
698
+ label: "Status",
699
+ type: "string",
700
+ required: true,
701
+ comments: "Filters the returned statements to only those matching this execution status. Use ALL to retrieve statements in any state.",
702
+ example: "ALL",
703
+ model: STATUS_OPTIONS,
704
+ default: "ALL",
705
+ clean: (value) => _prismatic_io_spectral.util.types.toString(value)
706
+ });
707
+ const executeStatementInputs = {
708
+ awsConnection,
709
+ sqlStatement,
710
+ databaseName,
711
+ awsRegion,
712
+ workgroupName,
713
+ clusterIdentifier,
714
+ getStatementResult: getStatementResult$1,
715
+ databaseUser,
716
+ secretArn,
717
+ sqlParameters,
718
+ additionalFields: (0, _prismatic_io_spectral.structuredObjectInput)({
719
+ label: "Additional Fields",
720
+ required: false,
721
+ comments: "Additional optional fields: includes Statement Name, Result Format, Session Keep Alive (seconds), Client Token, and Session ID.",
722
+ inputs: {
723
+ statementName,
724
+ resultFormat,
725
+ sessionKeepAliveSeconds,
726
+ clientToken,
727
+ sessionId
728
+ }
729
+ })
730
+ };
731
+ const getStatementResultInputs = {
732
+ awsConnection,
733
+ statementId: {
734
+ ...statementId,
735
+ comments: `${statementId.comments} <strong>Note:</strong> Only statements that return results are supported.`
736
+ },
737
+ awsRegion,
738
+ nextToken
739
+ };
740
+ const pagination = (0, _prismatic_io_spectral.structuredObjectInput)({
741
+ label: "Pagination",
742
+ required: false,
743
+ comments: "Page and page-size controls.",
744
+ inputs: {
745
+ nextToken,
746
+ maxResults: (0, _prismatic_io_spectral.input)({
747
+ label: "Max Results",
748
+ type: "string",
749
+ required: false,
750
+ comments: "The maximum number of SQL statements to return per page. Valid range: 0-100.",
751
+ example: "100",
752
+ placeholder: "100",
753
+ clean: toOptionalNumber
754
+ })
755
+ }
756
+ });
757
+ const listStatementsInputs = {
758
+ awsConnection,
759
+ awsRegion,
760
+ status,
761
+ filters: (0, _prismatic_io_spectral.structuredObjectInput)({
762
+ label: "Filters",
763
+ required: false,
764
+ comments: "Optional filters to narrow the returned statements by database, workgroup, cluster, and statement name.",
765
+ inputs: {
766
+ databaseName: {
767
+ ...databaseName,
768
+ required: false,
769
+ comments: "The name of the database when listing statements run against a <code>ClusterIdentifier</code> or <code>WorkgroupName</code>."
770
+ },
771
+ workgroupName: {
772
+ ...workgroupName,
773
+ required: false,
774
+ comments: "The serverless workgroup name or Amazon Resource Name (ARN). Only statements that ran on this workgroup are returned. When providing <code>WorkgroupName</code>, then <code>ClusterIdentifier</code> can't be specified."
775
+ },
776
+ clusterIdentifier: {
777
+ ...clusterIdentifier,
778
+ required: false,
779
+ comments: "The cluster identifier. Only statements that ran on this cluster are returned. When providing <code>ClusterIdentifier</code>, then <code>WorkgroupName</code> can't be specified."
780
+ },
781
+ statementName: {
782
+ ...statementName,
783
+ comments: "The name of the SQL statement specified as input to <code>BatchExecuteStatement</code> or <code>ExecuteStatement</code> to identify the query. Multiple statements can be matched by providing a prefix that matches the beginning of the statement name."
784
+ }
785
+ }
786
+ }),
787
+ fetchAll,
788
+ pagination
789
+ };
790
+ const describeStatementInputs = {
791
+ awsConnection,
792
+ statementId,
793
+ awsRegion
794
+ };
795
+ const rawRequestInputs = {
796
+ awsConnection,
797
+ awsRegion,
798
+ body: (0, _prismatic_io_spectral.input)({
799
+ label: "Body",
800
+ type: "code",
801
+ language: "json",
802
+ required: true,
803
+ comments: "The JSON payload sent to the selected Redshift Data API operation. The required fields vary by action — refer to the AWS Redshift Data API documentation for the expected structure of each operation.",
804
+ example: JSON.stringify({
805
+ WorkgroupName: "my-workgroup",
806
+ Database: "analytics",
807
+ Sql: "SELECT * FROM users WHERE status = 'active'",
808
+ SecretArn: "arn:aws:secretsmanager:us-east-1:123456789012:secret:redshift-credentials"
809
+ }, null, 2),
810
+ clean: _prismatic_io_spectral.util.types.toString
811
+ }),
812
+ action: (0, _prismatic_io_spectral.input)({
813
+ label: "Action",
814
+ type: "string",
815
+ required: true,
816
+ comments: "The Redshift Data API operation to invoke. Determines which API method is called with the provided body.",
817
+ example: "RedshiftData.ExecuteStatement",
818
+ placeholder: "Enter the action",
819
+ model: RAW_REQUEST_ACTION_OPTIONS,
820
+ clean: _prismatic_io_spectral.util.types.toString
821
+ })
822
+ };
823
+ //#endregion
824
+ //#region src/actions/misc/index.ts
825
+ var misc_default = { rawRequest: (0, _prismatic_io_spectral.action)({
826
+ display: {
827
+ label: "Raw Request",
828
+ description: "Send raw HTTP request to Redshift Data API."
829
+ },
830
+ inputs: rawRequestInputs,
831
+ perform: async (context, { awsConnection, awsRegion, body, action }) => {
832
+ const { client, credentials, host } = await getRedshiftDataApiClient(awsConnection, awsRegion, context.debug.enabled);
833
+ const requestOpts = {
834
+ host,
835
+ path: "/",
836
+ service: "redshift-data",
837
+ region: awsRegion,
838
+ method: "POST",
839
+ headers: {
840
+ "Content-Type": "application/x-amz-json-1.1",
841
+ "X-Amz-Target": action
842
+ },
843
+ body
844
+ };
845
+ (0, aws4.sign)(requestOpts, credentials);
846
+ const { data } = await client.post("/", requestOpts.body, { headers: requestOpts.headers });
847
+ return { data };
848
+ }
849
+ }) };
850
+ //#endregion
851
+ //#region src/examplePayloads/getStatementResultExamplePayload.ts
852
+ const getStatementResultExamplePayload = { data: {
853
+ $metadata: {
854
+ httpStatusCode: 200,
855
+ requestId: "example-request-id-12345-67890-abcdef",
856
+ extendedRequestId: void 0,
857
+ cfId: void 0,
858
+ attempts: 1,
859
+ totalRetryDelay: 0
860
+ },
861
+ ColumnMetadata: [
862
+ {
863
+ isCaseSensitive: false,
864
+ isCurrency: false,
865
+ isSigned: true,
866
+ label: "id",
867
+ length: 0,
868
+ name: "id",
869
+ nullable: 1,
870
+ precision: 10,
871
+ scale: 0,
872
+ schemaName: "public",
873
+ tableName: "users",
874
+ typeName: "int4"
875
+ },
876
+ {
877
+ isCaseSensitive: true,
878
+ isCurrency: false,
879
+ isSigned: false,
880
+ label: "name",
881
+ length: 0,
882
+ name: "name",
883
+ nullable: 1,
884
+ precision: 50,
885
+ scale: 0,
886
+ schemaName: "public",
887
+ tableName: "users",
888
+ typeName: "varchar"
889
+ },
890
+ {
891
+ isCaseSensitive: true,
892
+ isCurrency: false,
893
+ isSigned: false,
894
+ label: "email",
895
+ length: 0,
896
+ name: "email",
897
+ nullable: 1,
898
+ precision: 100,
899
+ scale: 0,
900
+ schemaName: "public",
901
+ tableName: "users",
902
+ typeName: "varchar"
903
+ }
904
+ ],
905
+ Records: [[
906
+ { longValue: 1 },
907
+ { stringValue: "Alice" },
908
+ { stringValue: "alice@example.com" }
909
+ ]],
910
+ TotalNumRows: 1
911
+ } };
912
+ //#endregion
913
+ //#region src/examplePayloads/executeStatementExamplePayload.ts
914
+ const executeStatementExamplePayload = { data: {
915
+ executeStatement: {
916
+ $metadata: {
917
+ httpStatusCode: 200,
918
+ requestId: "example-request-id-12345-67890-abcdef",
919
+ extendedRequestId: void 0,
920
+ cfId: void 0,
921
+ attempts: 1,
922
+ totalRetryDelay: 0
923
+ },
924
+ CreatedAt: /* @__PURE__ */ new Date("2025-01-15T10:30:00.000Z"),
925
+ Database: "example_database",
926
+ Id: "example-statement-id-12345-67890-abcdef",
927
+ SecretArn: "arn:aws:secretsmanager:us-east-1:123456789012:secret:redshift/example-secret-abc123",
928
+ WorkgroupName: "example_workgroup"
929
+ },
930
+ statementResults: getStatementResultExamplePayload.data
931
+ } };
932
+ //#endregion
933
+ //#region src/examplePayloads/listStatementsExamplePayload.ts
934
+ const listStatementsExamplePayload = { data: {
935
+ $metadata: {
936
+ httpStatusCode: 200,
937
+ requestId: "example-list-request-id-12345-67890-abcdef",
938
+ extendedRequestId: void 0,
939
+ cfId: void 0,
940
+ attempts: 1,
941
+ totalRetryDelay: 0
942
+ },
943
+ Statements: [{
944
+ CreatedAt: /* @__PURE__ */ new Date("2025-01-15T10:30:00.000Z"),
945
+ Id: "example-statement-id-12345-67890-abcdef",
946
+ QueryString: "CREATE TABLE users (\n id INT,\n name VARCHAR(50),\n email VARCHAR(100)\n);\n",
947
+ ResultFormat: "JSON",
948
+ SecretArn: "arn:aws:secretsmanager:us-east-1:123456789012:secret:redshift/example-secret-abc123",
949
+ StatementName: "ExampleStatement",
950
+ Status: "PICKED",
951
+ UpdatedAt: /* @__PURE__ */ new Date("2025-01-15T10:31:00.000Z")
952
+ }]
953
+ } };
954
+ //#endregion
955
+ //#region src/examplePayloads/describeStatementExamplePayload.ts
956
+ const describeStatementExamplePayload = { data: {
957
+ $metadata: {
958
+ httpStatusCode: 200,
959
+ requestId: "example-request-id-12345-67890-abcdef",
960
+ extendedRequestId: void 0,
961
+ cfId: void 0,
962
+ attempts: 1,
963
+ totalRetryDelay: 0
964
+ },
965
+ CreatedAt: /* @__PURE__ */ new Date("2025-01-15T10:30:00.000Z"),
966
+ Database: "example_database",
967
+ Duration: 257716773,
968
+ HasResultSet: false,
969
+ Id: "example-statement-id-12345-67890-abcdef",
970
+ QueryString: "INSERT INTO example_table (id, name, email)\nVALUES (1, 'Example User', 'user@example.com');\n",
971
+ RedshiftPid: 123456789,
972
+ RedshiftQueryId: 987654,
973
+ ResultFormat: "JSON",
974
+ ResultRows: 1,
975
+ ResultSize: 0,
976
+ SecretArn: "arn:aws:secretsmanager:us-east-1:123456789012:secret:redshift/example-secret-name",
977
+ Status: "FINISHED",
978
+ UpdatedAt: /* @__PURE__ */ new Date("2025-01-15T10:31:00.000Z"),
979
+ WorkgroupName: "example-workgroup"
980
+ } };
981
+ //#endregion
982
+ //#region src/actions/statements/index.ts
983
+ var statements_default = {
984
+ describeStatement: (0, _prismatic_io_spectral.action)({
985
+ display: {
986
+ label: "Describe Statement",
987
+ description: "Get detailed information about a specific SQL statement in Redshift."
988
+ },
989
+ inputs: describeStatementInputs,
990
+ perform: async (context, { awsConnection, awsRegion, statementId }) => {
991
+ const client = await createRedshiftClient(awsConnection, awsRegion, context.debug.enabled);
992
+ const command = new _aws_sdk_client_redshift_data.DescribeStatementCommand({ Id: statementId });
993
+ return { data: await client.send(command) };
994
+ },
995
+ examplePayload: describeStatementExamplePayload
996
+ }),
997
+ executeStatement: (0, _prismatic_io_spectral.action)({
998
+ display: {
999
+ label: "Execute SQL Statement",
1000
+ description: "Execute a SQL statement in Redshift."
1001
+ },
1002
+ inputs: executeStatementInputs,
1003
+ perform: async (context, { awsConnection, sqlStatement, databaseName, awsRegion, workgroupName, clusterIdentifier, getStatementResult, databaseUser, secretArn, sqlParameters, additionalFields = {} }) => {
1004
+ const client = await createRedshiftClient(awsConnection, awsRegion, context.debug.enabled);
1005
+ if (!clusterIdentifier && !workgroupName) throw new Error("Either Cluster Identifier or Workgroup Name must be provided");
1006
+ const command = new _aws_sdk_client_redshift_data.ExecuteStatementCommand({
1007
+ Sql: sqlStatement,
1008
+ Database: databaseName,
1009
+ StatementName: additionalFields.statementName,
1010
+ DbUser: databaseUser,
1011
+ SecretArn: secretArn,
1012
+ Parameters: sqlParameters,
1013
+ ResultFormat: additionalFields.resultFormat,
1014
+ SessionId: additionalFields.sessionId,
1015
+ SessionKeepAliveSeconds: additionalFields.sessionKeepAliveSeconds,
1016
+ ClientToken: additionalFields.clientToken,
1017
+ ClusterIdentifier: clusterIdentifier,
1018
+ WorkgroupName: workgroupName
1019
+ });
1020
+ const response = await client.send(command);
1021
+ if (!getStatementResult) return { data: { executeStatement: response } };
1022
+ const id = response.Id;
1023
+ if (!id) throw new Error("Statement ID not found in execute statement response");
1024
+ const describeCommandInput = { Id: id };
1025
+ let needsToWait = true;
1026
+ let status;
1027
+ let hasResultSet = false;
1028
+ do {
1029
+ const describeCommand = new _aws_sdk_client_redshift_data.DescribeStatementCommand(describeCommandInput);
1030
+ const describeResponse = await client.send(describeCommand);
1031
+ status = describeResponse.Status;
1032
+ if (!status) throw new Error("Status not found in describe statement response");
1033
+ needsToWait = ![
1034
+ "FINISHED",
1035
+ "FAILED",
1036
+ "ABORTED"
1037
+ ].includes(status);
1038
+ hasResultSet = describeResponse.HasResultSet ?? false;
1039
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
1040
+ } while (needsToWait);
1041
+ if (status === _aws_sdk_client_redshift_data.StatusString.FAILED) throw new Error("Statement failed");
1042
+ if (status === _aws_sdk_client_redshift_data.StatusString.ABORTED) throw new Error("Statement aborted");
1043
+ if (hasResultSet) {
1044
+ const getStatementResultCommand = new _aws_sdk_client_redshift_data.GetStatementResultCommand({ Id: id });
1045
+ return { data: {
1046
+ executeStatement: response,
1047
+ statementResults: await client.send(getStatementResultCommand)
1048
+ } };
1049
+ }
1050
+ return { data: {
1051
+ executeStatement: response,
1052
+ statementResults: null
1053
+ } };
1054
+ },
1055
+ examplePayload: executeStatementExamplePayload
1056
+ }),
1057
+ getStatementResult: (0, _prismatic_io_spectral.action)({
1058
+ display: {
1059
+ label: "Get Statement Result",
1060
+ description: "Retrieve the results of an executed SQL statement from Redshift."
1061
+ },
1062
+ inputs: getStatementResultInputs,
1063
+ perform: async (context, { awsConnection, awsRegion, statementId, nextToken }) => {
1064
+ const client = await createRedshiftClient(awsConnection, awsRegion, context.debug.enabled);
1065
+ const command = new _aws_sdk_client_redshift_data.GetStatementResultCommand({
1066
+ Id: statementId,
1067
+ NextToken: nextToken
1068
+ });
1069
+ return { data: await client.send(command) };
1070
+ },
1071
+ examplePayload: getStatementResultExamplePayload
1072
+ }),
1073
+ listStatements: (0, _prismatic_io_spectral.action)({
1074
+ display: {
1075
+ label: "List Statements",
1076
+ description: "List executed SQL statements in Redshift."
1077
+ },
1078
+ inputs: listStatementsInputs,
1079
+ perform: async (context, { awsConnection, awsRegion, status, fetchAll, filters = {}, pagination = {} }) => {
1080
+ const client = await createRedshiftClient(awsConnection, awsRegion, context.debug.enabled);
1081
+ if (fetchAll) {
1082
+ const { allStatements, lastResponse } = await getAllStatements({
1083
+ client,
1084
+ databaseName: filters.databaseName,
1085
+ workgroupName: filters.workgroupName,
1086
+ clusterIdentifier: filters.clusterIdentifier,
1087
+ status,
1088
+ statementName: filters.statementName
1089
+ });
1090
+ return { data: {
1091
+ ...lastResponse,
1092
+ Statements: allStatements
1093
+ } };
1094
+ }
1095
+ const command = new _aws_sdk_client_redshift_data.ListStatementsCommand({
1096
+ Database: filters.databaseName,
1097
+ WorkgroupName: filters.workgroupName,
1098
+ ClusterIdentifier: filters.clusterIdentifier,
1099
+ Status: status,
1100
+ StatementName: filters.statementName,
1101
+ NextToken: pagination.nextToken,
1102
+ MaxResults: pagination.maxResults
1103
+ });
1104
+ return { data: await client.send(command) };
1105
+ },
1106
+ examplePayload: listStatementsExamplePayload
1107
+ })
1108
+ };
1109
+ //#endregion
1110
+ //#region src/actions/index.ts
1111
+ var actions_default = {
1112
+ ...misc_default,
1113
+ ...statements_default
1114
+ };
1115
+ //#endregion
1116
+ //#region src/dataSources/index.ts
1117
+ var dataSources_default = { selectRegion };
1118
+ //#endregion
1119
+ //#region src/index.ts
1120
+ var src_default = (0, _prismatic_io_spectral.component)({
1121
+ key: "aws-redshift",
1122
+ public: true,
1123
+ display: {
1124
+ label: "Redshift",
1125
+ description: "Execute SQL statements and manage data in Amazon Redshift using the AWS Redshift Data API",
1126
+ iconPath: "icon.png",
1127
+ category: "Application Connectors"
1128
+ },
1129
+ documentationUrl: "https://prismatic.io/docs/components/aws-redshift/",
1130
+ connections: connections_default,
1131
+ dataSources: dataSources_default,
1132
+ actions: actions_default,
1133
+ hooks: { error: _prismatic_io_spectral_http.handleErrors }
1134
+ });
1135
+ //#endregion
1136
+ //#region npm-dist/.entry.ts
1137
+ var _entry_default = (0, _prismatic_io_spectral.callableComponent)(src_default);
1138
+ //#endregion
1139
+ module.exports = _entry_default;