@blob-solutions/vcr-am-sdk 0.16.0 → 0.18.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/CHANGELOG.md CHANGED
@@ -2,6 +2,60 @@
2
2
 
3
3
  All notable changes to `@blob-solutions/vcr-am-sdk`. The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project follows [Semantic Versioning](https://semver.org/).
4
4
 
5
+ ## [0.18.0] — 2026-08-28
6
+
7
+ Stops making integrators guess a department id.
8
+
9
+ ### Changed
10
+
11
+ - **`SaleItem.department` is now optional.** Omit it and the line inherits the department of the offer it references — for an inline new offer, the `defaultDepartment` you declared on it. Passing one explicitly still works and still wins, which is what you want when you deliberately sell the same SKU out of a second department.
12
+
13
+ The field was required, so every integration had to name a department per line, and the natural thing to write is the first id. That is not a harmless default: departments carry the tax regime, every register is created with one department per regime in a fixed order, and `{ id: 1 }` is the VAT one on every register whether or not the merchant owes VAT. Nothing rejects the mismatch — the receipt simply prints a VAT line the merchant does not owe, and a fiscal receipt can only be refunded and reissued, never corrected. We found this in the field.
14
+
15
+ ```diff
16
+ items: [
17
+ {
18
+ offer: { externalId: "sku-coffee" },
19
+ - department: { id: 1 },
20
+ quantity: "1",
21
+ price: "1500",
22
+ unit: "pc",
23
+ },
24
+ ],
25
+ ```
26
+
27
+ Requires the server-side change shipped alongside it; against an older deployment an omitted `department` is a `422`.
28
+
29
+ ## [0.17.0] — 2026-08-28
30
+
31
+ Makes a `502` from an unreachable tax service recoverable. Until now the SDK told you the call failed but gave you no way to learn whether the document survived, and the only obvious response — retry — was the one that creates a duplicate fiscal receipt.
32
+
33
+ ### Added
34
+
35
+ - **`ApiErrorBody.pending?: PendingResource`** — a `502` raised because SRC was unreachable now carries `{ type, id, statusUrl }`. It means the document **was** persisted and queued for automatic resubmission: do not resend it. Previously the SDK dropped the field, because the error envelope parses with a non-strict `z.object` and unknown keys are silently stripped.
36
+
37
+ ```ts
38
+ try {
39
+ await vcr.registerSale(sale);
40
+ } catch (error) {
41
+ if (error instanceof VCRApiError && error.body.pending !== undefined) {
42
+ await queue.push(error.body.pending); // nothing was lost
43
+ return;
44
+ }
45
+ throw error;
46
+ }
47
+ ```
48
+
49
+ `type` is a plain string rather than an enum on purpose: if the server adds a pending resource type an older SDK does not know about, an enum would fail the whole envelope and mask the real API error.
50
+
51
+ - **`RequestOptions.idempotencyKey?: string`** — sends an `Idempotency-Key` header on document-creating calls. Same key and same body replays the original response verbatim (with `Idempotent-Replay: true`) instead of creating a second document; same key with a different body is a `422`; same key while the first call is still in flight is a `409`. Keys are scoped per register and per endpoint and retained for 24 hours.
52
+
53
+ The SDK deliberately does **not** generate the key. It only helps if the value is stable across your retries, so it has to come from something you own — an order id, a job id — never a fresh UUID per call.
54
+
55
+ - **`SaleDetail.srcStatus` / `PrepaymentDetail.srcStatus`** (and the exported `SrcStatus` type) — where the document stands with SRC: `accepted`, `rejected`, `pending`, or `needs_decision`. This is what closes the loop after a `pending` 502: read the document back and check this field rather than resending.
56
+
57
+ `pending` and `rejected` are genuinely different outcomes — the first means VCR still owns the retry and you must not resend, the second means SRC refused the payload and resending it unchanged gets the same answer.
58
+
5
59
  ## [0.16.0] — 2026-07-10
6
60
 
7
61
  ### Added
package/README.md CHANGED
@@ -28,6 +28,7 @@ Official TypeScript / JavaScript SDK for the [VCR.AM](https://vcr.am) Virtual Ca
28
28
  - [Error handling](#error-handling)
29
29
  - [Cancellation and timeouts](#cancellation-and-timeouts)
30
30
  - [Idempotency and retries](#idempotency-and-retries)
31
+ - [When the tax service is unreachable](#when-the-tax-service-is-unreachable)
31
32
  - [Browser usage](#browser-usage)
32
33
  - [Development](#development)
33
34
  - [Versioning](#versioning)
@@ -56,7 +57,6 @@ const { crn, srcReceiptId, fiscal } = await vcr.registerSale({
56
57
  items: [
57
58
  {
58
59
  offer: { externalId: "sku-coffee" },
59
- department: { id: 1 },
60
60
  quantity: "1",
61
61
  price: "1500",
62
62
  unit: "pc",
@@ -141,7 +141,7 @@ await vcr.registerSale({
141
141
  cashier: { id: 1 },
142
142
  items: [
143
143
  // price is in USD; VCR converts to AMD.
144
- { offer: { id: 5 }, department: { id: 1 }, quantity: "1", price: "10", currency: "USD", unit: "pc" },
144
+ { offer: { id: 5 }, quantity: "1", price: "10", currency: "USD", unit: "pc" },
145
145
  ],
146
146
  autoSettle: { tender: "cash" }, // AMD total is server-derived
147
147
  buyer: { type: "individual" },
@@ -190,6 +190,10 @@ const cashier = await vcr.createCashier({
190
190
 
191
191
  `listOffers({ externalId?, type?, includeArchived? })` is handy for checking whether an offer already exists (by `externalId`) before creating it. `updateOffer` renames an offer's title going forward — already-issued receipts are unchanged. Offer titles use the canonical `OfferTitle` shape (`{ type: "localized" | "universal", ... }`); `createOffer` also still accepts the deprecated legacy `{ value, localizationStrategy }` shape.
192
192
 
193
+ **Departments decide the tax regime**, so `defaultDepartment` is the one field on `createOffer` worth stopping over. Every register is created with one department per regime — VAT, VAT-exempt, turnover tax, micro-enterprise — and they are numbered in that order, which makes `{ id: 1 }` the VAT one on every register whether or not the merchant owes VAT. Call `listDepartments()` once, read `taxRegime`, and use the id that matches how the business is actually registered. Booking a sale under the wrong regime is not rejected by anything, and a fiscal receipt can only be refunded and reissued, never corrected.
194
+
195
+ Sale items then leave `department` out and inherit the offer's, so the decision is made once per offer instead of once per line.
196
+
193
197
  ```typescript
194
198
  const [existing] = await vcr.listOffers({ externalId: "sku-coffee" });
195
199
  if (existing === undefined) {
@@ -278,7 +282,67 @@ The whole request flow — connection, body read, schema parse — is bounded by
278
282
 
279
283
  ## Idempotency and retries
280
284
 
281
- **The SDK does not retry.** This is intentional. The fiscal API does not currently support idempotency keys, so retrying a `registerSale` after a network blip can double-fiscalize a receipt. Implement application-level retry only on operations you have confirmed are safe to repeat (typically reads: `whoami`, `getSale`, `getPrepayment`, `listPrepayments`, `listCashiers`, `listOffers`, `getOffer`, `listDepartments`, `searchClassifier`, `getExchangeRate`).
285
+ **The SDK does not retry.** This is intentional: a blind retry of `registerSale` can double-fiscalize a receipt, and a duplicate fiscal receipt is a real tax document — it cannot be deleted, only refunded.
286
+
287
+ To retry a document-creating call safely, pass `idempotencyKey`:
288
+
289
+ ```typescript
290
+ await vcr.registerSale(sale, { idempotencyKey: `order-${order.id}` });
291
+ ```
292
+
293
+ The key makes the retry a replay: the original response comes back verbatim and nothing new is created. This covers the case that bites hardest — a 502 from an unreachable tax service, where the sale **was** saved on our side and a naive retry would register a second one.
294
+
295
+ The SDK deliberately does not generate the key for you. It only helps if the value stays **stable across your retries**, so it has to come from something you own — an order id, a job id — not a fresh UUID per call.
296
+
297
+ Rules:
298
+
299
+ - Same key, same body -> the original response, with an `Idempotent-Replay: true` header.
300
+ - Same key, different body -> `422`. Use one key per distinct operation.
301
+ - Same key while the first call is still running -> `409`. Retry shortly, with the same key.
302
+ - Keys are scoped per register and per endpoint, and are retained for 24 hours.
303
+
304
+ Reads (`whoami`, `getSale`, `getPrepayment`, `listPrepayments`, `listCashiers`, `listOffers`, `getOffer`, `listDepartments`, `searchClassifier`, `getExchangeRate`) are always safe to repeat and need no key.
305
+
306
+ ## When the tax service is unreachable
307
+
308
+ A `502` does **not** always mean nothing happened. When SRC was merely unreachable, VCR still saved the document and queued it for automatic resubmission — the error then carries a `pending` handle, and resending would fiscalize a second receipt.
309
+
310
+ ```typescript
311
+ import { VCRApiError } from "@blob-solutions/vcr-am-sdk";
312
+
313
+ try {
314
+ await vcr.registerSale(sale, { idempotencyKey: `order-${order.id}` });
315
+ } catch (error) {
316
+ if (error instanceof VCRApiError && error.body.pending !== undefined) {
317
+ const { type, id } = error.body.pending;
318
+ // Nothing was lost. Record the id and check back later; do not resend.
319
+ await queue.push({ type, id });
320
+ return;
321
+ }
322
+ throw error;
323
+ }
324
+ ```
325
+
326
+ `pending` absent on an error means nothing was created, and the call can be repeated normally.
327
+
328
+ To find out how a queued document ended up, read it back and check `srcStatus`:
329
+
330
+ ```typescript
331
+ const sale = await vcr.getSale(id);
332
+
333
+ switch (sale.srcStatus) {
334
+ case "accepted":
335
+ return markFiscalized(sale.receipt);
336
+ case "pending":
337
+ return checkAgainLater(); // VCR is still retrying; do not resend
338
+ case "rejected":
339
+ return escalate("SRC refused the document — the payload has to change");
340
+ case "needs_decision":
341
+ return escalate("automatic retries gave up after 24h");
342
+ }
343
+ ```
344
+
345
+ Most queued documents clear within minutes. `pending` is the state that most looks like failure and most must not be treated as one — resending is the one action that turns a recoverable outage into a duplicate tax document.
282
346
 
283
347
  ## Browser usage
284
348
 
package/lib/index.cjs CHANGED
@@ -102,7 +102,18 @@ var apiErrorBodySchema = zod.z.object({
102
102
  // Server-generated correlation ID present on unexpected 5xx responses.
103
103
  // Kept lenient (plain string, not `.uuid()`) so a malformed value can never
104
104
  // make the error envelope fail to parse and mask the real API error.
105
- requestId: zod.z.string().optional()
105
+ requestId: zod.z.string().optional(),
106
+ // Present on a 502 when the document was persisted and queued for automatic
107
+ // resubmission to SRC. Its presence means the request was NOT lost.
108
+ //
109
+ // `type` is deliberately a plain string rather than an enum: a server that
110
+ // adds a new pending resource type must not make the whole error envelope
111
+ // fail to parse in an older SDK, which would mask the real API error.
112
+ pending: zod.z.object({
113
+ type: zod.z.string(),
114
+ id: zod.z.number(),
115
+ statusUrl: zod.z.string()
116
+ }).optional()
106
117
  });
107
118
  var isoDateTimeSchema = zod.z.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/, "Invalid ISO datetime");
108
119
  var detailLanguageSchema = zod.z.enum([...AVAILABLE_LANGUAGES, "multi"]);
@@ -266,9 +277,11 @@ var saleRefundPickSchema = zod.z.object({
266
277
  receipt: receiptPickSchema.nullable(),
267
278
  items: zod.z.array(zod.z.object({ quantity: zod.z.number() }))
268
279
  });
280
+ var srcStatusSchema = zod.z.enum(["accepted", "rejected", "pending", "needs_decision"]);
269
281
  var saleDetailResponseSchema = zod.z.object({
270
282
  id: zod.z.number().int().nonnegative(),
271
283
  createdAt: isoDateTimeSchema,
284
+ srcStatus: srcStatusSchema,
272
285
  buyerTin: zod.z.string().nullable(),
273
286
  comment: zod.z.string().nullable(),
274
287
  cashAmount: zod.z.number(),
@@ -289,6 +302,7 @@ var prepaymentStateSchema = zod.z.enum(["open", "consumed", "refunded"]);
289
302
  var prepaymentDetailResponseSchema = zod.z.object({
290
303
  id: zod.z.number().int().nonnegative(),
291
304
  createdAt: isoDateTimeSchema,
305
+ srcStatus: srcStatusSchema,
292
306
  buyerTin: zod.z.string().nullable(),
293
307
  cashAmount: zod.z.number(),
294
308
  nonCashAmount: zod.z.number(),
@@ -337,6 +351,9 @@ async function requestJson(schema, init) {
337
351
  "x-api-key": apiKey,
338
352
  accept: "application/json"
339
353
  };
354
+ if (init.idempotencyKey !== void 0) {
355
+ headers["idempotency-key"] = init.idempotencyKey;
356
+ }
340
357
  const requestInit = { method, headers };
341
358
  if (body !== void 0) {
342
359
  headers["content-type"] = "application/json";
@@ -680,6 +697,7 @@ exports.registerPrepaymentResponseSchema = registerPrepaymentResponseSchema;
680
697
  exports.registerSaleRefundResponseSchema = registerSaleRefundResponseSchema;
681
698
  exports.registerSaleResponseSchema = registerSaleResponseSchema;
682
699
  exports.saleDetailResponseSchema = saleDetailResponseSchema;
700
+ exports.srcStatusSchema = srcStatusSchema;
683
701
  exports.unitsKeys = unitsKeys;
684
702
  exports.whoamiResponseSchema = whoamiResponseSchema;
685
703
  //# sourceMappingURL=index.cjs.map
package/lib/index.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/errors.ts","../src/schemas.ts","../src/fetch.ts","../src/client.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["export const unitsKeys = [\n \"pc\",\n \"unit\",\n \"set\",\n \"box\",\n \"pack\",\n \"case\",\n \"hr\",\n \"sess\",\n \"proj\",\n \"sub\",\n \"kg\",\n \"l\",\n \"m\",\n \"g\",\n \"ml\",\n \"cm\",\n \"bottle\",\n \"can\",\n \"jar\",\n \"bag\",\n \"m2\",\n \"dozen\",\n \"pair\",\n \"mm\",\n \"roll\",\n \"tube\",\n \"km\",\n \"ton\",\n \"m3\",\n \"pallet\",\n \"other\",\n] as const;\n\nexport const AVAILABLE_LANGUAGES = [\"hy\", \"ru\", \"en\"] as const;\n\nexport const REFUND_REASONS = [\n \"customer_request\",\n \"defective_goods\",\n \"wrong_goods\",\n \"cashier_error\",\n \"duplicate_receipt\",\n \"other\",\n] as const;\n\nexport const TAX_REGIMES = [\"vat\", \"vat_exempt\", \"turnover_tax\", \"micro_enterprise\"] as const;\n\nexport const DEFAULT_API_URL = \"https://vcr.am/api/v1\";\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n","import type { z } from \"zod\";\n\nexport type ApiErrorIssue = {\n path: Array<string | number>;\n message: string;\n code: string;\n};\n\nexport type ApiErrorBody = {\n error: string;\n issues?: Array<ApiErrorIssue>;\n /**\n * Server-generated correlation ID, present on unexpected 5xx responses.\n * Include it when reporting the issue to support so the matching log entry\n * and Sentry event can be located.\n */\n requestId?: string;\n};\n\n/**\n * Base class for every error thrown by the SDK.\n * Catch this if you want a single catch-all.\n */\nexport abstract class VCRError extends Error {\n abstract readonly kind: string;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\n/**\n * Server returned a non-2xx response with a parseable JSON error body.\n * Mirrors the unified `{ error, issues? }` envelope from /api/v1.\n */\nexport class VCRApiError extends VCRError {\n readonly kind = \"api\" as const;\n\n constructor(\n readonly status: number,\n readonly body: ApiErrorBody,\n readonly url: string,\n ) {\n super(`VCR API ${status}: ${body.error}`);\n }\n}\n\n/**\n * Server returned a non-2xx response that did not match the error envelope,\n * or a 2xx response whose body did not match the expected schema.\n */\nexport class VCRValidationError extends VCRError {\n readonly kind = \"validation\" as const;\n\n constructor(\n message: string,\n readonly status: number,\n readonly url: string,\n readonly issues: z.ZodIssue[],\n readonly raw: unknown,\n ) {\n super(message);\n }\n}\n\n/**\n * Network-level failure: DNS, connection refused, timeout, abort.\n * The request never produced a parseable HTTP response.\n */\nexport class VCRNetworkError extends VCRError {\n readonly kind = \"network\" as const;\n\n constructor(\n message: string,\n readonly url: string,\n options: { cause: unknown },\n ) {\n super(message, options);\n }\n}\n","import { z } from \"zod\";\n\nimport { AVAILABLE_LANGUAGES, TAX_REGIMES, unitsKeys } from \"./constants\";\n\nexport const apiErrorBodySchema = z.object({\n error: z.string(),\n issues: z\n .array(\n z.object({\n path: z.array(z.union([z.string(), z.number()])),\n message: z.string(),\n code: z.string(),\n }),\n )\n .optional(),\n // Server-generated correlation ID present on unexpected 5xx responses.\n // Kept lenient (plain string, not `.uuid()`) so a malformed value can never\n // make the error envelope fail to parse and mask the real API error.\n requestId: z.string().optional(),\n});\n\nconst isoDateTimeSchema = z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/, \"Invalid ISO datetime\");\n\n// Detail responses use Prisma's `Language` enum, which is wider than\n// AVAILABLE_LANGUAGES — it also includes \"multi\" for cross-language content.\nconst detailLanguageSchema = z.enum([...AVAILABLE_LANGUAGES, \"multi\"]);\n\nconst localizationEntrySchema = z.object({\n id: z.number().int(),\n language: detailLanguageSchema,\n content: z.string(),\n});\n\nconst offerTypeSchema = z.enum([\"product\", \"service\"]);\nconst unitSchema = z.enum(unitsKeys);\nconst taxRegimeSchema = z.enum(TAX_REGIMES);\nconst discountTypeSchema = z.enum([\"percent\", \"price\", \"total\"]).nullable();\nconst additionalDiscountTypeSchema = z.enum([\"percent\", \"total\"]).nullable();\n\n// ─── Action responses ────────────────────────────────────────────────────────\n\nexport const registerSaleResponseSchema = z.object({\n urlId: z.string(),\n saleId: z.number().int().nonnegative(),\n crn: z.string(),\n srcReceiptId: z.number().int().nonnegative(),\n fiscal: z.string(),\n});\n\nexport const registerSaleRefundResponseSchema = z.object({\n urlId: z.string(),\n saleRefundId: z.number().int().nonnegative(),\n crn: z.string().nullable(),\n receiptId: z.number().int().nonnegative(),\n fiscal: z.string().nullable(),\n});\n\nexport const registerPrepaymentResponseSchema = z.object({\n urlId: z.string(),\n prepaymentId: z.number().int().nonnegative(),\n crn: z.string().nullable(),\n receiptId: z.number().int().nonnegative(),\n fiscal: z.string().nullable(),\n});\n\nexport const registerPrepaymentRefundResponseSchema = z.object({\n urlId: z.string(),\n prepaymentRefundId: z.number().int().nonnegative(),\n crn: z.string().nullable(),\n receiptId: z.number().int().nonnegative(),\n fiscal: z.string().nullable(),\n});\n\nexport const createOfferResponseSchema = z.object({\n offerId: z.number().int().nonnegative(),\n});\n\nexport const createCashierResponseSchema = z.object({\n id: z.number().int().nonnegative(),\n deskId: z.string(),\n});\n\nexport const createDepartmentResponseSchema = z.object({\n message: z.string(),\n department: z.number().int().nonnegative(),\n});\n\n// ─── Exchange rate ────────────────────────────────────────────────────────────\n\n// Mirrors the server's ExchangeRate response. `rateDate` / `saleDate` are kept\n// as plain strings (not a date-format regex) so a wire value can never make the\n// response fail to parse — the server already guarantees `YYYY-MM-DD`.\nexport const exchangeRateResponseSchema = z.object({\n /** ISO 4217 code, uppercased (echoes the requested currency). */\n currency: z.string(),\n /** AMD per one unit of `currency` (CBA rate / amount). */\n ratePerUnit: z.number(),\n /** CBA multi-lot multiplier (1, 100, 1000, ...). */\n amount: z.number().int(),\n /** Yerevan date whose rate was applied — the previous business day. */\n rateDate: z.string(),\n /** Yerevan calendar date the rate resolves for (server time). */\n saleDate: z.string(),\n /** Legal rule version applied (e.g. \"HO-234-N\"). */\n ruleVersion: z.string(),\n source: z.literal(\"CBA\"),\n});\n\n// ─── Account ──────────────────────────────────────────────────────────────────\n\nexport const whoamiResponseSchema = z.object({\n vcrId: z.number().int().nonnegative(),\n // `null` until the VCR is activated (freshly-imported registers have no CRN).\n crn: z.string().nullable(),\n mode: z.enum([\"production\", \"sandbox\"]),\n tradingPlatformName: z.string(),\n businessEntity: z.object({\n tin: z.string(),\n name: z.string(),\n }),\n});\n\n// ─── List & search ──────────────────────────────────────────────────────────\n\nconst cashierNameLocalizationSchema = z.object({\n language: z.enum([...AVAILABLE_LANGUAGES, \"multi\"]),\n content: z.string(),\n});\n\nexport const cashierListItemSchema = z.object({\n deskId: z.string(),\n internalId: z.number().int().nonnegative(),\n name: z.record(z.string(), cashierNameLocalizationSchema),\n});\n\nexport const cashierListResponseSchema = z.array(cashierListItemSchema);\n\nexport const departmentListItemSchema = z.object({\n internalId: z.number().int().nonnegative(),\n externalId: z.string().nullable(),\n taxRegime: taxRegimeSchema,\n // Map from language code -> { language, content }, matching the wire\n // format produced by makeLocalizationObject on the server. May be empty\n // for legacy departments created before titles were mandatory.\n title: z.record(z.string(), localizationEntrySchema),\n});\n\nexport const departmentListResponseSchema = z.array(departmentListItemSchema);\n\nexport const classifierSearchItemSchema = z.object({\n code: z.string(),\n // Optional: server may emit `{ code }` without `title` when the classifier\n // entry exists in fuse but lacks a translation in the requested language.\n title: z.string().optional(),\n});\n\nexport const classifierSearchResponseSchema = z.array(classifierSearchItemSchema);\n\n// Offer list/detail rows carry their title as an array of localization\n// entries (matching the detail endpoints), NOT the language-keyed record used\n// by the cashier / department lists.\nexport const offerListItemSchema = z.object({\n id: z.number().int().nonnegative(),\n externalId: z.string().nullable(),\n type: offerTypeSchema,\n classifierCode: z.string(),\n // Server types this as a plain string (not the unit enum) to stay faithful\n // to whatever is stored; mirror it so a legacy unit can never fail parsing.\n defaultMeasureUnit: z.string(),\n defaultDepartment: z.object({ internalId: z.number().int().nonnegative() }),\n title: z.array(localizationEntrySchema),\n archivedAt: isoDateTimeSchema.nullable(),\n createdAt: isoDateTimeSchema,\n});\n\nexport const offerListResponseSchema = z.array(offerListItemSchema);\n\n// ─── Detail responses ───────────────────────────────────────────────────────\n//\n// Mirror the `pick + extend` shape produced by serializeForWire on the server.\n// Decimal columns (Prisma) arrive as numbers (z.number()), bigint as numeric\n// strings, and dates as ISO strings — matching the prisma-zod-generator output\n// the server validates against before responding.\n\nconst receiptPickSchema = z.object({\n srcId: z.number().int(),\n time: z.string().regex(/^\\d+$/, \"Invalid bigint string\"),\n tin: z.string(),\n fiscal: z.string().nullable(),\n sn: z.string(),\n address: z.string().nullable(),\n total: z.number(),\n taxpayer: z.string(),\n change: z.number(),\n});\n\nconst cashierPickSchema = z.object({\n internalId: z.number().int().nonnegative(),\n deskId: z.string(),\n name: z.array(localizationEntrySchema),\n});\n\nconst departmentPickSchema = z.object({\n internalId: z.number().int().nonnegative(),\n taxRegime: taxRegimeSchema,\n title: z.array(localizationEntrySchema),\n});\n\nconst offerPickSchema = z.object({\n type: offerTypeSchema,\n classifierCode: z.string(),\n title: z.array(localizationEntrySchema),\n});\n\nconst saleItemPickSchema = z.object({\n srcId: z.number().int(),\n quantity: z.number(),\n price: z.number(),\n unit: unitSchema,\n discount: z.number().nullable(),\n discountType: discountTypeSchema,\n additionalDiscount: z.number().nullable(),\n additionalDiscountType: additionalDiscountTypeSchema,\n department: departmentPickSchema,\n offer: offerPickSchema,\n});\n\nconst saleRefundPickSchema = z.object({\n nonCashAmount: z.number(),\n cashAmount: z.number(),\n receipt: receiptPickSchema.nullable(),\n items: z.array(z.object({ quantity: z.number() })),\n});\n\nexport const saleDetailResponseSchema = z.object({\n id: z.number().int().nonnegative(),\n createdAt: isoDateTimeSchema,\n buyerTin: z.string().nullable(),\n comment: z.string().nullable(),\n cashAmount: z.number(),\n nonCashAmount: z.number(),\n prepaymentAmount: z.number(),\n compensationAmount: z.number(),\n receipt: receiptPickSchema.nullable(),\n refunds: z.array(saleRefundPickSchema),\n cashier: cashierPickSchema,\n items: z.array(saleItemPickSchema),\n});\n\nconst prepaymentRefundPickSchema = z.object({\n nonCashAmount: z.number(),\n cashAmount: z.number(),\n receipt: receiptPickSchema.nullable(),\n});\n\n// `open` — remaining > 0; can still be applied or refunded.\n// `consumed` — fully applied to subsequent sales.\n// `refunded` — a PrepaymentRefund row exists (always full per AM Annex 3 §29).\nexport const prepaymentStateSchema = z.enum([\"open\", \"consumed\", \"refunded\"]);\n\nexport const prepaymentDetailResponseSchema = z.object({\n id: z.number().int().nonnegative(),\n createdAt: isoDateTimeSchema,\n buyerTin: z.string().nullable(),\n cashAmount: z.number(),\n nonCashAmount: z.number(),\n receipt: receiptPickSchema.nullable(),\n refund: prepaymentRefundPickSchema.nullable(),\n cashier: cashierPickSchema,\n /** SUM(amount) across all ledger rows for this prepayment. */\n remaining: z.number(),\n state: prepaymentStateSchema,\n});\n\nexport const prepaymentListItemSchema = z.object({\n id: z.number().int().nonnegative(),\n createdAt: isoDateTimeSchema,\n buyerTin: z.string().nullable(),\n cashAmount: z.number(),\n nonCashAmount: z.number(),\n remaining: z.number(),\n state: prepaymentStateSchema,\n});\n\nexport const prepaymentListResponseSchema = z.array(prepaymentListItemSchema);\n\nconst customerOpenPrepaymentSchema = z.object({\n prepaymentId: z.number().int().nonnegative(),\n createdAt: isoDateTimeSchema,\n cashAmount: z.number(),\n nonCashAmount: z.number(),\n buyerTin: z.string().nullable(),\n remaining: z.number(),\n});\n\nexport const customerPrepaymentBalanceResponseSchema = z.object({\n entityId: z.number().int().nonnegative(),\n customerRef: z.string(),\n /** Total remaining across all open prepayments matching customerRef. */\n balance: z.number(),\n /** FIFO-ordered open prepayments contributing to the balance. */\n openPrepayments: z.array(customerOpenPrepaymentSchema),\n});\n\n// ─── Inferred types ─────────────────────────────────────────────────────────\n\nexport type RegisterSaleResponse = z.infer<typeof registerSaleResponseSchema>;\nexport type RegisterSaleRefundResponse = z.infer<typeof registerSaleRefundResponseSchema>;\nexport type RegisterPrepaymentResponse = z.infer<typeof registerPrepaymentResponseSchema>;\nexport type RegisterPrepaymentRefundResponse = z.infer<\n typeof registerPrepaymentRefundResponseSchema\n>;\nexport type CreateOfferResponse = z.infer<typeof createOfferResponseSchema>;\nexport type CreateCashierResponse = z.infer<typeof createCashierResponseSchema>;\nexport type CreateDepartmentResponse = z.infer<typeof createDepartmentResponseSchema>;\nexport type CashierListItem = z.infer<typeof cashierListItemSchema>;\nexport type ClassifierSearchItem = z.infer<typeof classifierSearchItemSchema>;\nexport type Whoami = z.infer<typeof whoamiResponseSchema>;\nexport type OfferListItem = z.infer<typeof offerListItemSchema>;\nexport type SaleDetail = z.infer<typeof saleDetailResponseSchema>;\nexport type PrepaymentDetail = z.infer<typeof prepaymentDetailResponseSchema>;\nexport type PrepaymentListItem = z.infer<typeof prepaymentListItemSchema>;\nexport type PrepaymentState = z.infer<typeof prepaymentStateSchema>;\nexport type CustomerPrepaymentBalance = z.infer<typeof customerPrepaymentBalanceResponseSchema>;\nexport type DepartmentListItem = z.infer<typeof departmentListItemSchema>;\nexport type ExchangeRate = z.infer<typeof exchangeRateResponseSchema>;\n","import type { z } from \"zod\";\n\nimport { type ApiErrorBody, VCRApiError, VCRNetworkError, VCRValidationError } from \"./errors\";\nimport { apiErrorBodySchema } from \"./schemas\";\n\nexport type RequestOptions = {\n signal?: AbortSignal;\n /** Override per-request timeout in ms. `null` disables the timeout. */\n timeoutMs?: number | null;\n};\n\nexport type FetchInit = {\n method: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n url: string;\n apiKey: string;\n body?: unknown;\n fetchImpl: typeof fetch;\n defaultTimeoutMs: number | null;\n} & RequestOptions;\n\nexport async function requestJson<TSchema extends z.ZodTypeAny>(\n schema: TSchema,\n init: FetchInit,\n): Promise<z.infer<TSchema>> {\n const { url, method, apiKey, body, fetchImpl, signal: externalSignal } = init;\n\n const effectiveTimeout = init.timeoutMs === undefined ? init.defaultTimeoutMs : init.timeoutMs;\n\n const timeoutController = effectiveTimeout !== null ? new AbortController() : undefined;\n const timeoutHandle =\n timeoutController !== undefined && effectiveTimeout !== null\n ? setTimeout(() => timeoutController.abort(new Error(\"Request timeout\")), effectiveTimeout)\n : undefined;\n\n const signal = mergeSignals(externalSignal, timeoutController?.signal);\n\n const headers: Record<string, string> = {\n \"x-api-key\": apiKey,\n accept: \"application/json\",\n };\n\n const requestInit: RequestInit = { method, headers };\n if (body !== undefined) {\n headers[\"content-type\"] = \"application/json\";\n requestInit.body = JSON.stringify(body);\n }\n if (signal !== undefined) {\n requestInit.signal = signal;\n }\n\n // The whole flow — connect, body read, parse — must be bounded by the same\n // timeout. Clearing the timer earlier (e.g. after fetch resolves) leaves\n // body reading and parsing unprotected against slow/hanging servers.\n try {\n let response: Response;\n let rawText: string;\n try {\n response = await fetchImpl(url, requestInit);\n rawText = await response.text();\n } catch (cause) {\n throw new VCRNetworkError(\n cause instanceof Error ? cause.message : \"Network request failed\",\n url,\n { cause },\n );\n }\n\n const rawJson = rawText.length === 0 ? undefined : safeJsonParse(rawText);\n\n if (!response.ok) {\n throw buildApiError(response.status, rawJson, url);\n }\n\n const parsed = schema.safeParse(rawJson);\n if (!parsed.success) {\n throw new VCRValidationError(\n `VCR response did not match expected schema for ${method} ${url}`,\n response.status,\n url,\n parsed.error.issues,\n rawJson,\n );\n }\n\n return parsed.data;\n } finally {\n if (timeoutHandle !== undefined) {\n clearTimeout(timeoutHandle);\n }\n }\n}\n\nfunction buildApiError(\n status: number,\n rawJson: unknown,\n url: string,\n): VCRApiError | VCRValidationError {\n const parsed = apiErrorBodySchema.safeParse(rawJson);\n if (parsed.success) {\n const body: ApiErrorBody = {\n error: parsed.data.error,\n ...(parsed.data.issues !== undefined && { issues: parsed.data.issues }),\n ...(parsed.data.requestId !== undefined && { requestId: parsed.data.requestId }),\n };\n return new VCRApiError(status, body, url);\n }\n\n return new VCRValidationError(\n `VCR returned ${status} but the error body did not match the expected envelope`,\n status,\n url,\n parsed.error.issues,\n rawJson,\n );\n}\n\nfunction safeJsonParse(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\nfunction mergeSignals(...signals: ReadonlyArray<AbortSignal | undefined>): AbortSignal | undefined {\n const present = signals.filter((signal): signal is AbortSignal => signal !== undefined);\n if (present.length === 0) {\n return undefined;\n }\n return AbortSignal.any(present);\n}\n","import type { z } from \"zod\";\nimport { DEFAULT_API_URL, DEFAULT_TIMEOUT_MS } from \"./constants\";\nimport { type RequestOptions, requestJson } from \"./fetch\";\nimport {\n type CashierListItem,\n type ClassifierSearchItem,\n type CreateCashierResponse,\n type CreateDepartmentResponse,\n type CreateOfferResponse,\n type CustomerPrepaymentBalance,\n cashierListResponseSchema,\n classifierSearchResponseSchema,\n createCashierResponseSchema,\n createDepartmentResponseSchema,\n createOfferResponseSchema,\n customerPrepaymentBalanceResponseSchema,\n type DepartmentListItem,\n departmentListResponseSchema,\n type ExchangeRate,\n exchangeRateResponseSchema,\n type OfferListItem,\n offerListItemSchema,\n offerListResponseSchema,\n type PrepaymentDetail,\n type PrepaymentListItem,\n type PrepaymentState,\n prepaymentDetailResponseSchema,\n prepaymentListResponseSchema,\n type RegisterPrepaymentRefundResponse,\n type RegisterPrepaymentResponse,\n type RegisterSaleRefundResponse,\n type RegisterSaleResponse,\n registerPrepaymentRefundResponseSchema,\n registerPrepaymentResponseSchema,\n registerSaleRefundResponseSchema,\n registerSaleResponseSchema,\n type SaleDetail,\n saleDetailResponseSchema,\n type Whoami,\n whoamiResponseSchema,\n} from \"./schemas\";\nimport type {\n ClassifierType,\n CreateCashierInput,\n CreateDepartmentInput,\n CreateOfferInput,\n Language,\n ListOffersFilter,\n RegisterPrepaymentInput,\n RegisterPrepaymentRefundInput,\n RegisterSaleInput,\n RegisterSaleRefundInput,\n SearchClassifierInput,\n UpdateOfferInput,\n} from \"./types\";\n\nexport type ListPrepaymentsFilter = {\n /** Exact-match filter against ledger.customerRef (TIN / phone / email). */\n customerRef?: string;\n /**\n * Filter by derived lifecycle state. `all` (the default) returns every\n * prepayment; the other values filter to a single lifecycle stage.\n */\n state?: PrepaymentState | \"all\";\n};\n\nexport type VCRClientOptions = {\n /** Base URL for the VCR API. Defaults to https://vcr.am/api/v1. */\n baseUrl?: string;\n /** Custom fetch implementation. Defaults to the global `fetch`. */\n fetch?: typeof fetch;\n /** Default request timeout in ms. Pass `null` to disable. Default 30s. */\n timeoutMs?: number | null;\n};\n\ntype Method = \"GET\" | \"POST\" | \"PATCH\";\n\nexport class VCRClient {\n readonly #apiKey: string;\n readonly #baseUrl: string;\n readonly #fetch: typeof fetch;\n readonly #defaultTimeoutMs: number | null;\n\n constructor(apiKey: string, options: VCRClientOptions = {}) {\n if (apiKey.length === 0) {\n throw new Error(\"VCRClient requires a non-empty apiKey\");\n }\n this.#apiKey = apiKey;\n this.#baseUrl = stripTrailingSlash(options.baseUrl ?? DEFAULT_API_URL);\n\n const candidate = options.fetch ?? globalThis.fetch;\n if (typeof candidate !== \"function\") {\n throw new Error(\n \"No fetch implementation available. Provide options.fetch or use a runtime that exposes a global fetch.\",\n );\n }\n // Only bind the global fetch, which on some runtimes requires `this ===\n // globalThis`. A user-supplied fetch keeps its own `this` so wrappers\n // (e.g. class methods, fetch with closure state) keep working.\n this.#fetch = options.fetch === undefined ? candidate.bind(globalThis) : candidate;\n\n this.#defaultTimeoutMs =\n options.timeoutMs === undefined ? DEFAULT_TIMEOUT_MS : options.timeoutMs;\n }\n\n // ─── Account ──────────────────────────────────────────────────────────────\n\n /**\n * Resolve which VCR the calling API key belongs to. Returns the register's\n * identity, its `mode` (`production` / `sandbox`), and the owning business\n * entity. Works on freshly-imported VCRs that have not been activated yet\n * (in which case `crn` is `null`) — handy as a cheap SDK health-check and to\n * tell production keys apart from sandbox ones.\n */\n whoami(options: RequestOptions = {}): Promise<Whoami> {\n return this.#json(\"GET\", \"/whoami\", whoamiResponseSchema, undefined, options);\n }\n\n // ─── Sales ─────────────────────────────────────────────────────────────────\n\n registerSale(\n data: RegisterSaleInput,\n options: RequestOptions = {},\n ): Promise<RegisterSaleResponse> {\n return this.#json(\"POST\", \"/sales\", registerSaleResponseSchema, data, options);\n }\n\n getSale(saleId: number, options: RequestOptions = {}): Promise<SaleDetail> {\n assertNonNegativeInt(saleId, \"saleId\");\n return this.#json(\"GET\", `/sales/${saleId}`, saleDetailResponseSchema, undefined, options);\n }\n\n registerSaleRefund(\n data: RegisterSaleRefundInput,\n options: RequestOptions = {},\n ): Promise<RegisterSaleRefundResponse> {\n return this.#json(\"POST\", \"/sales/refund\", registerSaleRefundResponseSchema, data, options);\n }\n\n // ─── Prepayments ──────────────────────────────────────────────────────────\n\n registerPrepayment(\n data: RegisterPrepaymentInput,\n options: RequestOptions = {},\n ): Promise<RegisterPrepaymentResponse> {\n return this.#json(\"POST\", \"/prepayments\", registerPrepaymentResponseSchema, data, options);\n }\n\n getPrepayment(prepaymentId: number, options: RequestOptions = {}): Promise<PrepaymentDetail> {\n assertNonNegativeInt(prepaymentId, \"prepaymentId\");\n return this.#json(\n \"GET\",\n `/prepayments/${prepaymentId}`,\n prepaymentDetailResponseSchema,\n undefined,\n options,\n );\n }\n\n registerPrepaymentRefund(\n data: RegisterPrepaymentRefundInput,\n options: RequestOptions = {},\n ): Promise<RegisterPrepaymentRefundResponse> {\n return this.#json(\n \"POST\",\n \"/prepayments/refund\",\n registerPrepaymentRefundResponseSchema,\n data,\n options,\n );\n }\n\n /**\n * List prepayments registered through the calling VCR. Server caps the\n * response at 500 rows; for larger sets, narrow with `customerRef` or\n * paginate by `id` outside the SDK.\n *\n * `remaining` and `state` are derived from the ledger — call this whenever\n * you want a current snapshot rather than caching the result.\n */\n listPrepayments(\n filter: ListPrepaymentsFilter = {},\n options: RequestOptions = {},\n ): Promise<PrepaymentListItem[]> {\n const query: Record<string, string> = {};\n if (filter.customerRef !== undefined) query[\"customerRef\"] = filter.customerRef;\n if (filter.state !== undefined) query[\"state\"] = filter.state;\n return this.#json(\n \"GET\",\n \"/prepayments\",\n prepaymentListResponseSchema,\n undefined,\n options,\n Object.keys(query).length > 0 ? query : undefined,\n );\n }\n\n /**\n * Get a customer's open prepayment balance scoped to the BusinessEntity\n * that owns the calling VCR's API key. Because the ledger is entity-scoped,\n * the result reflects deposits made through any VCR belonging to the same\n * entity — merchants who run more than one VCR see a single wallet.\n *\n * `customerRef` is matched exactly against the ledger — typically a TIN,\n * normalized E.164 phone, or lowercased email. Use whichever identifier the\n * customer gave at deposit time; identities are not auto-merged across\n * different ref types.\n */\n getCustomerPrepaymentBalance(\n input: { customerRef: string },\n options: RequestOptions = {},\n ): Promise<CustomerPrepaymentBalance> {\n return this.#json(\n \"GET\",\n \"/prepayments/balance\",\n customerPrepaymentBalanceResponseSchema,\n undefined,\n options,\n { customerRef: input.customerRef },\n );\n }\n\n // ─── Cashiers ─────────────────────────────────────────────────────────────\n\n listCashiers(options: RequestOptions = {}): Promise<CashierListItem[]> {\n return this.#json(\"GET\", \"/cashiers\", cashierListResponseSchema, undefined, options);\n }\n\n createCashier(\n data: CreateCashierInput,\n options: RequestOptions = {},\n ): Promise<CreateCashierResponse> {\n return this.#json(\"POST\", \"/cashiers\", createCashierResponseSchema, data, options);\n }\n\n // ─── Offers / Departments ─────────────────────────────────────────────────\n\n createOffer(data: CreateOfferInput, options: RequestOptions = {}): Promise<CreateOfferResponse> {\n return this.#json(\"POST\", \"/offers\", createOfferResponseSchema, data, options);\n }\n\n /**\n * List offers belonging to the calling VCR. Server caps the response at 500\n * rows; narrow with `externalId` / `type` for larger catalogs. Archived\n * offers are excluded unless `includeArchived` is set.\n *\n * A common use is checking whether an offer already exists (by `externalId`)\n * before creating it.\n */\n listOffers(\n filter: ListOffersFilter = {},\n options: RequestOptions = {},\n ): Promise<OfferListItem[]> {\n const query: Record<string, string> = {};\n if (filter.externalId !== undefined) query[\"externalId\"] = filter.externalId;\n if (filter.type !== undefined) query[\"type\"] = filter.type;\n if (filter.includeArchived !== undefined) {\n query[\"includeArchived\"] = filter.includeArchived ? \"true\" : \"false\";\n }\n return this.#json(\n \"GET\",\n \"/offers\",\n offerListResponseSchema,\n undefined,\n options,\n Object.keys(query).length > 0 ? query : undefined,\n );\n }\n\n getOffer(offerId: number, options: RequestOptions = {}): Promise<OfferListItem> {\n assertNonNegativeInt(offerId, \"offerId\");\n return this.#json(\"GET\", `/offers/${offerId}`, offerListItemSchema, undefined, options);\n }\n\n /**\n * Rename an offer's title. Affects only future receipts — already-issued\n * receipts keep the title they were created with, and the SRC fiscal record\n * is unchanged. Missing `en`/`ru` are filled per `localizationStrategy`,\n * exactly as on offer creation. Returns the updated offer.\n */\n updateOffer(\n offerId: number,\n data: UpdateOfferInput,\n options: RequestOptions = {},\n ): Promise<OfferListItem> {\n assertNonNegativeInt(offerId, \"offerId\");\n return this.#json(\"PATCH\", `/offers/${offerId}`, offerListItemSchema, data, options);\n }\n\n createDepartment(\n data: CreateDepartmentInput,\n options: RequestOptions = {},\n ): Promise<CreateDepartmentResponse> {\n return this.#json(\"POST\", \"/departments\", createDepartmentResponseSchema, data, options);\n }\n\n /**\n * List departments configured on the calling VCR — `internalId`,\n * `externalId`, `taxRegime`, and the localized `title`. Mirrors the\n * dashboard catalog: only departments confirmed by the tax service are\n * returned, so the `internalId` field is safe to reference from a sale\n * item's `department.id`.\n */\n listDepartments(options: RequestOptions = {}): Promise<DepartmentListItem[]> {\n return this.#json(\"GET\", \"/departments\", departmentListResponseSchema, undefined, options);\n }\n\n // ─── Classifier search ────────────────────────────────────────────────────\n\n searchClassifier(\n input: SearchClassifierInput,\n options: RequestOptions = {},\n ): Promise<ClassifierSearchItem[]> {\n return this.#json(\n \"GET\",\n \"/searchByClassifier\",\n classifierSearchResponseSchema,\n undefined,\n options,\n { query: input.query, type: input.type, language: input.language },\n );\n }\n\n /**\n * @deprecated Use {@link searchClassifier} with an options object. Will be\n * removed in 1.0. The new signature accepts `{ query, type, language }` so\n * future params can be added without breaking the call site.\n */\n searchClassifierCategory(\n query: string,\n type: ClassifierType,\n language: Language,\n options: RequestOptions = {},\n ): Promise<ClassifierSearchItem[]> {\n return this.searchClassifier({ query, type, language }, options);\n }\n\n // ─── Exchange rate ────────────────────────────────────────────────────────\n\n /**\n * Preview the AMD conversion rate VCR would apply to a foreign-currency sale\n * registered now — the CBA mid-market rate published on the previous business\n * day (Tax Code art. 16, HO-234-N). Use it to show a buyer the AMD equivalent\n * before charging. The sale itself is converted server-side from each item's\n * `currency` + `price` (see {@link RegisterSaleInput}); this endpoint is a\n * read-only preview and does not fiscalize anything.\n *\n * `currency` is a 3-letter ISO 4217 code, case-insensitive. `AMD` is rejected\n * (it is the native receipt currency and needs no conversion).\n */\n getExchangeRate(\n input: { currency: string },\n options: RequestOptions = {},\n ): Promise<ExchangeRate> {\n return this.#json(\"GET\", \"/exchange-rate\", exchangeRateResponseSchema, undefined, options, {\n currency: input.currency,\n });\n }\n\n // ─── Internal ─────────────────────────────────────────────────────────────\n\n #json<TSchema extends z.ZodTypeAny>(\n method: Method,\n path: string,\n schema: TSchema,\n body: unknown,\n options: RequestOptions,\n query?: Record<string, string>,\n ): Promise<z.infer<TSchema>> {\n const url =\n query === undefined\n ? `${this.#baseUrl}${path}`\n : appendQuery(`${this.#baseUrl}${path}`, query);\n\n return requestJson(schema, {\n method,\n url,\n apiKey: this.#apiKey,\n ...(body !== undefined && { body }),\n fetchImpl: this.#fetch,\n defaultTimeoutMs: this.#defaultTimeoutMs,\n ...options,\n });\n }\n}\n\nfunction appendQuery(url: string, query: Record<string, string>): string {\n const u = new URL(url);\n for (const [key, value] of Object.entries(query)) {\n u.searchParams.set(key, value);\n }\n return u.toString();\n}\n\nfunction stripTrailingSlash(url: string): string {\n return url.endsWith(\"/\") ? url.slice(0, -1) : url;\n}\n\nfunction assertNonNegativeInt(value: number, name: string): void {\n if (!Number.isInteger(value) || value < 0) {\n throw new Error(`${name} must be a non-negative integer (got ${value})`);\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/errors.ts","../src/schemas.ts","../src/fetch.ts","../src/client.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["export const unitsKeys = [\n \"pc\",\n \"unit\",\n \"set\",\n \"box\",\n \"pack\",\n \"case\",\n \"hr\",\n \"sess\",\n \"proj\",\n \"sub\",\n \"kg\",\n \"l\",\n \"m\",\n \"g\",\n \"ml\",\n \"cm\",\n \"bottle\",\n \"can\",\n \"jar\",\n \"bag\",\n \"m2\",\n \"dozen\",\n \"pair\",\n \"mm\",\n \"roll\",\n \"tube\",\n \"km\",\n \"ton\",\n \"m3\",\n \"pallet\",\n \"other\",\n] as const;\n\nexport const AVAILABLE_LANGUAGES = [\"hy\", \"ru\", \"en\"] as const;\n\nexport const REFUND_REASONS = [\n \"customer_request\",\n \"defective_goods\",\n \"wrong_goods\",\n \"cashier_error\",\n \"duplicate_receipt\",\n \"other\",\n] as const;\n\nexport const TAX_REGIMES = [\"vat\", \"vat_exempt\", \"turnover_tax\", \"micro_enterprise\"] as const;\n\nexport const DEFAULT_API_URL = \"https://vcr.am/api/v1\";\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n","import type { z } from \"zod\";\n\nexport type ApiErrorIssue = {\n path: Array<string | number>;\n message: string;\n code: string;\n};\n\n/**\n * A document VCR persisted and queued for automatic resubmission to SRC.\n *\n * Present on a 502 when SRC was merely unreachable. It means the request was\n * NOT lost: VCR owns the work and a background sweep usually completes it\n * within minutes. Poll `statusUrl` to find out; do NOT resend the request,\n * which would produce a second fiscal receipt.\n */\nexport type PendingResource = {\n /** Which collection `id` belongs to, e.g. `\"sale\"` or `\"prepayment\"`. */\n type: string;\n id: number;\n /** Path to poll for the outcome, e.g. `/api/v1/sales/5122`. */\n statusUrl: string;\n};\n\nexport type ApiErrorBody = {\n error: string;\n issues?: Array<ApiErrorIssue>;\n /**\n * Server-generated correlation ID, present on unexpected 5xx responses.\n * Include it when reporting the issue to support so the matching log entry\n * and Sentry event can be located.\n */\n requestId?: string;\n /**\n * Set when the request was persisted despite the error. Its absence on an\n * error means nothing was created.\n */\n pending?: PendingResource;\n};\n\n/**\n * Base class for every error thrown by the SDK.\n * Catch this if you want a single catch-all.\n */\nexport abstract class VCRError extends Error {\n abstract readonly kind: string;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\n/**\n * Server returned a non-2xx response with a parseable JSON error body.\n * Mirrors the unified `{ error, issues? }` envelope from /api/v1.\n */\nexport class VCRApiError extends VCRError {\n readonly kind = \"api\" as const;\n\n constructor(\n readonly status: number,\n readonly body: ApiErrorBody,\n readonly url: string,\n ) {\n super(`VCR API ${status}: ${body.error}`);\n }\n}\n\n/**\n * Server returned a non-2xx response that did not match the error envelope,\n * or a 2xx response whose body did not match the expected schema.\n */\nexport class VCRValidationError extends VCRError {\n readonly kind = \"validation\" as const;\n\n constructor(\n message: string,\n readonly status: number,\n readonly url: string,\n readonly issues: z.ZodIssue[],\n readonly raw: unknown,\n ) {\n super(message);\n }\n}\n\n/**\n * Network-level failure: DNS, connection refused, timeout, abort.\n * The request never produced a parseable HTTP response.\n */\nexport class VCRNetworkError extends VCRError {\n readonly kind = \"network\" as const;\n\n constructor(\n message: string,\n readonly url: string,\n options: { cause: unknown },\n ) {\n super(message, options);\n }\n}\n","import { z } from \"zod\";\n\nimport { AVAILABLE_LANGUAGES, TAX_REGIMES, unitsKeys } from \"./constants\";\n\nexport const apiErrorBodySchema = z.object({\n error: z.string(),\n issues: z\n .array(\n z.object({\n path: z.array(z.union([z.string(), z.number()])),\n message: z.string(),\n code: z.string(),\n }),\n )\n .optional(),\n // Server-generated correlation ID present on unexpected 5xx responses.\n // Kept lenient (plain string, not `.uuid()`) so a malformed value can never\n // make the error envelope fail to parse and mask the real API error.\n requestId: z.string().optional(),\n // Present on a 502 when the document was persisted and queued for automatic\n // resubmission to SRC. Its presence means the request was NOT lost.\n //\n // `type` is deliberately a plain string rather than an enum: a server that\n // adds a new pending resource type must not make the whole error envelope\n // fail to parse in an older SDK, which would mask the real API error.\n pending: z\n .object({\n type: z.string(),\n id: z.number(),\n statusUrl: z.string(),\n })\n .optional(),\n});\n\nconst isoDateTimeSchema = z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/, \"Invalid ISO datetime\");\n\n// Detail responses use Prisma's `Language` enum, which is wider than\n// AVAILABLE_LANGUAGES — it also includes \"multi\" for cross-language content.\nconst detailLanguageSchema = z.enum([...AVAILABLE_LANGUAGES, \"multi\"]);\n\nconst localizationEntrySchema = z.object({\n id: z.number().int(),\n language: detailLanguageSchema,\n content: z.string(),\n});\n\nconst offerTypeSchema = z.enum([\"product\", \"service\"]);\nconst unitSchema = z.enum(unitsKeys);\nconst taxRegimeSchema = z.enum(TAX_REGIMES);\nconst discountTypeSchema = z.enum([\"percent\", \"price\", \"total\"]).nullable();\nconst additionalDiscountTypeSchema = z.enum([\"percent\", \"total\"]).nullable();\n\n// ─── Action responses ────────────────────────────────────────────────────────\n\nexport const registerSaleResponseSchema = z.object({\n urlId: z.string(),\n saleId: z.number().int().nonnegative(),\n crn: z.string(),\n srcReceiptId: z.number().int().nonnegative(),\n fiscal: z.string(),\n});\n\nexport const registerSaleRefundResponseSchema = z.object({\n urlId: z.string(),\n saleRefundId: z.number().int().nonnegative(),\n crn: z.string().nullable(),\n receiptId: z.number().int().nonnegative(),\n fiscal: z.string().nullable(),\n});\n\nexport const registerPrepaymentResponseSchema = z.object({\n urlId: z.string(),\n prepaymentId: z.number().int().nonnegative(),\n crn: z.string().nullable(),\n receiptId: z.number().int().nonnegative(),\n fiscal: z.string().nullable(),\n});\n\nexport const registerPrepaymentRefundResponseSchema = z.object({\n urlId: z.string(),\n prepaymentRefundId: z.number().int().nonnegative(),\n crn: z.string().nullable(),\n receiptId: z.number().int().nonnegative(),\n fiscal: z.string().nullable(),\n});\n\nexport const createOfferResponseSchema = z.object({\n offerId: z.number().int().nonnegative(),\n});\n\nexport const createCashierResponseSchema = z.object({\n id: z.number().int().nonnegative(),\n deskId: z.string(),\n});\n\nexport const createDepartmentResponseSchema = z.object({\n message: z.string(),\n department: z.number().int().nonnegative(),\n});\n\n// ─── Exchange rate ────────────────────────────────────────────────────────────\n\n// Mirrors the server's ExchangeRate response. `rateDate` / `saleDate` are kept\n// as plain strings (not a date-format regex) so a wire value can never make the\n// response fail to parse — the server already guarantees `YYYY-MM-DD`.\nexport const exchangeRateResponseSchema = z.object({\n /** ISO 4217 code, uppercased (echoes the requested currency). */\n currency: z.string(),\n /** AMD per one unit of `currency` (CBA rate / amount). */\n ratePerUnit: z.number(),\n /** CBA multi-lot multiplier (1, 100, 1000, ...). */\n amount: z.number().int(),\n /** Yerevan date whose rate was applied — the previous business day. */\n rateDate: z.string(),\n /** Yerevan calendar date the rate resolves for (server time). */\n saleDate: z.string(),\n /** Legal rule version applied (e.g. \"HO-234-N\"). */\n ruleVersion: z.string(),\n source: z.literal(\"CBA\"),\n});\n\n// ─── Account ──────────────────────────────────────────────────────────────────\n\nexport const whoamiResponseSchema = z.object({\n vcrId: z.number().int().nonnegative(),\n // `null` until the VCR is activated (freshly-imported registers have no CRN).\n crn: z.string().nullable(),\n mode: z.enum([\"production\", \"sandbox\"]),\n tradingPlatformName: z.string(),\n businessEntity: z.object({\n tin: z.string(),\n name: z.string(),\n }),\n});\n\n// ─── List & search ──────────────────────────────────────────────────────────\n\nconst cashierNameLocalizationSchema = z.object({\n language: z.enum([...AVAILABLE_LANGUAGES, \"multi\"]),\n content: z.string(),\n});\n\nexport const cashierListItemSchema = z.object({\n deskId: z.string(),\n internalId: z.number().int().nonnegative(),\n name: z.record(z.string(), cashierNameLocalizationSchema),\n});\n\nexport const cashierListResponseSchema = z.array(cashierListItemSchema);\n\nexport const departmentListItemSchema = z.object({\n internalId: z.number().int().nonnegative(),\n externalId: z.string().nullable(),\n taxRegime: taxRegimeSchema,\n // Map from language code -> { language, content }, matching the wire\n // format produced by makeLocalizationObject on the server. May be empty\n // for legacy departments created before titles were mandatory.\n title: z.record(z.string(), localizationEntrySchema),\n});\n\nexport const departmentListResponseSchema = z.array(departmentListItemSchema);\n\nexport const classifierSearchItemSchema = z.object({\n code: z.string(),\n // Optional: server may emit `{ code }` without `title` when the classifier\n // entry exists in fuse but lacks a translation in the requested language.\n title: z.string().optional(),\n});\n\nexport const classifierSearchResponseSchema = z.array(classifierSearchItemSchema);\n\n// Offer list/detail rows carry their title as an array of localization\n// entries (matching the detail endpoints), NOT the language-keyed record used\n// by the cashier / department lists.\nexport const offerListItemSchema = z.object({\n id: z.number().int().nonnegative(),\n externalId: z.string().nullable(),\n type: offerTypeSchema,\n classifierCode: z.string(),\n // Server types this as a plain string (not the unit enum) to stay faithful\n // to whatever is stored; mirror it so a legacy unit can never fail parsing.\n defaultMeasureUnit: z.string(),\n defaultDepartment: z.object({ internalId: z.number().int().nonnegative() }),\n title: z.array(localizationEntrySchema),\n archivedAt: isoDateTimeSchema.nullable(),\n createdAt: isoDateTimeSchema,\n});\n\nexport const offerListResponseSchema = z.array(offerListItemSchema);\n\n// ─── Detail responses ───────────────────────────────────────────────────────\n//\n// Mirror the `pick + extend` shape produced by serializeForWire on the server.\n// Decimal columns (Prisma) arrive as numbers (z.number()), bigint as numeric\n// strings, and dates as ISO strings — matching the prisma-zod-generator output\n// the server validates against before responding.\n\nconst receiptPickSchema = z.object({\n srcId: z.number().int(),\n time: z.string().regex(/^\\d+$/, \"Invalid bigint string\"),\n tin: z.string(),\n fiscal: z.string().nullable(),\n sn: z.string(),\n address: z.string().nullable(),\n total: z.number(),\n taxpayer: z.string(),\n change: z.number(),\n});\n\nconst cashierPickSchema = z.object({\n internalId: z.number().int().nonnegative(),\n deskId: z.string(),\n name: z.array(localizationEntrySchema),\n});\n\nconst departmentPickSchema = z.object({\n internalId: z.number().int().nonnegative(),\n taxRegime: taxRegimeSchema,\n title: z.array(localizationEntrySchema),\n});\n\nconst offerPickSchema = z.object({\n type: offerTypeSchema,\n classifierCode: z.string(),\n title: z.array(localizationEntrySchema),\n});\n\nconst saleItemPickSchema = z.object({\n srcId: z.number().int(),\n quantity: z.number(),\n price: z.number(),\n unit: unitSchema,\n discount: z.number().nullable(),\n discountType: discountTypeSchema,\n additionalDiscount: z.number().nullable(),\n additionalDiscountType: additionalDiscountTypeSchema,\n department: departmentPickSchema,\n offer: offerPickSchema,\n});\n\nconst saleRefundPickSchema = z.object({\n nonCashAmount: z.number(),\n cashAmount: z.number(),\n receipt: receiptPickSchema.nullable(),\n items: z.array(z.object({ quantity: z.number() })),\n});\n\n/**\n * Where a document stands with the tax authority, derived from its submission\n * log. This is the field to poll after a 502 that carried a `pending` handle.\n *\n * - `accepted` — SRC registered it. Terminal and final; a fiscal receipt exists.\n * - `rejected` — SRC refused the document itself. Terminal: resending the same\n * payload gets the same refusal, so something has to change.\n * - `pending` — no answer from SRC yet. VCR owns the retry; do NOT resend.\n * - `needs_decision` — the automatic retry window (24h) closed without an\n * answer. Still not resendable blind — check the document before acting.\n *\n * A plain enum rather than a boolean because \"not accepted\" spans three very\n * different situations, and the one that matters most (`pending`) is the one\n * that looks like failure but must not be treated as one.\n */\nexport const srcStatusSchema = z.enum([\"accepted\", \"rejected\", \"pending\", \"needs_decision\"]);\n\nexport const saleDetailResponseSchema = z.object({\n id: z.number().int().nonnegative(),\n createdAt: isoDateTimeSchema,\n srcStatus: srcStatusSchema,\n buyerTin: z.string().nullable(),\n comment: z.string().nullable(),\n cashAmount: z.number(),\n nonCashAmount: z.number(),\n prepaymentAmount: z.number(),\n compensationAmount: z.number(),\n receipt: receiptPickSchema.nullable(),\n refunds: z.array(saleRefundPickSchema),\n cashier: cashierPickSchema,\n items: z.array(saleItemPickSchema),\n});\n\nconst prepaymentRefundPickSchema = z.object({\n nonCashAmount: z.number(),\n cashAmount: z.number(),\n receipt: receiptPickSchema.nullable(),\n});\n\n// `open` — remaining > 0; can still be applied or refunded.\n// `consumed` — fully applied to subsequent sales.\n// `refunded` — a PrepaymentRefund row exists (always full per AM Annex 3 §29).\nexport const prepaymentStateSchema = z.enum([\"open\", \"consumed\", \"refunded\"]);\n\nexport const prepaymentDetailResponseSchema = z.object({\n id: z.number().int().nonnegative(),\n createdAt: isoDateTimeSchema,\n srcStatus: srcStatusSchema,\n buyerTin: z.string().nullable(),\n cashAmount: z.number(),\n nonCashAmount: z.number(),\n receipt: receiptPickSchema.nullable(),\n refund: prepaymentRefundPickSchema.nullable(),\n cashier: cashierPickSchema,\n /** SUM(amount) across all ledger rows for this prepayment. */\n remaining: z.number(),\n state: prepaymentStateSchema,\n});\n\nexport const prepaymentListItemSchema = z.object({\n id: z.number().int().nonnegative(),\n createdAt: isoDateTimeSchema,\n buyerTin: z.string().nullable(),\n cashAmount: z.number(),\n nonCashAmount: z.number(),\n remaining: z.number(),\n state: prepaymentStateSchema,\n});\n\nexport const prepaymentListResponseSchema = z.array(prepaymentListItemSchema);\n\nconst customerOpenPrepaymentSchema = z.object({\n prepaymentId: z.number().int().nonnegative(),\n createdAt: isoDateTimeSchema,\n cashAmount: z.number(),\n nonCashAmount: z.number(),\n buyerTin: z.string().nullable(),\n remaining: z.number(),\n});\n\nexport const customerPrepaymentBalanceResponseSchema = z.object({\n entityId: z.number().int().nonnegative(),\n customerRef: z.string(),\n /** Total remaining across all open prepayments matching customerRef. */\n balance: z.number(),\n /** FIFO-ordered open prepayments contributing to the balance. */\n openPrepayments: z.array(customerOpenPrepaymentSchema),\n});\n\n// ─── Inferred types ─────────────────────────────────────────────────────────\n\nexport type RegisterSaleResponse = z.infer<typeof registerSaleResponseSchema>;\nexport type RegisterSaleRefundResponse = z.infer<typeof registerSaleRefundResponseSchema>;\nexport type RegisterPrepaymentResponse = z.infer<typeof registerPrepaymentResponseSchema>;\nexport type RegisterPrepaymentRefundResponse = z.infer<\n typeof registerPrepaymentRefundResponseSchema\n>;\nexport type CreateOfferResponse = z.infer<typeof createOfferResponseSchema>;\nexport type CreateCashierResponse = z.infer<typeof createCashierResponseSchema>;\nexport type CreateDepartmentResponse = z.infer<typeof createDepartmentResponseSchema>;\nexport type CashierListItem = z.infer<typeof cashierListItemSchema>;\nexport type ClassifierSearchItem = z.infer<typeof classifierSearchItemSchema>;\nexport type Whoami = z.infer<typeof whoamiResponseSchema>;\nexport type OfferListItem = z.infer<typeof offerListItemSchema>;\nexport type SrcStatus = z.infer<typeof srcStatusSchema>;\nexport type SaleDetail = z.infer<typeof saleDetailResponseSchema>;\nexport type PrepaymentDetail = z.infer<typeof prepaymentDetailResponseSchema>;\nexport type PrepaymentListItem = z.infer<typeof prepaymentListItemSchema>;\nexport type PrepaymentState = z.infer<typeof prepaymentStateSchema>;\nexport type CustomerPrepaymentBalance = z.infer<typeof customerPrepaymentBalanceResponseSchema>;\nexport type DepartmentListItem = z.infer<typeof departmentListItemSchema>;\nexport type ExchangeRate = z.infer<typeof exchangeRateResponseSchema>;\n","import type { z } from \"zod\";\n\nimport { type ApiErrorBody, VCRApiError, VCRNetworkError, VCRValidationError } from \"./errors\";\nimport { apiErrorBodySchema } from \"./schemas\";\n\nexport type RequestOptions = {\n signal?: AbortSignal;\n /** Override per-request timeout in ms. `null` disables the timeout. */\n timeoutMs?: number | null;\n /**\n * Opt-in replay protection for the document-creating endpoints\n * (`registerSale`, `registerSaleRefund`, `registerPrepayment`,\n * `registerPrepaymentRefund`). Retrying a request that carries the same key\n * returns the original response instead of registering a second document.\n *\n * Strongly recommended. Without it, retrying after a 502 produces a\n * duplicate fiscal receipt, which can only be undone by issuing a refund.\n *\n * The SDK deliberately does not generate this for you: the value must stay\n * **stable across your retries**, so it has to come from something you own —\n * typically your order id (`order-4821`) — not from a fresh UUID per call.\n */\n idempotencyKey?: string;\n};\n\nexport type FetchInit = {\n method: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n url: string;\n apiKey: string;\n body?: unknown;\n fetchImpl: typeof fetch;\n defaultTimeoutMs: number | null;\n} & RequestOptions;\n\nexport async function requestJson<TSchema extends z.ZodTypeAny>(\n schema: TSchema,\n init: FetchInit,\n): Promise<z.infer<TSchema>> {\n const { url, method, apiKey, body, fetchImpl, signal: externalSignal } = init;\n\n const effectiveTimeout = init.timeoutMs === undefined ? init.defaultTimeoutMs : init.timeoutMs;\n\n const timeoutController = effectiveTimeout !== null ? new AbortController() : undefined;\n const timeoutHandle =\n timeoutController !== undefined && effectiveTimeout !== null\n ? setTimeout(() => timeoutController.abort(new Error(\"Request timeout\")), effectiveTimeout)\n : undefined;\n\n const signal = mergeSignals(externalSignal, timeoutController?.signal);\n\n const headers: Record<string, string> = {\n \"x-api-key\": apiKey,\n accept: \"application/json\",\n };\n if (init.idempotencyKey !== undefined) {\n headers[\"idempotency-key\"] = init.idempotencyKey;\n }\n\n const requestInit: RequestInit = { method, headers };\n if (body !== undefined) {\n headers[\"content-type\"] = \"application/json\";\n requestInit.body = JSON.stringify(body);\n }\n if (signal !== undefined) {\n requestInit.signal = signal;\n }\n\n // The whole flow — connect, body read, parse — must be bounded by the same\n // timeout. Clearing the timer earlier (e.g. after fetch resolves) leaves\n // body reading and parsing unprotected against slow/hanging servers.\n try {\n let response: Response;\n let rawText: string;\n try {\n response = await fetchImpl(url, requestInit);\n rawText = await response.text();\n } catch (cause) {\n throw new VCRNetworkError(\n cause instanceof Error ? cause.message : \"Network request failed\",\n url,\n { cause },\n );\n }\n\n const rawJson = rawText.length === 0 ? undefined : safeJsonParse(rawText);\n\n if (!response.ok) {\n throw buildApiError(response.status, rawJson, url);\n }\n\n const parsed = schema.safeParse(rawJson);\n if (!parsed.success) {\n throw new VCRValidationError(\n `VCR response did not match expected schema for ${method} ${url}`,\n response.status,\n url,\n parsed.error.issues,\n rawJson,\n );\n }\n\n return parsed.data;\n } finally {\n if (timeoutHandle !== undefined) {\n clearTimeout(timeoutHandle);\n }\n }\n}\n\nfunction buildApiError(\n status: number,\n rawJson: unknown,\n url: string,\n): VCRApiError | VCRValidationError {\n const parsed = apiErrorBodySchema.safeParse(rawJson);\n if (parsed.success) {\n const body: ApiErrorBody = {\n error: parsed.data.error,\n ...(parsed.data.issues !== undefined && { issues: parsed.data.issues }),\n ...(parsed.data.requestId !== undefined && { requestId: parsed.data.requestId }),\n };\n return new VCRApiError(status, body, url);\n }\n\n return new VCRValidationError(\n `VCR returned ${status} but the error body did not match the expected envelope`,\n status,\n url,\n parsed.error.issues,\n rawJson,\n );\n}\n\nfunction safeJsonParse(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\nfunction mergeSignals(...signals: ReadonlyArray<AbortSignal | undefined>): AbortSignal | undefined {\n const present = signals.filter((signal): signal is AbortSignal => signal !== undefined);\n if (present.length === 0) {\n return undefined;\n }\n return AbortSignal.any(present);\n}\n","import type { z } from \"zod\";\nimport { DEFAULT_API_URL, DEFAULT_TIMEOUT_MS } from \"./constants\";\nimport { type RequestOptions, requestJson } from \"./fetch\";\nimport {\n type CashierListItem,\n type ClassifierSearchItem,\n type CreateCashierResponse,\n type CreateDepartmentResponse,\n type CreateOfferResponse,\n type CustomerPrepaymentBalance,\n cashierListResponseSchema,\n classifierSearchResponseSchema,\n createCashierResponseSchema,\n createDepartmentResponseSchema,\n createOfferResponseSchema,\n customerPrepaymentBalanceResponseSchema,\n type DepartmentListItem,\n departmentListResponseSchema,\n type ExchangeRate,\n exchangeRateResponseSchema,\n type OfferListItem,\n offerListItemSchema,\n offerListResponseSchema,\n type PrepaymentDetail,\n type PrepaymentListItem,\n type PrepaymentState,\n prepaymentDetailResponseSchema,\n prepaymentListResponseSchema,\n type RegisterPrepaymentRefundResponse,\n type RegisterPrepaymentResponse,\n type RegisterSaleRefundResponse,\n type RegisterSaleResponse,\n registerPrepaymentRefundResponseSchema,\n registerPrepaymentResponseSchema,\n registerSaleRefundResponseSchema,\n registerSaleResponseSchema,\n type SaleDetail,\n saleDetailResponseSchema,\n type Whoami,\n whoamiResponseSchema,\n} from \"./schemas\";\nimport type {\n ClassifierType,\n CreateCashierInput,\n CreateDepartmentInput,\n CreateOfferInput,\n Language,\n ListOffersFilter,\n RegisterPrepaymentInput,\n RegisterPrepaymentRefundInput,\n RegisterSaleInput,\n RegisterSaleRefundInput,\n SearchClassifierInput,\n UpdateOfferInput,\n} from \"./types\";\n\nexport type ListPrepaymentsFilter = {\n /** Exact-match filter against ledger.customerRef (TIN / phone / email). */\n customerRef?: string;\n /**\n * Filter by derived lifecycle state. `all` (the default) returns every\n * prepayment; the other values filter to a single lifecycle stage.\n */\n state?: PrepaymentState | \"all\";\n};\n\nexport type VCRClientOptions = {\n /** Base URL for the VCR API. Defaults to https://vcr.am/api/v1. */\n baseUrl?: string;\n /** Custom fetch implementation. Defaults to the global `fetch`. */\n fetch?: typeof fetch;\n /** Default request timeout in ms. Pass `null` to disable. Default 30s. */\n timeoutMs?: number | null;\n};\n\ntype Method = \"GET\" | \"POST\" | \"PATCH\";\n\nexport class VCRClient {\n readonly #apiKey: string;\n readonly #baseUrl: string;\n readonly #fetch: typeof fetch;\n readonly #defaultTimeoutMs: number | null;\n\n constructor(apiKey: string, options: VCRClientOptions = {}) {\n if (apiKey.length === 0) {\n throw new Error(\"VCRClient requires a non-empty apiKey\");\n }\n this.#apiKey = apiKey;\n this.#baseUrl = stripTrailingSlash(options.baseUrl ?? DEFAULT_API_URL);\n\n const candidate = options.fetch ?? globalThis.fetch;\n if (typeof candidate !== \"function\") {\n throw new Error(\n \"No fetch implementation available. Provide options.fetch or use a runtime that exposes a global fetch.\",\n );\n }\n // Only bind the global fetch, which on some runtimes requires `this ===\n // globalThis`. A user-supplied fetch keeps its own `this` so wrappers\n // (e.g. class methods, fetch with closure state) keep working.\n this.#fetch = options.fetch === undefined ? candidate.bind(globalThis) : candidate;\n\n this.#defaultTimeoutMs =\n options.timeoutMs === undefined ? DEFAULT_TIMEOUT_MS : options.timeoutMs;\n }\n\n // ─── Account ──────────────────────────────────────────────────────────────\n\n /**\n * Resolve which VCR the calling API key belongs to. Returns the register's\n * identity, its `mode` (`production` / `sandbox`), and the owning business\n * entity. Works on freshly-imported VCRs that have not been activated yet\n * (in which case `crn` is `null`) — handy as a cheap SDK health-check and to\n * tell production keys apart from sandbox ones.\n */\n whoami(options: RequestOptions = {}): Promise<Whoami> {\n return this.#json(\"GET\", \"/whoami\", whoamiResponseSchema, undefined, options);\n }\n\n // ─── Sales ─────────────────────────────────────────────────────────────────\n\n registerSale(\n data: RegisterSaleInput,\n options: RequestOptions = {},\n ): Promise<RegisterSaleResponse> {\n return this.#json(\"POST\", \"/sales\", registerSaleResponseSchema, data, options);\n }\n\n getSale(saleId: number, options: RequestOptions = {}): Promise<SaleDetail> {\n assertNonNegativeInt(saleId, \"saleId\");\n return this.#json(\"GET\", `/sales/${saleId}`, saleDetailResponseSchema, undefined, options);\n }\n\n registerSaleRefund(\n data: RegisterSaleRefundInput,\n options: RequestOptions = {},\n ): Promise<RegisterSaleRefundResponse> {\n return this.#json(\"POST\", \"/sales/refund\", registerSaleRefundResponseSchema, data, options);\n }\n\n // ─── Prepayments ──────────────────────────────────────────────────────────\n\n registerPrepayment(\n data: RegisterPrepaymentInput,\n options: RequestOptions = {},\n ): Promise<RegisterPrepaymentResponse> {\n return this.#json(\"POST\", \"/prepayments\", registerPrepaymentResponseSchema, data, options);\n }\n\n getPrepayment(prepaymentId: number, options: RequestOptions = {}): Promise<PrepaymentDetail> {\n assertNonNegativeInt(prepaymentId, \"prepaymentId\");\n return this.#json(\n \"GET\",\n `/prepayments/${prepaymentId}`,\n prepaymentDetailResponseSchema,\n undefined,\n options,\n );\n }\n\n registerPrepaymentRefund(\n data: RegisterPrepaymentRefundInput,\n options: RequestOptions = {},\n ): Promise<RegisterPrepaymentRefundResponse> {\n return this.#json(\n \"POST\",\n \"/prepayments/refund\",\n registerPrepaymentRefundResponseSchema,\n data,\n options,\n );\n }\n\n /**\n * List prepayments registered through the calling VCR. Server caps the\n * response at 500 rows; for larger sets, narrow with `customerRef` or\n * paginate by `id` outside the SDK.\n *\n * `remaining` and `state` are derived from the ledger — call this whenever\n * you want a current snapshot rather than caching the result.\n */\n listPrepayments(\n filter: ListPrepaymentsFilter = {},\n options: RequestOptions = {},\n ): Promise<PrepaymentListItem[]> {\n const query: Record<string, string> = {};\n if (filter.customerRef !== undefined) query[\"customerRef\"] = filter.customerRef;\n if (filter.state !== undefined) query[\"state\"] = filter.state;\n return this.#json(\n \"GET\",\n \"/prepayments\",\n prepaymentListResponseSchema,\n undefined,\n options,\n Object.keys(query).length > 0 ? query : undefined,\n );\n }\n\n /**\n * Get a customer's open prepayment balance scoped to the BusinessEntity\n * that owns the calling VCR's API key. Because the ledger is entity-scoped,\n * the result reflects deposits made through any VCR belonging to the same\n * entity — merchants who run more than one VCR see a single wallet.\n *\n * `customerRef` is matched exactly against the ledger — typically a TIN,\n * normalized E.164 phone, or lowercased email. Use whichever identifier the\n * customer gave at deposit time; identities are not auto-merged across\n * different ref types.\n */\n getCustomerPrepaymentBalance(\n input: { customerRef: string },\n options: RequestOptions = {},\n ): Promise<CustomerPrepaymentBalance> {\n return this.#json(\n \"GET\",\n \"/prepayments/balance\",\n customerPrepaymentBalanceResponseSchema,\n undefined,\n options,\n { customerRef: input.customerRef },\n );\n }\n\n // ─── Cashiers ─────────────────────────────────────────────────────────────\n\n listCashiers(options: RequestOptions = {}): Promise<CashierListItem[]> {\n return this.#json(\"GET\", \"/cashiers\", cashierListResponseSchema, undefined, options);\n }\n\n createCashier(\n data: CreateCashierInput,\n options: RequestOptions = {},\n ): Promise<CreateCashierResponse> {\n return this.#json(\"POST\", \"/cashiers\", createCashierResponseSchema, data, options);\n }\n\n // ─── Offers / Departments ─────────────────────────────────────────────────\n\n createOffer(data: CreateOfferInput, options: RequestOptions = {}): Promise<CreateOfferResponse> {\n return this.#json(\"POST\", \"/offers\", createOfferResponseSchema, data, options);\n }\n\n /**\n * List offers belonging to the calling VCR. Server caps the response at 500\n * rows; narrow with `externalId` / `type` for larger catalogs. Archived\n * offers are excluded unless `includeArchived` is set.\n *\n * A common use is checking whether an offer already exists (by `externalId`)\n * before creating it.\n */\n listOffers(\n filter: ListOffersFilter = {},\n options: RequestOptions = {},\n ): Promise<OfferListItem[]> {\n const query: Record<string, string> = {};\n if (filter.externalId !== undefined) query[\"externalId\"] = filter.externalId;\n if (filter.type !== undefined) query[\"type\"] = filter.type;\n if (filter.includeArchived !== undefined) {\n query[\"includeArchived\"] = filter.includeArchived ? \"true\" : \"false\";\n }\n return this.#json(\n \"GET\",\n \"/offers\",\n offerListResponseSchema,\n undefined,\n options,\n Object.keys(query).length > 0 ? query : undefined,\n );\n }\n\n getOffer(offerId: number, options: RequestOptions = {}): Promise<OfferListItem> {\n assertNonNegativeInt(offerId, \"offerId\");\n return this.#json(\"GET\", `/offers/${offerId}`, offerListItemSchema, undefined, options);\n }\n\n /**\n * Rename an offer's title. Affects only future receipts — already-issued\n * receipts keep the title they were created with, and the SRC fiscal record\n * is unchanged. Missing `en`/`ru` are filled per `localizationStrategy`,\n * exactly as on offer creation. Returns the updated offer.\n */\n updateOffer(\n offerId: number,\n data: UpdateOfferInput,\n options: RequestOptions = {},\n ): Promise<OfferListItem> {\n assertNonNegativeInt(offerId, \"offerId\");\n return this.#json(\"PATCH\", `/offers/${offerId}`, offerListItemSchema, data, options);\n }\n\n createDepartment(\n data: CreateDepartmentInput,\n options: RequestOptions = {},\n ): Promise<CreateDepartmentResponse> {\n return this.#json(\"POST\", \"/departments\", createDepartmentResponseSchema, data, options);\n }\n\n /**\n * List departments configured on the calling VCR — `internalId`,\n * `externalId`, `taxRegime`, and the localized `title`. Mirrors the\n * dashboard catalog: only departments confirmed by the tax service are\n * returned, so the `internalId` field is safe to reference from a sale\n * item's `department.id`.\n */\n listDepartments(options: RequestOptions = {}): Promise<DepartmentListItem[]> {\n return this.#json(\"GET\", \"/departments\", departmentListResponseSchema, undefined, options);\n }\n\n // ─── Classifier search ────────────────────────────────────────────────────\n\n searchClassifier(\n input: SearchClassifierInput,\n options: RequestOptions = {},\n ): Promise<ClassifierSearchItem[]> {\n return this.#json(\n \"GET\",\n \"/searchByClassifier\",\n classifierSearchResponseSchema,\n undefined,\n options,\n { query: input.query, type: input.type, language: input.language },\n );\n }\n\n /**\n * @deprecated Use {@link searchClassifier} with an options object. Will be\n * removed in 1.0. The new signature accepts `{ query, type, language }` so\n * future params can be added without breaking the call site.\n */\n searchClassifierCategory(\n query: string,\n type: ClassifierType,\n language: Language,\n options: RequestOptions = {},\n ): Promise<ClassifierSearchItem[]> {\n return this.searchClassifier({ query, type, language }, options);\n }\n\n // ─── Exchange rate ────────────────────────────────────────────────────────\n\n /**\n * Preview the AMD conversion rate VCR would apply to a foreign-currency sale\n * registered now — the CBA mid-market rate published on the previous business\n * day (Tax Code art. 16, HO-234-N). Use it to show a buyer the AMD equivalent\n * before charging. The sale itself is converted server-side from each item's\n * `currency` + `price` (see {@link RegisterSaleInput}); this endpoint is a\n * read-only preview and does not fiscalize anything.\n *\n * `currency` is a 3-letter ISO 4217 code, case-insensitive. `AMD` is rejected\n * (it is the native receipt currency and needs no conversion).\n */\n getExchangeRate(\n input: { currency: string },\n options: RequestOptions = {},\n ): Promise<ExchangeRate> {\n return this.#json(\"GET\", \"/exchange-rate\", exchangeRateResponseSchema, undefined, options, {\n currency: input.currency,\n });\n }\n\n // ─── Internal ─────────────────────────────────────────────────────────────\n\n #json<TSchema extends z.ZodTypeAny>(\n method: Method,\n path: string,\n schema: TSchema,\n body: unknown,\n options: RequestOptions,\n query?: Record<string, string>,\n ): Promise<z.infer<TSchema>> {\n const url =\n query === undefined\n ? `${this.#baseUrl}${path}`\n : appendQuery(`${this.#baseUrl}${path}`, query);\n\n return requestJson(schema, {\n method,\n url,\n apiKey: this.#apiKey,\n ...(body !== undefined && { body }),\n fetchImpl: this.#fetch,\n defaultTimeoutMs: this.#defaultTimeoutMs,\n ...options,\n });\n }\n}\n\nfunction appendQuery(url: string, query: Record<string, string>): string {\n const u = new URL(url);\n for (const [key, value] of Object.entries(query)) {\n u.searchParams.set(key, value);\n }\n return u.toString();\n}\n\nfunction stripTrailingSlash(url: string): string {\n return url.endsWith(\"/\") ? url.slice(0, -1) : url;\n}\n\nfunction assertNonNegativeInt(value: number, name: string): void {\n if (!Number.isInteger(value) || value < 0) {\n throw new Error(`${name} must be a non-negative integer (got ${value})`);\n }\n}\n"]}