@pfdev/api-types 3.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -62
- package/index.ts +1 -1
- package/package.json +5 -2
- package/v3.ts +57 -37
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @pfdev/api-types
|
|
2
2
|
|
|
3
|
-
TypeScript types for PF API V3, directly
|
|
3
|
+
TypeScript types for PF API V3, synced directly from TypeBox schemas in pfapi-fs.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
@@ -13,98 +13,179 @@ npm install @pfdev/api-types
|
|
|
13
13
|
### Use in React/React Native
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
|
-
import
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
16
|
+
import { useState, useEffect } from 'react';
|
|
17
|
+
import type { SetDetail } from '@pfdev/api-types';
|
|
18
|
+
|
|
19
|
+
function SetDisplay({ setId }: { setId: string }) {
|
|
20
|
+
const [set, setSet] = useState<SetDetail | null>(null);
|
|
21
|
+
const [loading, setLoading] = useState(true);
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const fetchSet = async () => {
|
|
25
|
+
const response = await fetch(`/api/v3/sets/${setId}`);
|
|
26
|
+
const data: SetDetail = await response.json();
|
|
27
|
+
setSet(data);
|
|
28
|
+
setLoading(false);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
fetchSet();
|
|
32
|
+
}, [setId]);
|
|
33
|
+
|
|
34
|
+
if (loading) return <div>Loading...</div>;
|
|
35
|
+
if (!set) return <div>Not found</div>;
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div>
|
|
39
|
+
<h1>{set.name}</h1>
|
|
40
|
+
<p>Series: {set.series}</p>
|
|
41
|
+
<p>Released: {set.releaseddate}</p>
|
|
42
|
+
<img src={set.imglogo} alt={set.name} />
|
|
43
|
+
|
|
44
|
+
{set.current_price && (
|
|
45
|
+
<p>Current Price: ${set.current_price}</p>
|
|
46
|
+
)}
|
|
47
|
+
|
|
48
|
+
<div>
|
|
49
|
+
<p>7-day change: {set.change_7d}%</p>
|
|
50
|
+
<p>1-year change: {set.change_1y}%</p>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<h3>Rarity Distribution</h3>
|
|
54
|
+
<ul>
|
|
55
|
+
{set.rarities.map((rarity) => (
|
|
56
|
+
<li key={rarity.rarity}>
|
|
57
|
+
{rarity.rarity}: {rarity.count} cards
|
|
58
|
+
</li>
|
|
59
|
+
))}
|
|
60
|
+
</ul>
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
32
64
|
```
|
|
33
65
|
|
|
66
|
+
**Benefits:**
|
|
67
|
+
- ✅ Full IDE autocomplete on `set.` properties
|
|
68
|
+
- ✅ Type errors caught at compile time
|
|
69
|
+
- ✅ Optional fields properly typed (e.g., `current_price?: number`)
|
|
70
|
+
- ✅ Nested types fully typed (e.g., `rarities: RarityCount[]`)
|
|
71
|
+
|
|
34
72
|
## Features
|
|
35
73
|
|
|
36
|
-
✅ **
|
|
37
|
-
✅ **
|
|
38
|
-
✅ **Zero
|
|
39
|
-
✅ **
|
|
40
|
-
✅ **Free
|
|
74
|
+
✅ **Single Source of Truth** - Types synced from pfapi-fs schemas
|
|
75
|
+
✅ **Fully Typed** - IDE autocompletion on all API responses
|
|
76
|
+
✅ **Zero Dependencies** - Only ~5 KB, no runtime overhead
|
|
77
|
+
✅ **Type Safe** - Catch errors at compile time, not runtime
|
|
78
|
+
✅ **Free** - No paid npm account needed
|
|
79
|
+
|
|
80
|
+
## Publishing Workflow
|
|
81
|
+
|
|
82
|
+
### Prerequisites
|
|
83
|
+
|
|
84
|
+
- pfapi-fs available locally (no need to run it)
|
|
85
|
+
- npm installed
|
|
41
86
|
|
|
42
|
-
|
|
87
|
+
### Step-by-Step
|
|
43
88
|
|
|
44
|
-
|
|
89
|
+
#### 1. Make changes in pfapi-fs
|
|
45
90
|
|
|
46
|
-
|
|
91
|
+
Add or modify V3 endpoints with TypeBox schemas:
|
|
47
92
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
93
|
+
```typescript
|
|
94
|
+
// pfapi-fs/src/routes/v3/sets/schemas.ts
|
|
95
|
+
export const SetDetailSchema = Type.Object({
|
|
96
|
+
setid: Type.String(),
|
|
97
|
+
name: Type.String(),
|
|
98
|
+
series: Type.String(),
|
|
99
|
+
// ... more fields
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
export type SetDetail = Static<typeof SetDetailSchema>;
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### 2. Bump version and generate types
|
|
52
106
|
|
|
53
|
-
Example workflow:
|
|
54
107
|
```bash
|
|
55
|
-
|
|
56
|
-
#
|
|
57
|
-
|
|
58
|
-
|
|
108
|
+
cd ../pfapi-types
|
|
109
|
+
npm version patch # or minor/major
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
This automatically:
|
|
113
|
+
- ✅ Syncs TypeBox schemas from `../pfapi-fs/src/routes/v3/*/schemas.ts`
|
|
114
|
+
- ✅ Validates with TypeScript
|
|
115
|
+
- ✅ Stages v3.ts with git
|
|
116
|
+
- ✅ Bumps version (3.0.0 → 3.0.1)
|
|
117
|
+
- ✅ Creates git tag
|
|
59
118
|
|
|
60
|
-
|
|
61
|
-
# pfapi-types/v3.ts
|
|
62
|
-
export { CardSchema, type Card } from '...'
|
|
119
|
+
#### 3. Publish to npm
|
|
63
120
|
|
|
64
|
-
|
|
65
|
-
npm version patch
|
|
121
|
+
```bash
|
|
66
122
|
npm publish
|
|
67
123
|
```
|
|
68
124
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
### First Time Only
|
|
125
|
+
Verifies v3.ts changed, then publishes to npm.
|
|
72
126
|
|
|
73
|
-
|
|
74
|
-
2. Login locally: `npm login`
|
|
75
|
-
3. Publish: `npm publish`
|
|
127
|
+
## Manual Type Generation
|
|
76
128
|
|
|
77
|
-
|
|
129
|
+
To manually regenerate types without versioning:
|
|
78
130
|
|
|
79
131
|
```bash
|
|
80
|
-
# Regenerate types from updated API
|
|
81
132
|
npm run generate
|
|
133
|
+
```
|
|
82
134
|
|
|
83
|
-
|
|
84
|
-
npm version patch # or minor/major
|
|
135
|
+
## How It Works
|
|
85
136
|
|
|
86
|
-
|
|
87
|
-
|
|
137
|
+
### Single Source of Truth
|
|
138
|
+
```
|
|
139
|
+
pfapi-fs/src/routes/v3/sets/schemas.ts ← Edit here
|
|
140
|
+
↓
|
|
141
|
+
npm run generate
|
|
142
|
+
↓
|
|
143
|
+
pfapi-types/v3.ts ← Auto-synced
|
|
144
|
+
↓
|
|
145
|
+
Consumer imports
|
|
88
146
|
```
|
|
89
147
|
|
|
90
|
-
|
|
148
|
+
**No drift possible** — types always match the backend schemas.
|
|
91
149
|
|
|
92
|
-
|
|
93
|
-
|
|
150
|
+
## Version Strategy
|
|
151
|
+
|
|
152
|
+
- **Major** (3.0.0 → 4.0.0) - Breaking API changes
|
|
153
|
+
- **Minor** (3.0.0 → 3.1.0) - New endpoints/features
|
|
154
|
+
- **Patch** (3.0.0 → 3.0.1) - Bug fixes in types
|
|
94
155
|
|
|
95
156
|
## Files
|
|
96
157
|
|
|
158
|
+
- `generate-types.sh` - Script that syncs TypeBox schemas from pfapi-fs
|
|
159
|
+
- `package.json` - npm metadata with automated scripts
|
|
160
|
+
- `v3.ts` - Auto-generated types (do not edit manually)
|
|
97
161
|
- `index.ts` - Main entry point (re-exports v3.ts)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
162
|
+
|
|
163
|
+
## Troubleshooting
|
|
164
|
+
|
|
165
|
+
### "Error: No changes to v3.ts since last tag"
|
|
166
|
+
|
|
167
|
+
The `preversion` hook prevents versioning if types haven't changed. Make sure:
|
|
168
|
+
- You've made actual changes to V3 schemas in pfapi-fs
|
|
169
|
+
- Run `npm run generate` to test schema sync
|
|
170
|
+
|
|
171
|
+
### "TypeScript validation failed"
|
|
172
|
+
|
|
173
|
+
Check that:
|
|
174
|
+
- All TypeBox schemas in pfapi-fs compile
|
|
175
|
+
- Imports are correct in `src/routes/v3/*/schemas.ts`
|
|
176
|
+
|
|
177
|
+
### "npm ERR! code E404"
|
|
178
|
+
|
|
179
|
+
Make sure npm is authenticated and you have publish permissions for `@pfdev/api-types`.
|
|
180
|
+
|
|
181
|
+
## Publishing for the First Time
|
|
182
|
+
|
|
183
|
+
1. Create free npm account: https://www.npmjs.com/signup
|
|
184
|
+
2. Login: `npm login`
|
|
185
|
+
3. Publish: `npm publish`
|
|
101
186
|
|
|
102
187
|
## No Cost
|
|
103
188
|
|
|
104
189
|
- ✅ npm account: FREE (forever)
|
|
105
190
|
- ✅ Publish to npm: FREE (unlimited public packages)
|
|
106
|
-
- ✅
|
|
107
|
-
|
|
108
|
-
## Support
|
|
109
|
-
|
|
110
|
-
See `SETUP.md` for troubleshooting and CI/CD setup.
|
|
191
|
+
- ✅ All tools: FREE (open source)
|
package/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
// Re-export all V3 API types
|
|
1
|
+
// Re-export all V3 API types synced from pfapi-fs
|
|
2
2
|
export * from './v3';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pfdev/api-types",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "TypeScript types for PF API V3",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"types": "index.ts",
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
"v3.ts"
|
|
10
10
|
],
|
|
11
11
|
"scripts": {
|
|
12
|
-
"verify": "tsc --noEmit v3.ts"
|
|
12
|
+
"verify": "tsc --noEmit v3.ts",
|
|
13
|
+
"generate": "bash generate-types.sh",
|
|
14
|
+
"preversion": "npm run generate && git add v3.ts",
|
|
15
|
+
"prepublishonly": "git diff HEAD v3.ts || (echo 'Error: No changes to v3.ts since last publish' && exit 1)"
|
|
13
16
|
},
|
|
14
17
|
"keywords": [
|
|
15
18
|
"api",
|
package/v3.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
// Update this as new V3 endpoints are added
|
|
1
|
+
// Auto-generated from pfapi-fs/src/routes/v3/*/schemas.ts
|
|
2
|
+
// Do not edit manually - run `npm run generate` to update
|
|
4
3
|
|
|
5
4
|
import { Static, Type } from '@sinclair/typebox';
|
|
6
5
|
|
|
6
|
+
|
|
7
7
|
// ============= SETS =============
|
|
8
8
|
|
|
9
|
+
|
|
10
|
+
// Response for list of sets
|
|
9
11
|
export const SetListItemSchema = Type.Object({
|
|
10
12
|
setid: Type.String({ description: 'Unique set identifier' }),
|
|
11
13
|
name: Type.String({ description: 'Set name' }),
|
|
@@ -21,48 +23,66 @@ export const SetListItemSchema = Type.Object({
|
|
|
21
23
|
|
|
22
24
|
export type SetListItem = Static<typeof SetListItemSchema>;
|
|
23
25
|
|
|
24
|
-
export const SetListResponseSchema = Type.Object(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
})
|
|
26
|
+
export const SetListResponseSchema = Type.Object(
|
|
27
|
+
{
|
|
28
|
+
data: Type.Array(SetListItemSchema, { description: 'Array of sets' }),
|
|
29
|
+
total: Type.Number({ description: 'Total number of sets available' }),
|
|
30
|
+
count: Type.Number({ description: 'Number of sets returned in this response' })
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
title: 'SetListResponse',
|
|
34
|
+
description: 'Paginated list of Pokemon card sets'
|
|
35
|
+
}
|
|
36
|
+
);
|
|
29
37
|
|
|
30
38
|
export type SetListResponse = Static<typeof SetListResponseSchema>;
|
|
31
39
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
})
|
|
40
|
+
// Response for set details
|
|
41
|
+
export const RarityCountSchema = Type.Object(
|
|
42
|
+
{
|
|
43
|
+
rarity: Type.String({ description: 'Rarity level' }),
|
|
44
|
+
count: Type.Number({ description: 'Number of cards with this rarity' })
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
title: 'RarityCount',
|
|
48
|
+
description: 'Card rarity distribution in a set'
|
|
49
|
+
}
|
|
50
|
+
);
|
|
36
51
|
|
|
37
52
|
export type RarityCount = Static<typeof RarityCountSchema>;
|
|
38
53
|
|
|
39
|
-
export const SetDetailSchema = Type.Object(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
})
|
|
54
|
+
export const SetDetailSchema = Type.Object(
|
|
55
|
+
{
|
|
56
|
+
setid: Type.String({ description: 'Unique set identifier' }),
|
|
57
|
+
name: Type.String({ description: 'Set name' }),
|
|
58
|
+
printedtotal: Type.Number({ description: 'Total cards printed (official)' }),
|
|
59
|
+
total: Type.Number({ description: 'Total unique cards in set' }),
|
|
60
|
+
series: Type.String({ description: 'Pokemon series name' }),
|
|
61
|
+
releaseddate: Type.String({ format: 'date', description: 'Release date' }),
|
|
62
|
+
updatedat: Type.String({ format: 'date-time', description: 'Last update timestamp' }),
|
|
63
|
+
imgsymbol: Type.String({ format: 'uri', description: 'Set symbol image URL' }),
|
|
64
|
+
imglogo: Type.String({ format: 'uri', description: 'Set logo image URL' }),
|
|
65
|
+
slug: Type.String({ description: 'URL-friendly identifier' }),
|
|
66
|
+
ptcgocode: Type.Optional(Type.String({ description: 'Pokemon TCG Live code (if available)' })),
|
|
67
|
+
legalities: Type.Optional(Type.Record(Type.String(), Type.String(), { description: 'Format legalities' })),
|
|
68
|
+
current_price: Type.Optional(Type.Number({ description: 'Current market price' })),
|
|
69
|
+
change_1d: Type.Optional(Type.Number({ description: '1-day price change %' })),
|
|
70
|
+
change_7d: Type.Optional(Type.Number({ description: '7-day price change %' })),
|
|
71
|
+
change_1m: Type.Optional(Type.Number({ description: '30-day price change %' })),
|
|
72
|
+
change_3m: Type.Optional(Type.Number({ description: '90-day price change %' })),
|
|
73
|
+
change_6m: Type.Optional(Type.Number({ description: '180-day price change %' })),
|
|
74
|
+
change_1y: Type.Optional(Type.Number({ description: '1-year price change %' })),
|
|
75
|
+
rarities: Type.Array(RarityCountSchema, { description: 'Card rarity distribution' })
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
title: 'SetDetail',
|
|
79
|
+
description: 'Detailed information about a Pokemon card set'
|
|
80
|
+
}
|
|
81
|
+
);
|
|
61
82
|
|
|
62
83
|
export type SetDetail = Static<typeof SetDetailSchema>;
|
|
63
84
|
|
|
64
|
-
//
|
|
65
|
-
|
|
85
|
+
// Query parameters
|
|
66
86
|
export const SetListQuerySchema = Type.Object({
|
|
67
87
|
search: Type.Optional(Type.String({ description: 'Search by set name' })),
|
|
68
88
|
series: Type.Optional(Type.String({ description: 'Filter by series' })),
|
|
@@ -72,9 +92,9 @@ export const SetListQuerySchema = Type.Object({
|
|
|
72
92
|
|
|
73
93
|
export type SetListQuery = Static<typeof SetListQuerySchema>;
|
|
74
94
|
|
|
95
|
+
// Path parameters
|
|
75
96
|
export const SetDetailParamSchema = Type.Object({
|
|
76
97
|
setid: Type.String({ description: 'Set ID or slug' })
|
|
77
98
|
});
|
|
78
99
|
|
|
79
100
|
export type SetDetailParam = Static<typeof SetDetailParamSchema>;
|
|
80
|
-
|