@flonkid/kyc 1.6.1 → 1.8.0
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 +175 -169
- package/dist/index.cjs +319 -363
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -10
- package/dist/index.d.ts +57 -10
- package/dist/index.js +319 -364
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +21 -46
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +21 -46
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +9 -3
- package/package.json +1 -1
package/dist/server.cjs
CHANGED
|
@@ -22,57 +22,39 @@ function _interopNamespace(e) {
|
|
|
22
22
|
|
|
23
23
|
var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
|
|
24
24
|
|
|
25
|
-
var __defProp = Object.defineProperty;
|
|
26
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
27
|
-
|
|
28
25
|
// src/shared/constants.ts
|
|
29
|
-
var SDK_VERSION = "1.
|
|
26
|
+
var SDK_VERSION = "1.8.0";
|
|
30
27
|
var DEFAULT_API_BASE = "https://api.flonk.id/v1";
|
|
31
28
|
|
|
32
29
|
// src/shared/errors.ts
|
|
33
30
|
var FlonkError = class extends Error {
|
|
34
|
-
static {
|
|
35
|
-
__name(this, "FlonkError");
|
|
36
|
-
}
|
|
37
|
-
code;
|
|
38
|
-
statusCode;
|
|
39
31
|
constructor(message, code, statusCode) {
|
|
40
|
-
super(message)
|
|
32
|
+
super(message);
|
|
33
|
+
this.code = code;
|
|
34
|
+
this.statusCode = statusCode;
|
|
41
35
|
this.name = "FlonkError";
|
|
42
36
|
}
|
|
43
37
|
};
|
|
44
38
|
var FlonkAPIError = class extends FlonkError {
|
|
45
|
-
static {
|
|
46
|
-
__name(this, "FlonkAPIError");
|
|
47
|
-
}
|
|
48
|
-
body;
|
|
49
39
|
constructor(message, statusCode, body) {
|
|
50
|
-
super(message, "api_error", statusCode)
|
|
40
|
+
super(message, "api_error", statusCode);
|
|
41
|
+
this.body = body;
|
|
51
42
|
this.name = "FlonkAPIError";
|
|
52
43
|
}
|
|
53
44
|
};
|
|
54
45
|
var FlonkAuthenticationError = class extends FlonkError {
|
|
55
|
-
static {
|
|
56
|
-
__name(this, "FlonkAuthenticationError");
|
|
57
|
-
}
|
|
58
46
|
constructor(message = "Invalid or missing secret key") {
|
|
59
47
|
super(message, "authentication_error", 401);
|
|
60
48
|
this.name = "FlonkAuthenticationError";
|
|
61
49
|
}
|
|
62
50
|
};
|
|
63
51
|
var FlonkValidationError = class extends FlonkError {
|
|
64
|
-
static {
|
|
65
|
-
__name(this, "FlonkValidationError");
|
|
66
|
-
}
|
|
67
52
|
constructor(message) {
|
|
68
53
|
super(message, "validation_error", 400);
|
|
69
54
|
this.name = "FlonkValidationError";
|
|
70
55
|
}
|
|
71
56
|
};
|
|
72
57
|
var FlonkWebhookSignatureError = class extends FlonkError {
|
|
73
|
-
static {
|
|
74
|
-
__name(this, "FlonkWebhookSignatureError");
|
|
75
|
-
}
|
|
76
58
|
constructor(message = "Invalid webhook signature") {
|
|
77
59
|
super(message, "webhook_signature_error");
|
|
78
60
|
this.name = "FlonkWebhookSignatureError";
|
|
@@ -81,12 +63,6 @@ var FlonkWebhookSignatureError = class extends FlonkError {
|
|
|
81
63
|
|
|
82
64
|
// src/server/http-client.ts
|
|
83
65
|
var HttpClient = class {
|
|
84
|
-
static {
|
|
85
|
-
__name(this, "HttpClient");
|
|
86
|
-
}
|
|
87
|
-
baseUrl;
|
|
88
|
-
secretKey;
|
|
89
|
-
timeout;
|
|
90
66
|
constructor(baseUrl, secretKey, timeout = 3e4) {
|
|
91
67
|
this.baseUrl = baseUrl;
|
|
92
68
|
this.secretKey = secretKey;
|
|
@@ -118,7 +94,11 @@ var HttpClient = class {
|
|
|
118
94
|
const json = await res.json().catch(() => null);
|
|
119
95
|
if (!res.ok) {
|
|
120
96
|
if (res.status === 401) throw new FlonkAuthenticationError();
|
|
121
|
-
throw new FlonkAPIError(
|
|
97
|
+
throw new FlonkAPIError(
|
|
98
|
+
json?.message || `Request failed: ${res.status}`,
|
|
99
|
+
res.status,
|
|
100
|
+
json
|
|
101
|
+
);
|
|
122
102
|
}
|
|
123
103
|
return json;
|
|
124
104
|
} catch (err) {
|
|
@@ -130,12 +110,9 @@ var HttpClient = class {
|
|
|
130
110
|
}
|
|
131
111
|
};
|
|
132
112
|
var Webhooks = class {
|
|
133
|
-
static {
|
|
134
|
-
__name(this, "Webhooks");
|
|
135
|
-
}
|
|
136
113
|
/**
|
|
137
|
-
|
|
138
|
-
|
|
114
|
+
* Verify X-Signature-256 header: "sha256=<hex>"
|
|
115
|
+
*/
|
|
139
116
|
verifySignature(payload, signature, secret) {
|
|
140
117
|
const expected = "sha256=" + crypto__namespace.createHmac("sha256", secret).update(payload).digest("hex");
|
|
141
118
|
if (!this.safeEqual(signature, expected)) {
|
|
@@ -144,8 +121,8 @@ var Webhooks = class {
|
|
|
144
121
|
return this.parsePayload(payload);
|
|
145
122
|
}
|
|
146
123
|
/**
|
|
147
|
-
|
|
148
|
-
|
|
124
|
+
* Verify Stripe-like header: "t=<unix>, v1=<hex>"
|
|
125
|
+
*/
|
|
149
126
|
verifyTimestampSignature(payload, header, secret, options) {
|
|
150
127
|
const maxSkew = options?.maxSkewSeconds ?? 300;
|
|
151
128
|
const parts = this.parseHeader(header);
|
|
@@ -164,8 +141,8 @@ var Webhooks = class {
|
|
|
164
141
|
return this.parsePayload(payload);
|
|
165
142
|
}
|
|
166
143
|
/**
|
|
167
|
-
|
|
168
|
-
|
|
144
|
+
* Auto-detect signature format and verify.
|
|
145
|
+
*/
|
|
169
146
|
constructEvent(payload, signature, secret) {
|
|
170
147
|
if (signature.startsWith("sha256=")) {
|
|
171
148
|
return this.verifySignature(payload, signature, secret);
|
|
@@ -199,13 +176,8 @@ var Webhooks = class {
|
|
|
199
176
|
// src/server/index.ts
|
|
200
177
|
var SK_PATTERN = /^sk_(live|sandbox|test_sandbox|test_live)_[A-Za-z0-9]{16,}$/;
|
|
201
178
|
var FlonkKYCServer = class {
|
|
202
|
-
static {
|
|
203
|
-
__name(this, "FlonkKYCServer");
|
|
204
|
-
}
|
|
205
|
-
static version = SDK_VERSION;
|
|
206
|
-
http;
|
|
207
|
-
webhooks = new Webhooks();
|
|
208
179
|
constructor(options) {
|
|
180
|
+
this.webhooks = new Webhooks();
|
|
209
181
|
if (!options.secretKey) throw new FlonkAuthenticationError("secretKey is required");
|
|
210
182
|
if (!SK_PATTERN.test(options.secretKey)) {
|
|
211
183
|
throw new FlonkAuthenticationError("Invalid secret key format. Expected: sk_live_*, sk_sandbox_*, sk_test_sandbox_*, sk_test_live_*");
|
|
@@ -213,6 +185,9 @@ var FlonkKYCServer = class {
|
|
|
213
185
|
const base = (options.apiBase || DEFAULT_API_BASE).replace(/\/$/, "");
|
|
214
186
|
this.http = new HttpClient(base, options.secretKey, options.timeout);
|
|
215
187
|
}
|
|
188
|
+
static {
|
|
189
|
+
this.version = SDK_VERSION;
|
|
190
|
+
}
|
|
216
191
|
async createSession(params) {
|
|
217
192
|
return this.http.post("/sessions", params ?? {});
|
|
218
193
|
}
|
package/dist/server.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/constants.ts","../src/shared/errors.ts","../src/server/http-client.ts","../src/server/webhooks.ts","../src/server/index.ts"],"names":["SDK_VERSION","DEFAULT_API_BASE","FlonkError","Error","message","code","statusCode","name","FlonkAPIError","body","FlonkAuthenticationError","FlonkValidationError","FlonkWebhookSignatureError","HttpClient","baseUrl","secretKey","timeout","get","path","request","post","patch","method","controller","AbortController","timer","setTimeout","abort","res","fetch","headers","JSON","stringify","undefined","signal","json","catch","ok","status","err","clearTimeout","Webhooks","verifySignature","payload","signature","secret","expected","createHmac","update","digest","safeEqual","parsePayload","verifyTimestampSignature","header","options","maxSkew","maxSkewSeconds","parts","parseHeader","ts","Number","v1","Math","abs","floor","Date","now","constructEvent","startsWith","includes","parse","result","part","split","k","v","trim","a","b","length","timingSafeEqual","Buffer","from","SK_PATTERN","FlonkKYCServer","version","http","webhooks","test","base","apiBase","replace","createSession","params","getSession","sessionId","updateSession"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAO,IAAMA,WAAAA,GAAc,OAAA;AAEpB,IAAMC,gBAAAA,GAAmB,yBAAA;;;ACFzB,IAAMC,UAAAA,GAAN,cAAyBC,KAAAA,CAAAA;EAAhC;;;;;EACE,WAAA,CACEC,OAAAA,EACgBC,MACAC,UAAAA,EAChB;AACA,IAAA,KAAA,CAAMF,OAAAA,CAAAA,EAAAA,IAAAA,CAHUC,IAAAA,GAAAA,IAAAA,EAAAA,KACAC,UAAAA,GAAAA,UAAAA;AAGhB,IAAA,IAAA,CAAKC,IAAAA,GAAO,YAAA;AACd,EAAA;AACF;AAEO,IAAMC,aAAAA,GAAN,cAA4BN,UAAAA,CAAAA;EAXnC;;;;EAYE,WAAA,CACEE,OAAAA,EACAE,YACgBG,IAAAA,EAChB;AACA,IAAA,KAAA,CAAML,OAAAA,EAAS,WAAA,EAAaE,UAAAA,CAAAA,EAAAA,KAFZG,IAAAA,GAAAA,IAAAA;AAGhB,IAAA,IAAA,CAAKF,IAAAA,GAAO,eAAA;AACd,EAAA;AACF;AAEO,IAAMG,wBAAAA,GAAN,cAAuCR,UAAAA,CAAAA;EAtB9C;;;AAuBE,EAAA,WAAA,CAAYE,UAAU,+BAAA,EAAiC;AACrD,IAAA,KAAA,CAAMA,OAAAA,EAAS,wBAAwB,GAAA,CAAA;AACvC,IAAA,IAAA,CAAKG,IAAAA,GAAO,0BAAA;AACd,EAAA;AACF;AAEO,IAAMI,oBAAAA,GAAN,cAAmCT,UAAAA,CAAAA;EA7B1C;;;AA8BE,EAAA,WAAA,CAAYE,OAAAA,EAAiB;AAC3B,IAAA,KAAA,CAAMA,OAAAA,EAAS,oBAAoB,GAAA,CAAA;AACnC,IAAA,IAAA,CAAKG,IAAAA,GAAO,sBAAA;AACd,EAAA;AACF;AAEO,IAAMK,0BAAAA,GAAN,cAAyCV,UAAAA,CAAAA;EApChD;;;AAqCE,EAAA,WAAA,CAAYE,UAAU,2BAAA,EAA6B;AACjD,IAAA,KAAA,CAAMA,SAAS,yBAAA,CAAA;AACf,IAAA,IAAA,CAAKG,IAAAA,GAAO,4BAAA;AACd,EAAA;AACF;;;ACtCO,IAAMM,aAAN,MAAMA;EAHb;;;;;;EAIE,WAAA,CACmBC,OAAAA,EACAC,SAAAA,EACAC,OAAAA,GAAU,GAAA,EAC3B;SAHiBF,OAAAA,GAAAA,OAAAA;SACAC,SAAAA,GAAAA,SAAAA;SACAC,OAAAA,GAAAA,OAAAA;AAChB,EAAA;AAEH,EAAA,MAAMC,IAAOC,IAAAA,EAA0B;AACrC,IAAA,OAAO,IAAA,CAAKC,OAAAA,CAAW,KAAA,EAAOD,IAAAA,CAAAA;AAChC,EAAA;EAEA,MAAME,IAAAA,CAAQF,MAAcT,IAAAA,EAA4B;AACtD,IAAA,OAAO,IAAA,CAAKU,OAAAA,CAAW,MAAA,EAAQD,IAAAA,EAAMT,IAAAA,CAAAA;AACvC,EAAA;EAEA,MAAMY,KAAAA,CAASH,MAAcT,IAAAA,EAA4B;AACvD,IAAA,OAAO,IAAA,CAAKU,OAAAA,CAAW,OAAA,EAASD,IAAAA,EAAMT,IAAAA,CAAAA;AACxC,EAAA;EAEA,MAAcU,OAAAA,CAAWG,MAAAA,EAAgBJ,IAAAA,EAAcT,IAAAA,EAA4B;AACjF,IAAA,MAAMc,UAAAA,GAAa,IAAIC,eAAAA,EAAAA;AACvB,IAAA,MAAMC,QAAQC,UAAAA,CAAW,MAAMH,WAAWI,KAAAA,EAAK,EAAI,KAAKX,OAAO,CAAA;AAE/D,IAAA,IAAI;AACF,MAAA,MAAMY,GAAAA,GAAM,MAAMC,KAAAA,CAAM,CAAA,EAAG,KAAKf,OAAO,CAAA,EAAGI,IAAAA,CAAAA,CAAAA,EAAQ;AAChDI,QAAAA,MAAAA;QACAQ,OAAAA,EAAS;UACP,eAAA,EAAiB,CAAA,OAAA,EAAU,KAAKf,SAAS,CAAA,CAAA;UACzC,cAAA,EAAgB,kBAAA;AAChB,UAAA,YAAA,EAAc,kBAAkBf,WAAAA,CAAAA;AAClC,SAAA;AACAS,QAAAA,IAAAA,EAAMA,IAAAA,GAAOsB,IAAAA,CAAKC,SAAAA,CAAUvB,IAAAA,CAAAA,GAAQwB,KAAAA,CAAAA;AACpCC,QAAAA,MAAAA,EAAQX,UAAAA,CAAWW;OACrB,CAAA;AAEA,MAAA,MAAMC,OAAO,MAAMP,GAAAA,CAAIO,MAAI,CAAGC,KAAAA,CAAM,MAAM,IAAA,CAAA;AAE1C,MAAA,IAAI,CAACR,IAAIS,EAAAA,EAAI;AACX,QAAA,IAAIT,GAAAA,CAAIU,MAAAA,KAAW,GAAA,EAAK,MAAM,IAAI5B,wBAAAA,EAAAA;AAClC,QAAA,MAAM,IAAIF,aAAAA,CACR2B,IAAAA,EAAM/B,OAAAA,IAAW,CAAA,gBAAA,EAAmBwB,IAAIU,MAAM,CAAA,CAAA,EAC9CV,GAAAA,CAAIU,MAAAA,EACJH,IAAAA,CAAAA;AAEJ,MAAA;AAEA,MAAA,OAAOA,IAAAA;AACT,IAAA,CAAA,CAAA,OAASI,GAAAA,EAAK;AACZ,MAAA,IAAIA,GAAAA,YAAe/B,aAAAA,IAAiB+B,GAAAA,YAAe7B,wBAAAA,EAA0B,MAAM6B,GAAAA;AACnF,MAAA,MAAM,IAAI/B,aAAAA,CAAe+B,GAAAA,CAAcnC,OAAAA,EAAS,CAAA,CAAA;IAClD,CAAA,SAAA;AACEoC,MAAAA,YAAAA,CAAaf,KAAAA,CAAAA;AACf,IAAA;AACF,EAAA;AACF,CAAA;ACrDO,IAAMgB,WAAN,MAAMA;EAJb;;;;;;EAQEC,eAAAA,CAAgBC,OAAAA,EAAiBC,WAAmBC,MAAAA,EAA8B;AAChF,IAAA,MAAMC,QAAAA,GACJ,SAAA,GAAmBC,iBAAAA,CAAAA,UAAAA,CAAW,QAAA,EAAUF,MAAAA,EAAQG,MAAAA,CAAOL,OAAAA,CAAAA,CAASM,MAAAA,CAAO,KAAA,CAAA;AAEzE,IAAA,IAAI,CAAC,IAAA,CAAKC,SAAAA,CAAUN,SAAAA,EAAWE,QAAAA,CAAAA,EAAW;AACxC,MAAA,MAAM,IAAIlC,0BAAAA,EAAAA;AACZ,IAAA;AAEA,IAAA,OAAO,IAAA,CAAKuC,aAAaR,OAAAA,CAAAA;AAC3B,EAAA;;;;EAKAS,wBAAAA,CACET,OAAAA,EACAU,MAAAA,EACAR,MAAAA,EACAS,OAAAA,EACc;AACd,IAAA,MAAMC,OAAAA,GAAUD,SAASE,cAAAA,IAAkB,GAAA;AAC3C,IAAA,MAAMC,KAAAA,GAAQ,IAAA,CAAKC,WAAAA,CAAYL,MAAAA,CAAAA;AAC/B,IAAA,MAAMM,EAAAA,GAAKC,MAAAA,CAAOH,KAAAA,CAAM,GAAA,CAAI,CAAA;AAC5B,IAAA,MAAMI,EAAAA,GAAKJ,MAAM,IAAA,CAAA;AAEjB,IAAA,IAAI,CAACE,EAAAA,IAAM,CAACE,EAAAA,EAAI;AACd,MAAA,MAAM,IAAIjD,2BAA2B,gCAAA,CAAA;AACvC,IAAA;AAEA,IAAA,IAAIkD,IAAAA,CAAKC,GAAAA,CAAID,IAAAA,CAAKE,KAAAA,CAAMC,IAAAA,CAAKC,GAAAA,EAAG,GAAK,GAAA,CAAA,GAAQP,EAAAA,CAAAA,GAAMJ,OAAAA,EAAS;AAC1D,MAAA,MAAM,IAAI3C,0BAAAA,CAA2B,CAAA,uBAAA,EAA0B2C,OAAAA,CAAAA,CAAAA,CAAU,CAAA;AAC3E,IAAA;AAEA,IAAA,MAAMT,QAAAA,GACHC,iBAAAA,CAAAA,UAAAA,CAAW,QAAA,EAAUF,MAAAA,CAAAA,CACrBG,MAAAA,CAAO,CAAA,EAAGW,EAAAA,CAAAA,CAAAA,EAAMhB,OAAAA,CAAAA,CAAS,CAAA,CACzBM,OAAO,KAAA,CAAA;AAEV,IAAA,IAAI,CAAC,IAAA,CAAKC,SAAAA,CAAUW,EAAAA,EAAIf,QAAAA,CAAAA,EAAW;AACjC,MAAA,MAAM,IAAIlC,0BAAAA,EAAAA;AACZ,IAAA;AAEA,IAAA,OAAO,IAAA,CAAKuC,aAAaR,OAAAA,CAAAA;AAC3B,EAAA;;;;EAKAwB,cAAAA,CAAexB,OAAAA,EAAiBC,WAAmBC,MAAAA,EAA8B;AAC/E,IAAA,IAAID,SAAAA,CAAUwB,UAAAA,CAAW,SAAA,CAAA,EAAY;AACnC,MAAA,OAAO,IAAA,CAAK1B,eAAAA,CAAgBC,OAAAA,EAASC,SAAAA,EAAWC,MAAAA,CAAAA;AAClD,IAAA;AACA,IAAA,IAAID,UAAUyB,QAAAA,CAAS,IAAA,KAASzB,SAAAA,CAAUyB,QAAAA,CAAS,KAAA,CAAA,EAAQ;AACzD,MAAA,OAAO,IAAA,CAAKjB,wBAAAA,CAAyBT,OAAAA,EAASC,SAAAA,EAAWC,MAAAA,CAAAA;AAC3D,IAAA;AACA,IAAA,MAAM,IAAIjC,2BAA2B,+BAAA,CAAA;AACvC,EAAA;AAEQuC,EAAAA,YAAAA,CAAaR,OAAAA,EAA+B;AAClD,IAAA,IAAI;AACF,MAAA,OAAOZ,IAAAA,CAAKuC,MAAM3B,OAAAA,CAAAA;IACpB,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI/B,2BAA2B,wBAAA,CAAA;AACvC,IAAA;AACF,EAAA;AAEQ8C,EAAAA,WAAAA,CAAYL,MAAAA,EAAwC;AAC1D,IAAA,MAAMkB,SAAiC,EAAC;AACxC,IAAA,KAAA,MAAWC,IAAAA,IAAQnB,MAAAA,CAAOoB,KAAAA,CAAM,GAAA,CAAA,EAAM;AACpC,MAAA,MAAM,CAACC,GAAGC,CAAAA,CAAAA,GAAKH,KAAKI,IAAAA,EAAI,CAAGH,MAAM,GAAA,CAAA;AACjC,MAAA,IAAIC,CAAAA,IAAKC,CAAAA,EAAGJ,MAAAA,CAAOG,CAAAA,CAAAA,GAAKC,CAAAA;AAC1B,IAAA;AACA,IAAA,OAAOJ,MAAAA;AACT,EAAA;AAEQrB,EAAAA,SAAAA,CAAU2B,GAAWC,CAAAA,EAAoB;AAC/C,IAAA,IAAID,CAAAA,CAAEE,MAAAA,KAAWD,CAAAA,CAAEC,MAAAA,EAAQ,OAAO,KAAA;AAClC,IAAA,OAAcC,iBAAAA,CAAAA,eAAAA,CAAgBC,OAAOC,IAAAA,CAAKL,CAAAA,GAAII,MAAAA,CAAOC,IAAAA,CAAKJ,CAAAA,CAAAA,CAAAA;AAC5D,EAAA;AACF;;;AC3EA,IAAMK,UAAAA,GAAa,6DAAA;AAEZ,IAAMC,iBAAN,MAAMA;EAdb;;;AAeE,EAAA,OAAgBC,OAAAA,GAAUrF,WAAAA;AAETsF,EAAAA,IAAAA;AACDC,EAAAA,QAAAA,GAAW,IAAI9C,QAAAA,EAAAA;AAE/B,EAAA,WAAA,CAAYa,OAAAA,EAAgC;AAC1C,IAAA,IAAI,CAACA,OAAAA,CAAQvC,SAAAA,EAAW,MAAM,IAAIL,yBAAyB,uBAAA,CAAA;AAC3D,IAAA,IAAI,CAACyE,UAAAA,CAAWK,IAAAA,CAAKlC,OAAAA,CAAQvC,SAAS,CAAA,EAAG;AACvC,MAAA,MAAM,IAAIL,yBAAyB,iGAAA,CAAA;AACrC,IAAA;AAEA,IAAA,MAAM+E,QAAQnC,OAAAA,CAAQoC,OAAAA,IAAWzF,gBAAAA,EAAkB0F,OAAAA,CAAQ,OAAO,EAAA,CAAA;AAClE,IAAA,IAAA,CAAKL,OAAO,IAAIzE,UAAAA,CAAW4E,MAAMnC,OAAAA,CAAQvC,SAAAA,EAAWuC,QAAQtC,OAAO,CAAA;AACrE,EAAA;AAEA,EAAA,MAAM4E,cAAcC,MAAAA,EAAgD;AAClE,IAAA,OAAO,KAAKP,IAAAA,CAAKlE,IAAAA,CAAc,WAAA,EAAayE,MAAAA,IAAU,EAAC,CAAA;AACzD,EAAA;AAEA,EAAA,MAAMC,WAAWC,SAAAA,EAA4C;AAC3D,IAAA,IAAI,CAACA,SAAAA,EAAW,MAAM,IAAIpF,qBAAqB,uBAAA,CAAA;AAC/C,IAAA,OAAO,IAAA,CAAK2E,IAAAA,CAAKrE,GAAAA,CAAoB,CAAA,UAAA,EAAa8E,SAAAA,CAAAA,CAAW,CAAA;AAC/D,EAAA;EAEA,MAAMC,aAAAA,CAAcD,WAAmBF,MAAAA,EAAsD;AAC3F,IAAA,IAAI,CAACE,SAAAA,EAAW,MAAM,IAAIpF,qBAAqB,uBAAA,CAAA;AAC/C,IAAA,OAAO,KAAK2E,IAAAA,CAAKjE,KAAAA,CAAsB,CAAA,UAAA,EAAa0E,SAAAA,IAAaF,MAAAA,CAAAA;AACnE,EAAA;AACF","file":"server.cjs","sourcesContent":["export const SDK_VERSION = '1.6.0';\r\nexport const DEFAULT_WIDGET_URL = 'https://widget.flonk.id';\r\nexport const DEFAULT_API_BASE = 'https://api.flonk.id/v1';\r\n\r\nexport const WIDGET_EVENTS = {\r\n READY: 'KYC_WIDGET_READY',\r\n COMPLETE: 'KYC_COMPLETE',\r\n CANCEL: 'KYC_CANCEL',\r\n ERROR: 'KYC_ERROR',\r\n} as const;\r\n","export class FlonkError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly code: string,\r\n public readonly statusCode?: number,\r\n ) {\r\n super(message);\r\n this.name = 'FlonkError';\r\n }\r\n}\r\n\r\nexport class FlonkAPIError extends FlonkError {\r\n constructor(\r\n message: string,\r\n statusCode: number,\r\n public readonly body?: unknown,\r\n ) {\r\n super(message, 'api_error', statusCode);\r\n this.name = 'FlonkAPIError';\r\n }\r\n}\r\n\r\nexport class FlonkAuthenticationError extends FlonkError {\r\n constructor(message = 'Invalid or missing secret key') {\r\n super(message, 'authentication_error', 401);\r\n this.name = 'FlonkAuthenticationError';\r\n }\r\n}\r\n\r\nexport class FlonkValidationError extends FlonkError {\r\n constructor(message: string) {\r\n super(message, 'validation_error', 400);\r\n this.name = 'FlonkValidationError';\r\n }\r\n}\r\n\r\nexport class FlonkWebhookSignatureError extends FlonkError {\r\n constructor(message = 'Invalid webhook signature') {\r\n super(message, 'webhook_signature_error');\r\n this.name = 'FlonkWebhookSignatureError';\r\n }\r\n}\r\n","import { SDK_VERSION } from '../shared/constants';\r\nimport { FlonkAPIError, FlonkAuthenticationError } from '../shared/errors';\r\n\r\nexport class HttpClient {\r\n constructor(\r\n private readonly baseUrl: string,\r\n private readonly secretKey: string,\r\n private readonly timeout = 30_000,\r\n ) {}\r\n\r\n async get<T>(path: string): Promise<T> {\r\n return this.request<T>('GET', path);\r\n }\r\n\r\n async post<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('POST', path, body);\r\n }\r\n\r\n async patch<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('PATCH', path, body);\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers: {\r\n 'Authorization': `Bearer ${this.secretKey}`,\r\n 'Content-Type': 'application/json',\r\n 'User-Agent': `flonk-kyc-node/${SDK_VERSION}`,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n const json = await res.json().catch(() => null);\r\n\r\n if (!res.ok) {\r\n if (res.status === 401) throw new FlonkAuthenticationError();\r\n throw new FlonkAPIError(\r\n json?.message || `Request failed: ${res.status}`,\r\n res.status,\r\n json,\r\n );\r\n }\r\n\r\n return json as T;\r\n } catch (err) {\r\n if (err instanceof FlonkAPIError || err instanceof FlonkAuthenticationError) throw err;\r\n throw new FlonkAPIError((err as Error).message, 0);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n}\r\n","import * as crypto from 'crypto';\r\nimport { FlonkWebhookSignatureError } from '../shared/errors';\r\nimport type { WebhookEvent, WebhookVerifyOptions } from '../shared/types';\r\n\r\nexport class Webhooks {\r\n /**\r\n * Verify X-Signature-256 header: \"sha256=<hex>\"\r\n */\r\n verifySignature(payload: string, signature: string, secret: string): WebhookEvent {\r\n const expected =\r\n 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');\r\n\r\n if (!this.safeEqual(signature, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Verify Stripe-like header: \"t=<unix>, v1=<hex>\"\r\n */\r\n verifyTimestampSignature(\r\n payload: string,\r\n header: string,\r\n secret: string,\r\n options?: WebhookVerifyOptions,\r\n ): WebhookEvent {\r\n const maxSkew = options?.maxSkewSeconds ?? 300;\r\n const parts = this.parseHeader(header);\r\n const ts = Number(parts['t']);\r\n const v1 = parts['v1'];\r\n\r\n if (!ts || !v1) {\r\n throw new FlonkWebhookSignatureError('Missing timestamp or signature');\r\n }\r\n\r\n if (Math.abs(Math.floor(Date.now() / 1000) - ts) > maxSkew) {\r\n throw new FlonkWebhookSignatureError(`Timestamp skew exceeds ${maxSkew}s`);\r\n }\r\n\r\n const expected = crypto\r\n .createHmac('sha256', secret)\r\n .update(`${ts}.${payload}`)\r\n .digest('hex');\r\n\r\n if (!this.safeEqual(v1, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Auto-detect signature format and verify.\r\n */\r\n constructEvent(payload: string, signature: string, secret: string): WebhookEvent {\r\n if (signature.startsWith('sha256=')) {\r\n return this.verifySignature(payload, signature, secret);\r\n }\r\n if (signature.includes('t=') && signature.includes('v1=')) {\r\n return this.verifyTimestampSignature(payload, signature, secret);\r\n }\r\n throw new FlonkWebhookSignatureError('Unrecognized signature format');\r\n }\r\n\r\n private parsePayload(payload: string): WebhookEvent {\r\n try {\r\n return JSON.parse(payload) as WebhookEvent;\r\n } catch {\r\n throw new FlonkWebhookSignatureError('Malformed JSON payload');\r\n }\r\n }\r\n\r\n private parseHeader(header: string): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n for (const part of header.split(',')) {\r\n const [k, v] = part.trim().split('=');\r\n if (k && v) result[k] = v;\r\n }\r\n return result;\r\n }\r\n\r\n private safeEqual(a: string, b: string): boolean {\r\n if (a.length !== b.length) return false;\r\n return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));\r\n }\r\n}\r\n","import { SDK_VERSION, DEFAULT_API_BASE } from '../shared/constants';\r\nimport { FlonkAuthenticationError, FlonkValidationError } from '../shared/errors';\r\nimport type {\r\n FlonkKYCServerOptions,\r\n CreateSessionParams,\r\n Session,\r\n SessionDetails,\r\n UpdateSessionParams,\r\n} from '../shared/types';\r\nimport { HttpClient } from './http-client';\r\nimport { Webhooks } from './webhooks';\r\n\r\nconst SK_PATTERN = /^sk_(live|sandbox|test_sandbox|test_live)_[A-Za-z0-9]{16,}$/;\r\n\r\nexport class FlonkKYCServer {\r\n static readonly version = SDK_VERSION;\r\n\r\n private readonly http: HttpClient;\r\n public readonly webhooks = new Webhooks();\r\n\r\n constructor(options: FlonkKYCServerOptions) {\r\n if (!options.secretKey) throw new FlonkAuthenticationError('secretKey is required');\r\n if (!SK_PATTERN.test(options.secretKey)) {\r\n throw new FlonkAuthenticationError('Invalid secret key format. Expected: sk_live_*, sk_sandbox_*, sk_test_sandbox_*, sk_test_live_*');\r\n }\r\n\r\n const base = (options.apiBase || DEFAULT_API_BASE).replace(/\\/$/, '');\r\n this.http = new HttpClient(base, options.secretKey, options.timeout);\r\n }\r\n\r\n async createSession(params?: CreateSessionParams): Promise<Session> {\r\n return this.http.post<Session>('/sessions', params ?? {});\r\n }\r\n\r\n async getSession(sessionId: string): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.get<SessionDetails>(`/sessions/${sessionId}`);\r\n }\r\n\r\n async updateSession(sessionId: string, params: UpdateSessionParams): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.patch<SessionDetails>(`/sessions/${sessionId}`, params);\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/shared/constants.ts","../src/shared/errors.ts","../src/server/http-client.ts","../src/server/webhooks.ts","../src/server/index.ts"],"names":["crypto"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAO,IAAM,WAAA,GAAc,OAAA;AAEpB,IAAM,gBAAA,GAAmB,yBAAA;;;ACFzB,IAAM,UAAA,GAAN,cAAyB,KAAA,CAAM;AAAA,EACpC,WAAA,CACE,OAAA,EACgB,IAAA,EACA,UAAA,EAChB;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAHG,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACA,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,YAAA;AAAA,EACd;AACF;AAEO,IAAM,aAAA,GAAN,cAA4B,UAAA,CAAW;AAAA,EAC5C,WAAA,CACE,OAAA,EACA,UAAA,EACgB,IAAA,EAChB;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,aAAa,UAAU,CAAA;AAFtB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAEO,IAAM,wBAAA,GAAN,cAAuC,UAAA,CAAW;AAAA,EACvD,WAAA,CAAY,UAAU,+BAAA,EAAiC;AACrD,IAAA,KAAA,CAAM,OAAA,EAAS,wBAAwB,GAAG,CAAA;AAC1C,IAAA,IAAA,CAAK,IAAA,GAAO,0BAAA;AAAA,EACd;AACF;AAEO,IAAM,oBAAA,GAAN,cAAmC,UAAA,CAAW;AAAA,EACnD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAA,EAAS,oBAAoB,GAAG,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,sBAAA;AAAA,EACd;AACF;AAEO,IAAM,0BAAA,GAAN,cAAyC,UAAA,CAAW;AAAA,EACzD,WAAA,CAAY,UAAU,2BAAA,EAA6B;AACjD,IAAA,KAAA,CAAM,SAAS,yBAAyB,CAAA;AACxC,IAAA,IAAA,CAAK,IAAA,GAAO,4BAAA;AAAA,EACd;AACF;;;ACtCO,IAAM,aAAN,MAAiB;AAAA,EACtB,WAAA,CACmB,OAAA,EACA,SAAA,EACA,OAAA,GAAU,GAAA,EAC3B;AAHiB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EAChB;AAAA,EAEH,MAAM,IAAO,IAAA,EAA0B;AACrC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAW,KAAA,EAAO,IAAI,CAAA;AAAA,EACpC;AAAA,EAEA,MAAM,IAAA,CAAQ,IAAA,EAAc,IAAA,EAA4B;AACtD,IAAA,OAAO,IAAA,CAAK,OAAA,CAAW,MAAA,EAAQ,IAAA,EAAM,IAAI,CAAA;AAAA,EAC3C;AAAA,EAEA,MAAM,KAAA,CAAS,IAAA,EAAc,IAAA,EAA4B;AACvD,IAAA,OAAO,IAAA,CAAK,OAAA,CAAW,OAAA,EAAS,IAAA,EAAM,IAAI,CAAA;AAAA,EAC5C;AAAA,EAEA,MAAc,OAAA,CAAW,MAAA,EAAgB,IAAA,EAAc,IAAA,EAA4B;AACjF,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,WAAW,KAAA,EAAM,EAAG,KAAK,OAAO,CAAA;AAE/D,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI;AAAA,QAChD,MAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,eAAA,EAAiB,CAAA,OAAA,EAAU,IAAA,CAAK,SAAS,CAAA,CAAA;AAAA,UACzC,cAAA,EAAgB,kBAAA;AAAA,UAChB,YAAA,EAAc,kBAAkB,WAAW,CAAA;AAAA,SAC7C;AAAA,QACA,IAAA,EAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,GAAI,KAAA,CAAA;AAAA,QACpC,QAAQ,UAAA,CAAW;AAAA,OACpB,CAAA;AAED,MAAA,MAAM,OAAO,MAAM,GAAA,CAAI,MAAK,CAAE,KAAA,CAAM,MAAM,IAAI,CAAA;AAE9C,MAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,QAAA,IAAI,GAAA,CAAI,MAAA,KAAW,GAAA,EAAK,MAAM,IAAI,wBAAA,EAAyB;AAC3D,QAAA,MAAM,IAAI,aAAA;AAAA,UACR,IAAA,EAAM,OAAA,IAAW,CAAA,gBAAA,EAAmB,GAAA,CAAI,MAAM,CAAA,CAAA;AAAA,UAC9C,GAAA,CAAI,MAAA;AAAA,UACJ;AAAA,SACF;AAAA,MACF;AAEA,MAAA,OAAO,IAAA;AAAA,IACT,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,GAAA,YAAe,aAAA,IAAiB,GAAA,YAAe,wBAAA,EAA0B,MAAM,GAAA;AACnF,MAAA,MAAM,IAAI,aAAA,CAAe,GAAA,CAAc,OAAA,EAAS,CAAC,CAAA;AAAA,IACnD,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAA;ACrDO,IAAM,WAAN,MAAe;AAAA;AAAA;AAAA;AAAA,EAIpB,eAAA,CAAgB,OAAA,EAAiB,SAAA,EAAmB,MAAA,EAA8B;AAChF,IAAA,MAAM,QAAA,GACJ,SAAA,GAAmBA,iBAAA,CAAA,UAAA,CAAW,QAAA,EAAU,MAAM,EAAE,MAAA,CAAO,OAAO,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA;AAE9E,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAU,SAAA,EAAW,QAAQ,CAAA,EAAG;AACxC,MAAA,MAAM,IAAI,0BAAA,EAA2B;AAAA,IACvC;AAEA,IAAA,OAAO,IAAA,CAAK,aAAa,OAAO,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAA,CACE,OAAA,EACA,MAAA,EACA,MAAA,EACA,OAAA,EACc;AACd,IAAA,MAAM,OAAA,GAAU,SAAS,cAAA,IAAkB,GAAA;AAC3C,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,WAAA,CAAY,MAAM,CAAA;AACrC,IAAA,MAAM,EAAA,GAAK,MAAA,CAAO,KAAA,CAAM,GAAG,CAAC,CAAA;AAC5B,IAAA,MAAM,EAAA,GAAK,MAAM,IAAI,CAAA;AAErB,IAAA,IAAI,CAAC,EAAA,IAAM,CAAC,EAAA,EAAI;AACd,MAAA,MAAM,IAAI,2BAA2B,gCAAgC,CAAA;AAAA,IACvE;AAEA,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,EAAI,GAAI,GAAI,CAAA,GAAI,EAAE,CAAA,GAAI,OAAA,EAAS;AAC1D,MAAA,MAAM,IAAI,0BAAA,CAA2B,CAAA,uBAAA,EAA0B,OAAO,CAAA,CAAA,CAAG,CAAA;AAAA,IAC3E;AAEA,IAAA,MAAM,QAAA,GACHA,iBAAA,CAAA,UAAA,CAAW,QAAA,EAAU,MAAM,CAAA,CAC3B,MAAA,CAAO,CAAA,EAAG,EAAE,CAAA,CAAA,EAAI,OAAO,CAAA,CAAE,CAAA,CACzB,OAAO,KAAK,CAAA;AAEf,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAU,EAAA,EAAI,QAAQ,CAAA,EAAG;AACjC,MAAA,MAAM,IAAI,0BAAA,EAA2B;AAAA,IACvC;AAEA,IAAA,OAAO,IAAA,CAAK,aAAa,OAAO,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAA,CAAe,OAAA,EAAiB,SAAA,EAAmB,MAAA,EAA8B;AAC/E,IAAA,IAAI,SAAA,CAAU,UAAA,CAAW,SAAS,CAAA,EAAG;AACnC,MAAA,OAAO,IAAA,CAAK,eAAA,CAAgB,OAAA,EAAS,SAAA,EAAW,MAAM,CAAA;AAAA,IACxD;AACA,IAAA,IAAI,UAAU,QAAA,CAAS,IAAI,KAAK,SAAA,CAAU,QAAA,CAAS,KAAK,CAAA,EAAG;AACzD,MAAA,OAAO,IAAA,CAAK,wBAAA,CAAyB,OAAA,EAAS,SAAA,EAAW,MAAM,CAAA;AAAA,IACjE;AACA,IAAA,MAAM,IAAI,2BAA2B,+BAA+B,CAAA;AAAA,EACtE;AAAA,EAEQ,aAAa,OAAA,EAA+B;AAClD,IAAA,IAAI;AACF,MAAA,OAAO,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,IAC3B,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,2BAA2B,wBAAwB,CAAA;AAAA,IAC/D;AAAA,EACF;AAAA,EAEQ,YAAY,MAAA,EAAwC;AAC1D,IAAA,MAAM,SAAiC,EAAC;AACxC,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG;AACpC,MAAA,MAAM,CAAC,GAAG,CAAC,CAAA,GAAI,KAAK,IAAA,EAAK,CAAE,MAAM,GAAG,CAAA;AACpC,MAAA,IAAI,CAAA,IAAK,CAAA,EAAG,MAAA,CAAO,CAAC,CAAA,GAAI,CAAA;AAAA,IAC1B;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEQ,SAAA,CAAU,GAAW,CAAA,EAAoB;AAC/C,IAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,MAAA,EAAQ,OAAO,KAAA;AAClC,IAAA,OAAcA,iBAAA,CAAA,eAAA,CAAgB,OAAO,IAAA,CAAK,CAAC,GAAG,MAAA,CAAO,IAAA,CAAK,CAAC,CAAC,CAAA;AAAA,EAC9D;AACF;;;AC3EA,IAAM,UAAA,GAAa,6DAAA;AAEZ,IAAM,iBAAN,MAAqB;AAAA,EAM1B,YAAY,OAAA,EAAgC;AAF5C,IAAA,IAAA,CAAgB,QAAA,GAAW,IAAI,QAAA,EAAS;AAGtC,IAAA,IAAI,CAAC,OAAA,CAAQ,SAAA,EAAW,MAAM,IAAI,yBAAyB,uBAAuB,CAAA;AAClF,IAAA,IAAI,CAAC,UAAA,CAAW,IAAA,CAAK,OAAA,CAAQ,SAAS,CAAA,EAAG;AACvC,MAAA,MAAM,IAAI,yBAAyB,iGAAiG,CAAA;AAAA,IACtI;AAEA,IAAA,MAAM,QAAQ,OAAA,CAAQ,OAAA,IAAW,gBAAA,EAAkB,OAAA,CAAQ,OAAO,EAAE,CAAA;AACpE,IAAA,IAAA,CAAK,OAAO,IAAI,UAAA,CAAW,MAAM,OAAA,CAAQ,SAAA,EAAW,QAAQ,OAAO,CAAA;AAAA,EACrE;AAAA,EAbA;AAAA,IAAA,IAAA,CAAgB,OAAA,GAAU,WAAA;AAAA;AAAA,EAe1B,MAAM,cAAc,MAAA,EAAgD;AAClE,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA,CAAc,WAAA,EAAa,MAAA,IAAU,EAAE,CAAA;AAAA,EAC1D;AAAA,EAEA,MAAM,WAAW,SAAA,EAA4C;AAC3D,IAAA,IAAI,CAAC,SAAA,EAAW,MAAM,IAAI,qBAAqB,uBAAuB,CAAA;AACtE,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,CAAoB,CAAA,UAAA,EAAa,SAAS,CAAA,CAAE,CAAA;AAAA,EAC/D;AAAA,EAEA,MAAM,aAAA,CAAc,SAAA,EAAmB,MAAA,EAAsD;AAC3F,IAAA,IAAI,CAAC,SAAA,EAAW,MAAM,IAAI,qBAAqB,uBAAuB,CAAA;AACtE,IAAA,OAAO,KAAK,IAAA,CAAK,KAAA,CAAsB,CAAA,UAAA,EAAa,SAAS,IAAI,MAAM,CAAA;AAAA,EACzE;AACF","file":"server.cjs","sourcesContent":["export const SDK_VERSION = '1.8.0';\r\nexport const DEFAULT_WIDGET_URL = 'https://widget.flonk.id';\r\nexport const DEFAULT_API_BASE = 'https://api.flonk.id/v1';\r\n\r\nexport const WIDGET_EVENTS = {\r\n READY: 'KYC_WIDGET_READY',\r\n COMPLETE: 'KYC_COMPLETE',\r\n CANCEL: 'KYC_CANCEL',\r\n ERROR: 'KYC_ERROR',\r\n} as const;\r\n","export class FlonkError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly code: string,\r\n public readonly statusCode?: number,\r\n ) {\r\n super(message);\r\n this.name = 'FlonkError';\r\n }\r\n}\r\n\r\nexport class FlonkAPIError extends FlonkError {\r\n constructor(\r\n message: string,\r\n statusCode: number,\r\n public readonly body?: unknown,\r\n ) {\r\n super(message, 'api_error', statusCode);\r\n this.name = 'FlonkAPIError';\r\n }\r\n}\r\n\r\nexport class FlonkAuthenticationError extends FlonkError {\r\n constructor(message = 'Invalid or missing secret key') {\r\n super(message, 'authentication_error', 401);\r\n this.name = 'FlonkAuthenticationError';\r\n }\r\n}\r\n\r\nexport class FlonkValidationError extends FlonkError {\r\n constructor(message: string) {\r\n super(message, 'validation_error', 400);\r\n this.name = 'FlonkValidationError';\r\n }\r\n}\r\n\r\nexport class FlonkWebhookSignatureError extends FlonkError {\r\n constructor(message = 'Invalid webhook signature') {\r\n super(message, 'webhook_signature_error');\r\n this.name = 'FlonkWebhookSignatureError';\r\n }\r\n}\r\n","import { SDK_VERSION } from '../shared/constants';\r\nimport { FlonkAPIError, FlonkAuthenticationError } from '../shared/errors';\r\n\r\nexport class HttpClient {\r\n constructor(\r\n private readonly baseUrl: string,\r\n private readonly secretKey: string,\r\n private readonly timeout = 30_000,\r\n ) {}\r\n\r\n async get<T>(path: string): Promise<T> {\r\n return this.request<T>('GET', path);\r\n }\r\n\r\n async post<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('POST', path, body);\r\n }\r\n\r\n async patch<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('PATCH', path, body);\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers: {\r\n 'Authorization': `Bearer ${this.secretKey}`,\r\n 'Content-Type': 'application/json',\r\n 'User-Agent': `flonk-kyc-node/${SDK_VERSION}`,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n const json = await res.json().catch(() => null);\r\n\r\n if (!res.ok) {\r\n if (res.status === 401) throw new FlonkAuthenticationError();\r\n throw new FlonkAPIError(\r\n json?.message || `Request failed: ${res.status}`,\r\n res.status,\r\n json,\r\n );\r\n }\r\n\r\n return json as T;\r\n } catch (err) {\r\n if (err instanceof FlonkAPIError || err instanceof FlonkAuthenticationError) throw err;\r\n throw new FlonkAPIError((err as Error).message, 0);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n}\r\n","import * as crypto from 'crypto';\r\nimport { FlonkWebhookSignatureError } from '../shared/errors';\r\nimport type { WebhookEvent, WebhookVerifyOptions } from '../shared/types';\r\n\r\nexport class Webhooks {\r\n /**\r\n * Verify X-Signature-256 header: \"sha256=<hex>\"\r\n */\r\n verifySignature(payload: string, signature: string, secret: string): WebhookEvent {\r\n const expected =\r\n 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');\r\n\r\n if (!this.safeEqual(signature, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Verify Stripe-like header: \"t=<unix>, v1=<hex>\"\r\n */\r\n verifyTimestampSignature(\r\n payload: string,\r\n header: string,\r\n secret: string,\r\n options?: WebhookVerifyOptions,\r\n ): WebhookEvent {\r\n const maxSkew = options?.maxSkewSeconds ?? 300;\r\n const parts = this.parseHeader(header);\r\n const ts = Number(parts['t']);\r\n const v1 = parts['v1'];\r\n\r\n if (!ts || !v1) {\r\n throw new FlonkWebhookSignatureError('Missing timestamp or signature');\r\n }\r\n\r\n if (Math.abs(Math.floor(Date.now() / 1000) - ts) > maxSkew) {\r\n throw new FlonkWebhookSignatureError(`Timestamp skew exceeds ${maxSkew}s`);\r\n }\r\n\r\n const expected = crypto\r\n .createHmac('sha256', secret)\r\n .update(`${ts}.${payload}`)\r\n .digest('hex');\r\n\r\n if (!this.safeEqual(v1, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Auto-detect signature format and verify.\r\n */\r\n constructEvent(payload: string, signature: string, secret: string): WebhookEvent {\r\n if (signature.startsWith('sha256=')) {\r\n return this.verifySignature(payload, signature, secret);\r\n }\r\n if (signature.includes('t=') && signature.includes('v1=')) {\r\n return this.verifyTimestampSignature(payload, signature, secret);\r\n }\r\n throw new FlonkWebhookSignatureError('Unrecognized signature format');\r\n }\r\n\r\n private parsePayload(payload: string): WebhookEvent {\r\n try {\r\n return JSON.parse(payload) as WebhookEvent;\r\n } catch {\r\n throw new FlonkWebhookSignatureError('Malformed JSON payload');\r\n }\r\n }\r\n\r\n private parseHeader(header: string): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n for (const part of header.split(',')) {\r\n const [k, v] = part.trim().split('=');\r\n if (k && v) result[k] = v;\r\n }\r\n return result;\r\n }\r\n\r\n private safeEqual(a: string, b: string): boolean {\r\n if (a.length !== b.length) return false;\r\n return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));\r\n }\r\n}\r\n","import { SDK_VERSION, DEFAULT_API_BASE } from '../shared/constants';\r\nimport { FlonkAuthenticationError, FlonkValidationError } from '../shared/errors';\r\nimport type {\r\n FlonkKYCServerOptions,\r\n CreateSessionParams,\r\n Session,\r\n SessionDetails,\r\n UpdateSessionParams,\r\n} from '../shared/types';\r\nimport { HttpClient } from './http-client';\r\nimport { Webhooks } from './webhooks';\r\n\r\nconst SK_PATTERN = /^sk_(live|sandbox|test_sandbox|test_live)_[A-Za-z0-9]{16,}$/;\r\n\r\nexport class FlonkKYCServer {\r\n static readonly version = SDK_VERSION;\r\n\r\n private readonly http: HttpClient;\r\n public readonly webhooks = new Webhooks();\r\n\r\n constructor(options: FlonkKYCServerOptions) {\r\n if (!options.secretKey) throw new FlonkAuthenticationError('secretKey is required');\r\n if (!SK_PATTERN.test(options.secretKey)) {\r\n throw new FlonkAuthenticationError('Invalid secret key format. Expected: sk_live_*, sk_sandbox_*, sk_test_sandbox_*, sk_test_live_*');\r\n }\r\n\r\n const base = (options.apiBase || DEFAULT_API_BASE).replace(/\\/$/, '');\r\n this.http = new HttpClient(base, options.secretKey, options.timeout);\r\n }\r\n\r\n async createSession(params?: CreateSessionParams): Promise<Session> {\r\n return this.http.post<Session>('/sessions', params ?? {});\r\n }\r\n\r\n async getSession(sessionId: string): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.get<SessionDetails>(`/sessions/${sessionId}`);\r\n }\r\n\r\n async updateSession(sessionId: string, params: UpdateSessionParams): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.patch<SessionDetails>(`/sessions/${sessionId}`, params);\r\n }\r\n}\r\n"]}
|
package/dist/server.d.cts
CHANGED
package/dist/server.d.ts
CHANGED
package/dist/server.js
CHANGED
|
@@ -1,56 +1,38 @@
|
|
|
1
1
|
import * as crypto from 'crypto';
|
|
2
2
|
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
|
-
|
|
6
3
|
// src/shared/constants.ts
|
|
7
|
-
var SDK_VERSION = "1.
|
|
4
|
+
var SDK_VERSION = "1.8.0";
|
|
8
5
|
var DEFAULT_API_BASE = "https://api.flonk.id/v1";
|
|
9
6
|
|
|
10
7
|
// src/shared/errors.ts
|
|
11
8
|
var FlonkError = class extends Error {
|
|
12
|
-
static {
|
|
13
|
-
__name(this, "FlonkError");
|
|
14
|
-
}
|
|
15
|
-
code;
|
|
16
|
-
statusCode;
|
|
17
9
|
constructor(message, code, statusCode) {
|
|
18
|
-
super(message)
|
|
10
|
+
super(message);
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.statusCode = statusCode;
|
|
19
13
|
this.name = "FlonkError";
|
|
20
14
|
}
|
|
21
15
|
};
|
|
22
16
|
var FlonkAPIError = class extends FlonkError {
|
|
23
|
-
static {
|
|
24
|
-
__name(this, "FlonkAPIError");
|
|
25
|
-
}
|
|
26
|
-
body;
|
|
27
17
|
constructor(message, statusCode, body) {
|
|
28
|
-
super(message, "api_error", statusCode)
|
|
18
|
+
super(message, "api_error", statusCode);
|
|
19
|
+
this.body = body;
|
|
29
20
|
this.name = "FlonkAPIError";
|
|
30
21
|
}
|
|
31
22
|
};
|
|
32
23
|
var FlonkAuthenticationError = class extends FlonkError {
|
|
33
|
-
static {
|
|
34
|
-
__name(this, "FlonkAuthenticationError");
|
|
35
|
-
}
|
|
36
24
|
constructor(message = "Invalid or missing secret key") {
|
|
37
25
|
super(message, "authentication_error", 401);
|
|
38
26
|
this.name = "FlonkAuthenticationError";
|
|
39
27
|
}
|
|
40
28
|
};
|
|
41
29
|
var FlonkValidationError = class extends FlonkError {
|
|
42
|
-
static {
|
|
43
|
-
__name(this, "FlonkValidationError");
|
|
44
|
-
}
|
|
45
30
|
constructor(message) {
|
|
46
31
|
super(message, "validation_error", 400);
|
|
47
32
|
this.name = "FlonkValidationError";
|
|
48
33
|
}
|
|
49
34
|
};
|
|
50
35
|
var FlonkWebhookSignatureError = class extends FlonkError {
|
|
51
|
-
static {
|
|
52
|
-
__name(this, "FlonkWebhookSignatureError");
|
|
53
|
-
}
|
|
54
36
|
constructor(message = "Invalid webhook signature") {
|
|
55
37
|
super(message, "webhook_signature_error");
|
|
56
38
|
this.name = "FlonkWebhookSignatureError";
|
|
@@ -59,12 +41,6 @@ var FlonkWebhookSignatureError = class extends FlonkError {
|
|
|
59
41
|
|
|
60
42
|
// src/server/http-client.ts
|
|
61
43
|
var HttpClient = class {
|
|
62
|
-
static {
|
|
63
|
-
__name(this, "HttpClient");
|
|
64
|
-
}
|
|
65
|
-
baseUrl;
|
|
66
|
-
secretKey;
|
|
67
|
-
timeout;
|
|
68
44
|
constructor(baseUrl, secretKey, timeout = 3e4) {
|
|
69
45
|
this.baseUrl = baseUrl;
|
|
70
46
|
this.secretKey = secretKey;
|
|
@@ -96,7 +72,11 @@ var HttpClient = class {
|
|
|
96
72
|
const json = await res.json().catch(() => null);
|
|
97
73
|
if (!res.ok) {
|
|
98
74
|
if (res.status === 401) throw new FlonkAuthenticationError();
|
|
99
|
-
throw new FlonkAPIError(
|
|
75
|
+
throw new FlonkAPIError(
|
|
76
|
+
json?.message || `Request failed: ${res.status}`,
|
|
77
|
+
res.status,
|
|
78
|
+
json
|
|
79
|
+
);
|
|
100
80
|
}
|
|
101
81
|
return json;
|
|
102
82
|
} catch (err) {
|
|
@@ -108,12 +88,9 @@ var HttpClient = class {
|
|
|
108
88
|
}
|
|
109
89
|
};
|
|
110
90
|
var Webhooks = class {
|
|
111
|
-
static {
|
|
112
|
-
__name(this, "Webhooks");
|
|
113
|
-
}
|
|
114
91
|
/**
|
|
115
|
-
|
|
116
|
-
|
|
92
|
+
* Verify X-Signature-256 header: "sha256=<hex>"
|
|
93
|
+
*/
|
|
117
94
|
verifySignature(payload, signature, secret) {
|
|
118
95
|
const expected = "sha256=" + crypto.createHmac("sha256", secret).update(payload).digest("hex");
|
|
119
96
|
if (!this.safeEqual(signature, expected)) {
|
|
@@ -122,8 +99,8 @@ var Webhooks = class {
|
|
|
122
99
|
return this.parsePayload(payload);
|
|
123
100
|
}
|
|
124
101
|
/**
|
|
125
|
-
|
|
126
|
-
|
|
102
|
+
* Verify Stripe-like header: "t=<unix>, v1=<hex>"
|
|
103
|
+
*/
|
|
127
104
|
verifyTimestampSignature(payload, header, secret, options) {
|
|
128
105
|
const maxSkew = options?.maxSkewSeconds ?? 300;
|
|
129
106
|
const parts = this.parseHeader(header);
|
|
@@ -142,8 +119,8 @@ var Webhooks = class {
|
|
|
142
119
|
return this.parsePayload(payload);
|
|
143
120
|
}
|
|
144
121
|
/**
|
|
145
|
-
|
|
146
|
-
|
|
122
|
+
* Auto-detect signature format and verify.
|
|
123
|
+
*/
|
|
147
124
|
constructEvent(payload, signature, secret) {
|
|
148
125
|
if (signature.startsWith("sha256=")) {
|
|
149
126
|
return this.verifySignature(payload, signature, secret);
|
|
@@ -177,13 +154,8 @@ var Webhooks = class {
|
|
|
177
154
|
// src/server/index.ts
|
|
178
155
|
var SK_PATTERN = /^sk_(live|sandbox|test_sandbox|test_live)_[A-Za-z0-9]{16,}$/;
|
|
179
156
|
var FlonkKYCServer = class {
|
|
180
|
-
static {
|
|
181
|
-
__name(this, "FlonkKYCServer");
|
|
182
|
-
}
|
|
183
|
-
static version = SDK_VERSION;
|
|
184
|
-
http;
|
|
185
|
-
webhooks = new Webhooks();
|
|
186
157
|
constructor(options) {
|
|
158
|
+
this.webhooks = new Webhooks();
|
|
187
159
|
if (!options.secretKey) throw new FlonkAuthenticationError("secretKey is required");
|
|
188
160
|
if (!SK_PATTERN.test(options.secretKey)) {
|
|
189
161
|
throw new FlonkAuthenticationError("Invalid secret key format. Expected: sk_live_*, sk_sandbox_*, sk_test_sandbox_*, sk_test_live_*");
|
|
@@ -191,6 +163,9 @@ var FlonkKYCServer = class {
|
|
|
191
163
|
const base = (options.apiBase || DEFAULT_API_BASE).replace(/\/$/, "");
|
|
192
164
|
this.http = new HttpClient(base, options.secretKey, options.timeout);
|
|
193
165
|
}
|
|
166
|
+
static {
|
|
167
|
+
this.version = SDK_VERSION;
|
|
168
|
+
}
|
|
194
169
|
async createSession(params) {
|
|
195
170
|
return this.http.post("/sessions", params ?? {});
|
|
196
171
|
}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/constants.ts","../src/shared/errors.ts","../src/server/http-client.ts","../src/server/webhooks.ts","../src/server/index.ts"],"names":["SDK_VERSION","DEFAULT_API_BASE","FlonkError","Error","message","code","statusCode","name","FlonkAPIError","body","FlonkAuthenticationError","FlonkValidationError","FlonkWebhookSignatureError","HttpClient","baseUrl","secretKey","timeout","get","path","request","post","patch","method","controller","AbortController","timer","setTimeout","abort","res","fetch","headers","JSON","stringify","undefined","signal","json","catch","ok","status","err","clearTimeout","Webhooks","verifySignature","payload","signature","secret","expected","createHmac","update","digest","safeEqual","parsePayload","verifyTimestampSignature","header","options","maxSkew","maxSkewSeconds","parts","parseHeader","ts","Number","v1","Math","abs","floor","Date","now","constructEvent","startsWith","includes","parse","result","part","split","k","v","trim","a","b","length","timingSafeEqual","Buffer","from","SK_PATTERN","FlonkKYCServer","version","http","webhooks","test","base","apiBase","replace","createSession","params","getSession","sessionId","updateSession"],"mappings":"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","file":"server.js","sourcesContent":["export const SDK_VERSION = '1.6.0';\r\nexport const DEFAULT_WIDGET_URL = 'https://widget.flonk.id';\r\nexport const DEFAULT_API_BASE = 'https://api.flonk.id/v1';\r\n\r\nexport const WIDGET_EVENTS = {\r\n READY: 'KYC_WIDGET_READY',\r\n COMPLETE: 'KYC_COMPLETE',\r\n CANCEL: 'KYC_CANCEL',\r\n ERROR: 'KYC_ERROR',\r\n} as const;\r\n","export class FlonkError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly code: string,\r\n public readonly statusCode?: number,\r\n ) {\r\n super(message);\r\n this.name = 'FlonkError';\r\n }\r\n}\r\n\r\nexport class FlonkAPIError extends FlonkError {\r\n constructor(\r\n message: string,\r\n statusCode: number,\r\n public readonly body?: unknown,\r\n ) {\r\n super(message, 'api_error', statusCode);\r\n this.name = 'FlonkAPIError';\r\n }\r\n}\r\n\r\nexport class FlonkAuthenticationError extends FlonkError {\r\n constructor(message = 'Invalid or missing secret key') {\r\n super(message, 'authentication_error', 401);\r\n this.name = 'FlonkAuthenticationError';\r\n }\r\n}\r\n\r\nexport class FlonkValidationError extends FlonkError {\r\n constructor(message: string) {\r\n super(message, 'validation_error', 400);\r\n this.name = 'FlonkValidationError';\r\n }\r\n}\r\n\r\nexport class FlonkWebhookSignatureError extends FlonkError {\r\n constructor(message = 'Invalid webhook signature') {\r\n super(message, 'webhook_signature_error');\r\n this.name = 'FlonkWebhookSignatureError';\r\n }\r\n}\r\n","import { SDK_VERSION } from '../shared/constants';\r\nimport { FlonkAPIError, FlonkAuthenticationError } from '../shared/errors';\r\n\r\nexport class HttpClient {\r\n constructor(\r\n private readonly baseUrl: string,\r\n private readonly secretKey: string,\r\n private readonly timeout = 30_000,\r\n ) {}\r\n\r\n async get<T>(path: string): Promise<T> {\r\n return this.request<T>('GET', path);\r\n }\r\n\r\n async post<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('POST', path, body);\r\n }\r\n\r\n async patch<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('PATCH', path, body);\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers: {\r\n 'Authorization': `Bearer ${this.secretKey}`,\r\n 'Content-Type': 'application/json',\r\n 'User-Agent': `flonk-kyc-node/${SDK_VERSION}`,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n const json = await res.json().catch(() => null);\r\n\r\n if (!res.ok) {\r\n if (res.status === 401) throw new FlonkAuthenticationError();\r\n throw new FlonkAPIError(\r\n json?.message || `Request failed: ${res.status}`,\r\n res.status,\r\n json,\r\n );\r\n }\r\n\r\n return json as T;\r\n } catch (err) {\r\n if (err instanceof FlonkAPIError || err instanceof FlonkAuthenticationError) throw err;\r\n throw new FlonkAPIError((err as Error).message, 0);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n}\r\n","import * as crypto from 'crypto';\r\nimport { FlonkWebhookSignatureError } from '../shared/errors';\r\nimport type { WebhookEvent, WebhookVerifyOptions } from '../shared/types';\r\n\r\nexport class Webhooks {\r\n /**\r\n * Verify X-Signature-256 header: \"sha256=<hex>\"\r\n */\r\n verifySignature(payload: string, signature: string, secret: string): WebhookEvent {\r\n const expected =\r\n 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');\r\n\r\n if (!this.safeEqual(signature, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Verify Stripe-like header: \"t=<unix>, v1=<hex>\"\r\n */\r\n verifyTimestampSignature(\r\n payload: string,\r\n header: string,\r\n secret: string,\r\n options?: WebhookVerifyOptions,\r\n ): WebhookEvent {\r\n const maxSkew = options?.maxSkewSeconds ?? 300;\r\n const parts = this.parseHeader(header);\r\n const ts = Number(parts['t']);\r\n const v1 = parts['v1'];\r\n\r\n if (!ts || !v1) {\r\n throw new FlonkWebhookSignatureError('Missing timestamp or signature');\r\n }\r\n\r\n if (Math.abs(Math.floor(Date.now() / 1000) - ts) > maxSkew) {\r\n throw new FlonkWebhookSignatureError(`Timestamp skew exceeds ${maxSkew}s`);\r\n }\r\n\r\n const expected = crypto\r\n .createHmac('sha256', secret)\r\n .update(`${ts}.${payload}`)\r\n .digest('hex');\r\n\r\n if (!this.safeEqual(v1, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Auto-detect signature format and verify.\r\n */\r\n constructEvent(payload: string, signature: string, secret: string): WebhookEvent {\r\n if (signature.startsWith('sha256=')) {\r\n return this.verifySignature(payload, signature, secret);\r\n }\r\n if (signature.includes('t=') && signature.includes('v1=')) {\r\n return this.verifyTimestampSignature(payload, signature, secret);\r\n }\r\n throw new FlonkWebhookSignatureError('Unrecognized signature format');\r\n }\r\n\r\n private parsePayload(payload: string): WebhookEvent {\r\n try {\r\n return JSON.parse(payload) as WebhookEvent;\r\n } catch {\r\n throw new FlonkWebhookSignatureError('Malformed JSON payload');\r\n }\r\n }\r\n\r\n private parseHeader(header: string): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n for (const part of header.split(',')) {\r\n const [k, v] = part.trim().split('=');\r\n if (k && v) result[k] = v;\r\n }\r\n return result;\r\n }\r\n\r\n private safeEqual(a: string, b: string): boolean {\r\n if (a.length !== b.length) return false;\r\n return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));\r\n }\r\n}\r\n","import { SDK_VERSION, DEFAULT_API_BASE } from '../shared/constants';\r\nimport { FlonkAuthenticationError, FlonkValidationError } from '../shared/errors';\r\nimport type {\r\n FlonkKYCServerOptions,\r\n CreateSessionParams,\r\n Session,\r\n SessionDetails,\r\n UpdateSessionParams,\r\n} from '../shared/types';\r\nimport { HttpClient } from './http-client';\r\nimport { Webhooks } from './webhooks';\r\n\r\nconst SK_PATTERN = /^sk_(live|sandbox|test_sandbox|test_live)_[A-Za-z0-9]{16,}$/;\r\n\r\nexport class FlonkKYCServer {\r\n static readonly version = SDK_VERSION;\r\n\r\n private readonly http: HttpClient;\r\n public readonly webhooks = new Webhooks();\r\n\r\n constructor(options: FlonkKYCServerOptions) {\r\n if (!options.secretKey) throw new FlonkAuthenticationError('secretKey is required');\r\n if (!SK_PATTERN.test(options.secretKey)) {\r\n throw new FlonkAuthenticationError('Invalid secret key format. Expected: sk_live_*, sk_sandbox_*, sk_test_sandbox_*, sk_test_live_*');\r\n }\r\n\r\n const base = (options.apiBase || DEFAULT_API_BASE).replace(/\\/$/, '');\r\n this.http = new HttpClient(base, options.secretKey, options.timeout);\r\n }\r\n\r\n async createSession(params?: CreateSessionParams): Promise<Session> {\r\n return this.http.post<Session>('/sessions', params ?? {});\r\n }\r\n\r\n async getSession(sessionId: string): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.get<SessionDetails>(`/sessions/${sessionId}`);\r\n }\r\n\r\n async updateSession(sessionId: string, params: UpdateSessionParams): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.patch<SessionDetails>(`/sessions/${sessionId}`, params);\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/shared/constants.ts","../src/shared/errors.ts","../src/server/http-client.ts","../src/server/webhooks.ts","../src/server/index.ts"],"names":[],"mappings":"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","file":"server.js","sourcesContent":["export const SDK_VERSION = '1.8.0';\r\nexport const DEFAULT_WIDGET_URL = 'https://widget.flonk.id';\r\nexport const DEFAULT_API_BASE = 'https://api.flonk.id/v1';\r\n\r\nexport const WIDGET_EVENTS = {\r\n READY: 'KYC_WIDGET_READY',\r\n COMPLETE: 'KYC_COMPLETE',\r\n CANCEL: 'KYC_CANCEL',\r\n ERROR: 'KYC_ERROR',\r\n} as const;\r\n","export class FlonkError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly code: string,\r\n public readonly statusCode?: number,\r\n ) {\r\n super(message);\r\n this.name = 'FlonkError';\r\n }\r\n}\r\n\r\nexport class FlonkAPIError extends FlonkError {\r\n constructor(\r\n message: string,\r\n statusCode: number,\r\n public readonly body?: unknown,\r\n ) {\r\n super(message, 'api_error', statusCode);\r\n this.name = 'FlonkAPIError';\r\n }\r\n}\r\n\r\nexport class FlonkAuthenticationError extends FlonkError {\r\n constructor(message = 'Invalid or missing secret key') {\r\n super(message, 'authentication_error', 401);\r\n this.name = 'FlonkAuthenticationError';\r\n }\r\n}\r\n\r\nexport class FlonkValidationError extends FlonkError {\r\n constructor(message: string) {\r\n super(message, 'validation_error', 400);\r\n this.name = 'FlonkValidationError';\r\n }\r\n}\r\n\r\nexport class FlonkWebhookSignatureError extends FlonkError {\r\n constructor(message = 'Invalid webhook signature') {\r\n super(message, 'webhook_signature_error');\r\n this.name = 'FlonkWebhookSignatureError';\r\n }\r\n}\r\n","import { SDK_VERSION } from '../shared/constants';\r\nimport { FlonkAPIError, FlonkAuthenticationError } from '../shared/errors';\r\n\r\nexport class HttpClient {\r\n constructor(\r\n private readonly baseUrl: string,\r\n private readonly secretKey: string,\r\n private readonly timeout = 30_000,\r\n ) {}\r\n\r\n async get<T>(path: string): Promise<T> {\r\n return this.request<T>('GET', path);\r\n }\r\n\r\n async post<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('POST', path, body);\r\n }\r\n\r\n async patch<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('PATCH', path, body);\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers: {\r\n 'Authorization': `Bearer ${this.secretKey}`,\r\n 'Content-Type': 'application/json',\r\n 'User-Agent': `flonk-kyc-node/${SDK_VERSION}`,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n const json = await res.json().catch(() => null);\r\n\r\n if (!res.ok) {\r\n if (res.status === 401) throw new FlonkAuthenticationError();\r\n throw new FlonkAPIError(\r\n json?.message || `Request failed: ${res.status}`,\r\n res.status,\r\n json,\r\n );\r\n }\r\n\r\n return json as T;\r\n } catch (err) {\r\n if (err instanceof FlonkAPIError || err instanceof FlonkAuthenticationError) throw err;\r\n throw new FlonkAPIError((err as Error).message, 0);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n}\r\n","import * as crypto from 'crypto';\r\nimport { FlonkWebhookSignatureError } from '../shared/errors';\r\nimport type { WebhookEvent, WebhookVerifyOptions } from '../shared/types';\r\n\r\nexport class Webhooks {\r\n /**\r\n * Verify X-Signature-256 header: \"sha256=<hex>\"\r\n */\r\n verifySignature(payload: string, signature: string, secret: string): WebhookEvent {\r\n const expected =\r\n 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');\r\n\r\n if (!this.safeEqual(signature, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Verify Stripe-like header: \"t=<unix>, v1=<hex>\"\r\n */\r\n verifyTimestampSignature(\r\n payload: string,\r\n header: string,\r\n secret: string,\r\n options?: WebhookVerifyOptions,\r\n ): WebhookEvent {\r\n const maxSkew = options?.maxSkewSeconds ?? 300;\r\n const parts = this.parseHeader(header);\r\n const ts = Number(parts['t']);\r\n const v1 = parts['v1'];\r\n\r\n if (!ts || !v1) {\r\n throw new FlonkWebhookSignatureError('Missing timestamp or signature');\r\n }\r\n\r\n if (Math.abs(Math.floor(Date.now() / 1000) - ts) > maxSkew) {\r\n throw new FlonkWebhookSignatureError(`Timestamp skew exceeds ${maxSkew}s`);\r\n }\r\n\r\n const expected = crypto\r\n .createHmac('sha256', secret)\r\n .update(`${ts}.${payload}`)\r\n .digest('hex');\r\n\r\n if (!this.safeEqual(v1, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Auto-detect signature format and verify.\r\n */\r\n constructEvent(payload: string, signature: string, secret: string): WebhookEvent {\r\n if (signature.startsWith('sha256=')) {\r\n return this.verifySignature(payload, signature, secret);\r\n }\r\n if (signature.includes('t=') && signature.includes('v1=')) {\r\n return this.verifyTimestampSignature(payload, signature, secret);\r\n }\r\n throw new FlonkWebhookSignatureError('Unrecognized signature format');\r\n }\r\n\r\n private parsePayload(payload: string): WebhookEvent {\r\n try {\r\n return JSON.parse(payload) as WebhookEvent;\r\n } catch {\r\n throw new FlonkWebhookSignatureError('Malformed JSON payload');\r\n }\r\n }\r\n\r\n private parseHeader(header: string): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n for (const part of header.split(',')) {\r\n const [k, v] = part.trim().split('=');\r\n if (k && v) result[k] = v;\r\n }\r\n return result;\r\n }\r\n\r\n private safeEqual(a: string, b: string): boolean {\r\n if (a.length !== b.length) return false;\r\n return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));\r\n }\r\n}\r\n","import { SDK_VERSION, DEFAULT_API_BASE } from '../shared/constants';\r\nimport { FlonkAuthenticationError, FlonkValidationError } from '../shared/errors';\r\nimport type {\r\n FlonkKYCServerOptions,\r\n CreateSessionParams,\r\n Session,\r\n SessionDetails,\r\n UpdateSessionParams,\r\n} from '../shared/types';\r\nimport { HttpClient } from './http-client';\r\nimport { Webhooks } from './webhooks';\r\n\r\nconst SK_PATTERN = /^sk_(live|sandbox|test_sandbox|test_live)_[A-Za-z0-9]{16,}$/;\r\n\r\nexport class FlonkKYCServer {\r\n static readonly version = SDK_VERSION;\r\n\r\n private readonly http: HttpClient;\r\n public readonly webhooks = new Webhooks();\r\n\r\n constructor(options: FlonkKYCServerOptions) {\r\n if (!options.secretKey) throw new FlonkAuthenticationError('secretKey is required');\r\n if (!SK_PATTERN.test(options.secretKey)) {\r\n throw new FlonkAuthenticationError('Invalid secret key format. Expected: sk_live_*, sk_sandbox_*, sk_test_sandbox_*, sk_test_live_*');\r\n }\r\n\r\n const base = (options.apiBase || DEFAULT_API_BASE).replace(/\\/$/, '');\r\n this.http = new HttpClient(base, options.secretKey, options.timeout);\r\n }\r\n\r\n async createSession(params?: CreateSessionParams): Promise<Session> {\r\n return this.http.post<Session>('/sessions', params ?? {});\r\n }\r\n\r\n async getSession(sessionId: string): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.get<SessionDetails>(`/sessions/${sessionId}`);\r\n }\r\n\r\n async updateSession(sessionId: string, params: UpdateSessionParams): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.patch<SessionDetails>(`/sessions/${sessionId}`, params);\r\n }\r\n}\r\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -11,9 +11,15 @@ interface WidgetInitConfig {
|
|
|
11
11
|
* Your project's publishable key (`pk_live_*` or `pk_sandbox_*`).
|
|
12
12
|
* Found in Dashboard → Project Settings → API Keys.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* Enables an instant branded loading screen: the brand color is resolved
|
|
15
|
+
* directly from the key (a Redis-cached read) in parallel with session
|
|
16
|
+
* setup, so the loader paints your color on first frame instead of waiting
|
|
17
|
+
* on the session. Works with both flows:
|
|
18
|
+
* - `serverUrl` (your backend creates the session), and
|
|
19
|
+
* - `sessionId` + `embedToken` (you pass a pre-created session).
|
|
20
|
+
*
|
|
21
|
+
* Without it, branding is resolved from the session and the loader shows
|
|
22
|
+
* the default color until that request returns. Recommended for the best UX.
|
|
17
23
|
*/
|
|
18
24
|
publishableKey?: string;
|
|
19
25
|
sessionId?: string;
|
package/package.json
CHANGED