@xivdyetools/types 1.7.0 → 1.9.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/LICENSE +37 -37
- package/README.md +290 -291
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/response.d.ts +1 -39
- package/dist/api/response.d.ts.map +1 -1
- package/dist/api/response.js +1 -1
- package/dist/auth/discord-snowflake.d.ts +71 -0
- package/dist/auth/discord-snowflake.d.ts.map +1 -0
- package/dist/auth/discord-snowflake.js +70 -0
- package/dist/auth/discord-snowflake.js.map +1 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/response.d.ts +7 -0
- package/dist/auth/response.d.ts.map +1 -1
- package/dist/character/index.d.ts +4 -0
- package/dist/character/index.d.ts.map +1 -1
- package/dist/character/index.js.map +1 -1
- package/dist/color/colorblind.d.ts +1 -0
- package/dist/color/colorblind.d.ts.map +1 -1
- package/dist/dye/database.d.ts +1 -0
- package/dist/dye/database.d.ts.map +1 -1
- package/dist/dye/dye.d.ts +1 -0
- package/dist/dye/dye.d.ts.map +1 -1
- package/dist/error/app-error.js +2 -0
- package/dist/error/app-error.js.map +1 -1
- package/dist/index.d.ts +7 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/preset/community.d.ts +0 -9
- package/dist/preset/community.d.ts.map +1 -1
- package/dist/preset/core.d.ts +0 -10
- package/dist/preset/core.d.ts.map +1 -1
- package/dist/preset/index.d.ts +2 -2
- package/dist/preset/index.d.ts.map +1 -1
- package/dist/preset/response.d.ts +11 -0
- package/dist/preset/response.d.ts.map +1 -1
- package/package.json +80 -81
- package/dist/utility/index.d.ts +0 -71
- package/dist/utility/index.d.ts.map +0 -1
- package/dist/utility/index.js +0 -20
- 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** |
|
|
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
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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
|
package/dist/api/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @module api
|
|
7
7
|
*/
|
|
8
|
-
export type {
|
|
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
|
package/dist/api/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,YAAY,EAAE,
|
|
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"}
|