ARCHITEKTURA
Buduj na fundamencie, którego nie musisz utrzymywać.
Architektura heksagonalna z portami i adapterami. Domena bez frameworka. Plugin SDK. Realne testy integracyjne przez Testcontainers.
JAK PŁYNĄ DANE
Zamówienia, oba kierunki.
Wszystko, co OpenLinker robi, sprowadza się do dwóch portów: jedna strona czyta zdarzenia z platformy źródłowej, druga strona zapisuje je do platformy docelowej. Core OpenLinkera siedzi pomiędzy: mapowanie identyfikatorów, retry, dedup, projekcje.
Marketplace (Allegro) Shop (PrestaShop)
│ ▲
│ 1. order event │ 4. create order,
▼ │ update status
[OrderSource] [OrderProcessorManager]
│ ▲
│ 2. hydrate │ 3. map customer,
│ full order │ resolve products
▼ │
OpenLinker core ─────────────────────────┘
identifier mapping · retries · dedup · projections CAPABILITY PORTS
Otwarte kontrakty, nie zamknięte klasy.
Capability, EntityType i PlatformType to otwarte stringi na granicy rejestru. Możesz dodać ShippingProvider, PricingAuthority, albo cokolwiek innego — bez PR-a do core'a. Znany zestaw to wskazówka, nie bramka.
Każda capability jest portem domeny — abstrakcją nad tym, co system potrafi zrobić. Adapter implementuje tylko porty, których dany klient potrzebuje. Reszta nie istnieje dla niego.
FRAMEWORK-FREE DOMAIN
Zero importów NestJS lub TypeORM w warstwie domenowej.
Katalog libs/core/src/**/domain/ ma zero importów z infrastruktury. Wymuszane runtime przez package.json#exports — jeśli ktoś spróbuje zaimportować NestJS do domeny, build zfailuje. Domena żyje własnym życiem; framework jest implementacją.
// libs/core/package.json
{
"name": "@openlinker/core",
"exports": {
"./domain/*": "./src/**/domain/*.ts",
"./application/*": "./src/**/application/*.ts"
// infrastructure intentionally not exported
}
}
// libs/core/src/orders/domain/Order.ts
export class Order {
// no NestJS, no TypeORM, no infrastructure imports.
// pure TypeScript over the domain model.
} PLUGIN SDK
Pluginy kompilują się przeciwko SDK, nie przeciwko hostowi.
Adaptery zewnętrzne kompilują się przeciwko @openlinker/plugin-sdk. SDK ships AdapterPlugin contract, HostServices bag, i typed dispatchCapability<T> helper. Plugin nie wie nic o NestJS, TypeORM, czy konkretnym deployment host'cie OpenLinkera. To znaczy: agencja pisząca adapter dla jednego klienta nie musi forkować core'a, ani migrować go między wersjami NestJS.
// libs/integrations/my-marketplace/src/index.ts
import { definePlugin, OrderSource } from '@openlinker/plugin-sdk';
export default definePlugin({
name: 'my-marketplace',
capabilities: {
OrderSource: class implements OrderSource {
async read(cursor) { /* ... */ }
},
},
}); REAL TESTS
Test-kit eksportowany. Realna baza, realny PrestaShop.
Testcontainers harness ships jako @openlinker/test-kit. Testy adapterów uruchamiają realny Postgres, realny Redis, realny instans PrestaShopa w kontenerach. Bez mockowania — co działa w testach, działa w produkcji. Adaptery zewnętrzne dziedziczą tę samą infrastrukturę testów.
// libs/integrations/my-marketplace/test/orders.spec.ts
import { stack } from '@openlinker/test-kit';
test('imports orders from cursor', async () => {
const { postgres, redis, prestashop } = await stack.up();
// real containers, real APIs, no mocks.
// ...
}); NOWA INTEGRACJA
Pięć kroków do pierwszego deployu.
- 01
Scaffold
pnpm create-adapter <platforma> — generator tworzy strukturę pluginu z manifestem, testami i typowanymi portami.
- 02
Wybierz role
Czy platforma jest źródłem zamówień? Marketplace'em? Dostawcą wysyłki? Wybierasz porty, które chcesz implementować.
- 03
Implementuj
Tylko porty, których platforma wspiera. Nie musisz implementować wszystkich — niektórzy dostawcy wysyłki to tylko etykiety, niektóre marketplace'y to tylko zamówienia.
- 04
Zarejestruj
Dodaj adapter do rejestru. Wszystko jest open strings — Twoja nazwa, Twoje typy, Twoje kategorie.
- 05
Test
pnpm test uruchamia Twoje testy przeciwko realnym kontenerom z test-kit. Jeśli przeszły testy, działa w działającym appie.
Zobacz kod, klonuj repo.
Architektura jest publiczna. Apache 2.0. Wszystkie ADRy w docs/architecture/adrs/.