@buun_group/gunspec-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -0
- package/dist/index.cjs +2342 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4554 -0
- package/dist/index.d.ts +4554 -0
- package/dist/index.js +2307 -0
- package/dist/index.js.map +1 -0
- package/package.json +67 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4554 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry logic with exponential backoff for the GunSpec SDK.
|
|
3
|
+
*
|
|
4
|
+
* Only **idempotent** HTTP methods (`GET`, `PUT`, `DELETE`) are retried
|
|
5
|
+
* automatically. Transient failures (timeouts, 429, 5xx) trigger a retry
|
|
6
|
+
* after an exponentially increasing delay with +-20 % jitter.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Configuration for the retry behaviour.
|
|
12
|
+
*
|
|
13
|
+
* All fields are optional and fall back to sensible defaults.
|
|
14
|
+
*/
|
|
15
|
+
interface RetryConfig {
|
|
16
|
+
/**
|
|
17
|
+
* Maximum number of retry attempts (excluding the initial request).
|
|
18
|
+
*
|
|
19
|
+
* Set to `0` to disable retries entirely.
|
|
20
|
+
*
|
|
21
|
+
* @defaultValue `2`
|
|
22
|
+
*/
|
|
23
|
+
maxRetries?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Initial delay in milliseconds before the first retry.
|
|
26
|
+
*
|
|
27
|
+
* @defaultValue `500`
|
|
28
|
+
*/
|
|
29
|
+
initialDelayMs?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Upper-bound delay in milliseconds. The computed delay is capped at this
|
|
32
|
+
* value regardless of how many retries have occurred.
|
|
33
|
+
*
|
|
34
|
+
* @defaultValue `8000`
|
|
35
|
+
*/
|
|
36
|
+
maxDelayMs?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Multiplier applied to the delay after each retry.
|
|
39
|
+
*
|
|
40
|
+
* @defaultValue `2`
|
|
41
|
+
*/
|
|
42
|
+
multiplier?: number;
|
|
43
|
+
}
|
|
44
|
+
/** Fully resolved retry configuration with all defaults applied. */
|
|
45
|
+
interface ResolvedRetryConfig {
|
|
46
|
+
readonly maxRetries: number;
|
|
47
|
+
readonly initialDelayMs: number;
|
|
48
|
+
readonly maxDelayMs: number;
|
|
49
|
+
readonly multiplier: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Authentication handler for the GunSpec SDK.
|
|
54
|
+
*
|
|
55
|
+
* Resolves an API key from an explicit option or the `GUNSPEC_API_KEY`
|
|
56
|
+
* environment variable, and produces the header map needed for every
|
|
57
|
+
* authenticated request.
|
|
58
|
+
*
|
|
59
|
+
* @module
|
|
60
|
+
*/
|
|
61
|
+
/**
|
|
62
|
+
* Options accepted by the authentication handler.
|
|
63
|
+
*/
|
|
64
|
+
interface AuthConfig {
|
|
65
|
+
/**
|
|
66
|
+
* An explicit API key to use for all requests.
|
|
67
|
+
*
|
|
68
|
+
* When omitted the handler falls back to the `GUNSPEC_API_KEY` environment
|
|
69
|
+
* variable (Node.js / Deno / Bun `process.env`). If neither is available
|
|
70
|
+
* the SDK operates in anonymous mode (no auth header is sent).
|
|
71
|
+
*/
|
|
72
|
+
apiKey?: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Resolve the API key to use for authentication.
|
|
76
|
+
*
|
|
77
|
+
* Resolution order:
|
|
78
|
+
* 1. Explicit `apiKey` option passed to the constructor.
|
|
79
|
+
* 2. `GUNSPEC_API_KEY` environment variable.
|
|
80
|
+
* 3. `undefined` (anonymous / unauthenticated).
|
|
81
|
+
*
|
|
82
|
+
* @param config - Authentication configuration.
|
|
83
|
+
* @returns The resolved API key, or `undefined` if none is available.
|
|
84
|
+
*/
|
|
85
|
+
declare function resolveApiKey(config: AuthConfig): string | undefined;
|
|
86
|
+
/**
|
|
87
|
+
* Build the authentication headers for a request.
|
|
88
|
+
*
|
|
89
|
+
* If an API key is available it is sent via the `X-API-Key` header.
|
|
90
|
+
* Returns an empty object when no key is available so the request proceeds
|
|
91
|
+
* in anonymous mode.
|
|
92
|
+
*
|
|
93
|
+
* @remarks
|
|
94
|
+
* The key value is **never** logged or serialised to avoid accidental
|
|
95
|
+
* credential leakage.
|
|
96
|
+
*
|
|
97
|
+
* @param apiKey - The resolved API key (may be `undefined`).
|
|
98
|
+
* @returns A header record to merge into the outgoing request.
|
|
99
|
+
*/
|
|
100
|
+
declare function buildAuthHeaders(apiKey: string | undefined): Record<string, string>;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* HTTP transport layer for the GunSpec SDK.
|
|
104
|
+
*
|
|
105
|
+
* Uses the native `fetch` API (available in Node 18+, Deno, Bun, Cloudflare
|
|
106
|
+
* Workers, and modern browsers) with zero external dependencies.
|
|
107
|
+
*
|
|
108
|
+
* @module
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Configuration accepted by the {@link HttpClient} constructor.
|
|
113
|
+
*/
|
|
114
|
+
interface HttpClientConfig {
|
|
115
|
+
/**
|
|
116
|
+
* Base URL for all API requests.
|
|
117
|
+
*
|
|
118
|
+
* Trailing slashes are stripped automatically.
|
|
119
|
+
*
|
|
120
|
+
* @defaultValue `"https://api.gunspec.io"`
|
|
121
|
+
*/
|
|
122
|
+
baseUrl?: string;
|
|
123
|
+
/**
|
|
124
|
+
* Default request timeout in milliseconds.
|
|
125
|
+
*
|
|
126
|
+
* Individual requests can override this via {@link RequestConfig.timeout}.
|
|
127
|
+
*
|
|
128
|
+
* @defaultValue `30_000` (30 seconds)
|
|
129
|
+
*/
|
|
130
|
+
timeout?: number;
|
|
131
|
+
/**
|
|
132
|
+
* Extra headers merged into every outgoing request.
|
|
133
|
+
*
|
|
134
|
+
* Useful for setting a custom `User-Agent` or forwarding correlation IDs.
|
|
135
|
+
*/
|
|
136
|
+
headers?: Record<string, string>;
|
|
137
|
+
/** Authentication options. */
|
|
138
|
+
auth?: AuthConfig;
|
|
139
|
+
/** Retry / backoff options. */
|
|
140
|
+
retry?: RetryConfig;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Describes a single HTTP request to be executed by the client.
|
|
144
|
+
*/
|
|
145
|
+
interface RequestConfig {
|
|
146
|
+
/** HTTP method. */
|
|
147
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
148
|
+
/**
|
|
149
|
+
* URL path **relative to the base URL**.
|
|
150
|
+
*
|
|
151
|
+
* Must start with `/` (e.g. `/v1/firearms`).
|
|
152
|
+
*/
|
|
153
|
+
path: string;
|
|
154
|
+
/**
|
|
155
|
+
* Query string parameters.
|
|
156
|
+
*
|
|
157
|
+
* - `undefined` values are silently omitted.
|
|
158
|
+
* - Arrays are serialised as repeated keys (`caliber=9mm&caliber=.45`).
|
|
159
|
+
* - Booleans are stringified (`"true"` / `"false"`).
|
|
160
|
+
*/
|
|
161
|
+
query?: Record<string, string | number | boolean | string[] | undefined>;
|
|
162
|
+
/** JSON request body (automatically stringified). */
|
|
163
|
+
body?: unknown;
|
|
164
|
+
/** Per-request header overrides. */
|
|
165
|
+
headers?: Record<string, string>;
|
|
166
|
+
/**
|
|
167
|
+
* Per-request timeout in milliseconds.
|
|
168
|
+
*
|
|
169
|
+
* Overrides the client-level default.
|
|
170
|
+
*/
|
|
171
|
+
timeout?: number;
|
|
172
|
+
/**
|
|
173
|
+
* An external `AbortSignal` that the caller can use to cancel the request.
|
|
174
|
+
*
|
|
175
|
+
* This signal is composed with the internal timeout signal so that either
|
|
176
|
+
* mechanism can abort the request.
|
|
177
|
+
*/
|
|
178
|
+
signal?: AbortSignal;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Unwrapped API response for endpoints that return a single resource.
|
|
182
|
+
*
|
|
183
|
+
* The SDK strips the `{ success, data }` envelope and hoists `data` to the
|
|
184
|
+
* top level.
|
|
185
|
+
*/
|
|
186
|
+
interface APIResponse<T> {
|
|
187
|
+
/** The unwrapped response payload. */
|
|
188
|
+
readonly data: T;
|
|
189
|
+
/** HTTP status code. */
|
|
190
|
+
readonly status: number;
|
|
191
|
+
/** Raw response headers. */
|
|
192
|
+
readonly headers: Headers;
|
|
193
|
+
/** The `X-Request-Id` response header. */
|
|
194
|
+
readonly requestId: string;
|
|
195
|
+
/** Parsed rate limit headers. */
|
|
196
|
+
readonly rateLimit: RateLimitInfo;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Unwrapped API response for endpoints that return a paginated list.
|
|
200
|
+
*/
|
|
201
|
+
interface PaginatedResponse<T> {
|
|
202
|
+
/** Array of resource objects. */
|
|
203
|
+
readonly data: T[];
|
|
204
|
+
/** Pagination metadata returned by the server. */
|
|
205
|
+
readonly pagination: PaginationMeta;
|
|
206
|
+
/** HTTP status code. */
|
|
207
|
+
readonly status: number;
|
|
208
|
+
/** Raw response headers. */
|
|
209
|
+
readonly headers: Headers;
|
|
210
|
+
/** The `X-Request-Id` response header. */
|
|
211
|
+
readonly requestId: string;
|
|
212
|
+
/** Parsed rate limit headers. */
|
|
213
|
+
readonly rateLimit: RateLimitInfo;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Pagination metadata included in list responses.
|
|
217
|
+
*/
|
|
218
|
+
interface PaginationMeta {
|
|
219
|
+
/** Current page number (1-indexed). */
|
|
220
|
+
readonly page: number;
|
|
221
|
+
/** Maximum number of items per page. */
|
|
222
|
+
readonly limit: number;
|
|
223
|
+
/** Total number of matching items (omitted for anonymous/free tiers). */
|
|
224
|
+
readonly total?: number;
|
|
225
|
+
/** Total number of pages (omitted when `total` is omitted). */
|
|
226
|
+
readonly totalPages?: number;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Rate limit information parsed from response headers.
|
|
230
|
+
*/
|
|
231
|
+
interface RateLimitInfo {
|
|
232
|
+
/** Maximum requests allowed per window, or `null` if the header is absent. */
|
|
233
|
+
readonly limit: number | null;
|
|
234
|
+
/** Requests remaining in the current window, or `null`. */
|
|
235
|
+
readonly remaining: number | null;
|
|
236
|
+
/** Unix timestamp (seconds) when the window resets, or `null`. */
|
|
237
|
+
readonly reset: number | null;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Low-level HTTP client for the GunSpec API.
|
|
241
|
+
*
|
|
242
|
+
* Handles URL construction, query string serialisation, authentication
|
|
243
|
+
* headers, timeout management, response envelope unwrapping, error mapping,
|
|
244
|
+
* and automatic retries with exponential backoff.
|
|
245
|
+
*
|
|
246
|
+
* Most consumers should use the high-level `GunSpec` client class instead,
|
|
247
|
+
* which delegates to an `HttpClient` instance internally.
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```ts
|
|
251
|
+
* const http = new HttpClient({ auth: { apiKey: process.env.GUNSPEC_API_KEY } });
|
|
252
|
+
* const res = await http.request<Firearm>({
|
|
253
|
+
* method: 'GET',
|
|
254
|
+
* path: '/v1/firearms/glock-g17',
|
|
255
|
+
* });
|
|
256
|
+
* console.log(res.data.name); // "Glock G17"
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
declare class HttpClient {
|
|
260
|
+
private readonly baseUrl;
|
|
261
|
+
private readonly defaultTimeout;
|
|
262
|
+
private readonly defaultHeaders;
|
|
263
|
+
private readonly apiKey;
|
|
264
|
+
private readonly retryConfig;
|
|
265
|
+
constructor(config?: HttpClientConfig);
|
|
266
|
+
/**
|
|
267
|
+
* Execute an HTTP request and return the unwrapped response.
|
|
268
|
+
*
|
|
269
|
+
* The API's `{ success: true, data: T }` envelope is stripped so that
|
|
270
|
+
* callers receive `T` directly via {@link APIResponse.data}.
|
|
271
|
+
*
|
|
272
|
+
* @typeParam T - The expected type of the `data` field in the response.
|
|
273
|
+
* @param config - Request configuration.
|
|
274
|
+
* @returns The unwrapped API response.
|
|
275
|
+
* @throws {@link APIError} on non-2xx responses.
|
|
276
|
+
* @throws {@link ConnectionError} on network failures.
|
|
277
|
+
* @throws {@link TimeoutError} when the request exceeds the timeout.
|
|
278
|
+
*/
|
|
279
|
+
request<T>(config: RequestConfig): Promise<APIResponse<T>>;
|
|
280
|
+
/**
|
|
281
|
+
* Execute an HTTP request and return a paginated response.
|
|
282
|
+
*
|
|
283
|
+
* The API's `{ success: true, data: T[], pagination }` envelope is
|
|
284
|
+
* unwrapped into a {@link PaginatedResponse}.
|
|
285
|
+
*
|
|
286
|
+
* @typeParam T - The element type of the paginated list.
|
|
287
|
+
* @param config - Request configuration.
|
|
288
|
+
* @returns The unwrapped paginated response.
|
|
289
|
+
* @throws {@link APIError} on non-2xx responses.
|
|
290
|
+
* @throws {@link ConnectionError} on network failures.
|
|
291
|
+
* @throws {@link TimeoutError} when the request exceeds the timeout.
|
|
292
|
+
*/
|
|
293
|
+
requestPaginated<T>(config: RequestConfig): Promise<PaginatedResponse<T>>;
|
|
294
|
+
/**
|
|
295
|
+
* Convenience wrapper for a GET request returning a single resource.
|
|
296
|
+
*/
|
|
297
|
+
get<T>(path: string, query?: Record<string, any>): Promise<APIResponse<T>>;
|
|
298
|
+
/**
|
|
299
|
+
* Convenience wrapper for a GET request returning a paginated list.
|
|
300
|
+
*/
|
|
301
|
+
getPaginated<T>(path: string, query?: Record<string, any>): Promise<PaginatedResponse<T>>;
|
|
302
|
+
/**
|
|
303
|
+
* Convenience wrapper for a POST request.
|
|
304
|
+
*/
|
|
305
|
+
post<T>(path: string, body?: unknown, query?: Record<string, any>): Promise<APIResponse<T>>;
|
|
306
|
+
/**
|
|
307
|
+
* Convenience wrapper for a PUT request.
|
|
308
|
+
*/
|
|
309
|
+
put<T>(path: string, body?: unknown, query?: Record<string, any>): Promise<APIResponse<T>>;
|
|
310
|
+
/**
|
|
311
|
+
* Convenience wrapper for a DELETE request.
|
|
312
|
+
*/
|
|
313
|
+
delete<T>(path: string, query?: Record<string, any>): Promise<APIResponse<T>>;
|
|
314
|
+
private executeRequest;
|
|
315
|
+
private executePaginatedRequest;
|
|
316
|
+
/**
|
|
317
|
+
* Perform the raw `fetch` call with merged headers, query string, timeout,
|
|
318
|
+
* and body serialisation.
|
|
319
|
+
*/
|
|
320
|
+
private doFetch;
|
|
321
|
+
/**
|
|
322
|
+
* Build the full URL from base URL, path, and query parameters.
|
|
323
|
+
*/
|
|
324
|
+
private buildUrl;
|
|
325
|
+
/**
|
|
326
|
+
* Parse an error response body and throw the appropriate {@link APIError}.
|
|
327
|
+
*/
|
|
328
|
+
private throwAPIError;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Pagination utilities for the GunSpec SDK.
|
|
333
|
+
*
|
|
334
|
+
* Provides a {@link Page} wrapper around paginated API responses with
|
|
335
|
+
* convenience methods for navigating between pages and an async iterator
|
|
336
|
+
* for automatic consumption of all pages.
|
|
337
|
+
*
|
|
338
|
+
* @module
|
|
339
|
+
*/
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* A function that fetches a specific page of results.
|
|
343
|
+
*
|
|
344
|
+
* Used internally by {@link Page} to implement {@link Page.getNextPage} and
|
|
345
|
+
* the async iterator without exposing the full `HttpClient` to consumers.
|
|
346
|
+
*
|
|
347
|
+
* @typeParam T - The element type of the paginated list.
|
|
348
|
+
*/
|
|
349
|
+
type PageFetcher<T> = (query: Record<string, string | number | boolean | string[] | undefined>) => Promise<PaginatedResponse<T>>;
|
|
350
|
+
/**
|
|
351
|
+
* A single page of results from a paginated API endpoint.
|
|
352
|
+
*
|
|
353
|
+
* Wraps the raw {@link PaginatedResponse} and adds navigation helpers:
|
|
354
|
+
*
|
|
355
|
+
* - {@link hasNextPage} — check if more pages are available.
|
|
356
|
+
* - {@link getNextPage} — fetch the next page.
|
|
357
|
+
* - `Symbol.asyncIterator` — iterate over **all** items across all pages.
|
|
358
|
+
*
|
|
359
|
+
* @typeParam T - The type of each item in the page.
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```ts
|
|
363
|
+
* const page = await client.firearms.list({ page: 1, limit: 25 });
|
|
364
|
+
*
|
|
365
|
+
* // Manual navigation
|
|
366
|
+
* console.log(page.data); // Firearm[]
|
|
367
|
+
* console.log(page.pagination); // { page: 1, limit: 25, total: 400, totalPages: 16 }
|
|
368
|
+
*
|
|
369
|
+
* if (page.hasNextPage()) {
|
|
370
|
+
* const next = await page.getNextPage();
|
|
371
|
+
* }
|
|
372
|
+
*
|
|
373
|
+
* // Automatic iteration over all items
|
|
374
|
+
* for await (const firearm of page) {
|
|
375
|
+
* console.log(firearm.name);
|
|
376
|
+
* }
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
declare class Page<T> {
|
|
380
|
+
/** The items on this page. */
|
|
381
|
+
readonly data: T[];
|
|
382
|
+
/** Pagination metadata returned by the server. */
|
|
383
|
+
readonly pagination: PaginationMeta;
|
|
384
|
+
/** The request ID for this page's HTTP response. */
|
|
385
|
+
readonly requestId: string;
|
|
386
|
+
/** The base query parameters used to fetch this page (without `page`). */
|
|
387
|
+
private readonly baseQuery;
|
|
388
|
+
/** The fetcher function used to retrieve subsequent pages. */
|
|
389
|
+
private readonly fetcher;
|
|
390
|
+
/**
|
|
391
|
+
* @internal
|
|
392
|
+
* Consumers should not construct `Page` instances directly. Use the
|
|
393
|
+
* resource methods on the high-level client instead.
|
|
394
|
+
*/
|
|
395
|
+
constructor(response: PaginatedResponse<T>, baseQuery: Record<string, string | number | boolean | string[] | undefined>, fetcher: PageFetcher<T>);
|
|
396
|
+
/**
|
|
397
|
+
* Whether there is a next page of results.
|
|
398
|
+
*
|
|
399
|
+
* When `totalPages` is available (pro/enterprise tiers) the check is exact.
|
|
400
|
+
* Otherwise the heuristic is: if the current page returned a full page of
|
|
401
|
+
* results (i.e. `data.length === limit`), there is likely another page.
|
|
402
|
+
*/
|
|
403
|
+
hasNextPage(): boolean;
|
|
404
|
+
/**
|
|
405
|
+
* Fetch the next page of results.
|
|
406
|
+
*
|
|
407
|
+
* @returns A new {@link Page} instance for the next page.
|
|
408
|
+
* @throws {Error} If there is no next page. Always check
|
|
409
|
+
* {@link hasNextPage} first.
|
|
410
|
+
*/
|
|
411
|
+
getNextPage(): Promise<Page<T>>;
|
|
412
|
+
/**
|
|
413
|
+
* Fetch the previous page of results.
|
|
414
|
+
*
|
|
415
|
+
* @returns A new {@link Page} instance for the previous page.
|
|
416
|
+
* @throws {Error} If this is already the first page.
|
|
417
|
+
*/
|
|
418
|
+
getPreviousPage(): Promise<Page<T>>;
|
|
419
|
+
/**
|
|
420
|
+
* Async iterator that yields every item across **all** pages, starting
|
|
421
|
+
* from the current page.
|
|
422
|
+
*
|
|
423
|
+
* Fetches subsequent pages on demand (lazily) so memory usage stays
|
|
424
|
+
* constant regardless of the total result set size.
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* ```ts
|
|
428
|
+
* const firstPage = await client.firearms.list({ limit: 50 });
|
|
429
|
+
* for await (const firearm of firstPage) {
|
|
430
|
+
* // Iterates page 1, then auto-fetches page 2, 3, ... until exhausted.
|
|
431
|
+
* console.log(firearm.name);
|
|
432
|
+
* }
|
|
433
|
+
* ```
|
|
434
|
+
*/
|
|
435
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<T>;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Create a {@link Page} from a raw paginated HTTP response.
|
|
439
|
+
*
|
|
440
|
+
* This is the primary factory used by resource classes to wrap their list
|
|
441
|
+
* endpoints.
|
|
442
|
+
*
|
|
443
|
+
* @typeParam T - The element type.
|
|
444
|
+
* @param response - The raw paginated response from {@link HttpClient.requestPaginated}.
|
|
445
|
+
* @param baseQuery - The query parameters used for the request (the `page`
|
|
446
|
+
* key is managed automatically).
|
|
447
|
+
* @param fetcher - A function that fetches a specific page given query
|
|
448
|
+
* parameters.
|
|
449
|
+
* @returns A new {@link Page} instance.
|
|
450
|
+
*/
|
|
451
|
+
declare function createPage<T>(response: PaginatedResponse<T>, baseQuery: Record<string, string | number | boolean | string[] | undefined>, fetcher: PageFetcher<T>): Page<T>;
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Error hierarchy for the GunSpec SDK.
|
|
455
|
+
*
|
|
456
|
+
* All SDK errors extend {@link GunSpecError} so consumers can catch them
|
|
457
|
+
* uniformly with a single `catch (e) { if (e instanceof GunSpecError) … }`.
|
|
458
|
+
*
|
|
459
|
+
* HTTP errors returned by the API are mapped to specific subclasses of
|
|
460
|
+
* {@link APIError} via the {@link createAPIError} factory function.
|
|
461
|
+
*
|
|
462
|
+
* @module
|
|
463
|
+
*/
|
|
464
|
+
/**
|
|
465
|
+
* Base error class for every error thrown by the GunSpec SDK.
|
|
466
|
+
*
|
|
467
|
+
* @remarks
|
|
468
|
+
* Restores the prototype chain so `instanceof` checks work correctly even
|
|
469
|
+
* when transpiled to ES5.
|
|
470
|
+
*/
|
|
471
|
+
declare class GunSpecError extends Error {
|
|
472
|
+
readonly name: string;
|
|
473
|
+
constructor(message: string);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* An error returned by the GunSpec API with an HTTP status code.
|
|
477
|
+
*
|
|
478
|
+
* Subclasses are created for well-known status codes (401, 403, 404, …).
|
|
479
|
+
* For any other status code the base `APIError` is thrown directly.
|
|
480
|
+
*/
|
|
481
|
+
declare class APIError extends GunSpecError {
|
|
482
|
+
readonly name: string;
|
|
483
|
+
/** HTTP status code returned by the API. */
|
|
484
|
+
readonly status: number;
|
|
485
|
+
/** Machine-readable error code from the response body (e.g. `"NOT_FOUND"`). */
|
|
486
|
+
readonly code: string;
|
|
487
|
+
/** The `X-Request-Id` header value, useful for support requests. */
|
|
488
|
+
readonly requestId: string;
|
|
489
|
+
/** Raw response headers for further inspection. */
|
|
490
|
+
readonly headers: Headers;
|
|
491
|
+
constructor(status: number, code: string, message: string, requestId: string, headers: Headers);
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Thrown when the API returns **401 Unauthorized**.
|
|
495
|
+
*
|
|
496
|
+
* Usually means the API key is missing, invalid, or expired.
|
|
497
|
+
*/
|
|
498
|
+
declare class AuthenticationError extends APIError {
|
|
499
|
+
readonly name: string;
|
|
500
|
+
constructor(code: string, message: string, requestId: string, headers: Headers);
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Thrown when the API returns **403 Forbidden**.
|
|
504
|
+
*
|
|
505
|
+
* The API key is valid but the associated tier does not have access to the
|
|
506
|
+
* requested resource or action.
|
|
507
|
+
*/
|
|
508
|
+
declare class PermissionError extends APIError {
|
|
509
|
+
readonly name: string;
|
|
510
|
+
constructor(code: string, message: string, requestId: string, headers: Headers);
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Thrown when the API returns **404 Not Found**.
|
|
514
|
+
*/
|
|
515
|
+
declare class NotFoundError extends APIError {
|
|
516
|
+
readonly name: string;
|
|
517
|
+
constructor(code: string, message: string, requestId: string, headers: Headers);
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Thrown when the API returns **400 Bad Request**.
|
|
521
|
+
*
|
|
522
|
+
* Typically caused by invalid query parameters or a malformed request body.
|
|
523
|
+
*/
|
|
524
|
+
declare class BadRequestError extends APIError {
|
|
525
|
+
readonly name: string;
|
|
526
|
+
constructor(code: string, message: string, requestId: string, headers: Headers);
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Thrown when the API returns **429 Too Many Requests**.
|
|
530
|
+
*
|
|
531
|
+
* The {@link retryAfter} property contains the number of seconds to wait
|
|
532
|
+
* before retrying, parsed from the `Retry-After` response header.
|
|
533
|
+
*/
|
|
534
|
+
declare class RateLimitError extends APIError {
|
|
535
|
+
readonly name: string;
|
|
536
|
+
/**
|
|
537
|
+
* Number of seconds the client should wait before retrying, or `null` if
|
|
538
|
+
* the server did not provide a `Retry-After` header.
|
|
539
|
+
*/
|
|
540
|
+
readonly retryAfter: number | null;
|
|
541
|
+
constructor(code: string, message: string, requestId: string, headers: Headers, retryAfter: number | null);
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Thrown when the API returns **500 Internal Server Error**.
|
|
545
|
+
*/
|
|
546
|
+
declare class InternalServerError extends APIError {
|
|
547
|
+
readonly name: string;
|
|
548
|
+
constructor(code: string, message: string, requestId: string, headers: Headers);
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Thrown when a network-level failure prevents the request from completing.
|
|
552
|
+
*
|
|
553
|
+
* This covers DNS resolution errors, connection resets, and any other
|
|
554
|
+
* `TypeError` thrown by the native `fetch` implementation.
|
|
555
|
+
*/
|
|
556
|
+
declare class ConnectionError extends GunSpecError {
|
|
557
|
+
readonly name: string;
|
|
558
|
+
/** The original error thrown by `fetch`. */
|
|
559
|
+
readonly cause: unknown;
|
|
560
|
+
constructor(message: string, cause: unknown);
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Thrown when a request exceeds the configured timeout.
|
|
564
|
+
*
|
|
565
|
+
* The timeout is implemented via `AbortController` and fires when the
|
|
566
|
+
* elapsed time exceeds `HttpClientConfig.timeout`.
|
|
567
|
+
*/
|
|
568
|
+
declare class TimeoutError extends GunSpecError {
|
|
569
|
+
readonly name: string;
|
|
570
|
+
/** The timeout duration in milliseconds that was exceeded. */
|
|
571
|
+
readonly timeoutMs: number;
|
|
572
|
+
constructor(timeoutMs: number);
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Error envelope returned by the GunSpec API on non-2xx responses.
|
|
576
|
+
*/
|
|
577
|
+
interface ErrorBody$1 {
|
|
578
|
+
success: false;
|
|
579
|
+
error: {
|
|
580
|
+
code: string;
|
|
581
|
+
message: string;
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Create the appropriate {@link APIError} subclass for the given HTTP status
|
|
586
|
+
* code and response body.
|
|
587
|
+
*
|
|
588
|
+
* @param status - HTTP status code.
|
|
589
|
+
* @param body - Parsed JSON body (may be `null` if the body was empty or
|
|
590
|
+
* unparseable).
|
|
591
|
+
* @param requestId - Value of the `X-Request-Id` response header.
|
|
592
|
+
* @param headers - Raw response headers.
|
|
593
|
+
* @returns A concrete {@link APIError} subclass instance.
|
|
594
|
+
*/
|
|
595
|
+
declare function createAPIError(status: number, body: ErrorBody$1 | null, requestId: string, headers: Headers): APIError;
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* A firearm specification record.
|
|
599
|
+
*
|
|
600
|
+
* The full detail shape is returned by `GET /v1/firearms/:id`.
|
|
601
|
+
* List endpoints return a subset of these fields.
|
|
602
|
+
*
|
|
603
|
+
* @example
|
|
604
|
+
* ```ts
|
|
605
|
+
* const glock: Firearm = {
|
|
606
|
+
* id: 'glock-g17',
|
|
607
|
+
* name: 'Glock G17',
|
|
608
|
+
* manufacturerId: 'glock',
|
|
609
|
+
* categoryId: 'semi-automatic-pistol',
|
|
610
|
+
* status: 'in_production',
|
|
611
|
+
* yearIntroduced: 1982,
|
|
612
|
+
* countryOfOrigin: 'AT',
|
|
613
|
+
* actionType: 'short_recoil',
|
|
614
|
+
* };
|
|
615
|
+
* ```
|
|
616
|
+
*/
|
|
617
|
+
interface Firearm {
|
|
618
|
+
/** URL-safe slug identifier (e.g. `"glock-g17"`). */
|
|
619
|
+
readonly id: string;
|
|
620
|
+
/** Display name of the firearm. */
|
|
621
|
+
name: string;
|
|
622
|
+
/** Slug of the manufacturer (FK to {@link Manufacturer.id}). */
|
|
623
|
+
manufacturerId: string;
|
|
624
|
+
/** Slug of the category (FK to {@link Category.id}). */
|
|
625
|
+
categoryId: string;
|
|
626
|
+
/** Slug of the parent firearm when this is a variant. */
|
|
627
|
+
parentFirearmId?: string | null;
|
|
628
|
+
/** Free-text label describing the variant relationship (e.g. `"compact"`, `"tactical"`). */
|
|
629
|
+
variantType?: string | null;
|
|
630
|
+
/** Year the firearm was first produced. */
|
|
631
|
+
yearIntroduced?: number | null;
|
|
632
|
+
/** Year production ended, if applicable. */
|
|
633
|
+
yearDiscontinued?: number | null;
|
|
634
|
+
/** Current production status. */
|
|
635
|
+
status?: 'in_production' | 'discontinued' | 'prototype' | null;
|
|
636
|
+
/** ISO 3166-1 alpha-2 country code of origin (e.g. `"US"`, `"AT"`). */
|
|
637
|
+
countryOfOrigin?: string | null;
|
|
638
|
+
/** Empty weight in grams. */
|
|
639
|
+
weightEmptyG?: number | null;
|
|
640
|
+
/** Loaded weight in grams. */
|
|
641
|
+
weightLoadedG?: number | null;
|
|
642
|
+
/** Overall length in millimetres. */
|
|
643
|
+
overallLengthMm?: number | null;
|
|
644
|
+
/** Barrel length in millimetres. */
|
|
645
|
+
barrelLengthMm?: number | null;
|
|
646
|
+
/** Height in millimetres. */
|
|
647
|
+
heightMm?: number | null;
|
|
648
|
+
/** Width in millimetres. */
|
|
649
|
+
widthMm?: number | null;
|
|
650
|
+
/** Sight radius in millimetres. */
|
|
651
|
+
sightRadiusMm?: number | null;
|
|
652
|
+
/** Folded/collapsed length in millimetres, if applicable. */
|
|
653
|
+
foldedLengthMm?: number | null;
|
|
654
|
+
/** Action type slug (e.g. `"short_recoil"`, `"gas_operated"`). */
|
|
655
|
+
actionType?: string | null;
|
|
656
|
+
/** Firing mechanism description. */
|
|
657
|
+
firingMechanism?: string | null;
|
|
658
|
+
/** Trigger type (e.g. `"single_action"`, `"double_action"`). */
|
|
659
|
+
triggerType?: string | null;
|
|
660
|
+
/** Trigger pull force in newtons. */
|
|
661
|
+
triggerPullN?: number | null;
|
|
662
|
+
/** Standard magazine capacity in rounds. */
|
|
663
|
+
magazineCapacity?: number | null;
|
|
664
|
+
/** Magazine type description. */
|
|
665
|
+
magazineType?: string | null;
|
|
666
|
+
/** Muzzle velocity in metres per second. */
|
|
667
|
+
muzzleVelocityMps?: number | null;
|
|
668
|
+
/** Muzzle energy in joules. */
|
|
669
|
+
muzzleEnergyJ?: number | null;
|
|
670
|
+
/** Effective range in metres. */
|
|
671
|
+
effectiveRangeM?: number | null;
|
|
672
|
+
/** Maximum range in metres. */
|
|
673
|
+
maxRangeM?: number | null;
|
|
674
|
+
/** Cyclic rate of fire in rounds per minute. */
|
|
675
|
+
rateOfFireRpm?: number | null;
|
|
676
|
+
/** Barrel rifling description (e.g. `"polygonal"`, `"conventional"`). */
|
|
677
|
+
barrelRifling?: string | null;
|
|
678
|
+
/** Rifling twist rate in millimetres per revolution. */
|
|
679
|
+
riflingTwistMm?: number | null;
|
|
680
|
+
/** Number of rifling grooves. */
|
|
681
|
+
numberOfGrooves?: number | null;
|
|
682
|
+
/** Frame/receiver material. */
|
|
683
|
+
frameMaterial?: string | null;
|
|
684
|
+
/** Slide material. */
|
|
685
|
+
slideMaterial?: string | null;
|
|
686
|
+
/** Barrel material. */
|
|
687
|
+
barrelMaterial?: string | null;
|
|
688
|
+
/** Stock material. */
|
|
689
|
+
stockMaterial?: string | null;
|
|
690
|
+
/** Surface finish description. */
|
|
691
|
+
finish?: string | null;
|
|
692
|
+
/** Safety mechanism descriptions. */
|
|
693
|
+
safetyMechanisms?: string | null;
|
|
694
|
+
/** Notable features. */
|
|
695
|
+
features?: string | null;
|
|
696
|
+
/** Feed system descriptions. */
|
|
697
|
+
feedSystems?: string | null;
|
|
698
|
+
/** Alternative names / designations. */
|
|
699
|
+
alternateNames?: string | null;
|
|
700
|
+
/** Available firing modes (e.g. `["semi-automatic","full-automatic"]`). */
|
|
701
|
+
firingModes?: string | null;
|
|
702
|
+
/** Conflicts this firearm was used in (JSON array of objects). */
|
|
703
|
+
conflicts?: string | null;
|
|
704
|
+
/** Production numbers (JSON object). */
|
|
705
|
+
productionNumbers?: string | null;
|
|
706
|
+
/** Sources / references (JSON array). */
|
|
707
|
+
sources?: string | null;
|
|
708
|
+
/** Game damage rating (0-100). */
|
|
709
|
+
gameDamage?: number | null;
|
|
710
|
+
/** Game accuracy rating (0-100). */
|
|
711
|
+
gameAccuracy?: number | null;
|
|
712
|
+
/** Game range rating (0-100). */
|
|
713
|
+
gameRange?: number | null;
|
|
714
|
+
/** Game fire rate rating (0-100). */
|
|
715
|
+
gameFireRate?: number | null;
|
|
716
|
+
/** Game mobility rating (0-100). */
|
|
717
|
+
gameMobility?: number | null;
|
|
718
|
+
/** Game recoil control rating (0-100). */
|
|
719
|
+
gameRecoilControl?: number | null;
|
|
720
|
+
/** Game reload speed rating (0-100). */
|
|
721
|
+
gameReloadSpeed?: number | null;
|
|
722
|
+
/** Game concealment rating (0-100). */
|
|
723
|
+
gameConcealment?: number | null;
|
|
724
|
+
/** Long-form description / history. */
|
|
725
|
+
description?: string | null;
|
|
726
|
+
/** Editorial notes. */
|
|
727
|
+
notes?: string | null;
|
|
728
|
+
/** Firearm designer(s). */
|
|
729
|
+
designer?: string | null;
|
|
730
|
+
/** Historical lore / trivia text. */
|
|
731
|
+
lore?: string | null;
|
|
732
|
+
/** Source-reported muzzle velocity in m/s. */
|
|
733
|
+
sourceMuzzleVelocityMps?: number | null;
|
|
734
|
+
/** Source-reported muzzle energy in joules. */
|
|
735
|
+
sourceMuzzleEnergyJ?: number | null;
|
|
736
|
+
/** Source-reported effective range in metres. */
|
|
737
|
+
sourceEffectiveRangeM?: number | null;
|
|
738
|
+
/** Source-reported maximum range in metres. */
|
|
739
|
+
sourceMaxRangeM?: number | null;
|
|
740
|
+
/** Ballistics data source name. */
|
|
741
|
+
ballisticsSource?: string | null;
|
|
742
|
+
/** URL for ballistics data source. */
|
|
743
|
+
ballisticsSourceUrl?: string | null;
|
|
744
|
+
/** Default ammunition load slug. */
|
|
745
|
+
defaultAmmoId?: string | null;
|
|
746
|
+
/** Whether a 3-D model is available (`0` or `1`). */
|
|
747
|
+
has3dModel?: number | null;
|
|
748
|
+
/** URL to the SVG line-art silhouette. */
|
|
749
|
+
svgLineArtUrl?: string | null;
|
|
750
|
+
/** URL to the 3-D model asset (glTF / GLB). */
|
|
751
|
+
model3dUrl?: string | null;
|
|
752
|
+
/** Confidence score for the data (0.0 - 1.0). */
|
|
753
|
+
dataConfidence?: number | null;
|
|
754
|
+
/** ISO-8601 creation timestamp. */
|
|
755
|
+
readonly createdAt: string;
|
|
756
|
+
/** ISO-8601 last-update timestamp. */
|
|
757
|
+
readonly updatedAt: string;
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Full firearm detail including related entities.
|
|
761
|
+
*
|
|
762
|
+
* Returned by `GET /v1/firearms/:id`.
|
|
763
|
+
*/
|
|
764
|
+
interface FirearmDetail extends Firearm {
|
|
765
|
+
/** The manufacturer record. */
|
|
766
|
+
manufacturer: Manufacturer | null;
|
|
767
|
+
/** The category record. */
|
|
768
|
+
category: Category | null;
|
|
769
|
+
/** Calibers this firearm chambers. */
|
|
770
|
+
calibers: FirearmCaliberEntry[];
|
|
771
|
+
/** Associated images. */
|
|
772
|
+
images: FirearmImage[];
|
|
773
|
+
/** Known military / law-enforcement users. */
|
|
774
|
+
users: FirearmUser[];
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* A caliber entry on a firearm detail, joined from the junction table.
|
|
778
|
+
*/
|
|
779
|
+
interface FirearmCaliberEntry {
|
|
780
|
+
/** Caliber slug. */
|
|
781
|
+
caliberId: string;
|
|
782
|
+
/** Whether this is the primary chambering (`1`) or alternate (`0`). */
|
|
783
|
+
isPrimary: number;
|
|
784
|
+
/** Caliber display name. */
|
|
785
|
+
name: string;
|
|
786
|
+
/** NATO designation, if any. */
|
|
787
|
+
natoDesignation?: string | null;
|
|
788
|
+
/** Bullet diameter in mm. */
|
|
789
|
+
bulletDiameterMm?: number | null;
|
|
790
|
+
/** Case length in mm. */
|
|
791
|
+
caseLengthMm?: number | null;
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* A firearms manufacturer.
|
|
795
|
+
*
|
|
796
|
+
* @example
|
|
797
|
+
* ```ts
|
|
798
|
+
* const glock: Manufacturer = {
|
|
799
|
+
* id: 'glock',
|
|
800
|
+
* name: 'Glock',
|
|
801
|
+
* countryCode: 'AT',
|
|
802
|
+
* foundedYear: 1963,
|
|
803
|
+
* createdAt: '2024-01-01T00:00:00',
|
|
804
|
+
* updatedAt: '2024-01-01T00:00:00',
|
|
805
|
+
* };
|
|
806
|
+
* ```
|
|
807
|
+
*/
|
|
808
|
+
interface Manufacturer {
|
|
809
|
+
/** URL-safe slug identifier. */
|
|
810
|
+
readonly id: string;
|
|
811
|
+
/** Display name. */
|
|
812
|
+
name: string;
|
|
813
|
+
/** ISO 3166-1 alpha-2 country code. */
|
|
814
|
+
countryCode?: string | null;
|
|
815
|
+
/** Year the company was founded. */
|
|
816
|
+
foundedYear?: number | null;
|
|
817
|
+
/** Company website URL. */
|
|
818
|
+
website?: string | null;
|
|
819
|
+
/** URL to the company logo. */
|
|
820
|
+
logoUrl?: string | null;
|
|
821
|
+
/** Long-form description. */
|
|
822
|
+
description?: string | null;
|
|
823
|
+
/** ISO-8601 creation timestamp. */
|
|
824
|
+
readonly createdAt: string;
|
|
825
|
+
/** ISO-8601 last-update timestamp. */
|
|
826
|
+
readonly updatedAt: string;
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Per-manufacturer aggregate statistics.
|
|
830
|
+
*
|
|
831
|
+
* Returned by `GET /v1/manufacturers/:id/stats`.
|
|
832
|
+
*/
|
|
833
|
+
interface ManufacturerStats {
|
|
834
|
+
/** The manufacturer summary. */
|
|
835
|
+
manufacturer: {
|
|
836
|
+
id: string;
|
|
837
|
+
name: string;
|
|
838
|
+
};
|
|
839
|
+
/** Aggregate statistics. */
|
|
840
|
+
stats: {
|
|
841
|
+
total_firearms: number;
|
|
842
|
+
avg_weight_g: number | null;
|
|
843
|
+
avg_range_m: number | null;
|
|
844
|
+
avg_capacity: number | null;
|
|
845
|
+
active_count: number;
|
|
846
|
+
discontinued_count: number;
|
|
847
|
+
earliest_year: number | null;
|
|
848
|
+
latest_year: number | null;
|
|
849
|
+
} | null;
|
|
850
|
+
/** Breakdown by category. */
|
|
851
|
+
categories: Array<{
|
|
852
|
+
id: string;
|
|
853
|
+
name: string;
|
|
854
|
+
count: number;
|
|
855
|
+
}>;
|
|
856
|
+
/** The most common caliber among this manufacturer's firearms. */
|
|
857
|
+
mostCommonCaliber: {
|
|
858
|
+
id: string;
|
|
859
|
+
name: string;
|
|
860
|
+
count: number;
|
|
861
|
+
} | null;
|
|
862
|
+
}
|
|
863
|
+
/**
|
|
864
|
+
* Manufacturer timeline grouping firearms by year introduced.
|
|
865
|
+
*
|
|
866
|
+
* Returned by `GET /v1/manufacturers/:id/timeline`.
|
|
867
|
+
*/
|
|
868
|
+
interface ManufacturerTimeline {
|
|
869
|
+
/** The manufacturer summary. */
|
|
870
|
+
manufacturer: {
|
|
871
|
+
id: string;
|
|
872
|
+
name: string;
|
|
873
|
+
};
|
|
874
|
+
/** Firearms grouped by year. */
|
|
875
|
+
timeline: Array<{
|
|
876
|
+
year: number | null;
|
|
877
|
+
firearms: Array<{
|
|
878
|
+
id: string;
|
|
879
|
+
name: string;
|
|
880
|
+
yearIntroduced: number | null;
|
|
881
|
+
categoryId: string;
|
|
882
|
+
status: string | null;
|
|
883
|
+
}>;
|
|
884
|
+
}>;
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* A cartridge / caliber specification.
|
|
888
|
+
*
|
|
889
|
+
* @example
|
|
890
|
+
* ```ts
|
|
891
|
+
* const nato556: Caliber = {
|
|
892
|
+
* id: '5-56x45mm-nato',
|
|
893
|
+
* name: '5.56x45mm NATO',
|
|
894
|
+
* cartridgeType: 'centerfire_rifle',
|
|
895
|
+
* bulletDiameterMm: 5.70,
|
|
896
|
+
* createdAt: '2024-01-01T00:00:00',
|
|
897
|
+
* updatedAt: '2024-01-01T00:00:00',
|
|
898
|
+
* };
|
|
899
|
+
* ```
|
|
900
|
+
*/
|
|
901
|
+
interface Caliber {
|
|
902
|
+
/** URL-safe slug identifier. */
|
|
903
|
+
readonly id: string;
|
|
904
|
+
/** Display name. */
|
|
905
|
+
name: string;
|
|
906
|
+
/** JSON array of alternative names (stored as text). */
|
|
907
|
+
aliases?: string | null;
|
|
908
|
+
/** NATO designation (e.g. `"5.56x45mm NATO"`). */
|
|
909
|
+
natoDesignation?: string | null;
|
|
910
|
+
/** Bullet diameter in millimetres. */
|
|
911
|
+
bulletDiameterMm?: number | null;
|
|
912
|
+
/** Neck diameter in millimetres. */
|
|
913
|
+
neckDiameterMm?: number | null;
|
|
914
|
+
/** Base diameter in millimetres. */
|
|
915
|
+
baseDiameterMm?: number | null;
|
|
916
|
+
/** Case length in millimetres. */
|
|
917
|
+
caseLengthMm?: number | null;
|
|
918
|
+
/** Overall cartridge length in millimetres. */
|
|
919
|
+
overallLengthMm?: number | null;
|
|
920
|
+
/** Maximum chamber pressure in megapascals. */
|
|
921
|
+
maxPressureMpa?: number | null;
|
|
922
|
+
/** Maximum chamber pressure in PSI. */
|
|
923
|
+
maxPressurePsi?: number | null;
|
|
924
|
+
/** Typical bullet weight in grams. */
|
|
925
|
+
typicalBulletWeightG?: number | null;
|
|
926
|
+
/** Typical muzzle velocity in m/s. */
|
|
927
|
+
typicalMuzzleVelocityMps?: number | null;
|
|
928
|
+
/** Typical muzzle energy in joules. */
|
|
929
|
+
typicalMuzzleEnergyJ?: number | null;
|
|
930
|
+
/** Primer type (e.g. `"Boxer"`, `"Berdan"`). */
|
|
931
|
+
primerType?: string | null;
|
|
932
|
+
/** Cartridge type (e.g. `"centerfire_rifle"`, `"rimfire"`). */
|
|
933
|
+
cartridgeType?: string | null;
|
|
934
|
+
/** Slug of the parent cartridge, if this is a derivative. */
|
|
935
|
+
parentCartridgeId?: string | null;
|
|
936
|
+
/** Year the cartridge was introduced. */
|
|
937
|
+
yearIntroduced?: number | null;
|
|
938
|
+
/** Cartridge designer. */
|
|
939
|
+
designer?: string | null;
|
|
940
|
+
/** ISO-8601 creation timestamp. */
|
|
941
|
+
readonly createdAt: string;
|
|
942
|
+
/** ISO-8601 last-update timestamp. */
|
|
943
|
+
readonly updatedAt: string;
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* A specific ammunition load for a caliber.
|
|
947
|
+
*
|
|
948
|
+
* @example
|
|
949
|
+
* ```ts
|
|
950
|
+
* const m855: Ammunition = {
|
|
951
|
+
* id: 'm855-62gr-fmj',
|
|
952
|
+
* caliberId: '5-56x45mm-nato',
|
|
953
|
+
* name: 'M855 62gr FMJ',
|
|
954
|
+
* bulletWeightG: 4.02,
|
|
955
|
+
* bulletType: 'FMJ',
|
|
956
|
+
* referenceVelocityMps: 940,
|
|
957
|
+
* referenceBarrelLengthMm: 508,
|
|
958
|
+
* isCommon: 1,
|
|
959
|
+
* createdAt: '2024-01-01T00:00:00',
|
|
960
|
+
* updatedAt: '2024-01-01T00:00:00',
|
|
961
|
+
* };
|
|
962
|
+
* ```
|
|
963
|
+
*/
|
|
964
|
+
interface Ammunition {
|
|
965
|
+
/** URL-safe slug identifier. */
|
|
966
|
+
readonly id: string;
|
|
967
|
+
/** Caliber slug (FK to {@link Caliber.id}). */
|
|
968
|
+
caliberId: string;
|
|
969
|
+
/** Display name. */
|
|
970
|
+
name: string;
|
|
971
|
+
/** Military / NATO designation. */
|
|
972
|
+
designation?: string | null;
|
|
973
|
+
/** Ammunition manufacturer name. */
|
|
974
|
+
manufacturer?: string | null;
|
|
975
|
+
/** Country of origin ISO code. */
|
|
976
|
+
countryOfOrigin?: string | null;
|
|
977
|
+
/** Bullet weight in grams. */
|
|
978
|
+
bulletWeightG: number;
|
|
979
|
+
/** Bullet construction type (e.g. `"FMJ"`, `"JHP"`, `"AP"`). */
|
|
980
|
+
bulletType: string;
|
|
981
|
+
/** G1 ballistic coefficient (imperial). */
|
|
982
|
+
ballisticCoefficientG1?: number | null;
|
|
983
|
+
/** G7 ballistic coefficient (imperial). */
|
|
984
|
+
ballisticCoefficientG7?: number | null;
|
|
985
|
+
/** Reference muzzle velocity in m/s (measured from the reference barrel). */
|
|
986
|
+
referenceVelocityMps: number;
|
|
987
|
+
/** Barrel length in mm at which the reference velocity was measured. */
|
|
988
|
+
referenceBarrelLengthMm: number;
|
|
989
|
+
/** Exponent for velocity-vs-barrel-length power-law model. */
|
|
990
|
+
velocityRetentionExponent?: number | null;
|
|
991
|
+
/** Sectional density (lb/in^2). */
|
|
992
|
+
sectionalDensity?: number | null;
|
|
993
|
+
/** Long-form description. */
|
|
994
|
+
description?: string | null;
|
|
995
|
+
/** Year the load was introduced. */
|
|
996
|
+
yearIntroduced?: number | null;
|
|
997
|
+
/** Whether this is a common / widely-available load (`0` or `1`). */
|
|
998
|
+
isCommon: number;
|
|
999
|
+
/** Whether this is a military load (`0` or `1`). */
|
|
1000
|
+
isMilitary: number;
|
|
1001
|
+
/** ISO-8601 creation timestamp. */
|
|
1002
|
+
readonly createdAt: string;
|
|
1003
|
+
/** ISO-8601 last-update timestamp. */
|
|
1004
|
+
readonly updatedAt: string;
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* A single point along a ballistic trajectory.
|
|
1008
|
+
*
|
|
1009
|
+
* Computed by the ammunition ballistics engine.
|
|
1010
|
+
*/
|
|
1011
|
+
interface TrajectoryPoint {
|
|
1012
|
+
/** Distance from the muzzle in metres. */
|
|
1013
|
+
distanceM: number;
|
|
1014
|
+
/** Velocity at this distance in m/s. */
|
|
1015
|
+
velocityMps: number;
|
|
1016
|
+
/** Kinetic energy at this distance in joules. */
|
|
1017
|
+
energyJ: number;
|
|
1018
|
+
/** Bullet drop at this distance in centimetres. */
|
|
1019
|
+
dropCm: number;
|
|
1020
|
+
/** Time of flight to this distance in seconds. */
|
|
1021
|
+
timeOfFlightS: number;
|
|
1022
|
+
/** Mach number at this distance. */
|
|
1023
|
+
machNumber: number;
|
|
1024
|
+
/** Momentum at this distance in kg*m/s. */
|
|
1025
|
+
momentumKgMs: number;
|
|
1026
|
+
/** Taylor Knock-Out factor at this distance. */
|
|
1027
|
+
tkoFactor: number;
|
|
1028
|
+
/** Energy density at this distance in J/cm^2. */
|
|
1029
|
+
energyDensityJCm2: number;
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Muzzle-level terminal ballistics summary.
|
|
1033
|
+
*/
|
|
1034
|
+
interface TerminalBallistics {
|
|
1035
|
+
/** Taylor Knock-Out factor. */
|
|
1036
|
+
tkoFactor: number;
|
|
1037
|
+
/** Momentum in kg*m/s. */
|
|
1038
|
+
momentumKgMs: number;
|
|
1039
|
+
/** Sectional density (lb/in^2). */
|
|
1040
|
+
sectionalDensity: number;
|
|
1041
|
+
/** Hatcher Relative Stopping Power. */
|
|
1042
|
+
hatcherRSP: number;
|
|
1043
|
+
/** Energy density in J/cm^2. */
|
|
1044
|
+
energyDensityJCm2: number;
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Full ballistic profile for an ammunition load.
|
|
1048
|
+
*
|
|
1049
|
+
* Returned by `GET /v1/ammunition/:id/ballistics`.
|
|
1050
|
+
*/
|
|
1051
|
+
interface BallisticProfile {
|
|
1052
|
+
/** Ammunition summary. */
|
|
1053
|
+
ammunition: {
|
|
1054
|
+
id: string;
|
|
1055
|
+
name: string;
|
|
1056
|
+
caliberId: string;
|
|
1057
|
+
};
|
|
1058
|
+
/** Barrel length used for calculations in mm. */
|
|
1059
|
+
barrelLengthMm: number;
|
|
1060
|
+
/** Calculated muzzle velocity in m/s. */
|
|
1061
|
+
muzzleVelocityMps: number;
|
|
1062
|
+
/** Calculated muzzle energy in joules. */
|
|
1063
|
+
muzzleEnergyJ: number;
|
|
1064
|
+
/** Calculated effective range in metres. */
|
|
1065
|
+
effectiveRangeM: number;
|
|
1066
|
+
/** Terminal ballistics at the muzzle. */
|
|
1067
|
+
terminalBallistics: TerminalBallistics;
|
|
1068
|
+
/** Trajectory drop table at specified distances. */
|
|
1069
|
+
trajectory: TrajectoryPoint[];
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Firearm ballistic calculation result.
|
|
1073
|
+
*
|
|
1074
|
+
* Returned by `GET /v1/firearms/:id/calculate`.
|
|
1075
|
+
*/
|
|
1076
|
+
interface FirearmCalculation {
|
|
1077
|
+
/** Firearm summary. */
|
|
1078
|
+
firearm: {
|
|
1079
|
+
id: string;
|
|
1080
|
+
name: string;
|
|
1081
|
+
barrelLengthMm?: number | null;
|
|
1082
|
+
};
|
|
1083
|
+
/** Ammunition summary (absent when barrel length is unavailable). */
|
|
1084
|
+
ammunition?: {
|
|
1085
|
+
id: string;
|
|
1086
|
+
name: string;
|
|
1087
|
+
};
|
|
1088
|
+
/** Calculated values. */
|
|
1089
|
+
calculated?: {
|
|
1090
|
+
muzzleVelocityMps: number;
|
|
1091
|
+
muzzleEnergyJ: number;
|
|
1092
|
+
terminalBallistics: TerminalBallistics;
|
|
1093
|
+
};
|
|
1094
|
+
/** Source-reported values from the firearm record. */
|
|
1095
|
+
sourceReported?: {
|
|
1096
|
+
muzzleVelocityMps: number | null;
|
|
1097
|
+
muzzleEnergyJ: number | null;
|
|
1098
|
+
};
|
|
1099
|
+
/** Delta between calculated and source-reported values. */
|
|
1100
|
+
delta?: {
|
|
1101
|
+
velocityMps: number | null;
|
|
1102
|
+
energyJ: number | null;
|
|
1103
|
+
};
|
|
1104
|
+
/** Error message when calculation cannot be performed. */
|
|
1105
|
+
error?: string;
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* Firearm load profile including full trajectory.
|
|
1109
|
+
*
|
|
1110
|
+
* Returned by `GET /v1/firearms/:id/load`.
|
|
1111
|
+
*/
|
|
1112
|
+
interface FirearmLoadProfile {
|
|
1113
|
+
/** Firearm summary. */
|
|
1114
|
+
firearm: {
|
|
1115
|
+
id: string;
|
|
1116
|
+
name: string;
|
|
1117
|
+
barrelLengthMm?: number | null;
|
|
1118
|
+
};
|
|
1119
|
+
/** Ammunition details (absent on error). */
|
|
1120
|
+
ammunition?: {
|
|
1121
|
+
id: string;
|
|
1122
|
+
name: string;
|
|
1123
|
+
caliberId: string;
|
|
1124
|
+
bulletWeightG: number;
|
|
1125
|
+
bulletType: string;
|
|
1126
|
+
};
|
|
1127
|
+
/** Calculated ballistic values. */
|
|
1128
|
+
calculated?: {
|
|
1129
|
+
muzzleVelocityMps: number;
|
|
1130
|
+
muzzleEnergyJ: number;
|
|
1131
|
+
effectiveRangeM: number;
|
|
1132
|
+
terminalBallistics: TerminalBallistics;
|
|
1133
|
+
};
|
|
1134
|
+
/** Source-reported values from the firearm record. */
|
|
1135
|
+
sourceReported?: {
|
|
1136
|
+
muzzleVelocityMps: number | null;
|
|
1137
|
+
muzzleEnergyJ: number | null;
|
|
1138
|
+
effectiveRangeM: number | null;
|
|
1139
|
+
};
|
|
1140
|
+
/** Trajectory drop table. */
|
|
1141
|
+
trajectory?: TrajectoryPoint[];
|
|
1142
|
+
/** Error message when calculation cannot be performed. */
|
|
1143
|
+
error?: string;
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* A firearm category (e.g. "semi-automatic-pistol", "bolt-action-rifle").
|
|
1147
|
+
*/
|
|
1148
|
+
interface Category {
|
|
1149
|
+
/** URL-safe slug identifier. */
|
|
1150
|
+
readonly id: string;
|
|
1151
|
+
/** Display name. */
|
|
1152
|
+
name: string;
|
|
1153
|
+
/** Long-form description. */
|
|
1154
|
+
description?: string | null;
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* An image associated with a firearm.
|
|
1158
|
+
*/
|
|
1159
|
+
interface FirearmImage {
|
|
1160
|
+
/** Auto-increment integer ID. */
|
|
1161
|
+
readonly id: number;
|
|
1162
|
+
/** Firearm slug (FK to {@link Firearm.id}). */
|
|
1163
|
+
firearmId: string;
|
|
1164
|
+
/** Image URL. */
|
|
1165
|
+
url: string;
|
|
1166
|
+
/** Image type (e.g. `"gallery"`). */
|
|
1167
|
+
type?: string | null;
|
|
1168
|
+
/** Image source attribution. */
|
|
1169
|
+
source?: string | null;
|
|
1170
|
+
/** Image license. */
|
|
1171
|
+
license?: string | null;
|
|
1172
|
+
}
|
|
1173
|
+
/**
|
|
1174
|
+
* A military, law-enforcement, or other institutional user of a firearm.
|
|
1175
|
+
*/
|
|
1176
|
+
interface FirearmUser {
|
|
1177
|
+
/** Auto-increment integer ID. */
|
|
1178
|
+
readonly id: number;
|
|
1179
|
+
/** Firearm slug (FK to {@link Firearm.id}). */
|
|
1180
|
+
firearmId: string;
|
|
1181
|
+
/** User / organisation name (e.g. `"U.S. Army"`). */
|
|
1182
|
+
userName: string;
|
|
1183
|
+
/** User type (e.g. `"military"`, `"law_enforcement"`). */
|
|
1184
|
+
userType?: string | null;
|
|
1185
|
+
/** ISO 3166-1 alpha-2 country code. */
|
|
1186
|
+
countryCode?: string | null;
|
|
1187
|
+
/** Year the firearm was adopted. */
|
|
1188
|
+
adoptedYear?: number | null;
|
|
1189
|
+
/** Service designation (e.g. `"M9"`, `"P226"`). */
|
|
1190
|
+
designation?: string | null;
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Extracted game statistics for a firearm (0-100 scale per stat).
|
|
1194
|
+
*
|
|
1195
|
+
* Used in game-related endpoints.
|
|
1196
|
+
*/
|
|
1197
|
+
interface GameStats {
|
|
1198
|
+
/** Damage rating (0-100). */
|
|
1199
|
+
damage: number | null;
|
|
1200
|
+
/** Accuracy rating (0-100). */
|
|
1201
|
+
accuracy: number | null;
|
|
1202
|
+
/** Range rating (0-100). */
|
|
1203
|
+
range: number | null;
|
|
1204
|
+
/** Fire rate rating (0-100). */
|
|
1205
|
+
fireRate: number | null;
|
|
1206
|
+
/** Mobility rating (0-100). */
|
|
1207
|
+
mobility: number | null;
|
|
1208
|
+
/** Recoil control rating (0-100). */
|
|
1209
|
+
recoilControl: number | null;
|
|
1210
|
+
/** Reload speed rating (0-100). */
|
|
1211
|
+
reloadSpeed: number | null;
|
|
1212
|
+
/** Concealment rating (0-100). */
|
|
1213
|
+
concealment: number | null;
|
|
1214
|
+
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Firearm game profile including archetype classification.
|
|
1217
|
+
*
|
|
1218
|
+
* Returned by `GET /v1/firearms/:id/game/profile`.
|
|
1219
|
+
*/
|
|
1220
|
+
interface GameProfile {
|
|
1221
|
+
/** Firearm slug. */
|
|
1222
|
+
id: string;
|
|
1223
|
+
/** Firearm name. */
|
|
1224
|
+
name: string;
|
|
1225
|
+
/** Damage rating (0-100). */
|
|
1226
|
+
gameDamage: number | null;
|
|
1227
|
+
/** Accuracy rating (0-100). */
|
|
1228
|
+
gameAccuracy: number | null;
|
|
1229
|
+
/** Range rating (0-100). */
|
|
1230
|
+
gameRange: number | null;
|
|
1231
|
+
/** Fire rate rating (0-100). */
|
|
1232
|
+
gameFireRate: number | null;
|
|
1233
|
+
/** Mobility rating (0-100). */
|
|
1234
|
+
gameMobility: number | null;
|
|
1235
|
+
/** Recoil control rating (0-100). */
|
|
1236
|
+
gameRecoilControl: number | null;
|
|
1237
|
+
/** Reload speed rating (0-100). */
|
|
1238
|
+
gameReloadSpeed: number | null;
|
|
1239
|
+
/** Concealment rating (0-100). */
|
|
1240
|
+
gameConcealment: number | null;
|
|
1241
|
+
/** Computed archetype classification. */
|
|
1242
|
+
archetype: string;
|
|
1243
|
+
/** List of stat-based strengths. */
|
|
1244
|
+
strengths: string[];
|
|
1245
|
+
/** List of stat-based weaknesses. */
|
|
1246
|
+
weaknesses: string[];
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* A firearm in the game meta listing.
|
|
1250
|
+
*
|
|
1251
|
+
* Returned by `GET /v1/firearms/:id/game/meta`.
|
|
1252
|
+
*/
|
|
1253
|
+
interface GameMetaItem {
|
|
1254
|
+
/** Firearm slug. */
|
|
1255
|
+
id: string;
|
|
1256
|
+
/** Firearm name. */
|
|
1257
|
+
name: string;
|
|
1258
|
+
/** Computed archetype. */
|
|
1259
|
+
archetype: string;
|
|
1260
|
+
gameDamage: number | null;
|
|
1261
|
+
gameAccuracy: number | null;
|
|
1262
|
+
gameRange: number | null;
|
|
1263
|
+
gameFireRate: number | null;
|
|
1264
|
+
gameMobility: number | null;
|
|
1265
|
+
gameRecoilControl: number | null;
|
|
1266
|
+
gameReloadSpeed: number | null;
|
|
1267
|
+
gameConcealment: number | null;
|
|
1268
|
+
}
|
|
1269
|
+
/**
|
|
1270
|
+
* Balance report entry flagging statistical outliers.
|
|
1271
|
+
*
|
|
1272
|
+
* Returned by `GET /v1/game/balance`.
|
|
1273
|
+
*/
|
|
1274
|
+
interface BalanceEntry {
|
|
1275
|
+
/** Firearm slug. */
|
|
1276
|
+
firearmId: string;
|
|
1277
|
+
/** Firearm name. */
|
|
1278
|
+
firearmName: string;
|
|
1279
|
+
/** Stat deviations that exceeded the threshold. */
|
|
1280
|
+
deviations: BalanceDeviation[];
|
|
1281
|
+
}
|
|
1282
|
+
/**
|
|
1283
|
+
* A single stat deviation in a balance report.
|
|
1284
|
+
*/
|
|
1285
|
+
interface BalanceDeviation {
|
|
1286
|
+
/** Stat key (e.g. `"damage"`, `"accuracy"`). */
|
|
1287
|
+
stat: string;
|
|
1288
|
+
/** The firearm's value for this stat. */
|
|
1289
|
+
value: number;
|
|
1290
|
+
/** Population mean for this stat. */
|
|
1291
|
+
mean: number;
|
|
1292
|
+
/** Population standard deviation for this stat. */
|
|
1293
|
+
stdDev: number;
|
|
1294
|
+
/** Z-score (how many std devs from the mean). */
|
|
1295
|
+
zScore: number;
|
|
1296
|
+
}
|
|
1297
|
+
/**
|
|
1298
|
+
* Tier list grouping for a single game stat.
|
|
1299
|
+
*
|
|
1300
|
+
* Returned by `GET /v1/game/tier-list`.
|
|
1301
|
+
*/
|
|
1302
|
+
interface TierList {
|
|
1303
|
+
/** The stat used for ranking. */
|
|
1304
|
+
stat: string;
|
|
1305
|
+
/** Firearms grouped into S/A/B/C/D tiers. */
|
|
1306
|
+
tiers: {
|
|
1307
|
+
S: TierItem[];
|
|
1308
|
+
A: TierItem[];
|
|
1309
|
+
B: TierItem[];
|
|
1310
|
+
C: TierItem[];
|
|
1311
|
+
D: TierItem[];
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
/**
|
|
1315
|
+
* An item within a tier.
|
|
1316
|
+
*/
|
|
1317
|
+
interface TierItem {
|
|
1318
|
+
/** Firearm slug. */
|
|
1319
|
+
id: string;
|
|
1320
|
+
/** Firearm name. */
|
|
1321
|
+
name: string;
|
|
1322
|
+
/** Category slug. */
|
|
1323
|
+
categoryId: string | null;
|
|
1324
|
+
/** Stat value. */
|
|
1325
|
+
value: number;
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Game matchup result comparing two firearms' game stats.
|
|
1329
|
+
*
|
|
1330
|
+
* Returned by `GET /v1/game/matchups`.
|
|
1331
|
+
*/
|
|
1332
|
+
interface MatchupResult {
|
|
1333
|
+
/** Firearm A summary with stats. */
|
|
1334
|
+
a: {
|
|
1335
|
+
id: string;
|
|
1336
|
+
name: string;
|
|
1337
|
+
stats: GameStats;
|
|
1338
|
+
};
|
|
1339
|
+
/** Firearm B summary with stats. */
|
|
1340
|
+
b: {
|
|
1341
|
+
id: string;
|
|
1342
|
+
name: string;
|
|
1343
|
+
stats: GameStats;
|
|
1344
|
+
};
|
|
1345
|
+
/** Per-stat verdict: which firearm wins each category. */
|
|
1346
|
+
verdicts: Record<string, 'a' | 'b' | 'draw'>;
|
|
1347
|
+
/** Number of stats won by A. */
|
|
1348
|
+
aWins: number;
|
|
1349
|
+
/** Number of stats won by B. */
|
|
1350
|
+
bWins: number;
|
|
1351
|
+
/** Number of drawn stats. */
|
|
1352
|
+
draws: number;
|
|
1353
|
+
}
|
|
1354
|
+
/**
|
|
1355
|
+
* A firearm in a role roster.
|
|
1356
|
+
*
|
|
1357
|
+
* Returned by `GET /v1/game/role-roster`.
|
|
1358
|
+
*/
|
|
1359
|
+
interface RoleRosterItem {
|
|
1360
|
+
/** Firearm slug. */
|
|
1361
|
+
id: string;
|
|
1362
|
+
/** Firearm name. */
|
|
1363
|
+
name: string;
|
|
1364
|
+
/** Weighted score for the requested role. */
|
|
1365
|
+
roleScore: number;
|
|
1366
|
+
/** Full game stats. */
|
|
1367
|
+
stats: GameStats;
|
|
1368
|
+
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Stat distribution / histogram for a single game stat.
|
|
1371
|
+
*
|
|
1372
|
+
* Returned by `GET /v1/game/stat-distribution`.
|
|
1373
|
+
*/
|
|
1374
|
+
interface StatDistribution {
|
|
1375
|
+
/** The stat analysed. */
|
|
1376
|
+
stat: string;
|
|
1377
|
+
/** Number of firearms with this stat. */
|
|
1378
|
+
count: number;
|
|
1379
|
+
/** Arithmetic mean. */
|
|
1380
|
+
mean: number;
|
|
1381
|
+
/** Median value. */
|
|
1382
|
+
median: number;
|
|
1383
|
+
/** Standard deviation. */
|
|
1384
|
+
stdDev: number;
|
|
1385
|
+
/** Minimum value. */
|
|
1386
|
+
min: number;
|
|
1387
|
+
/** Maximum value. */
|
|
1388
|
+
max: number;
|
|
1389
|
+
/** Key percentiles. */
|
|
1390
|
+
percentiles: {
|
|
1391
|
+
p10: number;
|
|
1392
|
+
p25: number;
|
|
1393
|
+
p50: number;
|
|
1394
|
+
p75: number;
|
|
1395
|
+
p90: number;
|
|
1396
|
+
};
|
|
1397
|
+
/** 10-bucket histogram (0-10, 10-20, ..., 90-100). */
|
|
1398
|
+
histogram: Array<{
|
|
1399
|
+
bucket: string;
|
|
1400
|
+
count: number;
|
|
1401
|
+
}>;
|
|
1402
|
+
}
|
|
1403
|
+
/**
|
|
1404
|
+
* A versioned snapshot of game stats for all firearms.
|
|
1405
|
+
*
|
|
1406
|
+
* Returned by `GET /v1/game-stats/versions`.
|
|
1407
|
+
*/
|
|
1408
|
+
interface GameStatsVersion {
|
|
1409
|
+
/** Auto-increment ID. */
|
|
1410
|
+
readonly id: number;
|
|
1411
|
+
/** Version identifier (e.g. `"1.0.0"`). */
|
|
1412
|
+
version: string;
|
|
1413
|
+
/** Description of the snapshot. */
|
|
1414
|
+
description?: string | null;
|
|
1415
|
+
/** Number of firearms in this snapshot. */
|
|
1416
|
+
firearmCount: number;
|
|
1417
|
+
/** ISO-8601 creation timestamp. */
|
|
1418
|
+
readonly createdAt: string;
|
|
1419
|
+
}
|
|
1420
|
+
/**
|
|
1421
|
+
* A single entry in a game-stats snapshot.
|
|
1422
|
+
*/
|
|
1423
|
+
interface GameStatsSnapshotEntry {
|
|
1424
|
+
/** Auto-increment ID. */
|
|
1425
|
+
readonly id: number;
|
|
1426
|
+
/** Snapshot ID. */
|
|
1427
|
+
snapshotId: number;
|
|
1428
|
+
/** Firearm slug. */
|
|
1429
|
+
firearmId: string;
|
|
1430
|
+
/** Firearm name at time of snapshot. */
|
|
1431
|
+
firearmName: string;
|
|
1432
|
+
gameDamage: number | null;
|
|
1433
|
+
gameAccuracy: number | null;
|
|
1434
|
+
gameRange: number | null;
|
|
1435
|
+
gameFireRate: number | null;
|
|
1436
|
+
gameMobility: number | null;
|
|
1437
|
+
gameRecoilControl: number | null;
|
|
1438
|
+
gameReloadSpeed: number | null;
|
|
1439
|
+
gameConcealment: number | null;
|
|
1440
|
+
}
|
|
1441
|
+
/**
|
|
1442
|
+
* Comparison result for multiple firearms.
|
|
1443
|
+
*
|
|
1444
|
+
* Returned by `GET /v1/firearms/compare`.
|
|
1445
|
+
*/
|
|
1446
|
+
interface FirearmComparison {
|
|
1447
|
+
/** Full detail records for each compared firearm. */
|
|
1448
|
+
items: FirearmDetail[];
|
|
1449
|
+
/** Per-field deltas between the compared firearms. */
|
|
1450
|
+
deltas: Record<string, unknown>;
|
|
1451
|
+
}
|
|
1452
|
+
/**
|
|
1453
|
+
* Head-to-head comparison of two firearms on numeric specs.
|
|
1454
|
+
*
|
|
1455
|
+
* Returned by `GET /v1/firearms/head-to-head`.
|
|
1456
|
+
*/
|
|
1457
|
+
interface HeadToHead {
|
|
1458
|
+
/** Firearm A raw data (snake_case keys from D1). */
|
|
1459
|
+
a: Record<string, unknown>;
|
|
1460
|
+
/** Firearm B raw data (snake_case keys from D1). */
|
|
1461
|
+
b: Record<string, unknown>;
|
|
1462
|
+
/** Per-field verdicts indicating which firearm is superior. */
|
|
1463
|
+
verdicts: Record<string, {
|
|
1464
|
+
/** Which firearm wins for this field. */
|
|
1465
|
+
winner: 'a' | 'b' | 'draw';
|
|
1466
|
+
/** Value for firearm A. */
|
|
1467
|
+
a: number | null;
|
|
1468
|
+
/** Value for firearm B. */
|
|
1469
|
+
b: number | null;
|
|
1470
|
+
/** Human-readable description of why the winner is better. */
|
|
1471
|
+
better: string;
|
|
1472
|
+
}>;
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* Firearm family tree (ancestors + current + descendants).
|
|
1476
|
+
*
|
|
1477
|
+
* Returned by `GET /v1/firearms/:id/family`.
|
|
1478
|
+
*/
|
|
1479
|
+
interface FamilyTree {
|
|
1480
|
+
/** Ancestor firearms (oldest first). */
|
|
1481
|
+
ancestors: Record<string, unknown>[];
|
|
1482
|
+
/** The requested firearm (full record). */
|
|
1483
|
+
current: Firearm;
|
|
1484
|
+
/** Descendant / variant firearms. */
|
|
1485
|
+
descendants: Record<string, unknown>[];
|
|
1486
|
+
}
|
|
1487
|
+
/**
|
|
1488
|
+
* A similar firearm with a computed similarity score.
|
|
1489
|
+
*
|
|
1490
|
+
* Returned by `GET /v1/firearms/:id/similar`.
|
|
1491
|
+
*/
|
|
1492
|
+
interface SimilarFirearm {
|
|
1493
|
+
/** Firearm slug. */
|
|
1494
|
+
id: string;
|
|
1495
|
+
/** Firearm name. */
|
|
1496
|
+
name: string;
|
|
1497
|
+
/** Similarity score (higher is more similar). */
|
|
1498
|
+
score: number;
|
|
1499
|
+
}
|
|
1500
|
+
/**
|
|
1501
|
+
* Adoption map for a firearm, grouped by country.
|
|
1502
|
+
*
|
|
1503
|
+
* Returned by `GET /v1/firearms/:id/adoption`.
|
|
1504
|
+
*/
|
|
1505
|
+
interface AdoptionMap {
|
|
1506
|
+
/** Firearm slug. */
|
|
1507
|
+
firearmId: string;
|
|
1508
|
+
/** Firearm name. */
|
|
1509
|
+
firearmName: string;
|
|
1510
|
+
/** Users grouped by country. */
|
|
1511
|
+
countries: Array<{
|
|
1512
|
+
/** ISO country code (may be `null` for unknown). */
|
|
1513
|
+
code: string | null;
|
|
1514
|
+
/** Institutional users in this country. */
|
|
1515
|
+
users: Array<{
|
|
1516
|
+
name: string;
|
|
1517
|
+
type: string | null;
|
|
1518
|
+
year: number | null;
|
|
1519
|
+
designation: string | null;
|
|
1520
|
+
}>;
|
|
1521
|
+
}>;
|
|
1522
|
+
}
|
|
1523
|
+
/**
|
|
1524
|
+
* A firearm's computed power rating with breakdown.
|
|
1525
|
+
*
|
|
1526
|
+
* Returned by `GET /v1/firearms/power-rating`.
|
|
1527
|
+
*/
|
|
1528
|
+
interface PowerRating {
|
|
1529
|
+
/** Firearm slug. */
|
|
1530
|
+
id: string;
|
|
1531
|
+
/** Firearm name. */
|
|
1532
|
+
name: string;
|
|
1533
|
+
/** Manufacturer slug. */
|
|
1534
|
+
manufacturerId: string;
|
|
1535
|
+
/** Category slug. */
|
|
1536
|
+
categoryId: string;
|
|
1537
|
+
/** Composite power rating (0-100 scale). */
|
|
1538
|
+
powerRating: number;
|
|
1539
|
+
/** Per-component breakdown of the power rating. */
|
|
1540
|
+
breakdown: {
|
|
1541
|
+
/** Energy component (max 30). */
|
|
1542
|
+
energy: number;
|
|
1543
|
+
/** Range component (max 25). */
|
|
1544
|
+
range: number;
|
|
1545
|
+
/** Fire rate component (max 20). */
|
|
1546
|
+
fireRate: number;
|
|
1547
|
+
/** Capacity component (max 15). */
|
|
1548
|
+
capacity: number;
|
|
1549
|
+
/** Mobility component (max 10). */
|
|
1550
|
+
mobility: number;
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1553
|
+
/**
|
|
1554
|
+
* Firearm dimensions in both metric and imperial units.
|
|
1555
|
+
*
|
|
1556
|
+
* Returned by `GET /v1/firearms/:id/dimensions`.
|
|
1557
|
+
*/
|
|
1558
|
+
interface Dimensions {
|
|
1559
|
+
/** Firearm slug. */
|
|
1560
|
+
id: string;
|
|
1561
|
+
/** Firearm name. */
|
|
1562
|
+
name: string;
|
|
1563
|
+
/** Metric measurements. */
|
|
1564
|
+
metric: {
|
|
1565
|
+
weightEmptyG: number | null;
|
|
1566
|
+
weightLoadedG: number | null;
|
|
1567
|
+
overallLengthMm: number | null;
|
|
1568
|
+
barrelLengthMm: number | null;
|
|
1569
|
+
heightMm: number | null;
|
|
1570
|
+
widthMm: number | null;
|
|
1571
|
+
foldedLengthMm: number | null;
|
|
1572
|
+
};
|
|
1573
|
+
/** Imperial measurements (converted from metric). */
|
|
1574
|
+
imperial: {
|
|
1575
|
+
weightEmptyLbs: number | null;
|
|
1576
|
+
weightLoadedLbs: number | null;
|
|
1577
|
+
overallLengthIn: number | null;
|
|
1578
|
+
barrelLengthIn: number | null;
|
|
1579
|
+
heightIn: number | null;
|
|
1580
|
+
widthIn: number | null;
|
|
1581
|
+
foldedLengthIn: number | null;
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
/**
|
|
1585
|
+
* Available filter dropdown options.
|
|
1586
|
+
*
|
|
1587
|
+
* Returned by `GET /v1/firearms/filters`.
|
|
1588
|
+
*/
|
|
1589
|
+
interface FilterOptions {
|
|
1590
|
+
/** Available categories. */
|
|
1591
|
+
categories: Array<{
|
|
1592
|
+
slug: string;
|
|
1593
|
+
name: string;
|
|
1594
|
+
}>;
|
|
1595
|
+
/** Available manufacturers. */
|
|
1596
|
+
manufacturers: Array<{
|
|
1597
|
+
id: string;
|
|
1598
|
+
name: string;
|
|
1599
|
+
}>;
|
|
1600
|
+
/** Available calibers. */
|
|
1601
|
+
calibers: Array<{
|
|
1602
|
+
id: string;
|
|
1603
|
+
name: string;
|
|
1604
|
+
}>;
|
|
1605
|
+
/** Available action types. */
|
|
1606
|
+
actionTypes: Array<{
|
|
1607
|
+
id: string;
|
|
1608
|
+
name: string;
|
|
1609
|
+
}>;
|
|
1610
|
+
}
|
|
1611
|
+
/**
|
|
1612
|
+
* Database summary statistics.
|
|
1613
|
+
*
|
|
1614
|
+
* Returned by `GET /v1/stats/summary`.
|
|
1615
|
+
*/
|
|
1616
|
+
interface StatsSummary {
|
|
1617
|
+
/** Total number of firearms. */
|
|
1618
|
+
total_firearms: number;
|
|
1619
|
+
/** Total number of manufacturers. */
|
|
1620
|
+
total_manufacturers: number;
|
|
1621
|
+
/** Total number of calibers. */
|
|
1622
|
+
total_calibers: number;
|
|
1623
|
+
/** Number of distinct countries of origin. */
|
|
1624
|
+
countries_of_origin: number;
|
|
1625
|
+
/** Average data confidence percentage. */
|
|
1626
|
+
avg_confidence: number | null;
|
|
1627
|
+
/** Total number of firearm variants. */
|
|
1628
|
+
total_variants: number;
|
|
1629
|
+
}
|
|
1630
|
+
/**
|
|
1631
|
+
* Production status breakdown.
|
|
1632
|
+
*
|
|
1633
|
+
* Returned by `GET /v1/stats/production-status`.
|
|
1634
|
+
*/
|
|
1635
|
+
interface ProductionStatusItem {
|
|
1636
|
+
/** Status value. */
|
|
1637
|
+
status: string;
|
|
1638
|
+
/** Number of firearms with this status. */
|
|
1639
|
+
count: number;
|
|
1640
|
+
}
|
|
1641
|
+
/**
|
|
1642
|
+
* Field coverage percentage for a single field.
|
|
1643
|
+
*
|
|
1644
|
+
* Returned by `GET /v1/stats/field-coverage`.
|
|
1645
|
+
*/
|
|
1646
|
+
interface FieldCoverage {
|
|
1647
|
+
/** Field name (snake_case column name). */
|
|
1648
|
+
field: string;
|
|
1649
|
+
/** Percentage of firearms with a non-null value (0-100). */
|
|
1650
|
+
percentage: number;
|
|
1651
|
+
}
|
|
1652
|
+
/**
|
|
1653
|
+
* Popular caliber with firearm count.
|
|
1654
|
+
*
|
|
1655
|
+
* Returned by `GET /v1/stats/popular-calibers`.
|
|
1656
|
+
*/
|
|
1657
|
+
interface PopularCaliber {
|
|
1658
|
+
/** Caliber slug. */
|
|
1659
|
+
id: string;
|
|
1660
|
+
/** Caliber display name. */
|
|
1661
|
+
name: string;
|
|
1662
|
+
/** NATO designation. */
|
|
1663
|
+
nato_designation: string | null;
|
|
1664
|
+
/** Number of firearms chambered in this caliber. */
|
|
1665
|
+
firearm_count: number;
|
|
1666
|
+
}
|
|
1667
|
+
/**
|
|
1668
|
+
* Prolific manufacturer with firearm count.
|
|
1669
|
+
*
|
|
1670
|
+
* Returned by `GET /v1/stats/prolific-manufacturers`.
|
|
1671
|
+
*/
|
|
1672
|
+
interface ProlificManufacturer {
|
|
1673
|
+
/** Manufacturer slug. */
|
|
1674
|
+
id: string;
|
|
1675
|
+
/** Manufacturer name. */
|
|
1676
|
+
name: string;
|
|
1677
|
+
/** Country code. */
|
|
1678
|
+
country_code: string | null;
|
|
1679
|
+
/** Number of firearms produced. */
|
|
1680
|
+
firearm_count: number;
|
|
1681
|
+
}
|
|
1682
|
+
/**
|
|
1683
|
+
* Category statistics with averages.
|
|
1684
|
+
*
|
|
1685
|
+
* Returned by `GET /v1/stats/by-category`.
|
|
1686
|
+
*/
|
|
1687
|
+
interface CategoryStats {
|
|
1688
|
+
/** Category slug. */
|
|
1689
|
+
id: string;
|
|
1690
|
+
/** Category name. */
|
|
1691
|
+
name: string;
|
|
1692
|
+
/** Number of firearms in this category. */
|
|
1693
|
+
firearm_count: number;
|
|
1694
|
+
/** Average weight in grams. */
|
|
1695
|
+
avg_weight_g: number | null;
|
|
1696
|
+
/** Average magazine capacity. */
|
|
1697
|
+
avg_magazine_capacity: number | null;
|
|
1698
|
+
/** Average barrel length in mm. */
|
|
1699
|
+
avg_barrel_length_mm: number | null;
|
|
1700
|
+
}
|
|
1701
|
+
/**
|
|
1702
|
+
* Era (decade) statistics.
|
|
1703
|
+
*
|
|
1704
|
+
* Returned by `GET /v1/stats/by-era`.
|
|
1705
|
+
*/
|
|
1706
|
+
interface EraStats {
|
|
1707
|
+
/** Number of firearms introduced in this decade. */
|
|
1708
|
+
firearm_count: number;
|
|
1709
|
+
/** Average weight in grams. */
|
|
1710
|
+
avg_weight_g: number | null;
|
|
1711
|
+
/** Average magazine capacity. */
|
|
1712
|
+
avg_magazine_capacity: number | null;
|
|
1713
|
+
/** Average barrel length in mm. */
|
|
1714
|
+
avg_barrel_length_mm: number | null;
|
|
1715
|
+
/** Earliest year in the decade with data. */
|
|
1716
|
+
earliest_year: number | null;
|
|
1717
|
+
/** Latest year in the decade with data. */
|
|
1718
|
+
latest_year: number | null;
|
|
1719
|
+
}
|
|
1720
|
+
/**
|
|
1721
|
+
* Material usage breakdown per component.
|
|
1722
|
+
*
|
|
1723
|
+
* Returned by `GET /v1/stats/materials`.
|
|
1724
|
+
*/
|
|
1725
|
+
interface MaterialStats {
|
|
1726
|
+
/** Frame materials. */
|
|
1727
|
+
frame: Array<{
|
|
1728
|
+
material: string;
|
|
1729
|
+
count: number;
|
|
1730
|
+
}>;
|
|
1731
|
+
/** Slide materials. */
|
|
1732
|
+
slide: Array<{
|
|
1733
|
+
material: string;
|
|
1734
|
+
count: number;
|
|
1735
|
+
}>;
|
|
1736
|
+
/** Barrel materials. */
|
|
1737
|
+
barrel: Array<{
|
|
1738
|
+
material: string;
|
|
1739
|
+
count: number;
|
|
1740
|
+
}>;
|
|
1741
|
+
/** Stock materials. */
|
|
1742
|
+
stock: Array<{
|
|
1743
|
+
material: string;
|
|
1744
|
+
count: number;
|
|
1745
|
+
}>;
|
|
1746
|
+
}
|
|
1747
|
+
/**
|
|
1748
|
+
* Adoption record by country.
|
|
1749
|
+
*
|
|
1750
|
+
* Returned by `GET /v1/stats/adoption/country`.
|
|
1751
|
+
*/
|
|
1752
|
+
interface AdoptionByCountryItem {
|
|
1753
|
+
/** Firearm user record ID. */
|
|
1754
|
+
id: number;
|
|
1755
|
+
/** User / organisation name. */
|
|
1756
|
+
user_name: string;
|
|
1757
|
+
/** User type. */
|
|
1758
|
+
user_type: string | null;
|
|
1759
|
+
/** Year adopted. */
|
|
1760
|
+
adopted_year: number | null;
|
|
1761
|
+
/** Service designation. */
|
|
1762
|
+
designation: string | null;
|
|
1763
|
+
/** Firearm slug. */
|
|
1764
|
+
firearm_id: string;
|
|
1765
|
+
/** Firearm name. */
|
|
1766
|
+
firearm_name: string;
|
|
1767
|
+
}
|
|
1768
|
+
/**
|
|
1769
|
+
* Adoption record by user type.
|
|
1770
|
+
*
|
|
1771
|
+
* Returned by `GET /v1/stats/adoption/type`.
|
|
1772
|
+
*/
|
|
1773
|
+
interface AdoptionByTypeItem {
|
|
1774
|
+
/** Firearm slug. */
|
|
1775
|
+
firearm_id: string;
|
|
1776
|
+
/** Firearm name. */
|
|
1777
|
+
firearm_name: string;
|
|
1778
|
+
/** Number of countries that adopted this firearm for this role. */
|
|
1779
|
+
adoption_count: number;
|
|
1780
|
+
/** List of country codes. */
|
|
1781
|
+
countries: string[];
|
|
1782
|
+
}
|
|
1783
|
+
/**
|
|
1784
|
+
* Action type frequency.
|
|
1785
|
+
*
|
|
1786
|
+
* Returned by `GET /v1/stats/action-types`.
|
|
1787
|
+
*/
|
|
1788
|
+
interface ActionTypeStats {
|
|
1789
|
+
/** Action type slug. */
|
|
1790
|
+
action_type: string;
|
|
1791
|
+
/** Number of firearms with this action type. */
|
|
1792
|
+
count: number;
|
|
1793
|
+
}
|
|
1794
|
+
/**
|
|
1795
|
+
* Feature frequency item.
|
|
1796
|
+
*
|
|
1797
|
+
* Returned by `GET /v1/stats/feature-frequency`.
|
|
1798
|
+
*/
|
|
1799
|
+
interface FeatureFrequency {
|
|
1800
|
+
/** Feature name. */
|
|
1801
|
+
feature: string;
|
|
1802
|
+
/** Number of firearms with this feature. */
|
|
1803
|
+
count: number;
|
|
1804
|
+
}
|
|
1805
|
+
/**
|
|
1806
|
+
* Caliber popularity within a decade.
|
|
1807
|
+
*
|
|
1808
|
+
* Returned by `GET /v1/stats/caliber-popularity-by-era`.
|
|
1809
|
+
*/
|
|
1810
|
+
interface CaliberPopularityByEra {
|
|
1811
|
+
/** Decade label (e.g. `"1990s"`). */
|
|
1812
|
+
decade: string;
|
|
1813
|
+
/** Calibers ranked by popularity within this decade. */
|
|
1814
|
+
calibers: Array<{
|
|
1815
|
+
caliberId: string;
|
|
1816
|
+
caliberName: string;
|
|
1817
|
+
firearmCount: number;
|
|
1818
|
+
}>;
|
|
1819
|
+
}
|
|
1820
|
+
/**
|
|
1821
|
+
* A country with its firearm count.
|
|
1822
|
+
*
|
|
1823
|
+
* Returned by `GET /v1/countries`.
|
|
1824
|
+
*/
|
|
1825
|
+
interface Country {
|
|
1826
|
+
/** ISO 3166-1 alpha-2 country code. */
|
|
1827
|
+
code: string;
|
|
1828
|
+
/** Number of firearms originating from this country. */
|
|
1829
|
+
firearmCount: number;
|
|
1830
|
+
}
|
|
1831
|
+
/**
|
|
1832
|
+
* A conflict with associated firearms.
|
|
1833
|
+
*
|
|
1834
|
+
* Returned by `GET /v1/conflicts`.
|
|
1835
|
+
*/
|
|
1836
|
+
interface Conflict {
|
|
1837
|
+
/** Conflict name. */
|
|
1838
|
+
name: string;
|
|
1839
|
+
/** Number of firearms used in this conflict. */
|
|
1840
|
+
firearmCount: number;
|
|
1841
|
+
/** Firearms used in this conflict. */
|
|
1842
|
+
firearms: Array<{
|
|
1843
|
+
id: string;
|
|
1844
|
+
name: string;
|
|
1845
|
+
}>;
|
|
1846
|
+
}
|
|
1847
|
+
/**
|
|
1848
|
+
* Data coverage summary.
|
|
1849
|
+
*
|
|
1850
|
+
* Returned by `GET /v1/data/coverage`.
|
|
1851
|
+
*/
|
|
1852
|
+
interface DataCoverage {
|
|
1853
|
+
/** Field name. */
|
|
1854
|
+
field: string;
|
|
1855
|
+
/** Percentage of records with non-null values (0-100). */
|
|
1856
|
+
percentage: number;
|
|
1857
|
+
}
|
|
1858
|
+
/**
|
|
1859
|
+
* A firearm record with its computed data confidence score.
|
|
1860
|
+
*
|
|
1861
|
+
* Returned by the data quality confidence endpoint.
|
|
1862
|
+
*/
|
|
1863
|
+
interface ConfidenceEntry {
|
|
1864
|
+
/** Firearm slug. */
|
|
1865
|
+
slug: string;
|
|
1866
|
+
/** Firearm display name. */
|
|
1867
|
+
name: string;
|
|
1868
|
+
/** Confidence score (0-1). */
|
|
1869
|
+
confidenceScore: number;
|
|
1870
|
+
/** Number of non-null specification fields. */
|
|
1871
|
+
filledFields: number;
|
|
1872
|
+
/** Total number of specification fields. */
|
|
1873
|
+
totalFields: number;
|
|
1874
|
+
}
|
|
1875
|
+
/**
|
|
1876
|
+
* A country's firearm arsenal — military and law enforcement holdings.
|
|
1877
|
+
*/
|
|
1878
|
+
interface CountryArsenal {
|
|
1879
|
+
/** The country record. */
|
|
1880
|
+
country: Country;
|
|
1881
|
+
/** Total number of adopted firearms. */
|
|
1882
|
+
totalFirearms: number;
|
|
1883
|
+
/** Firearms grouped by usage type. */
|
|
1884
|
+
groups: {
|
|
1885
|
+
/** Usage type (e.g. "military", "law_enforcement"). */
|
|
1886
|
+
type: string;
|
|
1887
|
+
/** Firearms in this usage group. */
|
|
1888
|
+
firearms: Firearm[];
|
|
1889
|
+
}[];
|
|
1890
|
+
}
|
|
1891
|
+
/**
|
|
1892
|
+
* Ballistics data for a caliber at a given distance.
|
|
1893
|
+
*/
|
|
1894
|
+
interface BallisticsResult {
|
|
1895
|
+
/** Caliber slug or ID. */
|
|
1896
|
+
caliberId: string;
|
|
1897
|
+
/** Distance in meters. */
|
|
1898
|
+
distanceM: number;
|
|
1899
|
+
/** Bullet velocity at the given distance (fps). */
|
|
1900
|
+
velocityFps: number;
|
|
1901
|
+
/** Bullet energy at the given distance (ft-lbs). */
|
|
1902
|
+
energyFtLbs: number;
|
|
1903
|
+
/** Bullet drop at the given distance (inches). */
|
|
1904
|
+
dropInches: number;
|
|
1905
|
+
/** Wind drift at the given distance (inches). */
|
|
1906
|
+
driftInches?: number;
|
|
1907
|
+
/** Time of flight in seconds. */
|
|
1908
|
+
timeOfFlightS?: number;
|
|
1909
|
+
}
|
|
1910
|
+
/**
|
|
1911
|
+
* SVG silhouette data for a firearm.
|
|
1912
|
+
*/
|
|
1913
|
+
interface Silhouette {
|
|
1914
|
+
/** The firearm slug. */
|
|
1915
|
+
slug: string;
|
|
1916
|
+
/** Raw SVG string (when format is "svg"). */
|
|
1917
|
+
svg?: string;
|
|
1918
|
+
/** Base64 data URI (when format is "datauri"). */
|
|
1919
|
+
dataUri?: string;
|
|
1920
|
+
/** Stroke width used. */
|
|
1921
|
+
strokeWidth?: number;
|
|
1922
|
+
/** Stroke color used. */
|
|
1923
|
+
strokeColor?: string;
|
|
1924
|
+
/** Original image width in pixels. */
|
|
1925
|
+
width?: number;
|
|
1926
|
+
/** Original image height in pixels. */
|
|
1927
|
+
height?: number;
|
|
1928
|
+
}
|
|
1929
|
+
/**
|
|
1930
|
+
* Game balance report identifying outlier firearms.
|
|
1931
|
+
*/
|
|
1932
|
+
interface BalanceReport {
|
|
1933
|
+
/** Threshold percentage used for outlier detection. */
|
|
1934
|
+
threshold: number;
|
|
1935
|
+
/** Total firearms analyzed. */
|
|
1936
|
+
totalAnalyzed: number;
|
|
1937
|
+
/** Firearms flagged as overpowered. */
|
|
1938
|
+
overpowered: BalanceEntry[];
|
|
1939
|
+
/** Firearms flagged as underpowered. */
|
|
1940
|
+
underpowered: BalanceEntry[];
|
|
1941
|
+
/** Deviations by stat. */
|
|
1942
|
+
deviations?: BalanceDeviation[];
|
|
1943
|
+
}
|
|
1944
|
+
/**
|
|
1945
|
+
* A roster of firearms suited for a specific game role.
|
|
1946
|
+
*/
|
|
1947
|
+
interface RoleRoster {
|
|
1948
|
+
/** The role that was queried. */
|
|
1949
|
+
role: string;
|
|
1950
|
+
/** Total firearms considered. */
|
|
1951
|
+
totalConsidered: number;
|
|
1952
|
+
/** Firearms ranked by suitability for the role. */
|
|
1953
|
+
firearms: RoleRosterItem[];
|
|
1954
|
+
}
|
|
1955
|
+
/**
|
|
1956
|
+
* A user's favorited firearm.
|
|
1957
|
+
*
|
|
1958
|
+
* Returned by `GET /v1/me/favorites`.
|
|
1959
|
+
*/
|
|
1960
|
+
interface Favorite {
|
|
1961
|
+
/** Firearm slug. */
|
|
1962
|
+
firearmId: string;
|
|
1963
|
+
/** ISO-8601 timestamp when the favorite was added. */
|
|
1964
|
+
createdAt: string;
|
|
1965
|
+
}
|
|
1966
|
+
/**
|
|
1967
|
+
* Result of toggling a favorite.
|
|
1968
|
+
*
|
|
1969
|
+
* Returned by `POST /v1/me/favorites/:firearmId` and `DELETE /v1/me/favorites/:firearmId`.
|
|
1970
|
+
*/
|
|
1971
|
+
interface FavoriteToggle {
|
|
1972
|
+
/** Firearm slug. */
|
|
1973
|
+
firearmId: string;
|
|
1974
|
+
/** Whether the firearm is now favorited. */
|
|
1975
|
+
favorited: boolean;
|
|
1976
|
+
}
|
|
1977
|
+
/**
|
|
1978
|
+
* A user-submitted data quality report.
|
|
1979
|
+
*
|
|
1980
|
+
* Returned by `GET /v1/me/reports` and `POST /v1/me/reports`.
|
|
1981
|
+
*/
|
|
1982
|
+
interface DataReport {
|
|
1983
|
+
/** Unique report ID. */
|
|
1984
|
+
readonly id: string;
|
|
1985
|
+
/** Firearm slug the report pertains to. */
|
|
1986
|
+
firearmId: string;
|
|
1987
|
+
/** Section of the firearm page (e.g. `"specs"`, `"game-stats"`). */
|
|
1988
|
+
section: string;
|
|
1989
|
+
/** Type of issue reported. */
|
|
1990
|
+
issueType: 'incorrect' | 'missing' | 'outdated';
|
|
1991
|
+
/** User-provided description of the issue. */
|
|
1992
|
+
description: string;
|
|
1993
|
+
/** Optional reference URLs supporting the report. */
|
|
1994
|
+
references?: string[];
|
|
1995
|
+
/** Optional suggested correction. */
|
|
1996
|
+
suggestedValue?: string;
|
|
1997
|
+
/** Current review status. */
|
|
1998
|
+
status: 'pending' | 'reviewed' | 'resolved' | 'dismissed';
|
|
1999
|
+
/** ISO-8601 creation timestamp. */
|
|
2000
|
+
readonly createdAt: string;
|
|
2001
|
+
/** ISO-8601 last-update timestamp. */
|
|
2002
|
+
readonly updatedAt: string;
|
|
2003
|
+
}
|
|
2004
|
+
/**
|
|
2005
|
+
* A support ticket summary.
|
|
2006
|
+
*
|
|
2007
|
+
* Returned by `GET /v1/me/support`.
|
|
2008
|
+
*/
|
|
2009
|
+
interface SupportTicket {
|
|
2010
|
+
/** Unique ticket ID. */
|
|
2011
|
+
readonly id: string;
|
|
2012
|
+
/** Ticket subject line. */
|
|
2013
|
+
subject: string;
|
|
2014
|
+
/** Ticket description / body. */
|
|
2015
|
+
description: string;
|
|
2016
|
+
/** Ticket category. */
|
|
2017
|
+
category?: 'billing' | 'technical' | 'data_quality' | 'feature_request' | 'other';
|
|
2018
|
+
/** Priority level. */
|
|
2019
|
+
priority: 'low' | 'normal' | 'high' | 'urgent';
|
|
2020
|
+
/** Current status. */
|
|
2021
|
+
status: 'open' | 'in_progress' | 'waiting' | 'resolved' | 'closed';
|
|
2022
|
+
/** ISO-8601 creation timestamp. */
|
|
2023
|
+
readonly createdAt: string;
|
|
2024
|
+
/** ISO-8601 last-update timestamp. */
|
|
2025
|
+
readonly updatedAt: string;
|
|
2026
|
+
}
|
|
2027
|
+
/**
|
|
2028
|
+
* A support ticket with its reply thread.
|
|
2029
|
+
*
|
|
2030
|
+
* Returned by `GET /v1/me/support/:ticketId`.
|
|
2031
|
+
*/
|
|
2032
|
+
interface SupportTicketDetail extends SupportTicket {
|
|
2033
|
+
/** Reply thread ordered chronologically. */
|
|
2034
|
+
replies: SupportTicketReply[];
|
|
2035
|
+
}
|
|
2036
|
+
/**
|
|
2037
|
+
* A single reply in a support ticket thread.
|
|
2038
|
+
*/
|
|
2039
|
+
interface SupportTicketReply {
|
|
2040
|
+
/** Auto-increment reply ID. */
|
|
2041
|
+
readonly id: number;
|
|
2042
|
+
/** Parent ticket ID. */
|
|
2043
|
+
ticketId: string;
|
|
2044
|
+
/** Reply message body. */
|
|
2045
|
+
message: string;
|
|
2046
|
+
/** Whether this reply was from staff. */
|
|
2047
|
+
isStaff: boolean;
|
|
2048
|
+
/** ISO-8601 creation timestamp. */
|
|
2049
|
+
readonly createdAt: string;
|
|
2050
|
+
}
|
|
2051
|
+
/**
|
|
2052
|
+
* A webhook endpoint configuration.
|
|
2053
|
+
*
|
|
2054
|
+
* Returned by `GET /v1/me/webhooks` and related endpoints.
|
|
2055
|
+
*/
|
|
2056
|
+
interface WebhookEndpoint {
|
|
2057
|
+
/** Unique endpoint ID. */
|
|
2058
|
+
readonly id: string;
|
|
2059
|
+
/** Delivery URL. */
|
|
2060
|
+
url: string;
|
|
2061
|
+
/** Optional human-readable description. */
|
|
2062
|
+
description?: string | null;
|
|
2063
|
+
/** Event types this endpoint subscribes to. */
|
|
2064
|
+
events: string[];
|
|
2065
|
+
/** Whether the endpoint is active. */
|
|
2066
|
+
active: boolean;
|
|
2067
|
+
/** HMAC signing secret for verifying payloads. */
|
|
2068
|
+
secret: string;
|
|
2069
|
+
/** ISO-8601 creation timestamp. */
|
|
2070
|
+
readonly createdAt: string;
|
|
2071
|
+
/** ISO-8601 last-update timestamp. */
|
|
2072
|
+
readonly updatedAt: string;
|
|
2073
|
+
}
|
|
2074
|
+
/**
|
|
2075
|
+
* Result of sending a test event to a webhook endpoint.
|
|
2076
|
+
*
|
|
2077
|
+
* Returned by `POST /v1/me/webhooks/:id/test`.
|
|
2078
|
+
*/
|
|
2079
|
+
interface WebhookTestResult {
|
|
2080
|
+
/** Whether the test delivery was successful. */
|
|
2081
|
+
success: boolean;
|
|
2082
|
+
/** HTTP status code returned by the endpoint. */
|
|
2083
|
+
statusCode: number;
|
|
2084
|
+
/** Round-trip delivery time in milliseconds. */
|
|
2085
|
+
responseTimeMs: number;
|
|
2086
|
+
/** Error message if delivery failed. */
|
|
2087
|
+
error?: string;
|
|
2088
|
+
}
|
|
2089
|
+
/**
|
|
2090
|
+
* API usage statistics for the authenticated user.
|
|
2091
|
+
*
|
|
2092
|
+
* Returned by `GET /v1/me/usage`.
|
|
2093
|
+
*/
|
|
2094
|
+
interface UsageStats {
|
|
2095
|
+
/** Current billing month usage. */
|
|
2096
|
+
currentMonth: {
|
|
2097
|
+
/** Requests used this month. */
|
|
2098
|
+
used: number;
|
|
2099
|
+
/** Monthly request limit. */
|
|
2100
|
+
limit: number;
|
|
2101
|
+
/** Usage as a percentage (0-100). */
|
|
2102
|
+
percentage: number;
|
|
2103
|
+
/** ISO-8601 timestamp when usage resets. */
|
|
2104
|
+
resetsAt: string;
|
|
2105
|
+
};
|
|
2106
|
+
/** Daily request counts for the requested period. */
|
|
2107
|
+
dailyBreakdown: Array<{
|
|
2108
|
+
date: string;
|
|
2109
|
+
count: number;
|
|
2110
|
+
}>;
|
|
2111
|
+
/** Per-API-key usage breakdown. */
|
|
2112
|
+
perKey: Array<{
|
|
2113
|
+
keyId: string;
|
|
2114
|
+
keyName: string;
|
|
2115
|
+
count: number;
|
|
2116
|
+
}>;
|
|
2117
|
+
/** Total number of API keys. */
|
|
2118
|
+
keyCount: number;
|
|
2119
|
+
/** Current subscription tier details. */
|
|
2120
|
+
tier: {
|
|
2121
|
+
/** Tier display name. */
|
|
2122
|
+
name: string;
|
|
2123
|
+
/** Monthly request allowance. */
|
|
2124
|
+
requestsPerMonth: number;
|
|
2125
|
+
/** Requests per minute limit. */
|
|
2126
|
+
rateLimit: number;
|
|
2127
|
+
};
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
/**
|
|
2131
|
+
* Common pagination parameters accepted by all list endpoints.
|
|
2132
|
+
*
|
|
2133
|
+
* @example
|
|
2134
|
+
* ```ts
|
|
2135
|
+
* const params: PaginationParams = { page: 2, per_page: 50, order: 'desc' };
|
|
2136
|
+
* ```
|
|
2137
|
+
*/
|
|
2138
|
+
interface PaginationParams {
|
|
2139
|
+
/**
|
|
2140
|
+
* Page number (1-based).
|
|
2141
|
+
* @defaultValue `1`
|
|
2142
|
+
*/
|
|
2143
|
+
page?: number;
|
|
2144
|
+
/**
|
|
2145
|
+
* Number of items per page (1-100).
|
|
2146
|
+
* @defaultValue `20`
|
|
2147
|
+
*/
|
|
2148
|
+
per_page?: number;
|
|
2149
|
+
/** Column to sort by. Allowed values depend on the endpoint. */
|
|
2150
|
+
sort?: string;
|
|
2151
|
+
/**
|
|
2152
|
+
* Sort direction.
|
|
2153
|
+
* @defaultValue `"asc"`
|
|
2154
|
+
*/
|
|
2155
|
+
order?: 'asc' | 'desc';
|
|
2156
|
+
}
|
|
2157
|
+
/**
|
|
2158
|
+
* Parameters for `GET /v1/firearms`.
|
|
2159
|
+
*
|
|
2160
|
+
* @example
|
|
2161
|
+
* ```ts
|
|
2162
|
+
* const params: ListFirearmsParams = {
|
|
2163
|
+
* manufacturer: 'glock',
|
|
2164
|
+
* category: 'semi-automatic-pistol',
|
|
2165
|
+
* sort: 'name',
|
|
2166
|
+
* page: 1,
|
|
2167
|
+
* per_page: 20,
|
|
2168
|
+
* };
|
|
2169
|
+
* ```
|
|
2170
|
+
*/
|
|
2171
|
+
interface ListFirearmsParams extends PaginationParams {
|
|
2172
|
+
/** Filter by manufacturer slug. */
|
|
2173
|
+
manufacturer?: string;
|
|
2174
|
+
/** Filter by caliber slug (matched via junction table). */
|
|
2175
|
+
caliber?: string;
|
|
2176
|
+
/** Filter by category slug. */
|
|
2177
|
+
category?: string;
|
|
2178
|
+
/** Filter by action type slug. */
|
|
2179
|
+
action_type?: string;
|
|
2180
|
+
/** Filter by country of origin ISO code. */
|
|
2181
|
+
country_of_origin?: string;
|
|
2182
|
+
/** Minimum year introduced (inclusive). */
|
|
2183
|
+
year_introduced_min?: number;
|
|
2184
|
+
/** Maximum year introduced (inclusive). */
|
|
2185
|
+
year_introduced_max?: number;
|
|
2186
|
+
/** Minimum empty weight in grams. */
|
|
2187
|
+
weight_min?: number;
|
|
2188
|
+
/** Maximum empty weight in grams. */
|
|
2189
|
+
weight_max?: number;
|
|
2190
|
+
/** Minimum barrel length in mm. */
|
|
2191
|
+
barrel_length_min?: number;
|
|
2192
|
+
/** Filter by production status. */
|
|
2193
|
+
status?: 'in_production' | 'discontinued' | 'prototype';
|
|
2194
|
+
/** Filter for firearms with/without a 3-D model. */
|
|
2195
|
+
has_3d_model?: 'true' | 'false';
|
|
2196
|
+
/** Comma-separated list of fields to include in the response (sparse fieldset). */
|
|
2197
|
+
fields?: string;
|
|
2198
|
+
/**
|
|
2199
|
+
* Sort column.
|
|
2200
|
+
* @defaultValue `"name"`
|
|
2201
|
+
*/
|
|
2202
|
+
sort?: 'name' | 'weight' | 'year' | 'caliber' | 'created_at' | 'favorites';
|
|
2203
|
+
}
|
|
2204
|
+
/**
|
|
2205
|
+
* Parameters for `GET /v1/firearms/search`.
|
|
2206
|
+
*/
|
|
2207
|
+
interface SearchFirearmsParams extends PaginationParams {
|
|
2208
|
+
/** Full-text search query (1-200 characters). */
|
|
2209
|
+
q: string;
|
|
2210
|
+
}
|
|
2211
|
+
/**
|
|
2212
|
+
* Parameters for `GET /v1/firearms/compare`.
|
|
2213
|
+
*/
|
|
2214
|
+
interface CompareFirearmsParams {
|
|
2215
|
+
/**
|
|
2216
|
+
* Comma-separated firearm slugs to compare (maximum 5).
|
|
2217
|
+
*
|
|
2218
|
+
* @example `"glock-g17,beretta-92fs,sig-sauer-p226"`
|
|
2219
|
+
*/
|
|
2220
|
+
ids: string;
|
|
2221
|
+
}
|
|
2222
|
+
/**
|
|
2223
|
+
* Parameters for `GET /v1/firearms/:id/game/meta`.
|
|
2224
|
+
*/
|
|
2225
|
+
interface GameMetaParams {
|
|
2226
|
+
/** Filter by computed archetype. */
|
|
2227
|
+
archetype?: 'sniper' | 'assault' | 'tank' | 'glass-cannon' | 'all-rounder' | 'support' | 'stealth' | 'speedster';
|
|
2228
|
+
}
|
|
2229
|
+
/**
|
|
2230
|
+
* Parameters for `GET /v1/firearms/random`.
|
|
2231
|
+
*/
|
|
2232
|
+
interface RandomFirearmParams {
|
|
2233
|
+
/** Filter by category slug. */
|
|
2234
|
+
category?: string;
|
|
2235
|
+
/** Filter by country of origin ISO code. */
|
|
2236
|
+
country?: string;
|
|
2237
|
+
}
|
|
2238
|
+
/**
|
|
2239
|
+
* Parameters for `GET /v1/firearms/top`.
|
|
2240
|
+
*
|
|
2241
|
+
* @example
|
|
2242
|
+
* ```ts
|
|
2243
|
+
* const params: TopFirearmsParams = { stat: 'lightest', category: 'semi-automatic-pistol', limit: 5 };
|
|
2244
|
+
* ```
|
|
2245
|
+
*/
|
|
2246
|
+
interface TopFirearmsParams {
|
|
2247
|
+
/** The stat to rank by. */
|
|
2248
|
+
stat: 'lightest' | 'heaviest' | 'longest-range' | 'highest-rof' | 'most-compact' | 'highest-capacity' | 'most-powerful';
|
|
2249
|
+
/** Filter by category slug. */
|
|
2250
|
+
category?: string;
|
|
2251
|
+
/**
|
|
2252
|
+
* Maximum number of results (1-25).
|
|
2253
|
+
* @defaultValue `10`
|
|
2254
|
+
*/
|
|
2255
|
+
limit?: number;
|
|
2256
|
+
}
|
|
2257
|
+
/**
|
|
2258
|
+
* Parameters for `GET /v1/firearms/head-to-head`.
|
|
2259
|
+
*/
|
|
2260
|
+
interface HeadToHeadParams {
|
|
2261
|
+
/** Slug of firearm A. */
|
|
2262
|
+
a: string;
|
|
2263
|
+
/** Slug of firearm B. */
|
|
2264
|
+
b: string;
|
|
2265
|
+
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Parameters for `GET /v1/firearms/by-feature`.
|
|
2268
|
+
*/
|
|
2269
|
+
interface ByFeatureParams extends PaginationParams {
|
|
2270
|
+
/** Feature name to search for (matched via JSON LIKE). */
|
|
2271
|
+
feature: string;
|
|
2272
|
+
/** Optional category filter. */
|
|
2273
|
+
category?: string;
|
|
2274
|
+
}
|
|
2275
|
+
/**
|
|
2276
|
+
* Parameters for `GET /v1/firearms/by-action`.
|
|
2277
|
+
*/
|
|
2278
|
+
interface ByActionParams extends PaginationParams {
|
|
2279
|
+
/** Action type to filter by (exact match). */
|
|
2280
|
+
action: string;
|
|
2281
|
+
}
|
|
2282
|
+
/**
|
|
2283
|
+
* Parameters for `GET /v1/firearms/by-material`.
|
|
2284
|
+
*/
|
|
2285
|
+
interface ByMaterialParams extends PaginationParams {
|
|
2286
|
+
/** Material name to search for (substring match). */
|
|
2287
|
+
material: string;
|
|
2288
|
+
/** Which firearm component to search. */
|
|
2289
|
+
component: 'frame' | 'barrel' | 'stock' | 'slide';
|
|
2290
|
+
}
|
|
2291
|
+
/**
|
|
2292
|
+
* Parameters for `GET /v1/firearms/by-designer`.
|
|
2293
|
+
*/
|
|
2294
|
+
interface ByDesignerParams extends PaginationParams {
|
|
2295
|
+
/** Designer name to search for (substring match). */
|
|
2296
|
+
designer: string;
|
|
2297
|
+
}
|
|
2298
|
+
/**
|
|
2299
|
+
* Parameters for `GET /v1/firearms/power-rating`.
|
|
2300
|
+
*/
|
|
2301
|
+
interface PowerRatingParams extends PaginationParams {
|
|
2302
|
+
/** Optional category filter. */
|
|
2303
|
+
category?: string;
|
|
2304
|
+
}
|
|
2305
|
+
/**
|
|
2306
|
+
* Parameters for `GET /v1/firearms/timeline`.
|
|
2307
|
+
*/
|
|
2308
|
+
interface TimelineParams {
|
|
2309
|
+
/**
|
|
2310
|
+
* Page number (1-based).
|
|
2311
|
+
* @defaultValue `1`
|
|
2312
|
+
*/
|
|
2313
|
+
page?: number;
|
|
2314
|
+
/**
|
|
2315
|
+
* Items per page (1-100).
|
|
2316
|
+
* @defaultValue `50`
|
|
2317
|
+
*/
|
|
2318
|
+
per_page?: number;
|
|
2319
|
+
/** Sort column. */
|
|
2320
|
+
sort?: string;
|
|
2321
|
+
/**
|
|
2322
|
+
* Sort direction.
|
|
2323
|
+
* @defaultValue `"asc"`
|
|
2324
|
+
*/
|
|
2325
|
+
order?: 'asc' | 'desc';
|
|
2326
|
+
/** Earliest year to include (inclusive). */
|
|
2327
|
+
from?: number;
|
|
2328
|
+
/** Latest year to include (inclusive). */
|
|
2329
|
+
to?: number;
|
|
2330
|
+
/** Optional category filter. */
|
|
2331
|
+
category?: string;
|
|
2332
|
+
}
|
|
2333
|
+
/**
|
|
2334
|
+
* Parameters for `GET /v1/firearms/by-conflict`.
|
|
2335
|
+
*/
|
|
2336
|
+
interface ByConflictParams extends PaginationParams {
|
|
2337
|
+
/** Conflict name to search for (substring match). */
|
|
2338
|
+
conflict: string;
|
|
2339
|
+
}
|
|
2340
|
+
/**
|
|
2341
|
+
* Parameters for `GET /v1/firearms/:id/calculate`.
|
|
2342
|
+
*/
|
|
2343
|
+
interface CalculateBallisticsParams {
|
|
2344
|
+
/** Ammunition slug to calculate with. */
|
|
2345
|
+
ammo_id: string;
|
|
2346
|
+
}
|
|
2347
|
+
/**
|
|
2348
|
+
* Parameters for `GET /v1/firearms/:id/load`.
|
|
2349
|
+
*/
|
|
2350
|
+
interface LoadFirearmParams {
|
|
2351
|
+
/**
|
|
2352
|
+
* Ammunition slug.
|
|
2353
|
+
* If omitted, uses the firearm's default ammo or the most common ammo
|
|
2354
|
+
* for the primary caliber.
|
|
2355
|
+
*/
|
|
2356
|
+
ammo_id?: string;
|
|
2357
|
+
}
|
|
2358
|
+
/**
|
|
2359
|
+
* Parameters for `GET /v1/manufacturers`.
|
|
2360
|
+
*/
|
|
2361
|
+
interface ListManufacturersParams extends PaginationParams {
|
|
2362
|
+
/** Filter by country ISO code. */
|
|
2363
|
+
country?: string;
|
|
2364
|
+
}
|
|
2365
|
+
/**
|
|
2366
|
+
* Parameters for `GET /v1/calibers`.
|
|
2367
|
+
*/
|
|
2368
|
+
interface ListCalibersParams extends PaginationParams {
|
|
2369
|
+
/** Filter by cartridge type (e.g. `"centerfire_rifle"`). */
|
|
2370
|
+
cartridge_type?: string;
|
|
2371
|
+
/** Filter by primer type (e.g. `"Boxer"`). */
|
|
2372
|
+
primer_type?: string;
|
|
2373
|
+
}
|
|
2374
|
+
/**
|
|
2375
|
+
* Parameters for `GET /v1/calibers/compare`.
|
|
2376
|
+
*/
|
|
2377
|
+
interface CompareCalibersParams {
|
|
2378
|
+
/**
|
|
2379
|
+
* Comma-separated caliber slugs to compare (maximum 5).
|
|
2380
|
+
*
|
|
2381
|
+
* @example `"9x19mm-parabellum,45-acp,40-s-w"`
|
|
2382
|
+
*/
|
|
2383
|
+
ids: string;
|
|
2384
|
+
}
|
|
2385
|
+
/**
|
|
2386
|
+
* Parameters for `GET /v1/calibers/:id/ballistics`.
|
|
2387
|
+
*/
|
|
2388
|
+
interface CaliberBallisticsParams {
|
|
2389
|
+
/**
|
|
2390
|
+
* Distance in metres for the ballistic calculation (1-5000).
|
|
2391
|
+
* @defaultValue `100`
|
|
2392
|
+
*/
|
|
2393
|
+
distance?: number;
|
|
2394
|
+
}
|
|
2395
|
+
/**
|
|
2396
|
+
* Parameters for `GET /v1/ammunition`.
|
|
2397
|
+
*/
|
|
2398
|
+
interface ListAmmunitionParams extends PaginationParams {
|
|
2399
|
+
/** Filter by caliber slug. */
|
|
2400
|
+
caliber_id?: string;
|
|
2401
|
+
/** Filter by bullet type (e.g. `"FMJ"`, `"JHP"`). */
|
|
2402
|
+
bullet_type?: string;
|
|
2403
|
+
/** Filter by common status (`0` = uncommon, `1` = common). */
|
|
2404
|
+
is_common?: 0 | 1;
|
|
2405
|
+
}
|
|
2406
|
+
/**
|
|
2407
|
+
* Parameters for `GET /v1/ammunition/:id/ballistics`.
|
|
2408
|
+
*/
|
|
2409
|
+
interface AmmunitionBallisticsParams {
|
|
2410
|
+
/**
|
|
2411
|
+
* Barrel length in mm to use for the calculation (50-2000).
|
|
2412
|
+
* If omitted, uses the ammunition's reference barrel length.
|
|
2413
|
+
*/
|
|
2414
|
+
barrel_length_mm?: number;
|
|
2415
|
+
/**
|
|
2416
|
+
* Comma-separated distances in metres for the trajectory table.
|
|
2417
|
+
* If omitted, uses the default set: 0, 50, 100, 200, 300, 400, 500, 600, 800, 1000.
|
|
2418
|
+
*
|
|
2419
|
+
* @example `"0,100,200,300,500"`
|
|
2420
|
+
*/
|
|
2421
|
+
distances?: string;
|
|
2422
|
+
}
|
|
2423
|
+
/**
|
|
2424
|
+
* Parameters for `GET /v1/stats/popular-calibers`.
|
|
2425
|
+
*/
|
|
2426
|
+
interface PopularCalibersParams {
|
|
2427
|
+
/**
|
|
2428
|
+
* Maximum number of results (1-100).
|
|
2429
|
+
* @defaultValue `20`
|
|
2430
|
+
*/
|
|
2431
|
+
limit?: number;
|
|
2432
|
+
}
|
|
2433
|
+
/**
|
|
2434
|
+
* Parameters for `GET /v1/stats/prolific-manufacturers`.
|
|
2435
|
+
*/
|
|
2436
|
+
interface ProlificManufacturersParams {
|
|
2437
|
+
/**
|
|
2438
|
+
* Maximum number of results (1-100).
|
|
2439
|
+
* @defaultValue `20`
|
|
2440
|
+
*/
|
|
2441
|
+
limit?: number;
|
|
2442
|
+
/** Optional category filter. */
|
|
2443
|
+
category?: string;
|
|
2444
|
+
}
|
|
2445
|
+
/**
|
|
2446
|
+
* Parameters for `GET /v1/stats/by-era`.
|
|
2447
|
+
*
|
|
2448
|
+
* @example
|
|
2449
|
+
* ```ts
|
|
2450
|
+
* const params: ByEraParams = { decade: '1990s' };
|
|
2451
|
+
* ```
|
|
2452
|
+
*/
|
|
2453
|
+
interface ByEraParams {
|
|
2454
|
+
/** Decade string in format `"1990s"`, `"2000s"`, etc. */
|
|
2455
|
+
decade: string;
|
|
2456
|
+
}
|
|
2457
|
+
/**
|
|
2458
|
+
* Parameters for `GET /v1/stats/adoption/country`.
|
|
2459
|
+
*/
|
|
2460
|
+
interface AdoptionByCountryParams {
|
|
2461
|
+
/** ISO 3166-1 country code. */
|
|
2462
|
+
code: string;
|
|
2463
|
+
}
|
|
2464
|
+
/**
|
|
2465
|
+
* Parameters for `GET /v1/stats/adoption/type`.
|
|
2466
|
+
*/
|
|
2467
|
+
interface AdoptionByTypeParams {
|
|
2468
|
+
/** User type to query. */
|
|
2469
|
+
type: 'military' | 'law_enforcement' | 'civilian' | 'paramilitary' | 'special_forces' | 'private_security' | 'training';
|
|
2470
|
+
}
|
|
2471
|
+
/**
|
|
2472
|
+
* Parameters for `GET /v1/stats/action-types`.
|
|
2473
|
+
*/
|
|
2474
|
+
interface ActionTypesParams {
|
|
2475
|
+
/** Optional category filter. */
|
|
2476
|
+
category?: string;
|
|
2477
|
+
}
|
|
2478
|
+
/**
|
|
2479
|
+
* Parameters for `GET /v1/stats/feature-frequency`.
|
|
2480
|
+
*/
|
|
2481
|
+
interface FeatureFrequencyParams {
|
|
2482
|
+
/** Optional category filter. */
|
|
2483
|
+
category?: string;
|
|
2484
|
+
/**
|
|
2485
|
+
* Maximum number of results (1-100).
|
|
2486
|
+
* @defaultValue `50`
|
|
2487
|
+
*/
|
|
2488
|
+
limit?: number;
|
|
2489
|
+
}
|
|
2490
|
+
/**
|
|
2491
|
+
* Parameters for `GET /v1/stats/caliber-popularity-by-era`.
|
|
2492
|
+
*/
|
|
2493
|
+
interface CaliberPopularityByEraParams {
|
|
2494
|
+
/** Starting decade (inclusive, e.g. `"1950s"`). */
|
|
2495
|
+
from_decade?: string;
|
|
2496
|
+
/** Ending decade (inclusive, e.g. `"2020s"`). */
|
|
2497
|
+
to_decade?: string;
|
|
2498
|
+
}
|
|
2499
|
+
/**
|
|
2500
|
+
* Parameters for `GET /v1/game/balance`.
|
|
2501
|
+
*/
|
|
2502
|
+
interface BalanceReportParams {
|
|
2503
|
+
/**
|
|
2504
|
+
* Z-score threshold for flagging outliers (0-100).
|
|
2505
|
+
* @defaultValue `20`
|
|
2506
|
+
*/
|
|
2507
|
+
threshold?: number;
|
|
2508
|
+
}
|
|
2509
|
+
/**
|
|
2510
|
+
* Parameters for `GET /v1/game/tier-list`.
|
|
2511
|
+
*/
|
|
2512
|
+
interface TierListParams {
|
|
2513
|
+
/** Optional category filter. */
|
|
2514
|
+
category?: string;
|
|
2515
|
+
/**
|
|
2516
|
+
* Stat to rank by.
|
|
2517
|
+
* @defaultValue `"damage"`
|
|
2518
|
+
*/
|
|
2519
|
+
stat?: 'damage' | 'accuracy' | 'range' | 'fireRate' | 'mobility' | 'recoilControl' | 'reloadSpeed' | 'concealment';
|
|
2520
|
+
}
|
|
2521
|
+
/**
|
|
2522
|
+
* Parameters for `GET /v1/game/matchups`.
|
|
2523
|
+
*/
|
|
2524
|
+
interface MatchupsParams {
|
|
2525
|
+
/** Slug of firearm A. */
|
|
2526
|
+
a: string;
|
|
2527
|
+
/** Slug of firearm B. */
|
|
2528
|
+
b: string;
|
|
2529
|
+
}
|
|
2530
|
+
/**
|
|
2531
|
+
* Parameters for `GET /v1/game/role-roster`.
|
|
2532
|
+
*/
|
|
2533
|
+
interface RoleRosterParams {
|
|
2534
|
+
/** The role to build a roster for. */
|
|
2535
|
+
role: 'sniper' | 'assault' | 'tank' | 'support' | 'stealth' | 'speedster';
|
|
2536
|
+
/**
|
|
2537
|
+
* Number of firearms to return (1-25).
|
|
2538
|
+
* @defaultValue `5`
|
|
2539
|
+
*/
|
|
2540
|
+
count?: number;
|
|
2541
|
+
}
|
|
2542
|
+
/**
|
|
2543
|
+
* Parameters for `GET /v1/game/stat-distribution`.
|
|
2544
|
+
*/
|
|
2545
|
+
interface StatDistributionParams {
|
|
2546
|
+
/** The game stat to analyse. */
|
|
2547
|
+
stat: 'damage' | 'accuracy' | 'range' | 'fireRate' | 'mobility' | 'recoilControl' | 'reloadSpeed' | 'concealment';
|
|
2548
|
+
}
|
|
2549
|
+
/**
|
|
2550
|
+
* Parameters for `GET /v1/game-stats/:version/firearms`.
|
|
2551
|
+
*/
|
|
2552
|
+
interface ListSnapshotFirearmsParams extends PaginationParams {
|
|
2553
|
+
}
|
|
2554
|
+
/**
|
|
2555
|
+
* Parameters for `GET /v1/data/confidence`.
|
|
2556
|
+
*/
|
|
2557
|
+
interface ConfidenceParams extends PaginationParams {
|
|
2558
|
+
/**
|
|
2559
|
+
* Return firearms with confidence below this threshold (0.0-1.0).
|
|
2560
|
+
* @defaultValue `0.5`
|
|
2561
|
+
*/
|
|
2562
|
+
below?: number;
|
|
2563
|
+
}
|
|
2564
|
+
/**
|
|
2565
|
+
* Parameters for `GET /v1/firearms/:id/silhouette`.
|
|
2566
|
+
*/
|
|
2567
|
+
interface SilhouetteParams {
|
|
2568
|
+
/** Output format: `"svg"` (raw), `"datauri"` (base64), or `"json"` (metadata). */
|
|
2569
|
+
format?: 'svg' | 'datauri' | 'json';
|
|
2570
|
+
/** Stroke width in pixels. */
|
|
2571
|
+
stroke_width?: number;
|
|
2572
|
+
/** Stroke color (CSS color string). */
|
|
2573
|
+
stroke_color?: string;
|
|
2574
|
+
}
|
|
2575
|
+
/**
|
|
2576
|
+
* Parameters for `GET /v1/me/favorites`.
|
|
2577
|
+
*/
|
|
2578
|
+
interface ListFavoritesParams {
|
|
2579
|
+
/** Page number (1-based). */
|
|
2580
|
+
page?: number;
|
|
2581
|
+
/** Items per page (1-100). */
|
|
2582
|
+
limit?: number;
|
|
2583
|
+
}
|
|
2584
|
+
/**
|
|
2585
|
+
* Body for `POST /v1/me/reports`.
|
|
2586
|
+
*/
|
|
2587
|
+
interface CreateReportParams {
|
|
2588
|
+
/** Firearm slug to report on. */
|
|
2589
|
+
firearmId: string;
|
|
2590
|
+
/** Section of the firearm data. */
|
|
2591
|
+
section: 'game-stats' | 'specs' | 'ballistics' | 'barrel' | 'materials' | 'operating' | 'calibers' | 'users' | 'description';
|
|
2592
|
+
/** Type of data issue. */
|
|
2593
|
+
issueType: 'incorrect' | 'missing' | 'outdated';
|
|
2594
|
+
/** Description of the issue (10-2000 chars). */
|
|
2595
|
+
description: string;
|
|
2596
|
+
/** Optional reference URLs (max 5). */
|
|
2597
|
+
references?: string[];
|
|
2598
|
+
/** Optional suggested correction (max 1000 chars). */
|
|
2599
|
+
suggestedValue?: string;
|
|
2600
|
+
}
|
|
2601
|
+
/**
|
|
2602
|
+
* Parameters for `GET /v1/me/reports`.
|
|
2603
|
+
*/
|
|
2604
|
+
interface ListReportsParams {
|
|
2605
|
+
/** Page number (1-based). */
|
|
2606
|
+
page?: number;
|
|
2607
|
+
/** Items per page (1-100). */
|
|
2608
|
+
per_page?: number;
|
|
2609
|
+
}
|
|
2610
|
+
/**
|
|
2611
|
+
* Body for `POST /v1/me/support`.
|
|
2612
|
+
*/
|
|
2613
|
+
interface CreateTicketParams {
|
|
2614
|
+
/** Ticket subject (1-200 chars). */
|
|
2615
|
+
subject: string;
|
|
2616
|
+
/** Ticket description (1-5000 chars). */
|
|
2617
|
+
description: string;
|
|
2618
|
+
/** Ticket category. */
|
|
2619
|
+
category?: 'billing' | 'technical' | 'data_quality' | 'feature_request' | 'other';
|
|
2620
|
+
/** Priority level. */
|
|
2621
|
+
priority?: 'low' | 'normal' | 'high' | 'urgent';
|
|
2622
|
+
}
|
|
2623
|
+
/**
|
|
2624
|
+
* Parameters for `GET /v1/me/support`.
|
|
2625
|
+
*/
|
|
2626
|
+
interface ListTicketsParams {
|
|
2627
|
+
/** Page number (1-based). */
|
|
2628
|
+
page?: number;
|
|
2629
|
+
/** Items per page (1-100). */
|
|
2630
|
+
per_page?: number;
|
|
2631
|
+
/** Filter by status. */
|
|
2632
|
+
status?: 'open' | 'in_progress' | 'waiting' | 'resolved' | 'closed';
|
|
2633
|
+
/** Sort column. */
|
|
2634
|
+
sort?: 'created_at' | 'updated_at' | 'status' | 'priority';
|
|
2635
|
+
/** Sort direction. */
|
|
2636
|
+
order?: 'asc' | 'desc';
|
|
2637
|
+
}
|
|
2638
|
+
/**
|
|
2639
|
+
* Body for `POST /v1/me/support/:ticketId/replies`.
|
|
2640
|
+
*/
|
|
2641
|
+
interface CreateReplyParams {
|
|
2642
|
+
/** Reply message (1-5000 chars). */
|
|
2643
|
+
message: string;
|
|
2644
|
+
}
|
|
2645
|
+
/**
|
|
2646
|
+
* Body for `POST /v1/me/webhooks`.
|
|
2647
|
+
*/
|
|
2648
|
+
interface CreateWebhookEndpointParams {
|
|
2649
|
+
/** Delivery URL. */
|
|
2650
|
+
url: string;
|
|
2651
|
+
/** Optional description. */
|
|
2652
|
+
description?: string;
|
|
2653
|
+
/** Event types to subscribe to (at least one). */
|
|
2654
|
+
events: string[];
|
|
2655
|
+
}
|
|
2656
|
+
/**
|
|
2657
|
+
* Body for `PUT /v1/me/webhooks/:id`.
|
|
2658
|
+
*/
|
|
2659
|
+
interface UpdateWebhookEndpointParams {
|
|
2660
|
+
/** New delivery URL. */
|
|
2661
|
+
url?: string;
|
|
2662
|
+
/** Updated description. */
|
|
2663
|
+
description?: string | null;
|
|
2664
|
+
/** Updated event subscriptions. */
|
|
2665
|
+
events?: string[];
|
|
2666
|
+
/** Whether the endpoint is active. */
|
|
2667
|
+
active?: boolean;
|
|
2668
|
+
}
|
|
2669
|
+
/**
|
|
2670
|
+
* Parameters for `GET /v1/me/webhooks`.
|
|
2671
|
+
*/
|
|
2672
|
+
interface ListWebhookEndpointsParams {
|
|
2673
|
+
/** Page number (1-based). */
|
|
2674
|
+
page?: number;
|
|
2675
|
+
/** Items per page (1-100). */
|
|
2676
|
+
per_page?: number;
|
|
2677
|
+
}
|
|
2678
|
+
/**
|
|
2679
|
+
* Parameters for `GET /v1/me/usage`.
|
|
2680
|
+
*/
|
|
2681
|
+
interface UsageParams {
|
|
2682
|
+
/** Month in YYYY-MM format. */
|
|
2683
|
+
month?: string;
|
|
2684
|
+
/** Number of days for daily breakdown (1-90). */
|
|
2685
|
+
days?: number;
|
|
2686
|
+
}
|
|
2687
|
+
|
|
2688
|
+
/**
|
|
2689
|
+
* The error object nested inside an {@link APIErrorResponse}.
|
|
2690
|
+
*
|
|
2691
|
+
* @example
|
|
2692
|
+
* ```ts
|
|
2693
|
+
* const body: ErrorBody = {
|
|
2694
|
+
* code: 'NOT_FOUND',
|
|
2695
|
+
* message: "Firearm 'nonexistent-slug' not found",
|
|
2696
|
+
* };
|
|
2697
|
+
* ```
|
|
2698
|
+
*/
|
|
2699
|
+
interface ErrorBody {
|
|
2700
|
+
/**
|
|
2701
|
+
* Machine-readable error code.
|
|
2702
|
+
*
|
|
2703
|
+
* Known codes:
|
|
2704
|
+
* - `"NOT_FOUND"` -- Resource does not exist (HTTP 404).
|
|
2705
|
+
* - `"UNAUTHORIZED"` -- Authentication required (HTTP 401).
|
|
2706
|
+
* - `"FORBIDDEN"` -- Insufficient permissions (HTTP 403).
|
|
2707
|
+
* - `"RATE_LIMITED"` -- Too many requests (HTTP 429).
|
|
2708
|
+
* - `"VALIDATION_ERROR"` -- Request parameters failed validation (HTTP 400).
|
|
2709
|
+
*/
|
|
2710
|
+
code: string;
|
|
2711
|
+
/** Human-readable error message. */
|
|
2712
|
+
message: string;
|
|
2713
|
+
/**
|
|
2714
|
+
* Optional validation details.
|
|
2715
|
+
*
|
|
2716
|
+
* Present on `VALIDATION_ERROR` responses; shape varies by endpoint.
|
|
2717
|
+
*/
|
|
2718
|
+
details?: Record<string, unknown>;
|
|
2719
|
+
}
|
|
2720
|
+
/**
|
|
2721
|
+
* Standard API error response envelope.
|
|
2722
|
+
*
|
|
2723
|
+
* All non-2xx responses from the GunSpec.io API return this shape.
|
|
2724
|
+
*
|
|
2725
|
+
* @example
|
|
2726
|
+
* ```ts
|
|
2727
|
+
* // 404 response body
|
|
2728
|
+
* const response: APIErrorResponse = {
|
|
2729
|
+
* success: false,
|
|
2730
|
+
* error: {
|
|
2731
|
+
* code: 'NOT_FOUND',
|
|
2732
|
+
* message: "Firearm 'nonexistent-slug' not found",
|
|
2733
|
+
* },
|
|
2734
|
+
* };
|
|
2735
|
+
* ```
|
|
2736
|
+
*/
|
|
2737
|
+
interface APIErrorResponse {
|
|
2738
|
+
/** Always `false` for error responses. */
|
|
2739
|
+
success: false;
|
|
2740
|
+
/** The error details. */
|
|
2741
|
+
error: ErrorBody;
|
|
2742
|
+
}
|
|
2743
|
+
|
|
2744
|
+
/**
|
|
2745
|
+
* Firearms resource for the GunSpec SDK.
|
|
2746
|
+
*
|
|
2747
|
+
* Provides access to all `/v1/firearms` endpoints including listing,
|
|
2748
|
+
* searching, comparing, filtering, and retrieving individual firearm
|
|
2749
|
+
* details with sub-resources (images, variants, game stats, etc.).
|
|
2750
|
+
*
|
|
2751
|
+
* @module
|
|
2752
|
+
*/
|
|
2753
|
+
|
|
2754
|
+
/**
|
|
2755
|
+
* Resource class for interacting with the GunSpec Firearms API.
|
|
2756
|
+
*
|
|
2757
|
+
* Wraps all `/v1/firearms` endpoints. Instantiated internally by the
|
|
2758
|
+
* {@link GunSpec} client and exposed as `client.firearms`.
|
|
2759
|
+
*
|
|
2760
|
+
* @example
|
|
2761
|
+
* ```typescript
|
|
2762
|
+
* import GunSpec from '@gunspec/sdk';
|
|
2763
|
+
*
|
|
2764
|
+
* const client = new GunSpec();
|
|
2765
|
+
*
|
|
2766
|
+
* // List firearms with filters
|
|
2767
|
+
* const { data, pagination } = await client.firearms.list({
|
|
2768
|
+
* manufacturer: 'glock',
|
|
2769
|
+
* category: 'pistol',
|
|
2770
|
+
* per_page: 10,
|
|
2771
|
+
* });
|
|
2772
|
+
*
|
|
2773
|
+
* // Get a single firearm by slug
|
|
2774
|
+
* const { data: firearm } = await client.firearms.get('glock-g17');
|
|
2775
|
+
* ```
|
|
2776
|
+
*/
|
|
2777
|
+
declare class FirearmsResource {
|
|
2778
|
+
private readonly client;
|
|
2779
|
+
constructor(client: HttpClient);
|
|
2780
|
+
/**
|
|
2781
|
+
* List firearms with optional filters and pagination.
|
|
2782
|
+
*
|
|
2783
|
+
* @param params - Optional query parameters for filtering, sorting, and pagination.
|
|
2784
|
+
* @returns A paginated list of firearms matching the given filters.
|
|
2785
|
+
* @throws {BadRequestError} If any filter value is invalid.
|
|
2786
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
2787
|
+
*
|
|
2788
|
+
* @example
|
|
2789
|
+
* ```typescript
|
|
2790
|
+
* const result = await client.firearms.list({
|
|
2791
|
+
* manufacturer: 'beretta',
|
|
2792
|
+
* status: 'in_production',
|
|
2793
|
+
* sort: 'name',
|
|
2794
|
+
* order: 'asc',
|
|
2795
|
+
* page: 1,
|
|
2796
|
+
* per_page: 25,
|
|
2797
|
+
* });
|
|
2798
|
+
* console.log(result.data); // Firearm[]
|
|
2799
|
+
* console.log(result.pagination.totalPages);
|
|
2800
|
+
* ```
|
|
2801
|
+
*/
|
|
2802
|
+
list(params?: ListFirearmsParams): Promise<PaginatedResponse<Firearm>>;
|
|
2803
|
+
/**
|
|
2804
|
+
* Auto-paginate through all firearms matching the given filters.
|
|
2805
|
+
*
|
|
2806
|
+
* Returns an async iterator that fetches pages on demand, yielding
|
|
2807
|
+
* individual {@link Firearm} objects. Useful for processing large
|
|
2808
|
+
* result sets without managing pagination manually.
|
|
2809
|
+
*
|
|
2810
|
+
* @param params - Optional query parameters for filtering and sorting.
|
|
2811
|
+
* @returns An async iterable iterator yielding individual firearms.
|
|
2812
|
+
*
|
|
2813
|
+
* @example
|
|
2814
|
+
* ```typescript
|
|
2815
|
+
* for await (const firearm of client.firearms.listAutoPaging({ manufacturer: 'colt' })) {
|
|
2816
|
+
* console.log(firearm.name);
|
|
2817
|
+
* }
|
|
2818
|
+
* ```
|
|
2819
|
+
*/
|
|
2820
|
+
listAutoPaging(params?: ListFirearmsParams): AsyncIterableIterator<Firearm>;
|
|
2821
|
+
/**
|
|
2822
|
+
* Full-text search across firearms.
|
|
2823
|
+
*
|
|
2824
|
+
* @param params - Search query and pagination parameters.
|
|
2825
|
+
* @returns A paginated list of firearms matching the search query.
|
|
2826
|
+
* @throws {BadRequestError} If the search query is empty or too long.
|
|
2827
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
2828
|
+
*
|
|
2829
|
+
* @example
|
|
2830
|
+
* ```typescript
|
|
2831
|
+
* const result = await client.firearms.search({ q: '9mm compact' });
|
|
2832
|
+
* console.log(result.data.length);
|
|
2833
|
+
* ```
|
|
2834
|
+
*/
|
|
2835
|
+
search(params: SearchFirearmsParams): Promise<PaginatedResponse<Firearm>>;
|
|
2836
|
+
/**
|
|
2837
|
+
* Compare up to 5 firearms side by side.
|
|
2838
|
+
*
|
|
2839
|
+
* @param params - Object containing comma-separated firearm IDs.
|
|
2840
|
+
* @returns An array of firearms with full details for comparison.
|
|
2841
|
+
* @throws {BadRequestError} If more than 5 IDs are provided or any ID is invalid.
|
|
2842
|
+
* @throws {NotFoundError} If any of the specified firearms do not exist.
|
|
2843
|
+
*
|
|
2844
|
+
* @example
|
|
2845
|
+
* ```typescript
|
|
2846
|
+
* const { data } = await client.firearms.compare({ ids: 'glock-g17,sig-sauer-p320,beretta-92fs' });
|
|
2847
|
+
* console.log(data.items.length); // 3
|
|
2848
|
+
* ```
|
|
2849
|
+
*/
|
|
2850
|
+
compare(params: CompareFirearmsParams): Promise<APIResponse<FirearmComparison>>;
|
|
2851
|
+
/**
|
|
2852
|
+
* Retrieve game metadata for firearms (archetypes, stat ranges, etc.).
|
|
2853
|
+
*
|
|
2854
|
+
* @param params - Optional archetype filter.
|
|
2855
|
+
* @returns Game metadata including archetype definitions and stat ranges.
|
|
2856
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
2857
|
+
*
|
|
2858
|
+
* @example
|
|
2859
|
+
* ```typescript
|
|
2860
|
+
* const { data } = await client.firearms.gameMeta({ archetype: 'sniper' });
|
|
2861
|
+
* ```
|
|
2862
|
+
*/
|
|
2863
|
+
gameMeta(params?: GameMetaParams): Promise<APIResponse<GameMetaItem[]>>;
|
|
2864
|
+
/**
|
|
2865
|
+
* List all known action types across the database.
|
|
2866
|
+
*
|
|
2867
|
+
* @returns An array of distinct action type strings.
|
|
2868
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
2869
|
+
*
|
|
2870
|
+
* @example
|
|
2871
|
+
* ```typescript
|
|
2872
|
+
* const { data } = await client.firearms.actionTypes();
|
|
2873
|
+
* // ['Semi-automatic', 'Bolt action', 'Lever action', ...]
|
|
2874
|
+
* ```
|
|
2875
|
+
*/
|
|
2876
|
+
actionTypes(): Promise<APIResponse<ActionTypeStats[]>>;
|
|
2877
|
+
/**
|
|
2878
|
+
* Get available filter options for the firearms list endpoint.
|
|
2879
|
+
*
|
|
2880
|
+
* Returns distinct values for manufacturers, calibers, categories,
|
|
2881
|
+
* action types, countries, and statuses that can be used as filter values.
|
|
2882
|
+
*
|
|
2883
|
+
* @returns An object mapping filter fields to their available values.
|
|
2884
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
2885
|
+
*
|
|
2886
|
+
* @example
|
|
2887
|
+
* ```typescript
|
|
2888
|
+
* const { data } = await client.firearms.filterOptions();
|
|
2889
|
+
* console.log(data.manufacturers); // ['beretta', 'colt', ...]
|
|
2890
|
+
* console.log(data.categories); // ['pistol', 'rifle', ...]
|
|
2891
|
+
* ```
|
|
2892
|
+
*/
|
|
2893
|
+
filterOptions(): Promise<APIResponse<FilterOptions>>;
|
|
2894
|
+
/**
|
|
2895
|
+
* Get a random firearm, optionally filtered by category or country.
|
|
2896
|
+
*
|
|
2897
|
+
* @param params - Optional category and country filters.
|
|
2898
|
+
* @returns A single randomly selected firearm.
|
|
2899
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
2900
|
+
*
|
|
2901
|
+
* @example
|
|
2902
|
+
* ```typescript
|
|
2903
|
+
* const { data } = await client.firearms.random({ category: 'pistol' });
|
|
2904
|
+
* console.log(data.name);
|
|
2905
|
+
* ```
|
|
2906
|
+
*/
|
|
2907
|
+
random(params?: RandomFirearmParams): Promise<APIResponse<Firearm>>;
|
|
2908
|
+
/**
|
|
2909
|
+
* Get top firearms ranked by a specific statistic.
|
|
2910
|
+
*
|
|
2911
|
+
* @param params - The stat to rank by and optional category/limit filters.
|
|
2912
|
+
* @returns An ordered array of firearms ranked by the specified stat.
|
|
2913
|
+
* @throws {BadRequestError} If the stat value is not a recognized ranking metric.
|
|
2914
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
2915
|
+
*
|
|
2916
|
+
* @example
|
|
2917
|
+
* ```typescript
|
|
2918
|
+
* const { data } = await client.firearms.top({
|
|
2919
|
+
* stat: 'lightest',
|
|
2920
|
+
* category: 'pistol',
|
|
2921
|
+
* limit: 5,
|
|
2922
|
+
* });
|
|
2923
|
+
* ```
|
|
2924
|
+
*/
|
|
2925
|
+
top(params: TopFirearmsParams): Promise<APIResponse<Firearm[]>>;
|
|
2926
|
+
/**
|
|
2927
|
+
* Compare two firearms in a head-to-head matchup.
|
|
2928
|
+
*
|
|
2929
|
+
* @param params - The slugs of the two firearms to compare.
|
|
2930
|
+
* @returns A detailed head-to-head comparison with per-stat breakdowns.
|
|
2931
|
+
* @throws {NotFoundError} If either firearm does not exist.
|
|
2932
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
2933
|
+
*
|
|
2934
|
+
* @example
|
|
2935
|
+
* ```typescript
|
|
2936
|
+
* const { data } = await client.firearms.headToHead({ a: 'glock-g17', b: 'sig-sauer-p320' });
|
|
2937
|
+
* console.log(data.winner);
|
|
2938
|
+
* ```
|
|
2939
|
+
*/
|
|
2940
|
+
headToHead(params: HeadToHeadParams): Promise<APIResponse<HeadToHead>>;
|
|
2941
|
+
/**
|
|
2942
|
+
* Filter firearms by a specific feature.
|
|
2943
|
+
*
|
|
2944
|
+
* @param params - The feature name and optional category filter with pagination.
|
|
2945
|
+
* @returns A paginated list of firearms that have the specified feature.
|
|
2946
|
+
* @throws {BadRequestError} If the feature name is empty.
|
|
2947
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
2948
|
+
*
|
|
2949
|
+
* @example
|
|
2950
|
+
* ```typescript
|
|
2951
|
+
* const result = await client.firearms.byFeature({ feature: 'threaded-barrel' });
|
|
2952
|
+
* ```
|
|
2953
|
+
*/
|
|
2954
|
+
byFeature(params: ByFeatureParams): Promise<PaginatedResponse<Firearm>>;
|
|
2955
|
+
/**
|
|
2956
|
+
* Filter firearms by action type.
|
|
2957
|
+
*
|
|
2958
|
+
* @param params - The action type string with pagination.
|
|
2959
|
+
* @returns A paginated list of firearms with the specified action type.
|
|
2960
|
+
* @throws {BadRequestError} If the action type is empty.
|
|
2961
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
2962
|
+
*
|
|
2963
|
+
* @example
|
|
2964
|
+
* ```typescript
|
|
2965
|
+
* const result = await client.firearms.byAction({ action: 'semi-automatic' });
|
|
2966
|
+
* ```
|
|
2967
|
+
*/
|
|
2968
|
+
byAction(params: ByActionParams): Promise<PaginatedResponse<Firearm>>;
|
|
2969
|
+
/**
|
|
2970
|
+
* Filter firearms by frame/component material.
|
|
2971
|
+
*
|
|
2972
|
+
* @param params - The material name, component type, and pagination.
|
|
2973
|
+
* @returns A paginated list of firearms using the specified material.
|
|
2974
|
+
* @throws {BadRequestError} If the material or component is invalid.
|
|
2975
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
2976
|
+
*
|
|
2977
|
+
* @example
|
|
2978
|
+
* ```typescript
|
|
2979
|
+
* const result = await client.firearms.byMaterial({
|
|
2980
|
+
* material: 'polymer',
|
|
2981
|
+
* component: 'frame',
|
|
2982
|
+
* });
|
|
2983
|
+
* ```
|
|
2984
|
+
*/
|
|
2985
|
+
byMaterial(params: ByMaterialParams): Promise<PaginatedResponse<Firearm>>;
|
|
2986
|
+
/**
|
|
2987
|
+
* Filter firearms by designer name.
|
|
2988
|
+
*
|
|
2989
|
+
* @param params - The designer name string with pagination.
|
|
2990
|
+
* @returns A paginated list of firearms designed by the specified person.
|
|
2991
|
+
* @throws {BadRequestError} If the designer name is empty.
|
|
2992
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
2993
|
+
*
|
|
2994
|
+
* @example
|
|
2995
|
+
* ```typescript
|
|
2996
|
+
* const result = await client.firearms.byDesigner({ designer: 'John Browning' });
|
|
2997
|
+
* ```
|
|
2998
|
+
*/
|
|
2999
|
+
byDesigner(params: ByDesignerParams): Promise<PaginatedResponse<Firearm>>;
|
|
3000
|
+
/**
|
|
3001
|
+
* Get firearms ranked by computed power rating.
|
|
3002
|
+
*
|
|
3003
|
+
* @param params - Optional category filter with pagination.
|
|
3004
|
+
* @returns A paginated list of firearms with their power ratings.
|
|
3005
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3006
|
+
*
|
|
3007
|
+
* @example
|
|
3008
|
+
* ```typescript
|
|
3009
|
+
* const result = await client.firearms.powerRating({ category: 'rifle' });
|
|
3010
|
+
* for (const item of result.data) {
|
|
3011
|
+
* console.log(`${item.name}: ${item.rating}`);
|
|
3012
|
+
* }
|
|
3013
|
+
* ```
|
|
3014
|
+
*/
|
|
3015
|
+
powerRating(params?: PowerRatingParams): Promise<PaginatedResponse<PowerRating>>;
|
|
3016
|
+
/**
|
|
3017
|
+
* Get firearms arranged in a chronological timeline.
|
|
3018
|
+
*
|
|
3019
|
+
* @param params - Optional year range, category filter, and pagination.
|
|
3020
|
+
* @returns A paginated list of firearms ordered by introduction date.
|
|
3021
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3022
|
+
*
|
|
3023
|
+
* @example
|
|
3024
|
+
* ```typescript
|
|
3025
|
+
* const result = await client.firearms.timeline({ from: 1900, to: 1950 });
|
|
3026
|
+
* ```
|
|
3027
|
+
*/
|
|
3028
|
+
timeline(params?: TimelineParams): Promise<PaginatedResponse<Firearm>>;
|
|
3029
|
+
/**
|
|
3030
|
+
* Filter firearms by military conflict.
|
|
3031
|
+
*
|
|
3032
|
+
* @param params - The conflict identifier string with pagination.
|
|
3033
|
+
* @returns A paginated list of firearms used in the specified conflict.
|
|
3034
|
+
* @throws {BadRequestError} If the conflict name is empty.
|
|
3035
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3036
|
+
*
|
|
3037
|
+
* @example
|
|
3038
|
+
* ```typescript
|
|
3039
|
+
* const result = await client.firearms.byConflict({ conflict: 'world-war-ii' });
|
|
3040
|
+
* ```
|
|
3041
|
+
*/
|
|
3042
|
+
byConflict(params: ByConflictParams): Promise<PaginatedResponse<Firearm>>;
|
|
3043
|
+
/**
|
|
3044
|
+
* Get a single firearm by its slug or ID.
|
|
3045
|
+
*
|
|
3046
|
+
* @param id - The firearm slug (e.g. `"glock-g17"`) or numeric ID.
|
|
3047
|
+
* @returns The full firearm record with all available fields.
|
|
3048
|
+
* @throws {NotFoundError} If no firearm matches the given identifier.
|
|
3049
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3050
|
+
*
|
|
3051
|
+
* @example
|
|
3052
|
+
* ```typescript
|
|
3053
|
+
* const { data } = await client.firearms.get('beretta-92fs');
|
|
3054
|
+
* console.log(data.name); // "Beretta 92FS"
|
|
3055
|
+
* console.log(data.manufacturerId); // "beretta"
|
|
3056
|
+
* ```
|
|
3057
|
+
*/
|
|
3058
|
+
get(id: string): Promise<APIResponse<Firearm>>;
|
|
3059
|
+
/**
|
|
3060
|
+
* Get all variants of a firearm.
|
|
3061
|
+
*
|
|
3062
|
+
* @param id - The parent firearm slug or ID.
|
|
3063
|
+
* @returns An array of variant firearms derived from the parent.
|
|
3064
|
+
* @throws {NotFoundError} If the parent firearm does not exist.
|
|
3065
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3066
|
+
*
|
|
3067
|
+
* @example
|
|
3068
|
+
* ```typescript
|
|
3069
|
+
* const { data } = await client.firearms.getVariants('colt-1911');
|
|
3070
|
+
* console.log(data.map(v => v.name));
|
|
3071
|
+
* ```
|
|
3072
|
+
*/
|
|
3073
|
+
getVariants(id: string): Promise<APIResponse<Firearm[]>>;
|
|
3074
|
+
/**
|
|
3075
|
+
* Get images for a firearm.
|
|
3076
|
+
*
|
|
3077
|
+
* @param id - The firearm slug or ID.
|
|
3078
|
+
* @returns An array of image records with URLs, dimensions, and metadata.
|
|
3079
|
+
* @throws {NotFoundError} If the firearm does not exist.
|
|
3080
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3081
|
+
*
|
|
3082
|
+
* @example
|
|
3083
|
+
* ```typescript
|
|
3084
|
+
* const { data } = await client.firearms.getImages('sig-sauer-p226');
|
|
3085
|
+
* for (const img of data) {
|
|
3086
|
+
* console.log(img.url, img.width, img.height);
|
|
3087
|
+
* }
|
|
3088
|
+
* ```
|
|
3089
|
+
*/
|
|
3090
|
+
getImages(id: string): Promise<APIResponse<FirearmImage[]>>;
|
|
3091
|
+
/**
|
|
3092
|
+
* Get computed game statistics for a firearm.
|
|
3093
|
+
*
|
|
3094
|
+
* @param id - The firearm slug or ID.
|
|
3095
|
+
* @returns Game-balanced stats including damage, accuracy, range, etc.
|
|
3096
|
+
* @throws {NotFoundError} If the firearm does not exist.
|
|
3097
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3098
|
+
*
|
|
3099
|
+
* @example
|
|
3100
|
+
* ```typescript
|
|
3101
|
+
* const { data } = await client.firearms.getGameStats('ak-47');
|
|
3102
|
+
* console.log(data.damage, data.accuracy, data.range);
|
|
3103
|
+
* ```
|
|
3104
|
+
*/
|
|
3105
|
+
getGameStats(id: string): Promise<APIResponse<GameStats>>;
|
|
3106
|
+
/**
|
|
3107
|
+
* Get physical dimensions for a firearm.
|
|
3108
|
+
*
|
|
3109
|
+
* @param id - The firearm slug or ID.
|
|
3110
|
+
* @returns Detailed dimension data (length, height, width, barrel length, weight).
|
|
3111
|
+
* @throws {NotFoundError} If the firearm does not exist.
|
|
3112
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3113
|
+
*
|
|
3114
|
+
* @example
|
|
3115
|
+
* ```typescript
|
|
3116
|
+
* const { data } = await client.firearms.getDimensions('glock-g19');
|
|
3117
|
+
* console.log(`${data.overallLengthMm}mm overall`);
|
|
3118
|
+
* ```
|
|
3119
|
+
*/
|
|
3120
|
+
getDimensions(id: string): Promise<APIResponse<Dimensions>>;
|
|
3121
|
+
/**
|
|
3122
|
+
* Get known military/law-enforcement adopters of a firearm.
|
|
3123
|
+
*
|
|
3124
|
+
* @param id - The firearm slug or ID.
|
|
3125
|
+
* @returns An array of users/adopters with country and organization data.
|
|
3126
|
+
* @throws {NotFoundError} If the firearm does not exist.
|
|
3127
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3128
|
+
*
|
|
3129
|
+
* @example
|
|
3130
|
+
* ```typescript
|
|
3131
|
+
* const { data } = await client.firearms.getUsers('beretta-m9');
|
|
3132
|
+
* for (const user of data) {
|
|
3133
|
+
* console.log(user.country, user.organization);
|
|
3134
|
+
* }
|
|
3135
|
+
* ```
|
|
3136
|
+
*/
|
|
3137
|
+
getUsers(id: string): Promise<APIResponse<FirearmUser[]>>;
|
|
3138
|
+
/**
|
|
3139
|
+
* Get the family tree (lineage) of a firearm.
|
|
3140
|
+
*
|
|
3141
|
+
* @param id - The firearm slug or ID.
|
|
3142
|
+
* @returns A tree structure showing predecessors, descendants, and related models.
|
|
3143
|
+
* @throws {NotFoundError} If the firearm does not exist.
|
|
3144
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3145
|
+
*
|
|
3146
|
+
* @example
|
|
3147
|
+
* ```typescript
|
|
3148
|
+
* const { data } = await client.firearms.getFamilyTree('m16a2');
|
|
3149
|
+
* console.log(data.ancestors, data.descendants);
|
|
3150
|
+
* ```
|
|
3151
|
+
*/
|
|
3152
|
+
getFamilyTree(id: string): Promise<APIResponse<FamilyTree>>;
|
|
3153
|
+
/**
|
|
3154
|
+
* Get firearms similar to a given firearm.
|
|
3155
|
+
*
|
|
3156
|
+
* @param id - The firearm slug or ID.
|
|
3157
|
+
* @returns An array of similar firearms ranked by similarity score.
|
|
3158
|
+
* @throws {NotFoundError} If the firearm does not exist.
|
|
3159
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3160
|
+
*
|
|
3161
|
+
* @example
|
|
3162
|
+
* ```typescript
|
|
3163
|
+
* const { data } = await client.firearms.getSimilar('glock-g17');
|
|
3164
|
+
* for (const match of data) {
|
|
3165
|
+
* console.log(match.name, match.similarityScore);
|
|
3166
|
+
* }
|
|
3167
|
+
* ```
|
|
3168
|
+
*/
|
|
3169
|
+
getSimilar(id: string): Promise<APIResponse<SimilarFirearm[]>>;
|
|
3170
|
+
/**
|
|
3171
|
+
* Get the worldwide adoption map for a firearm.
|
|
3172
|
+
*
|
|
3173
|
+
* @param id - The firearm slug or ID.
|
|
3174
|
+
* @returns Adoption data by country with usage type and date ranges.
|
|
3175
|
+
* @throws {NotFoundError} If the firearm does not exist.
|
|
3176
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3177
|
+
*
|
|
3178
|
+
* @example
|
|
3179
|
+
* ```typescript
|
|
3180
|
+
* const { data } = await client.firearms.getAdoptionMap('fn-fal');
|
|
3181
|
+
* console.log(data.countries.length, 'countries adopted this firearm');
|
|
3182
|
+
* ```
|
|
3183
|
+
*/
|
|
3184
|
+
getAdoptionMap(id: string): Promise<APIResponse<AdoptionMap>>;
|
|
3185
|
+
/**
|
|
3186
|
+
* Get the full game profile for a firearm.
|
|
3187
|
+
*
|
|
3188
|
+
* @param id - The firearm slug or ID.
|
|
3189
|
+
* @returns Game-specific profile including archetype, tier, and stat breakdown.
|
|
3190
|
+
* @throws {NotFoundError} If the firearm does not exist.
|
|
3191
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3192
|
+
*
|
|
3193
|
+
* @example
|
|
3194
|
+
* ```typescript
|
|
3195
|
+
* const { data } = await client.firearms.getGameProfile('mp5');
|
|
3196
|
+
* console.log(data.archetype, data.tier);
|
|
3197
|
+
* ```
|
|
3198
|
+
*/
|
|
3199
|
+
getGameProfile(id: string): Promise<APIResponse<GameProfile>>;
|
|
3200
|
+
/**
|
|
3201
|
+
* Get an SVG silhouette (line art) of a firearm.
|
|
3202
|
+
*
|
|
3203
|
+
* @param id - The firearm slug or ID.
|
|
3204
|
+
* @param params - Optional format and stroke customization parameters.
|
|
3205
|
+
* @returns Silhouette data in the requested format (raw SVG, data URI, or JSON).
|
|
3206
|
+
* @throws {NotFoundError} If the firearm does not exist or has no silhouette.
|
|
3207
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3208
|
+
*
|
|
3209
|
+
* @example
|
|
3210
|
+
* ```typescript
|
|
3211
|
+
* const { data } = await client.firearms.getSilhouette('ak-47', {
|
|
3212
|
+
* format: 'datauri',
|
|
3213
|
+
* stroke_width: 2,
|
|
3214
|
+
* stroke_color: '#333',
|
|
3215
|
+
* });
|
|
3216
|
+
* // Use data.dataUri in an <img> tag
|
|
3217
|
+
* ```
|
|
3218
|
+
*/
|
|
3219
|
+
getSilhouette(id: string, params?: SilhouetteParams): Promise<APIResponse<Silhouette>>;
|
|
3220
|
+
/**
|
|
3221
|
+
* Calculate ballistics for a firearm with specific ammunition.
|
|
3222
|
+
*
|
|
3223
|
+
* @param id - The firearm slug or ID.
|
|
3224
|
+
* @param params - Ammunition ID and optional ballistic parameters.
|
|
3225
|
+
* @returns Calculated ballistic data including velocity, energy, and trajectory.
|
|
3226
|
+
* @throws {NotFoundError} If the firearm or ammunition does not exist.
|
|
3227
|
+
* @throws {BadRequestError} If the ammunition is incompatible with the firearm.
|
|
3228
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3229
|
+
*
|
|
3230
|
+
* @example
|
|
3231
|
+
* ```typescript
|
|
3232
|
+
* const { data } = await client.firearms.calculate('glock-g17', {
|
|
3233
|
+
* ammo_id: '9mm-federal-hst-124gr',
|
|
3234
|
+
* });
|
|
3235
|
+
* console.log(data.muzzleVelocity, data.muzzleEnergy);
|
|
3236
|
+
* ```
|
|
3237
|
+
*/
|
|
3238
|
+
calculate(id: string, params: CalculateBallisticsParams): Promise<APIResponse<FirearmCalculation>>;
|
|
3239
|
+
/**
|
|
3240
|
+
* Load a firearm with ammunition and get combined performance data.
|
|
3241
|
+
*
|
|
3242
|
+
* @param id - The firearm slug or ID.
|
|
3243
|
+
* @param params - Optional ammunition ID to load.
|
|
3244
|
+
* @returns Combined firearm + ammunition data with computed performance metrics.
|
|
3245
|
+
* @throws {NotFoundError} If the firearm does not exist.
|
|
3246
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3247
|
+
*
|
|
3248
|
+
* @example
|
|
3249
|
+
* ```typescript
|
|
3250
|
+
* const { data } = await client.firearms.load('sig-sauer-p226', {
|
|
3251
|
+
* ammo_id: '9mm-winchester-ranger-147gr',
|
|
3252
|
+
* });
|
|
3253
|
+
* ```
|
|
3254
|
+
*/
|
|
3255
|
+
load(id: string, params?: LoadFirearmParams): Promise<APIResponse<FirearmLoadProfile>>;
|
|
3256
|
+
}
|
|
3257
|
+
|
|
3258
|
+
/**
|
|
3259
|
+
* Manufacturers resource for the GunSpec SDK.
|
|
3260
|
+
*
|
|
3261
|
+
* Provides access to all `/v1/manufacturers` endpoints including listing,
|
|
3262
|
+
* retrieving details, and exploring a manufacturer's firearms catalog,
|
|
3263
|
+
* timeline, and statistics.
|
|
3264
|
+
*
|
|
3265
|
+
* @module
|
|
3266
|
+
*/
|
|
3267
|
+
|
|
3268
|
+
/**
|
|
3269
|
+
* Resource class for interacting with the GunSpec Manufacturers API.
|
|
3270
|
+
*
|
|
3271
|
+
* Wraps all `/v1/manufacturers` endpoints. Instantiated internally by the
|
|
3272
|
+
* {@link GunSpec} client and exposed as `client.manufacturers`.
|
|
3273
|
+
*
|
|
3274
|
+
* @example
|
|
3275
|
+
* ```typescript
|
|
3276
|
+
* import GunSpec from '@gunspec/sdk';
|
|
3277
|
+
*
|
|
3278
|
+
* const client = new GunSpec();
|
|
3279
|
+
*
|
|
3280
|
+
* // List manufacturers
|
|
3281
|
+
* const { data } = await client.manufacturers.list({ country: 'US' });
|
|
3282
|
+
*
|
|
3283
|
+
* // Get manufacturer details
|
|
3284
|
+
* const { data: mfr } = await client.manufacturers.get('beretta');
|
|
3285
|
+
* ```
|
|
3286
|
+
*/
|
|
3287
|
+
declare class ManufacturersResource {
|
|
3288
|
+
private readonly client;
|
|
3289
|
+
constructor(client: HttpClient);
|
|
3290
|
+
/**
|
|
3291
|
+
* List manufacturers with optional filters and pagination.
|
|
3292
|
+
*
|
|
3293
|
+
* @param params - Optional query parameters for filtering by country, sorting, and pagination.
|
|
3294
|
+
* @returns A paginated list of manufacturers.
|
|
3295
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3296
|
+
*
|
|
3297
|
+
* @example
|
|
3298
|
+
* ```typescript
|
|
3299
|
+
* const result = await client.manufacturers.list({
|
|
3300
|
+
* country: 'DE',
|
|
3301
|
+
* sort: 'name',
|
|
3302
|
+
* order: 'asc',
|
|
3303
|
+
* per_page: 50,
|
|
3304
|
+
* });
|
|
3305
|
+
* ```
|
|
3306
|
+
*/
|
|
3307
|
+
list(params?: ListManufacturersParams): Promise<PaginatedResponse<Manufacturer>>;
|
|
3308
|
+
/**
|
|
3309
|
+
* Auto-paginate through all manufacturers matching the given filters.
|
|
3310
|
+
*
|
|
3311
|
+
* Returns an async iterator that fetches pages on demand, yielding
|
|
3312
|
+
* individual {@link Manufacturer} objects.
|
|
3313
|
+
*
|
|
3314
|
+
* @param params - Optional query parameters for filtering and sorting.
|
|
3315
|
+
* @returns An async iterable iterator yielding individual manufacturers.
|
|
3316
|
+
*
|
|
3317
|
+
* @example
|
|
3318
|
+
* ```typescript
|
|
3319
|
+
* for await (const mfr of client.manufacturers.listAutoPaging()) {
|
|
3320
|
+
* console.log(mfr.name, mfr.country);
|
|
3321
|
+
* }
|
|
3322
|
+
* ```
|
|
3323
|
+
*/
|
|
3324
|
+
listAutoPaging(params?: ListManufacturersParams): AsyncIterableIterator<Manufacturer>;
|
|
3325
|
+
/**
|
|
3326
|
+
* Get a single manufacturer by its slug or ID.
|
|
3327
|
+
*
|
|
3328
|
+
* @param id - The manufacturer slug (e.g. `"beretta"`) or numeric ID.
|
|
3329
|
+
* @returns The full manufacturer record.
|
|
3330
|
+
* @throws {NotFoundError} If no manufacturer matches the given identifier.
|
|
3331
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3332
|
+
*
|
|
3333
|
+
* @example
|
|
3334
|
+
* ```typescript
|
|
3335
|
+
* const { data } = await client.manufacturers.get('sig-sauer');
|
|
3336
|
+
* console.log(data.name, data.foundedYear, data.country);
|
|
3337
|
+
* ```
|
|
3338
|
+
*/
|
|
3339
|
+
get(id: string): Promise<APIResponse<Manufacturer>>;
|
|
3340
|
+
/**
|
|
3341
|
+
* Get all firearms produced by a manufacturer.
|
|
3342
|
+
*
|
|
3343
|
+
* @param id - The manufacturer slug or ID.
|
|
3344
|
+
* @param params - Optional pagination parameters.
|
|
3345
|
+
* @returns A paginated list of firearms from the specified manufacturer.
|
|
3346
|
+
* @throws {NotFoundError} If the manufacturer does not exist.
|
|
3347
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3348
|
+
*
|
|
3349
|
+
* @example
|
|
3350
|
+
* ```typescript
|
|
3351
|
+
* const result = await client.manufacturers.getFirearms('colt', { per_page: 50 });
|
|
3352
|
+
* console.log(`Colt makes ${result.pagination.total} firearms`);
|
|
3353
|
+
* ```
|
|
3354
|
+
*/
|
|
3355
|
+
getFirearms(id: string, params?: PaginationParams): Promise<PaginatedResponse<Firearm>>;
|
|
3356
|
+
/**
|
|
3357
|
+
* Get a chronological timeline for a manufacturer.
|
|
3358
|
+
*
|
|
3359
|
+
* @param id - The manufacturer slug or ID.
|
|
3360
|
+
* @returns Timeline data with key events, product launches, and milestones.
|
|
3361
|
+
* @throws {NotFoundError} If the manufacturer does not exist.
|
|
3362
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3363
|
+
*
|
|
3364
|
+
* @example
|
|
3365
|
+
* ```typescript
|
|
3366
|
+
* const { data } = await client.manufacturers.getTimeline('browning');
|
|
3367
|
+
* for (const event of data.events) {
|
|
3368
|
+
* console.log(event.year, event.description);
|
|
3369
|
+
* }
|
|
3370
|
+
* ```
|
|
3371
|
+
*/
|
|
3372
|
+
getTimeline(id: string): Promise<APIResponse<ManufacturerTimeline>>;
|
|
3373
|
+
/**
|
|
3374
|
+
* Get aggregate statistics for a manufacturer.
|
|
3375
|
+
*
|
|
3376
|
+
* @param id - The manufacturer slug or ID.
|
|
3377
|
+
* @returns Statistical summary including firearm counts, caliber distribution, and more.
|
|
3378
|
+
* @throws {NotFoundError} If the manufacturer does not exist.
|
|
3379
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3380
|
+
*
|
|
3381
|
+
* @example
|
|
3382
|
+
* ```typescript
|
|
3383
|
+
* const { data } = await client.manufacturers.getStats('glock');
|
|
3384
|
+
* console.log(data.totalFirearms, data.caliberBreakdown);
|
|
3385
|
+
* ```
|
|
3386
|
+
*/
|
|
3387
|
+
getStats(id: string): Promise<APIResponse<ManufacturerStats>>;
|
|
3388
|
+
}
|
|
3389
|
+
|
|
3390
|
+
/**
|
|
3391
|
+
* Calibers resource for the GunSpec SDK.
|
|
3392
|
+
*
|
|
3393
|
+
* Provides access to all `/v1/calibers` endpoints including listing,
|
|
3394
|
+
* comparing, ballistics calculations, and exploring caliber families
|
|
3395
|
+
* and associated ammunition.
|
|
3396
|
+
*
|
|
3397
|
+
* @module
|
|
3398
|
+
*/
|
|
3399
|
+
|
|
3400
|
+
/**
|
|
3401
|
+
* Resource class for interacting with the GunSpec Calibers API.
|
|
3402
|
+
*
|
|
3403
|
+
* Wraps all `/v1/calibers` endpoints. Instantiated internally by the
|
|
3404
|
+
* {@link GunSpec} client and exposed as `client.calibers`.
|
|
3405
|
+
*
|
|
3406
|
+
* @example
|
|
3407
|
+
* ```typescript
|
|
3408
|
+
* import GunSpec from '@gunspec/sdk';
|
|
3409
|
+
*
|
|
3410
|
+
* const client = new GunSpec();
|
|
3411
|
+
*
|
|
3412
|
+
* // List calibers
|
|
3413
|
+
* const { data } = await client.calibers.list({ cartridge_type: 'centerfire' });
|
|
3414
|
+
*
|
|
3415
|
+
* // Compare calibers
|
|
3416
|
+
* const { data: comparison } = await client.calibers.compare({
|
|
3417
|
+
* ids: '9x19mm-parabellum,45-acp',
|
|
3418
|
+
* });
|
|
3419
|
+
* ```
|
|
3420
|
+
*/
|
|
3421
|
+
declare class CalibersResource {
|
|
3422
|
+
private readonly client;
|
|
3423
|
+
constructor(client: HttpClient);
|
|
3424
|
+
/**
|
|
3425
|
+
* List calibers with optional filters and pagination.
|
|
3426
|
+
*
|
|
3427
|
+
* @param params - Optional query parameters for filtering by cartridge type, primer type, etc.
|
|
3428
|
+
* @returns A paginated list of calibers.
|
|
3429
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3430
|
+
*
|
|
3431
|
+
* @example
|
|
3432
|
+
* ```typescript
|
|
3433
|
+
* const result = await client.calibers.list({
|
|
3434
|
+
* cartridge_type: 'centerfire',
|
|
3435
|
+
* primer_type: 'boxer',
|
|
3436
|
+
* per_page: 50,
|
|
3437
|
+
* });
|
|
3438
|
+
* ```
|
|
3439
|
+
*/
|
|
3440
|
+
list(params?: ListCalibersParams): Promise<PaginatedResponse<Caliber>>;
|
|
3441
|
+
/**
|
|
3442
|
+
* Auto-paginate through all calibers matching the given filters.
|
|
3443
|
+
*
|
|
3444
|
+
* Returns an async iterator that fetches pages on demand, yielding
|
|
3445
|
+
* individual {@link Caliber} objects.
|
|
3446
|
+
*
|
|
3447
|
+
* @param params - Optional query parameters for filtering and sorting.
|
|
3448
|
+
* @returns An async iterable iterator yielding individual calibers.
|
|
3449
|
+
*
|
|
3450
|
+
* @example
|
|
3451
|
+
* ```typescript
|
|
3452
|
+
* for await (const caliber of client.calibers.listAutoPaging()) {
|
|
3453
|
+
* console.log(caliber.name, caliber.bulletDiameterMm);
|
|
3454
|
+
* }
|
|
3455
|
+
* ```
|
|
3456
|
+
*/
|
|
3457
|
+
listAutoPaging(params?: ListCalibersParams): AsyncIterableIterator<Caliber>;
|
|
3458
|
+
/**
|
|
3459
|
+
* Compare up to 5 calibers side by side.
|
|
3460
|
+
*
|
|
3461
|
+
* @param params - Object containing comma-separated caliber IDs.
|
|
3462
|
+
* @returns An array of calibers with full details for comparison.
|
|
3463
|
+
* @throws {BadRequestError} If more than 5 IDs are provided.
|
|
3464
|
+
* @throws {NotFoundError} If any of the specified calibers do not exist.
|
|
3465
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3466
|
+
*
|
|
3467
|
+
* @example
|
|
3468
|
+
* ```typescript
|
|
3469
|
+
* const { data } = await client.calibers.compare({
|
|
3470
|
+
* ids: '9x19mm-parabellum,45-acp,40-s-w',
|
|
3471
|
+
* });
|
|
3472
|
+
* ```
|
|
3473
|
+
*/
|
|
3474
|
+
compare(params: CompareCalibersParams): Promise<APIResponse<Caliber[]>>;
|
|
3475
|
+
/**
|
|
3476
|
+
* Get ballistics data for a caliber at a specified distance.
|
|
3477
|
+
*
|
|
3478
|
+
* @param params - Caliber ID and distance in meters.
|
|
3479
|
+
* @returns Ballistic data including velocity, energy, and drop at the specified distance.
|
|
3480
|
+
* @throws {NotFoundError} If the caliber does not exist.
|
|
3481
|
+
* @throws {BadRequestError} If the distance is out of range.
|
|
3482
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3483
|
+
*
|
|
3484
|
+
* @example
|
|
3485
|
+
* ```typescript
|
|
3486
|
+
* const { data } = await client.calibers.ballistics({
|
|
3487
|
+
* id: '9x19mm-parabellum',
|
|
3488
|
+
* distance: 100,
|
|
3489
|
+
* });
|
|
3490
|
+
* console.log(data.velocity, data.energy, data.drop);
|
|
3491
|
+
* ```
|
|
3492
|
+
*/
|
|
3493
|
+
ballistics(params: CaliberBallisticsParams): Promise<APIResponse<BallisticsResult>>;
|
|
3494
|
+
/**
|
|
3495
|
+
* Get a single caliber by its slug or ID.
|
|
3496
|
+
*
|
|
3497
|
+
* @param id - The caliber slug (e.g. `"9x19mm-parabellum"`) or numeric ID.
|
|
3498
|
+
* @returns The full caliber record with all specifications.
|
|
3499
|
+
* @throws {NotFoundError} If no caliber matches the given identifier.
|
|
3500
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3501
|
+
*
|
|
3502
|
+
* @example
|
|
3503
|
+
* ```typescript
|
|
3504
|
+
* const { data } = await client.calibers.get('45-acp');
|
|
3505
|
+
* console.log(data.name, data.bulletDiameterMm, data.caseLengthMm);
|
|
3506
|
+
* ```
|
|
3507
|
+
*/
|
|
3508
|
+
get(id: string): Promise<APIResponse<Caliber>>;
|
|
3509
|
+
/**
|
|
3510
|
+
* Get all firearms that use a specific caliber.
|
|
3511
|
+
*
|
|
3512
|
+
* @param id - The caliber slug or ID.
|
|
3513
|
+
* @param params - Optional pagination parameters.
|
|
3514
|
+
* @returns A paginated list of firearms chambered in the specified caliber.
|
|
3515
|
+
* @throws {NotFoundError} If the caliber does not exist.
|
|
3516
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3517
|
+
*
|
|
3518
|
+
* @example
|
|
3519
|
+
* ```typescript
|
|
3520
|
+
* const result = await client.calibers.getFirearms('9x19mm-parabellum', { per_page: 50 });
|
|
3521
|
+
* console.log(`${result.pagination.total} firearms use 9mm`);
|
|
3522
|
+
* ```
|
|
3523
|
+
*/
|
|
3524
|
+
getFirearms(id: string, params?: PaginationParams): Promise<PaginatedResponse<Firearm>>;
|
|
3525
|
+
/**
|
|
3526
|
+
* Get the parent caliber chain (ancestry) for a caliber.
|
|
3527
|
+
*
|
|
3528
|
+
* @param id - The caliber slug or ID.
|
|
3529
|
+
* @returns An ordered array of calibers from the given caliber up to the root ancestor.
|
|
3530
|
+
* @throws {NotFoundError} If the caliber does not exist.
|
|
3531
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3532
|
+
*
|
|
3533
|
+
* @example
|
|
3534
|
+
* ```typescript
|
|
3535
|
+
* const { data } = await client.calibers.getParentChain('300-blackout');
|
|
3536
|
+
* // [300 Blackout, 5.56x45mm NATO, .223 Remington, ...]
|
|
3537
|
+
* ```
|
|
3538
|
+
*/
|
|
3539
|
+
getParentChain(id: string): Promise<APIResponse<Caliber[]>>;
|
|
3540
|
+
/**
|
|
3541
|
+
* Get the full family tree of related calibers.
|
|
3542
|
+
*
|
|
3543
|
+
* @param id - The caliber slug or ID.
|
|
3544
|
+
* @returns An array of calibers in the same family (parent, siblings, children).
|
|
3545
|
+
* @throws {NotFoundError} If the caliber does not exist.
|
|
3546
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3547
|
+
*
|
|
3548
|
+
* @example
|
|
3549
|
+
* ```typescript
|
|
3550
|
+
* const { data } = await client.calibers.getFamily('9x19mm-parabellum');
|
|
3551
|
+
* console.log(data.map(c => c.name));
|
|
3552
|
+
* ```
|
|
3553
|
+
*/
|
|
3554
|
+
getFamily(id: string): Promise<APIResponse<Caliber[]>>;
|
|
3555
|
+
/**
|
|
3556
|
+
* Get ammunition loads available for a caliber.
|
|
3557
|
+
*
|
|
3558
|
+
* @param id - The caliber slug or ID.
|
|
3559
|
+
* @param params - Optional pagination parameters.
|
|
3560
|
+
* @returns A paginated list of ammunition loads for the specified caliber.
|
|
3561
|
+
* @throws {NotFoundError} If the caliber does not exist.
|
|
3562
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3563
|
+
*
|
|
3564
|
+
* @example
|
|
3565
|
+
* ```typescript
|
|
3566
|
+
* const result = await client.calibers.getAmmunition('9x19mm-parabellum', { per_page: 25 });
|
|
3567
|
+
* for (const ammo of result.data) {
|
|
3568
|
+
* console.log(ammo.name, ammo.bulletWeightGrains);
|
|
3569
|
+
* }
|
|
3570
|
+
* ```
|
|
3571
|
+
*/
|
|
3572
|
+
getAmmunition(id: string, params?: PaginationParams): Promise<PaginatedResponse<Ammunition>>;
|
|
3573
|
+
}
|
|
3574
|
+
|
|
3575
|
+
/**
|
|
3576
|
+
* Categories resource for the GunSpec SDK.
|
|
3577
|
+
*
|
|
3578
|
+
* Provides access to `/v1/categories` endpoints for listing firearm
|
|
3579
|
+
* categories and retrieving firearms within a specific category.
|
|
3580
|
+
*
|
|
3581
|
+
* @module
|
|
3582
|
+
*/
|
|
3583
|
+
|
|
3584
|
+
/**
|
|
3585
|
+
* Resource class for interacting with the GunSpec Categories API.
|
|
3586
|
+
*
|
|
3587
|
+
* Wraps all `/v1/categories` endpoints. Instantiated internally by the
|
|
3588
|
+
* {@link GunSpec} client and exposed as `client.categories`.
|
|
3589
|
+
*
|
|
3590
|
+
* @example
|
|
3591
|
+
* ```typescript
|
|
3592
|
+
* import GunSpec from '@gunspec/sdk';
|
|
3593
|
+
*
|
|
3594
|
+
* const client = new GunSpec();
|
|
3595
|
+
*
|
|
3596
|
+
* // List all categories
|
|
3597
|
+
* const { data } = await client.categories.list();
|
|
3598
|
+
* console.log(data.map(c => c.name));
|
|
3599
|
+
*
|
|
3600
|
+
* // Get firearms in a category
|
|
3601
|
+
* const pistols = await client.categories.getFirearms('pistol');
|
|
3602
|
+
* ```
|
|
3603
|
+
*/
|
|
3604
|
+
declare class CategoriesResource {
|
|
3605
|
+
private readonly client;
|
|
3606
|
+
constructor(client: HttpClient);
|
|
3607
|
+
/**
|
|
3608
|
+
* List all firearm categories.
|
|
3609
|
+
*
|
|
3610
|
+
* @returns An array of all category records.
|
|
3611
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3612
|
+
*
|
|
3613
|
+
* @example
|
|
3614
|
+
* ```typescript
|
|
3615
|
+
* const { data } = await client.categories.list();
|
|
3616
|
+
* // [{ slug: 'pistol', name: 'Pistol' }, { slug: 'rifle', name: 'Rifle' }, ...]
|
|
3617
|
+
* ```
|
|
3618
|
+
*/
|
|
3619
|
+
list(): Promise<APIResponse<Category[]>>;
|
|
3620
|
+
/**
|
|
3621
|
+
* Get all firearms within a specific category.
|
|
3622
|
+
*
|
|
3623
|
+
* @param slug - The category slug (e.g. `"pistol"`, `"rifle"`, `"shotgun"`).
|
|
3624
|
+
* @param params - Optional pagination parameters.
|
|
3625
|
+
* @returns A paginated list of firearms in the specified category.
|
|
3626
|
+
* @throws {NotFoundError} If the category slug does not exist.
|
|
3627
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3628
|
+
*
|
|
3629
|
+
* @example
|
|
3630
|
+
* ```typescript
|
|
3631
|
+
* const result = await client.categories.getFirearms('shotgun', {
|
|
3632
|
+
* per_page: 25,
|
|
3633
|
+
* sort: 'name',
|
|
3634
|
+
* order: 'asc',
|
|
3635
|
+
* });
|
|
3636
|
+
* console.log(`${result.pagination.total} shotguns in database`);
|
|
3637
|
+
* ```
|
|
3638
|
+
*/
|
|
3639
|
+
getFirearms(slug: string, params?: PaginationParams): Promise<PaginatedResponse<Firearm>>;
|
|
3640
|
+
}
|
|
3641
|
+
|
|
3642
|
+
/**
|
|
3643
|
+
* Statistics resource for the GunSpec SDK.
|
|
3644
|
+
*
|
|
3645
|
+
* Provides access to all `/v1/stats` endpoints for retrieving aggregate
|
|
3646
|
+
* statistics about the firearms database including production status,
|
|
3647
|
+
* field coverage, caliber popularity, and more.
|
|
3648
|
+
*
|
|
3649
|
+
* @module
|
|
3650
|
+
*/
|
|
3651
|
+
|
|
3652
|
+
/**
|
|
3653
|
+
* Resource class for interacting with the GunSpec Statistics API.
|
|
3654
|
+
*
|
|
3655
|
+
* Wraps all `/v1/stats` endpoints. Instantiated internally by the
|
|
3656
|
+
* {@link GunSpec} client and exposed as `client.stats`.
|
|
3657
|
+
*
|
|
3658
|
+
* @example
|
|
3659
|
+
* ```typescript
|
|
3660
|
+
* import GunSpec from '@gunspec/sdk';
|
|
3661
|
+
*
|
|
3662
|
+
* const client = new GunSpec();
|
|
3663
|
+
*
|
|
3664
|
+
* const { data } = await client.stats.summary();
|
|
3665
|
+
* console.log(data.totalFirearms, data.totalManufacturers);
|
|
3666
|
+
* ```
|
|
3667
|
+
*/
|
|
3668
|
+
declare class StatsResource {
|
|
3669
|
+
private readonly client;
|
|
3670
|
+
constructor(client: HttpClient);
|
|
3671
|
+
/**
|
|
3672
|
+
* Get a high-level summary of the database.
|
|
3673
|
+
*
|
|
3674
|
+
* @returns Summary counts for firearms, manufacturers, calibers, and categories.
|
|
3675
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3676
|
+
*
|
|
3677
|
+
* @example
|
|
3678
|
+
* ```typescript
|
|
3679
|
+
* const { data } = await client.stats.summary();
|
|
3680
|
+
* console.log(`Database has ${data.totalFirearms} firearms`);
|
|
3681
|
+
* ```
|
|
3682
|
+
*/
|
|
3683
|
+
summary(): Promise<APIResponse<StatsSummary>>;
|
|
3684
|
+
/**
|
|
3685
|
+
* Get firearm counts grouped by production status.
|
|
3686
|
+
*
|
|
3687
|
+
* @returns Counts for in-production, discontinued, and prototype firearms.
|
|
3688
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3689
|
+
*
|
|
3690
|
+
* @example
|
|
3691
|
+
* ```typescript
|
|
3692
|
+
* const { data } = await client.stats.productionStatus();
|
|
3693
|
+
* // { in_production: 342, discontinued: 891, prototype: 12 }
|
|
3694
|
+
* ```
|
|
3695
|
+
*/
|
|
3696
|
+
productionStatus(): Promise<APIResponse<ProductionStatusItem[]>>;
|
|
3697
|
+
/**
|
|
3698
|
+
* Get field coverage statistics across the database.
|
|
3699
|
+
*
|
|
3700
|
+
* Shows the percentage of firearms that have data for each field,
|
|
3701
|
+
* useful for assessing data completeness.
|
|
3702
|
+
*
|
|
3703
|
+
* @returns Per-field coverage percentages.
|
|
3704
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3705
|
+
*
|
|
3706
|
+
* @example
|
|
3707
|
+
* ```typescript
|
|
3708
|
+
* const { data } = await client.stats.fieldCoverage();
|
|
3709
|
+
* console.log(`Weight field: ${data.weight}% coverage`);
|
|
3710
|
+
* ```
|
|
3711
|
+
*/
|
|
3712
|
+
fieldCoverage(): Promise<APIResponse<FieldCoverage>>;
|
|
3713
|
+
/**
|
|
3714
|
+
* Get the most popular calibers by firearm count.
|
|
3715
|
+
*
|
|
3716
|
+
* @param params - Optional limit parameter.
|
|
3717
|
+
* @returns An ordered list of calibers ranked by the number of firearms using them.
|
|
3718
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3719
|
+
*
|
|
3720
|
+
* @example
|
|
3721
|
+
* ```typescript
|
|
3722
|
+
* const { data } = await client.stats.popularCalibers({ limit: 10 });
|
|
3723
|
+
* for (const entry of data) {
|
|
3724
|
+
* console.log(`${entry.name}: ${entry.count} firearms`);
|
|
3725
|
+
* }
|
|
3726
|
+
* ```
|
|
3727
|
+
*/
|
|
3728
|
+
popularCalibers(params?: PopularCalibersParams): Promise<APIResponse<PopularCaliber[]>>;
|
|
3729
|
+
/**
|
|
3730
|
+
* Get the most prolific manufacturers by firearm count.
|
|
3731
|
+
*
|
|
3732
|
+
* @param params - Optional limit and category filter.
|
|
3733
|
+
* @returns An ordered list of manufacturers ranked by the number of firearms produced.
|
|
3734
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3735
|
+
*
|
|
3736
|
+
* @example
|
|
3737
|
+
* ```typescript
|
|
3738
|
+
* const { data } = await client.stats.prolificManufacturers({
|
|
3739
|
+
* limit: 10,
|
|
3740
|
+
* category: 'pistol',
|
|
3741
|
+
* });
|
|
3742
|
+
* ```
|
|
3743
|
+
*/
|
|
3744
|
+
prolificManufacturers(params?: ProlificManufacturersParams): Promise<APIResponse<ProlificManufacturer[]>>;
|
|
3745
|
+
/**
|
|
3746
|
+
* Get firearm counts grouped by category.
|
|
3747
|
+
*
|
|
3748
|
+
* @returns Counts per category (pistol, rifle, shotgun, etc.).
|
|
3749
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3750
|
+
*
|
|
3751
|
+
* @example
|
|
3752
|
+
* ```typescript
|
|
3753
|
+
* const { data } = await client.stats.byCategory();
|
|
3754
|
+
* // [{ category: 'pistol', count: 512 }, { category: 'rifle', count: 234 }, ...]
|
|
3755
|
+
* ```
|
|
3756
|
+
*/
|
|
3757
|
+
byCategory(): Promise<APIResponse<CategoryStats[]>>;
|
|
3758
|
+
/**
|
|
3759
|
+
* Get firearm statistics for a specific decade/era.
|
|
3760
|
+
*
|
|
3761
|
+
* @param params - The decade string (e.g. `"1990s"`).
|
|
3762
|
+
* @returns Statistics for firearms introduced during the specified decade.
|
|
3763
|
+
* @throws {BadRequestError} If the decade format is invalid (must be like `"1990s"`).
|
|
3764
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3765
|
+
*
|
|
3766
|
+
* @example
|
|
3767
|
+
* ```typescript
|
|
3768
|
+
* const { data } = await client.stats.byEra({ decade: '1940s' });
|
|
3769
|
+
* ```
|
|
3770
|
+
*/
|
|
3771
|
+
byEra(params: ByEraParams): Promise<APIResponse<EraStats>>;
|
|
3772
|
+
/**
|
|
3773
|
+
* Get statistics about materials used across all firearms.
|
|
3774
|
+
*
|
|
3775
|
+
* @returns Material usage counts and percentages by component type.
|
|
3776
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3777
|
+
*
|
|
3778
|
+
* @example
|
|
3779
|
+
* ```typescript
|
|
3780
|
+
* const { data } = await client.stats.materials();
|
|
3781
|
+
* ```
|
|
3782
|
+
*/
|
|
3783
|
+
materials(): Promise<APIResponse<MaterialStats>>;
|
|
3784
|
+
/**
|
|
3785
|
+
* Get firearm adoption statistics for a specific country.
|
|
3786
|
+
*
|
|
3787
|
+
* @param params - The country code (e.g. `"US"`, `"GB"`).
|
|
3788
|
+
* @returns Adoption data for the specified country.
|
|
3789
|
+
* @throws {BadRequestError} If the country code is invalid.
|
|
3790
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3791
|
+
*
|
|
3792
|
+
* @example
|
|
3793
|
+
* ```typescript
|
|
3794
|
+
* const { data } = await client.stats.adoptionByCountry({ code: 'US' });
|
|
3795
|
+
* ```
|
|
3796
|
+
*/
|
|
3797
|
+
adoptionByCountry(params: AdoptionByCountryParams): Promise<APIResponse<AdoptionByCountryItem[]>>;
|
|
3798
|
+
/**
|
|
3799
|
+
* Get firearm adoption statistics by usage type.
|
|
3800
|
+
*
|
|
3801
|
+
* @param params - The usage type (e.g. `"military"`, `"law_enforcement"`, `"civilian"`).
|
|
3802
|
+
* @returns Adoption data for the specified usage type.
|
|
3803
|
+
* @throws {BadRequestError} If the type is not a recognized usage category.
|
|
3804
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3805
|
+
*
|
|
3806
|
+
* @example
|
|
3807
|
+
* ```typescript
|
|
3808
|
+
* const { data } = await client.stats.adoptionByType({ type: 'military' });
|
|
3809
|
+
* ```
|
|
3810
|
+
*/
|
|
3811
|
+
adoptionByType(params: AdoptionByTypeParams): Promise<APIResponse<AdoptionByTypeItem[]>>;
|
|
3812
|
+
/**
|
|
3813
|
+
* Get firearm counts grouped by action type.
|
|
3814
|
+
*
|
|
3815
|
+
* @param params - Optional category filter.
|
|
3816
|
+
* @returns Counts per action type, optionally filtered by category.
|
|
3817
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3818
|
+
*
|
|
3819
|
+
* @example
|
|
3820
|
+
* ```typescript
|
|
3821
|
+
* const { data } = await client.stats.actionTypes({ category: 'rifle' });
|
|
3822
|
+
* ```
|
|
3823
|
+
*/
|
|
3824
|
+
actionTypes(params?: ActionTypesParams): Promise<APIResponse<ActionTypeStats[]>>;
|
|
3825
|
+
/**
|
|
3826
|
+
* Get feature frequency statistics across the database.
|
|
3827
|
+
*
|
|
3828
|
+
* @param params - Optional category filter and result limit.
|
|
3829
|
+
* @returns An ordered list of features ranked by frequency of occurrence.
|
|
3830
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3831
|
+
*
|
|
3832
|
+
* @example
|
|
3833
|
+
* ```typescript
|
|
3834
|
+
* const { data } = await client.stats.featureFrequency({
|
|
3835
|
+
* category: 'pistol',
|
|
3836
|
+
* limit: 20,
|
|
3837
|
+
* });
|
|
3838
|
+
* ```
|
|
3839
|
+
*/
|
|
3840
|
+
featureFrequency(params?: FeatureFrequencyParams): Promise<APIResponse<FeatureFrequency[]>>;
|
|
3841
|
+
/**
|
|
3842
|
+
* Get caliber popularity trends across historical eras.
|
|
3843
|
+
*
|
|
3844
|
+
* @param params - Optional from/to decade range (e.g. `"1940s"` to `"2020s"`).
|
|
3845
|
+
* @returns Caliber popularity data broken down by decade.
|
|
3846
|
+
* @throws {BadRequestError} If the decade format is invalid.
|
|
3847
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3848
|
+
*
|
|
3849
|
+
* @example
|
|
3850
|
+
* ```typescript
|
|
3851
|
+
* const { data } = await client.stats.caliberPopularityByEra({
|
|
3852
|
+
* from_decade: '1940s',
|
|
3853
|
+
* to_decade: '2020s',
|
|
3854
|
+
* });
|
|
3855
|
+
* ```
|
|
3856
|
+
*/
|
|
3857
|
+
caliberPopularityByEra(params?: CaliberPopularityByEraParams): Promise<APIResponse<CaliberPopularityByEra[]>>;
|
|
3858
|
+
}
|
|
3859
|
+
|
|
3860
|
+
/**
|
|
3861
|
+
* Game resource for the GunSpec SDK.
|
|
3862
|
+
*
|
|
3863
|
+
* Provides access to all `/v1/game` endpoints for game-balanced
|
|
3864
|
+
* firearm data including balance reports, tier lists, matchups,
|
|
3865
|
+
* role rosters, and stat distributions.
|
|
3866
|
+
*
|
|
3867
|
+
* @module
|
|
3868
|
+
*/
|
|
3869
|
+
|
|
3870
|
+
/**
|
|
3871
|
+
* Resource class for interacting with the GunSpec Game API.
|
|
3872
|
+
*
|
|
3873
|
+
* Wraps all `/v1/game` endpoints. These endpoints provide game-balanced
|
|
3874
|
+
* firearm data suitable for game development, including normalized stats,
|
|
3875
|
+
* tier rankings, and balance analysis.
|
|
3876
|
+
*
|
|
3877
|
+
* Instantiated internally by the {@link GunSpec} client and exposed as
|
|
3878
|
+
* `client.game`.
|
|
3879
|
+
*
|
|
3880
|
+
* @example
|
|
3881
|
+
* ```typescript
|
|
3882
|
+
* import GunSpec from '@gunspec/sdk';
|
|
3883
|
+
*
|
|
3884
|
+
* const client = new GunSpec();
|
|
3885
|
+
*
|
|
3886
|
+
* const { data } = await client.game.tierList({ stat: 'damage' });
|
|
3887
|
+
* console.log(data.tiers);
|
|
3888
|
+
* ```
|
|
3889
|
+
*/
|
|
3890
|
+
declare class GameResource {
|
|
3891
|
+
private readonly client;
|
|
3892
|
+
constructor(client: HttpClient);
|
|
3893
|
+
/**
|
|
3894
|
+
* Get a balance report showing outlier firearms.
|
|
3895
|
+
*
|
|
3896
|
+
* Identifies firearms whose game stats deviate significantly from
|
|
3897
|
+
* the average, useful for game balancing.
|
|
3898
|
+
*
|
|
3899
|
+
* @param params - Optional threshold for outlier detection (0-100).
|
|
3900
|
+
* @returns A balance report with overpowered and underpowered firearms.
|
|
3901
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3902
|
+
*
|
|
3903
|
+
* @example
|
|
3904
|
+
* ```typescript
|
|
3905
|
+
* const { data } = await client.game.balanceReport({ threshold: 15 });
|
|
3906
|
+
* console.log(data.length, 'firearms flagged as outliers');
|
|
3907
|
+
* ```
|
|
3908
|
+
*/
|
|
3909
|
+
balanceReport(params?: BalanceReportParams): Promise<APIResponse<BalanceEntry[]>>;
|
|
3910
|
+
/**
|
|
3911
|
+
* Get a tier list of firearms ranked by a specific stat.
|
|
3912
|
+
*
|
|
3913
|
+
* @param params - Optional category filter and stat to rank by.
|
|
3914
|
+
* @returns A tier list with firearms grouped into S/A/B/C/D/F tiers.
|
|
3915
|
+
* @throws {BadRequestError} If the stat is not a valid game stat.
|
|
3916
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3917
|
+
*
|
|
3918
|
+
* @example
|
|
3919
|
+
* ```typescript
|
|
3920
|
+
* const { data } = await client.game.tierList({
|
|
3921
|
+
* stat: 'accuracy',
|
|
3922
|
+
* category: 'rifle',
|
|
3923
|
+
* });
|
|
3924
|
+
* console.log('S-tier:', data.tiers.S.map(f => f.name));
|
|
3925
|
+
* ```
|
|
3926
|
+
*/
|
|
3927
|
+
tierList(params?: TierListParams): Promise<APIResponse<TierList>>;
|
|
3928
|
+
/**
|
|
3929
|
+
* Get a game-balanced matchup between two firearms.
|
|
3930
|
+
*
|
|
3931
|
+
* @param params - The slugs of the two firearms to compare.
|
|
3932
|
+
* @returns A detailed matchup result with per-stat comparisons and a winner.
|
|
3933
|
+
* @throws {NotFoundError} If either firearm does not exist.
|
|
3934
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3935
|
+
*
|
|
3936
|
+
* @example
|
|
3937
|
+
* ```typescript
|
|
3938
|
+
* const { data } = await client.game.matchups({ a: 'ak-47', b: 'm4-carbine' });
|
|
3939
|
+
* console.log(data.winner, data.statComparisons);
|
|
3940
|
+
* ```
|
|
3941
|
+
*/
|
|
3942
|
+
matchups(params: MatchupsParams): Promise<APIResponse<MatchupResult>>;
|
|
3943
|
+
/**
|
|
3944
|
+
* Get a roster of firearms best suited for a specific game role.
|
|
3945
|
+
*
|
|
3946
|
+
* @param params - The role to query and optional count limit.
|
|
3947
|
+
* @returns A roster of firearms ranked by suitability for the given role.
|
|
3948
|
+
* @throws {BadRequestError} If the role is not a recognized game role.
|
|
3949
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3950
|
+
*
|
|
3951
|
+
* @example
|
|
3952
|
+
* ```typescript
|
|
3953
|
+
* const { data } = await client.game.roleRoster({
|
|
3954
|
+
* role: 'sniper',
|
|
3955
|
+
* count: 10,
|
|
3956
|
+
* });
|
|
3957
|
+
* for (const firearm of data) {
|
|
3958
|
+
* console.log(firearm.name, firearm.roleScore);
|
|
3959
|
+
* }
|
|
3960
|
+
* ```
|
|
3961
|
+
*/
|
|
3962
|
+
roleRoster(params: RoleRosterParams): Promise<APIResponse<RoleRosterItem[]>>;
|
|
3963
|
+
/**
|
|
3964
|
+
* Get the statistical distribution for a specific game stat.
|
|
3965
|
+
*
|
|
3966
|
+
* Shows how firearms are distributed across value ranges for a given
|
|
3967
|
+
* stat, useful for understanding the spread and identifying balance issues.
|
|
3968
|
+
*
|
|
3969
|
+
* @param params - The stat to analyze (e.g. `"damage"`, `"accuracy"`).
|
|
3970
|
+
* @returns Distribution data including histogram buckets and summary statistics.
|
|
3971
|
+
* @throws {BadRequestError} If the stat is not a valid game stat.
|
|
3972
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
3973
|
+
*
|
|
3974
|
+
* @example
|
|
3975
|
+
* ```typescript
|
|
3976
|
+
* const { data } = await client.game.statDistribution({ stat: 'damage' });
|
|
3977
|
+
* console.log(data.mean, data.median, data.buckets);
|
|
3978
|
+
* ```
|
|
3979
|
+
*/
|
|
3980
|
+
statDistribution(params: StatDistributionParams): Promise<APIResponse<StatDistribution>>;
|
|
3981
|
+
}
|
|
3982
|
+
|
|
3983
|
+
/**
|
|
3984
|
+
* Game Stats Snapshots resource for the GunSpec SDK.
|
|
3985
|
+
*
|
|
3986
|
+
* Provides access to `/v1/game-stats` endpoints for retrieving versioned
|
|
3987
|
+
* snapshots of game-balanced firearm statistics. Each snapshot captures
|
|
3988
|
+
* the game stats at a specific point in time, enabling version tracking
|
|
3989
|
+
* and historical comparisons.
|
|
3990
|
+
*
|
|
3991
|
+
* @module
|
|
3992
|
+
*/
|
|
3993
|
+
|
|
3994
|
+
/**
|
|
3995
|
+
* Resource class for interacting with the GunSpec Game Stats Snapshots API.
|
|
3996
|
+
*
|
|
3997
|
+
* Wraps all `/v1/game-stats` endpoints. Instantiated internally by the
|
|
3998
|
+
* {@link GunSpec} client and exposed as `client.gameStats`.
|
|
3999
|
+
*
|
|
4000
|
+
* @example
|
|
4001
|
+
* ```typescript
|
|
4002
|
+
* import GunSpec from '@gunspec/sdk';
|
|
4003
|
+
*
|
|
4004
|
+
* const client = new GunSpec();
|
|
4005
|
+
*
|
|
4006
|
+
* // List all snapshot versions
|
|
4007
|
+
* const { data: versions } = await client.gameStats.listVersions();
|
|
4008
|
+
*
|
|
4009
|
+
* // Get firearms from a specific version
|
|
4010
|
+
* const result = await client.gameStats.listFirearms('1.0.0');
|
|
4011
|
+
* ```
|
|
4012
|
+
*/
|
|
4013
|
+
declare class GameStatsResource {
|
|
4014
|
+
private readonly client;
|
|
4015
|
+
constructor(client: HttpClient);
|
|
4016
|
+
/**
|
|
4017
|
+
* List all available game stats snapshot versions.
|
|
4018
|
+
*
|
|
4019
|
+
* @returns An array of version records with metadata about each snapshot.
|
|
4020
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
4021
|
+
*
|
|
4022
|
+
* @example
|
|
4023
|
+
* ```typescript
|
|
4024
|
+
* const { data } = await client.gameStats.listVersions();
|
|
4025
|
+
* for (const version of data) {
|
|
4026
|
+
* console.log(version.version, version.createdAt, version.description);
|
|
4027
|
+
* }
|
|
4028
|
+
* ```
|
|
4029
|
+
*/
|
|
4030
|
+
listVersions(): Promise<APIResponse<GameStatsVersion[]>>;
|
|
4031
|
+
/**
|
|
4032
|
+
* List all firearms in a specific game stats snapshot version.
|
|
4033
|
+
*
|
|
4034
|
+
* @param version - The snapshot version string (e.g. `"1.0.0"`).
|
|
4035
|
+
* @param params - Optional pagination parameters.
|
|
4036
|
+
* @returns A paginated list of firearms with their game stats for the given version.
|
|
4037
|
+
* @throws {NotFoundError} If the specified version does not exist.
|
|
4038
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
4039
|
+
*
|
|
4040
|
+
* @example
|
|
4041
|
+
* ```typescript
|
|
4042
|
+
* const result = await client.gameStats.listFirearms('1.0.0', { per_page: 50 });
|
|
4043
|
+
* for (const firearm of result.data) {
|
|
4044
|
+
* console.log(firearm.name, firearm.damage);
|
|
4045
|
+
* }
|
|
4046
|
+
* ```
|
|
4047
|
+
*/
|
|
4048
|
+
listFirearms(version: string, params?: ListSnapshotFirearmsParams): Promise<PaginatedResponse<GameStatsSnapshotEntry>>;
|
|
4049
|
+
/**
|
|
4050
|
+
* Get a single firearm's game stats from a specific snapshot version.
|
|
4051
|
+
*
|
|
4052
|
+
* @param version - The snapshot version string (e.g. `"1.0.0"`).
|
|
4053
|
+
* @param id - The firearm slug or ID.
|
|
4054
|
+
* @returns The firearm's game stats as captured in the specified version.
|
|
4055
|
+
* @throws {NotFoundError} If the version or firearm does not exist in the snapshot.
|
|
4056
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
4057
|
+
*
|
|
4058
|
+
* @example
|
|
4059
|
+
* ```typescript
|
|
4060
|
+
* const { data } = await client.gameStats.getFirearm('1.0.0', 'glock-g17');
|
|
4061
|
+
* console.log(data.damage, data.accuracy, data.range);
|
|
4062
|
+
* ```
|
|
4063
|
+
*/
|
|
4064
|
+
getFirearm(version: string, id: string): Promise<APIResponse<GameStatsSnapshotEntry>>;
|
|
4065
|
+
}
|
|
4066
|
+
|
|
4067
|
+
/**
|
|
4068
|
+
* Ammunition resource for the GunSpec SDK.
|
|
4069
|
+
*
|
|
4070
|
+
* Provides access to all `/v1/ammunition` endpoints including listing,
|
|
4071
|
+
* retrieving details, bullet SVG generation, and ballistic calculations.
|
|
4072
|
+
*
|
|
4073
|
+
* @module
|
|
4074
|
+
*/
|
|
4075
|
+
|
|
4076
|
+
/**
|
|
4077
|
+
* Resource class for interacting with the GunSpec Ammunition API.
|
|
4078
|
+
*
|
|
4079
|
+
* Wraps all `/v1/ammunition` endpoints. Instantiated internally by the
|
|
4080
|
+
* {@link GunSpec} client and exposed as `client.ammunition`.
|
|
4081
|
+
*
|
|
4082
|
+
* @example
|
|
4083
|
+
* ```typescript
|
|
4084
|
+
* import GunSpec from '@gunspec/sdk';
|
|
4085
|
+
*
|
|
4086
|
+
* const client = new GunSpec();
|
|
4087
|
+
*
|
|
4088
|
+
* // List ammunition
|
|
4089
|
+
* const { data } = await client.ammunition.list({ caliber_id: '9x19mm-parabellum' });
|
|
4090
|
+
*
|
|
4091
|
+
* // Get ballistics for a specific load
|
|
4092
|
+
* const { data: ballistics } = await client.ammunition.ballistics(
|
|
4093
|
+
* '9mm-federal-hst-124gr',
|
|
4094
|
+
* { distances: '0,25,50,100' },
|
|
4095
|
+
* );
|
|
4096
|
+
* ```
|
|
4097
|
+
*/
|
|
4098
|
+
declare class AmmunitionResource {
|
|
4099
|
+
private readonly client;
|
|
4100
|
+
constructor(client: HttpClient);
|
|
4101
|
+
/**
|
|
4102
|
+
* List ammunition with optional filters and pagination.
|
|
4103
|
+
*
|
|
4104
|
+
* @param params - Optional query parameters for filtering by caliber, bullet type, etc.
|
|
4105
|
+
* @returns A paginated list of ammunition loads.
|
|
4106
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
4107
|
+
*
|
|
4108
|
+
* @example
|
|
4109
|
+
* ```typescript
|
|
4110
|
+
* const result = await client.ammunition.list({
|
|
4111
|
+
* caliber_id: '9x19mm-parabellum',
|
|
4112
|
+
* bullet_type: 'hollow-point',
|
|
4113
|
+
* per_page: 25,
|
|
4114
|
+
* });
|
|
4115
|
+
* ```
|
|
4116
|
+
*/
|
|
4117
|
+
list(params?: ListAmmunitionParams): Promise<PaginatedResponse<Ammunition>>;
|
|
4118
|
+
/**
|
|
4119
|
+
* Auto-paginate through all ammunition matching the given filters.
|
|
4120
|
+
*
|
|
4121
|
+
* Returns an async iterator that fetches pages on demand, yielding
|
|
4122
|
+
* individual {@link Ammunition} objects.
|
|
4123
|
+
*
|
|
4124
|
+
* @param params - Optional query parameters for filtering and sorting.
|
|
4125
|
+
* @returns An async iterable iterator yielding individual ammunition loads.
|
|
4126
|
+
*
|
|
4127
|
+
* @example
|
|
4128
|
+
* ```typescript
|
|
4129
|
+
* for await (const ammo of client.ammunition.listAutoPaging({ caliber_id: '45-acp' })) {
|
|
4130
|
+
* console.log(ammo.name, ammo.bulletWeightGrains);
|
|
4131
|
+
* }
|
|
4132
|
+
* ```
|
|
4133
|
+
*/
|
|
4134
|
+
listAutoPaging(params?: ListAmmunitionParams): AsyncIterableIterator<Ammunition>;
|
|
4135
|
+
/**
|
|
4136
|
+
* Get a single ammunition load by its slug or ID.
|
|
4137
|
+
*
|
|
4138
|
+
* @param id - The ammunition slug (e.g. `"9mm-federal-hst-124gr"`) or numeric ID.
|
|
4139
|
+
* @returns The full ammunition record with specifications.
|
|
4140
|
+
* @throws {NotFoundError} If no ammunition matches the given identifier.
|
|
4141
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
4142
|
+
*
|
|
4143
|
+
* @example
|
|
4144
|
+
* ```typescript
|
|
4145
|
+
* const { data } = await client.ammunition.get('9mm-federal-hst-124gr');
|
|
4146
|
+
* console.log(data.name, data.muzzleVelocityFps, data.bulletWeightGrains);
|
|
4147
|
+
* ```
|
|
4148
|
+
*/
|
|
4149
|
+
get(id: string): Promise<APIResponse<Ammunition>>;
|
|
4150
|
+
/**
|
|
4151
|
+
* Get a bullet profile SVG image for an ammunition load.
|
|
4152
|
+
*
|
|
4153
|
+
* Returns a raw SVG string representing the bullet projectile shape.
|
|
4154
|
+
* This endpoint returns raw SVG content, not the standard JSON envelope.
|
|
4155
|
+
*
|
|
4156
|
+
* @param id - The ammunition slug or ID.
|
|
4157
|
+
* @returns The raw SVG string of the bullet profile.
|
|
4158
|
+
* @throws {NotFoundError} If the ammunition does not exist.
|
|
4159
|
+
*
|
|
4160
|
+
* @example
|
|
4161
|
+
* ```typescript
|
|
4162
|
+
* const svg = await client.ammunition.getBulletSvg('9mm-federal-hst-124gr');
|
|
4163
|
+
* // Insert into DOM: element.innerHTML = svg;
|
|
4164
|
+
* ```
|
|
4165
|
+
*/
|
|
4166
|
+
getBulletSvg(id: string): Promise<string>;
|
|
4167
|
+
/**
|
|
4168
|
+
* Get ballistic trajectory data for an ammunition load.
|
|
4169
|
+
*
|
|
4170
|
+
* @param id - The ammunition slug or ID.
|
|
4171
|
+
* @param params - Optional barrel length and distance parameters.
|
|
4172
|
+
* @returns Ballistic trajectory data at specified distances.
|
|
4173
|
+
* @throws {NotFoundError} If the ammunition does not exist.
|
|
4174
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
4175
|
+
*
|
|
4176
|
+
* @example
|
|
4177
|
+
* ```typescript
|
|
4178
|
+
* const { data } = await client.ammunition.ballistics('9mm-federal-hst-124gr', {
|
|
4179
|
+
* barrel_length_mm: 102,
|
|
4180
|
+
* distances: '0,25,50,100,200',
|
|
4181
|
+
* });
|
|
4182
|
+
* for (const point of data.trajectory) {
|
|
4183
|
+
* console.log(`${point.distanceM}m: ${point.velocityFps} fps, ${point.energyFtLbs} ft-lbs`);
|
|
4184
|
+
* }
|
|
4185
|
+
* ```
|
|
4186
|
+
*/
|
|
4187
|
+
ballistics(id: string, params?: AmmunitionBallisticsParams): Promise<APIResponse<BallisticProfile>>;
|
|
4188
|
+
}
|
|
4189
|
+
|
|
4190
|
+
/**
|
|
4191
|
+
* Countries resource for the GunSpec SDK.
|
|
4192
|
+
*
|
|
4193
|
+
* Provides access to `/v1/countries` endpoints for listing countries
|
|
4194
|
+
* and retrieving a country's full firearm arsenal.
|
|
4195
|
+
*
|
|
4196
|
+
* @module
|
|
4197
|
+
*/
|
|
4198
|
+
|
|
4199
|
+
/**
|
|
4200
|
+
* Resource class for interacting with the GunSpec Countries API.
|
|
4201
|
+
*
|
|
4202
|
+
* Wraps all `/v1/countries` endpoints. Instantiated internally by the
|
|
4203
|
+
* {@link GunSpec} client and exposed as `client.countries`.
|
|
4204
|
+
*
|
|
4205
|
+
* @example
|
|
4206
|
+
* ```typescript
|
|
4207
|
+
* import GunSpec from '@gunspec/sdk';
|
|
4208
|
+
*
|
|
4209
|
+
* const client = new GunSpec();
|
|
4210
|
+
*
|
|
4211
|
+
* // List all countries
|
|
4212
|
+
* const { data } = await client.countries.list();
|
|
4213
|
+
*
|
|
4214
|
+
* // Get a country's full arsenal
|
|
4215
|
+
* const { data: arsenal } = await client.countries.getArsenal('US');
|
|
4216
|
+
* ```
|
|
4217
|
+
*/
|
|
4218
|
+
declare class CountriesResource {
|
|
4219
|
+
private readonly client;
|
|
4220
|
+
constructor(client: HttpClient);
|
|
4221
|
+
/**
|
|
4222
|
+
* List all countries that have adopted at least one firearm.
|
|
4223
|
+
*
|
|
4224
|
+
* @returns An array of country records with codes and names.
|
|
4225
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
4226
|
+
*
|
|
4227
|
+
* @example
|
|
4228
|
+
* ```typescript
|
|
4229
|
+
* const { data } = await client.countries.list();
|
|
4230
|
+
* for (const country of data) {
|
|
4231
|
+
* console.log(country.code, country.name);
|
|
4232
|
+
* }
|
|
4233
|
+
* ```
|
|
4234
|
+
*/
|
|
4235
|
+
list(): Promise<APIResponse<Country[]>>;
|
|
4236
|
+
/**
|
|
4237
|
+
* Get the full firearm arsenal for a specific country.
|
|
4238
|
+
*
|
|
4239
|
+
* Returns all firearms adopted by the country, grouped by usage type
|
|
4240
|
+
* (military, law enforcement, etc.).
|
|
4241
|
+
*
|
|
4242
|
+
* @param code - The country code (e.g. `"US"`, `"GB"`, `"DE"`).
|
|
4243
|
+
* @returns The country's arsenal data with firearms grouped by adoption type.
|
|
4244
|
+
* @throws {NotFoundError} If the country code is not found in the database.
|
|
4245
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
4246
|
+
*
|
|
4247
|
+
* @example
|
|
4248
|
+
* ```typescript
|
|
4249
|
+
* const { data } = await client.countries.getArsenal('US');
|
|
4250
|
+
* console.log(`${data.country.name} has ${data.totalFirearms} firearms`);
|
|
4251
|
+
* for (const group of data.groups) {
|
|
4252
|
+
* console.log(`${group.type}: ${group.firearms.length} firearms`);
|
|
4253
|
+
* }
|
|
4254
|
+
* ```
|
|
4255
|
+
*/
|
|
4256
|
+
getArsenal(code: string): Promise<APIResponse<CountryArsenal>>;
|
|
4257
|
+
}
|
|
4258
|
+
|
|
4259
|
+
/**
|
|
4260
|
+
* Conflicts resource for the GunSpec SDK.
|
|
4261
|
+
*
|
|
4262
|
+
* Provides access to the `/v1/conflicts` endpoint for listing military
|
|
4263
|
+
* conflicts and their associated firearms.
|
|
4264
|
+
*
|
|
4265
|
+
* @module
|
|
4266
|
+
*/
|
|
4267
|
+
|
|
4268
|
+
/**
|
|
4269
|
+
* Resource class for interacting with the GunSpec Conflicts API.
|
|
4270
|
+
*
|
|
4271
|
+
* Wraps the `/v1/conflicts` endpoint. Instantiated internally by the
|
|
4272
|
+
* {@link GunSpec} client and exposed as `client.conflicts`.
|
|
4273
|
+
*
|
|
4274
|
+
* @example
|
|
4275
|
+
* ```typescript
|
|
4276
|
+
* import GunSpec from '@gunspec/sdk';
|
|
4277
|
+
*
|
|
4278
|
+
* const client = new GunSpec();
|
|
4279
|
+
*
|
|
4280
|
+
* const { data } = await client.conflicts.list();
|
|
4281
|
+
* for (const conflict of data) {
|
|
4282
|
+
* console.log(conflict.name, conflict.startYear, conflict.endYear);
|
|
4283
|
+
* }
|
|
4284
|
+
* ```
|
|
4285
|
+
*/
|
|
4286
|
+
declare class ConflictsResource {
|
|
4287
|
+
private readonly client;
|
|
4288
|
+
constructor(client: HttpClient);
|
|
4289
|
+
/**
|
|
4290
|
+
* List all military conflicts in the database.
|
|
4291
|
+
*
|
|
4292
|
+
* Returns conflicts with metadata including name, date range, and
|
|
4293
|
+
* participating nations. Use the conflict identifiers with
|
|
4294
|
+
* `client.firearms.byConflict()` to find firearms used in a specific conflict.
|
|
4295
|
+
*
|
|
4296
|
+
* @returns An array of all conflict records.
|
|
4297
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
4298
|
+
*
|
|
4299
|
+
* @example
|
|
4300
|
+
* ```typescript
|
|
4301
|
+
* const { data } = await client.conflicts.list();
|
|
4302
|
+
* for (const conflict of data) {
|
|
4303
|
+
* console.log(`${conflict.name} (${conflict.startYear}-${conflict.endYear})`);
|
|
4304
|
+
* }
|
|
4305
|
+
*
|
|
4306
|
+
* // Then find firearms used in a conflict:
|
|
4307
|
+
* const wwii = await client.firearms.byConflict({ conflict: 'world-war-ii' });
|
|
4308
|
+
* ```
|
|
4309
|
+
*/
|
|
4310
|
+
list(): Promise<APIResponse<Conflict[]>>;
|
|
4311
|
+
}
|
|
4312
|
+
|
|
4313
|
+
/**
|
|
4314
|
+
* Data Quality resource for the GunSpec SDK.
|
|
4315
|
+
*
|
|
4316
|
+
* Provides access to `/v1/data` endpoints for assessing database
|
|
4317
|
+
* coverage and per-record confidence scores.
|
|
4318
|
+
*
|
|
4319
|
+
* @module
|
|
4320
|
+
*/
|
|
4321
|
+
|
|
4322
|
+
/**
|
|
4323
|
+
* Resource class for interacting with the GunSpec Data Quality API.
|
|
4324
|
+
*
|
|
4325
|
+
* Wraps all `/v1/data` endpoints. Instantiated internally by the
|
|
4326
|
+
* {@link GunSpec} client and exposed as `client.dataQuality`.
|
|
4327
|
+
*
|
|
4328
|
+
* @example
|
|
4329
|
+
* ```typescript
|
|
4330
|
+
* import GunSpec from '@gunspec/sdk';
|
|
4331
|
+
*
|
|
4332
|
+
* const client = new GunSpec();
|
|
4333
|
+
*
|
|
4334
|
+
* // Check overall data coverage
|
|
4335
|
+
* const { data } = await client.dataQuality.coverage();
|
|
4336
|
+
* console.log(`${data.overallCoverage}% overall field coverage`);
|
|
4337
|
+
*
|
|
4338
|
+
* // Find low-confidence records
|
|
4339
|
+
* const lowConf = await client.dataQuality.confidence({ below: 0.3 });
|
|
4340
|
+
* ```
|
|
4341
|
+
*/
|
|
4342
|
+
declare class DataQualityResource {
|
|
4343
|
+
private readonly client;
|
|
4344
|
+
constructor(client: HttpClient);
|
|
4345
|
+
/**
|
|
4346
|
+
* Get overall data coverage statistics for the database.
|
|
4347
|
+
*
|
|
4348
|
+
* Returns per-field and aggregate coverage metrics showing what
|
|
4349
|
+
* percentage of records have data for each field.
|
|
4350
|
+
*
|
|
4351
|
+
* @returns Data coverage statistics including per-field percentages.
|
|
4352
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
4353
|
+
*
|
|
4354
|
+
* @example
|
|
4355
|
+
* ```typescript
|
|
4356
|
+
* const { data } = await client.dataQuality.coverage();
|
|
4357
|
+
* console.log(`Overall: ${data.overallCoverage}%`);
|
|
4358
|
+
* for (const field of data.fields) {
|
|
4359
|
+
* console.log(`${field.name}: ${field.coverage}%`);
|
|
4360
|
+
* }
|
|
4361
|
+
* ```
|
|
4362
|
+
*/
|
|
4363
|
+
coverage(): Promise<APIResponse<DataCoverage>>;
|
|
4364
|
+
/**
|
|
4365
|
+
* Get firearms with confidence scores below a specified threshold.
|
|
4366
|
+
*
|
|
4367
|
+
* Useful for identifying records that may need additional data
|
|
4368
|
+
* verification or enrichment.
|
|
4369
|
+
*
|
|
4370
|
+
* @param params - Optional threshold and pagination parameters.
|
|
4371
|
+
* @returns A paginated list of firearms with their confidence scores.
|
|
4372
|
+
* @throws {BadRequestError} If the threshold is outside the 0-1 range.
|
|
4373
|
+
* @throws {AuthenticationError} If the API key is missing or invalid.
|
|
4374
|
+
*
|
|
4375
|
+
* @example
|
|
4376
|
+
* ```typescript
|
|
4377
|
+
* const result = await client.dataQuality.confidence({
|
|
4378
|
+
* below: 0.5,
|
|
4379
|
+
* per_page: 25,
|
|
4380
|
+
* });
|
|
4381
|
+
* for (const item of result.data) {
|
|
4382
|
+
* console.log(`${item.name}: confidence ${item.confidenceScore}`);
|
|
4383
|
+
* }
|
|
4384
|
+
* ```
|
|
4385
|
+
*/
|
|
4386
|
+
confidence(params?: ConfidenceParams): Promise<PaginatedResponse<ConfidenceEntry>>;
|
|
4387
|
+
}
|
|
4388
|
+
|
|
4389
|
+
declare class FavoritesResource {
|
|
4390
|
+
private readonly client;
|
|
4391
|
+
constructor(client: HttpClient);
|
|
4392
|
+
list(params?: ListFavoritesParams): Promise<PaginatedResponse<Favorite>>;
|
|
4393
|
+
add(firearmId: string): Promise<APIResponse<FavoriteToggle>>;
|
|
4394
|
+
remove(firearmId: string): Promise<APIResponse<FavoriteToggle>>;
|
|
4395
|
+
}
|
|
4396
|
+
|
|
4397
|
+
declare class ReportsResource {
|
|
4398
|
+
private readonly client;
|
|
4399
|
+
constructor(client: HttpClient);
|
|
4400
|
+
create(params: CreateReportParams): Promise<APIResponse<DataReport>>;
|
|
4401
|
+
list(params?: ListReportsParams): Promise<PaginatedResponse<DataReport>>;
|
|
4402
|
+
}
|
|
4403
|
+
|
|
4404
|
+
declare class SupportResource {
|
|
4405
|
+
private readonly client;
|
|
4406
|
+
constructor(client: HttpClient);
|
|
4407
|
+
create(params: CreateTicketParams): Promise<APIResponse<SupportTicket>>;
|
|
4408
|
+
list(params?: ListTicketsParams): Promise<PaginatedResponse<SupportTicket>>;
|
|
4409
|
+
get(ticketId: string): Promise<APIResponse<SupportTicketDetail>>;
|
|
4410
|
+
reply(ticketId: string, params: CreateReplyParams): Promise<APIResponse<SupportTicketReply>>;
|
|
4411
|
+
}
|
|
4412
|
+
|
|
4413
|
+
declare class WebhooksResource {
|
|
4414
|
+
private readonly client;
|
|
4415
|
+
constructor(client: HttpClient);
|
|
4416
|
+
list(params?: ListWebhookEndpointsParams): Promise<PaginatedResponse<WebhookEndpoint>>;
|
|
4417
|
+
create(params: CreateWebhookEndpointParams): Promise<APIResponse<WebhookEndpoint>>;
|
|
4418
|
+
get(id: string): Promise<APIResponse<WebhookEndpoint>>;
|
|
4419
|
+
update(id: string, params: UpdateWebhookEndpointParams): Promise<APIResponse<WebhookEndpoint>>;
|
|
4420
|
+
delete(id: string): Promise<APIResponse<{
|
|
4421
|
+
deleted: boolean;
|
|
4422
|
+
}>>;
|
|
4423
|
+
test(id: string): Promise<APIResponse<WebhookTestResult>>;
|
|
4424
|
+
}
|
|
4425
|
+
|
|
4426
|
+
declare class UsageResource {
|
|
4427
|
+
private readonly client;
|
|
4428
|
+
constructor(client: HttpClient);
|
|
4429
|
+
get(params?: UsageParams): Promise<APIResponse<UsageStats>>;
|
|
4430
|
+
}
|
|
4431
|
+
|
|
4432
|
+
/**
|
|
4433
|
+
* Configuration options for the GunSpec client.
|
|
4434
|
+
*
|
|
4435
|
+
* @example
|
|
4436
|
+
* ```typescript
|
|
4437
|
+
* // Reads GUNSPEC_API_KEY from process.env automatically
|
|
4438
|
+
* const client = new GunSpec();
|
|
4439
|
+
*
|
|
4440
|
+
* // Or pass via environment variable explicitly
|
|
4441
|
+
* const client = new GunSpec({
|
|
4442
|
+
* apiKey: process.env.GUNSPEC_API_KEY,
|
|
4443
|
+
* });
|
|
4444
|
+
* ```
|
|
4445
|
+
*/
|
|
4446
|
+
interface ClientOptions {
|
|
4447
|
+
/**
|
|
4448
|
+
* API key for authentication. If not provided, reads from
|
|
4449
|
+
* the `GUNSPEC_API_KEY` environment variable.
|
|
4450
|
+
*/
|
|
4451
|
+
apiKey?: string;
|
|
4452
|
+
/**
|
|
4453
|
+
* Base URL for the API. Defaults to `https://api.gunspec.io`.
|
|
4454
|
+
*/
|
|
4455
|
+
baseURL?: string;
|
|
4456
|
+
/**
|
|
4457
|
+
* Request timeout in milliseconds. Defaults to 30000 (30s).
|
|
4458
|
+
*/
|
|
4459
|
+
timeout?: number;
|
|
4460
|
+
/**
|
|
4461
|
+
* Retry configuration for failed requests.
|
|
4462
|
+
*/
|
|
4463
|
+
retry?: RetryConfig;
|
|
4464
|
+
/**
|
|
4465
|
+
* Custom default headers to include with every request.
|
|
4466
|
+
*/
|
|
4467
|
+
defaultHeaders?: Record<string, string>;
|
|
4468
|
+
}
|
|
4469
|
+
/**
|
|
4470
|
+
* GunSpec.io API client — the main entry point for the SDK.
|
|
4471
|
+
*
|
|
4472
|
+
* Provides typed access to the firearms specification database API
|
|
4473
|
+
* through resource-oriented properties that mirror the API structure.
|
|
4474
|
+
*
|
|
4475
|
+
* @example
|
|
4476
|
+
* ```typescript
|
|
4477
|
+
* import { GunSpec } from '@gunspec/sdk';
|
|
4478
|
+
*
|
|
4479
|
+
* // Auto-reads GUNSPEC_API_KEY from environment
|
|
4480
|
+
* const client = new GunSpec();
|
|
4481
|
+
*
|
|
4482
|
+
* // List firearms with filters
|
|
4483
|
+
* const { data, pagination } = await client.firearms.list({
|
|
4484
|
+
* category: 'pistol',
|
|
4485
|
+
* status: 'in_production',
|
|
4486
|
+
* per_page: 50,
|
|
4487
|
+
* });
|
|
4488
|
+
*
|
|
4489
|
+
* // Get a specific firearm by slug
|
|
4490
|
+
* const { data: glock } = await client.firearms.get('glock-g17');
|
|
4491
|
+
*
|
|
4492
|
+
* // Search firearms
|
|
4493
|
+
* const results = await client.firearms.search({ q: 'beretta 92' });
|
|
4494
|
+
*
|
|
4495
|
+
* // Compare firearms side by side
|
|
4496
|
+
* const { data: comparison } = await client.firearms.compare({
|
|
4497
|
+
* ids: 'glock-g17,beretta-92fs,sig-sauer-p226',
|
|
4498
|
+
* });
|
|
4499
|
+
*
|
|
4500
|
+
* // Auto-paginate through all results
|
|
4501
|
+
* for await (const firearm of client.firearms.listAutoPaging({ category: 'rifle' })) {
|
|
4502
|
+
* console.log(firearm.name);
|
|
4503
|
+
* }
|
|
4504
|
+
*
|
|
4505
|
+
* // Game development features
|
|
4506
|
+
* const { data: tierList } = await client.game.tierList({ stat: 'damage' });
|
|
4507
|
+
* const { data: matchup } = await client.game.matchups({ a: 'ak-47', b: 'm16a4' });
|
|
4508
|
+
*
|
|
4509
|
+
* // Statistics
|
|
4510
|
+
* const { data: summary } = await client.stats.summary();
|
|
4511
|
+
* ```
|
|
4512
|
+
*/
|
|
4513
|
+
declare class GunSpec {
|
|
4514
|
+
/** Firearms specifications, search, comparison, and related data */
|
|
4515
|
+
readonly firearms: FirearmsResource;
|
|
4516
|
+
/** Firearm manufacturers and their products */
|
|
4517
|
+
readonly manufacturers: ManufacturersResource;
|
|
4518
|
+
/** Ammunition calibers and cartridge specifications */
|
|
4519
|
+
readonly calibers: CalibersResource;
|
|
4520
|
+
/** Firearm categories (pistol, rifle, shotgun, etc.) */
|
|
4521
|
+
readonly categories: CategoriesResource;
|
|
4522
|
+
/** Aggregate statistics across the database */
|
|
4523
|
+
readonly stats: StatsResource;
|
|
4524
|
+
/** Game development tools — balance reports, tier lists, matchups */
|
|
4525
|
+
readonly game: GameResource;
|
|
4526
|
+
/** Versioned game stats snapshots for pinning game builds */
|
|
4527
|
+
readonly gameStats: GameStatsResource;
|
|
4528
|
+
/** Ammunition loads, ballistics, and bullet data */
|
|
4529
|
+
readonly ammunition: AmmunitionResource;
|
|
4530
|
+
/** Countries and their military/law enforcement arsenals */
|
|
4531
|
+
readonly countries: CountriesResource;
|
|
4532
|
+
/** Armed conflicts and the firearms used in them */
|
|
4533
|
+
readonly conflicts: ConflictsResource;
|
|
4534
|
+
/** Data quality metrics (Enterprise tier) */
|
|
4535
|
+
readonly dataQuality: DataQualityResource;
|
|
4536
|
+
/** User's favorited firearms */
|
|
4537
|
+
readonly favorites: FavoritesResource;
|
|
4538
|
+
/** Data quality reports */
|
|
4539
|
+
readonly reports: ReportsResource;
|
|
4540
|
+
/** Support tickets (paid tiers) */
|
|
4541
|
+
readonly support: SupportResource;
|
|
4542
|
+
/** Webhook endpoint management (studio+ tier) */
|
|
4543
|
+
readonly webhooks: WebhooksResource;
|
|
4544
|
+
/** API usage statistics */
|
|
4545
|
+
readonly usage: UsageResource;
|
|
4546
|
+
/** The underlying HTTP client (for advanced use) */
|
|
4547
|
+
private readonly _client;
|
|
4548
|
+
constructor(options?: ClientOptions);
|
|
4549
|
+
}
|
|
4550
|
+
|
|
4551
|
+
/** Current SDK version */
|
|
4552
|
+
declare const VERSION = "0.1.0";
|
|
4553
|
+
|
|
4554
|
+
export { APIError, type APIErrorResponse, type APIResponse, type ActionTypesParams, type AdoptionByCountryParams, type AdoptionByTypeParams, type AdoptionMap, type Ammunition, type AmmunitionBallisticsParams, AmmunitionResource, type AuthConfig, AuthenticationError, BadRequestError, type BalanceReport, type BalanceReportParams, type BallisticsResult, type ByActionParams, type ByConflictParams, type ByDesignerParams, type ByEraParams, type ByFeatureParams, type ByMaterialParams, type CalculateBallisticsParams, type Caliber, type CaliberBallisticsParams, type CaliberPopularityByEraParams, CalibersResource, CategoriesResource, type Category, type ClientOptions, type CompareCalibersParams, type CompareFirearmsParams, type ConfidenceParams, type Conflict, ConflictsResource, ConnectionError, CountriesResource, type Country, type CountryArsenal, type CreateReplyParams, type CreateReportParams, type CreateTicketParams, type CreateWebhookEndpointParams, type DataCoverage, DataQualityResource, type DataReport, type Dimensions, type ErrorBody, type FamilyTree, type Favorite, type FavoriteToggle, FavoritesResource, type FeatureFrequencyParams, type FilterOptions, type Firearm, type FirearmImage, type FirearmUser, FirearmsResource, type GameMetaParams, type GameProfile, GameResource, type GameStats, GameStatsResource, type GameStatsVersion, GunSpec, GunSpecError, type HeadToHead, type HeadToHeadParams, HttpClient, type HttpClientConfig, InternalServerError, type ListAmmunitionParams, type ListCalibersParams, type ListFavoritesParams, type ListFirearmsParams, type ListManufacturersParams, type ListReportsParams, type ListSnapshotFirearmsParams, type ListTicketsParams, type ListWebhookEndpointsParams, type LoadFirearmParams, type Manufacturer, type ManufacturerStats, type ManufacturerTimeline, ManufacturersResource, type MatchupResult, type MatchupsParams, NotFoundError, Page, type PageFetcher, type PaginatedResponse, type PaginationMeta, type PaginationParams, PermissionError, type PopularCalibersParams, type PowerRating, type PowerRatingParams, type ProlificManufacturersParams, type RandomFirearmParams, RateLimitError, type RateLimitInfo, ReportsResource, type RequestConfig, type ResolvedRetryConfig, type RetryConfig, type RoleRoster, type RoleRosterItem, type RoleRosterParams, type SearchFirearmsParams, type Silhouette, type SilhouetteParams, type SimilarFirearm, type StatDistribution, type StatDistributionParams, StatsResource, type StatsSummary, SupportResource, type SupportTicket, type SupportTicketDetail, type SupportTicketReply, type TierList, type TierListParams, type TimelineParams, TimeoutError, type TopFirearmsParams, type UpdateWebhookEndpointParams, type UsageParams, UsageResource, type UsageStats, VERSION, type WebhookEndpoint, type WebhookTestResult, WebhooksResource, buildAuthHeaders, createAPIError, createPage, resolveApiKey };
|