ebag 0.0.2

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.
@@ -0,0 +1,447 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const commander_1 = require("commander");
10
+ const cart_1 = require("../lib/cart");
11
+ const auth_1 = require("../lib/auth");
12
+ const cookies_1 = require("../lib/cookies");
13
+ const config_1 = require("../lib/config");
14
+ const lists_1 = require("../lib/lists");
15
+ const orders_1 = require("../lib/orders");
16
+ const products_1 = require("../lib/products");
17
+ const search_1 = require("../lib/search");
18
+ const slots_1 = require("../lib/slots");
19
+ const format_1 = require("./format");
20
+ function requireSessionCookie() {
21
+ const session = (0, config_1.loadSession)();
22
+ if (!session.cookies) {
23
+ throw new Error('No session cookie found. Run `ebag login --cookie "<cookie>"` first.');
24
+ }
25
+ return session;
26
+ }
27
+ function formatError(err) {
28
+ const error = err;
29
+ const details = { message: error.message };
30
+ if (error.status)
31
+ details.status = error.status;
32
+ if (error.body)
33
+ details.body = error.body;
34
+ return details;
35
+ }
36
+ async function main() {
37
+ const program = new commander_1.Command();
38
+ function getPackageVersion() {
39
+ try {
40
+ const packagePath = node_path_1.default.resolve(__dirname, '../../package.json');
41
+ const raw = node_fs_1.default.readFileSync(packagePath, 'utf8');
42
+ const parsed = JSON.parse(raw);
43
+ return parsed.version || 'unknown';
44
+ }
45
+ catch {
46
+ return 'unknown';
47
+ }
48
+ }
49
+ program
50
+ .name('ebag')
51
+ .description('CLI for interacting with ebag.bg')
52
+ .version(getPackageVersion(), '-v, --version', 'Show CLI version')
53
+ .option('--json', 'Output JSON');
54
+ program
55
+ .command('login')
56
+ .description('Store session cookie and validate it')
57
+ .option('--cookie <cookie>', 'Cookie header value from browser')
58
+ .action(async (options) => {
59
+ const config = (0, config_1.loadConfig)();
60
+ const json = program.opts().json;
61
+ if (!options.cookie) {
62
+ if (json) {
63
+ (0, format_1.outputJson)({ instructions: (0, auth_1.getLoginInstructions)() });
64
+ }
65
+ else {
66
+ process.stdout.write(`${(0, auth_1.getLoginInstructions)()}\n`);
67
+ }
68
+ return;
69
+ }
70
+ const normalizedCookie = (0, cookies_1.normalizeCookieInput)(options.cookie);
71
+ const cookieError = (0, cookies_1.validateCookieInput)(normalizedCookie);
72
+ if (cookieError) {
73
+ throw new Error(`${cookieError} Run \`ebag login --cookie "<cookie>"\` with a Cookie header value.`);
74
+ }
75
+ try {
76
+ const session = {
77
+ cookies: normalizedCookie,
78
+ updatedAt: new Date().toISOString(),
79
+ };
80
+ const user = await (0, auth_1.validateSession)(config, session);
81
+ const email = user.email ||
82
+ user.username;
83
+ if (!email) {
84
+ throw new Error('Session validated but no user email was returned.');
85
+ }
86
+ (0, config_1.saveSession)(session);
87
+ if (json) {
88
+ (0, format_1.outputJson)({ status: 'ok', user, email });
89
+ }
90
+ else {
91
+ process.stdout.write('Login session validated and saved.\n');
92
+ process.stdout.write(`Logged in as: ${email}\n`);
93
+ }
94
+ }
95
+ catch (err) {
96
+ if (json) {
97
+ (0, format_1.outputJson)({ status: 'error', message: err.message });
98
+ }
99
+ else {
100
+ process.stderr.write(`Login failed: ${err.message}\n`);
101
+ }
102
+ }
103
+ });
104
+ program
105
+ .command('status')
106
+ .description('Show current login status')
107
+ .action(async () => {
108
+ const config = (0, config_1.loadConfig)();
109
+ const json = program.opts().json;
110
+ const session = (0, config_1.loadSession)();
111
+ if (!session.cookies) {
112
+ if (json) {
113
+ (0, format_1.outputJson)({ status: 'logged_out' });
114
+ }
115
+ else {
116
+ process.stdout.write('Logged out (no session cookie).\n');
117
+ }
118
+ return;
119
+ }
120
+ try {
121
+ const user = await (0, auth_1.validateSession)(config, session);
122
+ const email = user.email || user.username;
123
+ if (json) {
124
+ (0, format_1.outputJson)({ status: 'logged_in', user, email });
125
+ }
126
+ else {
127
+ process.stdout.write('Logged in.\n');
128
+ if (email) {
129
+ process.stdout.write(`Email: ${email}\n`);
130
+ }
131
+ }
132
+ }
133
+ catch (err) {
134
+ const error = err;
135
+ if (error.status && [401, 403].includes(error.status)) {
136
+ if (json) {
137
+ (0, format_1.outputJson)({ status: 'logged_out' });
138
+ }
139
+ else {
140
+ process.stdout.write('Logged out.\n');
141
+ }
142
+ return;
143
+ }
144
+ throw err;
145
+ }
146
+ });
147
+ program
148
+ .command('slots')
149
+ .description('Show the next available delivery slots')
150
+ .option('--limit <n>', 'Limit number of slots', '10')
151
+ .action(async (options) => {
152
+ const config = (0, config_1.loadConfig)();
153
+ const session = requireSessionCookie();
154
+ const json = program.opts().json;
155
+ const limit = Number(options.limit);
156
+ const slotsPayload = await (0, orders_1.getTimeSlots)(config, session);
157
+ const slots = (0, slots_1.normalizeSlots)(slotsPayload).filter((slot) => slot.isAvailable);
158
+ slots.sort(slots_1.sortSlots);
159
+ const limited = slots.slice(0, Number.isFinite(limit) ? limit : 10);
160
+ if (json) {
161
+ (0, format_1.outputJson)({ slots: limited });
162
+ return;
163
+ }
164
+ if (!limited.length) {
165
+ process.stdout.write('No available delivery slots.\n');
166
+ return;
167
+ }
168
+ const today = new Date();
169
+ const todayDate = today.toISOString().slice(0, 10);
170
+ const tomorrow = new Date(today);
171
+ tomorrow.setDate(today.getDate() + 1);
172
+ const tomorrowDate = tomorrow.toISOString().slice(0, 10);
173
+ let currentDate = '';
174
+ let printedHeader = false;
175
+ for (const slot of limited) {
176
+ if (slot.date !== currentDate) {
177
+ currentDate = slot.date;
178
+ let label = currentDate;
179
+ if (currentDate === todayDate) {
180
+ label = `Today (${currentDate})`;
181
+ }
182
+ else if (currentDate === tomorrowDate) {
183
+ label = `Tomorrow (${currentDate})`;
184
+ }
185
+ const headerPrefix = printedHeader ? '\n' : '';
186
+ process.stdout.write(`${headerPrefix}${(0, format_1.formatHeading)(`# ${label}`)}\n`);
187
+ printedHeader = true;
188
+ }
189
+ process.stdout.write(`${(0, slots_1.formatSlotRange)(slot.start, slot.end)} (${(0, slots_1.formatLoadPercent)(slot.loadPercent)})\n`);
190
+ }
191
+ });
192
+ program
193
+ .command('search')
194
+ .description('Search for products')
195
+ .argument('<query>', 'Search query')
196
+ .option('--limit <n>', 'Limit number of results', '20')
197
+ .option('--page <n>', 'Algolia page number (0-based)', '0')
198
+ .action(async (query, options) => {
199
+ const config = (0, config_1.loadConfig)();
200
+ const session = (0, config_1.loadSession)();
201
+ const json = program.opts().json;
202
+ const limit = Number(options.limit);
203
+ const page = Number(options.page);
204
+ const result = await (0, search_1.searchProducts)(config, session, query, { limit, page });
205
+ if (json) {
206
+ (0, format_1.outputJson)(result);
207
+ }
208
+ else {
209
+ (0, format_1.outputProducts)(result.results);
210
+ }
211
+ });
212
+ program
213
+ .command('product')
214
+ .description('Get product details by ID')
215
+ .argument('<productId>', 'Product ID')
216
+ .action(async (productId) => {
217
+ const config = (0, config_1.loadConfig)();
218
+ const session = (0, config_1.loadSession)();
219
+ const json = program.opts().json;
220
+ const result = await (0, products_1.getProductById)(config, session, Number(productId));
221
+ if (json) {
222
+ (0, format_1.outputJson)(result);
223
+ }
224
+ else {
225
+ (0, format_1.outputProductDetail)(result);
226
+ }
227
+ });
228
+ const order = program.command('order').description('Order operations');
229
+ order
230
+ .command('list')
231
+ .description('List recent orders')
232
+ .option('--limit <n>', 'Limit number of results', '10')
233
+ .option('--page <n>', 'Page number')
234
+ .option('--from <date>', 'Filter from date (YYYY-MM-DD)')
235
+ .option('--to <date>', 'Filter to date (YYYY-MM-DD)')
236
+ .action(async (options) => {
237
+ const config = (0, config_1.loadConfig)();
238
+ const session = requireSessionCookie();
239
+ const json = program.opts().json;
240
+ const limit = Number(options.limit);
241
+ const page = options.page ? Number(options.page) : undefined;
242
+ const from = options.from;
243
+ const to = options.to;
244
+ const result = await (0, orders_1.listOrders)(config, session, {
245
+ limit: Number.isFinite(limit) ? limit : 10,
246
+ page: page !== undefined && Number.isFinite(page) ? page : undefined,
247
+ from,
248
+ to,
249
+ });
250
+ if (json) {
251
+ (0, format_1.outputJson)(result);
252
+ }
253
+ else if (!result.results.length) {
254
+ process.stdout.write('No orders found.\n');
255
+ }
256
+ else {
257
+ (0, format_1.outputOrdersList)(result.results);
258
+ }
259
+ });
260
+ order
261
+ .command('show')
262
+ .description('Show order details')
263
+ .argument('<orderId>', 'Order ID')
264
+ .action(async (orderId) => {
265
+ const config = (0, config_1.loadConfig)();
266
+ const session = requireSessionCookie();
267
+ const json = program.opts().json;
268
+ const detail = await (0, orders_1.getOrderDetail)(config, session, String(orderId));
269
+ if (json) {
270
+ (0, format_1.outputJson)(detail);
271
+ }
272
+ else {
273
+ (0, format_1.outputOrderDetail)(detail);
274
+ }
275
+ });
276
+ const cart = program.command('cart').description('Cart operations');
277
+ cart
278
+ .command('add')
279
+ .argument('<productId>', 'Product ID')
280
+ .option('--qty <n>', 'Quantity', '1')
281
+ .action(async (productId, options) => {
282
+ const config = (0, config_1.loadConfig)();
283
+ const session = requireSessionCookie();
284
+ const json = program.opts().json;
285
+ const qty = Number(options.qty);
286
+ const result = await (0, cart_1.addToCart)(config, session, Number(productId), qty);
287
+ if (json) {
288
+ (0, format_1.outputJson)(result);
289
+ }
290
+ else {
291
+ process.stdout.write('Added to cart.\n');
292
+ }
293
+ });
294
+ cart
295
+ .command('update')
296
+ .argument('<productId>', 'Product ID')
297
+ .option('--qty <n>', 'Quantity', '1')
298
+ .action(async (productId, options) => {
299
+ const config = (0, config_1.loadConfig)();
300
+ const session = requireSessionCookie();
301
+ const json = program.opts().json;
302
+ const qty = Number(options.qty);
303
+ const result = await (0, cart_1.updateCart)(config, session, Number(productId), qty);
304
+ if (json) {
305
+ (0, format_1.outputJson)(result);
306
+ }
307
+ else {
308
+ process.stdout.write('Cart updated.\n');
309
+ }
310
+ });
311
+ cart
312
+ .command('show')
313
+ .description('Show cart contents')
314
+ .action(async () => {
315
+ const config = (0, config_1.loadConfig)();
316
+ const session = requireSessionCookie();
317
+ const json = program.opts().json;
318
+ const cartData = await (0, cart_1.getCart)(config, session);
319
+ if (json) {
320
+ (0, format_1.outputJson)(cartData);
321
+ return;
322
+ }
323
+ const items = Array.isArray(cartData.items)
324
+ ? cartData.items
325
+ : [];
326
+ const listItems = items
327
+ .map((item) => {
328
+ const entry = item;
329
+ const id = entry.product?.id ?? entry.product_id ?? entry.productId ?? entry.id;
330
+ const name = entry.product?.name ?? entry.name ?? 'Unknown';
331
+ const count = entry.quantity ?? entry.qty;
332
+ if (!id)
333
+ return null;
334
+ return { id: Number(id), name, count };
335
+ })
336
+ .filter(Boolean);
337
+ if (listItems.length) {
338
+ (0, format_1.outputList)(listItems);
339
+ }
340
+ else {
341
+ process.stdout.write('Cart is empty.\n');
342
+ }
343
+ });
344
+ const list = program.command('list').description('List operations');
345
+ list
346
+ .command('show')
347
+ .description('Show your lists')
348
+ .argument('[listId]', 'List ID')
349
+ .action(async (listId) => {
350
+ const config = (0, config_1.loadConfig)();
351
+ const session = requireSessionCookie();
352
+ const json = program.opts().json;
353
+ const lists = await (0, lists_1.getLists)(config, session);
354
+ if (listId) {
355
+ const listEntry = lists.find((item) => Number(item.id) === Number(listId));
356
+ if (!listEntry) {
357
+ throw new Error(`List ${listId} not found.`);
358
+ }
359
+ const listItems = await (0, lists_1.getListItems)(config, session, Number(listId));
360
+ const results = Array.isArray(listItems.results)
361
+ ? listItems.results
362
+ : [];
363
+ const count = typeof listItems.count === 'number'
364
+ ? listItems.count
365
+ : results.length;
366
+ if (json) {
367
+ (0, format_1.outputJson)({
368
+ ...listEntry,
369
+ count,
370
+ items: results,
371
+ next: listItems.next ?? null,
372
+ previous: listItems.previous ?? null,
373
+ });
374
+ }
375
+ else {
376
+ process.stdout.write(`${listEntry.name} (${listEntry.id})`);
377
+ if (!count) {
378
+ process.stdout.write(' - empty\n');
379
+ return;
380
+ }
381
+ process.stdout.write(` - ${count} items\n`);
382
+ const outputItems = results
383
+ .map((item) => {
384
+ const entry = item;
385
+ const product = entry.product;
386
+ const id = product?.id ?? entry.product_id ?? entry.productId ?? entry.id;
387
+ const name = product?.name ?? entry.name ?? 'Unknown';
388
+ const itemCount = entry.quantity ?? entry.qty;
389
+ if (!id)
390
+ return null;
391
+ return { id: Number(id), name, count: itemCount };
392
+ })
393
+ .filter(Boolean);
394
+ (0, format_1.outputList)(outputItems);
395
+ }
396
+ return;
397
+ }
398
+ if (json) {
399
+ (0, format_1.outputJson)(lists);
400
+ return;
401
+ }
402
+ (0, format_1.outputList)(lists.map((item) => ({
403
+ id: item.id,
404
+ name: item.name,
405
+ count: item.products?.length,
406
+ })));
407
+ });
408
+ list
409
+ .command('add')
410
+ .argument('<listId>', 'List ID')
411
+ .argument('<productId>', 'Product ID')
412
+ .option('--qty <n>', 'Quantity', '1')
413
+ .action(async (listId, productId, options) => {
414
+ const config = (0, config_1.loadConfig)();
415
+ const session = requireSessionCookie();
416
+ const json = program.opts().json;
417
+ const qty = Number(options.qty);
418
+ const result = await (0, lists_1.addToList)(config, session, Number(listId), Number(productId), qty);
419
+ if (json) {
420
+ (0, format_1.outputJson)(result);
421
+ }
422
+ else {
423
+ process.stdout.write('Added to list.\n');
424
+ }
425
+ });
426
+ try {
427
+ await program.parseAsync(process.argv);
428
+ }
429
+ catch (err) {
430
+ const json = program.opts().json;
431
+ if (json) {
432
+ (0, format_1.outputJson)({ status: 'error', ...formatError(err) });
433
+ }
434
+ else {
435
+ const details = formatError(err);
436
+ process.stderr.write(`${details.message}\n`);
437
+ if (details.status) {
438
+ process.stderr.write(`Status: ${details.status}\n`);
439
+ }
440
+ if (details.body) {
441
+ process.stderr.write(`Body: ${details.body}\n`);
442
+ }
443
+ }
444
+ process.exit(1);
445
+ }
446
+ }
447
+ main();
@@ -0,0 +1,3 @@
1
+ import type { Config, Session } from './types';
2
+ export declare function getLoginInstructions(): string;
3
+ export declare function validateSession(config: Config, session: Session): Promise<unknown>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLoginInstructions = getLoginInstructions;
4
+ exports.validateSession = validateSession;
5
+ const client_1 = require("./client");
6
+ function getLoginInstructions() {
7
+ return [
8
+ '1) Log in to https://www.ebag.bg in your browser.',
9
+ '2) Open DevTools > Network and click any request to https://www.ebag.bg (not a static asset).',
10
+ '3) In the request headers, copy the full Cookie header value (semicolon-separated).',
11
+ '4) Run: ebag login --cookie "<cookie>"',
12
+ ].join('\n');
13
+ }
14
+ async function validateSession(config, session) {
15
+ const result = await (0, client_1.requestEbag)(config, session, '/user/json');
16
+ return result.data;
17
+ }
@@ -0,0 +1,4 @@
1
+ import type { Config, Session } from './types';
2
+ export declare function addToCart(config: Config, session: Session, productId: number, quantity: number, unitTypeOverride?: string): Promise<unknown>;
3
+ export declare function updateCart(config: Config, session: Session, productId: number, quantity: number, unitTypeOverride?: string): Promise<unknown>;
4
+ export declare function getCart(config: Config, session: Session): Promise<unknown>;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addToCart = addToCart;
4
+ exports.updateCart = updateCart;
5
+ exports.getCart = getCart;
6
+ const client_1 = require("./client");
7
+ async function addToCart(config, session, productId, quantity, unitTypeOverride = 'false') {
8
+ const baseUrl = config.baseUrl || 'https://www.ebag.bg';
9
+ const body = new URLSearchParams({
10
+ product_id: String(productId),
11
+ quantity: String(quantity),
12
+ unit_type_override: unitTypeOverride,
13
+ });
14
+ const result = await (0, client_1.requestEbag)(config, session, '/cart/add', {
15
+ method: 'POST',
16
+ headers: {
17
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
18
+ origin: baseUrl,
19
+ referer: `${baseUrl}/search/`,
20
+ },
21
+ body,
22
+ });
23
+ return result.data;
24
+ }
25
+ async function updateCart(config, session, productId, quantity, unitTypeOverride = 'false') {
26
+ const baseUrl = config.baseUrl || 'https://www.ebag.bg';
27
+ const body = new URLSearchParams({
28
+ product_id: String(productId),
29
+ quantity: String(quantity),
30
+ unit_type_override: unitTypeOverride,
31
+ });
32
+ const result = await (0, client_1.requestEbag)(config, session, '/cart/update', {
33
+ method: 'POST',
34
+ headers: {
35
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
36
+ origin: baseUrl,
37
+ referer: `${baseUrl}/search/`,
38
+ },
39
+ body,
40
+ });
41
+ return result.data;
42
+ }
43
+ async function getCart(config, session) {
44
+ const result = await (0, client_1.requestEbag)(config, session, '/cart/json');
45
+ return result.data;
46
+ }
@@ -0,0 +1,13 @@
1
+ import type { Config, Session } from './types';
2
+ export type RequestResult<T> = {
3
+ status: number;
4
+ data: T;
5
+ headers: Record<string, string>;
6
+ };
7
+ export declare function requestEbag<T>(config: Config, session: Session, path: string, options?: {
8
+ method?: string;
9
+ headers?: Record<string, string>;
10
+ body?: string | URLSearchParams;
11
+ query?: Record<string, string | number | undefined>;
12
+ }): Promise<RequestResult<T>>;
13
+ export declare function requestAlgolia<T>(config: Config, body: unknown): Promise<RequestResult<T>>;
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requestEbag = requestEbag;
4
+ exports.requestAlgolia = requestAlgolia;
5
+ function normalizeHeaders(headers) {
6
+ const out = {};
7
+ headers.forEach((value, key) => {
8
+ out[key] = value;
9
+ });
10
+ return out;
11
+ }
12
+ function getCookieValue(cookies, name) {
13
+ if (!cookies)
14
+ return undefined;
15
+ const parts = cookies.split(';').map((part) => part.trim());
16
+ for (const part of parts) {
17
+ if (part.startsWith(`${name}=`)) {
18
+ return part.slice(name.length + 1);
19
+ }
20
+ }
21
+ return undefined;
22
+ }
23
+ async function requestEbag(config, session, path, options = {}) {
24
+ const baseUrl = config.baseUrl || 'https://www.ebag.bg';
25
+ const url = new URL(path, baseUrl);
26
+ if (options.query) {
27
+ for (const [key, value] of Object.entries(options.query)) {
28
+ if (value !== undefined) {
29
+ url.searchParams.set(key, String(value));
30
+ }
31
+ }
32
+ }
33
+ const headers = {
34
+ accept: 'application/json, text/plain, */*',
35
+ ...options.headers,
36
+ };
37
+ if (session.cookies) {
38
+ headers.cookie = session.cookies;
39
+ }
40
+ const method = (options.method || 'GET').toUpperCase();
41
+ if (!headers['x-csrftoken'] && method !== 'GET') {
42
+ const token = getCookieValue(session.cookies, 'csrftoken');
43
+ if (token) {
44
+ headers['x-csrftoken'] = token;
45
+ }
46
+ }
47
+ const response = await fetch(url.toString(), {
48
+ method,
49
+ headers,
50
+ body: options.body instanceof URLSearchParams ? options.body.toString() : options.body,
51
+ });
52
+ const contentType = response.headers.get('content-type') || '';
53
+ const raw = await response.text();
54
+ const data = contentType.includes('application/json') ? JSON.parse(raw) : raw;
55
+ if (!response.ok) {
56
+ const err = new Error(`Request failed ${response.status} ${url}`);
57
+ err.status = response.status;
58
+ err.body = raw;
59
+ throw err;
60
+ }
61
+ return {
62
+ status: response.status,
63
+ data,
64
+ headers: normalizeHeaders(response.headers),
65
+ };
66
+ }
67
+ async function requestAlgolia(config, body) {
68
+ const host = config.algolia?.host || 'jmjmdq9hhx-dsn.algolia.net';
69
+ const appId = config.algolia?.appId || 'JMJMDQ9HHX';
70
+ const apiKey = config.algolia?.apiKey || '42ca9458d9354298c7016ce9155d8481';
71
+ const url = new URL(`/1/indexes/*/queries`, `https://${host}`);
72
+ url.searchParams.set('x-algolia-agent', 'Algolia for JavaScript (4.24.0); Browser; instantsearch.js (4.80.0)');
73
+ const response = await fetch(url.toString(), {
74
+ method: 'POST',
75
+ headers: {
76
+ 'x-algolia-application-id': appId,
77
+ 'x-algolia-api-key': apiKey,
78
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
79
+ },
80
+ body: JSON.stringify(body),
81
+ });
82
+ const contentType = response.headers.get('content-type') || '';
83
+ const raw = await response.text();
84
+ const data = contentType.includes('application/json') ? JSON.parse(raw) : raw;
85
+ if (!response.ok) {
86
+ const err = new Error(`Algolia request failed ${response.status}`);
87
+ err.status = response.status;
88
+ err.body = raw;
89
+ throw err;
90
+ }
91
+ return {
92
+ status: response.status,
93
+ data,
94
+ headers: normalizeHeaders(response.headers),
95
+ };
96
+ }
@@ -0,0 +1,11 @@
1
+ import type { Cache, Config, Session } from './types';
2
+ export declare function getConfigDir(): string;
3
+ export declare function getConfigPath(): string;
4
+ export declare function getSessionPath(): string;
5
+ export declare function getCachePath(): string;
6
+ export declare function loadConfig(): Config;
7
+ export declare function saveConfig(config: Config): void;
8
+ export declare function loadSession(): Session;
9
+ export declare function saveSession(session: Session): void;
10
+ export declare function loadCache(): Cache;
11
+ export declare function saveCache(cache: Cache): void;