Files
wehub-resource-sync e0e362d700
SDK Tests / changes (push) Successful in 2m29s
Real E2E Tests / changes (push) Successful in 2m29s
Deploy Docs Pages / build (push) Has been cancelled
Deploy Docs Pages / deploy (push) Has been cancelled
Real E2E Tests / JavaScript E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Python E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Java E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / C# E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Go E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Real E2E CI (push) Has been cancelled
SDK Tests / SDK CI (push) Has been cancelled
SDK Tests / CLI Tests (push) Has been cancelled
SDK Tests / Python SDK Quality (code-interpreter) (push) Has been cancelled
SDK Tests / Python SDK Quality (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (sandbox) (push) Has been cancelled
SDK Tests / CLI Quality (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Go SDK Quality And Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:39:33 +08:00

273 lines
8.0 KiB
JavaScript

import assert from "node:assert/strict";
import { readdir, readFile } from "node:fs/promises";
import test from "node:test";
import { EgressAdapter } from "../dist/internal.js";
const credential = {
name: "api-token",
source: { value: "write-only-value" },
};
const binding = {
name: "api-binding",
match: {
schemes: ["https"],
hosts: ["api.example.com"],
methods: ["GET", "POST"],
paths: ["/v1/*"],
},
auth: {
type: "apiKey",
name: "X-API-Key",
credential: "api-token",
},
};
const sanitizedCredential = {
name: "api-token",
sourceType: "inline",
revision: 7,
};
const sanitizedBinding = {
name: "api-binding",
revision: 5,
match: {
schemes: ["https"],
hosts: ["api.example.com"],
methods: ["GET", "POST"],
paths: ["/v1/*"],
},
auth: {
type: "apiKey",
name: "X-API-Key",
},
};
function stateResponse() {
return {
revision: 9,
credentials: [
{
...sanitizedCredential,
source: { type: "inline", value: "write-only-value" },
},
],
bindings: [
{
...sanitizedBinding,
auth: {
...sanitizedBinding.auth,
credential: "api-token",
headers: [{ name: "X-Extra", credential: "api-token" }],
},
},
],
};
}
function jsonResponse(body, init = {}) {
return new Response(body == null ? null : JSON.stringify(body), {
status: init.status ?? 200,
headers: {
"content-type": "application/json",
...(init.headers ?? {}),
},
});
}
function createAdapter() {
const requests = [];
const fetchImpl = async (input, init = {}) => {
const url = new URL(String(input));
const bodyText = typeof init.body === "string" ? init.body : undefined;
const request = {
method: init.method ?? "GET",
url: String(input),
pathname: url.pathname,
headers: Object.fromEntries(new Headers(init.headers).entries()),
body: bodyText ? JSON.parse(bodyText) : undefined,
};
requests.push(request);
if (request.pathname === "/credential-vault") {
if (request.method === "DELETE") {
return new Response(null, { status: 204 });
}
return jsonResponse(stateResponse());
}
if (request.pathname === "/credential-vault/credentials") {
return jsonResponse({
revision: 9,
credentials: [stateResponse().credentials[0]],
});
}
if (request.pathname === "/credential-vault/credentials/api-token%2Fprimary") {
return jsonResponse(stateResponse().credentials[0]);
}
if (request.pathname === "/credential-vault/bindings") {
return jsonResponse({
revision: 9,
bindings: [stateResponse().bindings[0]],
});
}
if (request.pathname === "/credential-vault/bindings/api%20binding") {
return jsonResponse(stateResponse().bindings[0]);
}
return jsonResponse({ code: "NOT_FOUND", message: "not found" }, { status: 404 });
};
const policyClient = {
GET() {
throw new Error("policy GET was not expected");
},
PATCH() {
throw new Error("policy PATCH was not expected");
},
DELETE() {
throw new Error("policy DELETE was not expected");
},
};
return {
adapter: new EgressAdapter(policyClient, {
baseUrl: "https://egress.example",
fetch: fetchImpl,
headers: {
"OPEN-SANDBOX-API-KEY": "sdk-key",
"x-endpoint-token": "route-token",
},
}),
requests,
};
}
test("EgressAdapter sends Credential Vault JSON payloads with endpoint headers", async () => {
const { adapter, requests } = createAdapter();
const created = await adapter.create({
credentials: [credential],
bindings: [binding],
});
await adapter.patch({
expectedRevision: 9,
credentials: {
add: [credential],
replace: [credential],
delete: ["old-token"],
},
bindings: {
add: [binding],
replace: [binding],
delete: ["old-binding"],
},
});
const current = await adapter.get();
const credentials = await adapter.listCredentials();
const oneCredential = await adapter.getCredential("api-token/primary");
const bindings = await adapter.listBindings();
const oneBinding = await adapter.getBinding("api binding");
await adapter.delete();
assert.deepEqual(created, {
revision: 9,
credentials: [sanitizedCredential],
bindings: [sanitizedBinding],
});
assert.deepEqual(current, created);
assert.deepEqual(credentials, [sanitizedCredential]);
assert.deepEqual(oneCredential, sanitizedCredential);
assert.deepEqual(bindings, [sanitizedBinding]);
assert.deepEqual(oneBinding, sanitizedBinding);
assert.deepEqual(
requests.map((request) => [request.method, request.pathname]),
[
["POST", "/credential-vault"],
["PATCH", "/credential-vault"],
["GET", "/credential-vault"],
["GET", "/credential-vault/credentials"],
["GET", "/credential-vault/credentials/api-token%2Fprimary"],
["GET", "/credential-vault/bindings"],
["GET", "/credential-vault/bindings/api%20binding"],
["DELETE", "/credential-vault"],
],
);
assert.equal(requests[0].headers["open-sandbox-api-key"], "sdk-key");
assert.equal(requests[0].headers["x-endpoint-token"], "route-token");
assert.equal(requests[0].headers["content-type"], "application/json");
assert.equal(requests[2].headers["content-type"], undefined);
assert.deepEqual(requests[0].body, {
credentials: [credential],
bindings: [binding],
});
assert.deepEqual(requests[1].body, {
expectedRevision: 9,
credentials: {
add: [credential],
replace: [credential],
delete: ["old-token"],
},
bindings: {
add: [binding],
replace: [binding],
delete: ["old-binding"],
},
});
});
test("Credential Vault state omits plaintext secret fields", async () => {
const { adapter } = createAdapter();
const state = await adapter.get();
assert.equal(Object.hasOwn(state.credentials[0], "source"), false);
assert.equal(Object.hasOwn(state.bindings[0].auth, "credential"), false);
assert.equal(Object.hasOwn(state.bindings[0].auth, "headers"), false);
const dts = await readDistDeclarations();
const inlineCredentialSource = declarationBlock(dts, "InlineCredentialSource");
const credentialMetadata = declarationBlock(dts, "CredentialMetadata");
const authMetadata = declarationBlock(dts, "CredentialAuthMetadata");
const bindingMetadata = declarationBlock(dts, "CredentialBindingMetadata");
assert.match(inlineCredentialSource, /\btype\?: "inline"/);
assert.doesNotMatch(credentialMetadata, /extends Record/);
assert.doesNotMatch(credentialMetadata, /\bsource\s*[?:]/);
assert.doesNotMatch(authMetadata, /extends Record/);
assert.doesNotMatch(authMetadata, /\bcredential\s*[?:]/);
assert.doesNotMatch(authMetadata, /\bheaders\s*[?:]/);
assert.doesNotMatch(bindingMetadata, /extends Record/);
assert.match(bindingMetadata, /\bauth\??: CredentialAuthMetadata/);
});
test("Egress declarations keep Credential Vault optional for custom adapters", async () => {
const dts = await readDistDeclarations();
const egress = declarationBlock(dts, "Egress");
const egressStack = declarationBlock(dts, "EgressStack");
assert.doesNotMatch(egress, /extends CredentialVault/);
assert.doesNotMatch(egress, /\bcreate\(/);
assert.match(egressStack, /\begress: Egress/);
assert.match(egressStack, /\bcredentialVault\??: CredentialVault/);
});
async function readDistDeclarations() {
const distDir = new URL("../dist/", import.meta.url);
const entries = await readdir(distDir);
const declarations = entries.filter((entry) => entry.endsWith(".d.ts"));
const contents = await Promise.all(
declarations.map((entry) => readFile(new URL(entry, distDir), "utf8")),
);
return contents.join("\n");
}
function declarationBlock(dts, name) {
const start = dts.indexOf(`interface ${name}`);
assert.notEqual(start, -1, `missing ${name} declaration`);
const end = dts.indexOf("\n}", start);
assert.notEqual(end, -1, `missing ${name} declaration end`);
return dts.slice(start, end + 2);
}