vesant-sdk 1.2.0 → 1.3.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/{client-BWp5FI3x.d.ts → client-B6fUFAUM.d.mts} +2 -1
- package/dist/{client-BIfLMfuC.d.mts → client-DoczGA6L.d.ts} +2 -1
- package/dist/client-DzElM7u-.d.mts +238 -0
- package/dist/client-DzElM7u-.d.ts +238 -0
- package/dist/compliance/index.d.mts +5 -4
- package/dist/compliance/index.d.ts +5 -4
- package/dist/compliance/index.js +306 -98
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/index.mjs +306 -98
- package/dist/compliance/index.mjs.map +1 -1
- package/dist/decisions/index.d.mts +100 -0
- package/dist/decisions/index.d.ts +100 -0
- package/dist/decisions/index.js +607 -0
- package/dist/decisions/index.js.map +1 -0
- package/dist/decisions/index.mjs +605 -0
- package/dist/decisions/index.mjs.map +1 -0
- package/dist/geolocation/index.d.mts +4 -3
- package/dist/geolocation/index.d.ts +4 -3
- package/dist/geolocation/index.js +306 -98
- package/dist/geolocation/index.js.map +1 -1
- package/dist/geolocation/index.mjs +306 -98
- package/dist/geolocation/index.mjs.map +1 -1
- package/dist/index.d.mts +14 -6
- package/dist/index.d.ts +14 -6
- package/dist/index.js +641 -90
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +632 -91
- package/dist/index.mjs.map +1 -1
- package/dist/kyc/core.d.mts +3 -2
- package/dist/kyc/core.d.ts +3 -2
- package/dist/kyc/core.js +249 -29
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs +249 -29
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.d.mts +3 -2
- package/dist/kyc/index.d.ts +3 -2
- package/dist/kyc/index.js +249 -29
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs +249 -29
- package/dist/kyc/index.mjs.map +1 -1
- package/dist/react.d.mts +4 -3
- package/dist/react.d.ts +4 -3
- package/dist/react.js +1 -1
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +1 -1
- package/dist/react.mjs.map +1 -1
- package/dist/risk-profile/index.d.mts +4 -4
- package/dist/risk-profile/index.d.ts +4 -4
- package/dist/risk-profile/index.js +249 -29
- package/dist/risk-profile/index.js.map +1 -1
- package/dist/risk-profile/index.mjs +249 -29
- package/dist/risk-profile/index.mjs.map +1 -1
- package/dist/scores/index.d.mts +96 -0
- package/dist/scores/index.d.ts +96 -0
- package/dist/scores/index.js +594 -0
- package/dist/scores/index.js.map +1 -0
- package/dist/scores/index.mjs +591 -0
- package/dist/scores/index.mjs.map +1 -0
- package/dist/{types-DfHLp_tz.d.ts → types-DLC7Sfy5.d.ts} +1 -1
- package/dist/types-DZHongaK.d.mts +61 -0
- package/dist/types-DZHongaK.d.ts +61 -0
- package/dist/{types-DKCQN4C5.d.mts → types-jaLuzruy.d.mts} +1 -1
- package/dist/webhooks/index.d.mts +176 -0
- package/dist/webhooks/index.d.ts +176 -0
- package/dist/webhooks/index.js +193 -0
- package/dist/webhooks/index.js.map +1 -0
- package/dist/webhooks/index.mjs +188 -0
- package/dist/webhooks/index.mjs.map +1 -0
- package/package.json +16 -1
- package/dist/types-BpKxSXGF.d.mts +0 -177
- package/dist/types-BpKxSXGF.d.ts +0 -177
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/core/webhook-utils.ts
|
|
4
|
+
async function verifyWebhookSignature(payload, signature, secret) {
|
|
5
|
+
const hexDigest = await computeHmacSha256(payload, secret);
|
|
6
|
+
const expectedPrefixed = `sha256=${hexDigest}`;
|
|
7
|
+
if (signature.startsWith("sha256=")) {
|
|
8
|
+
return constantTimeEqual(signature, expectedPrefixed);
|
|
9
|
+
}
|
|
10
|
+
return constantTimeEqual(signature, hexDigest);
|
|
11
|
+
}
|
|
12
|
+
async function computeHmacSha256(message, secret) {
|
|
13
|
+
if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.subtle) {
|
|
14
|
+
const encoder = new TextEncoder();
|
|
15
|
+
const key = await globalThis.crypto.subtle.importKey(
|
|
16
|
+
"raw",
|
|
17
|
+
encoder.encode(secret),
|
|
18
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
19
|
+
false,
|
|
20
|
+
["sign"]
|
|
21
|
+
);
|
|
22
|
+
const sig = await globalThis.crypto.subtle.sign("HMAC", key, encoder.encode(message));
|
|
23
|
+
return Array.from(new Uint8Array(sig)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const { createHmac } = await import('crypto');
|
|
27
|
+
return createHmac("sha256", secret).update(message).digest("hex");
|
|
28
|
+
} catch {
|
|
29
|
+
throw new Error(
|
|
30
|
+
"No crypto implementation available. Requires Web Crypto API or Node.js crypto module."
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function constantTimeEqual(a, b) {
|
|
35
|
+
if (a.length !== b.length) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
let result = 0;
|
|
39
|
+
for (let i = 0; i < a.length; i++) {
|
|
40
|
+
result |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
41
|
+
}
|
|
42
|
+
return result === 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/webhooks/handler.ts
|
|
46
|
+
var WebhookHandler = class {
|
|
47
|
+
constructor(config) {
|
|
48
|
+
this.handlers = /* @__PURE__ */ new Map();
|
|
49
|
+
this.anyHandlers = [];
|
|
50
|
+
this.secret = config.secret;
|
|
51
|
+
this.tolerance = config.tolerance ?? 3e5;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Register a handler for a specific event type.
|
|
55
|
+
*/
|
|
56
|
+
on(eventType, handler) {
|
|
57
|
+
const existing = this.handlers.get(eventType) || [];
|
|
58
|
+
existing.push(handler);
|
|
59
|
+
this.handlers.set(eventType, existing);
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Register a catch-all handler for all event types.
|
|
64
|
+
*/
|
|
65
|
+
onAny(handler) {
|
|
66
|
+
this.anyHandlers.push(handler);
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Verify signature and parse the webhook body.
|
|
71
|
+
*/
|
|
72
|
+
async verifyAndParse(body, signature) {
|
|
73
|
+
const isValid = await verifyWebhookSignature(body, signature, this.secret);
|
|
74
|
+
if (!isValid) {
|
|
75
|
+
throw new Error("Invalid webhook signature");
|
|
76
|
+
}
|
|
77
|
+
return this.parseAndValidate(body);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Verify signature, parse, and dispatch to registered handlers.
|
|
81
|
+
*/
|
|
82
|
+
async handle(body, signature) {
|
|
83
|
+
const event = await this.verifyAndParse(body, signature);
|
|
84
|
+
await this.dispatch(event);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Parse an event without signature verification (for testing).
|
|
88
|
+
*/
|
|
89
|
+
parseEvent(body) {
|
|
90
|
+
return this.parseAndValidate(body);
|
|
91
|
+
}
|
|
92
|
+
parseAndValidate(body) {
|
|
93
|
+
const event = JSON.parse(body);
|
|
94
|
+
if (!event.type || !event.id || !event.timestamp) {
|
|
95
|
+
throw new Error("Invalid webhook event: missing required fields (type, id, timestamp)");
|
|
96
|
+
}
|
|
97
|
+
if (this.tolerance > 0) {
|
|
98
|
+
const eventTime = new Date(event.timestamp).getTime();
|
|
99
|
+
const now = Date.now();
|
|
100
|
+
if (Math.abs(now - eventTime) > this.tolerance) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
`Webhook event timestamp is outside tolerance window (${this.tolerance}ms)`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return event;
|
|
107
|
+
}
|
|
108
|
+
async dispatch(event) {
|
|
109
|
+
const typeHandlers = this.handlers.get(event.type) || [];
|
|
110
|
+
const allHandlers = [...typeHandlers, ...this.anyHandlers];
|
|
111
|
+
for (const handler of allHandlers) {
|
|
112
|
+
await handler(event);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// src/webhooks/middleware.ts
|
|
118
|
+
function createWebhookMiddleware(options) {
|
|
119
|
+
const handler = buildHandler(options);
|
|
120
|
+
const signatureHeader = options.signatureHeader || "x-webhook-signature";
|
|
121
|
+
return async (req, res, next) => {
|
|
122
|
+
try {
|
|
123
|
+
const body = typeof req.body === "string" ? req.body : req.body.toString("utf-8");
|
|
124
|
+
const signature = req.headers[signatureHeader];
|
|
125
|
+
if (!signature || typeof signature !== "string") {
|
|
126
|
+
res.status(401).json({ error: "Missing webhook signature" });
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
await handler.handle(body, signature);
|
|
130
|
+
res.status(200).json({ received: true });
|
|
131
|
+
} catch (error) {
|
|
132
|
+
const message = error instanceof Error ? error.message : "Webhook processing failed";
|
|
133
|
+
if (message.includes("signature")) {
|
|
134
|
+
res.status(401).json({ error: message });
|
|
135
|
+
} else if (message.includes("tolerance") || message.includes("timestamp")) {
|
|
136
|
+
res.status(400).json({ error: message });
|
|
137
|
+
} else if (next) {
|
|
138
|
+
next(error);
|
|
139
|
+
} else {
|
|
140
|
+
res.status(500).json({ error: message });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function createNextWebhookHandler(options) {
|
|
146
|
+
const handler = buildHandler(options);
|
|
147
|
+
const signatureHeader = options.signatureHeader || "x-webhook-signature";
|
|
148
|
+
return async (request) => {
|
|
149
|
+
try {
|
|
150
|
+
const body = await request.text();
|
|
151
|
+
const signature = request.headers.get(signatureHeader);
|
|
152
|
+
if (!signature) {
|
|
153
|
+
return new Response(JSON.stringify({ error: "Missing webhook signature" }), {
|
|
154
|
+
status: 401,
|
|
155
|
+
headers: { "Content-Type": "application/json" }
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
await handler.handle(body, signature);
|
|
159
|
+
return new Response(JSON.stringify({ received: true }), {
|
|
160
|
+
status: 200,
|
|
161
|
+
headers: { "Content-Type": "application/json" }
|
|
162
|
+
});
|
|
163
|
+
} catch (error) {
|
|
164
|
+
const message = error instanceof Error ? error.message : "Webhook processing failed";
|
|
165
|
+
const status = message.includes("signature") ? 401 : message.includes("tolerance") || message.includes("timestamp") ? 400 : 500;
|
|
166
|
+
return new Response(JSON.stringify({ error: message }), {
|
|
167
|
+
status,
|
|
168
|
+
headers: { "Content-Type": "application/json" }
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function buildHandler(options) {
|
|
174
|
+
const handler = new WebhookHandler(options);
|
|
175
|
+
if (options.handlers) {
|
|
176
|
+
for (const [eventType, eventHandler] of Object.entries(options.handlers)) {
|
|
177
|
+
if (eventHandler) {
|
|
178
|
+
handler.on(eventType, eventHandler);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (options.onAny) {
|
|
183
|
+
handler.onAny(options.onAny);
|
|
184
|
+
}
|
|
185
|
+
return handler;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
exports.WebhookHandler = WebhookHandler;
|
|
189
|
+
exports.createNextWebhookHandler = createNextWebhookHandler;
|
|
190
|
+
exports.createWebhookMiddleware = createWebhookMiddleware;
|
|
191
|
+
exports.verifyWebhookSignature = verifyWebhookSignature;
|
|
192
|
+
//# sourceMappingURL=index.js.map
|
|
193
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/webhook-utils.ts","../../src/webhooks/handler.ts","../../src/webhooks/middleware.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Webhook signature verification utilities.\n *\n * Supports both Web Crypto API (browsers, Deno, Cloudflare Workers)\n * and Node.js crypto module with automatic runtime detection.\n * Uses constant-time comparison to prevent timing attacks.\n */\n\n/**\n * Verify an HMAC-SHA256 webhook signature.\n *\n * @param payload - The raw request body string\n * @param signature - The signature from the webhook header\n * @param secret - The webhook signing secret\n * @returns true if the signature is valid\n */\nexport async function verifyWebhookSignature(\n payload: string,\n signature: string,\n secret: string\n): Promise<boolean> {\n const hexDigest = await computeHmacSha256(payload, secret);\n\n // Backend sends \"sha256=<hex>\" format — support both prefixed and raw signatures\n const expectedPrefixed = `sha256=${hexDigest}`;\n\n if (signature.startsWith('sha256=')) {\n return constantTimeEqual(signature, expectedPrefixed);\n }\n\n return constantTimeEqual(signature, hexDigest);\n}\n\n/**\n * Compute HMAC-SHA256 hex digest.\n * Automatically selects Web Crypto API or Node.js crypto.\n */\nasync function computeHmacSha256(message: string, secret: string): Promise<string> {\n // Try Web Crypto API first (browsers, Deno, Cloudflare Workers, Node 18+)\n if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.subtle) {\n const encoder = new TextEncoder();\n const key = await globalThis.crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n );\n const sig = await globalThis.crypto.subtle.sign('HMAC', key, encoder.encode(message));\n return Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n // Fallback to Node.js crypto module\n try {\n const { createHmac } = await import('crypto');\n return createHmac('sha256', secret).update(message).digest('hex');\n } catch {\n throw new Error(\n 'No crypto implementation available. Requires Web Crypto API or Node.js crypto module.'\n );\n }\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n */\nfunction constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n","/**\n * Webhook event handler with signature verification and typed dispatch.\n */\n\nimport { verifyWebhookSignature } from '../core/webhook-utils';\nimport type {\n WebhookEvent,\n WebhookEventType,\n WebhookEventHandler,\n WebhookAnyHandler,\n WebhookHandlerConfig,\n} from './types';\n\nexport class WebhookHandler {\n private handlers = new Map<WebhookEventType, WebhookEventHandler[]>();\n private anyHandlers: WebhookAnyHandler[] = [];\n private readonly secret: string;\n private readonly tolerance: number;\n\n constructor(config: WebhookHandlerConfig) {\n this.secret = config.secret;\n this.tolerance = config.tolerance ?? 300000; // 5 minutes\n }\n\n /**\n * Register a handler for a specific event type.\n */\n on<T extends WebhookEventType>(\n eventType: T,\n handler: WebhookEventHandler<T>\n ): this {\n const existing = this.handlers.get(eventType) || [];\n existing.push(handler as unknown as WebhookEventHandler);\n this.handlers.set(eventType, existing);\n return this;\n }\n\n /**\n * Register a catch-all handler for all event types.\n */\n onAny(handler: WebhookAnyHandler): this {\n this.anyHandlers.push(handler);\n return this;\n }\n\n /**\n * Verify signature and parse the webhook body.\n */\n async verifyAndParse(body: string, signature: string): Promise<WebhookEvent> {\n const isValid = await verifyWebhookSignature(body, signature, this.secret);\n if (!isValid) {\n throw new Error('Invalid webhook signature');\n }\n\n return this.parseAndValidate(body);\n }\n\n /**\n * Verify signature, parse, and dispatch to registered handlers.\n */\n async handle(body: string, signature: string): Promise<void> {\n const event = await this.verifyAndParse(body, signature);\n await this.dispatch(event);\n }\n\n /**\n * Parse an event without signature verification (for testing).\n */\n parseEvent(body: string): WebhookEvent {\n return this.parseAndValidate(body);\n }\n\n private parseAndValidate(body: string): WebhookEvent {\n const event = JSON.parse(body) as WebhookEvent;\n\n if (!event.type || !event.id || !event.timestamp) {\n throw new Error('Invalid webhook event: missing required fields (type, id, timestamp)');\n }\n\n // Timestamp tolerance check\n if (this.tolerance > 0) {\n const eventTime = new Date(event.timestamp).getTime();\n const now = Date.now();\n if (Math.abs(now - eventTime) > this.tolerance) {\n throw new Error(\n `Webhook event timestamp is outside tolerance window (${this.tolerance}ms)`\n );\n }\n }\n\n return event;\n }\n\n private async dispatch(event: WebhookEvent): Promise<void> {\n const typeHandlers = this.handlers.get(event.type) || [];\n const allHandlers = [...typeHandlers, ...this.anyHandlers];\n\n for (const handler of allHandlers) {\n await (handler as WebhookAnyHandler)(event);\n }\n }\n}\n","/**\n * Framework middleware helpers for webhook handling.\n *\n * Provides pre-built integrations for Express/Connect and Next.js App Router.\n */\n\nimport { WebhookHandler } from './handler';\nimport type { WebhookHandlerConfig, WebhookEventType, WebhookEventHandler, WebhookAnyHandler } from './types';\n\nexport interface WebhookMiddlewareOptions extends WebhookHandlerConfig {\n /** Event handlers to register */\n handlers?: Partial<Record<WebhookEventType, WebhookEventHandler>>;\n /** Catch-all handler */\n onAny?: WebhookAnyHandler;\n}\n\n/**\n * Create an Express/Connect-compatible middleware for webhook handling.\n *\n * Expects the raw body to be available as `req.body` (string).\n * Use `express.raw({ type: 'application/json' })` or similar middleware upstream.\n */\nexport function createWebhookMiddleware(options: WebhookMiddlewareOptions) {\n const handler = buildHandler(options);\n const signatureHeader = options.signatureHeader || 'x-webhook-signature';\n\n return async (\n req: { body: string | Buffer; headers: Record<string, string | string[] | undefined> },\n res: { status(code: number): { json(body: unknown): void }; json?(body: unknown): void },\n next?: (err?: unknown) => void\n ) => {\n try {\n const body = typeof req.body === 'string' ? req.body : req.body.toString('utf-8');\n const signature = req.headers[signatureHeader];\n\n if (!signature || typeof signature !== 'string') {\n res.status(401).json({ error: 'Missing webhook signature' });\n return;\n }\n\n await handler.handle(body, signature);\n res.status(200).json({ received: true });\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Webhook processing failed';\n\n if (message.includes('signature')) {\n res.status(401).json({ error: message });\n } else if (message.includes('tolerance') || message.includes('timestamp')) {\n res.status(400).json({ error: message });\n } else if (next) {\n next(error);\n } else {\n res.status(500).json({ error: message });\n }\n }\n };\n}\n\n/**\n * Create a Next.js App Router-compatible webhook handler.\n *\n * Returns an async function `(request: Request) => Promise<Response>`.\n */\nexport function createNextWebhookHandler(\n options: WebhookMiddlewareOptions\n): (request: Request) => Promise<Response> {\n const handler = buildHandler(options);\n const signatureHeader = options.signatureHeader || 'x-webhook-signature';\n\n return async (request: Request): Promise<Response> => {\n try {\n const body = await request.text();\n const signature = request.headers.get(signatureHeader);\n\n if (!signature) {\n return new Response(JSON.stringify({ error: 'Missing webhook signature' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n await handler.handle(body, signature);\n\n return new Response(JSON.stringify({ received: true }), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Webhook processing failed';\n const status = message.includes('signature')\n ? 401\n : message.includes('tolerance') || message.includes('timestamp')\n ? 400\n : 500;\n\n return new Response(JSON.stringify({ error: message }), {\n status,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n };\n}\n\nfunction buildHandler(options: WebhookMiddlewareOptions): WebhookHandler {\n const handler = new WebhookHandler(options);\n\n if (options.handlers) {\n for (const [eventType, eventHandler] of Object.entries(options.handlers)) {\n if (eventHandler) {\n handler.on(eventType as WebhookEventType, eventHandler);\n }\n }\n }\n\n if (options.onAny) {\n handler.onAny(options.onAny);\n }\n\n return handler;\n}\n"]}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// src/core/webhook-utils.ts
|
|
2
|
+
async function verifyWebhookSignature(payload, signature, secret) {
|
|
3
|
+
const hexDigest = await computeHmacSha256(payload, secret);
|
|
4
|
+
const expectedPrefixed = `sha256=${hexDigest}`;
|
|
5
|
+
if (signature.startsWith("sha256=")) {
|
|
6
|
+
return constantTimeEqual(signature, expectedPrefixed);
|
|
7
|
+
}
|
|
8
|
+
return constantTimeEqual(signature, hexDigest);
|
|
9
|
+
}
|
|
10
|
+
async function computeHmacSha256(message, secret) {
|
|
11
|
+
if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.subtle) {
|
|
12
|
+
const encoder = new TextEncoder();
|
|
13
|
+
const key = await globalThis.crypto.subtle.importKey(
|
|
14
|
+
"raw",
|
|
15
|
+
encoder.encode(secret),
|
|
16
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
17
|
+
false,
|
|
18
|
+
["sign"]
|
|
19
|
+
);
|
|
20
|
+
const sig = await globalThis.crypto.subtle.sign("HMAC", key, encoder.encode(message));
|
|
21
|
+
return Array.from(new Uint8Array(sig)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const { createHmac } = await import('crypto');
|
|
25
|
+
return createHmac("sha256", secret).update(message).digest("hex");
|
|
26
|
+
} catch {
|
|
27
|
+
throw new Error(
|
|
28
|
+
"No crypto implementation available. Requires Web Crypto API or Node.js crypto module."
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function constantTimeEqual(a, b) {
|
|
33
|
+
if (a.length !== b.length) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
let result = 0;
|
|
37
|
+
for (let i = 0; i < a.length; i++) {
|
|
38
|
+
result |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
39
|
+
}
|
|
40
|
+
return result === 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/webhooks/handler.ts
|
|
44
|
+
var WebhookHandler = class {
|
|
45
|
+
constructor(config) {
|
|
46
|
+
this.handlers = /* @__PURE__ */ new Map();
|
|
47
|
+
this.anyHandlers = [];
|
|
48
|
+
this.secret = config.secret;
|
|
49
|
+
this.tolerance = config.tolerance ?? 3e5;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Register a handler for a specific event type.
|
|
53
|
+
*/
|
|
54
|
+
on(eventType, handler) {
|
|
55
|
+
const existing = this.handlers.get(eventType) || [];
|
|
56
|
+
existing.push(handler);
|
|
57
|
+
this.handlers.set(eventType, existing);
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Register a catch-all handler for all event types.
|
|
62
|
+
*/
|
|
63
|
+
onAny(handler) {
|
|
64
|
+
this.anyHandlers.push(handler);
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Verify signature and parse the webhook body.
|
|
69
|
+
*/
|
|
70
|
+
async verifyAndParse(body, signature) {
|
|
71
|
+
const isValid = await verifyWebhookSignature(body, signature, this.secret);
|
|
72
|
+
if (!isValid) {
|
|
73
|
+
throw new Error("Invalid webhook signature");
|
|
74
|
+
}
|
|
75
|
+
return this.parseAndValidate(body);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Verify signature, parse, and dispatch to registered handlers.
|
|
79
|
+
*/
|
|
80
|
+
async handle(body, signature) {
|
|
81
|
+
const event = await this.verifyAndParse(body, signature);
|
|
82
|
+
await this.dispatch(event);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Parse an event without signature verification (for testing).
|
|
86
|
+
*/
|
|
87
|
+
parseEvent(body) {
|
|
88
|
+
return this.parseAndValidate(body);
|
|
89
|
+
}
|
|
90
|
+
parseAndValidate(body) {
|
|
91
|
+
const event = JSON.parse(body);
|
|
92
|
+
if (!event.type || !event.id || !event.timestamp) {
|
|
93
|
+
throw new Error("Invalid webhook event: missing required fields (type, id, timestamp)");
|
|
94
|
+
}
|
|
95
|
+
if (this.tolerance > 0) {
|
|
96
|
+
const eventTime = new Date(event.timestamp).getTime();
|
|
97
|
+
const now = Date.now();
|
|
98
|
+
if (Math.abs(now - eventTime) > this.tolerance) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
`Webhook event timestamp is outside tolerance window (${this.tolerance}ms)`
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return event;
|
|
105
|
+
}
|
|
106
|
+
async dispatch(event) {
|
|
107
|
+
const typeHandlers = this.handlers.get(event.type) || [];
|
|
108
|
+
const allHandlers = [...typeHandlers, ...this.anyHandlers];
|
|
109
|
+
for (const handler of allHandlers) {
|
|
110
|
+
await handler(event);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// src/webhooks/middleware.ts
|
|
116
|
+
function createWebhookMiddleware(options) {
|
|
117
|
+
const handler = buildHandler(options);
|
|
118
|
+
const signatureHeader = options.signatureHeader || "x-webhook-signature";
|
|
119
|
+
return async (req, res, next) => {
|
|
120
|
+
try {
|
|
121
|
+
const body = typeof req.body === "string" ? req.body : req.body.toString("utf-8");
|
|
122
|
+
const signature = req.headers[signatureHeader];
|
|
123
|
+
if (!signature || typeof signature !== "string") {
|
|
124
|
+
res.status(401).json({ error: "Missing webhook signature" });
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
await handler.handle(body, signature);
|
|
128
|
+
res.status(200).json({ received: true });
|
|
129
|
+
} catch (error) {
|
|
130
|
+
const message = error instanceof Error ? error.message : "Webhook processing failed";
|
|
131
|
+
if (message.includes("signature")) {
|
|
132
|
+
res.status(401).json({ error: message });
|
|
133
|
+
} else if (message.includes("tolerance") || message.includes("timestamp")) {
|
|
134
|
+
res.status(400).json({ error: message });
|
|
135
|
+
} else if (next) {
|
|
136
|
+
next(error);
|
|
137
|
+
} else {
|
|
138
|
+
res.status(500).json({ error: message });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function createNextWebhookHandler(options) {
|
|
144
|
+
const handler = buildHandler(options);
|
|
145
|
+
const signatureHeader = options.signatureHeader || "x-webhook-signature";
|
|
146
|
+
return async (request) => {
|
|
147
|
+
try {
|
|
148
|
+
const body = await request.text();
|
|
149
|
+
const signature = request.headers.get(signatureHeader);
|
|
150
|
+
if (!signature) {
|
|
151
|
+
return new Response(JSON.stringify({ error: "Missing webhook signature" }), {
|
|
152
|
+
status: 401,
|
|
153
|
+
headers: { "Content-Type": "application/json" }
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
await handler.handle(body, signature);
|
|
157
|
+
return new Response(JSON.stringify({ received: true }), {
|
|
158
|
+
status: 200,
|
|
159
|
+
headers: { "Content-Type": "application/json" }
|
|
160
|
+
});
|
|
161
|
+
} catch (error) {
|
|
162
|
+
const message = error instanceof Error ? error.message : "Webhook processing failed";
|
|
163
|
+
const status = message.includes("signature") ? 401 : message.includes("tolerance") || message.includes("timestamp") ? 400 : 500;
|
|
164
|
+
return new Response(JSON.stringify({ error: message }), {
|
|
165
|
+
status,
|
|
166
|
+
headers: { "Content-Type": "application/json" }
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function buildHandler(options) {
|
|
172
|
+
const handler = new WebhookHandler(options);
|
|
173
|
+
if (options.handlers) {
|
|
174
|
+
for (const [eventType, eventHandler] of Object.entries(options.handlers)) {
|
|
175
|
+
if (eventHandler) {
|
|
176
|
+
handler.on(eventType, eventHandler);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (options.onAny) {
|
|
181
|
+
handler.onAny(options.onAny);
|
|
182
|
+
}
|
|
183
|
+
return handler;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export { WebhookHandler, createNextWebhookHandler, createWebhookMiddleware, verifyWebhookSignature };
|
|
187
|
+
//# sourceMappingURL=index.mjs.map
|
|
188
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/webhook-utils.ts","../../src/webhooks/handler.ts","../../src/webhooks/middleware.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Webhook signature verification utilities.\n *\n * Supports both Web Crypto API (browsers, Deno, Cloudflare Workers)\n * and Node.js crypto module with automatic runtime detection.\n * Uses constant-time comparison to prevent timing attacks.\n */\n\n/**\n * Verify an HMAC-SHA256 webhook signature.\n *\n * @param payload - The raw request body string\n * @param signature - The signature from the webhook header\n * @param secret - The webhook signing secret\n * @returns true if the signature is valid\n */\nexport async function verifyWebhookSignature(\n payload: string,\n signature: string,\n secret: string\n): Promise<boolean> {\n const hexDigest = await computeHmacSha256(payload, secret);\n\n // Backend sends \"sha256=<hex>\" format — support both prefixed and raw signatures\n const expectedPrefixed = `sha256=${hexDigest}`;\n\n if (signature.startsWith('sha256=')) {\n return constantTimeEqual(signature, expectedPrefixed);\n }\n\n return constantTimeEqual(signature, hexDigest);\n}\n\n/**\n * Compute HMAC-SHA256 hex digest.\n * Automatically selects Web Crypto API or Node.js crypto.\n */\nasync function computeHmacSha256(message: string, secret: string): Promise<string> {\n // Try Web Crypto API first (browsers, Deno, Cloudflare Workers, Node 18+)\n if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.subtle) {\n const encoder = new TextEncoder();\n const key = await globalThis.crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n );\n const sig = await globalThis.crypto.subtle.sign('HMAC', key, encoder.encode(message));\n return Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n // Fallback to Node.js crypto module\n try {\n const { createHmac } = await import('crypto');\n return createHmac('sha256', secret).update(message).digest('hex');\n } catch {\n throw new Error(\n 'No crypto implementation available. Requires Web Crypto API or Node.js crypto module.'\n );\n }\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n */\nfunction constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n","/**\n * Webhook event handler with signature verification and typed dispatch.\n */\n\nimport { verifyWebhookSignature } from '../core/webhook-utils';\nimport type {\n WebhookEvent,\n WebhookEventType,\n WebhookEventHandler,\n WebhookAnyHandler,\n WebhookHandlerConfig,\n} from './types';\n\nexport class WebhookHandler {\n private handlers = new Map<WebhookEventType, WebhookEventHandler[]>();\n private anyHandlers: WebhookAnyHandler[] = [];\n private readonly secret: string;\n private readonly tolerance: number;\n\n constructor(config: WebhookHandlerConfig) {\n this.secret = config.secret;\n this.tolerance = config.tolerance ?? 300000; // 5 minutes\n }\n\n /**\n * Register a handler for a specific event type.\n */\n on<T extends WebhookEventType>(\n eventType: T,\n handler: WebhookEventHandler<T>\n ): this {\n const existing = this.handlers.get(eventType) || [];\n existing.push(handler as unknown as WebhookEventHandler);\n this.handlers.set(eventType, existing);\n return this;\n }\n\n /**\n * Register a catch-all handler for all event types.\n */\n onAny(handler: WebhookAnyHandler): this {\n this.anyHandlers.push(handler);\n return this;\n }\n\n /**\n * Verify signature and parse the webhook body.\n */\n async verifyAndParse(body: string, signature: string): Promise<WebhookEvent> {\n const isValid = await verifyWebhookSignature(body, signature, this.secret);\n if (!isValid) {\n throw new Error('Invalid webhook signature');\n }\n\n return this.parseAndValidate(body);\n }\n\n /**\n * Verify signature, parse, and dispatch to registered handlers.\n */\n async handle(body: string, signature: string): Promise<void> {\n const event = await this.verifyAndParse(body, signature);\n await this.dispatch(event);\n }\n\n /**\n * Parse an event without signature verification (for testing).\n */\n parseEvent(body: string): WebhookEvent {\n return this.parseAndValidate(body);\n }\n\n private parseAndValidate(body: string): WebhookEvent {\n const event = JSON.parse(body) as WebhookEvent;\n\n if (!event.type || !event.id || !event.timestamp) {\n throw new Error('Invalid webhook event: missing required fields (type, id, timestamp)');\n }\n\n // Timestamp tolerance check\n if (this.tolerance > 0) {\n const eventTime = new Date(event.timestamp).getTime();\n const now = Date.now();\n if (Math.abs(now - eventTime) > this.tolerance) {\n throw new Error(\n `Webhook event timestamp is outside tolerance window (${this.tolerance}ms)`\n );\n }\n }\n\n return event;\n }\n\n private async dispatch(event: WebhookEvent): Promise<void> {\n const typeHandlers = this.handlers.get(event.type) || [];\n const allHandlers = [...typeHandlers, ...this.anyHandlers];\n\n for (const handler of allHandlers) {\n await (handler as WebhookAnyHandler)(event);\n }\n }\n}\n","/**\n * Framework middleware helpers for webhook handling.\n *\n * Provides pre-built integrations for Express/Connect and Next.js App Router.\n */\n\nimport { WebhookHandler } from './handler';\nimport type { WebhookHandlerConfig, WebhookEventType, WebhookEventHandler, WebhookAnyHandler } from './types';\n\nexport interface WebhookMiddlewareOptions extends WebhookHandlerConfig {\n /** Event handlers to register */\n handlers?: Partial<Record<WebhookEventType, WebhookEventHandler>>;\n /** Catch-all handler */\n onAny?: WebhookAnyHandler;\n}\n\n/**\n * Create an Express/Connect-compatible middleware for webhook handling.\n *\n * Expects the raw body to be available as `req.body` (string).\n * Use `express.raw({ type: 'application/json' })` or similar middleware upstream.\n */\nexport function createWebhookMiddleware(options: WebhookMiddlewareOptions) {\n const handler = buildHandler(options);\n const signatureHeader = options.signatureHeader || 'x-webhook-signature';\n\n return async (\n req: { body: string | Buffer; headers: Record<string, string | string[] | undefined> },\n res: { status(code: number): { json(body: unknown): void }; json?(body: unknown): void },\n next?: (err?: unknown) => void\n ) => {\n try {\n const body = typeof req.body === 'string' ? req.body : req.body.toString('utf-8');\n const signature = req.headers[signatureHeader];\n\n if (!signature || typeof signature !== 'string') {\n res.status(401).json({ error: 'Missing webhook signature' });\n return;\n }\n\n await handler.handle(body, signature);\n res.status(200).json({ received: true });\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Webhook processing failed';\n\n if (message.includes('signature')) {\n res.status(401).json({ error: message });\n } else if (message.includes('tolerance') || message.includes('timestamp')) {\n res.status(400).json({ error: message });\n } else if (next) {\n next(error);\n } else {\n res.status(500).json({ error: message });\n }\n }\n };\n}\n\n/**\n * Create a Next.js App Router-compatible webhook handler.\n *\n * Returns an async function `(request: Request) => Promise<Response>`.\n */\nexport function createNextWebhookHandler(\n options: WebhookMiddlewareOptions\n): (request: Request) => Promise<Response> {\n const handler = buildHandler(options);\n const signatureHeader = options.signatureHeader || 'x-webhook-signature';\n\n return async (request: Request): Promise<Response> => {\n try {\n const body = await request.text();\n const signature = request.headers.get(signatureHeader);\n\n if (!signature) {\n return new Response(JSON.stringify({ error: 'Missing webhook signature' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n await handler.handle(body, signature);\n\n return new Response(JSON.stringify({ received: true }), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Webhook processing failed';\n const status = message.includes('signature')\n ? 401\n : message.includes('tolerance') || message.includes('timestamp')\n ? 400\n : 500;\n\n return new Response(JSON.stringify({ error: message }), {\n status,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n };\n}\n\nfunction buildHandler(options: WebhookMiddlewareOptions): WebhookHandler {\n const handler = new WebhookHandler(options);\n\n if (options.handlers) {\n for (const [eventType, eventHandler] of Object.entries(options.handlers)) {\n if (eventHandler) {\n handler.on(eventType as WebhookEventType, eventHandler);\n }\n }\n }\n\n if (options.onAny) {\n handler.onAny(options.onAny);\n }\n\n return handler;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vesant-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "TypeScript SDK for Vesant Compliance Platform - Geolocation, KYC, Risk Profiling, CipherText, and Compliance Orchestration",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -40,6 +40,21 @@
|
|
|
40
40
|
"types": "./dist/kyc/core.d.ts",
|
|
41
41
|
"import": "./dist/kyc/core.mjs",
|
|
42
42
|
"require": "./dist/kyc/core.js"
|
|
43
|
+
},
|
|
44
|
+
"./decisions": {
|
|
45
|
+
"types": "./dist/decisions/index.d.ts",
|
|
46
|
+
"import": "./dist/decisions/index.mjs",
|
|
47
|
+
"require": "./dist/decisions/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./webhooks": {
|
|
50
|
+
"types": "./dist/webhooks/index.d.ts",
|
|
51
|
+
"import": "./dist/webhooks/index.mjs",
|
|
52
|
+
"require": "./dist/webhooks/index.js"
|
|
53
|
+
},
|
|
54
|
+
"./scores": {
|
|
55
|
+
"types": "./dist/scores/index.d.ts",
|
|
56
|
+
"import": "./dist/scores/index.mjs",
|
|
57
|
+
"require": "./dist/scores/index.js"
|
|
43
58
|
}
|
|
44
59
|
},
|
|
45
60
|
"files": [
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configuration types for Vesant SDK clients
|
|
3
|
-
*/
|
|
4
|
-
interface Logger {
|
|
5
|
-
debug(message: string, meta?: Record<string, unknown>): void;
|
|
6
|
-
info(message: string, meta?: Record<string, unknown>): void;
|
|
7
|
-
warn(message: string, meta?: Record<string, unknown>): void;
|
|
8
|
-
error(message: string, meta?: Record<string, unknown>): void;
|
|
9
|
-
}
|
|
10
|
-
interface RequestOptions {
|
|
11
|
-
signal?: AbortSignal;
|
|
12
|
-
}
|
|
13
|
-
interface RequestInterceptor {
|
|
14
|
-
/** Called before each request. Can modify headers or options. */
|
|
15
|
-
onRequest?: (url: string, options: RequestInit) => RequestInit | Promise<RequestInit>;
|
|
16
|
-
/** Called after a successful response. Can inspect or transform data. */
|
|
17
|
-
onResponse?: (url: string, data: unknown) => unknown | Promise<unknown>;
|
|
18
|
-
/** Called when a request fails. Can handle or re-throw. */
|
|
19
|
-
onError?: (url: string, error: Error) => void | Promise<void>;
|
|
20
|
-
}
|
|
21
|
-
interface BaseClientConfig {
|
|
22
|
-
/** Base URL for the service */
|
|
23
|
-
baseURL: string;
|
|
24
|
-
/** Tenant ID for multi-tenancy */
|
|
25
|
-
tenantId: string;
|
|
26
|
-
/** Optional API key for authentication */
|
|
27
|
-
apiKey?: string;
|
|
28
|
-
/** Custom headers to include in all requests */
|
|
29
|
-
headers?: Record<string, string>;
|
|
30
|
-
/** Request timeout in milliseconds (default: 10000) */
|
|
31
|
-
timeout?: number;
|
|
32
|
-
/** Number of retry attempts (default: 3) */
|
|
33
|
-
retries?: number;
|
|
34
|
-
/** Enable debug logging (default: false) */
|
|
35
|
-
debug?: boolean;
|
|
36
|
-
/** Request/response interceptors */
|
|
37
|
-
interceptors?: RequestInterceptor[];
|
|
38
|
-
/** Custom logger instance */
|
|
39
|
-
logger?: Logger;
|
|
40
|
-
}
|
|
41
|
-
interface CGSConfig {
|
|
42
|
-
/** Base URL for the Vesant API */
|
|
43
|
-
baseURL: string;
|
|
44
|
-
/** Tenant ID for multi-tenancy */
|
|
45
|
-
tenantId: string;
|
|
46
|
-
/** Optional API key for authentication */
|
|
47
|
-
apiKey?: string;
|
|
48
|
-
/** Custom headers to include in all requests */
|
|
49
|
-
headers?: Record<string, string>;
|
|
50
|
-
/** Request timeout in milliseconds (default: 10000) */
|
|
51
|
-
timeout?: number;
|
|
52
|
-
/** Number of retry attempts for failed requests (default: 3) */
|
|
53
|
-
retries?: number;
|
|
54
|
-
/** Enable debug logging (default: false) */
|
|
55
|
-
debug?: boolean;
|
|
56
|
-
/** Automatically create customer profiles on geolocation verification (default: true) */
|
|
57
|
-
autoCreateProfiles?: boolean;
|
|
58
|
-
/** Sync mode: 'async' uses events, 'sync' uses direct API calls (default: 'sync') */
|
|
59
|
-
syncMode?: 'async' | 'sync';
|
|
60
|
-
/** Request/response interceptors */
|
|
61
|
-
interceptors?: RequestInterceptor[];
|
|
62
|
-
/** Custom logger instance */
|
|
63
|
-
logger?: Logger;
|
|
64
|
-
}
|
|
65
|
-
type RequiredCGSConfig = Required<CGSConfig>;
|
|
66
|
-
type RequiredBaseClientConfig = Required<BaseClientConfig>;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Base HTTP client for all CGS SDK clients
|
|
70
|
-
*
|
|
71
|
-
* Provides common functionality:
|
|
72
|
-
* - Request/response handling
|
|
73
|
-
* - Error handling
|
|
74
|
-
* - Retry logic with exponential backoff
|
|
75
|
-
* - Timeout management
|
|
76
|
-
* - Debug logging
|
|
77
|
-
*/
|
|
78
|
-
|
|
79
|
-
declare abstract class BaseClient {
|
|
80
|
-
protected config: RequiredBaseClientConfig;
|
|
81
|
-
protected logger: Logger;
|
|
82
|
-
private interceptors;
|
|
83
|
-
constructor(config: BaseClientConfig);
|
|
84
|
-
/**
|
|
85
|
-
* Make an HTTP request with timeout and error handling
|
|
86
|
-
*/
|
|
87
|
-
protected request<T>(endpoint: string, options?: RequestInit, serviceURL?: string, requestOptions?: RequestOptions): Promise<T>;
|
|
88
|
-
/**
|
|
89
|
-
* Make an HTTP request with retry logic
|
|
90
|
-
*/
|
|
91
|
-
protected requestWithRetry<T>(endpoint: string, options?: RequestInit, serviceURL?: string, retries?: number, requestOptions?: RequestOptions): Promise<T>;
|
|
92
|
-
/**
|
|
93
|
-
* Handle error responses from API
|
|
94
|
-
*/
|
|
95
|
-
protected handleErrorResponse(status: number, data: Record<string, unknown>): never;
|
|
96
|
-
/**
|
|
97
|
-
* Build query string from parameters
|
|
98
|
-
*/
|
|
99
|
-
protected buildQueryString(params: Record<string, unknown>): string;
|
|
100
|
-
/**
|
|
101
|
-
* Update client configuration
|
|
102
|
-
*/
|
|
103
|
-
updateConfig(config: Partial<BaseClientConfig>): void;
|
|
104
|
-
/**
|
|
105
|
-
* Get current configuration (readonly)
|
|
106
|
-
*/
|
|
107
|
-
getConfig(): Readonly<BaseClientConfig>;
|
|
108
|
-
/**
|
|
109
|
-
* Health check endpoint
|
|
110
|
-
*/
|
|
111
|
-
healthCheck(): Promise<{
|
|
112
|
-
status: string;
|
|
113
|
-
timestamp: string;
|
|
114
|
-
}>;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Shared types used across all CGS SDK modules
|
|
119
|
-
*/
|
|
120
|
-
interface APIResponse<T> {
|
|
121
|
-
data?: T;
|
|
122
|
-
error?: string;
|
|
123
|
-
message?: string;
|
|
124
|
-
}
|
|
125
|
-
interface PaginationParams {
|
|
126
|
-
page?: number;
|
|
127
|
-
page_size?: number;
|
|
128
|
-
}
|
|
129
|
-
interface PaginatedResponse<T> {
|
|
130
|
-
data: T[];
|
|
131
|
-
total: number;
|
|
132
|
-
page: number;
|
|
133
|
-
page_size: number;
|
|
134
|
-
total_pages: number;
|
|
135
|
-
}
|
|
136
|
-
interface SuccessResponse<T = unknown> {
|
|
137
|
-
success: true;
|
|
138
|
-
data: T;
|
|
139
|
-
message?: string;
|
|
140
|
-
}
|
|
141
|
-
interface ErrorResponse {
|
|
142
|
-
success: false;
|
|
143
|
-
error: string;
|
|
144
|
-
code?: string;
|
|
145
|
-
details?: Record<string, unknown>;
|
|
146
|
-
}
|
|
147
|
-
type Result<T> = SuccessResponse<T> | ErrorResponse;
|
|
148
|
-
/**
|
|
149
|
-
* Standard timestamp format: ISO 8601
|
|
150
|
-
*/
|
|
151
|
-
type Timestamp = string;
|
|
152
|
-
/**
|
|
153
|
-
* UUID format
|
|
154
|
-
*/
|
|
155
|
-
type UUID = string;
|
|
156
|
-
/**
|
|
157
|
-
* Risk levels used across the platform
|
|
158
|
-
*/
|
|
159
|
-
type RiskLevel = 'low' | 'medium' | 'high' | 'critical';
|
|
160
|
-
/**
|
|
161
|
-
* Customer status types
|
|
162
|
-
*/
|
|
163
|
-
type CustomerStatus = 'active' | 'dormant' | 'deactive' | 'suspended';
|
|
164
|
-
/**
|
|
165
|
-
* Entity types for customer profiles
|
|
166
|
-
*/
|
|
167
|
-
type EntityType = 'individual' | 'corporate' | 'joint_account' | 'minor_with_guardian';
|
|
168
|
-
/**
|
|
169
|
-
* Location compliance status
|
|
170
|
-
*/
|
|
171
|
-
type LocationCompliance = 'compliant' | 'non-compliant' | 'unknown';
|
|
172
|
-
/**
|
|
173
|
-
* Verification event types
|
|
174
|
-
*/
|
|
175
|
-
type VerificationEventType = 'registration' | 'login' | 'transaction' | 'withdrawal' | 'deposit' | 'api_access' | 'profile_update';
|
|
176
|
-
|
|
177
|
-
export { type APIResponse as A, BaseClient as B, type CustomerStatus as C, type EntityType as E, type LocationCompliance as L, type PaginationParams as P, type RequestOptions as R, type SuccessResponse as S, type Timestamp as T, type UUID as U, type VerificationEventType as V, type PaginatedResponse as a, type Logger as b, type RequestInterceptor as c, type BaseClientConfig as d, type CGSConfig as e, type RequiredCGSConfig as f, type RequiredBaseClientConfig as g, type ErrorResponse as h, type Result as i, type RiskLevel as j };
|