@easyflow/javascript-sdk 2.1.8 → 2.1.9
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/README.md +71 -7
- package/dist/index.d.ts +421 -0
- package/package.json +19 -6
- package/.babelrc +0 -5
- package/.github/workflows/deploy-sdk-cf.yml +0 -49
- package/.github/workflows/release-sdk-cdn.yml +0 -144
- package/.github/workflows/release-sdk.yml +0 -112
- package/.prettierrc +0 -6
- package/CDN-DEPLOYMENT.md +0 -175
- package/DEMO.md +0 -258
- package/DEPLOYMENT.md +0 -224
- package/INTEGRATION-GUIDE.md +0 -521
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/easyflow-javascript-sdk/index.html +0 -116
- package/coverage/easyflow-javascript-sdk/libs/constants.mjs.html +0 -268
- package/coverage/easyflow-javascript-sdk/libs/errors.mjs.html +0 -271
- package/coverage/easyflow-javascript-sdk/libs/exception-handler.mjs.html +0 -148
- package/coverage/easyflow-javascript-sdk/libs/fingerprint.mjs.html +0 -895
- package/coverage/easyflow-javascript-sdk/libs/http.mjs.html +0 -502
- package/coverage/easyflow-javascript-sdk/libs/index.html +0 -266
- package/coverage/easyflow-javascript-sdk/libs/logger.mjs.html +0 -568
- package/coverage/easyflow-javascript-sdk/libs/sanitizer.mjs.html +0 -1099
- package/coverage/easyflow-javascript-sdk/libs/security.mjs.html +0 -733
- package/coverage/easyflow-javascript-sdk/libs/types.mjs.html +0 -508
- package/coverage/easyflow-javascript-sdk/libs/utils.mjs.html +0 -379
- package/coverage/easyflow-javascript-sdk/libs/validator.mjs.html +0 -2623
- package/coverage/easyflow-javascript-sdk/sdk.mjs.html +0 -2434
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -131
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/easyflow-javascript-sdk/index.html +0 -116
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/constants.mjs.html +0 -268
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/errors.mjs.html +0 -271
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/exception-handler.mjs.html +0 -148
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/fingerprint.mjs.html +0 -895
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/http.mjs.html +0 -502
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/index.html +0 -266
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/logger.mjs.html +0 -568
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/sanitizer.mjs.html +0 -1099
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/security.mjs.html +0 -733
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/types.mjs.html +0 -508
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/utils.mjs.html +0 -379
- package/coverage/lcov-report/easyflow-javascript-sdk/libs/validator.mjs.html +0 -2623
- package/coverage/lcov-report/easyflow-javascript-sdk/sdk.mjs.html +0 -2434
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -131
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov.info +0 -1429
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -196
- package/dist/435.easyflow-sdk.min.js +0 -1
- package/dist/easyflow-sdk.min.js +0 -1
- package/dist/easyflow-sdk.min.js.LICENSE.txt +0 -1
- package/dist/index.html +0 -756
- package/docs/index.html +0 -775
- package/examples/lovable-integration.html +0 -410
- package/index.html +0 -981
- package/jest.config.js +0 -37
- package/jsdoc.json +0 -42
- package/libs/auto-integration.mjs +0 -333
- package/libs/constants.mjs +0 -61
- package/libs/constants.spec.js +0 -198
- package/libs/errors.mjs +0 -62
- package/libs/errors.spec.js +0 -178
- package/libs/exception-handler.mjs +0 -21
- package/libs/exception-handler.spec.js +0 -237
- package/libs/fingerprint.mjs +0 -270
- package/libs/http.mjs +0 -163
- package/libs/http.spec.js +0 -427
- package/libs/integration-wrapper.mjs +0 -285
- package/libs/logger.mjs +0 -161
- package/libs/logger.spec.js +0 -389
- package/libs/sanitizer.mjs +0 -340
- package/libs/sanitizer.spec.js +0 -583
- package/libs/security.mjs +0 -217
- package/libs/types.mjs +0 -141
- package/libs/utils.mjs +0 -368
- package/libs/utils.spec.js +0 -231
- package/libs/validator.mjs +0 -952
- package/libs/validator.spec.js +0 -615
- package/mocks/offer.mock.js +0 -77
- package/scripts/publish-npm.sh +0 -82
- package/sdk.mjs +0 -945
- package/sdk.spec.js +0 -796
- package/test-setup.cjs +0 -211
- package/test.html +0 -154
- package/webpack.config.cjs +0 -41
package/libs/utils.mjs
DELETED
|
@@ -1,368 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utility functions for Easyflow SDK
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { PAYMENT_METHODS } from '../sdk.mjs'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Deep clone an object using JSON serialization
|
|
9
|
-
* @param {*} data - Data to clone
|
|
10
|
-
* @returns {*} Cloned data
|
|
11
|
-
*/
|
|
12
|
-
export function deepClone(data) {
|
|
13
|
-
return JSON.parse(JSON.stringify(data))
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Prepare order data by mapping payments
|
|
18
|
-
* @param {Object} data - Order data
|
|
19
|
-
* @returns {Object} Prepared order data
|
|
20
|
-
*/
|
|
21
|
-
export function mapCreditCardIfNeeded(data) {
|
|
22
|
-
const clonedData = deepClone(data)
|
|
23
|
-
clonedData.payments = clonedData.payments.map((payment) => {
|
|
24
|
-
if (payment.method === PAYMENT_METHODS.CREDIT_CARD) {
|
|
25
|
-
return {
|
|
26
|
-
...payment,
|
|
27
|
-
rawCreditCard: payment.creditCard,
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return payment
|
|
31
|
-
})
|
|
32
|
-
return clonedData
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Find payment by method in order data
|
|
37
|
-
* @param {Object} order - Order data
|
|
38
|
-
* @param {string} method - Payment method to find
|
|
39
|
-
* @param {Function} validator - Validation function for the payment data
|
|
40
|
-
* @returns {Object|null} Payment data or null if not found
|
|
41
|
-
*/
|
|
42
|
-
export function findPaymentByMethod(order, method, validator) {
|
|
43
|
-
if (!order?.payments?.length) {
|
|
44
|
-
return null
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const payment = order.payments.find(
|
|
48
|
-
(payment) => payment.method === method && validator(payment)
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
return payment || null
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Validate PIX payment data
|
|
56
|
-
* @param {Object} payment - Payment object
|
|
57
|
-
* @returns {boolean} True if valid PIX payment
|
|
58
|
-
*/
|
|
59
|
-
export function isValidPixPayment(payment) {
|
|
60
|
-
return payment.pix && (payment.pix.qrCode || payment.pix.copyAndPasteCode)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Validate bank billet payment data
|
|
65
|
-
* @param {Object} payment - Payment object
|
|
66
|
-
* @returns {boolean} True if valid bank billet payment
|
|
67
|
-
*/
|
|
68
|
-
export function isValidBankBilletPayment(payment) {
|
|
69
|
-
return (
|
|
70
|
-
payment.bankBillet &&
|
|
71
|
-
(payment.bankBillet.link ||
|
|
72
|
-
payment.bankBillet.line ||
|
|
73
|
-
payment.bankBillet.barCode)
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Merge headers with default headers
|
|
79
|
-
* @param {Object} defaultHeaders - Default headers
|
|
80
|
-
* @param {Object} additionalHeaders - Additional headers
|
|
81
|
-
* @returns {Object} Merged headers
|
|
82
|
-
*/
|
|
83
|
-
export function mergeHeaders(defaultHeaders = {}, additionalHeaders = {}) {
|
|
84
|
-
return { ...defaultHeaders, ...additionalHeaders }
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Build API URL with target and parameters
|
|
89
|
-
* @param {string} baseUrl - Base URL
|
|
90
|
-
* @param {string} target - API target
|
|
91
|
-
* @param {Object} params - URL parameters
|
|
92
|
-
* @returns {string} Complete API URL
|
|
93
|
-
*/
|
|
94
|
-
export function buildApiUrl(baseUrl, target, params = {}) {
|
|
95
|
-
const url = new URL(`/api/proxy?target=${target}`, baseUrl).toString()
|
|
96
|
-
const queryParams = new URLSearchParams(params).toString()
|
|
97
|
-
return queryParams ? `${url}&${queryParams}` : url
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Generate browser fingerprint for security and tracking
|
|
102
|
-
* @param {Object} options - Fingerprint options
|
|
103
|
-
* @param {boolean} options.hardwareOnly - Only use hardware-based data
|
|
104
|
-
* @param {boolean} options.enableWebgl - Enable WebGL fingerprinting
|
|
105
|
-
* @param {boolean} options.debug - Enable debug logging
|
|
106
|
-
* @returns {string} Fingerprint hash
|
|
107
|
-
*/
|
|
108
|
-
export function getBrowserFingerprint({ hardwareOnly = false, enableWebgl = false, debug = false } = {}) {
|
|
109
|
-
const {
|
|
110
|
-
cookieEnabled,
|
|
111
|
-
deviceMemory,
|
|
112
|
-
doNotTrack,
|
|
113
|
-
hardwareConcurrency,
|
|
114
|
-
language,
|
|
115
|
-
languages,
|
|
116
|
-
maxTouchPoints,
|
|
117
|
-
platform,
|
|
118
|
-
userAgent,
|
|
119
|
-
vendor
|
|
120
|
-
} = window.navigator
|
|
121
|
-
|
|
122
|
-
let { width, height, colorDepth, pixelDepth } = window.screen
|
|
123
|
-
width = 1000
|
|
124
|
-
height = 1000
|
|
125
|
-
|
|
126
|
-
const timezoneOffset = (new Date()).getTimezoneOffset()
|
|
127
|
-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
128
|
-
const touchSupport = 'ontouchstart' in window
|
|
129
|
-
const devicePixelRatio = window.devicePixelRatio
|
|
130
|
-
const canvas = getCanvasID(debug)
|
|
131
|
-
const webgl = enableWebgl ? getWebglID(debug) : undefined
|
|
132
|
-
const webglInfo = enableWebgl ? getWebglInfo(debug) : undefined
|
|
133
|
-
|
|
134
|
-
const fingerprintData = hardwareOnly
|
|
135
|
-
? JSON.stringify({
|
|
136
|
-
canvas,
|
|
137
|
-
colorDepth,
|
|
138
|
-
deviceMemory,
|
|
139
|
-
devicePixelRatio,
|
|
140
|
-
hardwareConcurrency,
|
|
141
|
-
height,
|
|
142
|
-
maxTouchPoints,
|
|
143
|
-
pixelDepth,
|
|
144
|
-
platform,
|
|
145
|
-
touchSupport,
|
|
146
|
-
webgl,
|
|
147
|
-
webglInfo,
|
|
148
|
-
width
|
|
149
|
-
})
|
|
150
|
-
: JSON.stringify({
|
|
151
|
-
canvas,
|
|
152
|
-
colorDepth,
|
|
153
|
-
cookieEnabled,
|
|
154
|
-
deviceMemory,
|
|
155
|
-
devicePixelRatio,
|
|
156
|
-
doNotTrack,
|
|
157
|
-
hardwareConcurrency,
|
|
158
|
-
height,
|
|
159
|
-
language,
|
|
160
|
-
languages,
|
|
161
|
-
maxTouchPoints,
|
|
162
|
-
pixelDepth,
|
|
163
|
-
platform,
|
|
164
|
-
timezone,
|
|
165
|
-
timezoneOffset,
|
|
166
|
-
touchSupport,
|
|
167
|
-
userAgent,
|
|
168
|
-
vendor,
|
|
169
|
-
webgl,
|
|
170
|
-
webglInfo,
|
|
171
|
-
width
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
const fingerprintJson = JSON.stringify(fingerprintData, null, 4)
|
|
175
|
-
|
|
176
|
-
if (debug) {
|
|
177
|
-
console.log('fingerprint data', fingerprintJson)
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return murmurhash3_32_gc(fingerprintJson)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Generate canvas fingerprint ID
|
|
185
|
-
* @param {boolean} debug - Enable debug mode
|
|
186
|
-
* @returns {string|null} Canvas fingerprint hash
|
|
187
|
-
*/
|
|
188
|
-
function getCanvasID(debug = false) {
|
|
189
|
-
try {
|
|
190
|
-
const canvas = document.createElement('canvas')
|
|
191
|
-
const ctx = canvas.getContext('2d')
|
|
192
|
-
const text = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`~1!2@3#4$5%6^7&8*9(0)-_=+[{]}|;:\',<.>/?'
|
|
193
|
-
|
|
194
|
-
ctx.textBaseline = 'top'
|
|
195
|
-
ctx.font = '14px \'Arial\''
|
|
196
|
-
ctx.textBaseline = 'alphabetic'
|
|
197
|
-
ctx.fillStyle = '#f60'
|
|
198
|
-
ctx.fillRect(125, 1, 62, 20)
|
|
199
|
-
ctx.fillStyle = '#069'
|
|
200
|
-
ctx.fillText(text, 2, 15)
|
|
201
|
-
ctx.fillStyle = 'rgba(102, 204, 0, 0.7)'
|
|
202
|
-
ctx.fillText(text, 4, 17)
|
|
203
|
-
|
|
204
|
-
const dataURL = canvas.toDataURL()
|
|
205
|
-
|
|
206
|
-
if (debug) {
|
|
207
|
-
document.body.appendChild(canvas)
|
|
208
|
-
} else {
|
|
209
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return murmurhash3_32_gc(dataURL)
|
|
213
|
-
} catch {
|
|
214
|
-
return null
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Generate WebGL fingerprint ID
|
|
220
|
-
* @param {boolean} debug - Enable debug mode
|
|
221
|
-
* @returns {string|null} WebGL fingerprint hash
|
|
222
|
-
*/
|
|
223
|
-
function getWebglID(debug = false) {
|
|
224
|
-
try {
|
|
225
|
-
const canvas = document.createElement('canvas')
|
|
226
|
-
const gl = canvas.getContext('webgl')
|
|
227
|
-
|
|
228
|
-
canvas.width = 256
|
|
229
|
-
canvas.height = 128
|
|
230
|
-
|
|
231
|
-
const vertexShaderSource = `
|
|
232
|
-
attribute vec2 attrVertex;
|
|
233
|
-
varying vec2 varyinTexCoordinate;
|
|
234
|
-
uniform vec2 uniformOffset;
|
|
235
|
-
void main() {
|
|
236
|
-
varyinTexCoordinate = attrVertex + uniformOffset;
|
|
237
|
-
gl_Position = vec4(attrVertex, 0, 1);
|
|
238
|
-
}
|
|
239
|
-
`
|
|
240
|
-
|
|
241
|
-
const fragmentShaderSource = `
|
|
242
|
-
precision mediump float;
|
|
243
|
-
varying vec2 varyinTexCoordinate;
|
|
244
|
-
void main() {
|
|
245
|
-
gl_FragColor = vec4(varyinTexCoordinate, 0, 1);
|
|
246
|
-
}
|
|
247
|
-
`
|
|
248
|
-
|
|
249
|
-
const buffer = gl.createBuffer()
|
|
250
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
|
|
251
|
-
|
|
252
|
-
const vertices = new Float32Array([-0.2, -0.9, 0, 0.4, -0.26, 0, 0, 0.7321, 0])
|
|
253
|
-
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
|
|
254
|
-
buffer.itemSize = 3
|
|
255
|
-
buffer.numItems = 3
|
|
256
|
-
|
|
257
|
-
const program = gl.createProgram()
|
|
258
|
-
const vertexShader = gl.createShader(gl.VERTEX_SHADER)
|
|
259
|
-
gl.shaderSource(vertexShader, vertexShaderSource)
|
|
260
|
-
gl.compileShader(vertexShader)
|
|
261
|
-
|
|
262
|
-
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
|
|
263
|
-
gl.shaderSource(fragmentShader, fragmentShaderSource)
|
|
264
|
-
gl.compileShader(fragmentShader)
|
|
265
|
-
|
|
266
|
-
gl.attachShader(program, vertexShader)
|
|
267
|
-
gl.attachShader(program, fragmentShader)
|
|
268
|
-
gl.linkProgram(program)
|
|
269
|
-
gl.useProgram(program)
|
|
270
|
-
|
|
271
|
-
program.vertexPosAttrib = gl.getAttribLocation(program, 'attrVertex')
|
|
272
|
-
program.offsetUniform = gl.getUniformLocation(program, 'uniformOffset')
|
|
273
|
-
|
|
274
|
-
gl.enableVertexAttribArray(program.vertexPosAttrib)
|
|
275
|
-
gl.vertexAttribPointer(program.vertexPosAttrib, buffer.itemSize, gl.FLOAT, false, 0, 0)
|
|
276
|
-
gl.uniform2f(program.offsetUniform, 1, 1)
|
|
277
|
-
gl.drawArrays(gl.TRIANGLE_STRIP, 0, buffer.numItems)
|
|
278
|
-
|
|
279
|
-
const pixels = new Uint8Array(canvas.width * canvas.height * 4)
|
|
280
|
-
gl.readPixels(0, 0, canvas.width, canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels)
|
|
281
|
-
|
|
282
|
-
const pixelsString = JSON.stringify(pixels).replace(/,?"[0-9]+":/g, '')
|
|
283
|
-
|
|
284
|
-
if (debug) {
|
|
285
|
-
document.body.appendChild(canvas)
|
|
286
|
-
} else {
|
|
287
|
-
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
return murmurhash3_32_gc(pixelsString)
|
|
291
|
-
} catch {
|
|
292
|
-
return null
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Get WebGL information
|
|
298
|
-
* @param {boolean} debug - Enable debug mode
|
|
299
|
-
* @returns {Object|null} WebGL information
|
|
300
|
-
*/
|
|
301
|
-
function getWebglInfo(debug = false) {
|
|
302
|
-
try {
|
|
303
|
-
const canvas = document.createElement('canvas')
|
|
304
|
-
const gl = canvas.getContext('webgl')
|
|
305
|
-
|
|
306
|
-
return {
|
|
307
|
-
VERSION: gl.getParameter(gl.VERSION),
|
|
308
|
-
SHADING_LANGUAGE_VERSION: gl.getParameter(gl.SHADING_LANGUAGE_VERSION),
|
|
309
|
-
VENDOR: gl.getParameter(gl.VENDOR),
|
|
310
|
-
SUPORTED_EXTENSIONS: gl.getSupportedExtensions()
|
|
311
|
-
}
|
|
312
|
-
} catch {
|
|
313
|
-
return null
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* MurmurHash3 implementation for fingerprint generation
|
|
319
|
-
* @param {string} str - String to hash
|
|
320
|
-
* @returns {string} Hash result
|
|
321
|
-
*/
|
|
322
|
-
function murmurhash3_32_gc(str) {
|
|
323
|
-
const c1 = 0xcc9e2d51
|
|
324
|
-
const c2 = 0x1b873593
|
|
325
|
-
const r1 = 15
|
|
326
|
-
const r2 = 13
|
|
327
|
-
const m = 5
|
|
328
|
-
const n = 0xe6546b64
|
|
329
|
-
|
|
330
|
-
let h = 0xdeadbeef
|
|
331
|
-
let k
|
|
332
|
-
|
|
333
|
-
for (let i = 0; i < str.length; i += 4) {
|
|
334
|
-
k = str.charCodeAt(i) |
|
|
335
|
-
(str.charCodeAt(i + 1) << 8) |
|
|
336
|
-
(str.charCodeAt(i + 2) << 16) |
|
|
337
|
-
(str.charCodeAt(i + 3) << 24)
|
|
338
|
-
|
|
339
|
-
k = Math.imul(k, c1)
|
|
340
|
-
k = (k << r1) | (k >>> (32 - r1))
|
|
341
|
-
k = Math.imul(k, c2)
|
|
342
|
-
|
|
343
|
-
h ^= k
|
|
344
|
-
h = (h << r2) | (h >>> (32 - r2))
|
|
345
|
-
h = Math.imul(h, m) + n
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
const remaining = str.length % 4
|
|
349
|
-
if (remaining > 0) {
|
|
350
|
-
let k = 0
|
|
351
|
-
for (let i = str.length - remaining; i < str.length; i++) {
|
|
352
|
-
k |= str.charCodeAt(i) << ((i - (str.length - remaining)) * 8)
|
|
353
|
-
}
|
|
354
|
-
k = Math.imul(k, c1)
|
|
355
|
-
k = (k << r1) | (k >>> (32 - r1))
|
|
356
|
-
k = Math.imul(k, c2)
|
|
357
|
-
h ^= k
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
h ^= str.length
|
|
361
|
-
h ^= h >>> 16
|
|
362
|
-
h = Math.imul(h, 0x85ebca6b)
|
|
363
|
-
h ^= h >>> 13
|
|
364
|
-
h = Math.imul(h, 0xc2b2ae35)
|
|
365
|
-
h ^= h >>> 16
|
|
366
|
-
|
|
367
|
-
return (h >>> 0).toString(16)
|
|
368
|
-
}
|
package/libs/utils.spec.js
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
import { jest, describe, it, expect, beforeEach } from '@jest/globals'
|
|
2
|
-
|
|
3
|
-
// Mock PAYMENT_METHODS para evitar import do SDK completo
|
|
4
|
-
await jest.unstable_mockModule('../sdk.mjs', () => ({
|
|
5
|
-
PAYMENT_METHODS: {
|
|
6
|
-
CREDIT_CARD: 'credit-card',
|
|
7
|
-
PIX: 'pix',
|
|
8
|
-
BANK_BILLET: 'bank-billet',
|
|
9
|
-
},
|
|
10
|
-
}))
|
|
11
|
-
|
|
12
|
-
const {
|
|
13
|
-
deepClone,
|
|
14
|
-
mapCreditCardIfNeeded,
|
|
15
|
-
findPaymentByMethod,
|
|
16
|
-
isValidPixPayment,
|
|
17
|
-
isValidBankBilletPayment,
|
|
18
|
-
mergeHeaders,
|
|
19
|
-
buildApiUrl,
|
|
20
|
-
} = await import('./utils.mjs')
|
|
21
|
-
|
|
22
|
-
describe('Utils', () => {
|
|
23
|
-
describe('deepClone', () => {
|
|
24
|
-
it('should clone simple object', () => {
|
|
25
|
-
const obj = { a: 1, b: 'x' }
|
|
26
|
-
const cloned = deepClone(obj)
|
|
27
|
-
expect(cloned).toEqual(obj)
|
|
28
|
-
expect(cloned).not.toBe(obj)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it('should clone nested object', () => {
|
|
32
|
-
const obj = { a: { b: { c: 1 } } }
|
|
33
|
-
const cloned = deepClone(obj)
|
|
34
|
-
expect(cloned).toEqual(obj)
|
|
35
|
-
expect(cloned.a).not.toBe(obj.a)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('should clone array', () => {
|
|
39
|
-
const arr = [1, { a: 2 }, [3]]
|
|
40
|
-
const cloned = deepClone(arr)
|
|
41
|
-
expect(cloned).toEqual(arr)
|
|
42
|
-
expect(cloned).not.toBe(arr)
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('should handle primitive values', () => {
|
|
46
|
-
expect(deepClone(1)).toBe(1)
|
|
47
|
-
expect(deepClone('x')).toBe('x')
|
|
48
|
-
expect(deepClone(true)).toBe(true)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('should handle empty objects and arrays', () => {
|
|
52
|
-
expect(deepClone({})).toEqual({})
|
|
53
|
-
expect(deepClone([])).toEqual([])
|
|
54
|
-
})
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
describe('mapCreditCardIfNeeded', () => {
|
|
58
|
-
it('should map credit card payment correctly', () => {
|
|
59
|
-
const data = {
|
|
60
|
-
payments: [
|
|
61
|
-
{ method: 'credit-card', creditCard: { token: 't', n: 1 } },
|
|
62
|
-
],
|
|
63
|
-
}
|
|
64
|
-
const result = mapCreditCardIfNeeded(data)
|
|
65
|
-
expect(result).not.toBe(data)
|
|
66
|
-
expect(result.payments[0].rawCreditCard).toEqual({
|
|
67
|
-
token: 't',
|
|
68
|
-
n: 1,
|
|
69
|
-
})
|
|
70
|
-
// não deve remover creditCard original
|
|
71
|
-
expect(result.payments[0].creditCard).toEqual({ token: 't', n: 1 })
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
it('should not modify non-credit-card payments', () => {
|
|
75
|
-
const data = {
|
|
76
|
-
payments: [{ method: 'pix' }, { method: 'bank-billet' }],
|
|
77
|
-
}
|
|
78
|
-
const result = mapCreditCardIfNeeded(data)
|
|
79
|
-
expect(result.payments).toEqual(data.payments)
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
it('should handle mixed payment methods', () => {
|
|
83
|
-
const data = {
|
|
84
|
-
payments: [
|
|
85
|
-
{ method: 'pix' },
|
|
86
|
-
{ method: 'credit-card', creditCard: { token: 'abc' } },
|
|
87
|
-
],
|
|
88
|
-
}
|
|
89
|
-
const result = mapCreditCardIfNeeded(data)
|
|
90
|
-
expect(result.payments[1].rawCreditCard).toEqual({ token: 'abc' })
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
it('should return deep clone of original data', () => {
|
|
94
|
-
const data = {
|
|
95
|
-
payments: [{ method: 'credit-card', creditCard: { t: 'x' } }],
|
|
96
|
-
}
|
|
97
|
-
const result = mapCreditCardIfNeeded(data)
|
|
98
|
-
expect(result).toEqual({
|
|
99
|
-
payments: [
|
|
100
|
-
{
|
|
101
|
-
method: 'credit-card',
|
|
102
|
-
creditCard: { t: 'x' },
|
|
103
|
-
rawCreditCard: { t: 'x' },
|
|
104
|
-
},
|
|
105
|
-
],
|
|
106
|
-
})
|
|
107
|
-
expect(result).not.toBe(data)
|
|
108
|
-
})
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
describe('findPaymentByMethod', () => {
|
|
112
|
-
it('should find payment by method when validator returns true', () => {
|
|
113
|
-
const order = {
|
|
114
|
-
payments: [{ method: 'pix', pix: { qrCode: 'q' } }],
|
|
115
|
-
}
|
|
116
|
-
const validator = (p) => !!p.pix?.qrCode
|
|
117
|
-
const found = findPaymentByMethod(order, 'pix', validator)
|
|
118
|
-
expect(found).toEqual(order.payments[0])
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
it('should return null when validator returns false', () => {
|
|
122
|
-
const order = { payments: [{ method: 'pix', pix: {} }] }
|
|
123
|
-
const validator = (p) => !!p.pix?.qrCode
|
|
124
|
-
expect(findPaymentByMethod(order, 'pix', validator)).toBeNull()
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
it('should return null when payment method not found', () => {
|
|
128
|
-
expect(
|
|
129
|
-
findPaymentByMethod({ payments: [] }, 'pix', () => true)
|
|
130
|
-
).toBeNull()
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
it('should return null when order has no payments', () => {
|
|
134
|
-
expect(findPaymentByMethod({}, 'pix', () => true)).toBeNull()
|
|
135
|
-
expect(findPaymentByMethod(null, 'pix', () => true)).toBeNull()
|
|
136
|
-
})
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
describe('isValidPixPayment', () => {
|
|
140
|
-
it('should return true for valid PIX payment with qrCode', () => {
|
|
141
|
-
expect(!!isValidPixPayment({ pix: { qrCode: 'x' } })).toBe(true)
|
|
142
|
-
})
|
|
143
|
-
it('should return true for valid PIX payment with copyAndPasteCode', () => {
|
|
144
|
-
expect(
|
|
145
|
-
!!isValidPixPayment({ pix: { copyAndPasteCode: 'y' } })
|
|
146
|
-
).toBe(true)
|
|
147
|
-
})
|
|
148
|
-
it('should return false for invalid pix object', () => {
|
|
149
|
-
expect(!!isValidPixPayment({})).toBe(false)
|
|
150
|
-
expect(!!isValidPixPayment({ pix: {} })).toBe(false)
|
|
151
|
-
expect(!!isValidPixPayment({ pix: null })).toBe(false)
|
|
152
|
-
})
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
describe('isValidBankBilletPayment', () => {
|
|
156
|
-
it('should return true for valid bank billet with link', () => {
|
|
157
|
-
expect(
|
|
158
|
-
!!isValidBankBilletPayment({ bankBillet: { link: 'l' } })
|
|
159
|
-
).toBe(true)
|
|
160
|
-
})
|
|
161
|
-
it('should return true for valid bank billet with line', () => {
|
|
162
|
-
expect(
|
|
163
|
-
!!isValidBankBilletPayment({ bankBillet: { line: 'ln' } })
|
|
164
|
-
).toBe(true)
|
|
165
|
-
})
|
|
166
|
-
it('should return true for valid bank billet with barCode', () => {
|
|
167
|
-
expect(
|
|
168
|
-
!!isValidBankBilletPayment({ bankBillet: { barCode: 'bc' } })
|
|
169
|
-
).toBe(true)
|
|
170
|
-
})
|
|
171
|
-
it('should return false for invalid bank billet object', () => {
|
|
172
|
-
expect(!!isValidBankBilletPayment({})).toBe(false)
|
|
173
|
-
expect(!!isValidBankBilletPayment({ bankBillet: {} })).toBe(false)
|
|
174
|
-
expect(!!isValidBankBilletPayment({ bankBillet: null })).toBe(false)
|
|
175
|
-
})
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
describe('mergeHeaders', () => {
|
|
179
|
-
it('should merge headers correctly and override defaults', () => {
|
|
180
|
-
const defaults = { A: '1', B: '2' }
|
|
181
|
-
const add = { B: '3', C: '4' }
|
|
182
|
-
expect(mergeHeaders(defaults, add)).toEqual({
|
|
183
|
-
A: '1',
|
|
184
|
-
B: '3',
|
|
185
|
-
C: '4',
|
|
186
|
-
})
|
|
187
|
-
})
|
|
188
|
-
|
|
189
|
-
it('should handle empty and undefined headers', () => {
|
|
190
|
-
expect(mergeHeaders({}, {})).toEqual({})
|
|
191
|
-
expect(mergeHeaders(undefined, { A: '1' })).toEqual({ A: '1' })
|
|
192
|
-
expect(mergeHeaders({ A: '1' }, undefined)).toEqual({ A: '1' })
|
|
193
|
-
})
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
describe('buildApiUrl', () => {
|
|
197
|
-
const baseUrl = 'https://api.example.com'
|
|
198
|
-
|
|
199
|
-
it('should build URL with target only', () => {
|
|
200
|
-
const url = buildApiUrl(baseUrl, 'get-offer')
|
|
201
|
-
// accept with or without origin
|
|
202
|
-
expect(url).toMatch(
|
|
203
|
-
/(https:\/\/api\.example\.com)?\/api\/proxy\?target=get-offer/
|
|
204
|
-
)
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
it('should build URL with target and parameters', () => {
|
|
208
|
-
const url = buildApiUrl(baseUrl, 'get-order', { orderId: '123' })
|
|
209
|
-
expect(url).toMatch(
|
|
210
|
-
/(https:\/\/api\.example\.com)?\/api\/proxy\?target=get-order&orderId=123/
|
|
211
|
-
)
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
it('should handle empty and undefined params', () => {
|
|
215
|
-
expect(buildApiUrl(baseUrl, 'x', {})).toMatch(
|
|
216
|
-
/(https:\/\/api\.example\.com)?\/api\/proxy\?target=x/
|
|
217
|
-
)
|
|
218
|
-
expect(buildApiUrl(baseUrl, 'y')).toMatch(
|
|
219
|
-
/(https:\/\/api\.example\.com)?\/api\/proxy\?target=y/
|
|
220
|
-
)
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
it('should encode URL parameters correctly', () => {
|
|
224
|
-
const url = buildApiUrl(baseUrl, 'search', { q: 'a b+c' })
|
|
225
|
-
// allow + or %20 for space encoding
|
|
226
|
-
expect(url).toMatch(
|
|
227
|
-
/(https:\/\/api\.example\.com)?\/api\/proxy\?target=search&q=a(\+|%20)b%2Bc/
|
|
228
|
-
)
|
|
229
|
-
})
|
|
230
|
-
})
|
|
231
|
-
})
|