107 lines
4.5 KiB
TypeScript
107 lines
4.5 KiB
TypeScript
// Generated HTTP client with a synthetic RequestBusinessBinding. No gateway/live acceptance.
|
|
import type { RequestBusinessBinding } from "@conusai-kit/business"
|
|
import { Container } from "@conusai-kit/core"
|
|
import { describe, expect, it } from "vitest"
|
|
import { ledgerServiceOf, sdkLedgerService } from "../adapters/service.js"
|
|
|
|
const id = "acc_00000000-0000-4000-8000-000000000001"
|
|
const txn = "txn_00000000-0000-4000-8000-000000000001"
|
|
function adapter(response: (request: Request) => Promise<Response>) {
|
|
const calls: Request[] = []
|
|
const binding = {
|
|
orgSlug: "verified-org",
|
|
client: (factory: Parameters<RequestBusinessBinding["client"]>[0]) => {
|
|
const client = factory({ baseUrl: "https://ledger.example.test", auth: "synthetic", throwOnError: false })
|
|
client.setConfig({
|
|
fetch: async (input) => {
|
|
const request = new Request(input)
|
|
calls.push(request.clone())
|
|
return response(request)
|
|
},
|
|
})
|
|
return client
|
|
},
|
|
} as RequestBusinessBinding
|
|
return { service: sdkLedgerService(binding), calls }
|
|
}
|
|
const json = (text: string, status = 200) =>
|
|
new Response(text, { status, headers: { "content-type": "application/json" } })
|
|
describe("generated Ledger HTTP adapter (synthetic fetch tier)", () => {
|
|
it("retains raw JSON integers above 2^53 in balances and revisions", async () => {
|
|
const a = adapter(async (request) =>
|
|
request.url.includes("balances")
|
|
? json(
|
|
`{"data":[{"account_id":"${id}","currency":"EUR","posted":9007199254740993,"pending":-9007199254740993,"available":9223372036854775807}]}`,
|
|
)
|
|
: json(
|
|
`{"ext":{},"id":"${id}","code":"TEST","name":"Synthetic","currency":"EUR","type":"asset","normal_balance":"debit","allow_negative":false,"status":"active","revision":9007199254740993}`,
|
|
),
|
|
)
|
|
expect((await a.service.balances()).rows[0]).toMatchObject({
|
|
posted: "9007199254740993",
|
|
pending: "-9007199254740993",
|
|
available: "9223372036854775807",
|
|
})
|
|
expect((await a.service.account(id)).revision).toBe("9007199254740993")
|
|
expect(new URL(a.calls[0]?.url ?? "").pathname).toContain("/orgs/verified-org/ledger/balances")
|
|
})
|
|
it("sends exact unquoted i64 amount and revision tokens through generated SDK serialization", async () => {
|
|
const bodies: string[] = []
|
|
const a = adapter(async (request) => {
|
|
bodies.push(await request.text())
|
|
return json(
|
|
`{"ext":{},"id":"${txn}","revision":9007199254740993,"effective_at":"2026-11-03T00:00:00Z","description":"Synthetic","status":"pending","entries":[]}`,
|
|
)
|
|
})
|
|
await a.service.record(
|
|
{
|
|
effectiveAt: "2026-11-03T00:00:00Z",
|
|
description: "Synthetic",
|
|
status: "pending",
|
|
entries: [
|
|
{ accountId: id, direction: "debit", amountMinor: "9007199254740993" },
|
|
{ accountId: id, direction: "credit", amountMinor: "9007199254740993" },
|
|
],
|
|
},
|
|
"stable-key",
|
|
)
|
|
await a.service.transition("post", txn, "9007199254740993", "stable-post")
|
|
expect(bodies[0]).toContain('"amount_minor":9007199254740993')
|
|
expect(bodies[0]).toContain('"idempotency_key":"stable-key"')
|
|
expect(bodies[1]).toContain('"revision":9007199254740993')
|
|
})
|
|
it("redacts domain conflicts, invalid inputs and upstream failures", async () => {
|
|
for (const [status, reason, code] of [
|
|
[409, "revision-conflict", "business_revision_conflict"],
|
|
[409, "idempotency-conflict", "business_idempotency_conflict"],
|
|
[422, "unbalanced", "business_unbalanced"],
|
|
[422, "invalid-request", "business_invalid"],
|
|
[503, "unavailable", "business_unavailable"],
|
|
] as const) {
|
|
const a = adapter(async () =>
|
|
json(
|
|
JSON.stringify({
|
|
type: `urn:conusai:ledger:${reason}`,
|
|
status,
|
|
code: `LEDGER_${reason.replaceAll("-", "_").toUpperCase()}`,
|
|
title: "SENSITIVE",
|
|
detail: "SECRET_PERSON_TOKEN",
|
|
}),
|
|
status,
|
|
),
|
|
)
|
|
try {
|
|
await a.service.account(id)
|
|
throw new Error("expected refusal")
|
|
} catch (error) {
|
|
expect(JSON.stringify(error)).not.toMatch(/SENSITIVE|SECRET_PERSON_TOKEN/)
|
|
expect(error).toHaveProperty("problem.status", status)
|
|
expect(error).toHaveProperty("problem.code", code)
|
|
}
|
|
}
|
|
})
|
|
it("refuses missing or unverified request binding without deployment credential fallback", () => {
|
|
expect(() => ledgerServiceOf(new Container(), "effect")).toThrow()
|
|
})
|
|
})
|