lunassets 1.0.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 (75) hide show
  1. package/.github/workflows/publish.yml +46 -0
  2. package/LICENSE +21 -0
  3. package/README.md +143 -0
  4. package/dist/core/api-client.d.ts +22 -0
  5. package/dist/core/api-client.d.ts.map +1 -0
  6. package/dist/core/api-client.js +80 -0
  7. package/dist/core/api-client.js.map +1 -0
  8. package/dist/core/asset-mapper.d.ts +106 -0
  9. package/dist/core/asset-mapper.d.ts.map +1 -0
  10. package/dist/core/asset-mapper.js +179 -0
  11. package/dist/core/asset-mapper.js.map +1 -0
  12. package/dist/core/cache-manager.d.ts +64 -0
  13. package/dist/core/cache-manager.d.ts.map +1 -0
  14. package/dist/core/cache-manager.js +140 -0
  15. package/dist/core/cache-manager.js.map +1 -0
  16. package/dist/core/data-fetcher.d.ts +59 -0
  17. package/dist/core/data-fetcher.d.ts.map +1 -0
  18. package/dist/core/data-fetcher.js +149 -0
  19. package/dist/core/data-fetcher.js.map +1 -0
  20. package/dist/core/index.d.ts +6 -0
  21. package/dist/core/index.d.ts.map +1 -0
  22. package/dist/core/index.js +15 -0
  23. package/dist/core/index.js.map +1 -0
  24. package/dist/core/url-builder.d.ts +46 -0
  25. package/dist/core/url-builder.d.ts.map +1 -0
  26. package/dist/core/url-builder.js +81 -0
  27. package/dist/core/url-builder.js.map +1 -0
  28. package/dist/index.d.ts +87 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +144 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/types/api.d.ts +62 -0
  33. package/dist/types/api.d.ts.map +1 -0
  34. package/dist/types/api.js +3 -0
  35. package/dist/types/api.js.map +1 -0
  36. package/dist/types/assets.d.ts +83 -0
  37. package/dist/types/assets.d.ts.map +1 -0
  38. package/dist/types/assets.js +3 -0
  39. package/dist/types/assets.js.map +1 -0
  40. package/dist/types/config.d.ts +32 -0
  41. package/dist/types/config.d.ts.map +1 -0
  42. package/dist/types/config.js +33 -0
  43. package/dist/types/config.js.map +1 -0
  44. package/dist/types/index.d.ts +4 -0
  45. package/dist/types/index.d.ts.map +1 -0
  46. package/dist/types/index.js +21 -0
  47. package/dist/types/index.js.map +1 -0
  48. package/dist/utils/constants.d.ts +27 -0
  49. package/dist/utils/constants.d.ts.map +1 -0
  50. package/dist/utils/constants.js +35 -0
  51. package/dist/utils/constants.js.map +1 -0
  52. package/dist/utils/helpers.d.ts +26 -0
  53. package/dist/utils/helpers.d.ts.map +1 -0
  54. package/dist/utils/helpers.js +51 -0
  55. package/dist/utils/helpers.js.map +1 -0
  56. package/dist/utils/index.d.ts +3 -0
  57. package/dist/utils/index.d.ts.map +1 -0
  58. package/dist/utils/index.js +20 -0
  59. package/dist/utils/index.js.map +1 -0
  60. package/package.json +36 -0
  61. package/src/core/api-client.ts +99 -0
  62. package/src/core/asset-mapper.ts +241 -0
  63. package/src/core/cache-manager.ts +176 -0
  64. package/src/core/data-fetcher.ts +179 -0
  65. package/src/core/index.ts +6 -0
  66. package/src/core/url-builder.ts +98 -0
  67. package/src/index.ts +181 -0
  68. package/src/types/api.ts +59 -0
  69. package/src/types/assets.ts +89 -0
  70. package/src/types/config.ts +52 -0
  71. package/src/types/index.ts +4 -0
  72. package/src/utils/constants.ts +35 -0
  73. package/src/utils/helpers.ts +53 -0
  74. package/src/utils/index.ts +3 -0
  75. package/tsconfig.json +32 -0
@@ -0,0 +1,46 @@
1
+ name: Publish
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths: ["package.json"]
7
+ pull_request:
8
+ branches: [main]
9
+ workflow_dispatch:
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+
15
+ strategy:
16
+ matrix:
17
+ node-version: [20.x]
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - name: Use Node.js ${{ matrix.node-version }}
22
+ uses: actions/setup-node@v4
23
+ with:
24
+ node-version: ${{ matrix.node-version }}
25
+ cache: "npm"
26
+ - run: npm ci
27
+ - run: npm run build
28
+
29
+ publish:
30
+ needs: build
31
+ runs-on: ubuntu-latest
32
+ if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
33
+
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+ - name: Use Node.js
37
+ uses: actions/setup-node@v4
38
+ with:
39
+ node-version: "20.x"
40
+ cache: "npm"
41
+ registry-url: "https://registry.npmjs.org"
42
+ - run: npm ci
43
+ - run: npm run build
44
+ - run: npm publish --access public
45
+ env:
46
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Luna (Kiznaiverr)
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.
package/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # Lunassets
2
+
3
+ Luna's TypeScript library wrapper for asset management from Enka Network API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install lunassets
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { EnkaAssetWrapper } from "lunassets";
15
+
16
+ async function getPlayerData() {
17
+ const enka = new EnkaAssetWrapper();
18
+
19
+ try {
20
+ const assets = await enka.getPlayerAssets("856012067");
21
+ console.log(assets);
22
+ } catch (error) {
23
+ console.error("Error:", error.message);
24
+ }
25
+ }
26
+
27
+ getPlayerData();
28
+ ```
29
+
30
+ ## Example Response
31
+
32
+ ```json
33
+ {
34
+ "playerInfo": {
35
+ "nickname": "Kiznavierr",
36
+ "level": 60,
37
+ "signature": "sometimes even reality is a lie",
38
+ "worldLevel": 9,
39
+ "finishAchievementNum": 1366,
40
+ "towerFloorIndex": 12,
41
+ "towerLevelIndex": 3,
42
+ "theaterActIndex": 10,
43
+ "theaterModeIndex": 83,
44
+ "theaterStarIndex": 10,
45
+ "isShowAvatarTalent": true,
46
+ "fetterCount": 33,
47
+ "towerStarIndex": 35,
48
+ "stygianIndex": 3,
49
+ "stygianSeconds": 79,
50
+ "stygianId": 5269006
51
+ },
52
+ "profilePicture": {
53
+ "id": 7300,
54
+ "iconName": "/ui/UI_AvatarIcon_Charlotte_Circle.png",
55
+ "url": "https://enka.network/ui/UI_AvatarIcon_Charlotte_Circle.png"
56
+ },
57
+ "nameCard": {
58
+ "id": 210214,
59
+ "iconName": "UI_NameCardPic_RoleCombat2_P",
60
+ "url": "https://enka.network/ui/UI_NameCardPic_RoleCombat2_P.png"
61
+ },
62
+ "showAvatars": [
63
+ {
64
+ "avatarId": 10000047,
65
+ "iconName": "UI_AvatarIcon_Kazuha",
66
+ "url": "https://enka.network/ui/UI_AvatarIcon_Kazuha.png",
67
+ "quality": 5,
68
+ "level": 90,
69
+ "talentLevel": 2,
70
+ "element": "Wind",
71
+ "weaponType": "WEAPON_SWORD_ONE_HAND"
72
+ }
73
+ ],
74
+ "ttl": 60,
75
+ "lastUpdated": "2026-02-15T04:51:05.385Z"
76
+ }
77
+ ```
78
+
79
+ ## API Methods
80
+
81
+ ### getPlayerAssets(uid)
82
+
83
+ ```typescript
84
+ const assets = await enka.getPlayerAssets("123456789");
85
+ ```
86
+
87
+ ### getPlayerAssetsUncached(uid)
88
+
89
+ ```typescript
90
+ const assets = await enka.getPlayerAssetsUncached("123456789");
91
+ ```
92
+
93
+ ### buildAssetUrl(iconName, options)
94
+
95
+ ```typescript
96
+ const url = enka.buildAssetUrl("UI_AvatarIcon_Ayaka");
97
+ ```
98
+
99
+ ### Cache Management
100
+
101
+ ```typescript
102
+ // Check if player data is cached
103
+ const isCached = enka.isPlayerCached("123456789");
104
+
105
+ // Clear specific player cache
106
+ enka.clearPlayerCache("123456789");
107
+
108
+ // Clear all cache
109
+ enka.clearAllCache();
110
+ ```
111
+
112
+ ### Data Validation
113
+
114
+ ```typescript
115
+ // Check if character exists in reference data
116
+ const hasCharacter = await enka.hasCharacter(10000002);
117
+
118
+ // Check if profile picture exists
119
+ const hasPfp = await enka.hasProfilePicture(7300);
120
+
121
+ // Check if name card exists
122
+ const hasNameCard = await enka.hasNameCard(210214);
123
+ ```
124
+
125
+ ## Error Handling
126
+
127
+ ```typescript
128
+ import { EnkaApiError, EnkaMappingError } from "lunassets";
129
+
130
+ try {
131
+ const assets = await enka.getPlayerAssets("123456");
132
+ } catch (error) {
133
+ if (error instanceof EnkaApiError) {
134
+ console.error("API Error:", error.message);
135
+ } else if (error instanceof EnkaMappingError) {
136
+ console.error("Mapping Error:", error.message);
137
+ }
138
+ }
139
+ ```
140
+
141
+ ## License
142
+
143
+ See the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,22 @@
1
+ import { EnkaApiResponse, FetchPlayerParams, EnkaAssetConfig } from "../types";
2
+ export declare class EnkaApiClient {
3
+ private config;
4
+ constructor(config?: Partial<EnkaAssetConfig>);
5
+ /**
6
+ * Fetch player data from Enka Network API
7
+ */
8
+ fetchPlayerData(params: FetchPlayerParams): Promise<EnkaApiResponse>;
9
+ /**
10
+ * Get player data with rate limiting awareness
11
+ */
12
+ getPlayerData(uid: string | number): Promise<EnkaApiResponse>;
13
+ /**
14
+ * Update configuration
15
+ */
16
+ updateConfig(newConfig: Partial<EnkaAssetConfig>): void;
17
+ /**
18
+ * Get current configuration
19
+ */
20
+ getConfig(): EnkaAssetConfig;
21
+ }
22
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/core/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,iBAAiB,EAEjB,eAAe,EAChB,MAAM,UAAU,CAAC;AAGlB,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAkB;gBAEpB,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;IAO7C;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC;IA2C1E;;OAEG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAenE;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAOvD;;OAEG;IACH,SAAS,IAAI,eAAe;CAG7B"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EnkaApiClient = void 0;
4
+ const types_1 = require("../types");
5
+ const utils_1 = require("../utils");
6
+ class EnkaApiClient {
7
+ constructor(config) {
8
+ this.config = {
9
+ ...utils_1.DEFAULT_CONFIG,
10
+ ...config,
11
+ };
12
+ }
13
+ /**
14
+ * Fetch player data from Enka Network API
15
+ */
16
+ async fetchPlayerData(params) {
17
+ const { uid, info = true } = params;
18
+ // Build URL
19
+ const url = `${this.config.apiUrl}/uid/${uid}${info ? "?info" : ""}`;
20
+ try {
21
+ const response = await fetch(url, {
22
+ headers: {
23
+ "User-Agent": this.config.userAgent || utils_1.DEFAULT_CONFIG.userAgent,
24
+ },
25
+ // Note: timeout handling can be done with AbortController if needed
26
+ });
27
+ if (!response.ok) {
28
+ throw new types_1.EnkaApiError(`API request failed: ${response.status} ${response.statusText}`, response.status);
29
+ }
30
+ const data = (await response.json());
31
+ // Validate response structure
32
+ if (!data.playerInfo) {
33
+ throw new types_1.EnkaApiError("Invalid API response: missing playerInfo");
34
+ }
35
+ return data;
36
+ }
37
+ catch (error) {
38
+ if (error instanceof types_1.EnkaApiError) {
39
+ throw error;
40
+ }
41
+ // Network atau parsing errors
42
+ if (error instanceof Error) {
43
+ throw new types_1.EnkaApiError(`Network error: ${error.message}`);
44
+ }
45
+ throw new types_1.EnkaApiError("Unknown API error");
46
+ }
47
+ }
48
+ /**
49
+ * Get player data with rate limiting awareness
50
+ */
51
+ async getPlayerData(uid) {
52
+ try {
53
+ return await this.fetchPlayerData({ uid, info: true });
54
+ }
55
+ catch (error) {
56
+ if (error instanceof types_1.EnkaApiError && error.statusCode === 429) {
57
+ // Rate limited, bisa implement retry atau throw dengan pesan yang lebih friendly
58
+ throw new types_1.EnkaApiError("Rate limited by Enka API. Please try again later.", 429);
59
+ }
60
+ throw error;
61
+ }
62
+ }
63
+ /**
64
+ * Update configuration
65
+ */
66
+ updateConfig(newConfig) {
67
+ this.config = {
68
+ ...this.config,
69
+ ...newConfig,
70
+ };
71
+ }
72
+ /**
73
+ * Get current configuration
74
+ */
75
+ getConfig() {
76
+ return { ...this.config };
77
+ }
78
+ }
79
+ exports.EnkaApiClient = EnkaApiClient;
80
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/core/api-client.ts"],"names":[],"mappings":";;;AAAA,oCAKkB;AAClB,oCAA0C;AAE1C,MAAa,aAAa;IAGxB,YAAY,MAAiC;QAC3C,IAAI,CAAC,MAAM,GAAG;YACZ,GAAG,sBAAc;YACjB,GAAG,MAAM;SACV,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,MAAyB;QAC7C,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;QAEpC,YAAY;QACZ,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAErE,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,OAAO,EAAE;oBACP,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,sBAAc,CAAC,SAAS;iBAChE;gBACD,oEAAoE;aACrE,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,oBAAY,CACpB,uBAAuB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,EAC/D,QAAQ,CAAC,MAAM,CAChB,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAoB,CAAC;YAExD,8BAA8B;YAC9B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;gBACrB,MAAM,IAAI,oBAAY,CAAC,0CAA0C,CAAC,CAAC;YACrE,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,oBAAY,EAAE,CAAC;gBAClC,MAAM,KAAK,CAAC;YACd,CAAC;YAED,8BAA8B;YAC9B,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,MAAM,IAAI,oBAAY,CAAC,kBAAkB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5D,CAAC;YAED,MAAM,IAAI,oBAAY,CAAC,mBAAmB,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,GAAoB;QACtC,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,eAAe,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,oBAAY,IAAI,KAAK,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;gBAC9D,iFAAiF;gBACjF,MAAM,IAAI,oBAAY,CACpB,mDAAmD,EACnD,GAAG,CACJ,CAAC;YACJ,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,SAAmC;QAC9C,IAAI,CAAC,MAAM,GAAG;YACZ,GAAG,IAAI,CAAC,MAAM;YACd,GAAG,SAAS;SACb,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC5B,CAAC;CACF;AA1FD,sCA0FC"}
@@ -0,0 +1,106 @@
1
+ import { EnkaApiResponse, ProcessedPlayerAssets } from "../types";
2
+ import { EnkaUrlBuilder } from "./url-builder";
3
+ export declare class EnkaAssetMapper {
4
+ private dataFetcher;
5
+ private urlBuilder;
6
+ constructor(urlBuilder: EnkaUrlBuilder);
7
+ /**
8
+ * Map API response to processed player assets
9
+ */
10
+ mapPlayerAssets(apiResponse: EnkaApiResponse): Promise<ProcessedPlayerAssets>;
11
+ /**
12
+ * Map profile picture ID to processed profile picture
13
+ */
14
+ private mapProfilePicture;
15
+ /**
16
+ * Map name card ID to processed name card
17
+ */
18
+ private mapNameCard;
19
+ /**
20
+ * Map avatar ID to processed show avatar
21
+ */
22
+ private mapShowAvatar;
23
+ /**
24
+ * Get character data by ID
25
+ */
26
+ getCharacterData(avatarId: number): Promise<{
27
+ Element: string;
28
+ Consts: string[];
29
+ SkillOrder: number[];
30
+ Skills: {
31
+ [skillId: string]: string;
32
+ };
33
+ ProudMap: {
34
+ [skillId: string]: number;
35
+ };
36
+ NameTextMapHash: number;
37
+ SideIconName: string;
38
+ QualityType: "QUALITY_ORANGE" | "QUALITY_PURPLE";
39
+ WeaponType: string;
40
+ Costumes?: {
41
+ [costumeId: string]: {
42
+ sideIconName: string;
43
+ icon: string;
44
+ art: string;
45
+ avatarId: number;
46
+ };
47
+ };
48
+ }>;
49
+ /**
50
+ * Get profile picture data by ID
51
+ */
52
+ getProfilePictureData(pfpId: number): Promise<{
53
+ IconPath: string;
54
+ }>;
55
+ /**
56
+ * Get name card data by ID
57
+ */
58
+ getNameCardData(nameCardId: number): Promise<{
59
+ icon: string;
60
+ }>;
61
+ /**
62
+ * Check if character exists
63
+ */
64
+ hasCharacter(avatarId: number): Promise<boolean>;
65
+ /**
66
+ * Check if profile picture exists
67
+ */
68
+ hasProfilePicture(pfpId: number): Promise<boolean>;
69
+ /**
70
+ * Check if name card exists
71
+ */
72
+ hasNameCard(nameCardId: number): Promise<boolean>;
73
+ /**
74
+ * Get statistics about loaded data
75
+ */
76
+ getDataStats(): Promise<{
77
+ characters: number;
78
+ profilePictures: number;
79
+ nameCards: number;
80
+ }>;
81
+ /**
82
+ * Get data fetcher cache info
83
+ */
84
+ getDataCacheInfo(): {
85
+ characters: {
86
+ cached: boolean;
87
+ age: number;
88
+ expired: boolean;
89
+ };
90
+ pfps: {
91
+ cached: boolean;
92
+ age: number;
93
+ expired: boolean;
94
+ };
95
+ namecards: {
96
+ cached: boolean;
97
+ age: number;
98
+ expired: boolean;
99
+ };
100
+ };
101
+ /**
102
+ * Clear reference data cache
103
+ */
104
+ clearDataCache(): void;
105
+ }
106
+ //# sourceMappingURL=asset-mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-mapper.d.ts","sourceRoot":"","sources":["../../src/core/asset-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EAIf,qBAAqB,EAKtB,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,qBAAa,eAAe;IAC1B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,UAAU,CAAiB;gBAEvB,UAAU,EAAE,cAAc;IAKtC;;OAEG;IACG,eAAe,CACnB,WAAW,EAAE,eAAe,GAC3B,OAAO,CAAC,qBAAqB,CAAC;IA6CjC;;OAEG;YACW,iBAAiB;IAuB/B;;OAEG;YACW,WAAW;IAoBzB;;OAEG;YACW,aAAa;IAoC3B;;OAEG;IACG,gBAAgB,CAAC,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;IAKvC;;OAEG;IACG,qBAAqB,CAAC,KAAK,EAAE,MAAM;;;IAKzC;;OAEG;IACG,eAAe,CAAC,UAAU,EAAE,MAAM;;;IAKxC;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKtD;;OAEG;IACG,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKxD;;OAEG;IACG,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKvD;;OAEG;IACG,YAAY;;;;;IAclB;;OAEG;IACH,gBAAgB;;;;;;;;;;;;;;;;;IAIhB;;OAEG;IACH,cAAc,IAAI,IAAI;CAGvB"}
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EnkaAssetMapper = void 0;
4
+ const types_1 = require("../types");
5
+ const utils_1 = require("../utils");
6
+ const data_fetcher_1 = require("./data-fetcher");
7
+ class EnkaAssetMapper {
8
+ constructor(urlBuilder) {
9
+ this.dataFetcher = new data_fetcher_1.EnkaDataFetcher();
10
+ this.urlBuilder = urlBuilder;
11
+ }
12
+ /**
13
+ * Map API response to processed player assets
14
+ */
15
+ async mapPlayerAssets(apiResponse) {
16
+ const { playerInfo } = apiResponse;
17
+ // Process profile picture
18
+ const profilePicture = await this.mapProfilePicture(playerInfo.profilePicture.id);
19
+ // Process name card
20
+ const nameCard = await this.mapNameCard(playerInfo.nameCardId);
21
+ // Process show avatars
22
+ const showAvatars = await Promise.all(playerInfo.showAvatarInfoList.map((avatar) => this.mapShowAvatar(avatar.avatarId, avatar.level, avatar.talentLevel)));
23
+ return {
24
+ playerInfo: {
25
+ nickname: playerInfo.nickname,
26
+ level: playerInfo.level,
27
+ signature: playerInfo.signature,
28
+ worldLevel: playerInfo.worldLevel,
29
+ finishAchievementNum: playerInfo.finishAchievementNum,
30
+ towerFloorIndex: playerInfo.towerFloorIndex,
31
+ towerLevelIndex: playerInfo.towerLevelIndex,
32
+ theaterActIndex: playerInfo.theaterActIndex,
33
+ theaterModeIndex: playerInfo.theaterModeIndex,
34
+ theaterStarIndex: playerInfo.theaterStarIndex,
35
+ isShowAvatarTalent: playerInfo.isShowAvatarTalent,
36
+ fetterCount: playerInfo.fetterCount,
37
+ towerStarIndex: playerInfo.towerStarIndex,
38
+ stygianIndex: playerInfo.stygianIndex,
39
+ stygianSeconds: playerInfo.stygianSeconds,
40
+ stygianId: playerInfo.stygianId,
41
+ },
42
+ profilePicture,
43
+ nameCard,
44
+ showAvatars,
45
+ ttl: apiResponse.ttl,
46
+ lastUpdated: new Date(),
47
+ };
48
+ }
49
+ /**
50
+ * Map profile picture ID to processed profile picture
51
+ */
52
+ async mapProfilePicture(pfpId) {
53
+ const pfpsData = await this.dataFetcher.getPfpsData();
54
+ const pfpData = pfpsData[pfpId.toString()];
55
+ if (!pfpData) {
56
+ throw new types_1.EnkaMappingError(`Profile picture not found for ID: ${pfpId}`, pfpId);
57
+ }
58
+ // IconPath di pfps.json sudah include full path dan extension
59
+ const url = `https://enka.network${pfpData.IconPath}`;
60
+ return {
61
+ id: pfpId,
62
+ iconName: pfpData.IconPath,
63
+ url,
64
+ };
65
+ }
66
+ /**
67
+ * Map name card ID to processed name card
68
+ */
69
+ async mapNameCard(nameCardId) {
70
+ const namecardsData = await this.dataFetcher.getNamecardsData();
71
+ const nameCardData = namecardsData[nameCardId.toString()];
72
+ if (!nameCardData) {
73
+ throw new types_1.EnkaMappingError(`Name card not found for ID: ${nameCardId}`, nameCardId);
74
+ }
75
+ const url = this.urlBuilder.buildNameCardUrl(nameCardData.icon);
76
+ return {
77
+ id: nameCardId,
78
+ iconName: nameCardData.icon,
79
+ url,
80
+ };
81
+ }
82
+ /**
83
+ * Map avatar ID to processed show avatar
84
+ */
85
+ async mapShowAvatar(avatarId, level, talentLevel) {
86
+ const charactersData = await this.dataFetcher.getCharactersData();
87
+ const characterData = charactersData[avatarId.toString()];
88
+ if (!characterData) {
89
+ throw new types_1.EnkaMappingError(`Character not found for ID: ${avatarId}`, avatarId);
90
+ }
91
+ // Transform SideIconName (hilangkan "Side_")
92
+ const iconName = (0, utils_1.transformIconName)(characterData.SideIconName);
93
+ // Convert quality type to numeric
94
+ const quality = (0, utils_1.getQualityNumeric)(characterData.QualityType);
95
+ // Build URL
96
+ const url = this.urlBuilder.buildCharacterIconUrl(iconName);
97
+ return {
98
+ avatarId,
99
+ iconName,
100
+ url,
101
+ quality,
102
+ level,
103
+ talentLevel,
104
+ element: characterData.Element,
105
+ weaponType: characterData.WeaponType,
106
+ };
107
+ }
108
+ /**
109
+ * Get character data by ID
110
+ */
111
+ async getCharacterData(avatarId) {
112
+ const charactersData = await this.dataFetcher.getCharactersData();
113
+ return charactersData[avatarId.toString()] || null;
114
+ }
115
+ /**
116
+ * Get profile picture data by ID
117
+ */
118
+ async getProfilePictureData(pfpId) {
119
+ const pfpsData = await this.dataFetcher.getPfpsData();
120
+ return pfpsData[pfpId.toString()] || null;
121
+ }
122
+ /**
123
+ * Get name card data by ID
124
+ */
125
+ async getNameCardData(nameCardId) {
126
+ const namecardsData = await this.dataFetcher.getNamecardsData();
127
+ return namecardsData[nameCardId.toString()] || null;
128
+ }
129
+ /**
130
+ * Check if character exists
131
+ */
132
+ async hasCharacter(avatarId) {
133
+ const charactersData = await this.dataFetcher.getCharactersData();
134
+ return avatarId.toString() in charactersData;
135
+ }
136
+ /**
137
+ * Check if profile picture exists
138
+ */
139
+ async hasProfilePicture(pfpId) {
140
+ const pfpsData = await this.dataFetcher.getPfpsData();
141
+ return pfpId.toString() in pfpsData;
142
+ }
143
+ /**
144
+ * Check if name card exists
145
+ */
146
+ async hasNameCard(nameCardId) {
147
+ const namecardsData = await this.dataFetcher.getNamecardsData();
148
+ return nameCardId.toString() in namecardsData;
149
+ }
150
+ /**
151
+ * Get statistics about loaded data
152
+ */
153
+ async getDataStats() {
154
+ const [charactersData, pfpsData, namecardsData] = await Promise.all([
155
+ this.dataFetcher.getCharactersData(),
156
+ this.dataFetcher.getPfpsData(),
157
+ this.dataFetcher.getNamecardsData(),
158
+ ]);
159
+ return {
160
+ characters: Object.keys(charactersData).length,
161
+ profilePictures: Object.keys(pfpsData).length,
162
+ nameCards: Object.keys(namecardsData).length,
163
+ };
164
+ }
165
+ /**
166
+ * Get data fetcher cache info
167
+ */
168
+ getDataCacheInfo() {
169
+ return this.dataFetcher.getCacheInfo();
170
+ }
171
+ /**
172
+ * Clear reference data cache
173
+ */
174
+ clearDataCache() {
175
+ this.dataFetcher.clearCache();
176
+ }
177
+ }
178
+ exports.EnkaAssetMapper = EnkaAssetMapper;
179
+ //# sourceMappingURL=asset-mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-mapper.js","sourceRoot":"","sources":["../../src/core/asset-mapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import { EnkaAssetConfig } from "../types";
2
+ export declare class EnkaCacheManager {
3
+ private cache;
4
+ private config;
5
+ constructor(config?: Partial<EnkaAssetConfig>);
6
+ /**
7
+ * Get data from cache if valid
8
+ */
9
+ get<T>(key: string): T | null;
10
+ /**
11
+ * Set data in cache
12
+ */
13
+ set<T>(key: string, data: T, ttl?: number): void;
14
+ /**
15
+ * Get player data cache key
16
+ */
17
+ getPlayerCacheKey(uid: string | number): string;
18
+ /**
19
+ * Check if player data is cached and valid
20
+ */
21
+ hasValidPlayerCache(uid: string | number): boolean;
22
+ /**
23
+ * Get cached player data
24
+ */
25
+ getCachedPlayerData<T>(uid: string | number): T | null;
26
+ /**
27
+ * Cache player data
28
+ */
29
+ cachePlayerData<T>(uid: string | number, data: T): void;
30
+ /**
31
+ * Clear specific cache entry
32
+ */
33
+ invalidate(key: string): boolean;
34
+ /**
35
+ * Clear player cache
36
+ */
37
+ invalidatePlayer(uid: string | number): boolean;
38
+ /**
39
+ * Clear all cache
40
+ */
41
+ clear(): void;
42
+ /**
43
+ * Get cache statistics
44
+ */
45
+ getStats(): {
46
+ total: number;
47
+ valid: number;
48
+ expired: number;
49
+ };
50
+ /**
51
+ * Cleanup expired entries
52
+ */
53
+ cleanup(): number;
54
+ /**
55
+ * Get cache entry info
56
+ */
57
+ getCacheInfo(key: string): {
58
+ exists: boolean;
59
+ valid?: boolean;
60
+ age?: number;
61
+ ttl?: number;
62
+ };
63
+ }
64
+ //# sourceMappingURL=cache-manager.d.ts.map