@flonkid/kyc 1.5.1 → 1.6.1

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.
@@ -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":["crypto"],"mappings":"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","file":"server.cjs","sourcesContent":["export const SDK_VERSION = '1.5.1';\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":["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"]}
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.5.1";
99
+ static readonly version = "1.6.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.5.1";
99
+ static readonly version = "1.6.0";
100
100
  private readonly http;
101
101
  readonly webhooks: Webhooks;
102
102
  constructor(options: FlonkKYCServerOptions);
package/dist/server.js CHANGED
@@ -1,38 +1,56 @@
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
+
3
6
  // src/shared/constants.ts
4
- var SDK_VERSION = "1.5.1";
7
+ var SDK_VERSION = "1.6.0";
5
8
  var DEFAULT_API_BASE = "https://api.flonk.id/v1";
6
9
 
7
10
  // src/shared/errors.ts
8
11
  var FlonkError = class extends Error {
12
+ static {
13
+ __name(this, "FlonkError");
14
+ }
15
+ code;
16
+ statusCode;
9
17
  constructor(message, code, statusCode) {
10
- super(message);
11
- this.code = code;
12
- this.statusCode = statusCode;
18
+ super(message), this.code = code, this.statusCode = statusCode;
13
19
  this.name = "FlonkError";
14
20
  }
15
21
  };
16
22
  var FlonkAPIError = class extends FlonkError {
23
+ static {
24
+ __name(this, "FlonkAPIError");
25
+ }
26
+ body;
17
27
  constructor(message, statusCode, body) {
18
- super(message, "api_error", statusCode);
19
- this.body = body;
28
+ super(message, "api_error", statusCode), this.body = body;
20
29
  this.name = "FlonkAPIError";
21
30
  }
22
31
  };
23
32
  var FlonkAuthenticationError = class extends FlonkError {
33
+ static {
34
+ __name(this, "FlonkAuthenticationError");
35
+ }
24
36
  constructor(message = "Invalid or missing secret key") {
25
37
  super(message, "authentication_error", 401);
26
38
  this.name = "FlonkAuthenticationError";
27
39
  }
28
40
  };
29
41
  var FlonkValidationError = class extends FlonkError {
42
+ static {
43
+ __name(this, "FlonkValidationError");
44
+ }
30
45
  constructor(message) {
31
46
  super(message, "validation_error", 400);
32
47
  this.name = "FlonkValidationError";
33
48
  }
34
49
  };
35
50
  var FlonkWebhookSignatureError = class extends FlonkError {
51
+ static {
52
+ __name(this, "FlonkWebhookSignatureError");
53
+ }
36
54
  constructor(message = "Invalid webhook signature") {
37
55
  super(message, "webhook_signature_error");
38
56
  this.name = "FlonkWebhookSignatureError";
@@ -41,6 +59,12 @@ var FlonkWebhookSignatureError = class extends FlonkError {
41
59
 
42
60
  // src/server/http-client.ts
43
61
  var HttpClient = class {
62
+ static {
63
+ __name(this, "HttpClient");
64
+ }
65
+ baseUrl;
66
+ secretKey;
67
+ timeout;
44
68
  constructor(baseUrl, secretKey, timeout = 3e4) {
45
69
  this.baseUrl = baseUrl;
46
70
  this.secretKey = secretKey;
@@ -72,11 +96,7 @@ var HttpClient = class {
72
96
  const json = await res.json().catch(() => null);
73
97
  if (!res.ok) {
74
98
  if (res.status === 401) throw new FlonkAuthenticationError();
75
- throw new FlonkAPIError(
76
- json?.message || `Request failed: ${res.status}`,
77
- res.status,
78
- json
79
- );
99
+ throw new FlonkAPIError(json?.message || `Request failed: ${res.status}`, res.status, json);
80
100
  }
81
101
  return json;
82
102
  } catch (err) {
@@ -88,9 +108,12 @@ var HttpClient = class {
88
108
  }
89
109
  };
90
110
  var Webhooks = class {
111
+ static {
112
+ __name(this, "Webhooks");
113
+ }
91
114
  /**
92
- * Verify X-Signature-256 header: "sha256=<hex>"
93
- */
115
+ * Verify X-Signature-256 header: "sha256=<hex>"
116
+ */
94
117
  verifySignature(payload, signature, secret) {
95
118
  const expected = "sha256=" + crypto.createHmac("sha256", secret).update(payload).digest("hex");
96
119
  if (!this.safeEqual(signature, expected)) {
@@ -99,8 +122,8 @@ var Webhooks = class {
99
122
  return this.parsePayload(payload);
100
123
  }
101
124
  /**
102
- * Verify Stripe-like header: "t=<unix>, v1=<hex>"
103
- */
125
+ * Verify Stripe-like header: "t=<unix>, v1=<hex>"
126
+ */
104
127
  verifyTimestampSignature(payload, header, secret, options) {
105
128
  const maxSkew = options?.maxSkewSeconds ?? 300;
106
129
  const parts = this.parseHeader(header);
@@ -119,8 +142,8 @@ var Webhooks = class {
119
142
  return this.parsePayload(payload);
120
143
  }
121
144
  /**
122
- * Auto-detect signature format and verify.
123
- */
145
+ * Auto-detect signature format and verify.
146
+ */
124
147
  constructEvent(payload, signature, secret) {
125
148
  if (signature.startsWith("sha256=")) {
126
149
  return this.verifySignature(payload, signature, secret);
@@ -154,8 +177,13 @@ var Webhooks = class {
154
177
  // src/server/index.ts
155
178
  var SK_PATTERN = /^sk_(live|sandbox|test_sandbox|test_live)_[A-Za-z0-9]{16,}$/;
156
179
  var FlonkKYCServer = class {
180
+ static {
181
+ __name(this, "FlonkKYCServer");
182
+ }
183
+ static version = SDK_VERSION;
184
+ http;
185
+ webhooks = new Webhooks();
157
186
  constructor(options) {
158
- this.webhooks = new Webhooks();
159
187
  if (!options.secretKey) throw new FlonkAuthenticationError("secretKey is required");
160
188
  if (!SK_PATTERN.test(options.secretKey)) {
161
189
  throw new FlonkAuthenticationError("Invalid secret key format. Expected: sk_live_*, sk_sandbox_*, sk_test_sandbox_*, sk_test_live_*");
@@ -163,9 +191,6 @@ var FlonkKYCServer = class {
163
191
  const base = (options.apiBase || DEFAULT_API_BASE).replace(/\/$/, "");
164
192
  this.http = new HttpClient(base, options.secretKey, options.timeout);
165
193
  }
166
- static {
167
- this.version = SDK_VERSION;
168
- }
169
194
  async createSession(params) {
170
195
  return this.http.post("/sessions", params ?? {});
171
196
  }
@@ -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":[],"mappings":"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","file":"server.js","sourcesContent":["export const SDK_VERSION = '1.5.1';\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":["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"]}
package/dist/types.d.ts CHANGED
@@ -7,6 +7,14 @@ interface FlonkKYCOptions {
7
7
  }
8
8
  interface WidgetInitConfig {
9
9
  serverUrl?: string;
10
+ /**
11
+ * Your project's publishable key (`pk_live_*` or `pk_sandbox_*`).
12
+ * Found in Dashboard → Project Settings → API Keys.
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.
17
+ */
10
18
  publishableKey?: string;
11
19
  sessionId?: string;
12
20
  embedToken?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flonkid/kyc",
3
- "version": "1.5.1",
3
+ "version": "1.6.1",
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)",