comic-vine-sdk 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,11 +2,7 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
- ## [1.3.0](https://github.com/AllyMurray/comic-vine/compare/v1.2.8...v1.3.0) (2025-07-03)
6
-
7
- ### Features
8
-
9
- - complete migration from projen to standard npm project ([4c3ef8d](https://github.com/AllyMurray/comic-vine/commit/4c3ef8dbac71f10b17c6154421eaa750f1fa4ebf))
5
+ ### [1.3.1](https://github.com/AllyMurray/comic-vine/compare/v1.3.0...v1.3.1) (2025-07-03)
10
6
 
11
7
  ## [1.2.8] - 2024-01-01
12
8
 
@@ -0,0 +1,294 @@
1
+ # Contributing to Comic Vine SDK
2
+
3
+ Thank you for your interest in contributing to the Comic Vine SDK! This document provides guidelines and information to help you contribute effectively to the project.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Code of Conduct](#code-of-conduct)
8
+ - [Getting Started](#getting-started)
9
+ - [Development Setup](#development-setup)
10
+ - [Development Workflow](#development-workflow)
11
+ - [Code Standards](#code-standards)
12
+ - [Testing](#testing)
13
+ - [Submitting Changes](#submitting-changes)
14
+ - [Project Structure](#project-structure)
15
+ - [Resources](#resources)
16
+
17
+ ## Code of Conduct
18
+
19
+ This project adheres to a [Code of Conduct](./CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [allymurray88@gmail.com](mailto:allymurray88@gmail.com).
20
+
21
+ ## Getting Started
22
+
23
+ ### Prerequisites
24
+
25
+ Before you begin, ensure you have the following installed:
26
+
27
+ - **Node.js**: Version 20.0.0 or higher
28
+ - **pnpm**: Version 9.15.4+ (specified in package.json)
29
+ ```bash
30
+ npm install -g pnpm@9.15.4
31
+ ```
32
+
33
+ ### Development Setup
34
+
35
+ 1. **Fork and Clone**
36
+
37
+ ```bash
38
+ git clone https://github.com/your-username/comic-vine.git
39
+ cd comic-vine
40
+ ```
41
+
42
+ 2. **Install Dependencies**
43
+
44
+ ```bash
45
+ pnpm install
46
+ ```
47
+
48
+ 3. **Verify Setup**
49
+ ```bash
50
+ pnpm test
51
+ ```
52
+
53
+ If all tests pass, you're ready to start developing!
54
+
55
+ ## Development Workflow
56
+
57
+ ### Creating a Branch
58
+
59
+ 1. Create a feature branch from `main`:
60
+
61
+ ```bash
62
+ git checkout -b feature/your-feature-name
63
+ # or
64
+ git checkout -b fix/issue-description
65
+ ```
66
+
67
+ 2. Use descriptive branch names:
68
+ - `feature/add-search-pagination`
69
+ - `fix/handle-rate-limiting`
70
+ - `docs/update-readme-examples`
71
+
72
+ ### Making Changes
73
+
74
+ 1. **Write Code**: Follow the [Code Standards](#code-standards) below
75
+ 2. **Add Tests**: Ensure new functionality has corresponding tests
76
+ 3. **Run Tests**: `pnpm test` to run tests and linting
77
+ 4. **Build**: `pnpm compile` to ensure your changes compile correctly
78
+
79
+ ### Commit Messages
80
+
81
+ Follow conventional commit format:
82
+
83
+ ```
84
+ type(scope): description
85
+
86
+ [optional body]
87
+
88
+ [optional footer]
89
+ ```
90
+
91
+ **Types:**
92
+
93
+ - `feat`: New feature
94
+ - `fix`: Bug fix
95
+ - `docs`: Documentation changes
96
+ - `style`: Code style changes (formatting, etc.)
97
+ - `refactor`: Code refactoring
98
+ - `test`: Adding or updating tests
99
+ - `chore`: Maintenance tasks
100
+
101
+ **Examples:**
102
+
103
+ ```
104
+ feat(resources): add pagination support to character list
105
+ fix(http-client): handle network timeout errors
106
+ docs(readme): update installation instructions
107
+ ```
108
+
109
+ ## Code Standards
110
+
111
+ ### TypeScript Guidelines
112
+
113
+ - **Type Safety**: Prefer explicit types over `any`
114
+ - **Interfaces**: Use interfaces for object shapes
115
+ - **Generics**: Leverage generics for reusable components
116
+ - **Strict Mode**: The project uses strict TypeScript settings
117
+
118
+ ### Code Style
119
+
120
+ The project uses **ESLint** and **Prettier** for code formatting:
121
+
122
+ ```bash
123
+ # Auto-fix linting issues and format code
124
+ pnpm lint
125
+
126
+ # Check linting without fixing
127
+ npx eslint src --ext .ts
128
+ ```
129
+
130
+ **Key Style Rules:**
131
+
132
+ - Use camelCase for variables and functions
133
+ - Use PascalCase for classes and interfaces
134
+ - Prefer `const` over `let` when possible
135
+ - Use meaningful variable names
136
+ - Add JSDoc comments for public APIs
137
+
138
+ ### Import Organization
139
+
140
+ Imports should be organized as follows:
141
+
142
+ ```typescript
143
+ // 1. Built-in Node.js modules
144
+ import { readFile } from 'fs/promises';
145
+
146
+ // 2. External dependencies
147
+ import axios from 'axios';
148
+ import { z } from 'zod';
149
+
150
+ // 3. Internal modules (ordered alphabetically)
151
+ import { BaseResource } from './base-resource';
152
+ import { HttpClient } from './http-client';
153
+ ```
154
+
155
+ ## Testing
156
+
157
+ ### Running Tests
158
+
159
+ ```bash
160
+ # Run all tests with linting
161
+ pnpm test
162
+
163
+ # Run tests only (without linting)
164
+ pnpm test:run
165
+
166
+ # Run tests in watch mode
167
+ npx vitest --dir=src
168
+ ```
169
+
170
+ ### Writing Tests
171
+
172
+ 1. **Location**: Place test files alongside source files with `.test.ts` extension
173
+ 2. **Naming**: Use descriptive test names that explain the behavior being tested
174
+ 3. **Structure**: Follow Arrange-Act-Assert pattern
175
+
176
+ **Example Test:**
177
+
178
+ ```typescript
179
+ import { describe, test, expect } from 'vitest';
180
+
181
+ describe('ResourceName', () => {
182
+ test('should return correct data when field list is specified', async () => {
183
+ // Arrange
184
+ const expectedFields = ['id', 'name'];
185
+
186
+ // Act
187
+ const result = await resource.retrieve(123, { fieldList: expectedFields });
188
+
189
+ // Assert
190
+ expect(Object.keys(result)).toEqual(expectedFields);
191
+ });
192
+ });
193
+ ```
194
+
195
+ ### Test Coverage
196
+
197
+ - Write tests for all new functionality
198
+ - Include both success and error scenarios
199
+ - Mock external dependencies using **nock** for HTTP requests
200
+ - Test files are located in `src/__mocks__/` for mock data
201
+
202
+ ## Submitting Changes
203
+
204
+ ### Pull Request Process
205
+
206
+ 1. **Update Documentation**: Ensure README, JSDoc, and other docs reflect your changes
207
+
208
+ 2. **Verify Quality Checks**: All checks must pass before merging
209
+
210
+ ```bash
211
+ pnpm test:run # All tests pass
212
+ pnpm lint # No linting errors
213
+ pnpm compile # Code compiles successfully
214
+ ```
215
+
216
+ 3. **Create Pull Request**:
217
+ - Use a descriptive title
218
+ - Reference any related issues
219
+ - Provide clear description of changes
220
+ - Include examples if adding new features
221
+
222
+ 4. **Review Process**:
223
+ - Maintainers will review your PR
224
+ - Address any feedback promptly
225
+ - See [CODE_REVIEW.md](./CODE_REVIEW.md) for review criteria
226
+
227
+ ### Pre-commit Hooks
228
+
229
+ The project uses **Husky** and **lint-staged** to ensure code quality:
230
+
231
+ - **Auto-formatting**: Prettier formats code on commit
232
+ - **Linting**: ESLint checks are enforced
233
+ - **Type checking**: TypeScript compilation is verified
234
+
235
+ If pre-commit hooks fail, fix the issues before committing:
236
+
237
+ ```bash
238
+ pnpm lint # Fix linting issues
239
+ git add . # Stage the fixes
240
+ git commit # Try committing again
241
+ ```
242
+
243
+ ## Project Structure
244
+
245
+ ```
246
+ src/
247
+ ├── comic-vine.ts # Main SDK class
248
+ ├── errors/ # Custom error classes
249
+ ├── http-client/ # HTTP client and URL builder
250
+ ├── options/ # Configuration options
251
+ ├── resources/ # API resource implementations
252
+ │ ├── base-resource.ts # Base class for all resources
253
+ │ ├── character/ # Character-specific code
254
+ │ ├── issue/ # Issue-specific code
255
+ │ └── ... # Other Comic Vine resources
256
+ ├── types/ # TypeScript type definitions
257
+ └── utils/ # Utility functions
258
+ ```
259
+
260
+ ### Adding New Resources
261
+
262
+ When adding support for a new Comic Vine API resource:
263
+
264
+ 1. Create a new directory under `src/resources/`
265
+ 2. Implement the resource class extending `BaseResource`
266
+ 3. Add TypeScript types in a `types/` subdirectory
267
+ 4. Write comprehensive tests
268
+ 5. Update the main `ComicVine` class to include the new resource
269
+ 6. Add mock data for testing
270
+
271
+ ## Resources
272
+
273
+ ### Documentation
274
+
275
+ - [Comic Vine API Documentation](https://comicvine.gamespot.com/api/documentation)
276
+ - [Project README](./README.md)
277
+ - [Code Review Guidelines](./CODE_REVIEW.md)
278
+
279
+ ### Getting Help
280
+
281
+ - **Issues**: [GitHub Issues](https://github.com/AllyMurray/comic-vine/issues)
282
+ - **Discussions**: Use GitHub Discussions for questions
283
+
284
+ ### Development Tools
285
+
286
+ - **Package Manager**: [pnpm](https://pnpm.io/)
287
+ - **Testing**: [Vitest](https://vitest.dev/)
288
+ - **Linting**: [ESLint](https://eslint.org/) + [TypeScript ESLint](https://typescript-eslint.io/)
289
+ - **Formatting**: [Prettier](https://prettier.io/)
290
+ - **Git Hooks**: [Husky](https://typicode.github.io/husky/)
291
+
292
+ ---
293
+
294
+ Thank you for contributing to Comic Vine SDK! Your contributions help make this library better for everyone. 🚀
package/README.md CHANGED
@@ -1,10 +1,21 @@
1
1
  # Comic Vine SDK
2
2
 
3
+ [![NPM Version](https://img.shields.io/npm/v/comic-vine-sdk)](https://www.npmjs.com/package/comic-vine-sdk)
4
+ [![License](https://img.shields.io/npm/l/comic-vine-sdk)](https://github.com/AllyMurray/comic-vine/blob/main/LICENSE)
5
+ [![Node.js Version](https://img.shields.io/node/v/comic-vine-sdk)](https://nodejs.org/)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue)](https://www.typescriptlang.org/)
7
+
3
8
  The Comic Vine SDK provides convenient access to the [Comic Vine API][comic-vine-api] from applications written in JavaScript/TypeScript. The API provides full access to the structured-wiki content.
4
9
 
5
10
  ## Table of Contents
6
11
 
12
+ - [Requirements](#requirements)
7
13
  - [Installation](#installation)
14
+ - [Quick Start](#quick-start)
15
+ - [API Key Security](#api-key-security)
16
+ - [Rate Limiting](#rate-limiting)
17
+ - [Error Handling](#error-handling)
18
+ - [Advanced Usage](#advanced-usage)
8
19
  - [Roadmap](#roadmap)
9
20
  - [Comic Vine Resources](#comic-vine-resources)
10
21
  - [Usage/Examples](#usageexamples)
@@ -18,19 +29,426 @@ The Comic Vine SDK provides convenient access to the [Comic Vine API][comic-vine
18
29
  - [Run Locally](#run-locally)
19
30
  - [Authors](#authors)
20
31
 
32
+ ## Requirements
33
+
34
+ - Node.js 20.0.0 or higher
35
+ - npm, yarn, or pnpm
36
+
21
37
  ## Installation
22
38
 
23
- Install the package with:
39
+ Choose your preferred package manager:
40
+
41
+ **pnpm**
42
+
43
+ ```sh
44
+ pnpm add comic-vine-sdk
45
+ ```
46
+
47
+ **npm**
24
48
 
25
49
  ```sh
26
50
  npm install comic-vine-sdk
27
- # or
51
+ ```
52
+
53
+ **yarn**
54
+
55
+ ```sh
28
56
  yarn add comic-vine-sdk
29
57
  ```
30
58
 
59
+ ## Quick Start
60
+
61
+ ```js
62
+ import ComicVine from 'comic-vine-sdk';
63
+
64
+ // Initialize the client
65
+ const comicVine = new ComicVine('your-api-key-here');
66
+
67
+ // Fetch a single publisher
68
+ const publisher = await comicVine.publisher.retrieve(1859);
69
+ console.log(publisher.name);
70
+
71
+ // Fetch a list of issues
72
+ const issues = await comicVine.issue.list({ limit: 10 });
73
+ console.log(issues.data.map((issue) => issue.name));
74
+
75
+ // Fetch with field limiting
76
+ const limitedIssue = await comicVine.issue.retrieve(1234, {
77
+ fieldList: ['id', 'name', 'description'],
78
+ });
79
+ console.log(limitedIssue.name);
80
+ ```
81
+
82
+ ## API Key Security
83
+
84
+ ⚠️ **Important**: Never expose your API key in client-side code or commit it to version control.
85
+
86
+ ### Environment Variables (Recommended)
87
+
88
+ **Create a .env file:**
89
+
90
+ ```bash
91
+ # .env file
92
+ COMIC_VINE_API_KEY=your-api-key-here
93
+ ```
94
+
95
+ **Use in your application:**
96
+
97
+ ```js
98
+ import ComicVine from 'comic-vine-sdk';
99
+
100
+ const comicVine = new ComicVine(process.env.COMIC_VINE_API_KEY);
101
+ ```
102
+
103
+ ### Browser Usage
104
+
105
+ The Comic Vine API doesn't support CORS. For browser usage, you'll need:
106
+
107
+ - A backend proxy to make API calls
108
+ - Server-side API key storage (never send keys to the browser)
109
+
110
+ **Example proxy setup:**
111
+
112
+ ```js
113
+ // Backend API route (Express.js example)
114
+ app.get('/api/comic-vine/publisher/:id', async (req, res) => {
115
+ try {
116
+ const comicVine = new ComicVine(process.env.COMIC_VINE_API_KEY);
117
+ const publisher = await comicVine.publisher.retrieve(req.params.id);
118
+ res.json(publisher);
119
+ } catch (error) {
120
+ res.status(500).json({ error: error.message });
121
+ }
122
+ });
123
+ ```
124
+
31
125
  ## TypeScript Typings
32
126
 
33
- There's a good change you may find an issue with the typings in the API response objects. They were generated using sample data from the API, if you find a problem [open an issue](https://github.com/AllyMurray/comic-vine/issues/new) detailing the problem along with the request details so I can add that request to the sample dataset. While you wait for it to be fixed add `// @ts-expect-error` above the line causing the problem. This will allow you to compile in the meantime but will flag when the problem has been fixed.
127
+ There's a good chance you may find an issue with the typings in the API response objects. They were generated using sample data from the API, if you find a problem [open an issue](https://github.com/AllyMurray/comic-vine/issues/new) detailing the problem along with the request details so I can add that request to the sample dataset. While you wait for it to be fixed add `// @ts-expect-error` above the line causing the problem. This will allow you to compile in the meantime but will flag when the problem has been fixed.
128
+
129
+ ## Rate Limiting
130
+
131
+ The Comic Vine API implements rate limiting to ensure fair usage and API health for all users.
132
+
133
+ > ⚠️ **Note**: This library will soon include built-in solutions for caching, request deduplication, and rate limiting. The examples below are temporary workarounds until these features are available.
134
+
135
+ ### Limits
136
+
137
+ - **200 requests per resource per hour** - Official limit per user
138
+ - **Velocity detection** - Prevents too many requests per second
139
+ - **Temporary blocks** - May occur if limits are exceeded
140
+
141
+ ### Best Practices
142
+
143
+ **Cache responses** to avoid duplicate requests:
144
+
145
+ ```js
146
+ // Example: Simple in-memory cache
147
+ const cache = new Map();
148
+
149
+ async function getCachedPublisher(id) {
150
+ const cacheKey = `publisher-${id}`;
151
+
152
+ if (cache.has(cacheKey)) {
153
+ return cache.get(cacheKey);
154
+ }
155
+
156
+ const publisher = await comicVine.publisher.retrieve(id);
157
+ cache.set(cacheKey, publisher);
158
+
159
+ return publisher;
160
+ }
161
+ ```
162
+
163
+ **Implement delays** between requests:
164
+
165
+ ```js
166
+ // Example: Add delay between requests
167
+ async function fetchMultipleIssues(ids) {
168
+ const issues = [];
169
+
170
+ for (const id of ids) {
171
+ const issue = await comicVine.issue.retrieve(id);
172
+ issues.push(issue);
173
+
174
+ // Wait 100ms between requests
175
+ await new Promise((resolve) => setTimeout(resolve, 100));
176
+ }
177
+
178
+ return issues;
179
+ }
180
+ ```
181
+
182
+ **Use pagination wisely**:
183
+
184
+ ```js
185
+ // Instead of making many small requests
186
+ const issues = await comicVine.issue.list({ limit: 100 }); // Better
187
+ // Rather than
188
+ const issues = await comicVine.issue.list({ limit: 10 }); // Less efficient
189
+ ```
190
+
191
+ ## Error Handling
192
+
193
+ The Comic Vine SDK provides specific error types to help you handle different failure scenarios gracefully.
194
+
195
+ ### Error Types
196
+
197
+ All errors extend the base `BaseError` class and include:
198
+
199
+ - `message`: Human-readable error description
200
+ - `help`: Guidance on how to resolve the issue
201
+
202
+ **Common Error Types:**
203
+
204
+ | Error Type | When It Occurs | How to Handle |
205
+ | ------------------------------ | ----------------------- | -------------------------------- |
206
+ | `ComicVineUnauthorizedError` | Invalid API key | Check your API key |
207
+ | `ComicVineObjectNotFoundError` | Resource doesn't exist | Verify the resource ID |
208
+ | `OptionsValidationError` | Invalid request options | Check your parameters |
209
+ | `ComicVineGenericRequestError` | API request failed | Retry or check API status |
210
+ | `ComicVineSubscriberOnlyError` | Premium content access | Requires Comic Vine subscription |
211
+
212
+ ### Basic Error Handling
213
+
214
+ **Simple try-catch:**
215
+
216
+ ```js
217
+ import ComicVine from 'comic-vine-sdk';
218
+
219
+ const comicVine = new ComicVine('your-api-key-here');
220
+
221
+ try {
222
+ const publisher = await comicVine.publisher.retrieve(999999);
223
+ console.log(publisher.name);
224
+ } catch (error) {
225
+ console.error('Error:', error.message);
226
+ console.error('Help:', error.help);
227
+ }
228
+ ```
229
+
230
+ ### Specific Error Handling
231
+
232
+ **Handle different error types:**
233
+
234
+ ```js
235
+ import ComicVine, {
236
+ ComicVineUnauthorizedError,
237
+ ComicVineObjectNotFoundError,
238
+ OptionsValidationError,
239
+ } from 'comic-vine-sdk';
240
+
241
+ const comicVine = new ComicVine('your-api-key-here');
242
+
243
+ try {
244
+ const issue = await comicVine.issue.retrieve(999999);
245
+ } catch (error) {
246
+ if (error instanceof ComicVineUnauthorizedError) {
247
+ console.error(
248
+ 'Invalid API key. Get one from: https://comicvine.gamespot.com/api/',
249
+ );
250
+ } else if (error instanceof ComicVineObjectNotFoundError) {
251
+ console.error('Issue not found. Please check the ID.');
252
+ } else if (error instanceof OptionsValidationError) {
253
+ console.error('Invalid request parameters:', error.message);
254
+ } else {
255
+ console.error('Unexpected error:', error.message);
256
+ }
257
+ }
258
+ ```
259
+
260
+ ### Robust Error Handling with Retry
261
+
262
+ **Implement retry logic for transient errors:**
263
+
264
+ ```js
265
+ async function fetchWithRetry(fetchFn, maxRetries = 3) {
266
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
267
+ try {
268
+ return await fetchFn();
269
+ } catch (error) {
270
+ // Don't retry on client errors
271
+ if (
272
+ error instanceof ComicVineUnauthorizedError ||
273
+ error instanceof ComicVineObjectNotFoundError ||
274
+ error instanceof OptionsValidationError
275
+ ) {
276
+ throw error;
277
+ }
278
+
279
+ // Retry on server errors
280
+ if (attempt === maxRetries) {
281
+ throw error;
282
+ }
283
+
284
+ // Wait before retrying (exponential backoff)
285
+ const delay = Math.pow(2, attempt) * 1000;
286
+ await new Promise((resolve) => setTimeout(resolve, delay));
287
+ }
288
+ }
289
+ }
290
+
291
+ // Usage
292
+ try {
293
+ const publisher = await fetchWithRetry(() =>
294
+ comicVine.publisher.retrieve(1859),
295
+ );
296
+ console.log(publisher.name);
297
+ } catch (error) {
298
+ console.error('Failed after retries:', error.message);
299
+ }
300
+ ```
301
+
302
+ ### Error Handling in Lists
303
+
304
+ **Handle errors when processing multiple items:**
305
+
306
+ ```js
307
+ async function fetchMultipleIssues(ids) {
308
+ const results = [];
309
+ const errors = [];
310
+
311
+ for (const id of ids) {
312
+ try {
313
+ const issue = await comicVine.issue.retrieve(id);
314
+ results.push({ id, issue });
315
+ } catch (error) {
316
+ errors.push({ id, error: error.message });
317
+ }
318
+ }
319
+
320
+ return { results, errors };
321
+ }
322
+
323
+ // Usage
324
+ const { results, errors } = await fetchMultipleIssues([1, 2, 999999]);
325
+ console.log(`Successfully fetched: ${results.length}`);
326
+ console.log(`Errors: ${errors.length}`);
327
+ ```
328
+
329
+ ## Advanced Usage
330
+
331
+ ### Available Filters
332
+
333
+ Common filter options for list methods:
334
+
335
+ **Filter by name:**
336
+
337
+ ```js
338
+ const issues = await comicVine.issue.list({
339
+ filter: { name: 'The Boys' },
340
+ });
341
+ ```
342
+
343
+ **Filter by date range:**
344
+
345
+ ```js
346
+ const recentIssues = await comicVine.issue.list({
347
+ filter: {
348
+ date_added: '2024-01-01 00:00:00|2024-12-31 23:59:59',
349
+ },
350
+ });
351
+ ```
352
+
353
+ **Multiple filters:**
354
+
355
+ ```js
356
+ const filteredIssues = await comicVine.issue.list({
357
+ filter: {
358
+ name: 'Spider-Man',
359
+ date_added: '2024-01-01 00:00:00|2024-12-31 23:59:59',
360
+ },
361
+ });
362
+ ```
363
+
364
+ **Publisher-specific content:**
365
+
366
+ ```js
367
+ const marvelIssues = await comicVine.issue.list({
368
+ filter: {
369
+ publisher: 'Marvel Comics',
370
+ },
371
+ limit: 50,
372
+ });
373
+ ```
374
+
375
+ ### Common Field Lists
376
+
377
+ **Minimal issue data:**
378
+
379
+ ```js
380
+ const lightIssue = await comicVine.issue.retrieve(1234, {
381
+ fieldList: ['id', 'name', 'issue_number'],
382
+ });
383
+ ```
384
+
385
+ **Full issue details:**
386
+
387
+ ```js
388
+ const fullIssue = await comicVine.issue.retrieve(1234, {
389
+ fieldList: ['id', 'name', 'description', 'cover_date', 'image', 'volume'],
390
+ });
391
+ ```
392
+
393
+ **Character essentials:**
394
+
395
+ ```js
396
+ const character = await comicVine.character.retrieve(1234, {
397
+ fieldList: ['id', 'name', 'description', 'image', 'publisher', 'powers'],
398
+ });
399
+ ```
400
+
401
+ **Publisher overview:**
402
+
403
+ ```js
404
+ const publisher = await comicVine.publisher.retrieve(1234, {
405
+ fieldList: [
406
+ 'id',
407
+ 'name',
408
+ 'description',
409
+ 'image',
410
+ 'date_added',
411
+ 'location_city',
412
+ ],
413
+ });
414
+ ```
415
+
416
+ ### Sorting and Ordering
417
+
418
+ **Sort by date (newest first):**
419
+
420
+ ```js
421
+ const recentIssues = await comicVine.issue.list({
422
+ sort: 'date_added:desc',
423
+ limit: 10,
424
+ });
425
+ ```
426
+
427
+ **Sort by name:**
428
+
429
+ ```js
430
+ const sortedCharacters = await comicVine.character.list({
431
+ sort: 'name:asc',
432
+ limit: 100,
433
+ });
434
+ ```
435
+
436
+ ### Complex Queries
437
+
438
+ **Combine multiple options:**
439
+
440
+ ```js
441
+ const complexQuery = await comicVine.issue.list({
442
+ filter: {
443
+ name: 'Spider-Man',
444
+ date_added: '2024-01-01 00:00:00|2024-12-31 23:59:59',
445
+ },
446
+ fieldList: ['id', 'name', 'issue_number', 'cover_date', 'image'],
447
+ sort: 'cover_date:desc',
448
+ limit: 25,
449
+ offset: 0,
450
+ });
451
+ ```
34
452
 
35
453
  ## Roadmap
36
454
 
@@ -82,7 +500,7 @@ const comicVine = new ComicVine('your-api-key-here');
82
500
 
83
501
  comicVine.publisher
84
502
  .retrieve(1859)
85
- .then((customer) => console.log(customer.id))
503
+ .then((publisher) => console.log(publisher.id))
86
504
  .catch((error) => console.error(error));
87
505
  ```
88
506
 
@@ -160,7 +578,7 @@ const comicVine = new ComicVine('your-api-key-here');
160
578
 
161
579
  ### Fetch a resource list
162
580
 
163
- All resources have a retrieve method, the following example retrieves a list of publishers
581
+ All resources have a list method, the following example retrieves a list of publishers
164
582
 
165
583
  ```js
166
584
  import ComicVine from 'comic-vine-sdk';
@@ -188,7 +606,7 @@ const comicVine = new ComicVine('your-api-key-here');
188
606
 
189
607
  (async () => {
190
608
  try {
191
- const issue = await comicVine.issue.retrieve(id, {
609
+ const issue = await comicVine.issue.retrieve(1234, {
192
610
  fieldList: ['id', 'name', 'description'],
193
611
  });
194
612
 
@@ -219,18 +637,22 @@ const comicVine = new ComicVine('your-api-key-here');
219
637
 
220
638
  (async () => {
221
639
  try {
222
- const limit: 50;
223
- const filter: { name: 'The Boys' },
640
+ const limit = 50;
641
+ const filter = { name: 'The Boys' };
224
642
 
225
643
  // Retrieve the first 50 issues of The Boys (Page 1)
226
644
  const issuesPage1 = await comicVine.issue.list({ limit, filter });
227
645
  console.log(`Total issues: ${issuesPage1.data.length}`);
228
- console.log(issuesPage1.data.map(issue => issue.name).join(', '));
646
+ console.log(issuesPage1.data.map((issue) => issue.name).join(', '));
229
647
 
230
648
  // Retrieve the next 50 issues of The Boys (Page 2)
231
- const issuesPage2 = await comicVine.issue.list({ limit, filter, offset: 50 });
649
+ const issuesPage2 = await comicVine.issue.list({
650
+ limit,
651
+ filter,
652
+ offset: 50,
653
+ });
232
654
  console.log(`Total issues: ${issuesPage2.data.length}`);
233
- console.log(issuesPage2.data.map(issue => issue.name).join(', '));
655
+ console.log(issuesPage2.data.map((issue) => issue.name).join(', '));
234
656
  } catch (error) {
235
657
  console.error(error);
236
658
  }
@@ -256,7 +678,7 @@ const comicVine = new ComicVine('your-api-key-here');
256
678
 
257
679
  let issueNames = [];
258
680
  for await (const issue of comicVine.issue.list(listOptions)) {
259
- issueName.push(issue.name);
681
+ issueNames.push(issue.name);
260
682
  }
261
683
 
262
684
  console.log(`Total issues: ${issueNames.length}`);
package/package.json CHANGED
@@ -66,12 +66,12 @@
66
66
  "metadata"
67
67
  ],
68
68
  "engines": {
69
- "node": ">= 18.0.0"
69
+ "node": ">= 20.0.0"
70
70
  },
71
71
  "main": "lib/cjs/index.js",
72
72
  "license": "MIT",
73
73
  "homepage": "https://github.com/AllyMurray/comic-vine#readme",
74
- "version": "1.3.0",
74
+ "version": "1.3.1",
75
75
  "bugs": {
76
76
  "url": "https://github.com/AllyMurray/comic-vine/issues"
77
77
  },