@testsmith/api-spector 0.7.4 → 0.7.6
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/out/main/chunks/{broker-client-VwFF9sbp.js → broker-client-5IyCTx40.js} +1 -1
- package/out/main/chunks/{handle-BY_jaVBT.js → handle-DRmKOL-s.js} +1 -0
- package/out/main/chunks/{import-DR_r1DUP.js → import-B5T5wDu7.js} +2 -2
- package/out/main/chunks/{request-exec-CcLHtkwG.js → request-exec-CwJ8_OKC.js} +206 -53
- package/out/main/chunks/{soap-handler-CkoLJHoI.js → soap-handler-DTfFnzNY.js} +2 -2
- package/out/main/contract.js +3 -3
- package/out/main/flow.js +3 -3
- package/out/main/index.js +37 -5
- package/out/main/lib.js +2 -2
- package/out/main/runner.js +3 -3
- package/out/main/wsdl.js +3 -3
- package/out/preload/index.js +2 -0
- package/out/renderer/assets/{GraphQLEditor-Ih9tb7XI.js → GraphQLEditor-CDLI1OHR.js} +1 -1
- package/out/renderer/assets/{SoapEditor-CwrFQmAx.js → SoapEditor-CSUFJk7c.js} +1 -1
- package/out/renderer/assets/{index-Cy2EGsQK.js → index-8bbf24uI.js} +322 -59
- package/out/renderer/assets/index-CYArpqm5.css +627 -0
- package/out/renderer/index.html +2 -2
- package/package.json +1 -1
- package/out/renderer/assets/index-CkWcesWQ.css +0 -627
|
@@ -3,7 +3,7 @@ const promises = require("node:fs/promises");
|
|
|
3
3
|
const path = require("node:path");
|
|
4
4
|
const crypto = require("node:crypto");
|
|
5
5
|
const undici = require("undici");
|
|
6
|
-
const requestExec = require("./request-exec-
|
|
6
|
+
const requestExec = require("./request-exec-CwJ8_OKC.js");
|
|
7
7
|
const Ajv = require("ajv");
|
|
8
8
|
const jsYaml = require("js-yaml");
|
|
9
9
|
require("node:http");
|
|
@@ -73,6 +73,7 @@ const IPC = {
|
|
|
73
73
|
// ─── Import ────────────────────────────────────────────────────────────────
|
|
74
74
|
import: {
|
|
75
75
|
postman: "import:postman",
|
|
76
|
+
postmanEnvironment: "import:postman-environment",
|
|
76
77
|
openapi: "import:openapi",
|
|
77
78
|
openapiUrl: "import:openapi-url",
|
|
78
79
|
insomnia: "import:insomnia",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const uuid = require("uuid");
|
|
4
|
-
const soapHandler = require("./soap-handler-
|
|
5
|
-
require("./handle-
|
|
4
|
+
const soapHandler = require("./soap-handler-DTfFnzNY.js");
|
|
5
|
+
require("./handle-DRmKOL-s.js");
|
|
6
6
|
require("node:https");
|
|
7
7
|
require("node:http");
|
|
8
8
|
require("@xmldom/xmldom");
|
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
const undici = require("undici");
|
|
25
25
|
const promises$1 = require("fs/promises");
|
|
26
26
|
const nodeTls = require("tls");
|
|
27
|
-
const handle = require("./handle-
|
|
27
|
+
const handle = require("./handle-DRmKOL-s.js");
|
|
28
28
|
const fs = require("node:fs");
|
|
29
29
|
const os = require("node:os");
|
|
30
30
|
const path = require("node:path");
|
|
@@ -114,7 +114,7 @@ function setSecretsConfig(settings) {
|
|
|
114
114
|
function getSecretsConfig() {
|
|
115
115
|
return current;
|
|
116
116
|
}
|
|
117
|
-
function env$
|
|
117
|
+
function env$4(...names) {
|
|
118
118
|
for (const n of names) {
|
|
119
119
|
const v = process.env[n];
|
|
120
120
|
if (v !== void 0 && v !== "") return v;
|
|
@@ -128,22 +128,22 @@ function readFileTrim(path2) {
|
|
|
128
128
|
return void 0;
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
|
-
function resolveConn$
|
|
131
|
+
function resolveConn$4() {
|
|
132
132
|
const cfg = getSecretsConfig()?.vault ?? {};
|
|
133
|
-
const address = env$
|
|
133
|
+
const address = env$4("VAULT_ADDR", "API_SPECTOR_VAULT_ADDR") ?? cfg.address;
|
|
134
134
|
if (!address) {
|
|
135
135
|
throw new Error("Vault is not configured: set VAULT_ADDR (or settings.secrets.vault.address)");
|
|
136
136
|
}
|
|
137
|
-
const token = env$
|
|
138
|
-
const roleId = env$
|
|
139
|
-
const secretId = env$
|
|
140
|
-
const jwt = env$
|
|
141
|
-
const jwtRole = env$
|
|
142
|
-
const explicit = env$
|
|
137
|
+
const token = env$4("VAULT_TOKEN", "API_SPECTOR_VAULT_TOKEN") ?? readFileTrim(path.join(os.homedir(), ".vault-token"));
|
|
138
|
+
const roleId = env$4("VAULT_ROLE_ID", "API_SPECTOR_VAULT_ROLE_ID") ?? cfg.roleId;
|
|
139
|
+
const secretId = env$4("VAULT_SECRET_ID", "API_SPECTOR_VAULT_SECRET_ID");
|
|
140
|
+
const jwt = env$4("VAULT_JWT", "API_SPECTOR_VAULT_JWT") ?? (env$4("VAULT_JWT_PATH", "API_SPECTOR_VAULT_JWT_PATH") ? readFileTrim(env$4("VAULT_JWT_PATH", "API_SPECTOR_VAULT_JWT_PATH")) : void 0);
|
|
141
|
+
const jwtRole = env$4("VAULT_JWT_ROLE", "API_SPECTOR_VAULT_JWT_ROLE") ?? cfg.jwtRole;
|
|
142
|
+
const explicit = env$4("VAULT_AUTH_METHOD", "API_SPECTOR_VAULT_AUTH_METHOD") ?? cfg.authMethod;
|
|
143
143
|
const authMethod = explicit ?? (token ? "token" : roleId ? "approle" : jwt ? "jwt" : "token");
|
|
144
144
|
return {
|
|
145
145
|
address: address.replace(/\/+$/, ""),
|
|
146
|
-
namespace: env$
|
|
146
|
+
namespace: env$4("VAULT_NAMESPACE", "API_SPECTOR_VAULT_NAMESPACE") ?? cfg.namespace,
|
|
147
147
|
authMethod,
|
|
148
148
|
token,
|
|
149
149
|
roleId,
|
|
@@ -151,13 +151,13 @@ function resolveConn$3() {
|
|
|
151
151
|
jwt,
|
|
152
152
|
jwtRole,
|
|
153
153
|
loginMount: cfg.loginMount,
|
|
154
|
-
kvVersion: env$
|
|
155
|
-
skipVerify: (env$
|
|
156
|
-
caPath: env$
|
|
154
|
+
kvVersion: env$4("VAULT_KV_VERSION", "API_SPECTOR_VAULT_KV_VERSION") ?? cfg.kvVersion ?? "auto",
|
|
155
|
+
skipVerify: (env$4("VAULT_SKIP_VERIFY", "API_SPECTOR_VAULT_SKIP_VERIFY") ?? "").toLowerCase() === "true" || cfg.skipVerify === true,
|
|
156
|
+
caPath: env$4("VAULT_CACERT", "API_SPECTOR_VAULT_CACERT")
|
|
157
157
|
};
|
|
158
158
|
}
|
|
159
|
-
let cachedToken$
|
|
160
|
-
const secretCache$
|
|
159
|
+
let cachedToken$2 = null;
|
|
160
|
+
const secretCache$2 = /* @__PURE__ */ new Map();
|
|
161
161
|
let _dispatcher;
|
|
162
162
|
let _dispatcherKey = "";
|
|
163
163
|
async function dispatcherFor(conn) {
|
|
@@ -200,7 +200,7 @@ async function clientToken(conn) {
|
|
|
200
200
|
return conn.token;
|
|
201
201
|
}
|
|
202
202
|
const now = Date.now();
|
|
203
|
-
if (cachedToken$
|
|
203
|
+
if (cachedToken$2 && cachedToken$2.expiresAt > now + 5e3) return cachedToken$2.value;
|
|
204
204
|
let mount;
|
|
205
205
|
let body;
|
|
206
206
|
if (conn.authMethod === "approle") {
|
|
@@ -224,7 +224,7 @@ async function clientToken(conn) {
|
|
|
224
224
|
const token = json?.auth?.client_token;
|
|
225
225
|
if (!token) throw new Error("Vault login did not return a client token");
|
|
226
226
|
const ttl = Number(json?.auth?.lease_duration ?? 0);
|
|
227
|
-
cachedToken$
|
|
227
|
+
cachedToken$2 = { value: token, expiresAt: ttl > 0 ? now + ttl * 1e3 : now + 5 * 6e4 };
|
|
228
228
|
return token;
|
|
229
229
|
}
|
|
230
230
|
async function readSecret(refBody) {
|
|
@@ -237,11 +237,11 @@ async function readSecret(refBody) {
|
|
|
237
237
|
if (!path2 || !key) {
|
|
238
238
|
throw new Error(`Vault reference must be 'vault:<path>#<key>' (got 'vault:${refBody}')`);
|
|
239
239
|
}
|
|
240
|
-
const conn = resolveConn$
|
|
240
|
+
const conn = resolveConn$4();
|
|
241
241
|
const cacheKey = `${conn.address}|${conn.namespace ?? ""}|${path2}`;
|
|
242
242
|
const now = Date.now();
|
|
243
243
|
let bag;
|
|
244
|
-
const hit = secretCache$
|
|
244
|
+
const hit = secretCache$2.get(cacheKey);
|
|
245
245
|
if (hit && hit.expiresAt > now) {
|
|
246
246
|
bag = hit.bag;
|
|
247
247
|
} else {
|
|
@@ -250,7 +250,7 @@ async function readSecret(refBody) {
|
|
|
250
250
|
bag = isV2 ? json?.data?.data : json?.data;
|
|
251
251
|
const lease = Number(json?.lease_duration ?? 0);
|
|
252
252
|
if (bag) {
|
|
253
|
-
secretCache$
|
|
253
|
+
secretCache$2.set(cacheKey, { bag, expiresAt: lease > 0 ? now + lease * 1e3 : now + 5 * 6e4 });
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
if (!bag || !(key in bag)) {
|
|
@@ -293,23 +293,23 @@ function signSigV4(input) {
|
|
|
293
293
|
Authorization: `AWS4-HMAC-SHA256 Credential=${input.accessKeyId}/${scope}, SignedHeaders=${signedHeaders}, Signature=${signature}`
|
|
294
294
|
};
|
|
295
295
|
}
|
|
296
|
-
function env$
|
|
296
|
+
function env$3(...names) {
|
|
297
297
|
for (const n of names) {
|
|
298
298
|
const v = process.env[n];
|
|
299
299
|
if (v !== void 0 && v !== "") return v;
|
|
300
300
|
}
|
|
301
301
|
return void 0;
|
|
302
302
|
}
|
|
303
|
-
function resolveConn$
|
|
303
|
+
function resolveConn$3() {
|
|
304
304
|
const cfg = getSecretsConfig()?.aws ?? {};
|
|
305
|
-
const region = env$
|
|
306
|
-
const accessKeyId = env$
|
|
307
|
-
const secretAccessKey = env$
|
|
305
|
+
const region = env$3("AWS_REGION", "AWS_DEFAULT_REGION", "API_SPECTOR_AWS_REGION") ?? cfg.region;
|
|
306
|
+
const accessKeyId = env$3("AWS_ACCESS_KEY_ID");
|
|
307
|
+
const secretAccessKey = env$3("AWS_SECRET_ACCESS_KEY");
|
|
308
308
|
if (!region) throw new Error("AWS Secrets Manager: no region (set AWS_REGION or settings.secrets.aws.region)");
|
|
309
309
|
if (!accessKeyId || !secretAccessKey) {
|
|
310
310
|
throw new Error("AWS Secrets Manager: no credentials (set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY)");
|
|
311
311
|
}
|
|
312
|
-
return { region, accessKeyId, secretAccessKey, sessionToken: env$
|
|
312
|
+
return { region, accessKeyId, secretAccessKey, sessionToken: env$3("AWS_SESSION_TOKEN") };
|
|
313
313
|
}
|
|
314
314
|
const cache = /* @__PURE__ */ new Map();
|
|
315
315
|
async function getSecretString(conn, secretId) {
|
|
@@ -346,12 +346,12 @@ async function getSecretString(conn, secretId) {
|
|
|
346
346
|
cache.set(cacheKey, { raw, expiresAt: now + 5 * 6e4 });
|
|
347
347
|
return raw;
|
|
348
348
|
}
|
|
349
|
-
async function resolve$
|
|
349
|
+
async function resolve$3(refBody) {
|
|
350
350
|
const hash = refBody.lastIndexOf("#");
|
|
351
351
|
const secretId = hash < 0 ? refBody : refBody.slice(0, hash);
|
|
352
352
|
const key = hash < 0 ? null : refBody.slice(hash + 1);
|
|
353
353
|
if (!secretId) throw new Error(`AWS reference must be 'aws:<secretId>[#<key>]' (got 'aws:${refBody}')`);
|
|
354
|
-
const raw = await getSecretString(resolveConn$
|
|
354
|
+
const raw = await getSecretString(resolveConn$3(), secretId);
|
|
355
355
|
if (key === null) return raw;
|
|
356
356
|
let parsed;
|
|
357
357
|
try {
|
|
@@ -364,30 +364,30 @@ async function resolve$2(refBody) {
|
|
|
364
364
|
}
|
|
365
365
|
const awsSecretsProvider = {
|
|
366
366
|
scheme: "aws",
|
|
367
|
-
resolve: (refBody) => resolve$
|
|
367
|
+
resolve: (refBody) => resolve$3(refBody)
|
|
368
368
|
};
|
|
369
|
-
function env$
|
|
369
|
+
function env$2(...names) {
|
|
370
370
|
for (const n of names) {
|
|
371
371
|
const v = process.env[n];
|
|
372
372
|
if (v !== void 0 && v !== "") return v;
|
|
373
373
|
}
|
|
374
374
|
return void 0;
|
|
375
375
|
}
|
|
376
|
-
function resolveConn$
|
|
376
|
+
function resolveConn$2() {
|
|
377
377
|
const cfg = getSecretsConfig()?.azure ?? {};
|
|
378
|
-
const tenantId = env$
|
|
379
|
-
const clientId = env$
|
|
380
|
-
const clientSecret = env$
|
|
378
|
+
const tenantId = env$2("AZURE_TENANT_ID", "API_SPECTOR_AZURE_TENANT_ID") ?? cfg.tenantId;
|
|
379
|
+
const clientId = env$2("AZURE_CLIENT_ID", "API_SPECTOR_AZURE_CLIENT_ID") ?? cfg.clientId;
|
|
380
|
+
const clientSecret = env$2("AZURE_CLIENT_SECRET", "API_SPECTOR_AZURE_CLIENT_SECRET");
|
|
381
381
|
if (!tenantId || !clientId || !clientSecret) {
|
|
382
382
|
throw new Error("Azure Key Vault: set AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET");
|
|
383
383
|
}
|
|
384
384
|
return { tenantId, clientId, clientSecret, defaultVault: cfg.vault };
|
|
385
385
|
}
|
|
386
|
-
let cachedToken = null;
|
|
387
|
-
const secretCache = /* @__PURE__ */ new Map();
|
|
388
|
-
async function accessToken(conn) {
|
|
386
|
+
let cachedToken$1 = null;
|
|
387
|
+
const secretCache$1 = /* @__PURE__ */ new Map();
|
|
388
|
+
async function accessToken$1(conn) {
|
|
389
389
|
const now = Date.now();
|
|
390
|
-
if (cachedToken && cachedToken.expiresAt > now + 3e4) return cachedToken.value;
|
|
390
|
+
if (cachedToken$1 && cachedToken$1.expiresAt > now + 3e4) return cachedToken$1.value;
|
|
391
391
|
const form = new URLSearchParams({
|
|
392
392
|
grant_type: "client_credentials",
|
|
393
393
|
client_id: conn.clientId,
|
|
@@ -407,7 +407,7 @@ async function accessToken(conn) {
|
|
|
407
407
|
const token = json?.access_token;
|
|
408
408
|
if (!token) throw new Error("Azure AD did not return an access token");
|
|
409
409
|
const ttl = Number(json?.expires_in ?? 0);
|
|
410
|
-
cachedToken = { value: token, expiresAt: ttl > 0 ? now + ttl * 1e3 : now + 5 * 6e4 };
|
|
410
|
+
cachedToken$1 = { value: token, expiresAt: ttl > 0 ? now + ttl * 1e3 : now + 5 * 6e4 };
|
|
411
411
|
return token;
|
|
412
412
|
}
|
|
413
413
|
function secretUrl(refBody, defaultVault) {
|
|
@@ -430,13 +430,13 @@ function secretUrl(refBody, defaultVault) {
|
|
|
430
430
|
const path2 = version ? `secrets/${name}/${version}` : `secrets/${name}`;
|
|
431
431
|
return `${base}/${path2}?api-version=7.4`;
|
|
432
432
|
}
|
|
433
|
-
async function resolve$
|
|
434
|
-
const conn = resolveConn$
|
|
433
|
+
async function resolve$2(refBody) {
|
|
434
|
+
const conn = resolveConn$2();
|
|
435
435
|
const url = secretUrl(refBody, conn.defaultVault);
|
|
436
436
|
const now = Date.now();
|
|
437
|
-
const hit = secretCache.get(url);
|
|
437
|
+
const hit = secretCache$1.get(url);
|
|
438
438
|
if (hit && hit.expiresAt > now) return hit.value;
|
|
439
|
-
const res = await fetch(url, { headers: { authorization: `Bearer ${await accessToken(conn)}` } });
|
|
439
|
+
const res = await fetch(url, { headers: { authorization: `Bearer ${await accessToken$1(conn)}` } });
|
|
440
440
|
if (!res.ok) {
|
|
441
441
|
const text = await res.text().catch(() => "");
|
|
442
442
|
throw new Error(`Azure Key Vault ${res.status} for '${refBody}': ${text.slice(0, 300)}`);
|
|
@@ -444,24 +444,24 @@ async function resolve$1(refBody) {
|
|
|
444
444
|
const json = await res.json();
|
|
445
445
|
const value = json?.value;
|
|
446
446
|
if (value === void 0) throw new Error(`Azure Key Vault secret '${refBody}' has no value`);
|
|
447
|
-
secretCache.set(url, { value, expiresAt: now + 5 * 6e4 });
|
|
447
|
+
secretCache$1.set(url, { value, expiresAt: now + 5 * 6e4 });
|
|
448
448
|
return value;
|
|
449
449
|
}
|
|
450
450
|
const azureKeyVaultProvider = {
|
|
451
451
|
scheme: "azure",
|
|
452
|
-
resolve: (refBody) => resolve$
|
|
452
|
+
resolve: (refBody) => resolve$2(refBody)
|
|
453
453
|
};
|
|
454
|
-
function env(...names) {
|
|
454
|
+
function env$1(...names) {
|
|
455
455
|
for (const n of names) {
|
|
456
456
|
const v = process.env[n];
|
|
457
457
|
if (v !== void 0 && v !== "") return v;
|
|
458
458
|
}
|
|
459
459
|
return void 0;
|
|
460
460
|
}
|
|
461
|
-
function resolveConn() {
|
|
461
|
+
function resolveConn$1() {
|
|
462
462
|
const cfg = getSecretsConfig()?.onePassword ?? {};
|
|
463
|
-
const host = env("OP_CONNECT_HOST", "API_SPECTOR_OP_CONNECT_HOST") ?? cfg.connectHost;
|
|
464
|
-
const token = env("OP_CONNECT_TOKEN", "API_SPECTOR_OP_CONNECT_TOKEN");
|
|
463
|
+
const host = env$1("OP_CONNECT_HOST", "API_SPECTOR_OP_CONNECT_HOST") ?? cfg.connectHost;
|
|
464
|
+
const token = env$1("OP_CONNECT_TOKEN", "API_SPECTOR_OP_CONNECT_TOKEN");
|
|
465
465
|
if (!host || !token) {
|
|
466
466
|
throw new Error("1Password: set OP_CONNECT_HOST and OP_CONNECT_TOKEN (1Password Connect)");
|
|
467
467
|
}
|
|
@@ -500,7 +500,7 @@ async function itemId(conn, vid, item) {
|
|
|
500
500
|
idCache.set(cacheKey, id);
|
|
501
501
|
return id;
|
|
502
502
|
}
|
|
503
|
-
async function resolve(refBody) {
|
|
503
|
+
async function resolve$1(refBody) {
|
|
504
504
|
const parts = refBody.replace(/^\/\//, "").replace(/^\/+/, "").split("/").filter(Boolean);
|
|
505
505
|
if (parts.length < 3) {
|
|
506
506
|
throw new Error(`1Password reference must be 'op://<vault>/<item>/<field>' (got 'op:${refBody}')`);
|
|
@@ -508,7 +508,7 @@ async function resolve(refBody) {
|
|
|
508
508
|
const [vault, item, ...rest] = parts;
|
|
509
509
|
const sectionLabel = rest.length >= 2 ? rest[0] : null;
|
|
510
510
|
const fieldLabel = rest[rest.length - 1];
|
|
511
|
-
const conn = resolveConn();
|
|
511
|
+
const conn = resolveConn$1();
|
|
512
512
|
const vid = await vaultId(conn, vault);
|
|
513
513
|
const iid = await itemId(conn, vid, item);
|
|
514
514
|
const cacheKey = `${vid}/${iid}`;
|
|
@@ -535,12 +535,158 @@ async function resolve(refBody) {
|
|
|
535
535
|
}
|
|
536
536
|
const onePasswordProvider = {
|
|
537
537
|
scheme: "op",
|
|
538
|
+
resolve: (refBody) => resolve$1(refBody)
|
|
539
|
+
};
|
|
540
|
+
const TOKEN_URI = "https://oauth2.googleapis.com/token";
|
|
541
|
+
const SCOPE = "https://www.googleapis.com/auth/cloud-platform";
|
|
542
|
+
const API_BASE = "https://secretmanager.googleapis.com/v1";
|
|
543
|
+
function env(...names) {
|
|
544
|
+
for (const n of names) {
|
|
545
|
+
const v = process.env[n];
|
|
546
|
+
if (v !== void 0 && v !== "") return v;
|
|
547
|
+
}
|
|
548
|
+
return void 0;
|
|
549
|
+
}
|
|
550
|
+
function loadServiceAccount() {
|
|
551
|
+
const inline = env("GCP_SERVICE_ACCOUNT_KEY", "GOOGLE_APPLICATION_CREDENTIALS_JSON");
|
|
552
|
+
const path2 = env("GOOGLE_APPLICATION_CREDENTIALS");
|
|
553
|
+
let raw;
|
|
554
|
+
if (inline) {
|
|
555
|
+
raw = inline;
|
|
556
|
+
} else if (path2) {
|
|
557
|
+
try {
|
|
558
|
+
raw = fs.readFileSync(path2, "utf8");
|
|
559
|
+
} catch (e) {
|
|
560
|
+
throw new Error(`GCP Secret Manager: cannot read GOOGLE_APPLICATION_CREDENTIALS '${path2}': ${e.message}`);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (!raw) return void 0;
|
|
564
|
+
let key;
|
|
565
|
+
try {
|
|
566
|
+
key = JSON.parse(raw);
|
|
567
|
+
} catch {
|
|
568
|
+
throw new Error("GCP Secret Manager: the service-account key is not valid JSON");
|
|
569
|
+
}
|
|
570
|
+
if (!key.client_email || !key.private_key) {
|
|
571
|
+
throw new Error("GCP Secret Manager: the service-account key is missing client_email or private_key");
|
|
572
|
+
}
|
|
573
|
+
return key;
|
|
574
|
+
}
|
|
575
|
+
function resolveConn() {
|
|
576
|
+
const cfg = getSecretsConfig()?.gcp ?? {};
|
|
577
|
+
const accessToken2 = env("GCP_ACCESS_TOKEN", "GOOGLE_OAUTH_ACCESS_TOKEN");
|
|
578
|
+
const serviceAccount = loadServiceAccount();
|
|
579
|
+
if (!accessToken2 && !serviceAccount) {
|
|
580
|
+
throw new Error(
|
|
581
|
+
"GCP Secret Manager: no credentials (set GCP_ACCESS_TOKEN, or GOOGLE_APPLICATION_CREDENTIALS / GOOGLE_APPLICATION_CREDENTIALS_JSON to a service-account key)"
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
const defaultProject = env("GCP_PROJECT", "GOOGLE_CLOUD_PROJECT", "CLOUDSDK_CORE_PROJECT") ?? cfg.project ?? serviceAccount?.project_id;
|
|
585
|
+
return { accessToken: accessToken2, serviceAccount, defaultProject };
|
|
586
|
+
}
|
|
587
|
+
let cachedToken = null;
|
|
588
|
+
const secretCache = /* @__PURE__ */ new Map();
|
|
589
|
+
const b64url = (b) => (Buffer.isBuffer(b) ? b : Buffer.from(b)).toString("base64url");
|
|
590
|
+
async function mintAccessToken(sa) {
|
|
591
|
+
const iat = Math.floor(Date.now() / 1e3);
|
|
592
|
+
const aud = sa.token_uri || TOKEN_URI;
|
|
593
|
+
const header = b64url(JSON.stringify({ alg: "RS256", typ: "JWT" }));
|
|
594
|
+
const claims = b64url(JSON.stringify({ iss: sa.client_email, scope: SCOPE, aud, iat, exp: iat + 3600 }));
|
|
595
|
+
const signingInput = `${header}.${claims}`;
|
|
596
|
+
const signature = b64url(crypto.createSign("RSA-SHA256").update(signingInput).sign(sa.private_key));
|
|
597
|
+
const assertion = `${signingInput}.${signature}`;
|
|
598
|
+
const body = new URLSearchParams({
|
|
599
|
+
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
|
600
|
+
assertion
|
|
601
|
+
});
|
|
602
|
+
const res = await fetch(aud, {
|
|
603
|
+
method: "POST",
|
|
604
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
605
|
+
body: body.toString()
|
|
606
|
+
});
|
|
607
|
+
if (!res.ok) {
|
|
608
|
+
const text = await res.text().catch(() => "");
|
|
609
|
+
throw new Error(`GCP token exchange ${res.status}: ${text.slice(0, 300)}`);
|
|
610
|
+
}
|
|
611
|
+
const json = await res.json();
|
|
612
|
+
const token = json?.access_token;
|
|
613
|
+
if (!token) throw new Error("GCP token endpoint did not return an access_token");
|
|
614
|
+
return { token, ttl: Number(json?.expires_in ?? 3600) };
|
|
615
|
+
}
|
|
616
|
+
async function accessToken(conn) {
|
|
617
|
+
if (conn.accessToken) return conn.accessToken;
|
|
618
|
+
const now = Date.now();
|
|
619
|
+
if (cachedToken && cachedToken.expiresAt > now + 3e4) return cachedToken.value;
|
|
620
|
+
const { token, ttl } = await mintAccessToken(conn.serviceAccount);
|
|
621
|
+
cachedToken = { value: token, expiresAt: ttl > 0 ? now + ttl * 1e3 : now + 5 * 6e4 };
|
|
622
|
+
return token;
|
|
623
|
+
}
|
|
624
|
+
function accessUrl(refPath, defaultProject) {
|
|
625
|
+
if (refPath.startsWith("projects/")) {
|
|
626
|
+
const hasVersion = /\/versions\/[^/]+$/.test(refPath);
|
|
627
|
+
const full = hasVersion ? refPath : `${refPath.replace(/\/+$/, "")}/versions/latest`;
|
|
628
|
+
return `${API_BASE}/${full}:access`;
|
|
629
|
+
}
|
|
630
|
+
const parts = refPath.replace(/^\/+/, "").split("/").filter(Boolean);
|
|
631
|
+
let project;
|
|
632
|
+
let secret;
|
|
633
|
+
let version = "latest";
|
|
634
|
+
if (parts.length >= 2) {
|
|
635
|
+
[project, secret, version = "latest"] = parts;
|
|
636
|
+
} else if (parts.length === 1) {
|
|
637
|
+
project = defaultProject;
|
|
638
|
+
secret = parts[0];
|
|
639
|
+
} else {
|
|
640
|
+
throw new Error(`GCP reference must be 'gcp:<project>/<secret>[/<version>]' (got 'gcp:${refPath}')`);
|
|
641
|
+
}
|
|
642
|
+
if (!project) {
|
|
643
|
+
throw new Error(
|
|
644
|
+
`GCP reference 'gcp:${refPath}' has no project and no default is set (set GCP_PROJECT or settings.secrets.gcp.project, or write 'gcp:<project>/<secret>')`
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
return `${API_BASE}/projects/${project}/secrets/${secret}/versions/${version}:access`;
|
|
648
|
+
}
|
|
649
|
+
async function resolve(refBody) {
|
|
650
|
+
const hash = refBody.lastIndexOf("#");
|
|
651
|
+
const refPath = hash < 0 ? refBody : refBody.slice(0, hash);
|
|
652
|
+
const key = hash < 0 ? null : refBody.slice(hash + 1);
|
|
653
|
+
const conn = resolveConn();
|
|
654
|
+
const url = accessUrl(refPath, conn.defaultProject);
|
|
655
|
+
const now = Date.now();
|
|
656
|
+
const hit = secretCache.get(url);
|
|
657
|
+
const rawPayload = hit && hit.expiresAt > now ? hit.value : await fetchPayload(conn, url, refBody);
|
|
658
|
+
if (key === null) return rawPayload;
|
|
659
|
+
let parsed;
|
|
660
|
+
try {
|
|
661
|
+
parsed = JSON.parse(rawPayload);
|
|
662
|
+
} catch {
|
|
663
|
+
throw new Error(`GCP secret '${refPath}' is not JSON, so key '${key}' cannot be read (drop the '#${key}')`);
|
|
664
|
+
}
|
|
665
|
+
if (!(key in parsed)) throw new Error(`GCP secret '${refPath}' has no key '${key}'`);
|
|
666
|
+
return String(parsed[key]);
|
|
667
|
+
}
|
|
668
|
+
async function fetchPayload(conn, url, refBody) {
|
|
669
|
+
const res = await fetch(url, { headers: { authorization: `Bearer ${await accessToken(conn)}` } });
|
|
670
|
+
if (!res.ok) {
|
|
671
|
+
const text = await res.text().catch(() => "");
|
|
672
|
+
throw new Error(`GCP Secret Manager ${res.status} for '${refBody}': ${text.slice(0, 300)}`);
|
|
673
|
+
}
|
|
674
|
+
const json = await res.json();
|
|
675
|
+
const data = json?.payload?.data;
|
|
676
|
+
if (data === void 0) throw new Error(`GCP secret '${refBody}' returned no payload data`);
|
|
677
|
+
const value = Buffer.from(data, "base64").toString("utf8");
|
|
678
|
+
secretCache.set(url, { value, expiresAt: Date.now() + 5 * 6e4 });
|
|
679
|
+
return value;
|
|
680
|
+
}
|
|
681
|
+
const gcpSecretManagerProvider = {
|
|
682
|
+
scheme: "gcp",
|
|
538
683
|
resolve: (refBody) => resolve(refBody)
|
|
539
684
|
};
|
|
540
685
|
registerSecretProvider(vaultProvider);
|
|
541
686
|
registerSecretProvider(awsSecretsProvider);
|
|
542
687
|
registerSecretProvider(azureKeyVaultProvider);
|
|
543
688
|
registerSecretProvider(onePasswordProvider);
|
|
689
|
+
registerSecretProvider(gcpSecretManagerProvider);
|
|
544
690
|
const MASTER_KEY_ENV = "API_SPECTOR_MASTER_KEY";
|
|
545
691
|
let secretStore = {};
|
|
546
692
|
let secretStorePath = null;
|
|
@@ -741,7 +887,14 @@ async function buildEnvVars(environment) {
|
|
|
741
887
|
return vars;
|
|
742
888
|
}
|
|
743
889
|
function mergeVars(envVars, collectionVars, globals2, localVars = {}, dynamicVars = {}) {
|
|
744
|
-
|
|
890
|
+
const out = {};
|
|
891
|
+
for (const src of [dynamicVars, globals2, collectionVars, envVars, localVars]) {
|
|
892
|
+
for (const [k, v] of Object.entries(src ?? {})) {
|
|
893
|
+
if (v == null) continue;
|
|
894
|
+
out[k] = v;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
return out;
|
|
745
898
|
}
|
|
746
899
|
function xmlFindAll(node, tag, nth) {
|
|
747
900
|
const results = [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const handle = require("./handle-
|
|
2
|
+
const handle = require("./handle-DRmKOL-s.js");
|
|
3
3
|
const https = require("node:https");
|
|
4
4
|
const http = require("node:http");
|
|
5
5
|
const xmldom = require("@xmldom/xmldom");
|
|
@@ -313,7 +313,7 @@ function registerSoapHandlers(ipc) {
|
|
|
313
313
|
handle.handleIpc(ipc, handle.IPC.wsdl.import, async (_event, opts) => {
|
|
314
314
|
const { validateWsdlImport } = await Promise.resolve().then(() => require("./ipc-validate-sqUFqRmE.js"));
|
|
315
315
|
validateWsdlImport(opts);
|
|
316
|
-
const { importWsdl } = await Promise.resolve().then(() => require("./import-
|
|
316
|
+
const { importWsdl } = await Promise.resolve().then(() => require("./import-B5T5wDu7.js"));
|
|
317
317
|
const wsdlText = opts.xml ?? (opts.url ? await fetchUrl(opts.url) : "");
|
|
318
318
|
if (!wsdlText) throw new Error("wsdl:import requires either `url` or `xml`");
|
|
319
319
|
return importWsdl(wsdlText, { name: opts.name, existingMockPorts: opts.existingMockPorts });
|
package/out/main/contract.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
const promises = require("node:fs/promises");
|
|
4
4
|
const path = require("node:path");
|
|
5
|
-
const brokerClient = require("./chunks/broker-client-
|
|
5
|
+
const brokerClient = require("./chunks/broker-client-5IyCTx40.js");
|
|
6
6
|
const escape = require("./chunks/escape-DDVAlOvZ.js");
|
|
7
7
|
const crypto = require("node:crypto");
|
|
8
8
|
const undici = require("undici");
|
|
@@ -11,10 +11,10 @@ const cliCommon = require("./chunks/cli-common-GnihVSjU.js");
|
|
|
11
11
|
const node_child_process = require("node:child_process");
|
|
12
12
|
const jsYaml = require("js-yaml");
|
|
13
13
|
const environments = require("./chunks/environments-iM3SUM-4.js");
|
|
14
|
-
require("./chunks/request-exec-
|
|
14
|
+
require("./chunks/request-exec-CwJ8_OKC.js");
|
|
15
15
|
require("fs/promises");
|
|
16
16
|
require("tls");
|
|
17
|
-
require("./chunks/handle-
|
|
17
|
+
require("./chunks/handle-DRmKOL-s.js");
|
|
18
18
|
require("node:fs");
|
|
19
19
|
require("dayjs");
|
|
20
20
|
require("node:vm");
|
package/out/main/flow.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
const promises = require("node:fs/promises");
|
|
4
4
|
const path = require("node:path");
|
|
5
|
-
const requestExec = require("./chunks/request-exec-
|
|
5
|
+
const requestExec = require("./chunks/request-exec-CwJ8_OKC.js");
|
|
6
6
|
const requestCollection = require("./chunks/request-collection-KGPuvN7o.js");
|
|
7
7
|
const environments = require("./chunks/environments-iM3SUM-4.js");
|
|
8
8
|
const flowEngine = require("./chunks/flow-engine-BVzjz4lJ.js");
|
|
@@ -10,7 +10,7 @@ const cliCommon = require("./chunks/cli-common-GnihVSjU.js");
|
|
|
10
10
|
require("undici");
|
|
11
11
|
require("fs/promises");
|
|
12
12
|
require("tls");
|
|
13
|
-
require("./chunks/handle-
|
|
13
|
+
require("./chunks/handle-DRmKOL-s.js");
|
|
14
14
|
require("node:fs");
|
|
15
15
|
require("node:os");
|
|
16
16
|
require("node:crypto");
|
|
@@ -265,7 +265,7 @@ async function main() {
|
|
|
265
265
|
const envName = args.environment ?? args.env;
|
|
266
266
|
const env = environments.selectEnvironment(workspace, environments$1, envName);
|
|
267
267
|
const verbose = Boolean(args.verbose);
|
|
268
|
-
const version = `v${"0.7.
|
|
268
|
+
const version = `v${"0.7.6"}`;
|
|
269
269
|
console.log("");
|
|
270
270
|
console.log(cliCommon.color(" API Flow Runner" + (version ? ` ${version}` : ""), cliCommon.C.bold, cliCommon.C.white));
|
|
271
271
|
console.log(cliCommon.color(` Flow: ${flow.name}`, cliCommon.C.gray));
|
package/out/main/index.js
CHANGED
|
@@ -22,14 +22,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
22
|
mod
|
|
23
23
|
));
|
|
24
24
|
const electron = require("electron");
|
|
25
|
-
const handle = require("./chunks/handle-
|
|
25
|
+
const handle = require("./chunks/handle-DRmKOL-s.js");
|
|
26
26
|
const path = require("node:path");
|
|
27
27
|
const fs = require("node:fs");
|
|
28
28
|
const promises = require("node:fs/promises");
|
|
29
29
|
const crypto = require("node:crypto");
|
|
30
30
|
const JSZip = require("jszip");
|
|
31
31
|
const dataFiles = require("./chunks/data-files-BYqhsoPe.js");
|
|
32
|
-
const requestExec = require("./chunks/request-exec-
|
|
32
|
+
const requestExec = require("./chunks/request-exec-CwJ8_OKC.js");
|
|
33
33
|
const ipcValidate = require("./chunks/ipc-validate-sqUFqRmE.js");
|
|
34
34
|
const uuid = require("uuid");
|
|
35
35
|
const jsYaml = require("js-yaml");
|
|
@@ -42,9 +42,9 @@ const WebSocket = require("ws");
|
|
|
42
42
|
const os = require("node:os");
|
|
43
43
|
const grpc = require("@grpc/grpc-js");
|
|
44
44
|
const protoLoader = require("@grpc/proto-loader");
|
|
45
|
-
const soapHandler = require("./chunks/soap-handler-
|
|
45
|
+
const soapHandler = require("./chunks/soap-handler-DTfFnzNY.js");
|
|
46
46
|
const escape = require("./chunks/escape-DDVAlOvZ.js");
|
|
47
|
-
const brokerClient = require("./chunks/broker-client-
|
|
47
|
+
const brokerClient = require("./chunks/broker-client-5IyCTx40.js");
|
|
48
48
|
const simpleGit = require("simple-git");
|
|
49
49
|
const recorder = require("./chunks/recorder-BkO8G_mB.js");
|
|
50
50
|
const electronUpdater = require("electron-updater");
|
|
@@ -1299,6 +1299,29 @@ async function importPostman(filePath) {
|
|
|
1299
1299
|
requests
|
|
1300
1300
|
};
|
|
1301
1301
|
}
|
|
1302
|
+
async function importPostmanEnvironment(filePath) {
|
|
1303
|
+
const raw = await promises.readFile(filePath, "utf8");
|
|
1304
|
+
let data;
|
|
1305
|
+
try {
|
|
1306
|
+
data = JSON.parse(raw);
|
|
1307
|
+
} catch {
|
|
1308
|
+
throw new Error("Not valid JSON — pick a Postman environment export file.");
|
|
1309
|
+
}
|
|
1310
|
+
if (!Array.isArray(data.values) || data._postman_variable_scope === "collection") {
|
|
1311
|
+
throw new Error('Not a Postman environment file (no "values" array found).');
|
|
1312
|
+
}
|
|
1313
|
+
const variables = data.values.filter((v) => !!v && typeof v.key === "string" && v.key.length > 0).map((v) => ({
|
|
1314
|
+
key: v.key,
|
|
1315
|
+
value: v.value == null ? "" : String(v.value),
|
|
1316
|
+
enabled: v.enabled !== false
|
|
1317
|
+
}));
|
|
1318
|
+
return {
|
|
1319
|
+
version: "1.0",
|
|
1320
|
+
id: uuid.v4(),
|
|
1321
|
+
name: data.name && String(data.name).trim() || "Imported Environment",
|
|
1322
|
+
variables
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1302
1325
|
async function loadSpec(filePath) {
|
|
1303
1326
|
const raw = await promises.readFile(filePath, "utf8");
|
|
1304
1327
|
if (filePath.endsWith(".yaml") || filePath.endsWith(".yml")) {
|
|
@@ -2041,6 +2064,15 @@ function registerImportHandlers(ipc) {
|
|
|
2041
2064
|
if (result.canceled || !result.filePaths[0]) return null;
|
|
2042
2065
|
return importPostman(result.filePaths[0]);
|
|
2043
2066
|
});
|
|
2067
|
+
handle.handleIpc(ipc, handle.IPC.import.postmanEnvironment, async () => {
|
|
2068
|
+
const result = await electron.dialog.showOpenDialog({
|
|
2069
|
+
title: "Import Postman Environment",
|
|
2070
|
+
filters: [{ name: "JSON", extensions: ["json"] }],
|
|
2071
|
+
properties: ["openFile"]
|
|
2072
|
+
});
|
|
2073
|
+
if (result.canceled || !result.filePaths[0]) return null;
|
|
2074
|
+
return importPostmanEnvironment(result.filePaths[0]);
|
|
2075
|
+
});
|
|
2044
2076
|
handle.handleIpc(ipc, handle.IPC.import.openapi, async () => {
|
|
2045
2077
|
const result = await electron.dialog.showOpenDialog({
|
|
2046
2078
|
title: "Import OpenAPI Definition",
|
|
@@ -6110,7 +6142,7 @@ function isNewer(a, b) {
|
|
|
6110
6142
|
return a2 > b2;
|
|
6111
6143
|
}
|
|
6112
6144
|
async function checkForUpdate() {
|
|
6113
|
-
const current = "0.7.
|
|
6145
|
+
const current = "0.7.6";
|
|
6114
6146
|
try {
|
|
6115
6147
|
const res = await fetch(REGISTRY_URL, { signal: AbortSignal.timeout(4e3) });
|
|
6116
6148
|
if (!res.ok) return null;
|
package/out/main/lib.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const mockServer = require("./chunks/mock-server-C4kTFkod.js");
|
|
4
|
-
const requestExec = require("./chunks/request-exec-
|
|
4
|
+
const requestExec = require("./chunks/request-exec-CwJ8_OKC.js");
|
|
5
5
|
const flowEngine = require("./chunks/flow-engine-BVzjz4lJ.js");
|
|
6
6
|
require("node:http");
|
|
7
7
|
require("node:crypto");
|
|
@@ -11,7 +11,7 @@ require("@xmldom/xmldom");
|
|
|
11
11
|
require("undici");
|
|
12
12
|
require("fs/promises");
|
|
13
13
|
require("tls");
|
|
14
|
-
require("./chunks/handle-
|
|
14
|
+
require("./chunks/handle-DRmKOL-s.js");
|
|
15
15
|
require("node:fs");
|
|
16
16
|
require("node:os");
|
|
17
17
|
require("node:path");
|