@vivoa/partner-sdk 0.1.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/CHANGELOG.md +13 -0
- package/README.md +162 -0
- package/dist/cjs/adapters/fetch-transport.d.ts +7 -0
- package/dist/cjs/adapters/fetch-transport.js +34 -0
- package/dist/cjs/adapters/in-memory/fake-vivoa.d.ts +93 -0
- package/dist/cjs/adapters/in-memory/fake-vivoa.js +468 -0
- package/dist/cjs/adapters/manual-clock.d.ts +9 -0
- package/dist/cjs/adapters/manual-clock.js +20 -0
- package/dist/cjs/adapters/node-crypto.d.ts +2 -0
- package/dist/cjs/adapters/node-crypto.js +13 -0
- package/dist/cjs/adapters/system-clock.d.ts +2 -0
- package/dist/cjs/adapters/system-clock.js +7 -0
- package/dist/cjs/application/partner-client.d.ts +45 -0
- package/dist/cjs/application/partner-client.js +55 -0
- package/dist/cjs/application/resources/fleet.d.ts +7 -0
- package/dist/cjs/application/resources/fleet.js +13 -0
- package/dist/cjs/application/resources/me.d.ts +13 -0
- package/dist/cjs/application/resources/me.js +23 -0
- package/dist/cjs/application/resources/merchants.d.ts +37 -0
- package/dist/cjs/application/resources/merchants.js +92 -0
- package/dist/cjs/application/resources/webhooks.d.ts +16 -0
- package/dist/cjs/application/resources/webhooks.js +30 -0
- package/dist/cjs/application/signed-http.d.ts +41 -0
- package/dist/cjs/application/signed-http.js +105 -0
- package/dist/cjs/application/use-cases/provision-store.d.ts +50 -0
- package/dist/cjs/application/use-cases/provision-store.js +103 -0
- package/dist/cjs/domain/errors.d.ts +72 -0
- package/dist/cjs/domain/errors.js +111 -0
- package/dist/cjs/domain/merchant.d.ts +74 -0
- package/dist/cjs/domain/merchant.js +28 -0
- package/dist/cjs/domain/operator.d.ts +32 -0
- package/dist/cjs/domain/operator.js +6 -0
- package/dist/cjs/domain/signature.d.ts +21 -0
- package/dist/cjs/domain/signature.js +23 -0
- package/dist/cjs/domain/webhook.d.ts +48 -0
- package/dist/cjs/domain/webhook.js +10 -0
- package/dist/cjs/index.d.ts +25 -0
- package/dist/cjs/index.js +61 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/ports/clock.port.d.ts +5 -0
- package/dist/cjs/ports/clock.port.js +2 -0
- package/dist/cjs/ports/crypto.port.d.ts +7 -0
- package/dist/cjs/ports/crypto.port.js +2 -0
- package/dist/cjs/ports/http-transport.port.d.ts +25 -0
- package/dist/cjs/ports/http-transport.port.js +2 -0
- package/dist/cjs/ports/index.d.ts +5 -0
- package/dist/cjs/ports/index.js +5 -0
- package/dist/cjs/ports/logger.port.d.ts +6 -0
- package/dist/cjs/ports/logger.port.js +7 -0
- package/dist/cjs/testing.d.ts +12 -0
- package/dist/cjs/testing.js +16 -0
- package/dist/cjs/webhooks/verify-webhook.d.ts +21 -0
- package/dist/cjs/webhooks/verify-webhook.js +36 -0
- package/dist/esm/adapters/fetch-transport.d.ts +7 -0
- package/dist/esm/adapters/fetch-transport.js +30 -0
- package/dist/esm/adapters/in-memory/fake-vivoa.d.ts +93 -0
- package/dist/esm/adapters/in-memory/fake-vivoa.js +464 -0
- package/dist/esm/adapters/manual-clock.d.ts +9 -0
- package/dist/esm/adapters/manual-clock.js +16 -0
- package/dist/esm/adapters/node-crypto.d.ts +2 -0
- package/dist/esm/adapters/node-crypto.js +10 -0
- package/dist/esm/adapters/system-clock.d.ts +2 -0
- package/dist/esm/adapters/system-clock.js +4 -0
- package/dist/esm/application/partner-client.d.ts +45 -0
- package/dist/esm/application/partner-client.js +51 -0
- package/dist/esm/application/resources/fleet.d.ts +7 -0
- package/dist/esm/application/resources/fleet.js +9 -0
- package/dist/esm/application/resources/me.d.ts +13 -0
- package/dist/esm/application/resources/me.js +19 -0
- package/dist/esm/application/resources/merchants.d.ts +37 -0
- package/dist/esm/application/resources/merchants.js +87 -0
- package/dist/esm/application/resources/webhooks.d.ts +16 -0
- package/dist/esm/application/resources/webhooks.js +26 -0
- package/dist/esm/application/signed-http.d.ts +41 -0
- package/dist/esm/application/signed-http.js +101 -0
- package/dist/esm/application/use-cases/provision-store.d.ts +50 -0
- package/dist/esm/application/use-cases/provision-store.js +99 -0
- package/dist/esm/cli.d.ts +2 -0
- package/dist/esm/cli.js +106 -0
- package/dist/esm/domain/errors.d.ts +72 -0
- package/dist/esm/domain/errors.js +92 -0
- package/dist/esm/domain/merchant.d.ts +74 -0
- package/dist/esm/domain/merchant.js +23 -0
- package/dist/esm/domain/operator.d.ts +32 -0
- package/dist/esm/domain/operator.js +3 -0
- package/dist/esm/domain/signature.d.ts +21 -0
- package/dist/esm/domain/signature.js +19 -0
- package/dist/esm/domain/webhook.d.ts +48 -0
- package/dist/esm/domain/webhook.js +7 -0
- package/dist/esm/index.d.ts +25 -0
- package/dist/esm/index.js +33 -0
- package/dist/esm/ports/clock.port.d.ts +5 -0
- package/dist/esm/ports/clock.port.js +1 -0
- package/dist/esm/ports/crypto.port.d.ts +7 -0
- package/dist/esm/ports/crypto.port.js +1 -0
- package/dist/esm/ports/http-transport.port.d.ts +25 -0
- package/dist/esm/ports/http-transport.port.js +1 -0
- package/dist/esm/ports/index.d.ts +5 -0
- package/dist/esm/ports/index.js +1 -0
- package/dist/esm/ports/logger.port.d.ts +6 -0
- package/dist/esm/ports/logger.port.js +4 -0
- package/dist/esm/testing.d.ts +12 -0
- package/dist/esm/testing.js +11 -0
- package/dist/esm/webhooks/verify-webhook.d.ts +21 -0
- package/dist/esm/webhooks/verify-webhook.js +33 -0
- package/package.json +56 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@vivoa/partner-sdk/testing` — test your integration without touching the
|
|
3
|
+
* platform: plug `FakeVivoa` in as the transport and a `ManualClock` so polling
|
|
4
|
+
* and backoff run instantly.
|
|
5
|
+
*
|
|
6
|
+
* const clock = new ManualClock();
|
|
7
|
+
* const vivoa = new FakeVivoa({ clock, operators: [{ apiKey: 'k', apiSecret: 's' }] });
|
|
8
|
+
* const client = createPartnerClient({ apiKey: 'k', apiSecret: 's', transport: vivoa, clock });
|
|
9
|
+
*/
|
|
10
|
+
export { FakeVivoa } from "./adapters/in-memory/fake-vivoa.js";
|
|
11
|
+
export { ManualClock } from "./adapters/manual-clock.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CryptoProvider } from '../ports/crypto.port.ts';
|
|
2
|
+
import type { WebhookEvent } from '../domain/webhook.ts';
|
|
3
|
+
export interface VerifyWebhookParams {
|
|
4
|
+
/** The body EXACTLY as received — before any JSON parsing. */
|
|
5
|
+
rawBody: string | Uint8Array;
|
|
6
|
+
/** Value of the `X-Vivoa-Signature` header (`sha256=<hex>`). */
|
|
7
|
+
signatureHeader: string | null | undefined;
|
|
8
|
+
/** Signing secret returned by `webhooks.set()` / `webhooks.rotateSecret()`. */
|
|
9
|
+
signingSecret: string;
|
|
10
|
+
/**
|
|
11
|
+
* Reject events whose `sentAt` is older than this (replay window). Default
|
|
12
|
+
* 5 min; `0` disables the check.
|
|
13
|
+
*/
|
|
14
|
+
toleranceMs?: number;
|
|
15
|
+
nowMs?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Verifies and parses a Vivoa webhook. Throws `VivoaWebhookSignatureError` on
|
|
19
|
+
* any mismatch — respond 400/401 and do not process the event.
|
|
20
|
+
*/
|
|
21
|
+
export declare function verifyWebhook(crypto: CryptoProvider, params: VerifyWebhookParams): Promise<WebhookEvent>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { VivoaWebhookSignatureError } from "../domain/errors.js";
|
|
2
|
+
const DEFAULT_TOLERANCE_MS = 5 * 60_000;
|
|
3
|
+
/**
|
|
4
|
+
* Verifies and parses a Vivoa webhook. Throws `VivoaWebhookSignatureError` on
|
|
5
|
+
* any mismatch — respond 400/401 and do not process the event.
|
|
6
|
+
*/
|
|
7
|
+
export async function verifyWebhook(crypto, params) {
|
|
8
|
+
const raw = typeof params.rawBody === 'string' ? params.rawBody : new TextDecoder().decode(params.rawBody);
|
|
9
|
+
const header = params.signatureHeader?.trim();
|
|
10
|
+
if (!header?.startsWith('sha256=')) {
|
|
11
|
+
throw new VivoaWebhookSignatureError('Missing or malformed X-Vivoa-Signature header');
|
|
12
|
+
}
|
|
13
|
+
const expected = await crypto.hmacSha256Hex(params.signingSecret, raw);
|
|
14
|
+
if (!(await crypto.timingSafeEqualHex(expected, header.slice('sha256='.length)))) {
|
|
15
|
+
throw new VivoaWebhookSignatureError('Invalid webhook signature');
|
|
16
|
+
}
|
|
17
|
+
let event;
|
|
18
|
+
try {
|
|
19
|
+
event = JSON.parse(raw);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
throw new VivoaWebhookSignatureError('Signed body is not valid JSON');
|
|
23
|
+
}
|
|
24
|
+
const tolerance = params.toleranceMs ?? DEFAULT_TOLERANCE_MS;
|
|
25
|
+
if (tolerance > 0) {
|
|
26
|
+
const sentAt = Date.parse(event.sentAt);
|
|
27
|
+
const now = params.nowMs ?? Date.now();
|
|
28
|
+
if (!Number.isFinite(sentAt) || Math.abs(now - sentAt) > tolerance) {
|
|
29
|
+
throw new VivoaWebhookSignatureError('Webhook sentAt outside the tolerance window (possible replay)');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return event;
|
|
33
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vivoa/partner-sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official SDK for the Vivoa Partner API — create and operate stores for your merchants",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"packageManager": "pnpm@9.0.0",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/VivoaPlatform/partner-sdk.git"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["vivoa", "partner", "ecommerce", "sdk", "white-label"],
|
|
13
|
+
"main": "./dist/cjs/index.js",
|
|
14
|
+
"module": "./dist/esm/index.js",
|
|
15
|
+
"types": "./dist/esm/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"import": { "types": "./dist/esm/index.d.ts", "default": "./dist/esm/index.js" },
|
|
19
|
+
"require": { "types": "./dist/cjs/index.d.ts", "default": "./dist/cjs/index.js" }
|
|
20
|
+
},
|
|
21
|
+
"./testing": {
|
|
22
|
+
"import": { "types": "./dist/esm/testing.d.ts", "default": "./dist/esm/testing.js" },
|
|
23
|
+
"require": { "types": "./dist/cjs/testing.d.ts", "default": "./dist/cjs/testing.js" }
|
|
24
|
+
},
|
|
25
|
+
"./package.json": "./package.json"
|
|
26
|
+
},
|
|
27
|
+
"bin": {
|
|
28
|
+
"vivoa-partner": "./dist/esm/cli.js"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md",
|
|
33
|
+
"CHANGELOG.md"
|
|
34
|
+
],
|
|
35
|
+
"sideEffects": false,
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=22.18"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"registry": "https://registry.npmjs.org",
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.esm.json && tsc -p tsconfig.build.cjs.json && node scripts/mark-cjs.mjs",
|
|
45
|
+
"typecheck": "tsc -p tsconfig.test.json",
|
|
46
|
+
"test": "node --test \"test/**/*.test.ts\"",
|
|
47
|
+
"test:live": "VIVOA_LIVE=1 node --test test/contract/live.test.ts",
|
|
48
|
+
"test:dist": "node scripts/smoke-dist.mjs",
|
|
49
|
+
"cli": "node src/cli.ts",
|
|
50
|
+
"prepublishOnly": "pnpm run typecheck && pnpm run test && pnpm run build && pnpm run test:dist"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/node": "^22.10.7",
|
|
54
|
+
"typescript": "^5.8.3"
|
|
55
|
+
}
|
|
56
|
+
}
|