@easyflow/javascript-sdk 2.1.7

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.
Files changed (93) hide show
  1. package/.babelrc +5 -0
  2. package/.github/workflows/deploy-sdk-cf.yml +49 -0
  3. package/.github/workflows/release-sdk-cdn.yml +144 -0
  4. package/.github/workflows/release-sdk.yml +112 -0
  5. package/.prettierrc +6 -0
  6. package/CDN-DEPLOYMENT.md +175 -0
  7. package/DEMO.md +258 -0
  8. package/DEPLOYMENT.md +224 -0
  9. package/INTEGRATION-GUIDE.md +521 -0
  10. package/README.md +1013 -0
  11. package/coverage/base.css +224 -0
  12. package/coverage/block-navigation.js +87 -0
  13. package/coverage/easyflow-javascript-sdk/index.html +116 -0
  14. package/coverage/easyflow-javascript-sdk/libs/constants.mjs.html +268 -0
  15. package/coverage/easyflow-javascript-sdk/libs/errors.mjs.html +271 -0
  16. package/coverage/easyflow-javascript-sdk/libs/exception-handler.mjs.html +148 -0
  17. package/coverage/easyflow-javascript-sdk/libs/fingerprint.mjs.html +895 -0
  18. package/coverage/easyflow-javascript-sdk/libs/http.mjs.html +502 -0
  19. package/coverage/easyflow-javascript-sdk/libs/index.html +266 -0
  20. package/coverage/easyflow-javascript-sdk/libs/logger.mjs.html +568 -0
  21. package/coverage/easyflow-javascript-sdk/libs/sanitizer.mjs.html +1099 -0
  22. package/coverage/easyflow-javascript-sdk/libs/security.mjs.html +733 -0
  23. package/coverage/easyflow-javascript-sdk/libs/types.mjs.html +508 -0
  24. package/coverage/easyflow-javascript-sdk/libs/utils.mjs.html +379 -0
  25. package/coverage/easyflow-javascript-sdk/libs/validator.mjs.html +2623 -0
  26. package/coverage/easyflow-javascript-sdk/sdk.mjs.html +2434 -0
  27. package/coverage/favicon.png +0 -0
  28. package/coverage/index.html +131 -0
  29. package/coverage/lcov-report/base.css +224 -0
  30. package/coverage/lcov-report/block-navigation.js +87 -0
  31. package/coverage/lcov-report/easyflow-javascript-sdk/index.html +116 -0
  32. package/coverage/lcov-report/easyflow-javascript-sdk/libs/constants.mjs.html +268 -0
  33. package/coverage/lcov-report/easyflow-javascript-sdk/libs/errors.mjs.html +271 -0
  34. package/coverage/lcov-report/easyflow-javascript-sdk/libs/exception-handler.mjs.html +148 -0
  35. package/coverage/lcov-report/easyflow-javascript-sdk/libs/fingerprint.mjs.html +895 -0
  36. package/coverage/lcov-report/easyflow-javascript-sdk/libs/http.mjs.html +502 -0
  37. package/coverage/lcov-report/easyflow-javascript-sdk/libs/index.html +266 -0
  38. package/coverage/lcov-report/easyflow-javascript-sdk/libs/logger.mjs.html +568 -0
  39. package/coverage/lcov-report/easyflow-javascript-sdk/libs/sanitizer.mjs.html +1099 -0
  40. package/coverage/lcov-report/easyflow-javascript-sdk/libs/security.mjs.html +733 -0
  41. package/coverage/lcov-report/easyflow-javascript-sdk/libs/types.mjs.html +508 -0
  42. package/coverage/lcov-report/easyflow-javascript-sdk/libs/utils.mjs.html +379 -0
  43. package/coverage/lcov-report/easyflow-javascript-sdk/libs/validator.mjs.html +2623 -0
  44. package/coverage/lcov-report/easyflow-javascript-sdk/sdk.mjs.html +2434 -0
  45. package/coverage/lcov-report/favicon.png +0 -0
  46. package/coverage/lcov-report/index.html +131 -0
  47. package/coverage/lcov-report/prettify.css +1 -0
  48. package/coverage/lcov-report/prettify.js +2 -0
  49. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  50. package/coverage/lcov-report/sorter.js +196 -0
  51. package/coverage/lcov.info +1429 -0
  52. package/coverage/prettify.css +1 -0
  53. package/coverage/prettify.js +2 -0
  54. package/coverage/sort-arrow-sprite.png +0 -0
  55. package/coverage/sorter.js +196 -0
  56. package/dist/435.easyflow-sdk.min.js +1 -0
  57. package/dist/easyflow-sdk.min.js +1 -0
  58. package/dist/easyflow-sdk.min.js.LICENSE.txt +1 -0
  59. package/dist/index.html +756 -0
  60. package/docs/index.html +775 -0
  61. package/examples/lovable-integration.html +410 -0
  62. package/index.html +981 -0
  63. package/jest.config.js +37 -0
  64. package/jsdoc.json +42 -0
  65. package/libs/auto-integration.mjs +333 -0
  66. package/libs/constants.mjs +61 -0
  67. package/libs/constants.spec.js +198 -0
  68. package/libs/errors.mjs +62 -0
  69. package/libs/errors.spec.js +178 -0
  70. package/libs/exception-handler.mjs +21 -0
  71. package/libs/exception-handler.spec.js +237 -0
  72. package/libs/fingerprint.mjs +270 -0
  73. package/libs/http.mjs +163 -0
  74. package/libs/http.spec.js +427 -0
  75. package/libs/integration-wrapper.mjs +285 -0
  76. package/libs/logger.mjs +161 -0
  77. package/libs/logger.spec.js +389 -0
  78. package/libs/sanitizer.mjs +340 -0
  79. package/libs/sanitizer.spec.js +583 -0
  80. package/libs/security.mjs +217 -0
  81. package/libs/types.mjs +141 -0
  82. package/libs/utils.mjs +368 -0
  83. package/libs/utils.spec.js +231 -0
  84. package/libs/validator.mjs +952 -0
  85. package/libs/validator.spec.js +615 -0
  86. package/mocks/offer.mock.js +77 -0
  87. package/package.json +72 -0
  88. package/scripts/publish-npm.sh +82 -0
  89. package/sdk.mjs +945 -0
  90. package/sdk.spec.js +796 -0
  91. package/test-setup.cjs +211 -0
  92. package/test.html +154 -0
  93. package/webpack.config.cjs +41 -0
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Módulo de Segurança do Easyflow SDK
3
+ * Implementa todas as proteções de segurança necessárias para distribuição via CDN
4
+ */
5
+ import { throwsError } from './exception-handler.mjs'
6
+ import { NetworkError, SecurityError } from './errors.mjs'
7
+ import { Validator } from './validator.mjs'
8
+ import { Sanitizer } from './sanitizer.mjs'
9
+ import { mergeHeaders } from './utils.mjs'
10
+ import { makeFingerprint } from './fingerprint.mjs'
11
+
12
+ // Configurações de segurança
13
+ // Buscar configurações de um arquivo de configuração externo ou variáveis de ambiente
14
+ const SECURITY_CONFIG = {
15
+ ALLOWED_ORIGINS: [
16
+ 'https://easyflow.digital',
17
+ 'https://pay.easyflow.digital',
18
+ 'https://app.easyflow.digital',
19
+ 'https://localhost:443',
20
+ 'https://127.0.0.1:443',
21
+ ],
22
+ ALLOWED_DOMAINS: [
23
+ 'easyflow.digital',
24
+ 'pay.easyflow.digital',
25
+ 'app.easyflow.digital',
26
+ ],
27
+ MAX_REQUESTS_PER_MINUTE: 30,
28
+ REQUEST_TIMEOUT: 30000,
29
+ DEBUG_PROTECTION: false,
30
+ PRODUCTION_MODE: true,
31
+ // Allow iframe usage for low-code platforms
32
+ ALLOW_IFRAME: true,
33
+ }
34
+
35
+ /**
36
+ * Verificador de Ambiente Seguro
37
+ */
38
+ class EnvironmentValidator {
39
+ static validate() {
40
+ this.checkHTTPS()
41
+ this.checkIframe()
42
+ this.checkCryptoAPI()
43
+ this.checkTrustedTypes()
44
+ this.checkOrigin()
45
+ }
46
+
47
+ static checkHTTPS() {
48
+ if (
49
+ location.protocol !== 'https:' &&
50
+ location.hostname !== 'localhost' &&
51
+ location.hostname !== '127.0.0.1'
52
+ ) {
53
+ throwsError(new SecurityError('HTTPS required for security'))
54
+ }
55
+ }
56
+
57
+ static checkIframe() {
58
+ if (!SECURITY_CONFIG.ALLOW_IFRAME && window.top !== window.self) {
59
+ throwsError(new SecurityError('Cannot run in iframe for security'))
60
+ }
61
+ }
62
+
63
+ static checkCryptoAPI() {
64
+ if (!window.crypto || !window.crypto.subtle) {
65
+ throwsError(new SecurityError('Web Crypto API required'))
66
+ }
67
+ }
68
+
69
+ static checkTrustedTypes() {
70
+ if (!window.trustedTypes) {
71
+ console.warn('Trusted Types not supported - security reduced')
72
+ }
73
+ }
74
+
75
+ static checkOrigin() {
76
+ const currentOrigin = window.location.origin
77
+ if (!SECURITY_CONFIG.ALLOWED_ORIGINS.includes(currentOrigin)) {
78
+ console.warn(`Origin ${currentOrigin} not in allowed list`)
79
+ }
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Rate Limiter Avançado
85
+ */
86
+ class RateLimiter {
87
+ constructor() {
88
+ this.requests = new Map()
89
+ this.maxRequests = SECURITY_CONFIG.MAX_REQUESTS_PER_MINUTE
90
+ this.timeWindow = 60000
91
+ }
92
+
93
+ async checkLimit(identifier) {
94
+ const now = Date.now()
95
+ const userRequests = this.requests.get(identifier) || []
96
+ const validRequests = userRequests.filter(
97
+ (time) => now - time < this.timeWindow
98
+ )
99
+ if (validRequests.length >= this.maxRequests) {
100
+ const delay = this.calculateBackoff(validRequests.length)
101
+ await new Promise((resolve) => setTimeout(resolve, delay))
102
+ throwsError(new SecurityError('Rate limit exceeded'))
103
+ }
104
+ validRequests.push(now)
105
+ this.requests.set(identifier, validRequests)
106
+ }
107
+
108
+ calculateBackoff(requestCount) {
109
+ return Math.min(
110
+ 1000 * Math.pow(2, requestCount - this.maxRequests),
111
+ 30000
112
+ )
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Proteção contra Replay Attacks
118
+ */
119
+ class ReplayProtection {
120
+ static generateNonce() {
121
+ return crypto
122
+ .getRandomValues(new Uint8Array(16))
123
+ .reduce((acc, val) => acc + val.toString(16).padStart(2, '0'), '')
124
+ }
125
+ }
126
+
127
+ function fingerprint() {
128
+ return makeFingerprint() ?? Math.random().toString(10).substring(10)
129
+ }
130
+
131
+ function getSecurityHeaders(fingerprintId = fingerprint()) {
132
+ return {
133
+ 'Content-Security-Policy':
134
+ "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';",
135
+ 'X-Frame-Options': 'DENY',
136
+ 'X-Content-Type-Options': 'nosniff',
137
+ 'Referrer-Policy': 'strict-origin-when-cross-origin',
138
+ 'X-XSS-Protection': '1; mode=block',
139
+ 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
140
+ 'Permissions-Policy': 'geolocation=(), microphone=(), camera=()',
141
+ 'X-Download-Options': 'noopen',
142
+ 'X-Permitted-Cross-Domain-Policies': 'none',
143
+ 'x-fingerprint-id': fingerprintId,
144
+ 'X-Nonce': ReplayProtection.generateNonce(),
145
+ 'X-Timestamp': Date.now().toString(),
146
+ 'X-Client-Version': '2.1.3',
147
+ 'X-Client-Platform': 'web',
148
+ }
149
+ }
150
+
151
+ function makeEmptyRequestOptions() {
152
+ return {
153
+ method: 'POST',
154
+ headers: {},
155
+ body: null,
156
+ mode: 'cors',
157
+ cache: 'no-cache',
158
+ credentials: 'same-origin',
159
+ redirect: 'error',
160
+ referrerPolicy: 'no-referrer',
161
+ }
162
+ }
163
+
164
+ class SecureFetch {
165
+ static async request(url, options = makeEmptyRequestOptions()) {
166
+ const controller = new AbortController()
167
+ const timeoutId = setTimeout(
168
+ () => controller.abort(),
169
+ SECURITY_CONFIG.REQUEST_TIMEOUT
170
+ )
171
+ try {
172
+ const headersSanitized = Sanitizer.sanitizeHeaders(options.headers)
173
+ const secureHeaders = mergeHeaders(
174
+ getSecurityHeaders(headersSanitized['x-fingerprint-id']),
175
+ headersSanitized
176
+ )
177
+ console.log('url', url)
178
+ const secureUrl = Validator.validateUrl(url)
179
+ const params = {
180
+ ...options,
181
+ headers: secureHeaders,
182
+ signal: controller.signal,
183
+ }
184
+ console.log('ALL params before fetch', params)
185
+ const response = await fetch(secureUrl, params)
186
+ clearTimeout(timeoutId)
187
+ if (!response.ok) {
188
+ throwsError(
189
+ new NetworkError(
190
+ `HTTP ${response.status}: ${response.statusText}`
191
+ )
192
+ )
193
+ }
194
+ return response
195
+ } catch (error) {
196
+ console.log('Error in SecureFetch:', error)
197
+ clearTimeout(timeoutId)
198
+ throwsError(error)
199
+ }
200
+ }
201
+ }
202
+
203
+ if (typeof window !== 'undefined') {
204
+ try {
205
+ EnvironmentValidator.validate()
206
+ } catch (error) {
207
+ console.error('Security initialization failed:', error.message)
208
+ }
209
+ }
210
+
211
+ export {
212
+ EnvironmentValidator,
213
+ RateLimiter,
214
+ ReplayProtection,
215
+ SecureFetch,
216
+ SECURITY_CONFIG,
217
+ }
package/libs/types.mjs ADDED
@@ -0,0 +1,141 @@
1
+ /**
2
+ * @typedef {Object} EasyflowConfig
3
+ * @property {string} [baseUrl] - Base URL for the API (default: 'https://pay.easyflow.digital')
4
+ * @property {string} businessId - Business identifier
5
+ * @property {Object} [headers] - Default headers to include in all requests
6
+ * @property {number} [timeout] - Request timeout in milliseconds
7
+ */
8
+
9
+ /**
10
+ * @typedef {Object} Address
11
+ * @property {string} zipCode - ZIP/Postal code
12
+ * @property {string} street - Street name
13
+ * @property {string} complement - Address complement (apartment, suite, etc.)
14
+ * @property {string} neighborhood - Neighborhood/district
15
+ * @property {string} city - City name
16
+ * @property {string} state - State/province
17
+ * @property {string} number - Street number
18
+ */
19
+
20
+ /**
21
+ * @typedef {Object} LegalDocument
22
+ * @property {'CPF'|'CNPJ'} type - Document type (CPF for individuals, CNPJ for companies)
23
+ * @property {string} number - Document number
24
+ */
25
+
26
+ /**
27
+ * @typedef {Object} Phone
28
+ * @property {string} areaCode - Country area code (e.g., '+55' for Brazil)
29
+ * @property {string} ddd - Area code (e.g., '11' for São Paulo)
30
+ * @property {string} number - Phone number
31
+ * @property {boolean} isMobile - Whether the phone number is mobile
32
+ */
33
+
34
+ /**
35
+ * @typedef {Object} Business
36
+ * @property {string} id - Business identifier
37
+ * @property {string} name - Business name
38
+ * @property {string} [document] - Business document (CNPJ)
39
+ */
40
+
41
+ /**
42
+ * @typedef {Object} Customer
43
+ * @property {string} id - Customer unique identifier
44
+ * @property {Business} business - Business information
45
+ * @property {string} name - Customer full name
46
+ * @property {string} email - Customer email address
47
+ * @property {Address} [address] - Customer billing address
48
+ * @property {Address} [deliveryAddress] - Customer delivery address
49
+ * @property {LegalDocument} document - Customer legal document
50
+ * @property {Phone} phone - Customer phone information
51
+ */
52
+
53
+ /**
54
+ * @typedef {Object} CreditCardAnon
55
+ * @property {string} nickname - Card nickname for identification
56
+ * @property {string} last4Numbers - Last 4 digits of the card
57
+ * @property {Object} holder - Partial credit card holder information
58
+ * @property {string} expiresAtMonth - Expiration month (MM format)
59
+ * @property {string} expiresAtYear - Expiration year (YYYY format)
60
+ * @property {string} brand - Card brand (Visa, Mastercard, etc.)
61
+ */
62
+
63
+ /**
64
+ * @typedef {Object} PaginatedResult
65
+ * @template T
66
+ * @property {T[]} docs - Array of documents/items
67
+ * @property {number} totalDocs - Total number of documents
68
+ * @property {number} totalPages - Total number of pages
69
+ * @property {number} currentPage - Current page number
70
+ * @property {number} nextPage - Next page number
71
+ * @property {boolean} hasNext - Whether there is a next page
72
+ * @property {number} limit - Number of items per page
73
+ */
74
+
75
+ /**
76
+ * @typedef {Object} PaymentMethod
77
+ * @property {string} method - Payment method type
78
+ * @property {number} amount - Amount in cents
79
+ * @property {Object} [creditCard] - Credit card data
80
+ * @property {Object} [pix] - PIX payment data
81
+ * @property {Object} [bankBillet] - Bank billet data
82
+ */
83
+
84
+ /**
85
+ * @typedef {Object} OrderData
86
+ * @property {Object} customer - Customer information
87
+ * @property {Array<PaymentMethod>} payments - Payment methods
88
+ * @property {Object} [metadata] - Additional metadata
89
+ */
90
+
91
+ /**
92
+ * @typedef {Object} Customer
93
+ * @property {string} name - Customer name
94
+ * @property {string} email - Customer email
95
+ * @property {string} document - Customer document (CPF/CNPJ)
96
+ */
97
+
98
+ /**
99
+ * @typedef {Object} CreditCardData
100
+ * @property {string} number - Card number
101
+ * @property {string} holderName - Card holder name
102
+ * @property {string} expirationMonth - Expiration month
103
+ * @property {string} expirationYear - Expiration year
104
+ * @property {string} cvv - Security code
105
+ */
106
+
107
+ /**
108
+ * @typedef {Object} PixData
109
+ * @property {string} [qrCode] - PIX QR code (base64 image)
110
+ * @property {string} [copyAndPasteCode] - PIX copy and paste code
111
+ */
112
+
113
+ /**
114
+ * @typedef {Object} BankBilletData
115
+ * @property {string} [link] - Bank billet link
116
+ * @property {string} [line] - Bank billet line (linha digitável)
117
+ * @property {string} [barCode] - Bank billet barcode
118
+ */
119
+
120
+ /**
121
+ * @typedef {Object} ApiResponse
122
+ * @property {Object} [data] - Response data
123
+ * @property {string} [error] - Error message
124
+ * @property {number} [status] - HTTP status code
125
+ */
126
+
127
+ /**
128
+ * @typedef {Object} OfferData
129
+ * @property {string} id - Offer ID
130
+ * @property {Array<Object>} items - Offer items
131
+ * @property {Object} [metadata] - Additional metadata
132
+ */
133
+
134
+ /**
135
+ * @typedef {Object} OrderResponse
136
+ * @property {string} orderId - Order ID
137
+ * @property {string} status - Order status
138
+ * @property {Array<PaymentMethod>} payments - Payment methods
139
+ * @property {Object} customer - Customer information
140
+ * @property {Object} [metadata] - Additional metadata
141
+ */