@labyrinthe/connect 0.0.0-stage → 1.2.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/next.cjs ADDED
@@ -0,0 +1,48 @@
1
+ 'use strict';
2
+
3
+ var connect = require('@labyrinthe/connect');
4
+
5
+ // src/next.ts
6
+ function labyrintheWebhookHandler(options) {
7
+ return async (request) => {
8
+ const secret = options.secret ?? readEnv("LABYRINTHE_WEBHOOK_SECRET");
9
+ if (secret === void 0 || secret === "") {
10
+ return json(500, { error: { code: "WEBHOOK_SECRET_MISSING", message: "No webhook secret configured." } });
11
+ }
12
+ let event;
13
+ try {
14
+ const rawBody = new Uint8Array(await request.arrayBuffer());
15
+ event = await connect.Webhooks.constructEvent(
16
+ rawBody,
17
+ request.headers.get("x-signature"),
18
+ secret,
19
+ options.toleranceSeconds === void 0 ? {} : { toleranceSeconds: options.toleranceSeconds }
20
+ );
21
+ } catch (error) {
22
+ if (error instanceof connect.SignatureVerificationError || error instanceof connect.InvalidWebhookPayloadError) {
23
+ return json(400, { error: { code: error.code, message: error.message } });
24
+ }
25
+ throw error;
26
+ }
27
+ try {
28
+ const result = await options.onEvent(event, request);
29
+ return result instanceof Response ? result : json(200, { received: true });
30
+ } catch (error) {
31
+ const logger = globalThis.console;
32
+ logger?.error?.("Labyrinthe webhook handler failed", { event: event.event, id: event.id }, error);
33
+ return json(500, { error: { code: "WEBHOOK_HANDLER_FAILED", message: "The webhook handler failed." } });
34
+ }
35
+ };
36
+ }
37
+ function json(status, body) {
38
+ return new Response(JSON.stringify(body), { status, headers: { "Content-Type": "application/json" } });
39
+ }
40
+ function readEnv(name) {
41
+ try {
42
+ return globalThis.process?.env?.[name];
43
+ } catch {
44
+ return void 0;
45
+ }
46
+ }
47
+
48
+ exports.labyrintheWebhookHandler = labyrintheWebhookHandler;
@@ -0,0 +1,31 @@
1
+ import { WebhookEvent } from '@labyrinthe/connect';
2
+ export { WebhookEvent } from '@labyrinthe/connect';
3
+
4
+ /**
5
+ * Webhook handler for Next.js App Router Route Handlers — and any runtime
6
+ * built on the Fetch API `Request` / `Response` (Vercel edge, Deno, Bun, Hono…).
7
+ *
8
+ * // app/api/webhooks/labyrinthe/route.ts
9
+ * import { labyrintheWebhookHandler } from '@labyrinthe/connect/next';
10
+ *
11
+ * export const POST = labyrintheWebhookHandler({
12
+ * secret: process.env.LABYRINTHE_WEBHOOK_SECRET!,
13
+ * onEvent: async (event) => { … },
14
+ * });
15
+ */
16
+
17
+ interface LabyrintheWebhookHandlerOptions {
18
+ /** Endpoint secret (client area > Developers > Webhooks). Defaults to `process.env.LABYRINTHE_WEBHOOK_SECRET`. */
19
+ secret?: string;
20
+ /** Max age of a delivery, in seconds (default 300; 0 disables the check). */
21
+ toleranceSeconds?: number;
22
+ /**
23
+ * Handles a verified event. Return nothing to answer 200, or your own
24
+ * `Response`. If it throws, the handler answers 500 and the delivery is
25
+ * retried later. Answer within 10 seconds: queue slow work.
26
+ */
27
+ onEvent: (event: WebhookEvent, request: Request) => unknown;
28
+ }
29
+ declare function labyrintheWebhookHandler(options: LabyrintheWebhookHandlerOptions): (request: Request) => Promise<Response>;
30
+
31
+ export { type LabyrintheWebhookHandlerOptions, labyrintheWebhookHandler };
package/dist/next.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { WebhookEvent } from '@labyrinthe/connect';
2
+ export { WebhookEvent } from '@labyrinthe/connect';
3
+
4
+ /**
5
+ * Webhook handler for Next.js App Router Route Handlers — and any runtime
6
+ * built on the Fetch API `Request` / `Response` (Vercel edge, Deno, Bun, Hono…).
7
+ *
8
+ * // app/api/webhooks/labyrinthe/route.ts
9
+ * import { labyrintheWebhookHandler } from '@labyrinthe/connect/next';
10
+ *
11
+ * export const POST = labyrintheWebhookHandler({
12
+ * secret: process.env.LABYRINTHE_WEBHOOK_SECRET!,
13
+ * onEvent: async (event) => { … },
14
+ * });
15
+ */
16
+
17
+ interface LabyrintheWebhookHandlerOptions {
18
+ /** Endpoint secret (client area > Developers > Webhooks). Defaults to `process.env.LABYRINTHE_WEBHOOK_SECRET`. */
19
+ secret?: string;
20
+ /** Max age of a delivery, in seconds (default 300; 0 disables the check). */
21
+ toleranceSeconds?: number;
22
+ /**
23
+ * Handles a verified event. Return nothing to answer 200, or your own
24
+ * `Response`. If it throws, the handler answers 500 and the delivery is
25
+ * retried later. Answer within 10 seconds: queue slow work.
26
+ */
27
+ onEvent: (event: WebhookEvent, request: Request) => unknown;
28
+ }
29
+ declare function labyrintheWebhookHandler(options: LabyrintheWebhookHandlerOptions): (request: Request) => Promise<Response>;
30
+
31
+ export { type LabyrintheWebhookHandlerOptions, labyrintheWebhookHandler };
package/dist/next.js ADDED
@@ -0,0 +1,46 @@
1
+ import { Webhooks, SignatureVerificationError, InvalidWebhookPayloadError } from '@labyrinthe/connect';
2
+
3
+ // src/next.ts
4
+ function labyrintheWebhookHandler(options) {
5
+ return async (request) => {
6
+ const secret = options.secret ?? readEnv("LABYRINTHE_WEBHOOK_SECRET");
7
+ if (secret === void 0 || secret === "") {
8
+ return json(500, { error: { code: "WEBHOOK_SECRET_MISSING", message: "No webhook secret configured." } });
9
+ }
10
+ let event;
11
+ try {
12
+ const rawBody = new Uint8Array(await request.arrayBuffer());
13
+ event = await Webhooks.constructEvent(
14
+ rawBody,
15
+ request.headers.get("x-signature"),
16
+ secret,
17
+ options.toleranceSeconds === void 0 ? {} : { toleranceSeconds: options.toleranceSeconds }
18
+ );
19
+ } catch (error) {
20
+ if (error instanceof SignatureVerificationError || error instanceof InvalidWebhookPayloadError) {
21
+ return json(400, { error: { code: error.code, message: error.message } });
22
+ }
23
+ throw error;
24
+ }
25
+ try {
26
+ const result = await options.onEvent(event, request);
27
+ return result instanceof Response ? result : json(200, { received: true });
28
+ } catch (error) {
29
+ const logger = globalThis.console;
30
+ logger?.error?.("Labyrinthe webhook handler failed", { event: event.event, id: event.id }, error);
31
+ return json(500, { error: { code: "WEBHOOK_HANDLER_FAILED", message: "The webhook handler failed." } });
32
+ }
33
+ };
34
+ }
35
+ function json(status, body) {
36
+ return new Response(JSON.stringify(body), { status, headers: { "Content-Type": "application/json" } });
37
+ }
38
+ function readEnv(name) {
39
+ try {
40
+ return globalThis.process?.env?.[name];
41
+ } catch {
42
+ return void 0;
43
+ }
44
+ }
45
+
46
+ export { labyrintheWebhookHandler };
package/package.json CHANGED
@@ -1,6 +1,121 @@
1
1
  {
2
2
  "name": "@labyrinthe/connect",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.2.0",
4
+ "description": "Official Node.js / TypeScript SDK for Labyrinthe Connect: send SMS and verify phone numbers with OTP (DR Congo, Central Africa).",
5
+ "keywords": [
6
+ "labyrinthe",
7
+ "sms",
8
+ "otp",
9
+ "2fa",
10
+ "verification",
11
+ "drc",
12
+ "congo",
13
+ "sdk"
14
+ ],
15
+ "homepage": "https://github.com/Labyrinthe-Team/labyrinthe-connect-sdks/tree/main/node#readme",
16
+ "bugs": {
17
+ "url": "https://github.com/Labyrinthe-Team/labyrinthe-connect-sdks/issues",
18
+ "email": "connect@labyrinthe-rdc.com"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/Labyrinthe-Team/labyrinthe-connect-sdks.git",
23
+ "directory": "node"
24
+ },
25
+ "license": "MIT",
26
+ "author": "Labyrinthe Connect <connect@labyrinthe-rdc.com>",
27
+ "type": "module",
28
+ "sideEffects": false,
29
+ "exports": {
30
+ ".": {
31
+ "import": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/index.d.cts",
37
+ "default": "./dist/index.cjs"
38
+ }
39
+ },
40
+ "./express": {
41
+ "import": {
42
+ "types": "./dist/express.d.ts",
43
+ "default": "./dist/express.js"
44
+ },
45
+ "require": {
46
+ "types": "./dist/express.d.cts",
47
+ "default": "./dist/express.cjs"
48
+ }
49
+ },
50
+ "./next": {
51
+ "import": {
52
+ "types": "./dist/next.d.ts",
53
+ "default": "./dist/next.js"
54
+ },
55
+ "require": {
56
+ "types": "./dist/next.d.cts",
57
+ "default": "./dist/next.cjs"
58
+ }
59
+ },
60
+ "./package.json": "./package.json"
61
+ },
62
+ "main": "./dist/index.cjs",
63
+ "module": "./dist/index.js",
64
+ "types": "./dist/index.d.cts",
65
+ "files": [
66
+ "dist",
67
+ "README.md",
68
+ "README.fr.md",
69
+ "CHANGELOG.md",
70
+ "LICENSE"
71
+ ],
72
+ "engines": {
73
+ "node": ">=18"
74
+ },
75
+ "scripts": {
76
+ "build": "tsup",
77
+ "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.src.json",
78
+ "lint": "eslint .",
79
+ "test": "vitest run",
80
+ "test:watch": "vitest",
81
+ "test:integration": "vitest run tests/integration.test.ts",
82
+ "check:dist": "node scripts/check-dist.mjs && node scripts/check-dist.cjs",
83
+ "publint": "publint --strict",
84
+ "attw": "attw --pack . --profile node16",
85
+ "check": "npm run lint && npm run typecheck && npm test && npm run build && npm run check:dist && npm run publint && npm run attw",
86
+ "prepublishOnly": "npm run build"
87
+ },
88
+ "peerDependencies": {
89
+ "express": ">=4.17",
90
+ "next": ">=13.4"
91
+ },
92
+ "peerDependenciesMeta": {
93
+ "express": {
94
+ "optional": true
95
+ },
96
+ "next": {
97
+ "optional": true
98
+ }
99
+ },
100
+ "devDependencies": {
101
+ "@arethetypeswrong/cli": "0.18.5",
102
+ "@eslint/js": "9.39.5",
103
+ "@types/express": "5.0.6",
104
+ "@types/node": "20.19.43",
105
+ "ajv": "8.20.0",
106
+ "ajv-formats": "3.0.1",
107
+ "eslint": "9.39.5",
108
+ "express": "5.2.1",
109
+ "publint": "0.3.25",
110
+ "tsup": "8.5.1",
111
+ "typescript": "5.9.3",
112
+ "typescript-eslint": "8.72.0",
113
+ "vite": "6.4.4",
114
+ "vitest": "3.2.7",
115
+ "yaml": "2.9.1"
116
+ },
117
+ "publishConfig": {
118
+ "access": "public",
119
+ "provenance": true
120
+ }
121
+ }