Stability & versioning
This page is the contract between Lonca and your integration: what we promise to keep stable, what we deliberately leave outside the promise, and how changes reach you.
Versioning policy
Section titled “Versioning policy”All packages follow Semantic Versioning.
From 1.0.0 onwards:
- The public API is stable. Breaking changes ship only in major versions.
- Deprecations are announced at least two minor versions before removal — a deprecated export keeps working (with a
@deprecatedTSDoc tag and a CHANGELOG notice) until the next major. - New features arrive in minors; fixes in patches.
Each package’s CHANGELOG.md is generated by Changesets and is the source of truth for what changed in every release.
What counts as the public API
Section titled “What counts as the public API”The public API is everything exported from these entry points:
| Package | Entry points |
|---|---|
@lonca/core |
. (root) |
@lonca/trendyol |
. (root), ./testing |
@lonca/hepsiburada |
. (root), ./testing |
That surface is locked in CI: the rolled-up type declarations of all five entry points are snapshotted in etc/*.snapshot, and pnpm api:check fails any pull request that changes them without explicitly updating the snapshot. An API change is therefore always visible in review — never accidental.
What does NOT count
Section titled “What does NOT count”- Wire-level details behind normalisers. The contents of
rawpayload fields mirror whatever the marketplace returned. They are passed through for debugging, not normalised, and may change whenever the marketplace changes. - Marketplace behaviour itself. Trendyol and Hepsiburada can change their APIs without notice. The contract-probe suite (
pnpm probe:check, run locally against live endpoints) detects that drift, but drift is not a Lonca breaking change. - Undocumented passthrough fields on inputs. If a field is not in an input’s type, sending it may happen to work — that is not covered by semver.
How marketplace changes are caught
Section titled “How marketplace changes are caught”Three checks keep the SDK types honest against what the marketplaces actually send:
- Specs.
specs/holds the marketplaces’ own OpenAPI definitions (Hepsiburada’s portal export, Trendyol’s developer-portal definitions), regenerated by script. - Live shapes. The contract probes record the key sets and JSON types — never values — of real production responses for the main read endpoints, and
pnpm driftcompares them with the specs (undocumented fields, type mismatches, missing required fields). Accepted, explained differences live inprobe-snapshots/known-discrepancies.json. - SDK types.
pnpm drift:typescompares the SDK’s TypeScript types with the specs and the recorded shapes; CI publishes it as a warning-only report on every pull request.
When a check finds that a field the SDK exposes never arrives, the field is kept and marked @deprecated with its replacement (a minor release), not removed — see 1.1.0 for an example.
Supported runtimes
Section titled “Supported runtimes”- Node.js >= 22 (declared in each package’s
engines). - Both ESM and CJS consumers are supported; every entry point ships dual builds with matching type declarations, verified in CI with
publintand@arethetypeswrong/cli.
Documented transport behaviours
Section titled “Documented transport behaviours”The following @lonca/core transport behaviours are deliberate. They are part of the documented contract, not bugs:
safeJsonreturns the raw body text asTfor non-JSON 200 responses. Marketplaces occasionally return plain text on success; surfacing it beats throwing away a 200.- A caller abort during retry backoff throws the raw abort reason, not a
LoncaError. Your abort is your signal — wrapping it would hide the reason you passed toAbortController.abort(). Retry-After: 0(or a negative/past value) is ignored. A non-positive hint would collapse exponential backoff into an immediate retry loop against an already-throttling server.- A body on a
GETrequest is silently discarded. GET bodies are undefined behaviour in HTTP and rejected by many intermediaries, so the transport never sends one. - A caller-supplied
Content-Typeheader is dropped when the body isFormData.fetchmust generate the multipart header itself because it contains the boundary; a manual value would corrupt the upload.
Security disclosure
Section titled “Security disclosure”Report vulnerabilities privately as described in SECURITY.md — please do not open a public issue for security problems.
Release cadence
Section titled “Release cadence”Releases are cut from main via Changesets: merged PRs accumulate changeset entries, a release PR aggregates them, and merging it publishes to npm. Packages are published with npm provenance through OIDC trusted publishing from GitHub Actions, so every version on npm is verifiably built from this repository.
Unofficial. Lonca is an independent, community-maintained project — not affiliated with, endorsed by, or supported by Trendyol, Hepsiburada, or any other marketplace. All marketplace names and trademarks belong to their respective owners.