@helix-tools/sdk-typescript 1.2.1

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,160 @@
1
+ /**
2
+ * Helix Connect Platform Producer SDK
3
+ * For data producers who want to upload and manage datasets
4
+ */
5
+ export interface HelixProducerConfig {
6
+ awsAccessKeyId: string;
7
+ awsSecretAccessKey: string;
8
+ customerId: string;
9
+ apiEndpoint?: string;
10
+ region?: string;
11
+ }
12
+ /**
13
+ * Options for uploading a dataset.
14
+ *
15
+ * Security and Performance Defaults (v2.0+):
16
+ * - encrypt: true (KMS envelope encryption enabled by default)
17
+ * - compress: true (gzip compression enabled by default)
18
+ * - compressionLevel: 6 (balanced speed/size ratio)
19
+ *
20
+ * To disable encryption or compression, explicitly set to false:
21
+ * { ...options, encrypt: false, compress: false }
22
+ */
23
+ export interface UploadOptions {
24
+ /** Name for the dataset (required) */
25
+ datasetName: string;
26
+ /** Description of the dataset */
27
+ description?: string;
28
+ /** Dataset category (default: "general") */
29
+ category?: string;
30
+ /** How often data is updated (default: "daily") */
31
+ dataFreshness?: string;
32
+ /** Additional custom metadata */
33
+ metadata?: Record<string, any>;
34
+ /** Enable KMS encryption (default: true for security) */
35
+ encrypt?: boolean;
36
+ /** Enable gzip compression (default: true for cost optimization) */
37
+ compress?: boolean;
38
+ /** Gzip compression level 1-9 (default: 6, balanced speed/size) */
39
+ compressionLevel?: number;
40
+ /** Optional callback to track upload progress */
41
+ progressCallback?: (bytesUploaded: number, totalBytes: number) => void;
42
+ }
43
+ export interface Dataset {
44
+ _id?: string;
45
+ dataset_id?: string;
46
+ name: string;
47
+ description: string;
48
+ producer_id: string;
49
+ category: string;
50
+ data_freshness: string;
51
+ s3_key: string;
52
+ size_bytes: number;
53
+ metadata?: Record<string, any>;
54
+ }
55
+ export declare class HelixProducer {
56
+ private customerId;
57
+ private apiEndpoint;
58
+ private region;
59
+ private bucketName;
60
+ private kmsKeyId;
61
+ private kmsClient;
62
+ private s3Client;
63
+ private stsClient;
64
+ private awsAccessKeyId;
65
+ private awsSecretAccessKey;
66
+ /**
67
+ * Creates a new Helix Producer instance.
68
+ * Initializes AWS clients, validates credentials, and retrieves producer-specific resources from SSM.
69
+ */
70
+ constructor(config: HelixProducerConfig);
71
+ /**
72
+ * Initializes the producer by validating credentials and retrieving S3 bucket and KMS key from SSM.
73
+ * Called automatically during construction.
74
+ */
75
+ private initialize;
76
+ /**
77
+ * Compresses data using gzip compression.
78
+ * Compression works best on unencrypted data due to patterns and redundancy.
79
+ */
80
+ private compressData;
81
+ /**
82
+ * Encrypts data using envelope encryption with KMS and AES-256-GCM.
83
+ * Process: Generate data key, encrypt data with data key, encrypt data key with KMS.
84
+ * Format: [4 bytes: key length][encrypted key][16 bytes: IV][16 bytes: tag][encrypted data]
85
+ */
86
+ private encryptData;
87
+ /**
88
+ * Uploads a dataset with encryption and compression.
89
+ *
90
+ * Security and Performance Defaults (v2.0+):
91
+ * - Encryption is ENABLED by default (KMS envelope encryption)
92
+ * - Compression is ENABLED by default (gzip compression level 6)
93
+ * - This provides security by default and reduces S3 storage costs
94
+ *
95
+ * Process:
96
+ * 1. Compress data first (if enabled) - works best on unencrypted data
97
+ * 2. Encrypt compressed data (if enabled) - KMS envelope encryption
98
+ * 3. Upload to S3 with generated S3 key
99
+ * 4. Register dataset in catalog via API
100
+ *
101
+ * Example with secure defaults:
102
+ * ```typescript
103
+ * const producer = new HelixProducer({...});
104
+ * const dataset = await producer.uploadDataset('/path/to/data.ndjson', {
105
+ * datasetName: 'my-dataset',
106
+ * description: 'My dataset'
107
+ * // encrypt and compress default to true
108
+ * });
109
+ * ```
110
+ *
111
+ * To disable (not recommended for sensitive data):
112
+ * ```typescript
113
+ * await producer.uploadDataset(filePath, {
114
+ * datasetName: 'my-dataset',
115
+ * encrypt: false, // Disable encryption
116
+ * compress: false // Disable compression
117
+ * });
118
+ * ```
119
+ *
120
+ * @param filePath - Local path to the dataset file
121
+ * @param options - Upload options with secure defaults
122
+ * @returns Dataset metadata including ID and S3 key
123
+ * @throws Error if file not found, encryption fails, or upload fails
124
+ */
125
+ uploadDataset(filePath: string, options: UploadOptions): Promise<Dataset>;
126
+ /**
127
+ * Lists all datasets uploaded by this producer.
128
+ * Returns metadata for all datasets owned by the current producer account.
129
+ */
130
+ listMyDatasets(): Promise<Dataset[]>;
131
+ /**
132
+ * Signs an HTTP request using AWS Signature Version 4.
133
+ * Used for authenticating API requests to Helix Connect Platform.
134
+ */
135
+ private signRequest;
136
+ /**
137
+ * Lists incoming subscription requests for this producer.
138
+ * Returns requests that match the specified status filter.
139
+ */
140
+ listSubscriptionRequests(status?: 'pending' | 'approved' | 'rejected'): Promise<any[]>;
141
+ /**
142
+ * Approves a subscription request from a consumer.
143
+ * Creates the necessary resources (SQS queue, SNS subscription) for the consumer.
144
+ */
145
+ approveSubscriptionRequest(requestId: string, notes?: string): Promise<any>;
146
+ /**
147
+ * Rejects a subscription request from a consumer.
148
+ */
149
+ rejectSubscriptionRequest(requestId: string, reason?: string): Promise<any>;
150
+ /**
151
+ * Makes an authenticated API request with form-encoded data.
152
+ */
153
+ private makeFormApiRequest;
154
+ /**
155
+ * Makes an authenticated API request to Helix Connect Platform.
156
+ * Handles request signing, error responses, and retries.
157
+ */
158
+ private makeApiRequest;
159
+ }
160
+ //# sourceMappingURL=producer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"producer.d.ts","sourceRoot":"","sources":["../src/producer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAeH,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IAEpB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,mDAAmD;IACnD,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE/B,yDAAyD;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACxE;AAED,MAAM,WAAW,OAAO;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,kBAAkB,CAAS;IAEnC;;;OAGG;gBACS,MAAM,EAAE,mBAAmB;IA4BvC;;;OAGG;YACW,UAAU;IAoDxB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAUpB;;;;OAIG;YACW,WAAW;IA4DzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;IACG,aAAa,CACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,OAAO,CAAC;IAkHnB;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAc1C;;;OAGG;YACW,WAAW;IAyCzB;;;OAGG;IACG,wBAAwB,CAAC,MAAM,GAAE,SAAS,GAAG,UAAU,GAAG,UAAsB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAQvG;;;OAGG;IACG,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAajF;;OAEG;IACG,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAajF;;OAEG;YACW,kBAAkB;IAsChC;;;OAGG;YACW,cAAc;CAqC7B"}
@@ -0,0 +1,491 @@
1
+ "use strict";
2
+ /**
3
+ * Helix Connect Platform Producer SDK
4
+ * For data producers who want to upload and manage datasets
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ var __importDefault = (this && this.__importDefault) || function (mod) {
40
+ return (mod && mod.__esModule) ? mod : { "default": mod };
41
+ };
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.HelixProducer = void 0;
44
+ const client_kms_1 = require("@aws-sdk/client-kms");
45
+ const client_s3_1 = require("@aws-sdk/client-s3");
46
+ const client_ssm_1 = require("@aws-sdk/client-ssm");
47
+ const client_sts_1 = require("@aws-sdk/client-sts");
48
+ const signature_v4_1 = require("@smithy/signature-v4");
49
+ const protocol_http_1 = require("@smithy/protocol-http");
50
+ const sha256_js_1 = require("@aws-crypto/sha256-js");
51
+ const axios_1 = __importDefault(require("axios"));
52
+ const pako = __importStar(require("pako"));
53
+ const fs = __importStar(require("fs"));
54
+ const crypto = __importStar(require("crypto"));
55
+ class HelixProducer {
56
+ /**
57
+ * Creates a new Helix Producer instance.
58
+ * Initializes AWS clients, validates credentials, and retrieves producer-specific resources from SSM.
59
+ */
60
+ constructor(config) {
61
+ this.customerId = config.customerId;
62
+ this.apiEndpoint = (config.apiEndpoint || 'https://api.helix.tools').replace(/\/$/, '');
63
+ this.region = config.region || 'us-east-1';
64
+ this.awsAccessKeyId = config.awsAccessKeyId;
65
+ this.awsSecretAccessKey = config.awsSecretAccessKey;
66
+ // Initialize AWS clients
67
+ const awsConfig = {
68
+ region: this.region,
69
+ credentials: {
70
+ accessKeyId: this.awsAccessKeyId,
71
+ secretAccessKey: this.awsSecretAccessKey,
72
+ },
73
+ };
74
+ this.kmsClient = new client_kms_1.KMSClient(awsConfig);
75
+ this.s3Client = new client_s3_1.S3Client(awsConfig);
76
+ this.stsClient = new client_sts_1.STSClient(awsConfig);
77
+ // Will be populated after validation
78
+ this.bucketName = '';
79
+ this.kmsKeyId = '';
80
+ // Validate credentials and get producer resources
81
+ this.initialize();
82
+ }
83
+ /**
84
+ * Initializes the producer by validating credentials and retrieving S3 bucket and KMS key from SSM.
85
+ * Called automatically during construction.
86
+ */
87
+ async initialize() {
88
+ // Validate credentials
89
+ try {
90
+ const command = new client_sts_1.GetCallerIdentityCommand({});
91
+ await this.stsClient.send(command);
92
+ }
93
+ catch (error) {
94
+ throw new Error(`Invalid AWS credentials. Please check your access key and secret key. Error: ${error}`);
95
+ }
96
+ // Get producer-specific resources from SSM
97
+ const ssmClient = new client_ssm_1.SSMClient({
98
+ region: this.region,
99
+ credentials: {
100
+ accessKeyId: this.awsAccessKeyId,
101
+ secretAccessKey: this.awsSecretAccessKey,
102
+ },
103
+ });
104
+ try {
105
+ // Get S3 bucket name
106
+ const bucketParam = `/helix/customers/${this.customerId}/s3_bucket`;
107
+ const bucketResponse = await ssmClient.send(new client_ssm_1.GetParameterCommand({ Name: bucketParam }));
108
+ if (!bucketResponse.Parameter?.Value) {
109
+ throw new Error(`S3 bucket not found for producer ${this.customerId}`);
110
+ }
111
+ this.bucketName = bucketResponse.Parameter.Value;
112
+ }
113
+ catch (error) {
114
+ throw new Error(`S3 bucket not found for producer ${this.customerId}: ${error}`);
115
+ }
116
+ // Get KMS key ID (optional for producers)
117
+ try {
118
+ const kmsParam = `/helix/customers/${this.customerId}/kms_key_id`;
119
+ const kmsResponse = await ssmClient.send(new client_ssm_1.GetParameterCommand({ Name: kmsParam }));
120
+ if (kmsResponse.Parameter?.Value) {
121
+ this.kmsKeyId = kmsResponse.Parameter.Value;
122
+ }
123
+ }
124
+ catch (error) {
125
+ console.log(`Warning: KMS key not found, encryption will be disabled: ${error}`);
126
+ this.kmsKeyId = '';
127
+ }
128
+ }
129
+ /**
130
+ * Compresses data using gzip compression.
131
+ * Compression works best on unencrypted data due to patterns and redundancy.
132
+ */
133
+ compressData(data, level) {
134
+ try {
135
+ // pako expects specific compression levels: 0-9, -1
136
+ const validLevel = Math.max(0, Math.min(9, Math.floor(level)));
137
+ return Buffer.from(pako.gzip(data, { level: validLevel }));
138
+ }
139
+ catch (error) {
140
+ throw new Error(`Compression failed: ${error}`);
141
+ }
142
+ }
143
+ /**
144
+ * Encrypts data using envelope encryption with KMS and AES-256-GCM.
145
+ * Process: Generate data key, encrypt data with data key, encrypt data key with KMS.
146
+ * Format: [4 bytes: key length][encrypted key][16 bytes: IV][16 bytes: tag][encrypted data]
147
+ */
148
+ async encryptData(data) {
149
+ if (!this.kmsKeyId) {
150
+ throw new Error('KMS key not configured, cannot encrypt data');
151
+ }
152
+ try {
153
+ // Generate random data key and IV
154
+ const dataKey = crypto.randomBytes(32); // 256-bit key for AES-256
155
+ const iv = crypto.randomBytes(16); // 128-bit IV for GCM mode
156
+ // Encrypt data with data key using AES-256-GCM
157
+ const cipher = crypto.createCipheriv('aes-256-gcm', dataKey, iv);
158
+ const encryptedData = Buffer.concat([
159
+ cipher.update(data),
160
+ cipher.final(),
161
+ ]);
162
+ const authTag = cipher.getAuthTag();
163
+ // Encrypt the data key with KMS (only 32 bytes, well under 4KB limit)
164
+ const encryptCommand = new client_kms_1.EncryptCommand({
165
+ KeyId: this.kmsKeyId,
166
+ Plaintext: dataKey,
167
+ });
168
+ const encryptResult = await this.kmsClient.send(encryptCommand);
169
+ if (!encryptResult.CiphertextBlob) {
170
+ throw new Error('KMS encryption returned no ciphertext');
171
+ }
172
+ const encryptedKey = Buffer.from(encryptResult.CiphertextBlob);
173
+ // Package: [4 bytes: key length][encrypted key][16 bytes: IV][16 bytes: tag][encrypted data]
174
+ const result = Buffer.allocUnsafe(4 + encryptedKey.length + 16 + 16 + encryptedData.length);
175
+ let offset = 0;
176
+ // Write encrypted key length (4 bytes, big-endian)
177
+ result.writeUInt32BE(encryptedKey.length, offset);
178
+ offset += 4;
179
+ // Write encrypted key
180
+ encryptedKey.copy(result, offset);
181
+ offset += encryptedKey.length;
182
+ // Write IV (16 bytes)
183
+ iv.copy(result, offset);
184
+ offset += 16;
185
+ // Write auth tag (16 bytes)
186
+ authTag.copy(result, offset);
187
+ offset += 16;
188
+ // Write encrypted data
189
+ encryptedData.copy(result, offset);
190
+ return result;
191
+ }
192
+ catch (error) {
193
+ throw new Error(`Encryption failed: ${error}`);
194
+ }
195
+ }
196
+ /**
197
+ * Uploads a dataset with encryption and compression.
198
+ *
199
+ * Security and Performance Defaults (v2.0+):
200
+ * - Encryption is ENABLED by default (KMS envelope encryption)
201
+ * - Compression is ENABLED by default (gzip compression level 6)
202
+ * - This provides security by default and reduces S3 storage costs
203
+ *
204
+ * Process:
205
+ * 1. Compress data first (if enabled) - works best on unencrypted data
206
+ * 2. Encrypt compressed data (if enabled) - KMS envelope encryption
207
+ * 3. Upload to S3 with generated S3 key
208
+ * 4. Register dataset in catalog via API
209
+ *
210
+ * Example with secure defaults:
211
+ * ```typescript
212
+ * const producer = new HelixProducer({...});
213
+ * const dataset = await producer.uploadDataset('/path/to/data.ndjson', {
214
+ * datasetName: 'my-dataset',
215
+ * description: 'My dataset'
216
+ * // encrypt and compress default to true
217
+ * });
218
+ * ```
219
+ *
220
+ * To disable (not recommended for sensitive data):
221
+ * ```typescript
222
+ * await producer.uploadDataset(filePath, {
223
+ * datasetName: 'my-dataset',
224
+ * encrypt: false, // Disable encryption
225
+ * compress: false // Disable compression
226
+ * });
227
+ * ```
228
+ *
229
+ * @param filePath - Local path to the dataset file
230
+ * @param options - Upload options with secure defaults
231
+ * @returns Dataset metadata including ID and S3 key
232
+ * @throws Error if file not found, encryption fails, or upload fails
233
+ */
234
+ async uploadDataset(filePath, options) {
235
+ // Set defaults (encryption and compression enabled by default)
236
+ const category = options.category || 'general';
237
+ const dataFreshness = options.dataFreshness || 'daily';
238
+ const compress = options.compress !== false; // Default: true
239
+ let encrypt = options.encrypt !== false; // Default: true
240
+ const compressionLevel = options.compressionLevel || 6;
241
+ // Check if file exists
242
+ if (!fs.existsSync(filePath)) {
243
+ throw new Error(`File not found: ${filePath}`);
244
+ }
245
+ // Read original file
246
+ let data = fs.readFileSync(filePath);
247
+ const originalSize = data.length;
248
+ // Track sizes for metadata
249
+ const sizes = {
250
+ original_size_bytes: originalSize,
251
+ compressed_size_bytes: originalSize,
252
+ encrypted_size_bytes: originalSize,
253
+ encryption_enabled: encrypt,
254
+ compression_enabled: compress,
255
+ };
256
+ // Step 1: Compress FIRST (if enabled)
257
+ // Compression works best on unencrypted data due to patterns/redundancy
258
+ if (compress) {
259
+ console.log(`📦 Compressing ${data.length} bytes with gzip (level ${compressionLevel})...`);
260
+ const compressed = this.compressData(data, compressionLevel);
261
+ data = compressed;
262
+ sizes.compressed_size_bytes = data.length;
263
+ const compressionRatio = (1 - data.length / originalSize) * 100;
264
+ console.log(`Compressed: ${data.length} bytes (${compressionRatio.toFixed(1)}% reduction)`);
265
+ }
266
+ // Step 2: Encrypt SECOND (if enabled)
267
+ // Encrypt the compressed data for security
268
+ if (encrypt) {
269
+ if (!this.kmsKeyId) {
270
+ console.log('Warning: Encryption requested but KMS key not found. Skipping encryption.');
271
+ encrypt = false;
272
+ sizes.encryption_enabled = false;
273
+ }
274
+ else {
275
+ console.log(`🔒 Encrypting ${data.length} bytes with KMS key...`);
276
+ const encrypted = await this.encryptData(data);
277
+ data = encrypted;
278
+ sizes.encrypted_size_bytes = data.length;
279
+ console.log(`Encrypted: ${data.length} bytes`);
280
+ }
281
+ }
282
+ // Generate S3 key with consistent filename (no date, no randomness)
283
+ // This enables in-place updates - same dataset name = same S3 key = file overwrite
284
+ let fileName = 'data.ndjson';
285
+ if (compress) {
286
+ fileName += '.gz';
287
+ }
288
+ const s3Key = `datasets/${options.datasetName}/${fileName}`;
289
+ // Build S3 object tags for cost tracking
290
+ // Format: CustomerID=value&Component=storage&Purpose=dataset-storage&DatasetName=value
291
+ const tags = [
292
+ `CustomerID=${encodeURIComponent(this.customerId)}`,
293
+ `Component=${encodeURIComponent('storage')}`,
294
+ `Purpose=${encodeURIComponent('dataset-storage')}`,
295
+ `DatasetName=${encodeURIComponent(options.datasetName)}`,
296
+ ].join('&');
297
+ // Upload to S3
298
+ console.log(`📤 Uploading ${data.length} bytes to S3...`);
299
+ try {
300
+ const putCommand = new client_s3_1.PutObjectCommand({
301
+ Bucket: this.bucketName,
302
+ Key: s3Key,
303
+ Body: data, // Buffer is compatible with Body type
304
+ Tagging: tags,
305
+ });
306
+ await this.s3Client.send(putCommand);
307
+ console.log(`✅ Uploaded to s3://${this.bucketName}/${s3Key} (tagged: CustomerID=${this.customerId})`);
308
+ }
309
+ catch (error) {
310
+ throw new Error(`Failed to upload file: ${error}`);
311
+ }
312
+ // Register dataset in catalog via API
313
+ const payload = {
314
+ name: options.datasetName,
315
+ description: options.description || '',
316
+ producer_id: this.customerId,
317
+ category,
318
+ data_freshness: dataFreshness,
319
+ s3_key: s3Key,
320
+ size_bytes: sizes.compressed_size_bytes,
321
+ metadata: { ...(options.metadata || {}), ...sizes },
322
+ };
323
+ try {
324
+ const dataset = await this.makeApiRequest('POST', '/v1/datasets', payload);
325
+ return dataset;
326
+ }
327
+ catch (error) {
328
+ // Upload succeeded but registration failed - log warning
329
+ console.log(`⚠️ Warning: File uploaded but catalog registration failed: ${error}`);
330
+ return {
331
+ ...payload,
332
+ metadata: {
333
+ ...payload.metadata,
334
+ status: 'uploaded_unregistered',
335
+ error: String(error),
336
+ },
337
+ };
338
+ }
339
+ }
340
+ /**
341
+ * Lists all datasets uploaded by this producer.
342
+ * Returns metadata for all datasets owned by the current producer account.
343
+ */
344
+ async listMyDatasets() {
345
+ const response = await this.makeApiRequest('GET', `/v1/datasets?producer_id=${encodeURIComponent(this.customerId)}`);
346
+ return response.datasets;
347
+ }
348
+ /**
349
+ * Signs an HTTP request using AWS Signature Version 4.
350
+ * Used for authenticating API requests to Helix Connect Platform.
351
+ */
352
+ async signRequest(method, path, body, contentType = 'application/json') {
353
+ const url = new URL(this.apiEndpoint + path);
354
+ // Parse query parameters separately for proper SigV4 signing
355
+ const queryParams = {};
356
+ url.searchParams.forEach((value, key) => {
357
+ queryParams[key] = value;
358
+ });
359
+ const request = new protocol_http_1.HttpRequest({
360
+ method,
361
+ protocol: url.protocol,
362
+ hostname: url.hostname,
363
+ path: url.pathname, // Path without query string
364
+ query: Object.keys(queryParams).length > 0 ? queryParams : undefined, // Query params separately
365
+ headers: {
366
+ 'Content-Type': contentType,
367
+ host: url.hostname,
368
+ },
369
+ body,
370
+ });
371
+ const signer = new signature_v4_1.SignatureV4({
372
+ credentials: {
373
+ accessKeyId: this.awsAccessKeyId,
374
+ secretAccessKey: this.awsSecretAccessKey,
375
+ },
376
+ region: this.region,
377
+ service: 'execute-api',
378
+ sha256: sha256_js_1.Sha256,
379
+ });
380
+ const signedRequest = await signer.sign(request);
381
+ return signedRequest.headers;
382
+ }
383
+ /**
384
+ * Lists incoming subscription requests for this producer.
385
+ * Returns requests that match the specified status filter.
386
+ */
387
+ async listSubscriptionRequests(status = 'pending') {
388
+ const response = await this.makeApiRequest('GET', `/v1/producers/subscription-requests?status=${status}`);
389
+ return response.requests || response;
390
+ }
391
+ /**
392
+ * Approves a subscription request from a consumer.
393
+ * Creates the necessary resources (SQS queue, SNS subscription) for the consumer.
394
+ */
395
+ async approveSubscriptionRequest(requestId, notes) {
396
+ const formData = { action: 'approve' };
397
+ if (notes) {
398
+ formData.notes = notes;
399
+ }
400
+ const response = await this.makeFormApiRequest('POST', `/v1/subscription-requests/${requestId}`, formData);
401
+ return response;
402
+ }
403
+ /**
404
+ * Rejects a subscription request from a consumer.
405
+ */
406
+ async rejectSubscriptionRequest(requestId, reason) {
407
+ const formData = { action: 'reject' };
408
+ if (reason) {
409
+ formData.reason = reason;
410
+ }
411
+ const response = await this.makeFormApiRequest('POST', `/v1/subscription-requests/${requestId}`, formData);
412
+ return response;
413
+ }
414
+ /**
415
+ * Makes an authenticated API request with form-encoded data.
416
+ */
417
+ async makeFormApiRequest(method, path, formData) {
418
+ const body = formData ? new URLSearchParams(formData).toString() : undefined;
419
+ const headers = await this.signRequest(method, path, body, 'application/x-www-form-urlencoded');
420
+ const config = {
421
+ method,
422
+ url: this.apiEndpoint + path,
423
+ headers,
424
+ data: body,
425
+ timeout: 30000,
426
+ };
427
+ try {
428
+ const response = await (0, axios_1.default)(config);
429
+ return response.data;
430
+ }
431
+ catch (error) {
432
+ if (error.response) {
433
+ const status = error.response.status;
434
+ const message = error.response.data?.error || error.response.statusText;
435
+ if (status === 401) {
436
+ throw new Error(`Authentication failed: ${message}`);
437
+ }
438
+ else if (status === 403) {
439
+ throw new Error(`Permission denied: ${message}`);
440
+ }
441
+ else if (status === 404) {
442
+ throw new Error(`Resource not found: ${message}`);
443
+ }
444
+ else {
445
+ throw new Error(`API request failed: ${status} - ${message}`);
446
+ }
447
+ }
448
+ throw error;
449
+ }
450
+ }
451
+ /**
452
+ * Makes an authenticated API request to Helix Connect Platform.
453
+ * Handles request signing, error responses, and retries.
454
+ */
455
+ async makeApiRequest(method, path, data) {
456
+ const body = data ? JSON.stringify(data) : undefined;
457
+ const headers = await this.signRequest(method, path, body);
458
+ const config = {
459
+ method,
460
+ url: this.apiEndpoint + path,
461
+ headers,
462
+ data,
463
+ timeout: 30000, // 30 second timeout
464
+ };
465
+ try {
466
+ const response = await (0, axios_1.default)(config);
467
+ return response.data;
468
+ }
469
+ catch (error) {
470
+ if (error.response) {
471
+ const status = error.response.status;
472
+ const message = error.response.data?.error || error.response.statusText;
473
+ if (status === 401) {
474
+ throw new Error(`Authentication failed: ${message}`);
475
+ }
476
+ else if (status === 403) {
477
+ throw new Error(`Permission denied: ${message}`);
478
+ }
479
+ else if (status === 404) {
480
+ throw new Error(`Resource not found: ${message}`);
481
+ }
482
+ else {
483
+ throw new Error(`API request failed: ${status} - ${message}`);
484
+ }
485
+ }
486
+ throw error;
487
+ }
488
+ }
489
+ }
490
+ exports.HelixProducer = HelixProducer;
491
+ //# sourceMappingURL=producer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"producer.js","sourceRoot":"","sources":["../src/producer.ts"],"names":[],"mappings":"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"}