@stewardhq/sdk 0.2.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +123 -88
- package/dist/_chunks/errors.js +1 -1
- package/dist/_chunks/events.d.ts +315 -4
- package/dist/_chunks/events.js +1155 -9
- package/dist/_chunks/index.d.ts +3473 -90
- package/dist/_chunks/locale.d.ts +269 -1
- package/dist/_chunks/src.js +842 -24
- package/dist/_chunks/validators.d.ts +45 -1
- package/dist/_chunks/validators.js +128 -27
- package/dist/contract.d.ts +4 -4
- package/dist/contract.js +4 -4
- package/dist/index.d.ts +436 -22
- package/dist/index.js +1659 -26
- package/dist/server.d.ts +44 -6
- package/dist/server.js +29 -2
- package/package.json +4 -10
- package/dist/_chunks/steward.d.ts +0 -189
- package/dist/_chunks/steward.js +0 -560
- package/dist/testing/fixtures/events/LOCK.json +0 -27
- package/dist/testing/fixtures/events/account.deleted.json +0 -36
- package/dist/testing/fixtures/events/account.state_changed.json +0 -53
- package/dist/testing/fixtures/events/account.updated.json +0 -37
- package/dist/testing/fixtures/events/checkout.completed.json +0 -36
- package/dist/testing/fixtures/events/checkout.expired.json +0 -26
- package/dist/testing/fixtures/events/checkout.failed.json +0 -27
- package/dist/testing/fixtures/events/invoice.created.json +0 -37
- package/dist/testing/fixtures/events/invoice.issued.json +0 -38
- package/dist/testing/fixtures/events/invoice.voided.json +0 -39
- package/dist/testing/fixtures/events/subscription.activated.json +0 -40
- package/dist/testing/fixtures/events/subscription.cancel_scheduled.json +0 -38
- package/dist/testing/fixtures/events/subscription.canceled.json +0 -29
- package/dist/testing/fixtures/events/subscription.expired.json +0 -27
- package/dist/testing/fixtures/events/subscription.payment_failed.json +0 -38
- package/dist/testing/fixtures/events/subscription.reactivated.json +0 -36
- package/dist/testing/fixtures/events/subscription.renewed.json +0 -39
- package/dist/testing/fixtures/events/subscription.suspended.json +0 -36
- package/dist/testing/fixtures/events/subscription.terminated.json +0 -28
- package/dist/testing.d.ts +0 -626
- package/dist/testing.js +0 -3638
package/README.md
CHANGED
|
@@ -17,13 +17,11 @@ ESM, Node ≥ 22. Tek çalışma zamanı bağımlılığı zod.
|
|
|
17
17
|
|
|
18
18
|
| Import | İçerik |
|
|
19
19
|
| --- | --- |
|
|
20
|
-
| `@stewardhq/sdk` | Tüm şema/tipler + fırlatan istemci `createSteward`, hesap durumu önbelleği `stateCache`, `defineCatalog`, hata sınıfları + `httpStatusFor`, `isValidTckn`/`isValidVkn`/`isE164` |
|
|
20
|
+
| `@stewardhq/sdk` | Tüm şema/tipler + fırlatan istemci `createSteward`, hesap durumu önbelleği `stateCache`, `defineCatalog`, hata sınıfları + `httpStatusFor`, `isValidTckn`/`isValidVkn`/`isE164`; metering: `Events()`, `Meters()` |
|
|
21
21
|
| `@stewardhq/sdk/contract` | Yalnızca şemalar ve tipler |
|
|
22
22
|
| `@stewardhq/sdk/webhook` | `signWebhook` / `verifyWebhook` / `verifyWebhookRaw` (Node HMAC, senkron) |
|
|
23
23
|
| `@stewardhq/sdk/webhook/web` | Aynı API WebCrypto ile (async; edge/workerd/tarayıcı) |
|
|
24
|
-
| `@stewardhq/sdk/testing/fixtures/events/<tür>.json` | Her event türünün örnek gövdesi |
|
|
25
24
|
| `@stewardhq/sdk/server` | `Webhooks()`: imzalı event alıcısı, canlı durum + önbellek, tipli hook'lar (Node); `Checkout()`: hosted checkout oturumu (`create` → `url`) ve dönüş sonucu (`result`); `CustomerPortal()`: hosted müşteri portalı oturumu (`create` → `url`) |
|
|
26
|
-
| `@stewardhq/sdk/testing` | Test çiftleri (Node): `createFakeSteward()` (HTTP düzeyinde sahte steward, `simulate.*`, `connect`), `signedEvent()` |
|
|
27
25
|
|
|
28
26
|
Kök giriş, `./contract` ve `./webhook/web` `node:*` kullanmaz (edge/tarayıcı);
|
|
29
27
|
`./webhook` senkron Node HMAC'idir.
|
|
@@ -304,6 +302,101 @@ const placeholder = catalog.stateOf("org_1", "team", { accessState: "active", di
|
|
|
304
302
|
katalogda yoksa varsayılan plandan) alır, asla "sınırsız" üretmez; `onFallback`
|
|
305
303
|
ile alarm verilebilir. Snapshot yoksa varsayılan planın hakları.
|
|
306
304
|
|
|
305
|
+
Benefits (billing core) — reusable definitions plans list by code; `rank` is optional (the
|
|
306
|
+
benefits resolution does not read it). A `featureFlag()` sets catalog features with their
|
|
307
|
+
types; an undefined benefit or feature key and a wrong value type do not compile:
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
import { defineCatalog, featureFlag, flag, limit } from "@stewardhq/sdk";
|
|
311
|
+
|
|
312
|
+
export const catalog = defineCatalog({
|
|
313
|
+
defaultPlan: "free",
|
|
314
|
+
features: { max_projects: limit(), sso: flag() },
|
|
315
|
+
benefits: { sso: featureFlag({ sso: true }, { description: { tr: "Tek oturum açma", en: "Single sign-on" } }) },
|
|
316
|
+
plans: {
|
|
317
|
+
free: { name: "Free", sellable: false, entitlements: { max_projects: 1, sso: false } },
|
|
318
|
+
team: { name: "Team", sellable: true, entitlements: { max_projects: null, sso: false }, benefits: ["sso"] },
|
|
319
|
+
},
|
|
320
|
+
prices: [{ plan: "team", interval: "month", currency: "TRY", amountMinor: 125_000, taxInclusive: true, taxRateBps: 2000 }],
|
|
321
|
+
});
|
|
322
|
+
type BenefitCode = typeof catalog.$benefit; // "sso"
|
|
323
|
+
const { benefits } = await state.state(orgId); // [{ code, type, properties, source, grantedAt }]; code typed
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
`entitlementsOf`, `resolve` and `stateOf` take a plan's entitlements from the contract's
|
|
327
|
+
resolver (`resolveEntitlements`), the rule steward applies. `steward catalog push` sends a
|
|
328
|
+
catalog with benefits only to a steward whose `me().capabilities` lists `"benefits"`.
|
|
329
|
+
|
|
330
|
+
`Webhooks()` gains `onInvoicePaid` (`invoice.paid`) and `onBenefitGranted` / `onBenefitRevoked`
|
|
331
|
+
(`benefit_grant.created` / `.revoked`, with `benefit` and `grantId`; list these types in the
|
|
332
|
+
endpoint's `eventTypes`); like every hook they get the live `state`. Invoices and subscriptions
|
|
333
|
+
(billing core): `steward.invoices.createPaymentSession(id, { locale?, returnUrl? })` → `{ id, url,
|
|
334
|
+
expiresAt }` (redirect to steward's pay page), `steward.invoices.waive(id, { reason })`,
|
|
335
|
+
`steward.subscriptions.change(id, { planCode?, interval?, price?: "current", when: "next_period" })`,
|
|
336
|
+
`steward.subscriptions.uncancel(id)`.
|
|
337
|
+
|
|
338
|
+
Metering (phase 2) — the product records WHAT HAPPENED as events; catalog meters (a saved filter
|
|
339
|
+
+ an aggregation) decide what counts as usage; credits are `meterCredit()` benefits; a metered
|
|
340
|
+
price bills overage on the renewal invoice. Units may be decimals (≤ 6 places; the SDK computes in
|
|
341
|
+
micro units, never float math):
|
|
342
|
+
|
|
343
|
+
```ts
|
|
344
|
+
import { count, defineCatalog, Events, meter, meterCredit, Meters, sum } from "@stewardhq/sdk";
|
|
345
|
+
|
|
346
|
+
export const catalog = defineCatalog({
|
|
347
|
+
defaultPlan: "free",
|
|
348
|
+
features: { max_projects: limit(), sso: flag() },
|
|
349
|
+
benefits: { tokens_50k: meterCredit("ai_tokens", { units: 50_000 }), tokens_2m: meterCredit("ai_tokens", { units: 2_000_000, rollover: { capUnits: 1_000_000 } }) },
|
|
350
|
+
meters: {
|
|
351
|
+
ai_tokens: meter({ event: "ai.completion", aggregate: sum("tokens"), label: { tr: "AI token", en: "AI tokens" } }),
|
|
352
|
+
api_calls: meter({ aggregate: count(), label: { tr: "API isteği", en: "API requests" },
|
|
353
|
+
filter: { and: [{ name: "api.request" }, { "metadata.status": { lt: 500 } }] } }),
|
|
354
|
+
},
|
|
355
|
+
plans: { free: { …, benefits: ["tokens_50k"] }, team: { …, benefits: ["tokens_2m"] } },
|
|
356
|
+
prices: [{ plan: "team", interval: "month", currency: "TRY", amountMinor: 125_000, taxInclusive: true, taxRateBps: 2000 }],
|
|
357
|
+
meteredPrices: [{ plan: "team", meter: "ai_tokens", currency: "TRY", amountMinor: 1_250, perUnits: 1_000, taxInclusive: true, taxRateBps: 2000 }],
|
|
358
|
+
});
|
|
359
|
+
type Meter = typeof catalog.$meter; // "ai_tokens" | "api_calls"
|
|
360
|
+
type Event = typeof catalog.$event; // "ai.completion" (the `event` shorthands)
|
|
361
|
+
|
|
362
|
+
export const events = Events({ steward, catalog, actorRef: "service:api" });
|
|
363
|
+
export const meters = Meters({ steward, catalog, cache: state, events });
|
|
364
|
+
|
|
365
|
+
const gate = await meters.check(org.id, "ai_tokens", { units: estimatedTokens });
|
|
366
|
+
if (!gate.allowed) return c.json({ error: "credits_exhausted", balance: gate.balance }, 402);
|
|
367
|
+
events.track(org.id, "ai.completion", { tokens: 1500, model: "gpt-4o" }, { externalId: `cmpl_${res.id}` });
|
|
368
|
+
process.once("SIGTERM", () => void events.flush()); // the SDK never hooks process events
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
- `Events({ steward, catalog?, actorRef?, flushIntervalMs = 2000, maxBatch = 500, maxQueue = 10_000,
|
|
372
|
+
autoFlush = true, onRejected?, onDrop? })`: `track(ref, name, metadata?, { externalId?, timestamp? })`
|
|
373
|
+
is sync and never throws (an invalid event → WARN + `onDrop`); batches go to `POST
|
|
374
|
+
/v1/events/ingest` with one `Idempotency-Key` per batch, reused by every retry (`503
|
|
375
|
+
events_backlog` included); after the retries the batch waits at the front of the queue (backoff
|
|
376
|
+
≤ 30 s); a full queue hands its OLDEST events to `onDrop(events, { reason: "queue_full" })`, an
|
|
377
|
+
invalid event and a batch refused for good (4xx) go there too (`"invalid_event"`,
|
|
378
|
+
`"request_failed"`); per-event rejections go to `onRejected(rejected)` (not retried). `track`
|
|
379
|
+
stamps `timestamp` with the call's time unless given. Give a deterministic `externalId`
|
|
380
|
+
(`cmpl_<id>`): the generated UUID only protects against the SDK's own retries. On the edge:
|
|
381
|
+
`Events({ autoFlush: false })` + `ctx.waitUntil(events.flush())`; `flush()` never rejects (what
|
|
382
|
+
failed stays queued). `ingest(events, { idempotencyKey? })` sends directly and throws;
|
|
383
|
+
`pending(ref)` lists the account's events steward has not counted yet (queued, in flight, acked in
|
|
384
|
+
the last minute) — `Meters({ events })` subtracts them.
|
|
385
|
+
- `Meters({ steward, catalog, cache?, events?, ttlMs = 10_000, staleIfErrorMs = 600_000,
|
|
386
|
+
onUnavailable = "allow", onFallback? })`: `get(ref)` (every meter, `Record<Meter, MeterBalance>`),
|
|
387
|
+
`balance(ref, meter)`, `check(ref, meter, { units = 1 })` → `{ allowed, balance, standing,
|
|
388
|
+
billable, source }` with `allowed = billable ? !capReached : includedUnits === null || balance −
|
|
389
|
+
pending ≥ units` (a billable meter closes once steward reports its period overage reached the
|
|
390
|
+
rate's `capMinor`). Reads are cached (ETag/304); this process's queued (and not yet rolled up) events are
|
|
391
|
+
subtracted; when steward is unreachable the stale value is used for 10 min, then the catalog's
|
|
392
|
+
default-plan credit (or the account's coarse facts from `cache`) and `onUnavailable` decide.
|
|
393
|
+
- `stateOf()` carries the `meters` block when the catalog has meters; `Webhooks()` gains
|
|
394
|
+
`onMeterThreshold` (standing `ok → low → exhausted`, also as the cause of
|
|
395
|
+
`account.state_changed`), `onMeterPeriodClosed` (with `period`) and `onBenefitCycled`
|
|
396
|
+
(`benefit_grant.cycled`). `steward.events.ingest`, `steward.meters.get/read/periods`,
|
|
397
|
+
`steward.credits.grant`, `steward.meterCharges.list` are the raw calls. Push a catalog with
|
|
398
|
+
meters only to a steward whose `me().capabilities` lists `"meters"` (an older one drops them).
|
|
399
|
+
|
|
307
400
|
Hatalar — ürün API'sinin durum kodu:
|
|
308
401
|
|
|
309
402
|
```ts
|
|
@@ -324,88 +417,6 @@ sayfalarındadır; SDK para biçimlendirme yardımcısı taşımaz.
|
|
|
324
417
|
Doğrulayıcılar: `isValidTckn`, `isValidVkn` (sağlama hanesi), `isE164(value, {country: "TR"}?)`
|
|
325
418
|
değeri olduğu gibi denetler (boşluk kırpmaz).
|
|
326
419
|
|
|
327
|
-
Testler (`/testing`, Node) — sahte steward sunucu açmaz, `fetch` verir; başlıkları
|
|
328
|
-
(`Bearer`, `X-Actor-Ref`, `Idempotency-Key` tekrarı), ETag/304, hata gövdelerini ve
|
|
329
|
-
event kurallarını servis gibi uygular. Aynı uyumluluk paketi hem sahteye hem gerçek
|
|
330
|
-
servis imajına karşı koşar:
|
|
331
|
-
|
|
332
|
-
```ts
|
|
333
|
-
import { createFakeSteward, signedEvent } from "@stewardhq/sdk/testing";
|
|
334
|
-
|
|
335
|
-
const fake = createFakeSteward({
|
|
336
|
-
catalog, // oluşturmada senkronlanır
|
|
337
|
-
webhook: { secret }, // eventTypes verilmezse ["account.state_changed"]; "legacy" = 15 eski tip
|
|
338
|
-
});
|
|
339
|
-
fake.connect((req) => webhooks.handle(req)); // alıcı sonradan (ya da webhook.handler); uygulama fake'ten sonra kurulabilir
|
|
340
|
-
const steward = fake.steward; // ya da ürünün kendi createSteward({ fetch: fake.fetch, baseUrl: fake.baseUrl, … })
|
|
341
|
-
await steward.accounts.upsert("org_1", { displayName: "Org" });
|
|
342
|
-
const session = await steward.checkoutSessions.create("org_1", input);
|
|
343
|
-
await fake.simulate.checkoutCompleted(session.id); // ya da checkoutFailed; hosted oturumda checkoutCanceled da
|
|
344
|
-
|
|
345
|
-
// Hosted (Checkout().create): url sahte steward'ın sayfası; tarayıcı gibi sürülebilir
|
|
346
|
-
const { id, url } = await checkout.create({ ref: "org_1", planCode: "team", interval: "month", actorRef: "user:1" });
|
|
347
|
-
const { redirectUrl, session: done } = await fake.simulate.completeHostedCheckout(url); // sayfa GET + "Tamamla" (outcome: "failed" → Reddet)
|
|
348
|
-
const page = await fake.fetch(url); // ya da elle: "Tamamla / Reddet / Vazgeç" formları (k gizli alanda)
|
|
349
|
-
const paid = await fake.fetch(new URL(`${id}/pay`, url), { method: "POST", body: new URLSearchParams({ k: new URL(url).searchParams.get("k")!, outcome: "succeeded" }) });
|
|
350
|
-
paid.headers.get("location"); // successUrl, yer tutucular servisle aynı kuralla dolu
|
|
351
|
-
|
|
352
|
-
// Portal (CustomerPortal().create): url sahte portal sayfası; servisle aynı rotalar ve bildirim kodları
|
|
353
|
-
const portalSession = await portal.create({ ref: "org_1", actorRef: "user:1" });
|
|
354
|
-
const k = new URL(portalSession.url).searchParams.get("k")!;
|
|
355
|
-
const base = `${fake.baseUrl}/public/v1/portal/${portalSession.id}`;
|
|
356
|
-
await fake.fetch(`${base}/cancel`, { method: "POST", body: new URLSearchParams({ k }) }); // 200 onay sayfası
|
|
357
|
-
await fake.fetch(`${base}/cancel`, { method: "POST", body: new URLSearchParams({ k, confirm: "1" }) }); // 303 …&done=canceled
|
|
358
|
-
await fake.simulate.portalCancel(portalSession.id); // ya da doğrudan: { result: "ok" | "already_scheduled" | "no_subscription", account }
|
|
359
|
-
await fake.simulate.portalRetryPayment(portalSession.id); // past_due'da { result: "ok" } — durum değişmez; sonuç renewal ile
|
|
360
|
-
|
|
361
|
-
await fake.simulate.flush(); // bekleyen event'ler alıcıya, sırayla (2xx dışı → bekler)
|
|
362
|
-
|
|
363
|
-
await fake.simulate.renewal("org_1", { fail: true }); // saat dönem sonuna; past_due + dunning
|
|
364
|
-
await fake.simulate.advance({ days: 7 }); // zamanlanmış işler kendi anında (dunning, dönem sonu iptali, checkout süresi, grant penceresi, portal oturumu silme)
|
|
365
|
-
fake.simulate.outage(true, { mode: "503" }); // ya da "network": fetch reddeder
|
|
366
|
-
await fake.simulate.deliver("account.state_changed", { ref: "org_1", duplicate: true, outOfOrder: true });
|
|
367
|
-
fake.simulate.redeliver(eventId); // operatörün pod CLI `redeliver-event`'i: aynı event sonraki flush'ta yeniden
|
|
368
|
-
|
|
369
|
-
const { request } = signedEvent("subscription.renewed", { accountRef: "org_1" }, { secret });
|
|
370
|
-
await webhooks.handle(request());
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
`fake.requests` gelen istekleri, `fake.events(ref?)` yayınlanan event'leri tutar. Endpoint `webhook`
|
|
374
|
-
seçeneğiyle oluşturmada açılır; filtre verilmezse yönetim ucunun yeni ürüne verdiği
|
|
375
|
-
`["account.state_changed"]`, `eventTypes: "legacy"` pod CLI'nın filtresiz (15 eski tip) endpoint'i.
|
|
376
|
-
Alıcı bağlanmadan `flush`/`deliver` fırlatır (event'ler outbox'ta bekler); `connect` alıcıyı değiştirir.
|
|
377
|
-
Sahtenin bilerek farklı olduğu yerler: teslimat asenkron değil (`flush()`), `dead`
|
|
378
|
-
olmaz ve geri çekilme beklenmez; sağlayıcı hata vermez; dönüş origin'i (`settings.appUrl`,
|
|
379
|
-
`settings.extraReturnOrigins` ya da kısayolu `returnOrigins`) hiç ayarlanmazsa her
|
|
380
|
-
`successUrl`/`cancelUrl`/`returnUrl` kabul; `admin.endpoints` ile açılan endpoint yalnızca kayıttır (teslimat
|
|
381
|
-
`webhook` seçeneğinin alıcısına gider, `lastDelivery` hep null; `doctor()`'da teşhisi
|
|
382
|
-
`no_deliveries`, sağlayıcı `fake` ve sağlıklı); dunning'de yeniden deneme
|
|
383
|
-
sonucu `renewal` ile gelir; her yanıt `X-Request-Id` (hata gövdesinde `requestId`) taşır;
|
|
384
|
-
idempotency kayıtları süpürülmez. Hosted checkout'ta sahte sayfa servisin sayfasını taklit
|
|
385
|
-
etmez, yalnızca `url` ↔ `simulate` sözleşmesini sürülebilir kılar: profil formu, TCKN/VKN
|
|
386
|
-
doğrulaması, onay kutuları, deneme hakkı, CSP ve POST kaynak denetimi yok. Servis profili
|
|
387
|
-
müşterinin `details` gönderiminde yazar; sahte bunu tamamlanma/red anında yapar — hesabın
|
|
388
|
-
profili yoksa `prefill`den (ad, e-posta, tür; geri kalanı sabit test verisi, kurumsalda VKN
|
|
389
|
-
`1234567890`) sahte profil yazılır (`billing_profile.updated`), varsa aynen kalır; belgeler
|
|
390
|
-
o anda onaylanmış sayılır. Sayfada sağlayıcı formu olmadığından vazgeç her zaman `canceled`
|
|
391
|
-
olur ve süresi dolan hosted oturumun nedeni `expired`dır.
|
|
392
|
-
|
|
393
|
-
Portal oturumu (`portalSessions.create`) servisle aynı kurallarla açılır (hesap yoksa 404,
|
|
394
|
-
`returnUrl` origin politikası, süre `portalTtlMinutes`, 43 karakterlik sayfa anahtarı; süresi
|
|
395
|
-
geçen, anahtarsız ya da anahtarı yanlış oturum aynı 404). Sahte portal sayfası da servisin
|
|
396
|
-
sayfasını taklit etmez — marka, tr/en metinler, CSP, POST kaynak denetimi (`Sec-Fetch-Site`),
|
|
397
|
-
IP başına yanlış anahtar ve oturum başına aksiyon sayaçları (429) yok — ama rotaları
|
|
398
|
-
(`GET ?k=`, `POST …/cancel` iki adım `confirm=1`, `…/retry-payment`, `…/profile`,
|
|
399
|
-
`GET …/invoices/:id/document?k=`), 303 bildirim kodları (`done=canceled|retry_requested|profile_saved`,
|
|
400
|
-
`error=no_subscription|already_canceled|nothing_to_retry|retry_too_soon`), profil alan hata kodları
|
|
401
|
-
(422) ve sonuçları servisle aynıdır; uyumluluk paketi iki hedefi de sayfa üzerinden sürer.
|
|
402
|
-
Yönlendirmeler mutlak adrestir (servis köke göre yol verir). Sahte sağlayıcı hata vermediğinden
|
|
403
|
-
`provider_error` bildirimi yok. "Ödemeyi yeniden dene" isteği kabul eder (`ok`, abonelik başına
|
|
404
|
-
10 dakikada bir; dry-run olmayan dunning retry adımı da sayılır) ama tahsilatı kendisi
|
|
405
|
-
sonuçlandırmaz: servisteki gibi sonuç sonradan gelir — `simulate.renewal(ref)` aynı başarısız
|
|
406
|
-
siparişi başarılı sayar (`subscription.reactivated`), `{fail: true}` yine başarısız.
|
|
407
|
-
`simulate.portalCancel/portalRetryPayment` bilinmeyen ya da süresi geçmiş oturumda fırlatır.
|
|
408
|
-
|
|
409
420
|
## `@steward/contract`'tan geçiş
|
|
410
421
|
|
|
411
422
|
| Eski | Yeni |
|
|
@@ -413,9 +424,10 @@ siparişi başarılı sayar (`subscription.reactivated`), `{fail: true}` yine ba
|
|
|
413
424
|
| `@z9cloud/steward-contract` | `@stewardhq/sdk` (ya da yalnız şema için `@stewardhq/sdk/contract`) |
|
|
414
425
|
| `@z9cloud/steward-contract/client` | `@stewardhq/sdk` `createSteward` (fırlatan; fırlatmayan `createBillingClient` dışa açılmaz) |
|
|
415
426
|
| `@z9cloud/steward-contract/webhook` | `@stewardhq/sdk/webhook` |
|
|
416
|
-
| `@z9cloud/steward-contract/fixtures/events/*.json` |
|
|
427
|
+
| `@z9cloud/steward-contract/fixtures/events/*.json` | Yok (paketle yayınlanmaz) |
|
|
428
|
+
| `@stewardhq/sdk/testing` (`signedEvent`, `createFakeSteward`) | Yok (0.4.0): servise karşı entegrasyon testi ya da `fetch` saplaması |
|
|
417
429
|
| `getEntitlements(ref)` / `accounts.entitlements(ref)` | `accounts.state(ref)` ya da `stateCache` (tek okuma modeli `AccountState`; uç 2026-09-16'da kaldırıldı) |
|
|
418
|
-
| `listEvents` / `redeliverEvent` / `events.*` | Yok (2026-09-16): kaçırılan durum için `accounts.resync(ref)`; dead teslimatı operatör pod CLI `redeliver-event` ile yeniden gönderir
|
|
430
|
+
| `listEvents` / `redeliverEvent` / `events.*` | Yok (2026-09-16): kaçırılan durum için `accounts.resync(ref)`; dead teslimatı operatör pod CLI `redeliver-event` ile yeniden gönderir |
|
|
419
431
|
|
|
420
432
|
GitHub Packages `.npmrc` satırı ve Docker `--secret` bağlaması artık gerekmez.
|
|
421
433
|
|
|
@@ -423,4 +435,27 @@ GitHub Packages `.npmrc` satırı ve Docker `--secret` bağlaması artık gerekm
|
|
|
423
435
|
|
|
424
436
|
Semver. Alan kaldırma/yeniden adlandırma kırıcıdır (major; 1.0 öncesi minor).
|
|
425
437
|
Yayın: `sdk/package.json` sürümü artırılır, `sdk-v<sürüm>` etiketi push edilir
|
|
426
|
-
(`.github/workflows/sdk-publish.yml
|
|
438
|
+
(`.github/workflows/sdk-publish.yml`).
|
|
439
|
+
|
|
440
|
+
**0.5.0** (contract 0.4.0, metering phase 2; additive; `API_VERSION` `2026-10-01` unchanged):
|
|
441
|
+
|
|
442
|
+
- Catalog: `meters` + `meter()`, `count()` / `sum(key)` / `max(key)` / `unique(key)`, `meterCredit()`
|
|
443
|
+
benefits, `meteredPrices`; `typeof catalog.$meter` / `$event`; `stateOf()` adds `meters`.
|
|
444
|
+
- `Events()` (`track`, `flush`, `ingest`, `pending`; `onRejected`, `onDrop(events, {reason})`) and `Meters()`
|
|
445
|
+
(`get`, `balance` → `MeterBalance`, `check`, `invalidate`) in the root entry, no `node:*`; `stateCache().peek(ref)`.
|
|
446
|
+
- Client: `events.ingest`, `meters.get/read/periods`, `credits.grant`, `meterCharges.list`.
|
|
447
|
+
- Hooks: `onMeterThreshold`, `onMeterPeriodClosed` (+ `period`), `onBenefitCycled`.
|
|
448
|
+
|
|
449
|
+
**0.4.0** (sözleşme 0.3.0, faturalama çekirdeği Faz 1; `API_VERSION` `2026-10-01` aynı):
|
|
450
|
+
|
|
451
|
+
- Kırıcı (0.x minor): `@stewardhq/sdk/testing` alt yolu (`signedEvent`, fixture'lar, sahte steward)
|
|
452
|
+
kaldırıldı; testler gerçek servise ya da `fetch` saplamasına karşı yazılır.
|
|
453
|
+
- Katalog: `benefits` + `featureFlag()`, `plans[].benefits`, `typeof catalog.$benefit`; `PlanSpec.rank`
|
|
454
|
+
isteğe bağlı ve hak çözümünde okunmaz (katman birleşimi, sözleşmenin `resolveBenefits`'i).
|
|
455
|
+
- Durum: `AccountState.benefits`, `subscriptions[]` (tekil `subscription` birincil abonelik),
|
|
456
|
+
`openInvoices[]`; abonelikteki `amountMinor` aboneliğin kilitli tutarıdır.
|
|
457
|
+
- Olaylar (endpoint'in `eventTypes`'ında istenirse): `invoice.paid`, `benefit_grant.created/updated/revoked`;
|
|
458
|
+
hook'lar `onInvoicePaid`, `onBenefitGranted`, `onBenefitRevoked` (ve tipten türeyen
|
|
459
|
+
`onBenefitGrantCreated/Updated/Revoked`).
|
|
460
|
+
- İstemci: `invoices.createPaymentSession`, `invoices.waive`, `subscriptions.change`,
|
|
461
|
+
`subscriptions.uncancel`; `me()` yanıtında `capabilities`.
|
package/dist/_chunks/errors.js
CHANGED