@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/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.6.0";
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), this.code = code, this.statusCode = statusCode;
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), this.body = body;
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(json?.message || `Request failed: ${res.status}`, res.status, json);
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
- * Verify X-Signature-256 header: "sha256=<hex>"
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
- * Verify Stripe-like header: "t=<unix>, v1=<hex>"
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
- * Auto-detect signature format and verify.
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
  }
@@ -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.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":"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","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
@@ -96,7 +96,7 @@ declare class Webhooks {
96
96
  }
97
97
 
98
98
  declare class FlonkKYCServer {
99
- static readonly version = "1.6.0";
99
+ static readonly version = "1.8.0";
100
100
  private readonly http;
101
101
  readonly webhooks: Webhooks;
102
102
  constructor(options: FlonkKYCServerOptions);
package/dist/server.d.ts CHANGED
@@ -96,7 +96,7 @@ declare class Webhooks {
96
96
  }
97
97
 
98
98
  declare class FlonkKYCServer {
99
- static readonly version = "1.6.0";
99
+ static readonly version = "1.8.0";
100
100
  private readonly http;
101
101
  readonly webhooks: Webhooks;
102
102
  constructor(options: FlonkKYCServerOptions);
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.6.0";
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), this.code = code, this.statusCode = statusCode;
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), this.body = body;
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(json?.message || `Request failed: ${res.status}`, res.status, json);
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
- * Verify X-Signature-256 header: "sha256=<hex>"
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
- * Verify Stripe-like header: "t=<unix>, v1=<hex>"
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
- * Auto-detect signature format and verify.
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
  }
@@ -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
- * When used with `serverUrl`, enables instant branded loading screen
15
- * by fetching design tokens in parallel with session creation.
16
- * Recommended for the best user experience.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flonkid/kyc",
3
- "version": "1.6.1",
3
+ "version": "1.8.0",
4
4
  "description": "Official Flonk KYC SDK — identity verification for any application",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Flonk.id — Dmytrii Popovych (dimon1936)",