@xivdyetools/types 1.7.0 → 1.10.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.
Files changed (45) hide show
  1. package/LICENSE +37 -37
  2. package/README.md +290 -291
  3. package/dist/api/index.d.ts +1 -1
  4. package/dist/api/index.d.ts.map +1 -1
  5. package/dist/api/response.d.ts +1 -39
  6. package/dist/api/response.d.ts.map +1 -1
  7. package/dist/api/response.js +1 -1
  8. package/dist/auth/discord-snowflake.d.ts +71 -0
  9. package/dist/auth/discord-snowflake.d.ts.map +1 -0
  10. package/dist/auth/discord-snowflake.js +70 -0
  11. package/dist/auth/discord-snowflake.js.map +1 -0
  12. package/dist/auth/index.d.ts +2 -0
  13. package/dist/auth/index.d.ts.map +1 -1
  14. package/dist/auth/index.js +1 -1
  15. package/dist/auth/index.js.map +1 -1
  16. package/dist/auth/response.d.ts +7 -0
  17. package/dist/auth/response.d.ts.map +1 -1
  18. package/dist/character/index.d.ts +4 -0
  19. package/dist/character/index.d.ts.map +1 -1
  20. package/dist/character/index.js.map +1 -1
  21. package/dist/color/colorblind.d.ts +1 -0
  22. package/dist/color/colorblind.d.ts.map +1 -1
  23. package/dist/dye/database.d.ts +1 -0
  24. package/dist/dye/database.d.ts.map +1 -1
  25. package/dist/dye/dye.d.ts +14 -0
  26. package/dist/dye/dye.d.ts.map +1 -1
  27. package/dist/error/app-error.js +2 -0
  28. package/dist/error/app-error.js.map +1 -1
  29. package/dist/index.d.ts +7 -8
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +1 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/preset/community.d.ts +0 -9
  34. package/dist/preset/community.d.ts.map +1 -1
  35. package/dist/preset/core.d.ts +0 -10
  36. package/dist/preset/core.d.ts.map +1 -1
  37. package/dist/preset/index.d.ts +2 -2
  38. package/dist/preset/index.d.ts.map +1 -1
  39. package/dist/preset/response.d.ts +11 -0
  40. package/dist/preset/response.d.ts.map +1 -1
  41. package/package.json +80 -81
  42. package/dist/utility/index.d.ts +0 -71
  43. package/dist/utility/index.d.ts.map +0 -1
  44. package/dist/utility/index.js +0 -20
  45. package/dist/utility/index.js.map +0 -1
package/LICENSE CHANGED
@@ -1,37 +1,37 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Flash Galatine
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
22
-
23
- ---
24
-
25
- FINAL FANTASY XIV © SQUARE ENIX CO., LTD. All Rights Reserved.
26
-
27
- This project is a fan-made tool and is not affiliated with, endorsed by, or
28
- sponsored by Square Enix Co., Ltd. FINAL FANTASY is a registered trademark
29
- of Square Enix Holdings Co., Ltd.
30
-
31
- Game data, including dye names, colors, and acquisition methods, are property
32
- of Square Enix Co., Ltd. and are used under fair use for educational and
33
- informational purposes only.
34
-
35
- Market board data is provided by Universalis (https://universalis.app/),
36
- an independent third-party service not affiliated with Square Enix.
37
-
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Flash Galatine
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ FINAL FANTASY XIV © SQUARE ENIX CO., LTD. All Rights Reserved.
26
+
27
+ This project is a fan-made tool and is not affiliated with, endorsed by, or
28
+ sponsored by Square Enix Co., Ltd. FINAL FANTASY is a registered trademark
29
+ of Square Enix Holdings Co., Ltd.
30
+
31
+ Game data, including dye names, colors, and acquisition methods, are property
32
+ of Square Enix Co., Ltd. and are used under fair use for educational and
33
+ informational purposes only.
34
+
35
+ Market board data is provided by Universalis (https://universalis.app/),
36
+ an independent third-party service not affiliated with Square Enix.
37
+
package/README.md CHANGED
@@ -1,291 +1,290 @@
1
- # @xivdyetools/types
2
-
3
- Shared TypeScript type definitions for the xivdyetools ecosystem.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install @xivdyetools/types
9
- ```
10
-
11
- ## Overview
12
-
13
- This package consolidates type definitions from multiple xivdyetools projects:
14
-
15
- - **xivdyetools-core** - Color types, dye types, error types
16
- - **xivdyetools-web-app** - Extended dye types, UI-specific types
17
- - **xivdyetools-discord-worker** - Preset types
18
- - **xivdyetools-presets-api** - API response types, moderation types
19
- - **xivdyetools-oauth** - Authentication types
20
-
21
- ## Usage
22
-
23
- ### Full Import
24
-
25
- ```typescript
26
- import {
27
- Dye,
28
- RGB,
29
- HexColor,
30
- createHexColor,
31
- CommunityPreset,
32
- AppError,
33
- ErrorCode,
34
- } from '@xivdyetools/types';
35
- ```
36
-
37
- ### Subpath Imports (Tree-Shaking)
38
-
39
- For smaller bundle sizes, import from specific modules:
40
-
41
- ```typescript
42
- // Color types
43
- import { RGB, HSV, LAB, HexColor, createHexColor, VisionType } from '@xivdyetools/types/color';
44
-
45
- // Dye types
46
- import { Dye, LocalizedDye, DyeWithDistance, DyeDatabase } from '@xivdyetools/types/dye';
47
-
48
- // Preset types
49
- import {
50
- CommunityPreset,
51
- PresetSubmission,
52
- PresetFilters,
53
- PresetListResponse,
54
- } from '@xivdyetools/types/preset';
55
-
56
- // Auth types
57
- import { AuthResponse, JWTPayload, DiscordUser } from '@xivdyetools/types/auth';
58
-
59
- // Error types
60
- import { AppError, ErrorCode, ErrorSeverity } from '@xivdyetools/types/error';
61
-
62
- // API types
63
- import { APIResponse, CachedData, ModerationResult } from '@xivdyetools/types/api';
64
-
65
- // Localization types
66
- import { LocaleCode, LocaleData, TranslationKey } from '@xivdyetools/types/localization';
67
- ```
68
-
69
- ## Type Categories
70
-
71
- ### Color Types
72
-
73
- ```typescript
74
- import { RGB, HSV, HexColor, createHexColor, DyeId, createDyeId } from '@xivdyetools/types';
75
-
76
- // RGB, HSV, and LAB interfaces
77
- const red: RGB = { r: 255, g: 0, b: 0 };
78
- const redHsv: HSV = { h: 0, s: 100, v: 100 };
79
-
80
- // LAB color space (for perceptual color matching)
81
- import { LAB } from '@xivdyetools/types';
82
- const redLab: LAB = { L: 53.23, a: 80.11, b: 67.22 };
83
-
84
- // Branded types with validation
85
- const hex: HexColor = createHexColor('#ff6b6b'); // Validates and normalizes to "#FF6B6B"
86
- const dyeId: DyeId | null = createDyeId(1); // Returns null if invalid (not 1-200)
87
-
88
- // Colorblindness types
89
- import { VisionType, ColorblindMatrices } from '@xivdyetools/types';
90
- const vision: VisionType = 'deuteranopia';
91
- ```
92
-
93
- ### Dye Types
94
-
95
- ```typescript
96
- import { Dye, LocalizedDye, DyeWithDistance, DyeDatabase } from '@xivdyetools/types';
97
-
98
- // Full dye object
99
- const dye: Dye = {
100
- itemID: 5729,
101
- stainID: 1, // Game's internal stain table ID (null for Facewear dyes)
102
- id: 1,
103
- name: 'Snow White',
104
- hex: '#FFFFFF',
105
- rgb: { r: 255, g: 255, b: 255 },
106
- hsv: { h: 0, s: 0, v: 100 },
107
- category: 'Neutral',
108
- acquisition: 'NPC',
109
- cost: 216,
110
- isMetallic: false,
111
- isPastel: false,
112
- isDark: false,
113
- isCosmic: false,
114
- };
115
-
116
- // Dye with color distance (for search results)
117
- const match: DyeWithDistance = { ...dye, distance: 12.5 };
118
- ```
119
-
120
- ### Preset Types
121
-
122
- ```typescript
123
- import {
124
- CommunityPreset,
125
- PresetSubmission,
126
- PresetFilters,
127
- PresetCategory,
128
- PresetStatus,
129
- } from '@xivdyetools/types';
130
-
131
- // Query presets
132
- const filters: PresetFilters = {
133
- category: 'jobs',
134
- sort: 'popular',
135
- page: 1,
136
- limit: 20,
137
- };
138
-
139
- // Submit a new preset
140
- const submission: PresetSubmission = {
141
- name: 'Red Mage Vibes',
142
- description: 'Crimson and black for the sophisticated caster',
143
- category_id: 'jobs',
144
- dyes: [12, 45, 78],
145
- tags: ['rdm', 'red', 'elegant'],
146
- };
147
- ```
148
-
149
- ### Auth Types
150
-
151
- ```typescript
152
- import { AuthResponse, JWTPayload, AuthProvider } from '@xivdyetools/types';
153
-
154
- // Check auth response
155
- function handleAuthResponse(response: AuthResponse) {
156
- if (response.success && response.token) {
157
- localStorage.setItem('token', response.token);
158
- }
159
- }
160
-
161
- // JWT payload structure
162
- const payload: JWTPayload = {
163
- sub: 'user-uuid',
164
- iat: Date.now() / 1000,
165
- exp: Date.now() / 1000 + 3600,
166
- iss: 'https://oauth.xivdyetools.com',
167
- username: 'User',
168
- global_name: 'Display Name',
169
- avatar: null,
170
- auth_provider: 'discord',
171
- discord_id: '123456789',
172
- };
173
- ```
174
-
175
- ### Error Types
176
-
177
- ```typescript
178
- import { AppError, ErrorCode } from '@xivdyetools/types';
179
-
180
- // Throw typed errors
181
- throw new AppError(ErrorCode.DYE_NOT_FOUND, 'Dye with ID 999 not found');
182
-
183
- // With severity
184
- throw new AppError(ErrorCode.DATABASE_LOAD_FAILED, 'Failed to load dyes', 'critical');
185
-
186
- // Serialize for API responses
187
- catch (error) {
188
- if (error instanceof AppError) {
189
- return { error: error.toJSON() };
190
- }
191
- }
192
- ```
193
-
194
- ### Utility Types
195
-
196
- ```typescript
197
- import { Result, isOk, isErr, Nullable } from '@xivdyetools/types';
198
-
199
- // Result type for operations that might fail
200
- function findDye(id: number): Result<Dye> {
201
- const dye = database.find(d => d.id === id);
202
- if (dye) {
203
- return { ok: true, value: dye };
204
- }
205
- return { ok: false, error: new AppError(ErrorCode.DYE_NOT_FOUND, `Dye ${id} not found`) };
206
- }
207
-
208
- // Type guards
209
- const result = findDye(1);
210
- if (isOk(result)) {
211
- console.log(result.value.name); // TypeScript knows this is Dye
212
- } else {
213
- console.error(result.error.message); // TypeScript knows this is AppError
214
- }
215
- ```
216
-
217
- ## Migration Guide
218
-
219
- ### From xivdyetools-core
220
-
221
- ```typescript
222
- // Before
223
- import { Dye, RGB, HexColor, AppError, ErrorCode } from 'xivdyetools-core';
224
-
225
- // After
226
- import { Dye, RGB, HexColor, AppError, ErrorCode } from '@xivdyetools/types';
227
- ```
228
-
229
- ### From xivdyetools-web-app/src/shared/types.ts
230
-
231
- ```typescript
232
- // Before
233
- import { Dye, DyeWithDistance, AppError } from '../shared/types';
234
-
235
- // After
236
- import { Dye, DyeWithDistance, AppError } from '@xivdyetools/types';
237
- ```
238
-
239
- ### From xivdyetools-presets-api/src/types.ts
240
-
241
- ```typescript
242
- // Before
243
- import { CommunityPreset, PresetFilters, ModerationResult } from './types';
244
-
245
- // After
246
- import { CommunityPreset, PresetFilters, ModerationResult } from '@xivdyetools/types';
247
- ```
248
-
249
- ## API Reference
250
-
251
- ### Modules
252
-
253
- | Module | Description |
254
- |--------|-------------|
255
- | `@xivdyetools/types` | All types (barrel export) |
256
- | `@xivdyetools/types/color` | RGB, HSV, HexColor, branded types |
257
- | `@xivdyetools/types/dye` | Dye, LocalizedDye, DyeWithDistance |
258
- | `@xivdyetools/types/preset` | Preset, community, filters, responses |
259
- | `@xivdyetools/types/auth` | OAuth, JWT, Discord, XIVAuth |
260
- | `@xivdyetools/types/api` | APIResponse, CachedData, moderation |
261
- | `@xivdyetools/types/error` | AppError, ErrorCode enum |
262
- | `@xivdyetools/types/localization` | LocaleCode, LocaleData |
263
-
264
- ### Helper Functions
265
-
266
- | Function | Description |
267
- |----------|-------------|
268
- | `createHexColor(hex)` | Validate and normalize hex color |
269
- | `createDyeId(id)` | Validate dye ID (1-200) |
270
- | `createHue(hue)` | Normalize hue to 0-360 |
271
- | `createSaturation(sat)` | Clamp saturation to 0-100 |
272
- | `isOk(result)` | Type guard for successful Result |
273
- | `isErr(result)` | Type guard for error Result |
274
-
275
- ## Connect With Me
276
-
277
- **Flash Galatine** | Balmung (Crystal)
278
-
279
- 🎮 **FFXIV**: [Lodestone Character](https://na.finalfantasyxiv.com/lodestone/character/7677106/)
280
- 📝 **Blog**: [Project Galatine](https://blog.projectgalatine.com/)
281
- 💻 **GitHub**: [@FlashGalatine](https://github.com/FlashGalatine)
282
- 🐦 **X / Twitter**: [@AsheJunius](https://x.com/AsheJunius)
283
- 📺 **Twitch**: [flashgalatine](https://www.twitch.tv/flashgalatine)
284
- 🌐 **BlueSky**: [projectgalatine.com](https://bsky.app/profile/projectgalatine.com)
285
- ❤️ **Patreon**: [ProjectGalatine](https://patreon.com/ProjectGalatine)
286
- **Ko-Fi**: [flashgalatine](https://ko-fi.com/flashgalatine)
287
- 💬 **Discord**: [Join Server](https://discord.gg/5VUSKTZCe5)
288
-
289
- ## License
290
-
291
- MIT © 2025 Flash Galatine
1
+ # @xivdyetools/types
2
+
3
+ Shared TypeScript type definitions for the xivdyetools ecosystem.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @xivdyetools/types
9
+ ```
10
+
11
+ ## Overview
12
+
13
+ This package consolidates type definitions from multiple xivdyetools projects:
14
+
15
+ - **xivdyetools-core** - Color types, dye types, error types
16
+ - **xivdyetools-web-app** - Extended dye types, UI-specific types
17
+ - **xivdyetools-discord-worker** - Preset types
18
+ - **xivdyetools-presets-api** - API response types, moderation types
19
+ - **xivdyetools-oauth** - Authentication types
20
+
21
+ ## Usage
22
+
23
+ ### Full Import
24
+
25
+ ```typescript
26
+ import {
27
+ Dye,
28
+ RGB,
29
+ HexColor,
30
+ createHexColor,
31
+ CommunityPreset,
32
+ AppError,
33
+ ErrorCode,
34
+ } from '@xivdyetools/types';
35
+ ```
36
+
37
+ ### Subpath Imports (Tree-Shaking)
38
+
39
+ For smaller bundle sizes, import from specific modules:
40
+
41
+ ```typescript
42
+ // Color types
43
+ import { RGB, HSV, LAB, HexColor, createHexColor, VisionType } from '@xivdyetools/types/color';
44
+
45
+ // Dye types
46
+ import { Dye, LocalizedDye, DyeWithDistance, DyeDatabase } from '@xivdyetools/types/dye';
47
+
48
+ // Preset types
49
+ import {
50
+ CommunityPreset,
51
+ PresetSubmission,
52
+ PresetFilters,
53
+ PresetListResponse,
54
+ } from '@xivdyetools/types/preset';
55
+
56
+ // Auth types
57
+ import { AuthResponse, JWTPayload, DiscordUser } from '@xivdyetools/types/auth';
58
+
59
+ // Error types
60
+ import { AppError, ErrorCode, ErrorSeverity } from '@xivdyetools/types/error';
61
+
62
+ // API types
63
+ import { APIResponse, CachedData, ModerationResult } from '@xivdyetools/types/api';
64
+
65
+ // Localization types
66
+ import { LocaleCode, LocaleData, TranslationKey } from '@xivdyetools/types/localization';
67
+ ```
68
+
69
+ ## Type Categories
70
+
71
+ ### Color Types
72
+
73
+ ```typescript
74
+ import { RGB, HSV, HexColor, createHexColor, DyeId, createDyeId } from '@xivdyetools/types';
75
+
76
+ // RGB, HSV, and LAB interfaces
77
+ const red: RGB = { r: 255, g: 0, b: 0 };
78
+ const redHsv: HSV = { h: 0, s: 100, v: 100 };
79
+
80
+ // LAB color space (for perceptual color matching)
81
+ import { LAB } from '@xivdyetools/types';
82
+ const redLab: LAB = { L: 53.23, a: 80.11, b: 67.22 };
83
+
84
+ // Branded types with validation
85
+ const hex: HexColor = createHexColor('#ff6b6b'); // Validates and normalizes to "#FF6B6B"
86
+ const dyeId: DyeId | null = createDyeId(1); // Returns null if invalid (not 1-200)
87
+
88
+ // Colorblindness types
89
+ import { VisionType, ColorblindMatrices } from '@xivdyetools/types';
90
+ const vision: VisionType = 'deuteranopia';
91
+ ```
92
+
93
+ ### Dye Types
94
+
95
+ ```typescript
96
+ import { Dye, LocalizedDye, DyeWithDistance, DyeDatabase } from '@xivdyetools/types';
97
+
98
+ // Full dye object
99
+ const dye: Dye = {
100
+ itemID: 5729,
101
+ stainID: 1, // Game's internal stain table ID (null for Facewear dyes)
102
+ id: 1,
103
+ name: 'Snow White',
104
+ hex: '#FFFFFF',
105
+ rgb: { r: 255, g: 255, b: 255 },
106
+ hsv: { h: 0, s: 0, v: 100 },
107
+ category: 'Neutral',
108
+ acquisition: 'NPC',
109
+ cost: 216,
110
+ isMetallic: false,
111
+ isPastel: false,
112
+ isDark: false,
113
+ isCosmic: false,
114
+ };
115
+
116
+ // Dye with color distance (for search results)
117
+ const match: DyeWithDistance = { ...dye, distance: 12.5 };
118
+ ```
119
+
120
+ ### Preset Types
121
+
122
+ ```typescript
123
+ import {
124
+ CommunityPreset,
125
+ PresetSubmission,
126
+ PresetFilters,
127
+ PresetCategory,
128
+ PresetStatus,
129
+ } from '@xivdyetools/types';
130
+
131
+ // Query presets
132
+ const filters: PresetFilters = {
133
+ category: 'jobs',
134
+ sort: 'popular',
135
+ page: 1,
136
+ limit: 20,
137
+ };
138
+
139
+ // Submit a new preset
140
+ const submission: PresetSubmission = {
141
+ name: 'Red Mage Vibes',
142
+ description: 'Crimson and black for the sophisticated caster',
143
+ category_id: 'jobs',
144
+ dyes: [12, 45, 78],
145
+ tags: ['rdm', 'red', 'elegant'],
146
+ };
147
+ ```
148
+
149
+ ### Auth Types
150
+
151
+ ```typescript
152
+ import { AuthResponse, JWTPayload, AuthProvider } from '@xivdyetools/types';
153
+
154
+ // Check auth response
155
+ function handleAuthResponse(response: AuthResponse) {
156
+ if (response.success && response.token) {
157
+ localStorage.setItem('token', response.token);
158
+ }
159
+ }
160
+
161
+ // JWT payload structure
162
+ const payload: JWTPayload = {
163
+ sub: 'user-uuid',
164
+ iat: Date.now() / 1000,
165
+ exp: Date.now() / 1000 + 3600,
166
+ iss: 'https://oauth.xivdyetools.com',
167
+ username: 'User',
168
+ global_name: 'Display Name',
169
+ avatar: null,
170
+ auth_provider: 'discord',
171
+ discord_id: '123456789',
172
+ };
173
+ ```
174
+
175
+ ### Error Types
176
+
177
+ ```typescript
178
+ import { AppError, ErrorCode } from '@xivdyetools/types';
179
+
180
+ // Throw typed errors
181
+ throw new AppError(ErrorCode.DYE_NOT_FOUND, 'Dye with ID 999 not found');
182
+
183
+ // With severity
184
+ throw new AppError(ErrorCode.DATABASE_LOAD_FAILED, 'Failed to load dyes', 'critical');
185
+
186
+ // Serialize for API responses
187
+ catch (error) {
188
+ if (error instanceof AppError) {
189
+ return { error: error.toJSON() };
190
+ }
191
+ }
192
+ ```
193
+
194
+ ### Utility Types
195
+
196
+ ```typescript
197
+ import { Result, isOk, isErr, Nullable } from '@xivdyetools/types';
198
+
199
+ // Result type for operations that might fail
200
+ function findDye(id: number): Result<Dye> {
201
+ const dye = database.find(d => d.id === id);
202
+ if (dye) {
203
+ return { ok: true, value: dye };
204
+ }
205
+ return { ok: false, error: new AppError(ErrorCode.DYE_NOT_FOUND, `Dye ${id} not found`) };
206
+ }
207
+
208
+ // Type guards
209
+ const result = findDye(1);
210
+ if (isOk(result)) {
211
+ console.log(result.value.name); // TypeScript knows this is Dye
212
+ } else {
213
+ console.error(result.error.message); // TypeScript knows this is AppError
214
+ }
215
+ ```
216
+
217
+ ## Migration Guide
218
+
219
+ ### From xivdyetools-core
220
+
221
+ ```typescript
222
+ // Before
223
+ import { Dye, RGB, HexColor, AppError, ErrorCode } from 'xivdyetools-core';
224
+
225
+ // After
226
+ import { Dye, RGB, HexColor, AppError, ErrorCode } from '@xivdyetools/types';
227
+ ```
228
+
229
+ ### From xivdyetools-web-app/src/shared/types.ts
230
+
231
+ ```typescript
232
+ // Before
233
+ import { Dye, DyeWithDistance, AppError } from '../shared/types';
234
+
235
+ // After
236
+ import { Dye, DyeWithDistance, AppError } from '@xivdyetools/types';
237
+ ```
238
+
239
+ ### From xivdyetools-presets-api/src/types.ts
240
+
241
+ ```typescript
242
+ // Before
243
+ import { CommunityPreset, PresetFilters, ModerationResult } from './types';
244
+
245
+ // After
246
+ import { CommunityPreset, PresetFilters, ModerationResult } from '@xivdyetools/types';
247
+ ```
248
+
249
+ ## API Reference
250
+
251
+ ### Modules
252
+
253
+ | Module | Description |
254
+ |--------|-------------|
255
+ | `@xivdyetools/types` | All types (barrel export) |
256
+ | `@xivdyetools/types/color` | RGB, HSV, HexColor, branded types |
257
+ | `@xivdyetools/types/dye` | Dye, LocalizedDye, DyeWithDistance |
258
+ | `@xivdyetools/types/preset` | Preset, community, filters, responses |
259
+ | `@xivdyetools/types/auth` | OAuth, JWT, Discord, XIVAuth |
260
+ | `@xivdyetools/types/api` | APIResponse, CachedData, moderation |
261
+ | `@xivdyetools/types/error` | AppError, ErrorCode enum |
262
+ | `@xivdyetools/types/localization` | LocaleCode, LocaleData |
263
+
264
+ ### Helper Functions
265
+
266
+ | Function | Description |
267
+ |----------|-------------|
268
+ | `createHexColor(hex)` | Validate and normalize hex color |
269
+ | `createDyeId(id)` | Validate dye ID (1-200) |
270
+ | `createHue(hue)` | Normalize hue to 0-360 |
271
+ | `createSaturation(sat)` | Clamp saturation to 0-100 |
272
+ | `isOk(result)` | Type guard for successful Result |
273
+ | `isErr(result)` | Type guard for error Result |
274
+
275
+ ## Connect With Me
276
+
277
+ **Flash Galatine** | Midgardsormr (Aether)
278
+
279
+ 🎮 **FFXIV**: [Lodestone Character](https://na.finalfantasyxiv.com/lodestone/character/7677106/)
280
+ 📝 **Blog**: [Project Galatine](https://blog.projectgalatine.com/)
281
+ 💻 **GitHub**: [@FlashGalatine](https://github.com/FlashGalatine)
282
+ 📺 **Twitch**: [flashgalatine](https://www.twitch.tv/flashgalatine)
283
+ 🌐 **BlueSky**: [projectgalatine.com](https://bsky.app/profile/projectgalatine.com)
284
+ ❤️ **Patreon**: [ProjectGalatine](https://patreon.com/ProjectGalatine)
285
+ **Ko-Fi**: [flashgalatine](https://ko-fi.com/flashgalatine)
286
+ 💬 **Discord**: [Join Server](https://discord.gg/5VUSKTZCe5)
287
+
288
+ ## License
289
+
290
+ MIT © 2025-2026 Flash Galatine
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @module api
7
7
  */
8
- export type { APISuccessResponse, APIErrorResponse, APIResponse, CachedData } from './response.js';
8
+ export type { CachedData } from './response.js';
9
9
  export type { ModerationResult, ModerationLogEntry, ModerationStats } from './moderation.js';
10
10
  export type { PriceData, RateLimitResult } from './price.js';
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACnG,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC7F,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC7F,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}