@blob-solutions/vcr-am-sdk 0.8.0 → 0.10.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 +37 -0
- package/LICENSE +15 -0
- package/README.md +226 -21
- package/lib/index.cjs +471 -1
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +453 -30
- package/lib/index.d.ts +453 -30
- package/lib/index.global.js +64 -12
- package/lib/index.global.js.map +1 -1
- package/lib/index.js +446 -1
- package/lib/index.js.map +1 -1
- package/package.json +60 -26
package/lib/index.cjs
CHANGED
|
@@ -1,2 +1,472 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var zod = require('zod');
|
|
4
|
+
|
|
5
|
+
// src/constants.ts
|
|
6
|
+
var unitsKeys = [
|
|
7
|
+
"pc",
|
|
8
|
+
"unit",
|
|
9
|
+
"set",
|
|
10
|
+
"box",
|
|
11
|
+
"pack",
|
|
12
|
+
"case",
|
|
13
|
+
"hr",
|
|
14
|
+
"sess",
|
|
15
|
+
"proj",
|
|
16
|
+
"sub",
|
|
17
|
+
"kg",
|
|
18
|
+
"l",
|
|
19
|
+
"m",
|
|
20
|
+
"g",
|
|
21
|
+
"ml",
|
|
22
|
+
"cm",
|
|
23
|
+
"bottle",
|
|
24
|
+
"can",
|
|
25
|
+
"jar",
|
|
26
|
+
"bag",
|
|
27
|
+
"m2",
|
|
28
|
+
"dozen",
|
|
29
|
+
"pair",
|
|
30
|
+
"mm",
|
|
31
|
+
"roll",
|
|
32
|
+
"tube",
|
|
33
|
+
"km",
|
|
34
|
+
"ton",
|
|
35
|
+
"m3",
|
|
36
|
+
"pallet",
|
|
37
|
+
"other"
|
|
38
|
+
];
|
|
39
|
+
var AVAILABLE_LANGUAGES = ["hy", "ru", "en"];
|
|
40
|
+
var REFUND_REASONS = [
|
|
41
|
+
"customer_request",
|
|
42
|
+
"defective_goods",
|
|
43
|
+
"wrong_goods",
|
|
44
|
+
"cashier_error",
|
|
45
|
+
"duplicate_receipt",
|
|
46
|
+
"other"
|
|
47
|
+
];
|
|
48
|
+
var TAX_REGIMES = ["vat", "vat_exempt", "turnover_tax", "micro_enterprise"];
|
|
49
|
+
var DEFAULT_API_URL = "https://vcr.am/api/v1";
|
|
50
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
51
|
+
|
|
52
|
+
// src/errors.ts
|
|
53
|
+
var VCRError = class extends Error {
|
|
54
|
+
constructor(message, options) {
|
|
55
|
+
super(message, options);
|
|
56
|
+
this.name = new.target.name;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
var VCRApiError = class extends VCRError {
|
|
60
|
+
constructor(status, body, url) {
|
|
61
|
+
super(`VCR API ${status}: ${body.error}`);
|
|
62
|
+
this.status = status;
|
|
63
|
+
this.body = body;
|
|
64
|
+
this.url = url;
|
|
65
|
+
}
|
|
66
|
+
status;
|
|
67
|
+
body;
|
|
68
|
+
url;
|
|
69
|
+
kind = "api";
|
|
70
|
+
};
|
|
71
|
+
var VCRValidationError = class extends VCRError {
|
|
72
|
+
constructor(message, status, url, issues, raw) {
|
|
73
|
+
super(message);
|
|
74
|
+
this.status = status;
|
|
75
|
+
this.url = url;
|
|
76
|
+
this.issues = issues;
|
|
77
|
+
this.raw = raw;
|
|
78
|
+
}
|
|
79
|
+
status;
|
|
80
|
+
url;
|
|
81
|
+
issues;
|
|
82
|
+
raw;
|
|
83
|
+
kind = "validation";
|
|
84
|
+
};
|
|
85
|
+
var VCRNetworkError = class extends VCRError {
|
|
86
|
+
constructor(message, url, options) {
|
|
87
|
+
super(message, options);
|
|
88
|
+
this.url = url;
|
|
89
|
+
}
|
|
90
|
+
url;
|
|
91
|
+
kind = "network";
|
|
92
|
+
};
|
|
93
|
+
var apiErrorBodySchema = zod.z.object({
|
|
94
|
+
error: zod.z.string(),
|
|
95
|
+
issues: zod.z.array(
|
|
96
|
+
zod.z.object({
|
|
97
|
+
path: zod.z.array(zod.z.union([zod.z.string(), zod.z.number()])),
|
|
98
|
+
message: zod.z.string(),
|
|
99
|
+
code: zod.z.string()
|
|
100
|
+
})
|
|
101
|
+
).optional()
|
|
102
|
+
});
|
|
103
|
+
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");
|
|
104
|
+
var detailLanguageSchema = zod.z.enum([...AVAILABLE_LANGUAGES, "multi"]);
|
|
105
|
+
var localizationEntrySchema = zod.z.object({
|
|
106
|
+
id: zod.z.number().int(),
|
|
107
|
+
language: detailLanguageSchema,
|
|
108
|
+
content: zod.z.string()
|
|
109
|
+
});
|
|
110
|
+
var offerTypeSchema = zod.z.enum(["product", "service"]);
|
|
111
|
+
var unitSchema = zod.z.enum(unitsKeys);
|
|
112
|
+
var taxRegimeSchema = zod.z.enum(TAX_REGIMES);
|
|
113
|
+
var discountTypeSchema = zod.z.enum(["percent", "price", "total"]).nullable();
|
|
114
|
+
var additionalDiscountTypeSchema = zod.z.enum(["percent", "total"]).nullable();
|
|
115
|
+
var registerSaleResponseSchema = zod.z.object({
|
|
116
|
+
urlId: zod.z.string(),
|
|
117
|
+
saleId: zod.z.number().int().nonnegative(),
|
|
118
|
+
crn: zod.z.string(),
|
|
119
|
+
srcReceiptId: zod.z.number().int().nonnegative(),
|
|
120
|
+
fiscal: zod.z.string()
|
|
121
|
+
});
|
|
122
|
+
var registerSaleRefundResponseSchema = zod.z.object({
|
|
123
|
+
urlId: zod.z.string(),
|
|
124
|
+
saleRefundId: zod.z.number().int().nonnegative(),
|
|
125
|
+
crn: zod.z.string().nullable(),
|
|
126
|
+
receiptId: zod.z.number().int().nonnegative(),
|
|
127
|
+
fiscal: zod.z.string().nullable()
|
|
128
|
+
});
|
|
129
|
+
var registerPrepaymentResponseSchema = zod.z.object({
|
|
130
|
+
urlId: zod.z.string(),
|
|
131
|
+
prepaymentId: zod.z.number().int().nonnegative(),
|
|
132
|
+
crn: zod.z.string().nullable(),
|
|
133
|
+
receiptId: zod.z.number().int().nonnegative(),
|
|
134
|
+
fiscal: zod.z.string().nullable()
|
|
135
|
+
});
|
|
136
|
+
var registerPrepaymentRefundResponseSchema = zod.z.object({
|
|
137
|
+
urlId: zod.z.string(),
|
|
138
|
+
prepaymentRefundId: zod.z.number().int().nonnegative(),
|
|
139
|
+
crn: zod.z.string().nullable(),
|
|
140
|
+
receiptId: zod.z.number().int().nonnegative(),
|
|
141
|
+
fiscal: zod.z.string().nullable()
|
|
142
|
+
});
|
|
143
|
+
var createOfferResponseSchema = zod.z.object({
|
|
144
|
+
offerId: zod.z.number().int().nonnegative()
|
|
145
|
+
});
|
|
146
|
+
var createCashierResponseSchema = zod.z.object({
|
|
147
|
+
id: zod.z.number().int().nonnegative(),
|
|
148
|
+
deskId: zod.z.string()
|
|
149
|
+
});
|
|
150
|
+
var createDepartmentResponseSchema = zod.z.object({
|
|
151
|
+
message: zod.z.string(),
|
|
152
|
+
department: zod.z.number().int().nonnegative()
|
|
153
|
+
});
|
|
154
|
+
var cashierNameLocalizationSchema = zod.z.object({
|
|
155
|
+
language: zod.z.enum([...AVAILABLE_LANGUAGES, "multi"]),
|
|
156
|
+
content: zod.z.string()
|
|
157
|
+
});
|
|
158
|
+
var cashierListItemSchema = zod.z.object({
|
|
159
|
+
deskId: zod.z.string(),
|
|
160
|
+
internalId: zod.z.number().int().nonnegative(),
|
|
161
|
+
name: zod.z.record(zod.z.string(), cashierNameLocalizationSchema)
|
|
162
|
+
});
|
|
163
|
+
var cashierListResponseSchema = zod.z.array(cashierListItemSchema);
|
|
164
|
+
var classifierSearchItemSchema = zod.z.object({
|
|
165
|
+
code: zod.z.string(),
|
|
166
|
+
// Optional: server may emit `{ code }` without `title` when the classifier
|
|
167
|
+
// entry exists in fuse but lacks a translation in the requested language.
|
|
168
|
+
title: zod.z.string().optional()
|
|
169
|
+
});
|
|
170
|
+
var classifierSearchResponseSchema = zod.z.array(classifierSearchItemSchema);
|
|
171
|
+
var receiptPickSchema = zod.z.object({
|
|
172
|
+
srcId: zod.z.number().int(),
|
|
173
|
+
time: zod.z.string().regex(/^\d+$/, "Invalid bigint string"),
|
|
174
|
+
tin: zod.z.string(),
|
|
175
|
+
fiscal: zod.z.string().nullable(),
|
|
176
|
+
sn: zod.z.string(),
|
|
177
|
+
address: zod.z.string().nullable(),
|
|
178
|
+
total: zod.z.number(),
|
|
179
|
+
taxpayer: zod.z.string(),
|
|
180
|
+
change: zod.z.number()
|
|
181
|
+
});
|
|
182
|
+
var cashierPickSchema = zod.z.object({
|
|
183
|
+
internalId: zod.z.number().int().nonnegative(),
|
|
184
|
+
deskId: zod.z.string(),
|
|
185
|
+
name: zod.z.array(localizationEntrySchema)
|
|
186
|
+
});
|
|
187
|
+
var departmentPickSchema = zod.z.object({
|
|
188
|
+
internalId: zod.z.number().int().nonnegative(),
|
|
189
|
+
taxRegime: taxRegimeSchema,
|
|
190
|
+
title: zod.z.array(localizationEntrySchema)
|
|
191
|
+
});
|
|
192
|
+
var offerPickSchema = zod.z.object({
|
|
193
|
+
type: offerTypeSchema,
|
|
194
|
+
classifierCode: zod.z.string(),
|
|
195
|
+
title: zod.z.array(localizationEntrySchema)
|
|
196
|
+
});
|
|
197
|
+
var saleItemPickSchema = zod.z.object({
|
|
198
|
+
srcId: zod.z.number().int(),
|
|
199
|
+
quantity: zod.z.number(),
|
|
200
|
+
price: zod.z.number(),
|
|
201
|
+
unit: unitSchema,
|
|
202
|
+
discount: zod.z.number().nullable(),
|
|
203
|
+
discountType: discountTypeSchema,
|
|
204
|
+
additionalDiscount: zod.z.number().nullable(),
|
|
205
|
+
additionalDiscountType: additionalDiscountTypeSchema,
|
|
206
|
+
department: departmentPickSchema,
|
|
207
|
+
offer: offerPickSchema
|
|
208
|
+
});
|
|
209
|
+
var saleRefundPickSchema = zod.z.object({
|
|
210
|
+
nonCashAmount: zod.z.number(),
|
|
211
|
+
cashAmount: zod.z.number(),
|
|
212
|
+
receipt: receiptPickSchema.nullable(),
|
|
213
|
+
items: zod.z.array(zod.z.object({ quantity: zod.z.number() }))
|
|
214
|
+
});
|
|
215
|
+
var saleDetailResponseSchema = zod.z.object({
|
|
216
|
+
id: zod.z.number().int().nonnegative(),
|
|
217
|
+
createdAt: isoDateTimeSchema,
|
|
218
|
+
buyerTin: zod.z.string().nullable(),
|
|
219
|
+
cashAmount: zod.z.number(),
|
|
220
|
+
nonCashAmount: zod.z.number(),
|
|
221
|
+
prepaymentAmount: zod.z.number(),
|
|
222
|
+
compensationAmount: zod.z.number(),
|
|
223
|
+
receipt: receiptPickSchema.nullable(),
|
|
224
|
+
refunds: zod.z.array(saleRefundPickSchema),
|
|
225
|
+
cashier: cashierPickSchema,
|
|
226
|
+
items: zod.z.array(saleItemPickSchema)
|
|
227
|
+
});
|
|
228
|
+
var prepaymentRefundPickSchema = zod.z.object({
|
|
229
|
+
nonCashAmount: zod.z.number(),
|
|
230
|
+
cashAmount: zod.z.number(),
|
|
231
|
+
receipt: receiptPickSchema.nullable()
|
|
232
|
+
});
|
|
233
|
+
var prepaymentDetailResponseSchema = zod.z.object({
|
|
234
|
+
id: zod.z.number().int().nonnegative(),
|
|
235
|
+
createdAt: isoDateTimeSchema,
|
|
236
|
+
buyerTin: zod.z.string().nullable(),
|
|
237
|
+
cashAmount: zod.z.number(),
|
|
238
|
+
nonCashAmount: zod.z.number(),
|
|
239
|
+
receipt: receiptPickSchema.nullable(),
|
|
240
|
+
refund: prepaymentRefundPickSchema.nullable(),
|
|
241
|
+
cashier: cashierPickSchema
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// src/fetch.ts
|
|
245
|
+
async function requestJson(schema, init) {
|
|
246
|
+
const { url, method, apiKey, body, fetchImpl, signal: externalSignal } = init;
|
|
247
|
+
const effectiveTimeout = init.timeoutMs === void 0 ? init.defaultTimeoutMs : init.timeoutMs;
|
|
248
|
+
const timeoutController = effectiveTimeout !== null ? new AbortController() : void 0;
|
|
249
|
+
const timeoutHandle = timeoutController !== void 0 && effectiveTimeout !== null ? setTimeout(() => timeoutController.abort(new Error("Request timeout")), effectiveTimeout) : void 0;
|
|
250
|
+
const signal = mergeSignals(externalSignal, timeoutController?.signal);
|
|
251
|
+
const headers = {
|
|
252
|
+
"x-api-key": apiKey,
|
|
253
|
+
accept: "application/json"
|
|
254
|
+
};
|
|
255
|
+
const requestInit = { method, headers };
|
|
256
|
+
if (body !== void 0) {
|
|
257
|
+
headers["content-type"] = "application/json";
|
|
258
|
+
requestInit.body = JSON.stringify(body);
|
|
259
|
+
}
|
|
260
|
+
if (signal !== void 0) {
|
|
261
|
+
requestInit.signal = signal;
|
|
262
|
+
}
|
|
263
|
+
try {
|
|
264
|
+
let response;
|
|
265
|
+
let rawText;
|
|
266
|
+
try {
|
|
267
|
+
response = await fetchImpl(url, requestInit);
|
|
268
|
+
rawText = await response.text();
|
|
269
|
+
} catch (cause) {
|
|
270
|
+
throw new VCRNetworkError(
|
|
271
|
+
cause instanceof Error ? cause.message : "Network request failed",
|
|
272
|
+
url,
|
|
273
|
+
{ cause }
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
const rawJson = rawText.length === 0 ? void 0 : safeJsonParse(rawText);
|
|
277
|
+
if (!response.ok) {
|
|
278
|
+
throw buildApiError(response.status, rawJson, url);
|
|
279
|
+
}
|
|
280
|
+
const parsed = schema.safeParse(rawJson);
|
|
281
|
+
if (!parsed.success) {
|
|
282
|
+
throw new VCRValidationError(
|
|
283
|
+
`VCR response did not match expected schema for ${method} ${url}`,
|
|
284
|
+
response.status,
|
|
285
|
+
url,
|
|
286
|
+
parsed.error.issues,
|
|
287
|
+
rawJson
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
return parsed.data;
|
|
291
|
+
} finally {
|
|
292
|
+
if (timeoutHandle !== void 0) {
|
|
293
|
+
clearTimeout(timeoutHandle);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function buildApiError(status, rawJson, url) {
|
|
298
|
+
const parsed = apiErrorBodySchema.safeParse(rawJson);
|
|
299
|
+
if (parsed.success) {
|
|
300
|
+
const body = {
|
|
301
|
+
error: parsed.data.error,
|
|
302
|
+
...parsed.data.issues !== void 0 && { issues: parsed.data.issues }
|
|
303
|
+
};
|
|
304
|
+
return new VCRApiError(status, body, url);
|
|
305
|
+
}
|
|
306
|
+
return new VCRValidationError(
|
|
307
|
+
`VCR returned ${status} but the error body did not match the expected envelope`,
|
|
308
|
+
status,
|
|
309
|
+
url,
|
|
310
|
+
parsed.error.issues,
|
|
311
|
+
rawJson
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
function safeJsonParse(text) {
|
|
315
|
+
try {
|
|
316
|
+
return JSON.parse(text);
|
|
317
|
+
} catch {
|
|
318
|
+
return text;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function mergeSignals(...signals) {
|
|
322
|
+
const present = signals.filter((signal) => signal !== void 0);
|
|
323
|
+
if (present.length === 0) {
|
|
324
|
+
return void 0;
|
|
325
|
+
}
|
|
326
|
+
return AbortSignal.any(present);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/client.ts
|
|
330
|
+
var VCRClient = class {
|
|
331
|
+
#apiKey;
|
|
332
|
+
#baseUrl;
|
|
333
|
+
#fetch;
|
|
334
|
+
#defaultTimeoutMs;
|
|
335
|
+
constructor(apiKey, options = {}) {
|
|
336
|
+
if (apiKey.length === 0) {
|
|
337
|
+
throw new Error("VCRClient requires a non-empty apiKey");
|
|
338
|
+
}
|
|
339
|
+
this.#apiKey = apiKey;
|
|
340
|
+
this.#baseUrl = stripTrailingSlash(options.baseUrl ?? DEFAULT_API_URL);
|
|
341
|
+
const candidate = options.fetch ?? globalThis.fetch;
|
|
342
|
+
if (typeof candidate !== "function") {
|
|
343
|
+
throw new Error(
|
|
344
|
+
"No fetch implementation available. Provide options.fetch or use a runtime that exposes a global fetch."
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
this.#fetch = options.fetch === void 0 ? candidate.bind(globalThis) : candidate;
|
|
348
|
+
this.#defaultTimeoutMs = options.timeoutMs === void 0 ? DEFAULT_TIMEOUT_MS : options.timeoutMs;
|
|
349
|
+
}
|
|
350
|
+
// ─── Sales ─────────────────────────────────────────────────────────────────
|
|
351
|
+
registerSale(data, options = {}) {
|
|
352
|
+
return this.#json("POST", "/sales", registerSaleResponseSchema, data, options);
|
|
353
|
+
}
|
|
354
|
+
getSale(saleId, options = {}) {
|
|
355
|
+
assertNonNegativeInt(saleId, "saleId");
|
|
356
|
+
return this.#json("GET", `/sales/${saleId}`, saleDetailResponseSchema, void 0, options);
|
|
357
|
+
}
|
|
358
|
+
registerSaleRefund(data, options = {}) {
|
|
359
|
+
return this.#json("POST", "/sales/refund", registerSaleRefundResponseSchema, data, options);
|
|
360
|
+
}
|
|
361
|
+
// ─── Prepayments ──────────────────────────────────────────────────────────
|
|
362
|
+
registerPrepayment(data, options = {}) {
|
|
363
|
+
return this.#json("POST", "/prepayments", registerPrepaymentResponseSchema, data, options);
|
|
364
|
+
}
|
|
365
|
+
getPrepayment(prepaymentId, options = {}) {
|
|
366
|
+
assertNonNegativeInt(prepaymentId, "prepaymentId");
|
|
367
|
+
return this.#json(
|
|
368
|
+
"GET",
|
|
369
|
+
`/prepayments/${prepaymentId}`,
|
|
370
|
+
prepaymentDetailResponseSchema,
|
|
371
|
+
void 0,
|
|
372
|
+
options
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
registerPrepaymentRefund(data, options = {}) {
|
|
376
|
+
return this.#json(
|
|
377
|
+
"POST",
|
|
378
|
+
"/prepayments/refund",
|
|
379
|
+
registerPrepaymentRefundResponseSchema,
|
|
380
|
+
data,
|
|
381
|
+
options
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
// ─── Cashiers ─────────────────────────────────────────────────────────────
|
|
385
|
+
listCashiers(options = {}) {
|
|
386
|
+
return this.#json("GET", "/cashiers", cashierListResponseSchema, void 0, options);
|
|
387
|
+
}
|
|
388
|
+
createCashier(data, options = {}) {
|
|
389
|
+
return this.#json("POST", "/cashiers", createCashierResponseSchema, data, options);
|
|
390
|
+
}
|
|
391
|
+
// ─── Offers / Departments ─────────────────────────────────────────────────
|
|
392
|
+
createOffer(data, options = {}) {
|
|
393
|
+
return this.#json("POST", "/offers", createOfferResponseSchema, data, options);
|
|
394
|
+
}
|
|
395
|
+
createDepartment(data, options = {}) {
|
|
396
|
+
return this.#json("POST", "/departments", createDepartmentResponseSchema, data, options);
|
|
397
|
+
}
|
|
398
|
+
// ─── Classifier search ────────────────────────────────────────────────────
|
|
399
|
+
searchClassifier(input, options = {}) {
|
|
400
|
+
return this.#json(
|
|
401
|
+
"GET",
|
|
402
|
+
"/searchByClassifier",
|
|
403
|
+
classifierSearchResponseSchema,
|
|
404
|
+
void 0,
|
|
405
|
+
options,
|
|
406
|
+
{ query: input.query, type: input.type, language: input.language }
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* @deprecated Use {@link searchClassifier} with an options object. Will be
|
|
411
|
+
* removed in 1.0. The new signature accepts `{ query, type, language }` so
|
|
412
|
+
* future params can be added without breaking the call site.
|
|
413
|
+
*/
|
|
414
|
+
searchClassifierCategory(query, type, language, options = {}) {
|
|
415
|
+
return this.searchClassifier({ query, type, language }, options);
|
|
416
|
+
}
|
|
417
|
+
// ─── Internal ─────────────────────────────────────────────────────────────
|
|
418
|
+
#json(method, path, schema, body, options, query) {
|
|
419
|
+
const url = query === void 0 ? `${this.#baseUrl}${path}` : appendQuery(`${this.#baseUrl}${path}`, query);
|
|
420
|
+
return requestJson(schema, {
|
|
421
|
+
method,
|
|
422
|
+
url,
|
|
423
|
+
apiKey: this.#apiKey,
|
|
424
|
+
...body !== void 0 && { body },
|
|
425
|
+
fetchImpl: this.#fetch,
|
|
426
|
+
defaultTimeoutMs: this.#defaultTimeoutMs,
|
|
427
|
+
...options
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
function appendQuery(url, query) {
|
|
432
|
+
const u = new URL(url);
|
|
433
|
+
for (const [key, value] of Object.entries(query)) {
|
|
434
|
+
u.searchParams.set(key, value);
|
|
435
|
+
}
|
|
436
|
+
return u.toString();
|
|
437
|
+
}
|
|
438
|
+
function stripTrailingSlash(url) {
|
|
439
|
+
return url.endsWith("/") ? url.slice(0, -1) : url;
|
|
440
|
+
}
|
|
441
|
+
function assertNonNegativeInt(value, name) {
|
|
442
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
443
|
+
throw new Error(`${name} must be a non-negative integer (got ${value})`);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
exports.AVAILABLE_LANGUAGES = AVAILABLE_LANGUAGES;
|
|
448
|
+
exports.DEFAULT_API_URL = DEFAULT_API_URL;
|
|
449
|
+
exports.DEFAULT_TIMEOUT_MS = DEFAULT_TIMEOUT_MS;
|
|
450
|
+
exports.REFUND_REASONS = REFUND_REASONS;
|
|
451
|
+
exports.TAX_REGIMES = TAX_REGIMES;
|
|
452
|
+
exports.VCRApiError = VCRApiError;
|
|
453
|
+
exports.VCRClient = VCRClient;
|
|
454
|
+
exports.VCRError = VCRError;
|
|
455
|
+
exports.VCRNetworkError = VCRNetworkError;
|
|
456
|
+
exports.VCRValidationError = VCRValidationError;
|
|
457
|
+
exports.cashierListItemSchema = cashierListItemSchema;
|
|
458
|
+
exports.cashierListResponseSchema = cashierListResponseSchema;
|
|
459
|
+
exports.classifierSearchItemSchema = classifierSearchItemSchema;
|
|
460
|
+
exports.classifierSearchResponseSchema = classifierSearchResponseSchema;
|
|
461
|
+
exports.createCashierResponseSchema = createCashierResponseSchema;
|
|
462
|
+
exports.createDepartmentResponseSchema = createDepartmentResponseSchema;
|
|
463
|
+
exports.createOfferResponseSchema = createOfferResponseSchema;
|
|
464
|
+
exports.prepaymentDetailResponseSchema = prepaymentDetailResponseSchema;
|
|
465
|
+
exports.registerPrepaymentRefundResponseSchema = registerPrepaymentRefundResponseSchema;
|
|
466
|
+
exports.registerPrepaymentResponseSchema = registerPrepaymentResponseSchema;
|
|
467
|
+
exports.registerSaleRefundResponseSchema = registerSaleRefundResponseSchema;
|
|
468
|
+
exports.registerSaleResponseSchema = registerSaleResponseSchema;
|
|
469
|
+
exports.saleDetailResponseSchema = saleDetailResponseSchema;
|
|
470
|
+
exports.unitsKeys = unitsKeys;
|
|
471
|
+
//# sourceMappingURL=index.cjs.map
|
|
2
472
|
//# sourceMappingURL=index.cjs.map
|
package/lib/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/VCRClient.ts","../src/constants.ts"],"sourcesContent":["export { default as VCRClient } from \"./VCRClient\";\nexport * from \"./types\";\nexport * from \"./constants\";\n","import { fetchWithValidation, simpleFetch } from \"simple-typed-fetch\";\nimport { z } from \"zod\";\n\nimport type { Language, SaleData } from \"./types\";\n\nconst API_URL = \"https://vcr.am/api/v1\";\n\nconst saleResponseSchema = z.object({\n urlId: z.string(),\n saleId: z.number(),\n crn: z.string(),\n srcReceiptId: z.number().int(),\n fiscal: z.string(),\n});\n\nconst errorResponseSchema = z.object({\n error: z.string(),\n});\n\nexport default class VCRClient {\n constructor(private readonly apiKey: string) {}\n\n async registerSale(data: SaleData) {\n const responseData = await simpleFetch(\n async () =>\n await fetchWithValidation(\n `${API_URL}/sales`,\n saleResponseSchema,\n {\n method: \"POST\",\n headers: {\n \"x-api-key\": this.apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(data),\n },\n errorResponseSchema\n )\n )();\n\n return responseData;\n }\n\n async searchClassifierCategory(\n query: string,\n type: \"product\" | \"service\",\n language: Language\n ) {\n const url = new URL(`${API_URL}/searchClassifier`);\n url.searchParams.append(\"query\", query);\n url.searchParams.append(\"type\", type);\n url.searchParams.append(\"language\", language);\n\n return await simpleFetch(\n async () =>\n await fetchWithValidation(\n url.toString(),\n z.array(z.object({ code: z.string(), title: z.string() })),\n {\n method: \"GET\",\n headers: {\n \"x-api-key\": this.apiKey,\n \"Content-Type\": \"application/json\",\n },\n },\n errorResponseSchema\n )\n )();\n }\n}\n","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"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,yBAAAE,EAAA,cAAAC,EAAA,cAAAC,IAAA,eAAAC,EAAAL,GCAA,IAAAM,EAAiD,8BACjDC,EAAkB,eAIZC,EAAU,wBAEVC,EAAqB,IAAE,OAAO,CAClC,MAAO,IAAE,OAAO,EAChB,OAAQ,IAAE,OAAO,EACjB,IAAK,IAAE,OAAO,EACd,aAAc,IAAE,OAAO,EAAE,IAAI,EAC7B,OAAQ,IAAE,OAAO,CACnB,CAAC,EAEKC,EAAsB,IAAE,OAAO,CACnC,MAAO,IAAE,OAAO,CAClB,CAAC,EAEoBC,EAArB,KAA+B,CAC7B,YAA6BC,EAAgB,CAAhB,YAAAA,CAAiB,CAE9C,MAAM,aAAaC,EAAgB,CAkBjC,OAjBqB,QAAM,eACzB,SACE,QAAM,uBACJ,GAAGL,CAAO,SACVC,EACA,CACE,OAAQ,OACR,QAAS,CACP,YAAa,KAAK,OAClB,eAAgB,kBAClB,EACA,KAAM,KAAK,UAAUI,CAAI,CAC3B,EACAH,CACF,CACJ,EAAE,CAGJ,CAEA,MAAM,yBACJI,EACAC,EACAC,EACA,CACA,IAAMC,EAAM,IAAI,IAAI,GAAGT,CAAO,mBAAmB,EACjD,OAAAS,EAAI,aAAa,OAAO,QAASH,CAAK,EACtCG,EAAI,aAAa,OAAO,OAAQF,CAAI,EACpCE,EAAI,aAAa,OAAO,WAAYD,CAAQ,EAErC,QAAM,eACX,SACE,QAAM,uBACJC,EAAI,SAAS,EACb,IAAE,MAAM,IAAE,OAAO,CAAE,KAAM,IAAE,OAAO,EAAG,MAAO,IAAE,OAAO,CAAE,CAAC,CAAC,EACzD,CACE,OAAQ,MACR,QAAS,CACP,YAAa,KAAK,OAClB,eAAgB,kBAClB,CACF,EACAP,CACF,CACJ,EAAE,CACJ,CACF,ECrEO,IAAMQ,EAAY,CACvB,KACA,OACA,MACA,MACA,OACA,OACA,KACA,OACA,OACA,MACA,KACA,IACA,IACA,IACA,KACA,KACA,SACA,MACA,MACA,MACA,KACA,QACA,OACA,KACA,OACA,OACA,KACA,MACA,KACA,SACA,OACF,EAEaC,EAAsB,CAAC,KAAM,KAAM,IAAI","names":["index_exports","__export","AVAILABLE_LANGUAGES","VCRClient","unitsKeys","__toCommonJS","import_simple_typed_fetch","import_zod","API_URL","saleResponseSchema","errorResponseSchema","VCRClient","apiKey","data","query","type","language","url","unitsKeys","AVAILABLE_LANGUAGES"]}
|
|
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\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});\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// ─── 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 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// ─── 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 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\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});\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 SaleDetail = z.infer<typeof saleDetailResponseSchema>;\nexport type PrepaymentDetail = z.infer<typeof prepaymentDetailResponseSchema>;\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 };\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 cashierListResponseSchema,\n classifierSearchResponseSchema,\n createCashierResponseSchema,\n createDepartmentResponseSchema,\n createOfferResponseSchema,\n type PrepaymentDetail,\n prepaymentDetailResponseSchema,\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} from \"./schemas\";\nimport type {\n ClassifierType,\n CreateCashierInput,\n CreateDepartmentInput,\n CreateOfferInput,\n Language,\n RegisterPrepaymentInput,\n RegisterPrepaymentRefundInput,\n RegisterSaleInput,\n RegisterSaleRefundInput,\n SearchClassifierInput,\n} from \"./types\";\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\";\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 // ─── 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 // ─── 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 createDepartment(\n data: CreateDepartmentInput,\n options: RequestOptions = {},\n ): Promise<CreateDepartmentResponse> {\n return this.#json(\"POST\", \"/departments\", createDepartmentResponseSchema, data, 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 // ─── 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"]}
|