🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@ksefnik/simulator

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ksefnik/simulator - npm Package Compare versions

Comparing version
0.0.1
to
0.1.0
+164
README.md
# @ksefnik/simulator — offline mock KSeF dla testów (TypeScript / Node.js)
**Mock serwera Krajowego Systemu e-Faktur (KSeF 2.0) do testów jednostkowych, integracyjnych i CI** — dla [Ksefnika](https://ksefnik.pl/), otwartego **KSeF SDK w TypeScript / Node.js**. Wstrzykujesz go w miejsce `@ksefnik/http`, odpalasz cały pipeline reconcyliacji offline, i masz deterministyczne, powtarzalne testy bez jednego requestu do `api.ksef.mf.gov.pl` — bez tokenu KSeF, bez klucza publicznego MF, bez zależności od dostępności środowiska testowego Ministerstwa Finansów.
Jeżeli szukasz **mocka do KSeF**, **test harness dla polskiej e-faktury** albo **KSeF sandbox offline** do CI w GitHub Actions — to jest ten pakiet. [Dokumentacja →](https://docs.ksefnik.pl/symulator/happy-path/)
Po co to w ogóle istnieje:
- **CI nie może rozmawiać z produkcją.** KSeF nie ma publicznego sandboxa otwartego dla każdego workflowa GitHub Actions.
- **Środowisko testowe MF (`api-test.ksef.mf.gov.pl`) bywa niestabilne.** W dniu releasu nie chcesz zielonego/czerwonego CI uzależnionego od tego, czy serwer resortowy akurat odpowiada.
- **Potrzebujesz scenariuszy brzegowych.** 429, timeout, wygasła sesja, błąd walidacji NIP, opóźnione UPO. Nie da się tego wymusić na produkcji.
- **Chcesz e2e bez sekretów.** Brak tokenu, brak klucza publicznego, brak NIP — `@ksefnik/simulator` działa w każdym workflow, również w forkach od zewnętrznych kontrybutorów.
## Instalacja
```bash
pnpm add -D @ksefnik/simulator @ksefnik/core @ksefnik/shared
```
Pakiet jest typowym **devDependency** — do produkcji idzie wyłącznie `@ksefnik/http`.
## Szybki start
```ts
import { createKsefnik } from '@ksefnik/core'
import { MockKsefAdapter, InvoiceStore, happyPath } from '@ksefnik/simulator'
// 1. Stwórz magazyn faktur i załaduj scenariusz
const store = new InvoiceStore()
happyPath(store) // dorzuca kilkanaście realistycznych faktur do store
// 2. Podepnij mock adapter
const adapter = new MockKsefAdapter(store)
const ksef = createKsefnik({
config: { nip: '7010002137', environment: 'test', token: 'fake-token' },
adapter,
})
// 3. Od teraz wszystko działa jak z prawdziwym KSeF — ale offline
const invoices = await ksef.invoices.fetch({ from: '2026-03-01', to: '2026-03-31' })
```
## Co jest w środku
### `MockKsefAdapter`
Implementacja `KsefAdapter` z `@ksefnik/shared` — ten sam interfejs co `@ksefnik/http`, więc kod produkcyjny nie wie, że odpowiada mu mock.
- `fetchInvoices(opts)` — filtruje `InvoiceStore` po dacie, NIP, `subjectType`
- `sendInvoice(input)` — generuje deterministyczną referencję `KSEF-SIM-<timestamp>-<random>`
- `getUpo(ref)` — zwraca symulowane UPO (z opcjonalnym opóźnieniem przez hook)
- `initSession()` / `closeSession()` — no-op, ale wołane tak jak przez HTTP adapter
Hooki pozwalają wstrzyknąć asercje lub wymusić błędy:
```ts
const adapter = new MockKsefAdapter(store, {
beforeFetch: async (opts) => {
expect(opts.from).toBe('2026-03-01')
},
beforeSend: async (input) => {
if (input.nip === '0000000000') throw new Error('Invalid NIP')
},
beforeGetUpo: async (ref) => {
if (ref.startsWith('KSEF-SIM-999')) return { ksefReference: ref, upoXml: '...', status: 'pending' }
return null
},
})
```
### `InvoiceStore`
In-memory magazyn faktur z filtrowaniem po zakresie dat. Używany przez adapter jako backend. Sam jest bardzo prosty — listy faktur wchodzą, listy faktur wychodzą — ale dzięki temu scenariusze są trywialne do pisania i czytania w code review.
### Scenariusze (`scenarios/`)
Gotowe "fixturki", które ładują realistyczne dane do `InvoiceStore`:
| Scenariusz | Zastosowanie |
|---|---|
| `happyPath(store)` | Reprezentatywny zestaw faktur sprzedażowych i zakupowych, różne kwoty, różne NIP-y, różne stawki VAT. Używaj jako default w testach jednostkowych reconcyliacji. |
| `timeout(store)` | Adapter zwraca się po konfigurowalnym opóźnieniu. Testuj retry policy, timeouty HTTP. |
| `invalidNip(store)` | Faktury z błędnymi NIP-ami (suma kontrolna, `0000000000`). Testuj pipeline walidacji. |
| `sessionExpired(store)` | `fetchInvoices` rzuca `KsefAuthError` przy pierwszym wywołaniu. Testuj ponowne logowanie i refresh tokenów. |
| `upoDelay(store)` | `getUpo` zwraca `status: 'pending'` przez pierwsze N wywołań. Testuj polling. |
Każdy scenariusz to jedna funkcja, więc trywialnie łączysz kilka na raz:
```ts
import { happyPath, upoDelay } from '@ksefnik/simulator'
happyPath(store)
upoDelay(store) // nadpisuje hook getUpo
```
### Własny scenariusz
```ts
import { InvoiceStore, type Invoice } from '@ksefnik/simulator'
export function myScenario(store: InvoiceStore) {
const invoice: Invoice = {
id: 'inv-001',
ksefReference: 'KSEF-2026-03-001',
invoiceNumber: 'FV/2026/03/001',
issueDate: '2026-03-15',
seller: { nip: '7010002137', name: 'Sprzedawca sp. z o.o.' },
buyer: { nip: '5261040828', name: 'Nabywca S.A.' },
totalAmount: 123456, // grosze
currency: 'PLN',
// ...
}
store.add(invoice)
}
```
## Testy z Vitest
```ts
import { describe, it, expect, beforeEach } from 'vitest'
import { createKsefnik } from '@ksefnik/core'
import { MockKsefAdapter, InvoiceStore, happyPath } from '@ksefnik/simulator'
describe('reconciliation pipeline', () => {
let ksef: ReturnType<typeof createKsefnik>
beforeEach(() => {
const store = new InvoiceStore()
happyPath(store)
const adapter = new MockKsefAdapter(store)
ksef = createKsefnik({
config: { nip: '7010002137', environment: 'test', token: 'test' },
adapter,
})
})
it('dopasowuje po referencji KSeF', async () => {
const invoices = await ksef.invoices.fetch({ from: '2026-03-01', to: '2026-03-31' })
const transactions = [/* ... */]
const report = await ksef.reconciliation.run({ invoices, transactions })
expect(report.matched).toHaveLength(invoices.length)
expect(report.matched[0]?.strategy).toBe('ksef-ref')
})
})
```
## Co to **nie** jest
- **Nie jest walidatorem schematu KSeF.** Nie sprawdza zgodności z XSD FA(2)/FA(3). Do tego służy `validation/` w `@ksefnik/core` + pełny walidator w `@ksefnik/pro` (planowany).
- **Nie jest load testerem.** Nie symuluje rate limitów MF (`8 req/s`, `20 req/h`) — to jest w `@ksefnik/http` i testy rate limit powinny używać prawdziwego klienta z mockowaniem `fetch`.
- **Nie symuluje kryptografii MF.** Challenge/response z RSA-OAEP SHA-256 jest w `@ksefnik/http`. Simulator pomija całą warstwę sesji.
## Powiązane pakiety
- [`@ksefnik/shared`](../shared) — kontrakt `KsefAdapter`
- [`@ksefnik/core`](../core) — silnik reconcyliacji, z którym łączysz simulator
- [`@ksefnik/http`](../http) — produkcyjny odpowiednik dla prawdziwego KSeF
## Licencja
MIT. Część monorepo [ksefnik](../../README.md) — open-source project od [CodeFormers.it](https://codeformers.it/). Jeżeli Twój zespół potrzebuje custom scenariuszy testowych KSeF pod skomplikowany flow księgowy (np. faktury zbiorcze, korekty, kompensaty, waluty obce) — [napisz do nas](https://codeformers.it/), robimy takie rzeczy na co dzień.
+44
-11
{
"name": "@ksefnik/simulator",
"version": "0.0.1",
"version": "0.1.0",
"description": "Offline KSeF mock server for testing and development without hitting the real Ministry of Finance API",

@@ -13,7 +13,40 @@ "license": "MIT",

},
"keywords": ["ksef", "ksefnik", "simulator", "mock", "testing", "einvoice"],
"keywords": [
"ksef",
"ksefnik",
"ksef-mock",
"ksef-simulator",
"ksef-test",
"ksef-sandbox",
"ksef-sdk",
"ksef-2",
"e-invoice",
"einvoice",
"e-faktura",
"faktura",
"poland",
"polish",
"krajowy-system-e-faktur",
"invoice",
"typescript",
"nodejs",
"sdk",
"mock",
"simulator",
"testing",
"test-harness",
"offline",
"vitest",
"ci"
],
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": ["dist", "!dist/**/__tests__", "!dist/**/*.test.*", "README.md", "LICENSE"],
"files": [
"dist",
"!dist/**/__tests__",
"!dist/**/*.test.*",
"README.md",
"LICENSE"
],
"publishConfig": {

@@ -28,2 +61,9 @@ "access": "public"

},
"dependencies": {
"@ksefnik/shared": "^0.1.0",
"@ksefnik/core": "^0.1.0"
},
"devDependencies": {
"typescript": "^5.7"
},
"scripts": {

@@ -33,10 +73,3 @@ "build": "tsc --build",

"typecheck": "tsc --noEmit"
},
"dependencies": {
"@ksefnik/shared": "workspace:^",
"@ksefnik/core": "workspace:^"
},
"devDependencies": {
"typescript": "^5.7"
}
}
}