Developers/SDK - TypeScript / Node.js

SDK - TypeScript / Node.js

@naprawksef/sdk - zero runtime dependencies, działa w Node ≥18, Bun, Deno i edge runtime.

Instalacja

bash
npm install @naprawksef/sdk
# lub
pnpm add @naprawksef/sdk
# lub
yarn add @naprawksef/sdk

Wymaga Node.js 18+. Korzysta z wbudowanego fetch i node:crypto - żadnych zewnętrznych pakietów.

Inicjalizacja

typescript
import { NaprawKsef } from "@naprawksef/sdk";

const client = new NaprawKsef({
  apiKey: process.env.NAPRAW_KSEF_API_KEY!, // nk_live_... lub nk_test_...
  appName: "trawers-erp/7.4.2",             // dorzucamy do User-Agent
  timeoutMs: 30_000,
  maxRetries: 3,                            // 0 = bez retries
});

Konstruktor waliduje format klucza - błąd konfiguracji wykryjesz przed pierwszym networkiem.

Walidacja XML

typescript
import { readFileSync } from "node:fs";

const result = await client.validate.run({
  xml: readFileSync("faktura.xml", "utf8"),
  filename: "faktura.xml",
  idempotencyKey: "invoice-42-v1", // opcjonalne, SDK generuje UUID jeśli brak
});

if (!result.valid) {
  for (const issue of result.issues) {
    console.error(`[${issue.severity}] ${issue.code}: ${issue.message}`);
  }
}

Analiza pod korekty FA(3)

typescript
const analysis = await client.correction.analyze({
  xml: readFileSync("faktura.xml", "utf8"),
});

console.log(analysis.analysis.totals);           // metadata
console.log(analysis.suggestions);               // top 5 scenariuszy
console.log(analysis.lines_jpk);                 // sugestie pól JPK_V7M

Webhooks - CRUD i test

typescript
const created = await client.webhooks.create({
  name: "Production receiver",
  url: "https://my-app.com/webhooks/napraw-ksef",
  events: ["validation.completed", "correction.created"],
});
// Plaintext sekret jest dostępny TYLKO RAZ:
console.log(created.secret);

const list = await client.webhooks.list();
const deliveries = await client.webhooks.listDeliveries(created.webhook.id);

await client.webhooks.sendTest(created.webhook.id); // smoke test
await client.webhooks.update(created.webhook.id, { is_active: false });
await client.webhooks.delete(created.webhook.id);

Weryfikacja podpisu webhooka

Można importować osobny entrypoint, jeśli endpoint webhookowy nie potrzebuje całego klienta:

typescript
import { verifyWebhookSignature } from "@naprawksef/sdk/webhooks";

export async function POST(req: Request) {
  const rawBody = await req.text();
  const result = verifyWebhookSignature({
    secret: process.env.NAPRAW_KSEF_WEBHOOK_SECRET!,
    rawBody,
    header: req.headers.get("x-nk-signature"),
  });
  if (!result.ok) return new Response(result.reason, { status: 401 });
  // …
  return new Response("ok");
}

Więcej w przewodniku Webhooks.

Typowane wyjątki

typescript
import {
  NaprawKsefRateLimitError,
  NaprawKsefAuthError,
  NaprawKsefValidationError,
} from "@naprawksef/sdk";

try {
  await client.validate.run({ xml });
} catch (e) {
  if (e instanceof NaprawKsefRateLimitError) {
    await sleep((e.retryAfterSeconds ?? 60) * 1000);
  } else if (e instanceof NaprawKsefAuthError) {
    rotateKey();
  } else if (e instanceof NaprawKsefValidationError) {
    showFieldErrors(e.details);
  } else {
    throw e;
  }
}

Obserwowalność

typescript
const client = new NaprawKsef({
  apiKey,
  hooks: {
    onResponse: ({ method, url, status, durationMs, requestId }) => {
      log.info({ method, url, status, durationMs, requestId }, "nk.api");
    },
    onRetry: ({ url, attempt, delayMs, reason }) => {
      log.warn({ url, attempt, delayMs, reason }, "nk.api.retry");
    },
  },
});
Pełny README
Pełna dokumentacja, lista typów wyjątków i przykłady receiver'ów Next.js / Express żyją w paczce na npm: npmjs.com/package/@naprawksef/sdk.