@oneaddress/setup 1.1.0 → 1.1.3
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/index.js +93 -43
- package/package.json +32 -32
package/dist/index.js
CHANGED
|
@@ -808,7 +808,7 @@ var L2 = () => {
|
|
|
808
808
|
};
|
|
809
809
|
|
|
810
810
|
// src/prompts.ts
|
|
811
|
-
var
|
|
811
|
+
var import_node_crypto4 = require("crypto");
|
|
812
812
|
var import_node_fs4 = require("fs");
|
|
813
813
|
var import_node_os2 = require("os");
|
|
814
814
|
var import_node_path5 = require("path");
|
|
@@ -821,13 +821,11 @@ var CRM = "\x1B[38;2;245;238;216m";
|
|
|
821
821
|
var FNT = "\x1B[38;2;130;100;45m";
|
|
822
822
|
var DIM = "\x1B[38;2;70;58;35m";
|
|
823
823
|
var MID = "\x1B[38;2;155;135;100m";
|
|
824
|
-
var GRN = "\x1B[38;2;80;200;120m";
|
|
825
824
|
var ab = (s) => `${B2}${AMB}${s}${R3}`;
|
|
826
825
|
var wb = (s) => `${B2}${CRM}${s}${R3}`;
|
|
827
826
|
var fn = (s) => `${FNT}${s}${R3}`;
|
|
828
827
|
var dm = (s) => `${DIM}${s}${R3}`;
|
|
829
828
|
var mi = (s) => `${MID}${s}${R3}`;
|
|
830
|
-
var gn = (s) => `${GRN}${s}${R3}`;
|
|
831
829
|
var _O = [" \u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588\u2588 "];
|
|
832
830
|
var _N = ["\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588"];
|
|
833
831
|
var _E = ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588"];
|
|
@@ -853,7 +851,7 @@ function printHeader() {
|
|
|
853
851
|
console.log(` ${SIDE}${" ".repeat(BAR_LEN)}${SIDE}`);
|
|
854
852
|
const wizard = mi("Partner Setup Wizard");
|
|
855
853
|
const version = fn("v2 \xB7 partners.oneaddress.io");
|
|
856
|
-
const tagLine = ` ${wizard} ${version}
|
|
854
|
+
const tagLine = ` ${wizard} ${version}`;
|
|
857
855
|
const padLen = BAR_LEN - 4 - stripAnsi(tagLine).length;
|
|
858
856
|
console.log(` ${SIDE} ${tagLine}${" ".repeat(Math.max(0, padLen))} ${SIDE}`);
|
|
859
857
|
console.log(` ${SIDE}${" ".repeat(BAR_LEN)}${SIDE}`);
|
|
@@ -2934,25 +2932,72 @@ async function registerInstall(installId, partnerId, webhookSecret, platform, we
|
|
|
2934
2932
|
}
|
|
2935
2933
|
|
|
2936
2934
|
// src/conformance.ts
|
|
2937
|
-
var
|
|
2938
|
-
function runConformance(webhookUrl,
|
|
2939
|
-
(
|
|
2940
|
-
"
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
"
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2935
|
+
var import_node_crypto2 = require("crypto");
|
|
2936
|
+
async function runConformance(webhookUrl, _partnerId, webhookSecret) {
|
|
2937
|
+
function sign(ts, body) {
|
|
2938
|
+
return (0, import_node_crypto2.createHmac)("sha256", webhookSecret).update(`${ts}.${body}`).digest("hex");
|
|
2939
|
+
}
|
|
2940
|
+
const validBody = JSON.stringify({ event: "conformance.ping", test: true });
|
|
2941
|
+
const now = String(Math.floor(Date.now() / 1e3));
|
|
2942
|
+
const staleTs = String(Math.floor(Date.now() / 1e3) - 400);
|
|
2943
|
+
const tests = [
|
|
2944
|
+
{
|
|
2945
|
+
name: "Replay attack rejected (stale timestamp)",
|
|
2946
|
+
ts: staleTs,
|
|
2947
|
+
sig: sign(staleTs, validBody),
|
|
2948
|
+
expectOk: false
|
|
2949
|
+
},
|
|
2950
|
+
{
|
|
2951
|
+
name: "Bad signature rejected",
|
|
2952
|
+
ts: now,
|
|
2953
|
+
sig: "deadbeef".repeat(8),
|
|
2954
|
+
expectOk: false
|
|
2955
|
+
},
|
|
2956
|
+
{
|
|
2957
|
+
name: "Valid signed request accepted",
|
|
2958
|
+
ts: now,
|
|
2959
|
+
sig: sign(now, validBody),
|
|
2960
|
+
expectOk: true
|
|
2961
|
+
}
|
|
2962
|
+
];
|
|
2963
|
+
let passed = 0;
|
|
2964
|
+
let failed = 0;
|
|
2965
|
+
for (const t of tests) {
|
|
2966
|
+
try {
|
|
2967
|
+
const res = await fetch(webhookUrl, {
|
|
2968
|
+
method: "POST",
|
|
2969
|
+
headers: {
|
|
2970
|
+
"Content-Type": "application/json",
|
|
2971
|
+
"X-OneAddress-Timestamp": t.ts,
|
|
2972
|
+
"X-OneAddress-Signature": t.sig,
|
|
2973
|
+
"X-OneAddress-Dispatch": "0"
|
|
2974
|
+
},
|
|
2975
|
+
body: validBody,
|
|
2976
|
+
signal: AbortSignal.timeout(8e3)
|
|
2977
|
+
});
|
|
2978
|
+
const gotOk = res.ok;
|
|
2979
|
+
const pass = t.expectOk ? gotOk : !gotOk;
|
|
2980
|
+
if (pass) {
|
|
2981
|
+
v2.success(` \u2713 ${t.name} (${res.status})`);
|
|
2982
|
+
passed++;
|
|
2983
|
+
} else {
|
|
2984
|
+
v2.warn(` \u2717 ${t.name} (${res.status} \u2014 expected ${t.expectOk ? "2xx" : "4xx"})`);
|
|
2985
|
+
failed++;
|
|
2986
|
+
}
|
|
2987
|
+
} catch (err) {
|
|
2988
|
+
v2.warn(` \u2717 ${t.name} (network error: ${err instanceof Error ? err.message : String(err)})`);
|
|
2989
|
+
failed++;
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
if (failed === 0) {
|
|
2993
|
+
v2.success(`Conformance passed ${passed}/${tests.length} \u2014 your endpoint is correctly secured.`);
|
|
2994
|
+
} else {
|
|
2995
|
+
v2.warn(`Conformance: ${passed}/${tests.length} passed. Check your WEBHOOK_SECRET and timestamp enforcement.`);
|
|
2996
|
+
}
|
|
2952
2997
|
}
|
|
2953
2998
|
|
|
2954
2999
|
// src/install.ts
|
|
2955
|
-
var
|
|
3000
|
+
var import_node_child_process = require("child_process");
|
|
2956
3001
|
var import_node_fs2 = require("fs");
|
|
2957
3002
|
var import_node_path2 = require("path");
|
|
2958
3003
|
var COMMANDS = {
|
|
@@ -2979,7 +3024,7 @@ function installDependencies(platform, outputDir) {
|
|
|
2979
3024
|
}
|
|
2980
3025
|
const cwd = spec.cwd ? (0, import_node_path2.join)(outputDir, spec.cwd) : outputDir;
|
|
2981
3026
|
const manualCommand = `cd ${outputDir} && ${spec.cmd} ${spec.args.join(" ")}`;
|
|
2982
|
-
const result = (0,
|
|
3027
|
+
const result = (0, import_node_child_process.spawnSync)(spec.cmd, spec.args, {
|
|
2983
3028
|
cwd,
|
|
2984
3029
|
stdio: "pipe",
|
|
2985
3030
|
encoding: "utf8",
|
|
@@ -2996,7 +3041,7 @@ function installDependencies(platform, outputDir) {
|
|
|
2996
3041
|
}
|
|
2997
3042
|
|
|
2998
3043
|
// src/autostart.ts
|
|
2999
|
-
var
|
|
3044
|
+
var import_node_child_process2 = require("child_process");
|
|
3000
3045
|
var import_node_path3 = require("path");
|
|
3001
3046
|
var import_node_fs3 = require("fs");
|
|
3002
3047
|
var COMMANDS2 = {
|
|
@@ -3012,7 +3057,14 @@ var serverOutput = "";
|
|
|
3012
3057
|
function stopServer() {
|
|
3013
3058
|
if (serverProcess) {
|
|
3014
3059
|
try {
|
|
3015
|
-
|
|
3060
|
+
if (process.platform === "win32" && serverProcess.pid) {
|
|
3061
|
+
(0, import_node_child_process2.spawn)("taskkill", ["/F", "/T", "/PID", String(serverProcess.pid)], {
|
|
3062
|
+
stdio: "ignore",
|
|
3063
|
+
detached: true
|
|
3064
|
+
});
|
|
3065
|
+
} else {
|
|
3066
|
+
serverProcess.kill("SIGTERM");
|
|
3067
|
+
}
|
|
3016
3068
|
} catch {
|
|
3017
3069
|
}
|
|
3018
3070
|
serverProcess = null;
|
|
@@ -3062,7 +3114,7 @@ async function startServer(platform, outputDir, port = 3001) {
|
|
|
3062
3114
|
}
|
|
3063
3115
|
serverOutput = "";
|
|
3064
3116
|
const manualCommand = `cd ${outputDir} && ${spec.cmd} ${spec.args.join(" ")}`;
|
|
3065
|
-
serverProcess = (0,
|
|
3117
|
+
serverProcess = (0, import_node_child_process2.spawn)(spec.cmd, spec.args, {
|
|
3066
3118
|
cwd: outputDir,
|
|
3067
3119
|
stdio: ["ignore", "pipe", "pipe"],
|
|
3068
3120
|
detached: false,
|
|
@@ -3084,7 +3136,7 @@ async function startServer(platform, outputDir, port = 3001) {
|
|
|
3084
3136
|
}
|
|
3085
3137
|
|
|
3086
3138
|
// src/tunnel.ts
|
|
3087
|
-
var
|
|
3139
|
+
var import_node_child_process3 = require("child_process");
|
|
3088
3140
|
var import_promises2 = require("fs/promises");
|
|
3089
3141
|
var import_node_path4 = require("path");
|
|
3090
3142
|
var import_node_os = __toESM(require("os"));
|
|
@@ -3120,7 +3172,7 @@ async function downloadCloudflared() {
|
|
|
3120
3172
|
}
|
|
3121
3173
|
async function resolveBinary() {
|
|
3122
3174
|
try {
|
|
3123
|
-
(0,
|
|
3175
|
+
(0, import_node_child_process3.execSync)("cloudflared --version", { stdio: "pipe" });
|
|
3124
3176
|
return "cloudflared";
|
|
3125
3177
|
} catch {
|
|
3126
3178
|
}
|
|
@@ -3129,7 +3181,7 @@ async function resolveBinary() {
|
|
|
3129
3181
|
async function startTunnel(port) {
|
|
3130
3182
|
const binary = await resolveBinary();
|
|
3131
3183
|
return new Promise((resolve2, reject) => {
|
|
3132
|
-
tunnelProcess = (0,
|
|
3184
|
+
tunnelProcess = (0, import_node_child_process3.spawn)(binary, ["tunnel", "--url", `http://localhost:${port}`], {
|
|
3133
3185
|
stdio: ["ignore", "pipe", "pipe"]
|
|
3134
3186
|
});
|
|
3135
3187
|
let resolved = false;
|
|
@@ -3168,13 +3220,13 @@ async function startTunnel(port) {
|
|
|
3168
3220
|
}
|
|
3169
3221
|
|
|
3170
3222
|
// src/register-url.ts
|
|
3171
|
-
var
|
|
3223
|
+
var import_node_crypto3 = require("crypto");
|
|
3172
3224
|
var PORTAL_API = "https://partners.oneaddress.io/api/partner/webhook-url";
|
|
3173
3225
|
async function registerWebhookUrl(partnerId, webhookSecret, webhookUrl) {
|
|
3174
3226
|
try {
|
|
3175
3227
|
const body = JSON.stringify({ webhook_url: webhookUrl });
|
|
3176
3228
|
const ts = String(Math.floor(Date.now() / 1e3));
|
|
3177
|
-
const sig = (0,
|
|
3229
|
+
const sig = (0, import_node_crypto3.createHmac)("sha256", webhookSecret).update(`${ts}.${body}`).digest("hex");
|
|
3178
3230
|
const res = await fetch(PORTAL_API, {
|
|
3179
3231
|
method: "PATCH",
|
|
3180
3232
|
headers: {
|
|
@@ -3197,7 +3249,7 @@ var R4 = "\x1B[0m";
|
|
|
3197
3249
|
var AMB2 = "\x1B[38;2;224;162;72m";
|
|
3198
3250
|
var MID2 = "\x1B[38;2;155;135;100m";
|
|
3199
3251
|
var DIM2 = "\x1B[38;2;70;58;35m";
|
|
3200
|
-
var
|
|
3252
|
+
var GRN = "\x1B[38;2;80;200;120m";
|
|
3201
3253
|
var CRM2 = "\x1B[1m\x1B[38;2;245;238;216m";
|
|
3202
3254
|
var cleanupFns = [];
|
|
3203
3255
|
function onCleanup(fn2) {
|
|
@@ -3274,7 +3326,7 @@ function normalisePrivateKey(raw) {
|
|
|
3274
3326
|
}
|
|
3275
3327
|
function validatePkcs8Pem(pem) {
|
|
3276
3328
|
try {
|
|
3277
|
-
(0,
|
|
3329
|
+
(0, import_node_crypto4.createPrivateKey)({ key: pem, format: "pem", type: "pkcs8" });
|
|
3278
3330
|
return void 0;
|
|
3279
3331
|
} catch (err) {
|
|
3280
3332
|
return `Key validation failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
@@ -3378,7 +3430,7 @@ async function main() {
|
|
|
3378
3430
|
process.exit(1);
|
|
3379
3431
|
}
|
|
3380
3432
|
const s2 = L2();
|
|
3381
|
-
s2.start("Installing dependencies\u2026");
|
|
3433
|
+
s2.start("Installing dependencies (this can take 30\u201360 s)\u2026");
|
|
3382
3434
|
const install = installDependencies(platform, outDir);
|
|
3383
3435
|
if (install.ok) {
|
|
3384
3436
|
s2.stop("Dependencies installed");
|
|
@@ -3454,7 +3506,7 @@ async function main() {
|
|
|
3454
3506
|
);
|
|
3455
3507
|
}
|
|
3456
3508
|
registerInstall(
|
|
3457
|
-
`OA-${(0,
|
|
3509
|
+
`OA-${(0, import_node_crypto4.randomUUID)()}`,
|
|
3458
3510
|
pid,
|
|
3459
3511
|
secret,
|
|
3460
3512
|
platform,
|
|
@@ -3462,15 +3514,13 @@ async function main() {
|
|
|
3462
3514
|
).catch(() => {
|
|
3463
3515
|
});
|
|
3464
3516
|
}
|
|
3465
|
-
if (webhookUrl
|
|
3466
|
-
v2.info("
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
v2.info("\nOnce your endpoint is live, run the conformance check:");
|
|
3473
|
-
v2.info(" npx @oneaddress/conformance test <your-https-url>/webhook");
|
|
3517
|
+
if (webhookUrl) {
|
|
3518
|
+
v2.info("");
|
|
3519
|
+
const s6 = L2();
|
|
3520
|
+
s6.start("Running conformance checks\u2026");
|
|
3521
|
+
await new Promise((r2) => setTimeout(r2, 200));
|
|
3522
|
+
s6.stop("Conformance checks:");
|
|
3523
|
+
await runConformance(webhookUrl, pid, secret);
|
|
3474
3524
|
}
|
|
3475
3525
|
const summary = [
|
|
3476
3526
|
`Partner ID: ${pid}`,
|
|
@@ -3490,7 +3540,7 @@ async function main() {
|
|
|
3490
3540
|
if (serverRunning) {
|
|
3491
3541
|
console.log("");
|
|
3492
3542
|
console.log(` ${DIM2}\u250C${"\u2500".repeat(56)}\u2510${R4}`);
|
|
3493
|
-
console.log(` ${DIM2}\u2502${R4} ${
|
|
3543
|
+
console.log(` ${DIM2}\u2502${R4} ${GRN}\u25C8${R4} ${CRM2}Server live${R4} ${MID2}on http://localhost:3001/webhook${R4} ${DIM2}\u2502${R4}`);
|
|
3494
3544
|
console.log(` ${DIM2}\u2502${R4} ${AMB2}\u25C8${R4} ${MID2}Edit ${CRM2}src/store.ts${R4} ${MID2}to wire your database${R4} ${DIM2}\u2502${R4}`);
|
|
3495
3545
|
console.log(` ${DIM2}\u2502${R4} ${MID2}Press Ctrl+C to stop the server and exit.${R4} ${DIM2} \u2502${R4}`);
|
|
3496
3546
|
console.log(` ${DIM2}\u2514${"\u2500".repeat(56)}\u2518${R4}`);
|
package/package.json
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@oneaddress/setup",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "Interactive setup wizard for OneAddress partner webhook integrations",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"setup": "dist/index.js"
|
|
8
|
-
},
|
|
9
|
-
"files": [
|
|
10
|
-
"dist",
|
|
11
|
-
"README.md"
|
|
12
|
-
],
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "tsup",
|
|
15
|
-
"prepare": "tsup",
|
|
16
|
-
"type-check": "tsc --noEmit"
|
|
17
|
-
},
|
|
18
|
-
"license": "UNLICENSED",
|
|
19
|
-
"publishConfig": {
|
|
20
|
-
"access": "public"
|
|
21
|
-
},
|
|
22
|
-
"dependencies": {
|
|
23
|
-
"@clack/prompts": "^0.9.0"
|
|
24
|
-
},
|
|
25
|
-
"devDependencies": {
|
|
26
|
-
"tsup": "^8.0.0",
|
|
27
|
-
"typescript": "^5.0.0"
|
|
28
|
-
},
|
|
29
|
-
"engines": {
|
|
30
|
-
"node": ">=18"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@oneaddress/setup",
|
|
3
|
+
"version": "1.1.3",
|
|
4
|
+
"description": "Interactive setup wizard for OneAddress partner webhook integrations",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"oneaddress-setup": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsup",
|
|
15
|
+
"prepare": "tsup",
|
|
16
|
+
"type-check": "tsc --noEmit"
|
|
17
|
+
},
|
|
18
|
+
"license": "UNLICENSED",
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@clack/prompts": "^0.9.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"tsup": "^8.0.0",
|
|
27
|
+
"typescript": "^5.0.0"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18"
|
|
31
|
+
}
|
|
32
|
+
}
|