blaaiz-nodejs-sdk 1.0.2 → 1.0.3

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/index.d.ts CHANGED
@@ -216,9 +216,10 @@ export interface FileUploadData {
216
216
  }
217
217
 
218
218
  export interface PreSignedUrlResponse {
219
- url: string;
219
+ message: string;
220
220
  file_id: string;
221
- headers: { [key: string]: string };
221
+ url: string;
222
+ headers: any[];
222
223
  }
223
224
 
224
225
  // Webhook Types
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blaaiz-nodejs-sdk",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Official Node.js SDK for Blaaiz RaaS (Remittance as a Service) API",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -13,7 +13,7 @@
13
13
  "lint:fix": "eslint src/**/*.js --fix",
14
14
  "audit": "npm audit --audit-level=moderate",
15
15
  "docs": "jsdoc -d docs src/**/*.js",
16
- "build": "npm run lint && npm test",
16
+ "build": "npm run lint",
17
17
  "prepublishOnly": "npm run build"
18
18
  },
19
19
  "keywords": [
@@ -80,7 +80,23 @@ class CustomerService {
80
80
  file_category // eslint-disable-line camelcase
81
81
  })
82
82
 
83
- const { url: presignedUrl, file_id } = presignedResponse.data.data // eslint-disable-line camelcase
83
+ // Handle API response structure: {"data": {"message": "...", "file_id": "...", "url": "..."}}
84
+ let presignedUrl, file_id // eslint-disable-line camelcase
85
+ if (presignedResponse.data && presignedResponse.data.url && presignedResponse.data.file_id) {
86
+ // Structure: {"data": {"message": "...", "file_id": "...", "url": "..."}}
87
+ presignedUrl = presignedResponse.data.url
88
+ file_id = presignedResponse.data.file_id // eslint-disable-line camelcase
89
+ } else if (presignedResponse.url && presignedResponse.file_id) {
90
+ // Direct structure from API docs
91
+ presignedUrl = presignedResponse.url
92
+ file_id = presignedResponse.file_id // eslint-disable-line camelcase
93
+ } else if (presignedResponse.data && presignedResponse.data.data) {
94
+ // Nested structure: {"data": {"data": {"url": "...", "file_id": "..."}}}
95
+ presignedUrl = presignedResponse.data.data.url
96
+ file_id = presignedResponse.data.data.file_id // eslint-disable-line camelcase
97
+ } else {
98
+ throw new Error(`Invalid presigned URL response structure. Expected 'url' and 'file_id' keys. Got: ${JSON.stringify(presignedResponse)}`)
99
+ }
84
100
 
85
101
  let fileBuffer
86
102
  if (Buffer.isBuffer(file)) {
@@ -123,8 +139,20 @@ class CustomerService {
123
139
 
124
140
  await this._uploadToS3(presignedUrl, fileBuffer, contentType, filename)
125
141
 
126
- const fileAssociation = await this.client.makeRequest('PUT', `/api/external/customer/${customerId}/files`, {
127
- id_file: file_id // eslint-disable-line camelcase
142
+ // Map file category to the correct field name expected by Laravel API
143
+ const fileFieldMapping = {
144
+ identity: 'id_file',
145
+ liveness_check: 'liveness_check_file',
146
+ proof_of_address: 'proof_of_address_file'
147
+ }
148
+
149
+ const fileFieldName = fileFieldMapping[file_category] // eslint-disable-line camelcase
150
+ if (!fileFieldName) {
151
+ throw new Error(`Unknown file category: ${file_category}`) // eslint-disable-line camelcase
152
+ }
153
+
154
+ const fileAssociation = await this.client.makeRequest('POST', `/api/external/customer/${customerId}/files`, {
155
+ [fileFieldName]: file_id // eslint-disable-line camelcase
128
156
  })
129
157
 
130
158
  return {
@@ -133,7 +161,14 @@ class CustomerService {
133
161
  presigned_url: presignedUrl
134
162
  }
135
163
  } catch (error) {
136
- throw new Error(`File upload failed: ${error.message}`)
164
+ // Provide better error information for debugging
165
+ if (error.message && error.message.includes('File upload failed:')) {
166
+ // Re-throw if already wrapped
167
+ throw error
168
+ } else {
169
+ // Wrap other exceptions with context
170
+ throw new Error(`File upload failed: ${error.message}`)
171
+ }
137
172
  }
138
173
  }
139
174
 
@@ -173,9 +208,17 @@ class CustomerService {
173
208
 
174
209
  res.on('end', () => {
175
210
  if (res.statusCode >= 200 && res.statusCode < 300) {
211
+ // Verify S3 upload success by checking for ETag
212
+ const etag = res.headers.etag || res.headers.ETag
213
+ if (!etag) {
214
+ reject(new Error('S3 upload failed: No ETag received from S3'))
215
+ return
216
+ }
217
+
176
218
  resolve({
177
219
  status: res.statusCode,
178
- data: responseData
220
+ data: responseData,
221
+ etag
179
222
  })
180
223
  } else {
181
224
  reject(new Error(`S3 upload failed with status ${res.statusCode}: ${responseData}`))