@lightdash/warehouses 2.228.0 → 2.229.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/dist/.tsbuildinfo.build +1 -0
- package/package.json +4 -4
- package/dist/.tsbuildinfo +0 -1
- package/dist/ssh/sshTunnelFailure.test.d.ts +0 -2
- package/dist/ssh/sshTunnelFailure.test.d.ts.map +0 -1
- package/dist/ssh/sshTunnelFailure.test.js +0 -90
- package/dist/validateWarehouseColumnReferences.test.d.ts +0 -2
- package/dist/validateWarehouseColumnReferences.test.d.ts.map +0 -1
- package/dist/validateWarehouseColumnReferences.test.js +0 -168
- package/dist/warehouseClients/AthenaWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/AthenaWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/AthenaWarehouseClient.test.js +0 -261
- package/dist/warehouseClients/BigqueryWarehouseClient.mock.d.ts +0 -83
- package/dist/warehouseClients/BigqueryWarehouseClient.mock.d.ts.map +0 -1
- package/dist/warehouseClients/BigqueryWarehouseClient.mock.js +0 -130
- package/dist/warehouseClients/BigqueryWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/BigqueryWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/BigqueryWarehouseClient.test.js +0 -493
- package/dist/warehouseClients/ClickhouseWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/ClickhouseWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/ClickhouseWarehouseClient.test.js +0 -115
- package/dist/warehouseClients/DatabricksWarehouseClient.mock.d.ts +0 -17
- package/dist/warehouseClients/DatabricksWarehouseClient.mock.d.ts.map +0 -1
- package/dist/warehouseClients/DatabricksWarehouseClient.mock.js +0 -111
- package/dist/warehouseClients/DatabricksWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/DatabricksWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/DatabricksWarehouseClient.test.js +0 -592
- package/dist/warehouseClients/DatabricksWarehouseStartupRetry.test.d.ts +0 -2
- package/dist/warehouseClients/DatabricksWarehouseStartupRetry.test.d.ts.map +0 -1
- package/dist/warehouseClients/DatabricksWarehouseStartupRetry.test.js +0 -129
- package/dist/warehouseClients/DuckdbWarehouseClient.embedded.test.d.ts +0 -2
- package/dist/warehouseClients/DuckdbWarehouseClient.embedded.test.d.ts.map +0 -1
- package/dist/warehouseClients/DuckdbWarehouseClient.embedded.test.js +0 -92
- package/dist/warehouseClients/DuckdbWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/DuckdbWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/DuckdbWarehouseClient.test.js +0 -1749
- package/dist/warehouseClients/MotherduckErrorClassifier.test.d.ts +0 -2
- package/dist/warehouseClients/MotherduckErrorClassifier.test.d.ts.map +0 -1
- package/dist/warehouseClients/MotherduckErrorClassifier.test.js +0 -31
- package/dist/warehouseClients/MotherduckInstanceCache.catalog.test.d.ts +0 -2
- package/dist/warehouseClients/MotherduckInstanceCache.catalog.test.d.ts.map +0 -1
- package/dist/warehouseClients/MotherduckInstanceCache.catalog.test.js +0 -52
- package/dist/warehouseClients/MotherduckInstanceCache.integration.test.d.ts +0 -2
- package/dist/warehouseClients/MotherduckInstanceCache.integration.test.d.ts.map +0 -1
- package/dist/warehouseClients/MotherduckInstanceCache.integration.test.js +0 -172
- package/dist/warehouseClients/MotherduckInstanceCache.security.test.d.ts +0 -2
- package/dist/warehouseClients/MotherduckInstanceCache.security.test.d.ts.map +0 -1
- package/dist/warehouseClients/MotherduckInstanceCache.security.test.js +0 -192
- package/dist/warehouseClients/MotherduckInstanceCache.test.d.ts +0 -2
- package/dist/warehouseClients/MotherduckInstanceCache.test.d.ts.map +0 -1
- package/dist/warehouseClients/MotherduckInstanceCache.test.js +0 -302
- package/dist/warehouseClients/PostgresWarehouseClient.mock.d.ts +0 -8
- package/dist/warehouseClients/PostgresWarehouseClient.mock.d.ts.map +0 -1
- package/dist/warehouseClients/PostgresWarehouseClient.mock.js +0 -66
- package/dist/warehouseClients/PostgresWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/PostgresWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/PostgresWarehouseClient.test.js +0 -371
- package/dist/warehouseClients/RedshiftWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/RedshiftWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/RedshiftWarehouseClient.test.js +0 -126
- package/dist/warehouseClients/SnowflakeWarehouseClient.mock.d.ts +0 -41
- package/dist/warehouseClients/SnowflakeWarehouseClient.mock.d.ts.map +0 -1
- package/dist/warehouseClients/SnowflakeWarehouseClient.mock.js +0 -184
- package/dist/warehouseClients/SnowflakeWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/SnowflakeWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/SnowflakeWarehouseClient.test.js +0 -777
- package/dist/warehouseClients/TrinoWarehouseClient.mock.d.ts +0 -23
- package/dist/warehouseClients/TrinoWarehouseClient.mock.d.ts.map +0 -1
- package/dist/warehouseClients/TrinoWarehouseClient.mock.js +0 -102
- package/dist/warehouseClients/TrinoWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/TrinoWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/TrinoWarehouseClient.test.js +0 -230
- package/dist/warehouseClients/WarehouseClient.mock.d.ts +0 -13
- package/dist/warehouseClients/WarehouseClient.mock.d.ts.map +0 -1
- package/dist/warehouseClients/WarehouseClient.mock.js +0 -51
- package/dist/warehouseClients/numericKinds.test.d.ts +0 -2
- package/dist/warehouseClients/numericKinds.test.d.ts.map +0 -1
- package/dist/warehouseClients/numericKinds.test.js +0 -168
- package/dist/warehouseClients/pgProtocolGuard.integration.test.d.ts +0 -2
- package/dist/warehouseClients/pgProtocolGuard.integration.test.d.ts.map +0 -1
- package/dist/warehouseClients/pgProtocolGuard.integration.test.js +0 -93
- package/dist/warehouseClients/pgProtocolGuard.test.d.ts +0 -2
- package/dist/warehouseClients/pgProtocolGuard.test.d.ts.map +0 -1
- package/dist/warehouseClients/pgProtocolGuard.test.js +0 -48
- package/dist/warehouseClients/redshiftIamCredentials.test.d.ts +0 -2
- package/dist/warehouseClients/redshiftIamCredentials.test.d.ts.map +0 -1
- package/dist/warehouseClients/redshiftIamCredentials.test.js +0 -210
- package/dist/warehouseClients/timestampDomain.test.d.ts +0 -2
- package/dist/warehouseClients/timestampDomain.test.d.ts.map +0 -1
- package/dist/warehouseClients/timestampDomain.test.js +0 -101
|
@@ -1,93 +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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
require("./pgProtocolGuard");
|
|
37
|
-
const net = __importStar(require("net"));
|
|
38
|
-
const pg_1 = require("pg");
|
|
39
|
-
// Builds a full AuthenticationResponse wire message with the given sub-code.
|
|
40
|
-
// Byte layout: 'R' (0x52) + Int32 length (includes length bytes, excludes
|
|
41
|
-
// code) + Int32 sub-code. Mirrors what the Redshift server sends for IAM
|
|
42
|
-
// Identity Center auth (sub-code 13) before pg-protocol's Parser throws.
|
|
43
|
-
const buildAuthTypeMessage = (subCode) => {
|
|
44
|
-
const buffer = Buffer.alloc(9);
|
|
45
|
-
buffer.writeUInt8(0x52, 0); // 'R'
|
|
46
|
-
buffer.writeUInt32BE(8, 1); // length
|
|
47
|
-
buffer.writeInt32BE(subCode, 5);
|
|
48
|
-
return buffer;
|
|
49
|
-
};
|
|
50
|
-
const startFakePostgresServer = (subCode) => new Promise((resolve) => {
|
|
51
|
-
const server = net.createServer((socket) => {
|
|
52
|
-
// Swallow the client's startup packet, then send the bad auth
|
|
53
|
-
// message. We only need one data event to kick it off.
|
|
54
|
-
socket.once('data', () => {
|
|
55
|
-
socket.write(buildAuthTypeMessage(subCode));
|
|
56
|
-
});
|
|
57
|
-
socket.on('error', () => {
|
|
58
|
-
/* ignore — client may RST after we send garbage */
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
server.listen(0, '127.0.0.1', () => resolve(server));
|
|
62
|
-
});
|
|
63
|
-
describe('pgProtocolGuard (integration)', () => {
|
|
64
|
-
// End-to-end regression for https://github.com/lightdash/lightdash/issues/22098.
|
|
65
|
-
// Without the guard, pg-protocol throws synchronously inside the socket's
|
|
66
|
-
// 'data' listener, which becomes an uncaught exception and crashes the
|
|
67
|
-
// Node process. With the guard, the same scenario rejects pg.Client's
|
|
68
|
-
// connect() promise cleanly.
|
|
69
|
-
it('rejects pg.Client.connect() instead of crashing the process', async () => {
|
|
70
|
-
const server = await startFakePostgresServer(13);
|
|
71
|
-
const address = server.address();
|
|
72
|
-
if (!address || typeof address === 'string') {
|
|
73
|
-
throw new Error('fake server did not bind to a TCP address');
|
|
74
|
-
}
|
|
75
|
-
const client = new pg_1.Client({
|
|
76
|
-
host: '127.0.0.1',
|
|
77
|
-
port: address.port,
|
|
78
|
-
user: 'anything',
|
|
79
|
-
password: 'anything',
|
|
80
|
-
database: 'anything',
|
|
81
|
-
ssl: false,
|
|
82
|
-
});
|
|
83
|
-
try {
|
|
84
|
-
await expect(client.connect()).rejects.toThrow(/unsupported authentication method \(code 13\).*Identity Center/);
|
|
85
|
-
}
|
|
86
|
-
finally {
|
|
87
|
-
await client.end().catch(() => { });
|
|
88
|
-
await new Promise((resolve) => {
|
|
89
|
-
server.close(() => resolve());
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pgProtocolGuard.test.d.ts","sourceRoot":"","sources":["../../src/warehouseClients/pgProtocolGuard.test.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAC"}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
require("./pgProtocolGuard");
|
|
4
|
-
const messages_1 = require("pg-protocol/dist/messages");
|
|
5
|
-
const parser_1 = require("pg-protocol/dist/parser");
|
|
6
|
-
// Build a single pg message: 1 byte code + UInt32BE length (incl. length
|
|
7
|
-
// bytes, excl. code) + payload.
|
|
8
|
-
const buildAuthenticationMessage = (authCode) => {
|
|
9
|
-
const codeByte = 82; // 'R' — AuthenticationResponse
|
|
10
|
-
const payload = Buffer.alloc(4);
|
|
11
|
-
payload.writeInt32BE(authCode, 0);
|
|
12
|
-
const length = 4 + payload.length; // length field itself + payload
|
|
13
|
-
const buffer = Buffer.alloc(1 + length);
|
|
14
|
-
buffer.writeUInt8(codeByte, 0);
|
|
15
|
-
buffer.writeUInt32BE(length, 1);
|
|
16
|
-
payload.copy(buffer, 5);
|
|
17
|
-
return buffer;
|
|
18
|
-
};
|
|
19
|
-
describe('pgProtocolGuard', () => {
|
|
20
|
-
// Regression for https://github.com/lightdash/lightdash/issues/22098
|
|
21
|
-
// Redshift IAM / Identity Center auth sends an unknown authentication
|
|
22
|
-
// message code (e.g. 13). Without the guard, pg-protocol's Parser
|
|
23
|
-
// throws synchronously from the TLSSocket 'data' listener, which
|
|
24
|
-
// becomes an uncaught exception and crashes the backend process.
|
|
25
|
-
it('converts synchronous parser errors into a DatabaseError callback', () => {
|
|
26
|
-
const parser = new parser_1.Parser();
|
|
27
|
-
const buffer = buildAuthenticationMessage(13);
|
|
28
|
-
const received = [];
|
|
29
|
-
expect(() => {
|
|
30
|
-
parser.parse(buffer, (msg) => received.push(msg));
|
|
31
|
-
}).not.toThrow();
|
|
32
|
-
expect(received).toHaveLength(1);
|
|
33
|
-
const [msg] = received;
|
|
34
|
-
expect(msg).toBeInstanceOf(messages_1.DatabaseError);
|
|
35
|
-
expect(msg.name).toBe('error');
|
|
36
|
-
expect(msg.message).toMatch(/unsupported authentication method \(code 13\)/);
|
|
37
|
-
expect(msg.message).toMatch(/Identity Center/);
|
|
38
|
-
});
|
|
39
|
-
it('passes known messages through unchanged', () => {
|
|
40
|
-
const parser = new parser_1.Parser();
|
|
41
|
-
// Auth code 0 — AuthenticationOk
|
|
42
|
-
const buffer = buildAuthenticationMessage(0);
|
|
43
|
-
const received = [];
|
|
44
|
-
parser.parse(buffer, (msg) => received.push(msg));
|
|
45
|
-
expect(received).toHaveLength(1);
|
|
46
|
-
expect(received[0].name).toBe('authenticationOk');
|
|
47
|
-
});
|
|
48
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"redshiftIamCredentials.test.d.ts","sourceRoot":"","sources":["../../src/warehouseClients/redshiftIamCredentials.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
/* eslint-disable prefer-arrow-callback, func-names */
|
|
4
|
-
const common_1 = require("@lightdash/common");
|
|
5
|
-
const mockClusterSend = vi.fn();
|
|
6
|
-
const mockServerlessSend = vi.fn();
|
|
7
|
-
vi.mock('@aws-sdk/client-redshift', () => ({
|
|
8
|
-
RedshiftClient: vi.fn(function () {
|
|
9
|
-
return { send: mockClusterSend };
|
|
10
|
-
}),
|
|
11
|
-
GetClusterCredentialsCommand: vi.fn(function (input) {
|
|
12
|
-
return { __command: 'cluster', input };
|
|
13
|
-
}),
|
|
14
|
-
GetClusterCredentialsWithIAMCommand: vi.fn(function (input) {
|
|
15
|
-
return { __command: 'cluster-with-iam', input };
|
|
16
|
-
}),
|
|
17
|
-
}));
|
|
18
|
-
vi.mock('@aws-sdk/client-redshift-serverless', () => ({
|
|
19
|
-
RedshiftServerlessClient: vi.fn(function () {
|
|
20
|
-
return { send: mockServerlessSend };
|
|
21
|
-
}),
|
|
22
|
-
GetCredentialsCommand: vi.fn(function (input) {
|
|
23
|
-
return { __command: 'serverless', input };
|
|
24
|
-
}),
|
|
25
|
-
}));
|
|
26
|
-
const { mockFromTemporaryCredentials } = vi.hoisted(() => ({
|
|
27
|
-
mockFromTemporaryCredentials: vi.fn(() => 'sts-credentials'),
|
|
28
|
-
}));
|
|
29
|
-
vi.mock('@aws-sdk/credential-providers', () => ({
|
|
30
|
-
fromTemporaryCredentials: mockFromTemporaryCredentials,
|
|
31
|
-
}));
|
|
32
|
-
// eslint-disable-next-line import/first -- Must import after mocks are set up
|
|
33
|
-
const redshiftIamCredentials_1 = require("./redshiftIamCredentials");
|
|
34
|
-
const provisionedCredentials = {
|
|
35
|
-
type: common_1.WarehouseTypes.REDSHIFT,
|
|
36
|
-
host: 'my-cluster.abc123.us-east-1.redshift.amazonaws.com',
|
|
37
|
-
user: 'analytics',
|
|
38
|
-
port: 5439,
|
|
39
|
-
dbname: 'dev',
|
|
40
|
-
schema: 'public',
|
|
41
|
-
authenticationType: common_1.RedshiftAuthenticationType.IAM,
|
|
42
|
-
region: 'us-east-1',
|
|
43
|
-
clusterIdentifier: 'my-cluster',
|
|
44
|
-
accessKeyId: 'AKID',
|
|
45
|
-
secretAccessKey: 'SECRET',
|
|
46
|
-
};
|
|
47
|
-
const serverlessCredentials = {
|
|
48
|
-
type: common_1.WarehouseTypes.REDSHIFT,
|
|
49
|
-
host: 'my-wg.123.us-east-1.redshift-serverless.amazonaws.com',
|
|
50
|
-
user: '',
|
|
51
|
-
port: 5439,
|
|
52
|
-
dbname: 'dev',
|
|
53
|
-
schema: 'public',
|
|
54
|
-
authenticationType: common_1.RedshiftAuthenticationType.IAM,
|
|
55
|
-
region: 'us-east-1',
|
|
56
|
-
isServerless: true,
|
|
57
|
-
workgroupName: 'my-workgroup',
|
|
58
|
-
accessKeyId: 'AKID',
|
|
59
|
-
secretAccessKey: 'SECRET',
|
|
60
|
-
};
|
|
61
|
-
describe('getRedshiftAwsCredentials', () => {
|
|
62
|
-
beforeEach(() => {
|
|
63
|
-
vi.clearAllMocks();
|
|
64
|
-
});
|
|
65
|
-
test('returns static credentials when access keys are provided', () => {
|
|
66
|
-
const result = (0, redshiftIamCredentials_1.getRedshiftAwsCredentials)(provisionedCredentials);
|
|
67
|
-
expect(result).toEqual({
|
|
68
|
-
accessKeyId: 'AKID',
|
|
69
|
-
secretAccessKey: 'SECRET',
|
|
70
|
-
sessionToken: undefined,
|
|
71
|
-
});
|
|
72
|
-
expect(mockFromTemporaryCredentials).not.toHaveBeenCalled();
|
|
73
|
-
});
|
|
74
|
-
test('returns undefined (default chain) when no access keys are provided', () => {
|
|
75
|
-
const result = (0, redshiftIamCredentials_1.getRedshiftAwsCredentials)({
|
|
76
|
-
...provisionedCredentials,
|
|
77
|
-
accessKeyId: undefined,
|
|
78
|
-
secretAccessKey: undefined,
|
|
79
|
-
});
|
|
80
|
-
expect(result).toBeUndefined();
|
|
81
|
-
});
|
|
82
|
-
test('wraps with assume-role when assumeRoleArn is set', () => {
|
|
83
|
-
(0, redshiftIamCredentials_1.getRedshiftAwsCredentials)({
|
|
84
|
-
...provisionedCredentials,
|
|
85
|
-
assumeRoleArn: 'arn:aws:iam::123456789012:role/redshift',
|
|
86
|
-
assumeRoleExternalId: 'ext-1',
|
|
87
|
-
});
|
|
88
|
-
expect(mockFromTemporaryCredentials).toHaveBeenCalledWith({
|
|
89
|
-
masterCredentials: {
|
|
90
|
-
accessKeyId: 'AKID',
|
|
91
|
-
secretAccessKey: 'SECRET',
|
|
92
|
-
sessionToken: undefined,
|
|
93
|
-
},
|
|
94
|
-
params: {
|
|
95
|
-
RoleArn: 'arn:aws:iam::123456789012:role/redshift',
|
|
96
|
-
RoleSessionName: 'lightdash-redshift-session',
|
|
97
|
-
ExternalId: 'ext-1',
|
|
98
|
-
},
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
test('does not re-assume when a session token is already present', () => {
|
|
102
|
-
const result = (0, redshiftIamCredentials_1.getRedshiftAwsCredentials)({
|
|
103
|
-
...provisionedCredentials,
|
|
104
|
-
sessionToken: 'TEMP_TOKEN',
|
|
105
|
-
assumeRoleArn: 'arn:aws:iam::123456789012:role/redshift',
|
|
106
|
-
});
|
|
107
|
-
expect(mockFromTemporaryCredentials).not.toHaveBeenCalled();
|
|
108
|
-
expect(result).toEqual({
|
|
109
|
-
accessKeyId: 'AKID',
|
|
110
|
-
secretAccessKey: 'SECRET',
|
|
111
|
-
sessionToken: 'TEMP_TOKEN',
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
describe('mintRedshiftIamCredentials', () => {
|
|
116
|
-
beforeEach(() => {
|
|
117
|
-
vi.clearAllMocks();
|
|
118
|
-
});
|
|
119
|
-
test('mints credentials for a provisioned cluster', async () => {
|
|
120
|
-
const expiration = new Date('2026-01-01T00:00:00Z');
|
|
121
|
-
mockClusterSend.mockResolvedValue({
|
|
122
|
-
DbUser: 'IAM:analytics',
|
|
123
|
-
DbPassword: 'temp-password',
|
|
124
|
-
Expiration: expiration,
|
|
125
|
-
});
|
|
126
|
-
const result = await (0, redshiftIamCredentials_1.mintRedshiftIamCredentials)(provisionedCredentials);
|
|
127
|
-
expect(result).toEqual({
|
|
128
|
-
dbUser: 'IAM:analytics',
|
|
129
|
-
dbPassword: 'temp-password',
|
|
130
|
-
expiration,
|
|
131
|
-
});
|
|
132
|
-
expect(mockClusterSend).toHaveBeenCalledTimes(1);
|
|
133
|
-
expect(mockServerlessSend).not.toHaveBeenCalled();
|
|
134
|
-
});
|
|
135
|
-
test('mints credentials from the IAM identity when no database user is provided', async () => {
|
|
136
|
-
const expiration = new Date('2026-01-01T00:00:00Z');
|
|
137
|
-
mockClusterSend.mockResolvedValue({
|
|
138
|
-
DbUser: 'IAMR:user-role',
|
|
139
|
-
DbPassword: 'temp-password',
|
|
140
|
-
Expiration: expiration,
|
|
141
|
-
});
|
|
142
|
-
const result = await (0, redshiftIamCredentials_1.mintRedshiftIamCredentials)({
|
|
143
|
-
...provisionedCredentials,
|
|
144
|
-
user: '',
|
|
145
|
-
assumeRoleArn: 'arn:aws:iam::123456789012:role/user-role',
|
|
146
|
-
});
|
|
147
|
-
expect(result).toEqual({
|
|
148
|
-
dbUser: 'IAMR:user-role',
|
|
149
|
-
dbPassword: 'temp-password',
|
|
150
|
-
expiration,
|
|
151
|
-
});
|
|
152
|
-
expect(mockClusterSend).toHaveBeenCalledWith({
|
|
153
|
-
__command: 'cluster-with-iam',
|
|
154
|
-
input: {
|
|
155
|
-
ClusterIdentifier: 'my-cluster',
|
|
156
|
-
DbName: 'dev',
|
|
157
|
-
DurationSeconds: 3600,
|
|
158
|
-
},
|
|
159
|
-
});
|
|
160
|
-
expect(mockServerlessSend).not.toHaveBeenCalled();
|
|
161
|
-
});
|
|
162
|
-
test('mints credentials for a serverless workgroup', async () => {
|
|
163
|
-
const expiration = new Date('2026-01-01T00:00:00Z');
|
|
164
|
-
mockServerlessSend.mockResolvedValue({
|
|
165
|
-
dbUser: 'IAMR:role',
|
|
166
|
-
dbPassword: 'temp-password',
|
|
167
|
-
expiration,
|
|
168
|
-
});
|
|
169
|
-
const result = await (0, redshiftIamCredentials_1.mintRedshiftIamCredentials)(serverlessCredentials);
|
|
170
|
-
expect(result).toEqual({
|
|
171
|
-
dbUser: 'IAMR:role',
|
|
172
|
-
dbPassword: 'temp-password',
|
|
173
|
-
expiration,
|
|
174
|
-
});
|
|
175
|
-
expect(mockServerlessSend).toHaveBeenCalledTimes(1);
|
|
176
|
-
expect(mockClusterSend).not.toHaveBeenCalled();
|
|
177
|
-
});
|
|
178
|
-
test('throws when the region is missing', async () => {
|
|
179
|
-
await expect((0, redshiftIamCredentials_1.mintRedshiftIamCredentials)({
|
|
180
|
-
...provisionedCredentials,
|
|
181
|
-
region: undefined,
|
|
182
|
-
})).rejects.toThrow(common_1.WarehouseConnectionError);
|
|
183
|
-
});
|
|
184
|
-
test('throws when a provisioned cluster identifier is missing', async () => {
|
|
185
|
-
await expect((0, redshiftIamCredentials_1.mintRedshiftIamCredentials)({
|
|
186
|
-
...provisionedCredentials,
|
|
187
|
-
clusterIdentifier: undefined,
|
|
188
|
-
})).rejects.toThrow(common_1.WarehouseConnectionError);
|
|
189
|
-
});
|
|
190
|
-
test('throws when a serverless workgroup name is missing', async () => {
|
|
191
|
-
await expect((0, redshiftIamCredentials_1.mintRedshiftIamCredentials)({
|
|
192
|
-
...serverlessCredentials,
|
|
193
|
-
workgroupName: undefined,
|
|
194
|
-
})).rejects.toThrow(common_1.WarehouseConnectionError);
|
|
195
|
-
});
|
|
196
|
-
test('throws RedshiftIamTokenError when the AWS session token has expired', async () => {
|
|
197
|
-
mockClusterSend.mockRejectedValue({
|
|
198
|
-
name: 'ExpiredTokenException',
|
|
199
|
-
message: 'The security token included in the request is expired',
|
|
200
|
-
});
|
|
201
|
-
await expect((0, redshiftIamCredentials_1.mintRedshiftIamCredentials)(provisionedCredentials)).rejects.toThrow(common_1.RedshiftIamTokenError);
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
describe('isExpiredAwsTokenError', () => {
|
|
205
|
-
test('detects expired AWS tokens by name or message', () => {
|
|
206
|
-
expect((0, redshiftIamCredentials_1.isExpiredAwsTokenError)({ name: 'ExpiredToken' })).toBe(true);
|
|
207
|
-
expect((0, redshiftIamCredentials_1.isExpiredAwsTokenError)(new Error('The security token included in the request is expired'))).toBe(true);
|
|
208
|
-
expect((0, redshiftIamCredentials_1.isExpiredAwsTokenError)(new Error('Access denied'))).toBe(false);
|
|
209
|
-
});
|
|
210
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"timestampDomain.test.d.ts","sourceRoot":"","sources":["../../src/warehouseClients/timestampDomain.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const AthenaWarehouseClient_1 = require("./AthenaWarehouseClient");
|
|
4
|
-
const BigqueryWarehouseClient_1 = require("./BigqueryWarehouseClient");
|
|
5
|
-
const ClickhouseWarehouseClient_1 = require("./ClickhouseWarehouseClient");
|
|
6
|
-
const DatabricksWarehouseClient_1 = require("./DatabricksWarehouseClient");
|
|
7
|
-
const DuckdbWarehouseClient_1 = require("./DuckdbWarehouseClient");
|
|
8
|
-
const PostgresWarehouseClient_1 = require("./PostgresWarehouseClient");
|
|
9
|
-
const SnowflakeWarehouseClient_1 = require("./SnowflakeWarehouseClient");
|
|
10
|
-
const TrinoWarehouseClient_1 = require("./TrinoWarehouseClient");
|
|
11
|
-
describe('postgres timestamp domain', () => {
|
|
12
|
-
it('classifies naive types', () => {
|
|
13
|
-
expect((0, PostgresWarehouseClient_1.getPostgresTimestampDomain)('timestamp')).toEqual('naive');
|
|
14
|
-
expect((0, PostgresWarehouseClient_1.getPostgresTimestampDomain)('timestamp without time zone')).toEqual('naive');
|
|
15
|
-
});
|
|
16
|
-
it('classifies aware types', () => {
|
|
17
|
-
expect((0, PostgresWarehouseClient_1.getPostgresTimestampDomain)('timestamptz')).toEqual('aware');
|
|
18
|
-
expect((0, PostgresWarehouseClient_1.getPostgresTimestampDomain)('timestamp with time zone')).toEqual('aware');
|
|
19
|
-
});
|
|
20
|
-
it('leaves non-timestamp types unclassified', () => {
|
|
21
|
-
expect((0, PostgresWarehouseClient_1.getPostgresTimestampDomain)('integer')).toBeUndefined();
|
|
22
|
-
expect((0, PostgresWarehouseClient_1.getPostgresTimestampDomain)('date')).toBeUndefined();
|
|
23
|
-
expect((0, PostgresWarehouseClient_1.getPostgresTimestampDomain)('time')).toBeUndefined();
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
describe('bigquery timestamp domain', () => {
|
|
27
|
-
it('classifies DATETIME as naive and TIMESTAMP as aware', () => {
|
|
28
|
-
expect((0, BigqueryWarehouseClient_1.getBigqueryTimestampDomain)('DATETIME')).toEqual('naive');
|
|
29
|
-
expect((0, BigqueryWarehouseClient_1.getBigqueryTimestampDomain)('TIMESTAMP')).toEqual('aware');
|
|
30
|
-
});
|
|
31
|
-
it('leaves TIME and non-timestamp types unclassified', () => {
|
|
32
|
-
expect((0, BigqueryWarehouseClient_1.getBigqueryTimestampDomain)('TIME')).toBeUndefined();
|
|
33
|
-
expect((0, BigqueryWarehouseClient_1.getBigqueryTimestampDomain)('STRING')).toBeUndefined();
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
describe('snowflake timestamp domain', () => {
|
|
37
|
-
it('classifies NTZ as naive, including parameterised types', () => {
|
|
38
|
-
expect((0, SnowflakeWarehouseClient_1.getSnowflakeTimestampDomain)('TIMESTAMP_NTZ')).toEqual('naive');
|
|
39
|
-
expect((0, SnowflakeWarehouseClient_1.getSnowflakeTimestampDomain)('TIMESTAMP_NTZ(9)')).toEqual('naive');
|
|
40
|
-
});
|
|
41
|
-
it('classifies TZ and LTZ as aware', () => {
|
|
42
|
-
expect((0, SnowflakeWarehouseClient_1.getSnowflakeTimestampDomain)('TIMESTAMP_TZ')).toEqual('aware');
|
|
43
|
-
expect((0, SnowflakeWarehouseClient_1.getSnowflakeTimestampDomain)('TIMESTAMP_LTZ(9)')).toEqual('aware');
|
|
44
|
-
});
|
|
45
|
-
it('leaves bare TIMESTAMP unclassified (account-level alias)', () => {
|
|
46
|
-
expect((0, SnowflakeWarehouseClient_1.getSnowflakeTimestampDomain)('TIMESTAMP')).toBeUndefined();
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
describe('databricks timestamp domain', () => {
|
|
50
|
-
it('classifies TIMESTAMP_NTZ as naive despite type normalization truncating it', () => {
|
|
51
|
-
expect((0, DatabricksWarehouseClient_1.getDatabricksTimestampDomain)('TIMESTAMP_NTZ')).toEqual('naive');
|
|
52
|
-
});
|
|
53
|
-
it('classifies bare TIMESTAMP as aware (stores an instant)', () => {
|
|
54
|
-
expect((0, DatabricksWarehouseClient_1.getDatabricksTimestampDomain)('TIMESTAMP')).toEqual('aware');
|
|
55
|
-
});
|
|
56
|
-
it('leaves non-timestamp types unclassified', () => {
|
|
57
|
-
expect((0, DatabricksWarehouseClient_1.getDatabricksTimestampDomain)('DECIMAL(10,2)')).toBeUndefined();
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
describe('trino timestamp domain', () => {
|
|
61
|
-
it('classifies bare timestamp as naive, stripping any precision', () => {
|
|
62
|
-
expect((0, TrinoWarehouseClient_1.getTrinoTimestampDomain)('timestamp')).toEqual('naive');
|
|
63
|
-
expect((0, TrinoWarehouseClient_1.getTrinoTimestampDomain)('timestamp(3)')).toEqual('naive');
|
|
64
|
-
expect((0, TrinoWarehouseClient_1.getTrinoTimestampDomain)('timestamp(6)')).toEqual('naive');
|
|
65
|
-
});
|
|
66
|
-
it('classifies timestamp with time zone as aware', () => {
|
|
67
|
-
expect((0, TrinoWarehouseClient_1.getTrinoTimestampDomain)('timestamp with time zone')).toEqual('aware');
|
|
68
|
-
expect((0, TrinoWarehouseClient_1.getTrinoTimestampDomain)('timestamp(3) with time zone')).toEqual('aware');
|
|
69
|
-
});
|
|
70
|
-
it('leaves non-timestamp types unclassified', () => {
|
|
71
|
-
expect((0, TrinoWarehouseClient_1.getTrinoTimestampDomain)('varchar')).toBeUndefined();
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
describe('clickhouse timestamp domain', () => {
|
|
75
|
-
it('classifies DateTime types as always aware', () => {
|
|
76
|
-
expect((0, ClickhouseWarehouseClient_1.getClickhouseTimestampDomain)('DateTime')).toEqual('aware');
|
|
77
|
-
expect((0, ClickhouseWarehouseClient_1.getClickhouseTimestampDomain)("DateTime64(3, 'UTC')")).toEqual('aware');
|
|
78
|
-
expect((0, ClickhouseWarehouseClient_1.getClickhouseTimestampDomain)('Nullable(DateTime)')).toEqual('aware');
|
|
79
|
-
});
|
|
80
|
-
it('leaves non-timestamp types unclassified', () => {
|
|
81
|
-
expect((0, ClickhouseWarehouseClient_1.getClickhouseTimestampDomain)('Date')).toBeUndefined();
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
describe('athena timestamp domain', () => {
|
|
85
|
-
it('classifies bare timestamp as naive and with time zone as aware', () => {
|
|
86
|
-
expect((0, AthenaWarehouseClient_1.getAthenaTimestampDomain)('timestamp')).toEqual('naive');
|
|
87
|
-
expect((0, AthenaWarehouseClient_1.getAthenaTimestampDomain)('timestamp(3)')).toEqual('naive');
|
|
88
|
-
expect((0, AthenaWarehouseClient_1.getAthenaTimestampDomain)('timestamp with time zone')).toEqual('aware');
|
|
89
|
-
});
|
|
90
|
-
it('leaves non-timestamp types unclassified', () => {
|
|
91
|
-
expect((0, AthenaWarehouseClient_1.getAthenaTimestampDomain)('varchar')).toBeUndefined();
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
describe('duckdb timestamp domain', () => {
|
|
95
|
-
it('classifies type name strings', () => {
|
|
96
|
-
expect((0, DuckdbWarehouseClient_1.getDuckdbTimestampDomainFromString)('TIMESTAMP')).toEqual('naive');
|
|
97
|
-
expect((0, DuckdbWarehouseClient_1.getDuckdbTimestampDomainFromString)('TIMESTAMP WITH TIME ZONE')).toEqual('aware');
|
|
98
|
-
expect((0, DuckdbWarehouseClient_1.getDuckdbTimestampDomainFromString)('TIMESTAMPTZ')).toEqual('aware');
|
|
99
|
-
expect((0, DuckdbWarehouseClient_1.getDuckdbTimestampDomainFromString)('BOOLEAN')).toBeUndefined();
|
|
100
|
-
});
|
|
101
|
-
});
|