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 +3 -2
- package/package.json +2 -2
- package/src/services/CustomerService.js +48 -5
package/index.d.ts
CHANGED
|
@@ -216,9 +216,10 @@ export interface FileUploadData {
|
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
export interface PreSignedUrlResponse {
|
|
219
|
-
|
|
219
|
+
message: string;
|
|
220
220
|
file_id: string;
|
|
221
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
127
|
-
|
|
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
|
-
|
|
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}`))
|