@cardog/api 0.1.1

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/dist/index.js ADDED
@@ -0,0 +1,2245 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var axios = require('axios');
6
+ var zod = require('zod');
7
+
8
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+
10
+ var axios__default = /*#__PURE__*/_interopDefault(axios);
11
+
12
+ // src/base.ts
13
+ var APIError = class extends Error {
14
+ constructor(message, status, code, data) {
15
+ super(message);
16
+ this.status = status;
17
+ this.code = code;
18
+ this.data = data;
19
+ this.name = "APIError";
20
+ }
21
+ };
22
+ var BaseClient = class {
23
+ constructor(config) {
24
+ this.config = config;
25
+ this.client = axios__default.default.create({
26
+ baseURL: config.baseUrl || "https://api.cardog.io",
27
+ headers: {
28
+ "Content-Type": "application/json",
29
+ ...config.apiKey && { Authorization: `Bearer ${config.apiKey}` }
30
+ }
31
+ });
32
+ this.setupInterceptors();
33
+ }
34
+ setConfig(config) {
35
+ this.config = config;
36
+ if (config.apiKey) {
37
+ this.client.defaults.headers.Authorization = `Bearer ${config.apiKey}`;
38
+ } else {
39
+ delete this.client.defaults.headers.Authorization;
40
+ }
41
+ }
42
+ setupInterceptors() {
43
+ this.client.interceptors.response.use(
44
+ (response) => response.data,
45
+ (error) => {
46
+ if (error.response) {
47
+ const { status, data } = error.response;
48
+ throw new APIError(
49
+ error.message,
50
+ status,
51
+ data?.code || "unknown_error",
52
+ data
53
+ );
54
+ }
55
+ throw error;
56
+ }
57
+ );
58
+ }
59
+ async get(path, options = {}) {
60
+ return this.client.get(path, {
61
+ headers: options.headers,
62
+ params: options.params
63
+ });
64
+ }
65
+ async post(path, data, options = {}) {
66
+ return this.client.post(path, data, {
67
+ headers: options.headers,
68
+ params: options.params
69
+ });
70
+ }
71
+ async put(path, data, options = {}) {
72
+ return this.client.put(path, data, {
73
+ headers: options.headers,
74
+ params: options.params
75
+ });
76
+ }
77
+ async patch(path, data, options = {}) {
78
+ return this.client.patch(path, data, {
79
+ headers: options.headers,
80
+ params: options.params
81
+ });
82
+ }
83
+ async delete(path, options = {}) {
84
+ return this.client.delete(path, {
85
+ headers: options.headers,
86
+ params: options.params
87
+ });
88
+ }
89
+ };
90
+ var MAX_PAGE_SIZE = 250;
91
+ var DEFAULT_RADIUS = 50;
92
+ var MAX_RADIUS = 500;
93
+ zod.z.object({
94
+ make: zod.z.string(),
95
+ model: zod.z.string(),
96
+ year: zod.z.coerce.number().int().min(1900).max(2050)
97
+ });
98
+ zod.z.string().length(17, "VIN must be exactly 17 characters").regex(/^[A-HJ-NPR-Z0-9]{17}$/, "Invalid VIN format");
99
+ var paginationSchema = zod.z.object({
100
+ page: zod.z.coerce.number().int().min(1, "Page number must be 1 or greater"),
101
+ // .default(1),
102
+ limit: zod.z.coerce.number().int().min(1, "Page size must be at least 1").max(MAX_PAGE_SIZE, `Page size cannot exceed ${MAX_PAGE_SIZE}`)
103
+ // .default(DEFAULT_PAGE_SIZE),
104
+ });
105
+ var locationSchema = zod.z.object({
106
+ lat: zod.z.coerce.number().min(-90, "Latitude must be between -90 and 90").max(90, "Latitude must be between -90 and 90"),
107
+ lng: zod.z.coerce.number().min(-180, "Longitude must be between -180 and 180").max(180, "Longitude must be between -180 and 180"),
108
+ radius: zod.z.coerce.number().min(1, "Radius must be at least 1 km").max(MAX_RADIUS, `Radius cannot exceed ${MAX_RADIUS} km`).default(DEFAULT_RADIUS)
109
+ });
110
+ var rangeSchema = (min, max) => zod.z.object({
111
+ min: zod.z.number().int().min(min).optional(),
112
+ max: zod.z.number().int().max(max).optional()
113
+ });
114
+ var sortDirectionsSchema = zod.z.string().transform((val) => val.toLowerCase()).pipe(zod.z.enum(["asc", "desc"]));
115
+ var idSchema = zod.z.string();
116
+ var timestampSchema = zod.z.string().datetime();
117
+ var sellerSchema = zod.z.object({
118
+ id: idSchema,
119
+ slug: zod.z.string().optional(),
120
+ // TODO: Remove soon.
121
+ type: zod.z.string(),
122
+ name: zod.z.string(),
123
+ email: zod.z.string().nullable(),
124
+ phone: zod.z.string().nullable(),
125
+ addressId: zod.z.number().nullable(),
126
+ dealershipId: idSchema.nullable(),
127
+ // Google My Business enhanced fields
128
+ gmbPhone: zod.z.string().nullable(),
129
+ gmbRating: zod.z.string().nullable(),
130
+ gmbReviewCount: zod.z.number().nullable(),
131
+ createdAt: timestampSchema,
132
+ updatedAt: timestampSchema,
133
+ deactivatedAt: timestampSchema.nullable()
134
+ });
135
+ var dealershipSchema = zod.z.object({
136
+ id: idSchema,
137
+ name: zod.z.string(),
138
+ primaryDomain: zod.z.string(),
139
+ metadata: zod.z.any(),
140
+ isVerified: zod.z.boolean(),
141
+ createdAt: timestampSchema,
142
+ updatedAt: timestampSchema
143
+ });
144
+ var addressSchema = zod.z.object({
145
+ id: zod.z.number(),
146
+ street: zod.z.string(),
147
+ city: zod.z.string(),
148
+ state: zod.z.string(),
149
+ postalCode: zod.z.string(),
150
+ country: zod.z.string(),
151
+ latitude: zod.z.string(),
152
+ longitude: zod.z.string(),
153
+ location: zod.z.object({
154
+ x: zod.z.number(),
155
+ y: zod.z.number()
156
+ }),
157
+ createdAt: timestampSchema,
158
+ updatedAt: timestampSchema
159
+ });
160
+ var mediaSchema = zod.z.object({
161
+ id: zod.z.number(),
162
+ listingId: idSchema.nullable(),
163
+ type: zod.z.string(),
164
+ url: zod.z.string(),
165
+ make: zod.z.string().nullable(),
166
+ model: zod.z.string().nullable(),
167
+ year: zod.z.number().nullable(),
168
+ width: zod.z.number().nullable(),
169
+ height: zod.z.number().nullable(),
170
+ sizeBytes: zod.z.number().nullable(),
171
+ mimeType: zod.z.string().nullable(),
172
+ sourceUri: zod.z.string().nullable(),
173
+ sourceType: zod.z.string().nullable(),
174
+ metadata: zod.z.any().nullable(),
175
+ createdAt: timestampSchema.nullable(),
176
+ updatedAt: timestampSchema.nullable(),
177
+ removedAt: timestampSchema.nullable()
178
+ });
179
+ var vehicleReportSchema = zod.z.object({
180
+ id: zod.z.string(),
181
+ vin: zod.z.string(),
182
+ url: zod.z.string().nullable(),
183
+ version: zod.z.string(),
184
+ type: zod.z.string(),
185
+ data: zod.z.any(),
186
+ // jsonb data
187
+ createdAt: timestampSchema,
188
+ updatedAt: timestampSchema
189
+ });
190
+ var patternMatchSchema = zod.z.object({
191
+ element: zod.z.string(),
192
+ code: zod.z.string(),
193
+ attributeId: zod.z.union([zod.z.string(), zod.z.number(), zod.z.null()]),
194
+ value: zod.z.string().nullable(),
195
+ confidence: zod.z.number(),
196
+ positions: zod.z.array(zod.z.number()),
197
+ schema: zod.z.string(),
198
+ metadata: zod.z.object({
199
+ lookupTable: zod.z.string().nullable().optional(),
200
+ groupName: zod.z.string().nullable().optional(),
201
+ elementWeight: zod.z.number().nullable().optional(),
202
+ patternType: zod.z.enum(["VDS", "VIS"]).nullable().optional(),
203
+ rawPattern: zod.z.string().nullable().optional(),
204
+ matchDetails: zod.z.object({
205
+ exactMatches: zod.z.number().optional(),
206
+ wildcardMatches: zod.z.number().optional(),
207
+ totalPositions: zod.z.number().optional()
208
+ }).nullable().optional()
209
+ }).optional()
210
+ });
211
+ zod.z.object({
212
+ vin: zod.z.string(),
213
+ valid: zod.z.boolean(),
214
+ components: zod.z.object({
215
+ checkDigit: zod.z.object({
216
+ position: zod.z.number(),
217
+ actual: zod.z.string(),
218
+ expected: zod.z.string().optional(),
219
+ isValid: zod.z.boolean()
220
+ }).optional(),
221
+ modelYear: zod.z.object({
222
+ year: zod.z.number(),
223
+ source: zod.z.enum(["position", "override", "calculated"]),
224
+ confidence: zod.z.number()
225
+ }).optional(),
226
+ wmi: zod.z.object({
227
+ code: zod.z.string(),
228
+ manufacturer: zod.z.string(),
229
+ country: zod.z.string(),
230
+ vehicleType: zod.z.string(),
231
+ region: zod.z.string(),
232
+ make: zod.z.string()
233
+ }).optional(),
234
+ vds: zod.z.object({
235
+ raw: zod.z.string(),
236
+ patterns: zod.z.array(patternMatchSchema)
237
+ }).optional(),
238
+ vis: zod.z.object({
239
+ raw: zod.z.string(),
240
+ patterns: zod.z.array(patternMatchSchema)
241
+ }).optional(),
242
+ vehicle: zod.z.object({
243
+ make: zod.z.string(),
244
+ model: zod.z.string(),
245
+ year: zod.z.number(),
246
+ series: zod.z.string().optional(),
247
+ trim: zod.z.string().optional(),
248
+ bodyStyle: zod.z.string().optional(),
249
+ driveType: zod.z.string().optional(),
250
+ engineType: zod.z.string().optional(),
251
+ fuelType: zod.z.string().optional(),
252
+ transmission: zod.z.string().optional(),
253
+ doors: zod.z.string().optional(),
254
+ gvwr: zod.z.string().optional(),
255
+ manufacturer: zod.z.string().optional()
256
+ }).optional(),
257
+ plant: zod.z.object({
258
+ country: zod.z.string(),
259
+ city: zod.z.string().optional(),
260
+ manufacturer: zod.z.string().optional(),
261
+ code: zod.z.string()
262
+ }).optional(),
263
+ engine: zod.z.object({
264
+ type: zod.z.string().optional(),
265
+ model: zod.z.string().optional(),
266
+ cylinders: zod.z.string().optional(),
267
+ displacement: zod.z.string().optional(),
268
+ fuel: zod.z.string().optional(),
269
+ power: zod.z.string().optional()
270
+ }).optional()
271
+ }),
272
+ errors: zod.z.array(zod.z.unknown()),
273
+ patterns: zod.z.array(patternMatchSchema).optional(),
274
+ metadata: zod.z.object({
275
+ processingTime: zod.z.number(),
276
+ confidence: zod.z.number(),
277
+ schemaVersion: zod.z.string(),
278
+ matchedSchema: zod.z.string().optional(),
279
+ totalPatterns: zod.z.number().optional(),
280
+ rawRecords: zod.z.array(zod.z.unknown()).optional(),
281
+ queries: zod.z.array(
282
+ zod.z.object({
283
+ sql: zod.z.string(),
284
+ params: zod.z.array(zod.z.unknown()),
285
+ timing: zod.z.number()
286
+ })
287
+ ).optional()
288
+ }).optional()
289
+ });
290
+ var vinDecodeResponseSchema = zod.z.object({
291
+ // TODO: Implement this properly with correct structure
292
+ variants: zod.z.array(zod.z.unknown())
293
+ // Temporary until research schemas are ported
294
+ });
295
+ var vinImageResponseSchema = zod.z.object({
296
+ result: zod.z.string(),
297
+ success: zod.z.boolean()
298
+ });
299
+ var marketOverviewSchema = zod.z.object({
300
+ vehicle: zod.z.string().describe("Human-readable vehicle label, e.g. '2022 Honda Civic'"),
301
+ totalListings: zod.z.number().describe("Count of active listings in the cohort"),
302
+ avgPrice: zod.z.number().describe("Average listing price (rounded)"),
303
+ medianPrice: zod.z.number().describe("Median listing price (rounded)"),
304
+ minPrice: zod.z.number().describe("Minimum listing price"),
305
+ maxPrice: zod.z.number().describe("Maximum listing price"),
306
+ q1Price: zod.z.number().describe("25th percentile price (rounded)"),
307
+ q3Price: zod.z.number().describe("75th percentile price (rounded)"),
308
+ avgDaysOnMarket: zod.z.number().describe("Average days on market across cohort (rounded)"),
309
+ avgOdometer: zod.z.number().describe("Average odometer reading across cohort (rounded)")
310
+ });
311
+ var priceDistributionSchema = zod.z.object({
312
+ bucketMin: zod.z.number().describe("Inclusive lower bound of the bucket"),
313
+ bucketMax: zod.z.number().describe(
314
+ "Inclusive upper bound for the last bucket, exclusive for others"
315
+ ),
316
+ count: zod.z.number().describe("Number of listings within the bucket bounds"),
317
+ percentage: zod.z.number().describe("Percentage of total listings that fall into the bucket")
318
+ }).describe("A single price histogram bucket.");
319
+ var pricingResponseSchema = zod.z.object({
320
+ distribution: zod.z.array(priceDistributionSchema).describe("Price distribution for a make/model/year cohort")
321
+ });
322
+ var odometerSegmentSchema = zod.z.object({
323
+ odometerMin: zod.z.number().describe("Inclusive lower bound of odometer segment"),
324
+ odometerMax: zod.z.number().describe("Inclusive upper bound for last segment, exclusive for others"),
325
+ listings: zod.z.number().describe("Number of listings within this odometer band"),
326
+ avgPrice: zod.z.number().describe("Average price within the segment (rounded)"),
327
+ avgOdometer: zod.z.number().describe("Average odometer within the segment (rounded)"),
328
+ minPrice: zod.z.number().describe("Minimum observed price in the segment"),
329
+ maxPrice: zod.z.number().describe("Maximum observed price in the segment")
330
+ });
331
+ var odometerResponseSchema = zod.z.object({
332
+ segments: zod.z.array(odometerSegmentSchema).describe("Odometer analysis for a make/model/year cohort")
333
+ });
334
+ var geographicMarketSchema = zod.z.object({
335
+ state: zod.z.string().describe("Two-letter region code (e.g. US state or CA province)"),
336
+ listings: zod.z.number().describe("Number of listings in the region"),
337
+ avgPrice: zod.z.number().describe("Average listing price in region (rounded)"),
338
+ medianPrice: zod.z.number().describe("Median listing price in region (rounded)"),
339
+ avgOdometer: zod.z.number().describe("Average odometer reading in region (rounded)"),
340
+ avgDaysOnMarket: zod.z.number().describe("Average days on market in region (rounded)"),
341
+ centerLat: zod.z.number().describe("Approximate geographic center latitude of listings in region"),
342
+ centerLng: zod.z.number().describe("Approximate geographic center longitude of listings in region")
343
+ });
344
+ var geographicResponseSchema = zod.z.object({
345
+ markets: zod.z.array(geographicMarketSchema).describe("Geographic analysis for a make/model/year cohort")
346
+ });
347
+ var timeSeriesPointSchema = zod.z.object({
348
+ period: zod.z.coerce.date().describe("Start of period (Monday for week, first day for month)"),
349
+ newListings: zod.z.number().describe("Number of new listings observed within the period"),
350
+ avgPrice: zod.z.number().describe("Period average listing price (rounded)"),
351
+ avgOdometer: zod.z.number().describe("Period average odometer (rounded)"),
352
+ priceChangePct: zod.z.number().describe(
353
+ "Price change vs previous period in percent (one decimal), if applicable"
354
+ )
355
+ });
356
+ var timeSeriesResponseSchema = zod.z.object({
357
+ trends: zod.z.array(timeSeriesPointSchema).describe("Time series data for a make/model/year cohort")
358
+ });
359
+ var marketAnalysisSchema = zod.z.object({
360
+ similarListings: zod.z.array(
361
+ zod.z.object({
362
+ id: zod.z.string(),
363
+ price: zod.z.number(),
364
+ odometer: zod.z.number(),
365
+ vin: zod.z.string(),
366
+ year: zod.z.number(),
367
+ make: zod.z.string(),
368
+ model: zod.z.string(),
369
+ trim: zod.z.string().nullable(),
370
+ listingDate: zod.z.coerce.date(),
371
+ daysOnMarket: zod.z.number(),
372
+ location: zod.z.string().nullable()
373
+ })
374
+ ),
375
+ priceAnalysis: zod.z.object({
376
+ count: zod.z.number(),
377
+ min: zod.z.number(),
378
+ max: zod.z.number(),
379
+ average: zod.z.number(),
380
+ median: zod.z.number(),
381
+ standardDev: zod.z.number(),
382
+ priceDistribution: zod.z.array(
383
+ zod.z.object({
384
+ range: zod.z.string(),
385
+ count: zod.z.number(),
386
+ percentage: zod.z.number()
387
+ })
388
+ )
389
+ }),
390
+ marketTrends: zod.z.object({
391
+ averageDaysOnMarket: zod.z.number(),
392
+ priceTrend: zod.z.number(),
393
+ listingVolume: zod.z.number()
394
+ }),
395
+ pricingGuidance: zod.z.object({
396
+ suggested: zod.z.number(),
397
+ confidence: zod.z.enum(["low", "medium", "high"])
398
+ })
399
+ });
400
+ var marketPositionSchema = zod.z.object({
401
+ id: zod.z.string().describe("Listing Id"),
402
+ price: zod.z.number().describe("Listing price"),
403
+ odometer: zod.z.number().describe("Odometer reading"),
404
+ trim: zod.z.string().nullable().describe("Vehicle trim"),
405
+ daysonmarket: zod.z.coerce.number().describe("Days on market"),
406
+ city: zod.z.string().nullable().describe("City"),
407
+ state: zod.z.string().nullable().describe("State"),
408
+ pricepercentile: zod.z.coerce.number().describe("Price percentile"),
409
+ pricevsmedian: zod.z.coerce.number().describe("Price vs median"),
410
+ pricecategory: zod.z.string().describe("Price category"),
411
+ marketaverage: zod.z.coerce.number().describe("Market average price")
412
+ });
413
+ var pulseResponseSchema = zod.z.object({
414
+ overview: zod.z.object({
415
+ totalListings: zod.z.number(),
416
+ avgPrice: zod.z.number(),
417
+ medianPrice: zod.z.number(),
418
+ minPrice: zod.z.number(),
419
+ maxPrice: zod.z.number(),
420
+ stdDev: zod.z.number()
421
+ }),
422
+ priceDistribution: zod.z.array(
423
+ zod.z.object({
424
+ range: zod.z.string(),
425
+ count: zod.z.number()
426
+ })
427
+ ).describe(
428
+ "Distribution of price ranges, e.g. [{ 'range': '$10,000 - $15,000', 'count': 100 }, { 'range': '$15,000 - $20,000', 'count': 50 }]"
429
+ ),
430
+ makeDistribution: zod.z.array(
431
+ zod.z.object({
432
+ make: zod.z.string(),
433
+ count: zod.z.number()
434
+ })
435
+ ).describe(
436
+ "Distribution of makes, e.g. [{ 'make': 'Honda', 'count': 100 }, { 'make': 'Toyota', 'count': 50 }]"
437
+ ),
438
+ modelDistribution: zod.z.record(
439
+ zod.z.string(),
440
+ zod.z.array(
441
+ zod.z.object({
442
+ model: zod.z.string(),
443
+ count: zod.z.number()
444
+ })
445
+ )
446
+ ).describe(
447
+ "Distribution of models by make, e.g. { 'Honda': [{ 'model': 'Civic', 'count': 100 }, { 'model': 'Accord', 'count': 50 }] }"
448
+ ),
449
+ yearDistribution: zod.z.array(
450
+ zod.z.object({
451
+ range: zod.z.string(),
452
+ count: zod.z.number()
453
+ })
454
+ ),
455
+ daysOnMarketByPrice: zod.z.array(
456
+ zod.z.object({
457
+ range: zod.z.string(),
458
+ avgDays: zod.z.number()
459
+ })
460
+ )
461
+ });
462
+ var trimBreakdownSchema = zod.z.object({
463
+ trim: zod.z.string().nullable().describe("Vehicle trim name"),
464
+ listings: zod.z.number().describe("Number of listings with this trim"),
465
+ avgPrice: zod.z.number().describe("Average listing price for this trim (rounded)"),
466
+ medianPrice: zod.z.number().describe("Median listing price for this trim (rounded)"),
467
+ minPrice: zod.z.number().describe("Minimum listing price for this trim"),
468
+ maxPrice: zod.z.number().describe("Maximum listing price for this trim"),
469
+ avgOdometer: zod.z.number().describe("Average odometer reading for this trim (rounded)"),
470
+ avgDaysOnMarket: zod.z.number().describe("Average days on market for this trim (rounded)"),
471
+ priceVsMarket: zod.z.number().describe("Percentage difference from overall market average")
472
+ });
473
+ var breakdownResponseSchema = zod.z.object({
474
+ vehicle: zod.z.string().describe("Human-readable vehicle label, e.g. '2022 Honda Civic'"),
475
+ totalListings: zod.z.number().describe("Total number of listings across all trims"),
476
+ overallAvgPrice: zod.z.number().describe("Overall average price across all trims"),
477
+ overallMedianPrice: zod.z.number().describe("Overall median price across all trims"),
478
+ trims: zod.z.array(trimBreakdownSchema).describe("Breakdown of prices by trim")
479
+ });
480
+ zod.z.object({
481
+ make: zod.z.string().describe("Vehicle make (e.g., 'Toyota')"),
482
+ model: zod.z.string().describe("Vehicle model (e.g., 'Camry')"),
483
+ year: zod.z.number().int().min(1900).max(2100).describe("Model year"),
484
+ lat: zod.z.number().min(-90).max(90).describe("Latitude of search center"),
485
+ lng: zod.z.number().min(-180).max(180).describe("Longitude of search center"),
486
+ radius: zod.z.number().min(10).max(500).default(75).describe("Search radius in kilometers (default 75km)")
487
+ });
488
+ var marketComparisonSchema = zod.z.object({
489
+ localAvgPrice: zod.z.number().describe("Local average price"),
490
+ nationalAvgPrice: zod.z.number().describe("National average price"),
491
+ priceDifferencePercent: zod.z.number().describe("Percentage difference (positive = local is higher)"),
492
+ localListings: zod.z.number().describe("Number of local listings"),
493
+ nationalListings: zod.z.number().describe("Total national listings")
494
+ });
495
+ var localMarketResponseSchema = zod.z.object({
496
+ vehicle: zod.z.string().describe("Vehicle label (e.g., '2022 Toyota Camry')"),
497
+ location: zod.z.object({
498
+ city: zod.z.string().nullable().describe("Nearest city name"),
499
+ province: zod.z.string().nullable().describe("Province/state"),
500
+ lat: zod.z.number().describe("Search center latitude"),
501
+ lng: zod.z.number().describe("Search center longitude"),
502
+ radiusKm: zod.z.number().describe("Search radius used")
503
+ }),
504
+ totalListings: zod.z.number().describe("Total listings found in area"),
505
+ pricing: zod.z.object({
506
+ avgPrice: zod.z.number().describe("Average listing price in the area"),
507
+ medianPrice: zod.z.number().describe("Median listing price in the area"),
508
+ minPrice: zod.z.number().describe("Minimum listing price found"),
509
+ maxPrice: zod.z.number().describe("Maximum listing price found"),
510
+ q1Price: zod.z.number().describe("25th percentile price"),
511
+ q3Price: zod.z.number().describe("75th percentile price")
512
+ }),
513
+ comparison: marketComparisonSchema,
514
+ priceDistribution: zod.z.array(
515
+ zod.z.object({
516
+ range: zod.z.string().describe("Price range label"),
517
+ count: zod.z.number().describe("Number of listings in this range")
518
+ })
519
+ ),
520
+ odometer: zod.z.object({
521
+ avgOdometer: zod.z.number().describe("Average odometer reading"),
522
+ minOdometer: zod.z.number().describe("Minimum odometer"),
523
+ maxOdometer: zod.z.number().describe("Maximum odometer")
524
+ }),
525
+ daysOnMarket: zod.z.object({
526
+ avg: zod.z.number().describe("Average days on market"),
527
+ median: zod.z.number().describe("Median days on market")
528
+ })
529
+ });
530
+ var demandMatrixCellSchema = zod.z.object({
531
+ count: zod.z.number().describe("Number of listings in this cell"),
532
+ avgPrice: zod.z.number().describe("Average price in this cell"),
533
+ avgDaysToSell: zod.z.number().describe("Average days to sell in this cell")
534
+ });
535
+ var demandMatrixRowSchema = zod.z.object({
536
+ priceBand: zod.z.string().describe("Price band label (e.g., 'P10-P25')"),
537
+ priceMin: zod.z.number().describe("Minimum price in this band"),
538
+ priceMax: zod.z.number().describe("Maximum price in this band"),
539
+ cells: zod.z.array(demandMatrixCellSchema).describe("Cells for each turn rate band")
540
+ });
541
+ var demandMatrixResponseSchema = zod.z.object({
542
+ vehicle: zod.z.string().describe("Vehicle label (e.g., '2022 Honda Civic')"),
543
+ totalListings: zod.z.number().describe("Total listings analyzed"),
544
+ totalSold: zod.z.number().describe("Total sold/removed listings used for turn rate"),
545
+ turnRateBands: zod.z.array(zod.z.string()).describe("Turn rate band labels (e.g., ['0-7d', '7-14d', ...])"),
546
+ priceBands: zod.z.array(demandMatrixRowSchema).describe("Price band rows with cell data"),
547
+ summary: zod.z.object({
548
+ medianPrice: zod.z.number().describe("Median price across all listings"),
549
+ medianDaysToSell: zod.z.number().describe("Median days to sell"),
550
+ fastestPriceBand: zod.z.string().nullable().describe("Price band with fastest turn"),
551
+ sweetSpot: zod.z.object({
552
+ priceBand: zod.z.string(),
553
+ turnRateBand: zod.z.string(),
554
+ count: zod.z.number()
555
+ }).nullable().describe("Optimal price/turn rate combination")
556
+ })
557
+ });
558
+ var sortFieldMap = {
559
+ price: "price",
560
+ year: "year",
561
+ odometer: "odometer",
562
+ createdat: "createdAt",
563
+ random: "random",
564
+ score: "score"
565
+ };
566
+ var listingSortFieldsSchema = zod.z.string().transform((val) => sortFieldMap[val.toLowerCase()]).refine((val) => val !== void 0, {
567
+ message: "Invalid sort field. Expected: price, year, odometer, createdAt, random, or score"
568
+ });
569
+ var listingSortSchema = zod.z.object({
570
+ field: listingSortFieldsSchema,
571
+ direction: sortDirectionsSchema
572
+ });
573
+ var listingFiltersSchema = zod.z.object({
574
+ ids: zod.z.array(zod.z.string()).optional().describe('An array of listing IDs to fetch directly. Example: ["abc-123", "def-456"]'),
575
+ makes: zod.z.array(zod.z.string()).optional().describe('An array of vehicle makes. Example: ["Toyota", "Honda"]'),
576
+ models: zod.z.record(zod.z.string(), zod.z.array(zod.z.string())).describe(
577
+ 'An object with vehicle makes as keys and an array of models as values. Example: {"Toyota": ["Corolla", "Camry"], "Honda": ["Civic"]}'
578
+ ).optional(),
579
+ trims: zod.z.array(zod.z.string()).optional().describe('An array of vehicle trims. Example: ["LE", "SE"]'),
580
+ year: rangeSchema(1900, 2030).optional().describe(
581
+ "An object with 'min' and 'max' properties representing the year range. Example: {min: 2010, max: 2020}"
582
+ ),
583
+ price: rangeSchema(0, 1e6).optional().describe(
584
+ "An object with 'min' and 'max' properties representing the price range. Example: {min: 10000, max: 20000}"
585
+ ),
586
+ odometer: rangeSchema(0, 1e6).optional().describe(
587
+ "An object with 'min' and 'max' properties representing the odometer range. Example: {min: 0, max: 50000}"
588
+ ),
589
+ saleTypes: zod.z.array(zod.z.string()).optional().describe('An array of sale types. Example: ["new", "used"]'),
590
+ bodyStyles: zod.z.array(zod.z.string()).optional().describe('An array of body styles. Example: ["SUV", "Sedan"]'),
591
+ fuelTypes: zod.z.array(zod.z.string()).optional().describe(
592
+ 'An array of fuel types. Example: ["Gasoline", "Electric", "Hybrid"]'
593
+ ),
594
+ exteriorColors: zod.z.array(zod.z.string()).optional().describe('An array of exterior colors. Example: ["Red", "Blue"]'),
595
+ interiorColors: zod.z.array(zod.z.string()).optional().describe('An array of interior colors. Example: ["Black", "Beige"]'),
596
+ location: locationSchema.optional(),
597
+ sellers: zod.z.array(zod.z.string()).optional().describe("An array of seller IDs. Example: ['123', '456']"),
598
+ createdAfter: timestampSchema.optional().describe("Filter listings created after this timestamp"),
599
+ createdBefore: timestampSchema.optional().describe("Filter listings created before this timestamp"),
600
+ updatedAfter: timestampSchema.optional().describe("Filter listings updated after this timestamp"),
601
+ updatedBefore: timestampSchema.optional().describe("Filter listings updated before this timestamp")
602
+ });
603
+ var listingQuerySchema = zod.z.object({
604
+ filters: listingFiltersSchema.optional(),
605
+ sort: listingSortSchema.optional(),
606
+ pagination: paginationSchema.optional()
607
+ });
608
+ var listingSchema = zod.z.object({
609
+ id: zod.z.string(),
610
+ vin: zod.z.string(),
611
+ sellerId: zod.z.string(),
612
+ websiteDomain: zod.z.string(),
613
+ price: zod.z.number().positive(),
614
+ currency: zod.z.string().default("USD"),
615
+ odometer: zod.z.number().optional(),
616
+ sourceUri: zod.z.string(),
617
+ stockNumber: zod.z.string().optional().nullable(),
618
+ score: zod.z.number(),
619
+ status: zod.z.string(),
620
+ mediaCount: zod.z.number(),
621
+ createdAt: timestampSchema,
622
+ updatedAt: timestampSchema,
623
+ removedAt: timestampSchema.nullable(),
624
+ make: zod.z.string(),
625
+ model: zod.z.string(),
626
+ year: zod.z.number().int().min(1900).max(2030),
627
+ trim: zod.z.string().optional().nullable(),
628
+ bodyStyle: zod.z.string().optional().nullable(),
629
+ fuelType: zod.z.string().optional().nullable(),
630
+ driveTrain: zod.z.string().optional().nullable(),
631
+ transmission: zod.z.string().optional().nullable(),
632
+ engineSize: zod.z.string().optional().nullable(),
633
+ horsepower: zod.z.string().optional().nullable(),
634
+ torque: zod.z.string().optional().nullable(),
635
+ exteriorColor: zod.z.string().optional().nullable(),
636
+ interiorColor: zod.z.string().optional().nullable(),
637
+ condition: zod.z.enum(["new", "used", "certified"]),
638
+ seller: sellerSchema,
639
+ media: zod.z.array(mediaSchema),
640
+ dealership: dealershipSchema,
641
+ location: addressSchema,
642
+ report: vehicleReportSchema.nullable().optional()
643
+ });
644
+ var listingSearchResponseSchema = zod.z.object({
645
+ listings: zod.z.array(listingSchema),
646
+ pagination: paginationSchema,
647
+ sort: listingSortSchema.optional(),
648
+ filters: listingFiltersSchema
649
+ });
650
+ var listingCountResponseSchema = zod.z.object({
651
+ count: zod.z.number().int().min(0),
652
+ filters: listingFiltersSchema
653
+ });
654
+ var facetItemSchema = zod.z.object({
655
+ value: zod.z.string(),
656
+ count: zod.z.number().int().min(0)
657
+ });
658
+ var histogramBucketSchema = zod.z.object({
659
+ min: zod.z.number(),
660
+ max: zod.z.number(),
661
+ count: zod.z.number().int().min(0)
662
+ });
663
+ var listingFacetsResponseSchema = zod.z.object({
664
+ makes: zod.z.array(facetItemSchema),
665
+ models: zod.z.array(
666
+ zod.z.object({
667
+ make: zod.z.string(),
668
+ model: zod.z.string(),
669
+ count: zod.z.number().int().min(0)
670
+ })
671
+ ),
672
+ bodyStyles: zod.z.array(facetItemSchema),
673
+ fuelTypes: zod.z.array(facetItemSchema),
674
+ saleTypes: zod.z.array(facetItemSchema),
675
+ exteriorColors: zod.z.array(facetItemSchema),
676
+ years: zod.z.object({
677
+ min: zod.z.number().int(),
678
+ max: zod.z.number().int()
679
+ }),
680
+ prices: zod.z.object({
681
+ min: zod.z.number(),
682
+ max: zod.z.number(),
683
+ histogram: zod.z.array(histogramBucketSchema)
684
+ }),
685
+ odometer: zod.z.object({
686
+ min: zod.z.number(),
687
+ max: zod.z.number(),
688
+ histogram: zod.z.array(histogramBucketSchema)
689
+ }),
690
+ totalCount: zod.z.number().int().min(0),
691
+ filters: listingFiltersSchema
692
+ });
693
+ var sellerTypeSchema = zod.z.enum([
694
+ "individual",
695
+ "dealership",
696
+ "auction",
697
+ "aggregator"
698
+ ]);
699
+ var locationSearchParamsSchema = zod.z.object({
700
+ lat: zod.z.coerce.number().min(-90).max(90).optional(),
701
+ lng: zod.z.coerce.number().min(-180).max(180).optional(),
702
+ radius: zod.z.coerce.number().min(0.1).max(500).optional(),
703
+ name: zod.z.string().optional(),
704
+ country: zod.z.string().optional(),
705
+ sellerType: sellerTypeSchema.optional(),
706
+ websiteDomain: zod.z.string().optional(),
707
+ hasActiveListings: zod.z.preprocess(
708
+ (val) => val === "true" ? true : val === "false" ? false : val,
709
+ zod.z.boolean().default(false)
710
+ ),
711
+ limit: zod.z.coerce.number().int().min(1).max(250).default(50),
712
+ offset: zod.z.coerce.number().int().min(0).default(0)
713
+ });
714
+ zod.z.object({
715
+ id: zod.z.string()
716
+ });
717
+ var locationAddressSchema = zod.z.object({
718
+ id: zod.z.number().nullable(),
719
+ street: zod.z.string().nullable(),
720
+ city: zod.z.string().nullable(),
721
+ state: zod.z.string().nullable(),
722
+ postalCode: zod.z.string().nullable(),
723
+ country: zod.z.string().nullable(),
724
+ latitude: zod.z.string().nullable(),
725
+ longitude: zod.z.string().nullable()
726
+ }).nullable();
727
+ var locationDealershipSchema = zod.z.object({
728
+ id: zod.z.string(),
729
+ name: zod.z.string(),
730
+ primaryDomain: zod.z.string().nullable()
731
+ }).nullable();
732
+ var locationResultSchema = zod.z.object({
733
+ id: zod.z.string(),
734
+ name: zod.z.string(),
735
+ slug: zod.z.string(),
736
+ type: sellerTypeSchema,
737
+ email: zod.z.string().nullable(),
738
+ phone: zod.z.string().nullable(),
739
+ // Google My Business enhanced fields
740
+ gmbPhone: zod.z.string().nullable().optional(),
741
+ gmbRating: zod.z.string().nullable().optional(),
742
+ gmbReviewCount: zod.z.number().nullable().optional(),
743
+ address: locationAddressSchema,
744
+ dealership: locationDealershipSchema,
745
+ totalActiveListings: zod.z.number(),
746
+ distance: zod.z.number().optional()
747
+ });
748
+ zod.z.object({
749
+ results: zod.z.array(locationResultSchema),
750
+ meta: zod.z.object({
751
+ total: zod.z.number(),
752
+ params: zod.z.any()
753
+ })
754
+ });
755
+ locationResultSchema.omit({
756
+ distance: true
757
+ });
758
+ var ConnectorType = /* @__PURE__ */ ((ConnectorType2) => {
759
+ ConnectorType2[ConnectorType2["TYPE_1"] = 1] = "TYPE_1";
760
+ ConnectorType2[ConnectorType2["TYPE_2"] = 25] = "TYPE_2";
761
+ ConnectorType2[ConnectorType2["CCS_TYPE_1"] = 33] = "CCS_TYPE_1";
762
+ ConnectorType2[ConnectorType2["CCS_TYPE_2"] = 32] = "CCS_TYPE_2";
763
+ ConnectorType2[ConnectorType2["CHADEMO"] = 2] = "CHADEMO";
764
+ ConnectorType2[ConnectorType2["TESLA"] = 27] = "TESLA";
765
+ ConnectorType2[ConnectorType2["NACS"] = 31] = "NACS";
766
+ ConnectorType2[ConnectorType2["WALL"] = 28] = "WALL";
767
+ ConnectorType2[ConnectorType2["TYPE_3"] = 3] = "TYPE_3";
768
+ ConnectorType2[ConnectorType2["IEC_60309"] = 8] = "IEC_60309";
769
+ ConnectorType2[ConnectorType2["DOMESTIC"] = 10] = "DOMESTIC";
770
+ ConnectorType2[ConnectorType2["COMMANDO"] = 11] = "COMMANDO";
771
+ ConnectorType2[ConnectorType2["GB_T"] = 13] = "GB_T";
772
+ ConnectorType2[ConnectorType2["UNSPECIFIED"] = 0] = "UNSPECIFIED";
773
+ return ConnectorType2;
774
+ })(ConnectorType || {});
775
+ var ChargingLevel = /* @__PURE__ */ ((ChargingLevel2) => {
776
+ ChargingLevel2[ChargingLevel2["LEVEL_1"] = 1] = "LEVEL_1";
777
+ ChargingLevel2[ChargingLevel2["LEVEL_2"] = 2] = "LEVEL_2";
778
+ ChargingLevel2[ChargingLevel2["LEVEL_3"] = 3] = "LEVEL_3";
779
+ ChargingLevel2[ChargingLevel2["UNSPECIFIED"] = 0] = "UNSPECIFIED";
780
+ return ChargingLevel2;
781
+ })(ChargingLevel || {});
782
+ var StationStatus = /* @__PURE__ */ ((StationStatus2) => {
783
+ StationStatus2["OPERATIONAL"] = "Operational";
784
+ StationStatus2["PLANNED"] = "Planned";
785
+ StationStatus2["NON_OPERATIONAL"] = "NonOperational";
786
+ StationStatus2["UNKNOWN"] = "Unknown";
787
+ return StationStatus2;
788
+ })(StationStatus || {});
789
+ zod.z.nativeEnum(ConnectorType);
790
+ zod.z.nativeEnum(ChargingLevel);
791
+ zod.z.nativeEnum(StationStatus);
792
+ var chargingConnectionSchema = zod.z.object({
793
+ connectionTypeId: zod.z.nativeEnum(ConnectorType),
794
+ connectionType: zod.z.string(),
795
+ powerKW: zod.z.number(),
796
+ currentType: zod.z.enum(["AC", "DC"]),
797
+ level: zod.z.nativeEnum(ChargingLevel),
798
+ voltage: zod.z.number(),
799
+ amperage: zod.z.number(),
800
+ pricing: zod.z.object({
801
+ costPerKWh: zod.z.number().nullable(),
802
+ costPerMinute: zod.z.number().nullable(),
803
+ costPerSession: zod.z.number().nullable(),
804
+ currency: zod.z.string()
805
+ }).optional()
806
+ });
807
+ var chargingStationSchema = zod.z.object({
808
+ id: zod.z.string(),
809
+ name: zod.z.string(),
810
+ address: zod.z.object({
811
+ addressLine1: zod.z.string(),
812
+ addressLine2: zod.z.string().optional().nullable(),
813
+ town: zod.z.string(),
814
+ stateOrProvince: zod.z.string(),
815
+ postcode: zod.z.string(),
816
+ countryCode: zod.z.string()
817
+ }),
818
+ location: zod.z.object({
819
+ latitude: zod.z.number(),
820
+ longitude: zod.z.number()
821
+ }),
822
+ connections: zod.z.array(chargingConnectionSchema),
823
+ status: zod.z.nativeEnum(StationStatus),
824
+ network: zod.z.string().nullable(),
825
+ operator: zod.z.string().nullable(),
826
+ dateCreated: zod.z.string(),
827
+ dateLastVerified: zod.z.string().nullable(),
828
+ usage: zod.z.string().nullable(),
829
+ supportPhone: zod.z.string().nullable(),
830
+ supportUrl: zod.z.string().nullable(),
831
+ isMembershipRequired: zod.z.boolean(),
832
+ isPayAtLocation: zod.z.boolean(),
833
+ photos: zod.z.array(zod.z.string()).optional(),
834
+ rating: zod.z.number().optional()
835
+ });
836
+ zod.z.object({
837
+ country: zod.z.string().default("US").describe("The country to search in"),
838
+ region: zod.z.string().optional().describe("The region to search in"),
839
+ lat: zod.z.coerce.number().optional().describe("The latitude to search in"),
840
+ lng: zod.z.coerce.number().optional().describe("The longitude to search in"),
841
+ radius: zod.z.coerce.number().optional().describe("The radius to search in"),
842
+ connector: zod.z.array(zod.z.nativeEnum(ConnectorType)).optional().describe("The connector types to search for"),
843
+ minPower: zod.z.coerce.number().optional().describe("The minimum power to search for"),
844
+ limit: zod.z.coerce.number().optional().describe("The number of results to return"),
845
+ includeInactive: zod.z.boolean().optional().describe("Whether to include inactive stations"),
846
+ includePhotos: zod.z.coerce.boolean().optional().describe("Whether to include photos")
847
+ });
848
+ var chargingStationResponseSchema = zod.z.object({
849
+ stations: zod.z.array(chargingStationSchema),
850
+ totalCount: zod.z.number(),
851
+ location: zod.z.object({
852
+ name: zod.z.string().nullable(),
853
+ countryCode: zod.z.string(),
854
+ regionCode: zod.z.string().nullable()
855
+ })
856
+ });
857
+ zod.z.object({
858
+ id: zod.z.string().min(1)
859
+ });
860
+ var chargingStationDetailResponseSchema = zod.z.object({
861
+ station: chargingStationSchema
862
+ });
863
+ var FuelType = /* @__PURE__ */ ((FuelType2) => {
864
+ FuelType2[FuelType2["REGULAR"] = 1] = "REGULAR";
865
+ FuelType2[FuelType2["MIDGRADE"] = 2] = "MIDGRADE";
866
+ FuelType2[FuelType2["PREMIUM"] = 3] = "PREMIUM";
867
+ FuelType2[FuelType2["DIESEL"] = 4] = "DIESEL";
868
+ FuelType2[FuelType2["E85"] = 5] = "E85";
869
+ FuelType2[FuelType2["E15"] = 6] = "E15";
870
+ FuelType2[FuelType2["PROPANE"] = 7] = "PROPANE";
871
+ FuelType2[FuelType2["BIODIESEL"] = 8] = "BIODIESEL";
872
+ FuelType2[FuelType2["CNG"] = 9] = "CNG";
873
+ FuelType2[FuelType2["LNG"] = 10] = "LNG";
874
+ return FuelType2;
875
+ })(FuelType || {});
876
+ var fuelTypeEnum = zod.z.nativeEnum(FuelType);
877
+ var fuelStationSchema = zod.z.object({
878
+ id: zod.z.string(),
879
+ name: zod.z.string(),
880
+ address: zod.z.object({
881
+ line1: zod.z.string(),
882
+ line2: zod.z.string().optional(),
883
+ locality: zod.z.string(),
884
+ region: zod.z.string(),
885
+ postalCode: zod.z.string(),
886
+ country: zod.z.string()
887
+ }),
888
+ location: zod.z.object({
889
+ latitude: zod.z.number(),
890
+ longitude: zod.z.number()
891
+ }),
892
+ price: zod.z.object({
893
+ credit: zod.z.number().nullable(),
894
+ cash: zod.z.number().nullable(),
895
+ postedTime: zod.z.string().nullable(),
896
+ formattedPrice: zod.z.string().nullable(),
897
+ reportedBy: zod.z.string().nullable()
898
+ }),
899
+ amenities: zod.z.array(zod.z.string()),
900
+ brands: zod.z.array(
901
+ zod.z.object({
902
+ id: zod.z.string(),
903
+ name: zod.z.string(),
904
+ type: zod.z.string(),
905
+ imageUrl: zod.z.string().optional().nullable()
906
+ })
907
+ ),
908
+ rating: zod.z.number().nullable(),
909
+ ratingsCount: zod.z.number(),
910
+ reviews: zod.z.array(
911
+ zod.z.object({
912
+ rating: zod.z.number(),
913
+ review: zod.z.string(),
914
+ nickname: zod.z.string(),
915
+ date: zod.z.string()
916
+ })
917
+ ),
918
+ fuels: zod.z.array(zod.z.string()),
919
+ isOpen: zod.z.boolean().optional()
920
+ });
921
+ var fuelStationResponseSchema = zod.z.object({
922
+ current: zod.z.number().nullable(),
923
+ average: zod.z.number().nullable(),
924
+ postedTime: zod.z.string().nullable(),
925
+ unit: zod.z.string(),
926
+ isMetric: zod.z.boolean(),
927
+ fuelType: fuelTypeEnum,
928
+ fuelName: zod.z.string(),
929
+ location: zod.z.object({
930
+ name: zod.z.string().nullable(),
931
+ countryCode: zod.z.string(),
932
+ regionCode: zod.z.string().nullable(),
933
+ locationType: zod.z.string().nullable(),
934
+ nearbyLocalities: zod.z.array(zod.z.string())
935
+ }),
936
+ history: zod.z.array(
937
+ zod.z.object({
938
+ date: zod.z.string(),
939
+ price: zod.z.number(),
940
+ formattedPrice: zod.z.string()
941
+ })
942
+ ),
943
+ stations: zod.z.array(fuelStationSchema)
944
+ });
945
+ zod.z.object({
946
+ // Coordinate-based search (preferred)
947
+ lat: zod.z.coerce.number().min(-90).max(90).optional(),
948
+ lng: zod.z.coerce.number().min(-180).max(180).optional(),
949
+ radius: zod.z.coerce.number().min(1).max(100).optional().default(10),
950
+ // km
951
+ // Region-based search (legacy)
952
+ country: zod.z.string().optional().default("US"),
953
+ region: zod.z.string().optional(),
954
+ city: zod.z.string().optional(),
955
+ // Filter options
956
+ fuelType: fuelTypeEnum.optional().default(1 /* REGULAR */),
957
+ limit: zod.z.coerce.number().min(1).max(50).optional().default(50),
958
+ distanceFormat: zod.z.enum(["auto", "mi", "km"]).optional().default("auto")
959
+ }).refine(
960
+ (data) => {
961
+ const hasCoords = data.lat !== void 0 && data.lng !== void 0;
962
+ const hasRegion = data.country !== void 0;
963
+ return hasCoords || hasRegion;
964
+ },
965
+ {
966
+ message: "Either lat/lng coordinates or country must be provided"
967
+ }
968
+ ).refine(
969
+ (data) => {
970
+ if (data.lat !== void 0 && data.lng === void 0) {
971
+ return false;
972
+ }
973
+ if (data.lng !== void 0 && data.lat === void 0) {
974
+ return false;
975
+ }
976
+ return true;
977
+ },
978
+ {
979
+ message: "Both lat and lng must be provided together"
980
+ }
981
+ );
982
+ zod.z.object({
983
+ stationId: zod.z.string().min(1)
984
+ });
985
+ var regionSchema = zod.z.enum(["US", "CA", "EU"]);
986
+ zod.z.enum([
987
+ "gasoline",
988
+ "diesel",
989
+ "electric",
990
+ "hybrid",
991
+ "plugin_hybrid",
992
+ "lpg",
993
+ "cng",
994
+ "hydrogen"
995
+ ]);
996
+ zod.z.enum(["FWD", "RWD", "AWD", "4WD"]);
997
+ zod.z.enum([
998
+ "manual",
999
+ "automatic",
1000
+ "CVT",
1001
+ "DCT",
1002
+ "AMT",
1003
+ "single_speed"
1004
+ ]);
1005
+ zod.z.record(zod.z.string(), zod.z.unknown());
1006
+ zod.z.record(zod.z.string(), zod.z.unknown());
1007
+ var variantSchema = zod.z.object({
1008
+ id: zod.z.string(),
1009
+ make: zod.z.string(),
1010
+ model: zod.z.string(),
1011
+ year: zod.z.number(),
1012
+ trim: zod.z.string().optional().nullable(),
1013
+ msrp: zod.z.number().optional().nullable(),
1014
+ bodyStyle: zod.z.string().optional().nullable(),
1015
+ styleName: zod.z.string().optional().nullable(),
1016
+ region: regionSchema.optional().nullable(),
1017
+ /** Spec object - passthrough to preserve all fields from different data sources */
1018
+ spec: zod.z.record(zod.z.string(), zod.z.unknown()).optional().nullable(),
1019
+ extra: zod.z.record(zod.z.string(), zod.z.unknown()).optional().nullable()
1020
+ });
1021
+ zod.z.object({
1022
+ make: zod.z.string().min(1, "Make is required")
1023
+ });
1024
+ zod.z.object({
1025
+ id: zod.z.string()
1026
+ });
1027
+ zod.z.object({
1028
+ listingId: zod.z.string()
1029
+ });
1030
+ zod.z.object({
1031
+ vin: zod.z.string().length(17, "VIN must be exactly 17 characters")
1032
+ });
1033
+ zod.z.object({
1034
+ make: zod.z.string().min(1, "Make is required"),
1035
+ model: zod.z.string().min(1, "Model is required")
1036
+ });
1037
+ zod.z.object({
1038
+ make: zod.z.string().min(1, "Make is required"),
1039
+ year: zod.z.coerce.number().int().min(1900).max(2030)
1040
+ });
1041
+ zod.z.object({
1042
+ make: zod.z.string().min(1, "Make is required"),
1043
+ model: zod.z.string().min(1, "Model is required"),
1044
+ year: zod.z.coerce.number().int().min(1900).max(2030)
1045
+ });
1046
+ zod.z.object({
1047
+ limit: zod.z.coerce.number().int().min(1).max(1e3).optional()
1048
+ });
1049
+ zod.z.object({
1050
+ page: zod.z.coerce.number().int().min(1).optional().default(1),
1051
+ limit: zod.z.coerce.number().int().min(1).max(500).optional().default(200),
1052
+ region: regionSchema.optional(),
1053
+ bodyStyle: zod.z.string().optional()
1054
+ });
1055
+ zod.z.object({
1056
+ region: regionSchema.optional()
1057
+ });
1058
+ zod.z.object({
1059
+ make: zod.z.string().min(1, "Make is required"),
1060
+ model: zod.z.string().min(1, "Model is required"),
1061
+ year: zod.z.coerce.number().int().min(1900).max(2030),
1062
+ limit: zod.z.coerce.number().int().min(1).max(100).optional(),
1063
+ page: zod.z.coerce.number().int().min(1).optional(),
1064
+ shotType: zod.z.enum([
1065
+ "FQ",
1066
+ "RQ",
1067
+ "I",
1068
+ "RI",
1069
+ "S",
1070
+ "CARGO",
1071
+ "E",
1072
+ "W",
1073
+ "D",
1074
+ "CC",
1075
+ "F",
1076
+ "R",
1077
+ "DETAIL",
1078
+ "B",
1079
+ "O",
1080
+ "PROFILE",
1081
+ "ALL"
1082
+ ]).optional(),
1083
+ category: zod.z.enum(["EXTERIOR", "INTERIOR"]).optional()
1084
+ });
1085
+ zod.z.object({
1086
+ make: zod.z.string().min(1, "Make is required"),
1087
+ model: zod.z.string().min(1, "Model is required"),
1088
+ year: zod.z.coerce.number().int().min(1900).max(2030)
1089
+ });
1090
+ var colorInfoSchema = zod.z.object({
1091
+ rgb: zod.z.string(),
1092
+ hex: zod.z.string(),
1093
+ name: zod.z.string()
1094
+ });
1095
+ var colorDataSchema = zod.z.object({
1096
+ EXTERIOR: zod.z.array(colorInfoSchema).optional(),
1097
+ INTERIOR: zod.z.array(colorInfoSchema).optional()
1098
+ });
1099
+ var researchImageSchema = zod.z.object({
1100
+ url: zod.z.string(),
1101
+ make: zod.z.string().optional().nullable(),
1102
+ model: zod.z.string().optional().nullable(),
1103
+ year: zod.z.number().optional().nullable(),
1104
+ shotType: zod.z.string().optional().nullable(),
1105
+ category: zod.z.string().optional().nullable(),
1106
+ title: zod.z.string().optional().nullable(),
1107
+ color: zod.z.string().optional().nullable(),
1108
+ metadata: zod.z.any().optional().nullable()
1109
+ });
1110
+ var lineupItemSchema = zod.z.object({
1111
+ make: zod.z.string(),
1112
+ model: zod.z.string(),
1113
+ year: zod.z.number(),
1114
+ msrp: zod.z.number().optional().nullable(),
1115
+ images: zod.z.array(researchImageSchema).optional()
1116
+ });
1117
+ var lineupResponseSchema = zod.z.object({
1118
+ data: zod.z.array(lineupItemSchema),
1119
+ total: zod.z.coerce.number(),
1120
+ page: zod.z.coerce.number(),
1121
+ limit: zod.z.coerce.number()
1122
+ });
1123
+ var variantArrayResponseSchema = zod.z.array(variantSchema);
1124
+ var variantResponseSchema = variantSchema.nullable();
1125
+ var researchImageArraySchema = zod.z.array(researchImageSchema);
1126
+ zod.z.object({
1127
+ makes: zod.z.array(zod.z.string().transform((val) => val.toUpperCase())).optional(),
1128
+ models: zod.z.array(zod.z.string().transform((val) => val.toUpperCase())).optional(),
1129
+ year: zod.z.object({
1130
+ min: zod.z.coerce.number().optional(),
1131
+ max: zod.z.coerce.number().optional()
1132
+ }).optional(),
1133
+ limit: zod.z.coerce.number().optional(),
1134
+ offset: zod.z.coerce.number().optional(),
1135
+ sort: zod.z.enum(["recall_date", "year", "make", "model"]).optional(),
1136
+ order: zod.z.enum(["asc", "desc"]).optional(),
1137
+ // Coerce country to country code
1138
+ country: zod.z.enum(["canada", "usa"]).optional().default("canada").transform((val) => val === "canada" ? "ca" : "us")
1139
+ });
1140
+ var transportCanadaRecallDetailSchema = zod.z.object({
1141
+ id: zod.z.string(),
1142
+ recallNumber: zod.z.string(),
1143
+ year: zod.z.number(),
1144
+ manufacturerRecallNumber: zod.z.string(),
1145
+ category: zod.z.string(),
1146
+ model: zod.z.string(),
1147
+ make: zod.z.string(),
1148
+ unitsAffected: zod.z.number(),
1149
+ systemType: zod.z.string(),
1150
+ notificationType: zod.z.string(),
1151
+ comment: zod.z.string(),
1152
+ dateYear: zod.z.number(),
1153
+ recallDate: zod.z.string(),
1154
+ processedAt: zod.z.string(),
1155
+ provider: zod.z.literal("Transport Canada")
1156
+ });
1157
+ var nhtsaRecallSummarySchema = zod.z.object({
1158
+ manufacturer: zod.z.string(),
1159
+ nhtsaCampaignNumber: zod.z.string(),
1160
+ parkIt: zod.z.boolean(),
1161
+ parkOutSide: zod.z.boolean(),
1162
+ overTheAirUpdate: zod.z.boolean(),
1163
+ nhtsaActionNumber: zod.z.string().optional(),
1164
+ reportReceivedDate: zod.z.string(),
1165
+ component: zod.z.string(),
1166
+ summary: zod.z.string(),
1167
+ consequence: zod.z.string(),
1168
+ remedy: zod.z.string(),
1169
+ notes: zod.z.string(),
1170
+ modelYear: zod.z.string(),
1171
+ make: zod.z.string(),
1172
+ model: zod.z.string(),
1173
+ provider: zod.z.literal("NHTSA")
1174
+ });
1175
+ var recallResponseSchema = zod.z.object({
1176
+ success: zod.z.boolean(),
1177
+ provider: zod.z.enum(["Transport Canada", "NHTSA"]).optional(),
1178
+ data: zod.z.array(
1179
+ zod.z.discriminatedUnion("provider", [
1180
+ transportCanadaRecallDetailSchema,
1181
+ nhtsaRecallSummarySchema
1182
+ ])
1183
+ ),
1184
+ meta: zod.z.object({
1185
+ make: zod.z.string().optional(),
1186
+ model: zod.z.string().optional(),
1187
+ startYear: zod.z.number().optional(),
1188
+ endYear: zod.z.number().optional(),
1189
+ modelYear: zod.z.number().optional(),
1190
+ recallNumber: zod.z.string().optional(),
1191
+ campaignNumber: zod.z.string().optional(),
1192
+ count: zod.z.number()
1193
+ })
1194
+ });
1195
+ zod.z.object({
1196
+ success: zod.z.boolean(),
1197
+ vin: zod.z.string(),
1198
+ vehicle: zod.z.object({
1199
+ make: zod.z.string(),
1200
+ model: zod.z.string(),
1201
+ year: zod.z.number()
1202
+ }),
1203
+ results: zod.z.array(recallResponseSchema),
1204
+ meta: zod.z.object({
1205
+ totalResults: zod.z.number(),
1206
+ providersSearched: zod.z.array(zod.z.string())
1207
+ })
1208
+ });
1209
+ var powertrainTypeSchema = zod.z.enum([
1210
+ "ice",
1211
+ "bev",
1212
+ "phev",
1213
+ "hev",
1214
+ "mhev",
1215
+ "fcev"
1216
+ ]);
1217
+ var testCycleSchema = zod.z.enum(["epa", "wltp", "mixed"]);
1218
+ var efficiencySourceSchema = zod.z.enum(["epa", "tc", "uk-vca", "eu-eea"]);
1219
+ zod.z.object({
1220
+ makes: zod.z.array(zod.z.string().transform((val) => val.toUpperCase())).optional(),
1221
+ models: zod.z.array(zod.z.string().transform((val) => val.toUpperCase())).optional(),
1222
+ year: rangeSchema(1900, 2050).optional(),
1223
+ powertrainTypes: zod.z.array(powertrainTypeSchema).optional(),
1224
+ fuelTypes: zod.z.array(zod.z.string()).optional(),
1225
+ sources: zod.z.array(efficiencySourceSchema).optional(),
1226
+ testCycles: zod.z.array(testCycleSchema).optional(),
1227
+ limit: zod.z.coerce.number().min(1).max(250).optional(),
1228
+ offset: zod.z.coerce.number().min(0).optional(),
1229
+ sort: zod.z.enum([
1230
+ "make",
1231
+ "model",
1232
+ "year",
1233
+ "combined_l_per_100km",
1234
+ "combined_kwh_per_100km",
1235
+ "co2_grams_per_km",
1236
+ "electric_range_km"
1237
+ ]).optional(),
1238
+ order: zod.z.enum(["asc", "desc"]).optional()
1239
+ });
1240
+ var efficiencyDetailSchema = zod.z.object({
1241
+ id: zod.z.number(),
1242
+ source: efficiencySourceSchema,
1243
+ sourceId: zod.z.string(),
1244
+ year: zod.z.number(),
1245
+ make: zod.z.string(),
1246
+ model: zod.z.string(),
1247
+ variant: zod.z.string().nullable(),
1248
+ powertrainType: powertrainTypeSchema,
1249
+ fuelType: zod.z.string(),
1250
+ transmission: zod.z.string().nullable(),
1251
+ driveType: zod.z.string().nullable(),
1252
+ // Engine specs
1253
+ engineDisplacementCc: zod.z.number().nullable(),
1254
+ enginePowerKw: zod.z.number().nullable(),
1255
+ cylinders: zod.z.number().nullable(),
1256
+ // Fuel consumption (L/100km)
1257
+ combinedLPer100km: zod.z.number().nullable(),
1258
+ cityLPer100km: zod.z.number().nullable(),
1259
+ highwayLPer100km: zod.z.number().nullable(),
1260
+ // Electric consumption (kWh/100km)
1261
+ combinedKwhPer100km: zod.z.number().nullable(),
1262
+ cityKwhPer100km: zod.z.number().nullable(),
1263
+ highwayKwhPer100km: zod.z.number().nullable(),
1264
+ // Emissions & Range
1265
+ co2GramsPerKm: zod.z.number().nullable(),
1266
+ electricRangeKm: zod.z.number().nullable(),
1267
+ totalRangeKm: zod.z.number().nullable(),
1268
+ // Vehicle specs
1269
+ massKg: zod.z.number().nullable(),
1270
+ wheelbaseMm: zod.z.number().nullable(),
1271
+ // Test info
1272
+ testCycle: testCycleSchema
1273
+ });
1274
+ var efficiencyStatsSchema = zod.z.object({
1275
+ totalRecords: zod.z.number(),
1276
+ bySource: zod.z.array(
1277
+ zod.z.object({
1278
+ source: efficiencySourceSchema,
1279
+ count: zod.z.number()
1280
+ })
1281
+ ),
1282
+ byPowertrain: zod.z.array(
1283
+ zod.z.object({
1284
+ powertrainType: zod.z.string(),
1285
+ count: zod.z.number()
1286
+ })
1287
+ ),
1288
+ byTestCycle: zod.z.array(
1289
+ zod.z.object({
1290
+ testCycle: zod.z.string(),
1291
+ count: zod.z.number()
1292
+ })
1293
+ ),
1294
+ yearRange: zod.z.object({
1295
+ min: zod.z.number(),
1296
+ max: zod.z.number()
1297
+ }),
1298
+ topMakes: zod.z.array(
1299
+ zod.z.object({
1300
+ make: zod.z.string(),
1301
+ count: zod.z.number()
1302
+ })
1303
+ )
1304
+ });
1305
+ zod.z.object({
1306
+ makes: zod.z.array(zod.z.string().transform((val) => val.toUpperCase())).optional(),
1307
+ models: zod.z.array(zod.z.string().transform((val) => val.toUpperCase())).optional(),
1308
+ year: rangeSchema(1900, 2050).optional(),
1309
+ vehicleClasses: zod.z.array(zod.z.string()).optional(),
1310
+ bodyStyles: zod.z.array(zod.z.string()).optional(),
1311
+ overallStars: zod.z.array(zod.z.string()).optional(),
1312
+ frontalRatings: zod.z.array(zod.z.string()).optional(),
1313
+ sideRatings: zod.z.array(zod.z.string()).optional(),
1314
+ rolloverRatings: zod.z.array(zod.z.string()).optional(),
1315
+ hasAdvancedSafety: zod.z.boolean().optional(),
1316
+ limit: zod.z.coerce.number().optional(),
1317
+ offset: zod.z.coerce.number().optional(),
1318
+ sort: zod.z.enum([
1319
+ "make",
1320
+ "model",
1321
+ "model_year",
1322
+ "overall_stars",
1323
+ "frontal_driver_stars",
1324
+ "side_driver_stars",
1325
+ "rollover_stars",
1326
+ "vehicle_class"
1327
+ ]).optional(),
1328
+ order: zod.z.enum(["asc", "desc"]).optional()
1329
+ });
1330
+ zod.z.object({
1331
+ id: zod.z.number(),
1332
+ make: zod.z.string(),
1333
+ model: zod.z.string(),
1334
+ modelYear: zod.z.number().nullable(),
1335
+ bodyStyle: zod.z.string().nullable(),
1336
+ vehicleClass: zod.z.string().nullable(),
1337
+ // Core Safety Ratings
1338
+ overallStars: zod.z.string().nullable(),
1339
+ frontalDriverStars: zod.z.string().nullable(),
1340
+ frontalPassengerStars: zod.z.string().nullable(),
1341
+ overallFrontalStars: zod.z.string().nullable(),
1342
+ sideDriverStars: zod.z.string().nullable(),
1343
+ sidePassengerStars: zod.z.string().nullable(),
1344
+ overallSideStars: zod.z.string().nullable(),
1345
+ sidePoleStars: zod.z.string().nullable(),
1346
+ rolloverStars: zod.z.string().nullable(),
1347
+ rolloverPossibility: zod.z.number().nullable(),
1348
+ // Advanced Safety Features
1349
+ frontCollisionWarning: zod.z.string().nullable(),
1350
+ laneDepartureWarning: zod.z.string().nullable(),
1351
+ crashImminentBrake: zod.z.string().nullable(),
1352
+ blindSpotDetection: zod.z.string().nullable(),
1353
+ backupCamera: zod.z.string().nullable(),
1354
+ abs: zod.z.string().nullable(),
1355
+ nhtsaEsc: zod.z.string().nullable(),
1356
+ // Airbag Information
1357
+ headSideAirbag: zod.z.string().nullable(),
1358
+ torsoSideAirbag: zod.z.string().nullable(),
1359
+ // Test Information
1360
+ frontalTestNumber: zod.z.number().nullable(),
1361
+ sideTestNumber: zod.z.number().nullable(),
1362
+ poleTestNumber: zod.z.number().nullable(),
1363
+ // Metadata
1364
+ processedAt: zod.z.string().nullable(),
1365
+ provider: zod.z.literal("NHTSA")
1366
+ });
1367
+ zod.z.object({
1368
+ totalReviews: zod.z.number(),
1369
+ reviewsWithOverallRating: zod.z.number(),
1370
+ topMakes: zod.z.array(
1371
+ zod.z.object({
1372
+ make: zod.z.string(),
1373
+ count: zod.z.number()
1374
+ })
1375
+ ),
1376
+ topVehicleClasses: zod.z.array(
1377
+ zod.z.object({
1378
+ vehicleClass: zod.z.string(),
1379
+ count: zod.z.number()
1380
+ })
1381
+ ),
1382
+ ratingDistribution: zod.z.array(
1383
+ zod.z.object({
1384
+ stars: zod.z.string(),
1385
+ count: zod.z.number()
1386
+ })
1387
+ ),
1388
+ advancedSafetyFeatures: zod.z.object({
1389
+ frontCollisionWarning: zod.z.number(),
1390
+ laneDepartureWarning: zod.z.number(),
1391
+ crashImminentBrake: zod.z.number(),
1392
+ blindSpotDetection: zod.z.number(),
1393
+ backupCamera: zod.z.number()
1394
+ })
1395
+ });
1396
+
1397
+ // ../contracts/src/codecs/base.codecs.ts
1398
+ function createSchemaWithCodec(schema, codec) {
1399
+ return {
1400
+ ...schema,
1401
+ encode: codec.encode,
1402
+ decode: codec.decode,
1403
+ schema
1404
+ // Original schema for validation
1405
+ };
1406
+ }
1407
+ var URLParamsBuilder = class {
1408
+ constructor() {
1409
+ this.params = new URLSearchParams();
1410
+ }
1411
+ /**
1412
+ * Set a single key-value pair
1413
+ * @param key - The parameter key
1414
+ * @param value - The value to set (undefined values are ignored)
1415
+ * @returns This builder instance for chaining
1416
+ */
1417
+ set(key, value) {
1418
+ if (value !== void 0) {
1419
+ this.params.set(key, encodeURIComponent(value.toString()));
1420
+ }
1421
+ return this;
1422
+ }
1423
+ /**
1424
+ * Set an array parameter as a comma-separated string
1425
+ * @param key - The parameter key
1426
+ * @param values - Array of strings to join (undefined/empty arrays are ignored)
1427
+ * @returns This builder instance for chaining
1428
+ */
1429
+ setArray(key, values) {
1430
+ if (values?.length) {
1431
+ this.set(key, values.join(","));
1432
+ }
1433
+ return this;
1434
+ }
1435
+ /**
1436
+ * Set a range parameter as separate min/max keys
1437
+ * @param key - The base parameter key
1438
+ * @param range - Object with optional min/max properties
1439
+ * @returns This builder instance for chaining
1440
+ */
1441
+ setRange(key, range) {
1442
+ if (range?.min !== void 0) {
1443
+ this.set(`${key}Min`, range.min);
1444
+ }
1445
+ if (range?.max !== void 0) {
1446
+ this.set(`${key}Max`, range.max);
1447
+ }
1448
+ return this;
1449
+ }
1450
+ /**
1451
+ * Build the final URLSearchParams object
1452
+ * @returns The constructed URLSearchParams instance
1453
+ */
1454
+ build() {
1455
+ return this.params;
1456
+ }
1457
+ };
1458
+ var URLParamsParser = class {
1459
+ constructor(params) {
1460
+ this.params = params;
1461
+ }
1462
+ /**
1463
+ * Get a single string parameter with proper URL decoding
1464
+ * @param key - The parameter key
1465
+ * @returns The decoded string value or undefined if not present
1466
+ */
1467
+ get(key) {
1468
+ const value = this.params.get(key);
1469
+ return value ? decodeURIComponent(value.replace(/\+/g, " ")) : void 0;
1470
+ }
1471
+ /**
1472
+ * Get a numeric parameter with type conversion
1473
+ * @param key - The parameter key
1474
+ * @param type - Whether to parse as integer or float
1475
+ * @returns The parsed number or undefined if not present/invalid
1476
+ */
1477
+ getNumber(key, type = "int") {
1478
+ const value = this.get(key);
1479
+ if (!value) return void 0;
1480
+ return type === "float" ? parseFloat(value) : parseInt(value);
1481
+ }
1482
+ /**
1483
+ * Get an array parameter by splitting on comma
1484
+ * @param key - The parameter key
1485
+ * @returns Array of trimmed strings or undefined if not present
1486
+ */
1487
+ getArray(key) {
1488
+ const value = this.get(key);
1489
+ return value?.split(",").map((s) => s.trim());
1490
+ }
1491
+ /**
1492
+ * Get a range parameter by looking for {key}Min and {key}Max
1493
+ * @param key - The base parameter key
1494
+ * @returns Object with min/max properties or undefined if neither present
1495
+ */
1496
+ getRange(key) {
1497
+ const min = this.getNumber(`${key}Min`);
1498
+ const max = this.getNumber(`${key}Max`);
1499
+ return min !== void 0 || max !== void 0 ? { min, max } : void 0;
1500
+ }
1501
+ };
1502
+
1503
+ // ../contracts/src/codecs/listings.codecs.ts
1504
+ var MAKE_MODEL_DELIMITER = ";";
1505
+ var MODEL_DELIMITER = "|";
1506
+ var SUB_MODEL_DELIMITER = ",";
1507
+ var ListingFiltersCodec = class {
1508
+ /**
1509
+ * Encode listing filters to URLSearchParams
1510
+ * @param filters - The filters object to encode
1511
+ * @returns URLSearchParams representation
1512
+ */
1513
+ encode(filters) {
1514
+ const builder = new URLParamsBuilder();
1515
+ builder.setArray("ids", filters.ids);
1516
+ builder.setArray("makes", filters.makes);
1517
+ builder.setArray("trims", filters.trims);
1518
+ builder.setArray("saleTypes", filters.saleTypes);
1519
+ builder.setArray("bodyStyles", filters.bodyStyles);
1520
+ builder.setArray("fuelTypes", filters.fuelTypes);
1521
+ builder.setArray("exteriorColors", filters.exteriorColors);
1522
+ builder.setArray("interiorColors", filters.interiorColors);
1523
+ builder.setArray("sellers", filters.sellers);
1524
+ if (filters.models) {
1525
+ const modelsString = Object.entries(filters.models).map(
1526
+ ([make, models]) => `${make}${MODEL_DELIMITER}${models.join(SUB_MODEL_DELIMITER)}`
1527
+ ).join(MAKE_MODEL_DELIMITER);
1528
+ builder.set("models", modelsString);
1529
+ }
1530
+ builder.setRange("year", filters.year);
1531
+ builder.setRange("price", filters.price);
1532
+ builder.setRange("odometer", filters.odometer);
1533
+ if (filters.location) {
1534
+ builder.set("lat", filters.location.lat);
1535
+ builder.set("lng", filters.location.lng);
1536
+ builder.set("radius", filters.location.radius);
1537
+ }
1538
+ return builder.build();
1539
+ }
1540
+ /**
1541
+ * Decode URLSearchParams back to listing filters
1542
+ * @param params - The URLSearchParams to decode
1543
+ * @returns The decoded filters object
1544
+ * @throws z.ZodError if the parameters don't match the expected schema
1545
+ */
1546
+ decode(params) {
1547
+ const parser = new URLParamsParser(params);
1548
+ const rawFilters = {
1549
+ ids: parser.getArray("ids"),
1550
+ makes: parser.getArray("makes"),
1551
+ models: this.parseModels(parser.get("models")),
1552
+ trims: parser.getArray("trims"),
1553
+ year: parser.getRange("year"),
1554
+ price: parser.getRange("price"),
1555
+ odometer: parser.getRange("odometer"),
1556
+ saleTypes: parser.getArray("saleTypes"),
1557
+ bodyStyles: parser.getArray("bodyStyles"),
1558
+ fuelTypes: parser.getArray("fuelTypes"),
1559
+ exteriorColors: parser.getArray("exteriorColors"),
1560
+ interiorColors: parser.getArray("interiorColors"),
1561
+ sellers: parser.getArray("sellers")
1562
+ };
1563
+ const lat = parser.getNumber("lat", "float");
1564
+ const lng = parser.getNumber("lng", "float");
1565
+ if (lat !== void 0 && lng !== void 0) {
1566
+ rawFilters.location = {
1567
+ lat,
1568
+ lng,
1569
+ radius: parser.getNumber("radius") ?? 50
1570
+ // Default radius
1571
+ };
1572
+ }
1573
+ return listingFiltersSchema.parse(rawFilters);
1574
+ }
1575
+ /**
1576
+ * Parse the complex models string format
1577
+ * @param value - The encoded models string
1578
+ * @returns Parsed models object or undefined
1579
+ * @private
1580
+ */
1581
+ parseModels(value) {
1582
+ if (!value) return void 0;
1583
+ return value.split(MAKE_MODEL_DELIMITER).reduce(
1584
+ (acc, makeModelPair) => {
1585
+ const [make, models] = makeModelPair.split(MODEL_DELIMITER);
1586
+ if (make && models) {
1587
+ acc[make] = models.split(SUB_MODEL_DELIMITER);
1588
+ }
1589
+ return acc;
1590
+ },
1591
+ {}
1592
+ );
1593
+ }
1594
+ };
1595
+ var ListingQueryCodec = class {
1596
+ constructor() {
1597
+ this.filtersCodec = new ListingFiltersCodec();
1598
+ }
1599
+ encode(query) {
1600
+ const params = new URLSearchParams();
1601
+ if (query.filters) {
1602
+ const filterParams = this.filtersCodec.encode(query.filters);
1603
+ filterParams.forEach((value, key) => {
1604
+ params.set(key, value);
1605
+ });
1606
+ }
1607
+ if (query.pagination) {
1608
+ if (query.pagination.page !== void 0) {
1609
+ params.set("page", query.pagination.page.toString());
1610
+ }
1611
+ if (query.pagination.limit !== void 0) {
1612
+ params.set("limit", query.pagination.limit.toString());
1613
+ }
1614
+ }
1615
+ if (query.sort) {
1616
+ params.set("sort", query.sort.field);
1617
+ params.set("order", query.sort.direction);
1618
+ }
1619
+ return params;
1620
+ }
1621
+ decode(params) {
1622
+ const parser = new URLParamsParser(params);
1623
+ const query = {};
1624
+ const filters = this.filtersCodec.decode(params);
1625
+ if (Object.keys(filters).length > 0) {
1626
+ query.filters = filters;
1627
+ }
1628
+ const page = parser.getNumber("page");
1629
+ const limit = parser.getNumber("limit");
1630
+ query.pagination = {
1631
+ page: page ?? 1,
1632
+ limit: limit ?? 25
1633
+ };
1634
+ const sort = parser.get("sort");
1635
+ const order = parser.get("order");
1636
+ if (sort) {
1637
+ query.sort = {
1638
+ field: sort,
1639
+ // Will be validated by schema
1640
+ direction: order ?? "desc"
1641
+ };
1642
+ }
1643
+ return listingQuerySchema.parse(query);
1644
+ }
1645
+ };
1646
+ createSchemaWithCodec(
1647
+ listingFiltersSchema,
1648
+ new ListingFiltersCodec()
1649
+ );
1650
+ createSchemaWithCodec(
1651
+ listingQuerySchema,
1652
+ new ListingQueryCodec()
1653
+ );
1654
+ var listingFiltersCodec = new ListingFiltersCodec();
1655
+ var listingQueryCodec = new ListingQueryCodec();
1656
+
1657
+ // src/routes/vin.ts
1658
+ var vinKeys = {
1659
+ all: ["vin"],
1660
+ image: (base64) => [...vinKeys.all, "image", base64],
1661
+ decode: (vin) => [...vinKeys.all, "decode", vin]
1662
+ };
1663
+ var VinAPI = class extends BaseClient {
1664
+ async decode(vin) {
1665
+ const response = await this.get(`/vin/${vin}`);
1666
+ return vinDecodeResponseSchema.parse(response);
1667
+ }
1668
+ async corgi(vin) {
1669
+ const response = await this.get(`/vin/corgi/${vin}`);
1670
+ return response;
1671
+ }
1672
+ async image(base64) {
1673
+ const response = await this.post(`/vin/image`, {
1674
+ image: base64
1675
+ });
1676
+ return vinImageResponseSchema.parse(response);
1677
+ }
1678
+ };
1679
+
1680
+ // src/routes/market.ts
1681
+ var marketKeys = {
1682
+ all: ["market"],
1683
+ analysis: (vin) => [...marketKeys.all, "analysis", vin],
1684
+ overview: (make, model, year) => [...marketKeys.all, "overview", make, model, year],
1685
+ pricing: (make, model, year) => [...marketKeys.all, "pricing", make, model, year],
1686
+ breakdown: (make, model, year) => [...marketKeys.all, "breakdown", make, model, year],
1687
+ odometer: (make, model, year) => [...marketKeys.all, "odometer", make, model, year],
1688
+ geography: (make, model, year) => [...marketKeys.all, "geography", make, model, year],
1689
+ trends: (make, model, year, period) => [...marketKeys.all, "trends", make, model, year, period],
1690
+ similar: (listingId, limit) => [...marketKeys.all, "similar", listingId, limit],
1691
+ position: (listingId) => [...marketKeys.all, "position", listingId],
1692
+ pulse: (options) => [...marketKeys.all, "pulse", options],
1693
+ byVin: (vin) => [...marketKeys.all, "byVin", vin],
1694
+ local: (params) => [...marketKeys.all, "local", params],
1695
+ demand: (make, model, year) => [...marketKeys.all, "demand", make, model, year]
1696
+ };
1697
+ var MarketAPI = class extends BaseClient {
1698
+ constructor() {
1699
+ super(...arguments);
1700
+ this.analysis = async (vin) => {
1701
+ const response = await this.get(`/market/analysis/vin/${vin}`);
1702
+ return marketAnalysisSchema.parse(response);
1703
+ };
1704
+ this.overview = async (make, model, year) => {
1705
+ const response = await this.get(
1706
+ `/market/${make}/${model}/${year}/overview`
1707
+ );
1708
+ return marketOverviewSchema.parse(response);
1709
+ };
1710
+ this.pricing = async (make, model, year) => {
1711
+ const response = await this.get(
1712
+ `/market/${make}/${model}/${year}/pricing`
1713
+ );
1714
+ return pricingResponseSchema.parse(response);
1715
+ };
1716
+ this.breakdown = async (make, model, year) => {
1717
+ const response = await this.get(
1718
+ `/market/${make}/${model}/${year}/breakdown`
1719
+ );
1720
+ return breakdownResponseSchema.parse(response);
1721
+ };
1722
+ this.odometer = async (make, model, year) => {
1723
+ const response = await this.get(
1724
+ `/market/${make}/${model}/${year}/odometer`
1725
+ );
1726
+ return odometerResponseSchema.parse(response);
1727
+ };
1728
+ this.geography = async (make, model, year) => {
1729
+ const response = await this.get(
1730
+ `/market/${make}/${model}/${year}/geography`
1731
+ );
1732
+ return geographicResponseSchema.parse(response);
1733
+ };
1734
+ this.trends = async (make, model, year, period) => {
1735
+ const response = await this.get(
1736
+ `/market/${make}/${model}/${year}/trends`,
1737
+ {
1738
+ params: {
1739
+ period
1740
+ }
1741
+ }
1742
+ );
1743
+ return timeSeriesResponseSchema.parse(response);
1744
+ };
1745
+ this.similar = async (listingId, limit) => {
1746
+ const response = await this.get(
1747
+ `/market/listings/${listingId}/similar`,
1748
+ {
1749
+ params: {
1750
+ limit
1751
+ }
1752
+ }
1753
+ );
1754
+ return response;
1755
+ };
1756
+ this.position = async (listingId) => {
1757
+ const response = await this.get(
1758
+ `/market/listings/${listingId}/position`
1759
+ );
1760
+ return marketPositionSchema.parse(response);
1761
+ };
1762
+ this.pulse = async (options) => {
1763
+ const response = await this.get(`/market/overview`, {
1764
+ params: options
1765
+ });
1766
+ return pulseResponseSchema.parse(response);
1767
+ };
1768
+ this.byVin = async (vin) => {
1769
+ return this.analysis(vin);
1770
+ };
1771
+ this.localMarket = async (params) => {
1772
+ const { make, model, year, lat, lng, radius } = params;
1773
+ const response = await this.get(
1774
+ `/market/${make}/${model}/${year}/local`,
1775
+ {
1776
+ params: { lat, lng, radius }
1777
+ }
1778
+ );
1779
+ return localMarketResponseSchema.parse(response);
1780
+ };
1781
+ this.demand = async (make, model, year) => {
1782
+ const response = await this.get(
1783
+ `/market/${make}/${model}/${year}/demand`
1784
+ );
1785
+ return demandMatrixResponseSchema.parse(response);
1786
+ };
1787
+ }
1788
+ };
1789
+
1790
+ // src/routes/listings.ts
1791
+ var listingsKeys = {
1792
+ all: ["listings"],
1793
+ search: (params) => [...listingsKeys.all, "search", params],
1794
+ count: (params) => [...listingsKeys.all, "count", params],
1795
+ facets: (params) => [...listingsKeys.all, "facets", params],
1796
+ getById: (id) => [...listingsKeys.all, "getById", id]
1797
+ };
1798
+ var ListingsAPI = class extends BaseClient {
1799
+ async search(params) {
1800
+ const searchParams = listingQueryCodec.encode(params);
1801
+ const response = await this.get("/listings/search", {
1802
+ params: searchParams
1803
+ });
1804
+ return listingSearchResponseSchema.parse(response);
1805
+ }
1806
+ async count(params) {
1807
+ const searchParams = listingQueryCodec.encode(params);
1808
+ const response = await this.get("/listings/count", {
1809
+ params: searchParams
1810
+ });
1811
+ return listingCountResponseSchema.parse(response);
1812
+ }
1813
+ async getById(id) {
1814
+ const response = await this.get(`/listings/id/${id}`);
1815
+ return listingSchema.parse(response);
1816
+ }
1817
+ async facets(params) {
1818
+ const searchParams = listingQueryCodec.encode(params);
1819
+ const response = await this.get("/listings/facets", {
1820
+ params: searchParams
1821
+ });
1822
+ return listingFacetsResponseSchema.parse(response);
1823
+ }
1824
+ decodeSearchParams(searchParams) {
1825
+ return listingFiltersCodec.decode(searchParams);
1826
+ }
1827
+ encodeFilters(filters) {
1828
+ return listingFiltersCodec.encode(filters);
1829
+ }
1830
+ };
1831
+ var searchResponseSchema = zod.z.object({
1832
+ results: zod.z.array(locationResultSchema),
1833
+ meta: zod.z.any().optional()
1834
+ });
1835
+ var locationsKeys = {
1836
+ all: ["locations"],
1837
+ search: (params) => [...locationsKeys.all, "search", params],
1838
+ detail: (id) => [...locationsKeys.all, "detail", id],
1839
+ bySlug: (slug) => [...locationsKeys.all, "slug", slug]
1840
+ };
1841
+ var LocationsAPI = class extends BaseClient {
1842
+ async search(params) {
1843
+ const parsed = locationSearchParamsSchema.parse(params);
1844
+ const cleanParams = Object.fromEntries(
1845
+ Object.entries(parsed).filter(([_, v]) => v !== void 0)
1846
+ );
1847
+ const response = await this.get("/locations/search", {
1848
+ params: cleanParams
1849
+ });
1850
+ return searchResponseSchema.parse(response);
1851
+ }
1852
+ async getById(id) {
1853
+ const response = await this.get(`/locations/id/${id}`);
1854
+ return locationResultSchema.parse(response);
1855
+ }
1856
+ async getByName(name) {
1857
+ const response = await this.get(
1858
+ `/locations/name/${encodeURIComponent(name)}`
1859
+ );
1860
+ return locationResultSchema.parse(response);
1861
+ }
1862
+ async getBySlug(slug) {
1863
+ const response = await this.get(`/locations/slug/${slug}`);
1864
+ return locationResultSchema.parse(response);
1865
+ }
1866
+ async getByIdentifier(identifier) {
1867
+ const response = await this.get(
1868
+ `/locations/${encodeURIComponent(identifier)}`
1869
+ );
1870
+ return locationResultSchema.parse(response);
1871
+ }
1872
+ };
1873
+
1874
+ // src/routes/charging.ts
1875
+ var chargingKeys = {
1876
+ all: ["charging"],
1877
+ stations: (params) => [...chargingKeys.all, "stations", params],
1878
+ station: (id) => [...chargingKeys.all, "station", id]
1879
+ };
1880
+ var ChargingAPI = class extends BaseClient {
1881
+ async getStations(params) {
1882
+ const response = await this.get("/charging", { params });
1883
+ return chargingStationResponseSchema.parse(response);
1884
+ }
1885
+ async getStation(id) {
1886
+ try {
1887
+ const response = await this.get(`/charging/${id}`);
1888
+ const parsed = chargingStationDetailResponseSchema.parse(response);
1889
+ return parsed.station;
1890
+ } catch {
1891
+ return null;
1892
+ }
1893
+ }
1894
+ };
1895
+
1896
+ // src/routes/fuel.ts
1897
+ var fuelKeys = {
1898
+ all: ["fuel"],
1899
+ search: (params) => [...fuelKeys.all, "search", params]
1900
+ };
1901
+ var FuelAPI = class extends BaseClient {
1902
+ /**
1903
+ * Search for fuel prices and stations
1904
+ */
1905
+ async search(params) {
1906
+ const { fuelType, ...queryParams } = params;
1907
+ const response = await this.get(
1908
+ `/fuel/${fuelType.toLowerCase()}`,
1909
+ { params: queryParams }
1910
+ );
1911
+ return fuelStationResponseSchema.parse(response);
1912
+ }
1913
+ };
1914
+
1915
+ // src/routes/research.ts
1916
+ var researchKeys = {
1917
+ all: ["research"],
1918
+ lineup: (make, params) => [...researchKeys.all, "lineup", make, params],
1919
+ byMake: (make) => [...researchKeys.all, "make", make],
1920
+ byId: (id) => [...researchKeys.all, "id", id],
1921
+ byListingId: (listingId) => [...researchKeys.all, "listing", listingId],
1922
+ byVin: (vin) => [...researchKeys.all, "vin", vin],
1923
+ byModel: (make, model) => [...researchKeys.all, "model", make, model],
1924
+ byYear: (make, year) => [...researchKeys.all, "year", make, year],
1925
+ byModelYear: (make, model, year) => [...researchKeys.all, "modelYear", make, model, year],
1926
+ images: (params) => [...researchKeys.all, "images", params],
1927
+ profileImages: (params) => [...researchKeys.all, "profileImages", params],
1928
+ colors: (params) => [...researchKeys.all, "colors", params]
1929
+ };
1930
+ var ResearchAPI = class extends BaseClient {
1931
+ async lineup(make, params) {
1932
+ const searchParams = new URLSearchParams();
1933
+ if (params?.page) searchParams.set("page", params.page.toString());
1934
+ if (params?.limit) searchParams.set("limit", params.limit.toString());
1935
+ if (params?.region) searchParams.set("region", params.region);
1936
+ if (params?.bodyStyle) searchParams.set("bodyStyle", params.bodyStyle);
1937
+ const query = searchParams.toString();
1938
+ const url = `/research/lineup/${make}${query ? `?${query}` : ""}`;
1939
+ const response = await this.get(url);
1940
+ return lineupResponseSchema.parse(response);
1941
+ }
1942
+ async byMake(make) {
1943
+ const response = await this.get(`/research/make/${make}`);
1944
+ return variantArrayResponseSchema.parse(response);
1945
+ }
1946
+ async byId(id) {
1947
+ const response = await this.get(`/research/id/${id}`);
1948
+ return variantResponseSchema.parse(response);
1949
+ }
1950
+ async byListingId(listingId) {
1951
+ const response = await this.get(`/research/listing/${listingId}`);
1952
+ return variantResponseSchema.parse(response);
1953
+ }
1954
+ async byVin(vin) {
1955
+ const response = await this.get(`/research/vin/${vin}`);
1956
+ return variantResponseSchema.parse(response);
1957
+ }
1958
+ async byModel(make, model) {
1959
+ const response = await this.get(
1960
+ `/research/make/${make}/model/${model}`
1961
+ );
1962
+ return variantArrayResponseSchema.parse(response);
1963
+ }
1964
+ async byYear(make, year) {
1965
+ const response = await this.get(
1966
+ `/research/make/${make}/year/${year}`
1967
+ );
1968
+ return variantArrayResponseSchema.parse(response);
1969
+ }
1970
+ async byModelYear(make, model, year) {
1971
+ const response = await this.get(
1972
+ `/research/make/${make}/model/${model}/year/${year}`
1973
+ );
1974
+ return variantArrayResponseSchema.parse(response);
1975
+ }
1976
+ async getImages(params) {
1977
+ const searchParams = new URLSearchParams({
1978
+ make: params.make,
1979
+ model: params.model,
1980
+ year: params.year.toString(),
1981
+ ...params.limit && { limit: params.limit.toString() },
1982
+ ...params.shotType && { shotType: params.shotType },
1983
+ ...params.category && { category: params.category }
1984
+ });
1985
+ const response = await this.get(
1986
+ `/research/images?${searchParams}`
1987
+ );
1988
+ return researchImageArraySchema.parse(response);
1989
+ }
1990
+ async getProfileImages(params) {
1991
+ const response = await this.get(
1992
+ `/research/images/profiles/${params.make}/${params.model}/${params.year}`
1993
+ );
1994
+ return researchImageArraySchema.parse(response);
1995
+ }
1996
+ async getColors(params) {
1997
+ const searchParams = new URLSearchParams({
1998
+ make: params.make,
1999
+ model: params.model,
2000
+ year: params.year.toString()
2001
+ });
2002
+ const response = await this.get(
2003
+ `/research/colors?${searchParams}`
2004
+ );
2005
+ return colorDataSchema.parse(response);
2006
+ }
2007
+ };
2008
+
2009
+ // src/routes/recalls.ts
2010
+ var recallKeys = {
2011
+ all: ["recalls"],
2012
+ search: (params) => [
2013
+ ...recallKeys.all,
2014
+ "search",
2015
+ params.country,
2016
+ params.makes,
2017
+ params.models,
2018
+ params.year
2019
+ ]
2020
+ };
2021
+ var RecallsAPI = class extends BaseClient {
2022
+ constructor() {
2023
+ super(...arguments);
2024
+ this.search = async (params) => {
2025
+ const response = await this.get(
2026
+ `/recalls/${params.country}/search`,
2027
+ {
2028
+ params: {
2029
+ yearMin: params.year?.min,
2030
+ yearMax: params.year?.max,
2031
+ makes: params.makes?.join(","),
2032
+ models: params.models?.join(","),
2033
+ limit: params.limit,
2034
+ offset: params.offset,
2035
+ sort: params.sort,
2036
+ order: params.order
2037
+ }
2038
+ }
2039
+ );
2040
+ return recallResponseSchema.parse(response);
2041
+ };
2042
+ }
2043
+ };
2044
+ var efficiencyResponseSchema = zod.z.object({
2045
+ success: zod.z.boolean(),
2046
+ data: zod.z.array(efficiencyDetailSchema),
2047
+ meta: zod.z.object({
2048
+ filter: zod.z.any().optional(),
2049
+ make: zod.z.string().optional(),
2050
+ model: zod.z.string().optional(),
2051
+ year: zod.z.number().optional(),
2052
+ trim: zod.z.string().optional(),
2053
+ count: zod.z.number(),
2054
+ fallback: zod.z.boolean().optional()
2055
+ })
2056
+ });
2057
+ var efficiencyStatsResponseSchema = zod.z.object({
2058
+ success: zod.z.boolean(),
2059
+ data: efficiencyStatsSchema
2060
+ });
2061
+ var efficiencyKeys = {
2062
+ all: ["efficiency"],
2063
+ search: (params) => [...efficiencyKeys.all, "search", params],
2064
+ byVehicle: (make, model, year) => [...efficiencyKeys.all, "vehicle", make, model, year],
2065
+ byVehicleTrim: (make, model, year, trim) => [...efficiencyKeys.all, "vehicle", make, model, year, trim],
2066
+ stats: () => [...efficiencyKeys.all, "stats"]
2067
+ };
2068
+ var EfficiencyAPI = class extends BaseClient {
2069
+ constructor() {
2070
+ super(...arguments);
2071
+ this.search = async (params) => {
2072
+ const response = await this.get("/efficiency/search", {
2073
+ params: {
2074
+ makes: params.makes?.join(","),
2075
+ models: params.models?.join(","),
2076
+ yearMin: params.year?.min,
2077
+ yearMax: params.year?.max,
2078
+ powertrainTypes: params.powertrainTypes?.join(","),
2079
+ fuelTypes: params.fuelTypes?.join(","),
2080
+ sources: params.sources?.join(","),
2081
+ testCycles: params.testCycles?.join(","),
2082
+ limit: params.limit,
2083
+ offset: params.offset,
2084
+ sort: params.sort,
2085
+ order: params.order
2086
+ }
2087
+ });
2088
+ return efficiencyResponseSchema.parse(response);
2089
+ };
2090
+ this.byVehicle = async (make, model, year) => {
2091
+ const response = await this.get(
2092
+ `/efficiency/${encodeURIComponent(make)}/${encodeURIComponent(model)}/${year}`
2093
+ );
2094
+ return efficiencyResponseSchema.parse(response);
2095
+ };
2096
+ this.byVehicleTrim = async (make, model, year, trim) => {
2097
+ const response = await this.get(
2098
+ `/efficiency/${encodeURIComponent(make)}/${encodeURIComponent(model)}/${year}/${encodeURIComponent(trim)}`
2099
+ );
2100
+ return efficiencyResponseSchema.parse(response);
2101
+ };
2102
+ this.stats = async () => {
2103
+ const response = await this.get("/efficiency/stats/overview");
2104
+ return efficiencyStatsResponseSchema.parse(response);
2105
+ };
2106
+ }
2107
+ };
2108
+ var complaintSchema = zod.z.object({
2109
+ complaintId: zod.z.number(),
2110
+ odiNumber: zod.z.string().nullable().optional(),
2111
+ manufacturerName: zod.z.string().nullable().optional(),
2112
+ make: zod.z.string(),
2113
+ model: zod.z.string(),
2114
+ year: zod.z.number(),
2115
+ vin: zod.z.string().nullable().optional(),
2116
+ crashInvolved: zod.z.boolean().nullable().optional(),
2117
+ incidentDate: zod.z.string().nullable().optional(),
2118
+ fireInvolved: zod.z.boolean().nullable().optional(),
2119
+ injuredCount: zod.z.number().nullable().optional(),
2120
+ deathsCount: zod.z.number().nullable().optional(),
2121
+ componentDescription: zod.z.string().nullable().optional(),
2122
+ consumerCity: zod.z.string().nullable().optional(),
2123
+ consumerState: zod.z.string().nullable().optional(),
2124
+ dateAdded: zod.z.string().nullable().optional(),
2125
+ dateReceived: zod.z.string().nullable().optional(),
2126
+ mileage: zod.z.number().nullable().optional(),
2127
+ occurrences: zod.z.number().nullable().optional(),
2128
+ complaintDescription: zod.z.string().nullable().optional(),
2129
+ complaintType: zod.z.string().nullable().optional(),
2130
+ policeReportFiled: zod.z.boolean().nullable().optional(),
2131
+ purchaseDate: zod.z.string().nullable().optional(),
2132
+ originalOwner: zod.z.boolean().nullable().optional(),
2133
+ productType: zod.z.string().nullable().optional(),
2134
+ repaired: zod.z.boolean().nullable().optional(),
2135
+ medicalAttention: zod.z.boolean().nullable().optional(),
2136
+ vehicleTowed: zod.z.boolean().nullable().optional(),
2137
+ processedAt: zod.z.string().nullable().optional(),
2138
+ provider: zod.z.string().nullable().optional()
2139
+ });
2140
+ var complaintsResponseSchema = zod.z.object({
2141
+ success: zod.z.boolean(),
2142
+ provider: zod.z.string(),
2143
+ data: zod.z.array(complaintSchema),
2144
+ meta: zod.z.object({
2145
+ filter: zod.z.any().optional(),
2146
+ count: zod.z.number()
2147
+ })
2148
+ });
2149
+ var complaintsKeys = {
2150
+ all: ["complaints"],
2151
+ search: (params) => [...complaintsKeys.all, "search", params]
2152
+ };
2153
+ var ComplaintsAPI = class extends BaseClient {
2154
+ constructor() {
2155
+ super(...arguments);
2156
+ this.search = async (params) => {
2157
+ const response = await this.get("/complaints/search", {
2158
+ params: {
2159
+ makes: params.makes?.join(","),
2160
+ models: params.models?.join(","),
2161
+ yearMin: params.year?.min,
2162
+ yearMax: params.year?.max,
2163
+ components: params.components?.join(","),
2164
+ limit: params.limit,
2165
+ offset: params.offset,
2166
+ sort: params.sort,
2167
+ order: params.order
2168
+ }
2169
+ });
2170
+ return complaintsResponseSchema.parse(response);
2171
+ };
2172
+ }
2173
+ };
2174
+
2175
+ // src/index.ts
2176
+ var queryKeys = {
2177
+ vin: vinKeys,
2178
+ market: marketKeys,
2179
+ listings: listingsKeys,
2180
+ locations: locationsKeys,
2181
+ charging: chargingKeys,
2182
+ fuel: fuelKeys,
2183
+ research: researchKeys,
2184
+ recalls: recallKeys,
2185
+ efficiency: efficiencyKeys,
2186
+ complaints: complaintsKeys
2187
+ };
2188
+ var CardogClient = class {
2189
+ constructor(config = {}) {
2190
+ this.vin = new VinAPI(config);
2191
+ this.market = new MarketAPI(config);
2192
+ this.listings = new ListingsAPI(config);
2193
+ this.locations = new LocationsAPI(config);
2194
+ this.fuel = new FuelAPI(config);
2195
+ this.charging = new ChargingAPI(config);
2196
+ this.research = new ResearchAPI(config);
2197
+ this.recalls = new RecallsAPI(config);
2198
+ this.efficiency = new EfficiencyAPI(config);
2199
+ this.complaints = new ComplaintsAPI(config);
2200
+ }
2201
+ setConfig(config) {
2202
+ this.vin.setConfig(config);
2203
+ this.market.setConfig(config);
2204
+ this.listings.setConfig(config);
2205
+ this.locations.setConfig(config);
2206
+ this.fuel.setConfig(config);
2207
+ this.charging.setConfig(config);
2208
+ this.research.setConfig(config);
2209
+ this.recalls.setConfig(config);
2210
+ this.efficiency.setConfig(config);
2211
+ this.complaints.setConfig(config);
2212
+ }
2213
+ };
2214
+ var index_default = CardogClient;
2215
+
2216
+ exports.APIError = APIError;
2217
+ exports.CardogClient = CardogClient;
2218
+ exports.ChargingAPI = ChargingAPI;
2219
+ exports.ComplaintsAPI = ComplaintsAPI;
2220
+ exports.EfficiencyAPI = EfficiencyAPI;
2221
+ exports.FuelAPI = FuelAPI;
2222
+ exports.FuelType = FuelType;
2223
+ exports.ListingsAPI = ListingsAPI;
2224
+ exports.LocationsAPI = LocationsAPI;
2225
+ exports.MarketAPI = MarketAPI;
2226
+ exports.RecallsAPI = RecallsAPI;
2227
+ exports.ResearchAPI = ResearchAPI;
2228
+ exports.VinAPI = VinAPI;
2229
+ exports.chargingKeys = chargingKeys;
2230
+ exports.complaintSchema = complaintSchema;
2231
+ exports.complaintsKeys = complaintsKeys;
2232
+ exports.complaintsResponseSchema = complaintsResponseSchema;
2233
+ exports.default = index_default;
2234
+ exports.efficiencyKeys = efficiencyKeys;
2235
+ exports.efficiencyResponseSchema = efficiencyResponseSchema;
2236
+ exports.efficiencyStatsResponseSchema = efficiencyStatsResponseSchema;
2237
+ exports.fuelKeys = fuelKeys;
2238
+ exports.listingSchema = listingSchema;
2239
+ exports.listingsKeys = listingsKeys;
2240
+ exports.locationsKeys = locationsKeys;
2241
+ exports.marketKeys = marketKeys;
2242
+ exports.queryKeys = queryKeys;
2243
+ exports.recallKeys = recallKeys;
2244
+ exports.researchKeys = researchKeys;
2245
+ exports.vinKeys = vinKeys;