sa2kit 1.6.3 → 1.6.6
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/dist/audioDetection/index.js.map +1 -1
- package/dist/audioDetection/index.mjs.map +1 -1
- package/dist/auth/index.d.mts +26 -1
- package/dist/auth/index.d.ts +26 -1
- package/dist/auth/index.js +51 -23
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/index.mjs +34 -3
- package/dist/auth/index.mjs.map +1 -1
- package/dist/auth/middleware/index.js +3 -3
- package/dist/auth/middleware/index.mjs +2 -2
- package/dist/auth/routes/index.js +14 -14
- package/dist/auth/routes/index.mjs +2 -2
- package/dist/auth/services/index.d.mts +1 -0
- package/dist/auth/services/index.d.ts +1 -0
- package/dist/auth/services/index.js +7 -7
- package/dist/auth/services/index.mjs +1 -1
- package/dist/calendar/index.d.mts +1197 -0
- package/dist/calendar/index.d.ts +1197 -0
- package/dist/calendar/index.js +5376 -0
- package/dist/calendar/index.js.map +1 -0
- package/dist/calendar/index.mjs +5311 -0
- package/dist/calendar/index.mjs.map +1 -0
- package/dist/calendar/routes/index.d.mts +118 -0
- package/dist/calendar/routes/index.d.ts +118 -0
- package/dist/calendar/routes/index.js +335 -0
- package/dist/calendar/routes/index.js.map +1 -0
- package/dist/calendar/routes/index.mjs +327 -0
- package/dist/calendar/routes/index.mjs.map +1 -0
- package/dist/calendar/server.d.mts +1184 -0
- package/dist/calendar/server.d.ts +1184 -0
- package/dist/calendar/server.js +219 -0
- package/dist/calendar/server.js.map +1 -0
- package/dist/calendar/server.mjs +165 -0
- package/dist/calendar/server.mjs.map +1 -0
- package/dist/{chunk-EBP7AE6F.js → chunk-2ODO4HEI.js} +48 -20
- package/dist/chunk-2ODO4HEI.js.map +1 -0
- package/dist/{chunk-RCNNVNLT.mjs → chunk-3BGPZN4X.mjs} +8 -3
- package/dist/chunk-3BGPZN4X.mjs.map +1 -0
- package/dist/{chunk-FV3FNHQY.js → chunk-6W5BMXJG.js} +4 -4
- package/dist/{chunk-FV3FNHQY.js.map → chunk-6W5BMXJG.js.map} +1 -1
- package/dist/chunk-6WXOA4BE.mjs +302 -0
- package/dist/chunk-6WXOA4BE.mjs.map +1 -0
- package/dist/{chunk-NMF4ANIC.js → chunk-7Z5LLJ3A.js} +8 -2
- package/dist/chunk-7Z5LLJ3A.js.map +1 -0
- package/dist/chunk-AXP7KROR.js +314 -0
- package/dist/chunk-AXP7KROR.js.map +1 -0
- package/dist/{chunk-42IJ7HEI.js → chunk-CD77U7LZ.js} +5 -5
- package/dist/{chunk-42IJ7HEI.js.map → chunk-CD77U7LZ.js.map} +1 -1
- package/dist/{chunk-6BL3AZGD.js → chunk-DUHZ7VZP.js} +2 -2
- package/dist/chunk-DUHZ7VZP.js.map +1 -0
- package/dist/{chunk-6VHWOPRR.mjs → chunk-ESRCX5TQ.mjs} +3 -3
- package/dist/{chunk-6VHWOPRR.mjs.map → chunk-ESRCX5TQ.mjs.map} +1 -1
- package/dist/{chunk-QKXKXAAV.js → chunk-G4AMEDO5.js} +2 -2
- package/dist/{chunk-QKXKXAAV.js.map → chunk-G4AMEDO5.js.map} +1 -1
- package/dist/chunk-GAC4J5GX.js +228 -0
- package/dist/chunk-GAC4J5GX.js.map +1 -0
- package/dist/chunk-IEA55H3G.js +106 -0
- package/dist/chunk-IEA55H3G.js.map +1 -0
- package/dist/{chunk-U2L6V7KD.mjs → chunk-OCR5DS4C.mjs} +2 -2
- package/dist/chunk-OCR5DS4C.mjs.map +1 -0
- package/dist/{chunk-IBLB7ARJ.mjs → chunk-QAT2RWAO.mjs} +3 -3
- package/dist/{chunk-IBLB7ARJ.mjs.map → chunk-QAT2RWAO.mjs.map} +1 -1
- package/dist/chunk-R2F4BXUU.mjs +100 -0
- package/dist/chunk-R2F4BXUU.mjs.map +1 -0
- package/dist/chunk-T6TE7GTY.mjs +218 -0
- package/dist/chunk-T6TE7GTY.mjs.map +1 -0
- package/dist/{chunk-MBG4DBGP.mjs → chunk-ZCLAF3XN.mjs} +47 -19
- package/dist/chunk-ZCLAF3XN.mjs.map +1 -0
- package/dist/{chunk-6LEA37ZM.mjs → chunk-ZYXF3L6T.mjs} +2 -2
- package/dist/{chunk-6LEA37ZM.mjs.map → chunk-ZYXF3L6T.mjs.map} +1 -1
- package/dist/imageCrop/index.js.map +1 -1
- package/dist/imageCrop/index.mjs.map +1 -1
- package/dist/{index-DtLpANUB.d.mts → index-DSel44Ke.d.mts} +24 -1
- package/dist/{index-DtLpANUB.d.ts → index-DSel44Ke.d.ts} +24 -1
- package/dist/index.d.mts +426 -3
- package/dist/index.d.ts +426 -3
- package/dist/index.js +2116 -65
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1949 -33
- package/dist/index.mjs.map +1 -1
- package/dist/mmd/index.d.mts +78 -1
- package/dist/mmd/index.d.ts +78 -1
- package/dist/mmd/index.js +397 -50
- package/dist/mmd/index.js.map +1 -1
- package/dist/mmd/index.mjs +399 -53
- package/dist/mmd/index.mjs.map +1 -1
- package/dist/music/index.d.mts +54 -5
- package/dist/music/index.d.ts +54 -5
- package/dist/music/index.js +35 -435
- package/dist/music/index.js.map +1 -1
- package/dist/music/index.mjs +2 -424
- package/dist/music/index.mjs.map +1 -1
- package/dist/music/server/index.d.mts +1 -1
- package/dist/music/server/index.d.ts +1 -1
- package/dist/music/server/index.js +14 -6
- package/dist/music/server/index.mjs +1 -1
- package/dist/testYourself/admin/index.js +3 -3
- package/dist/testYourself/admin/index.mjs +1 -1
- package/dist/testYourself/index.js +7 -7
- package/dist/testYourself/index.js.map +1 -1
- package/dist/testYourself/index.mjs +2 -2
- package/dist/testYourself/index.mjs.map +1 -1
- package/dist/universalFile/index.d.mts +125 -7
- package/dist/universalFile/index.d.ts +125 -7
- package/dist/universalFile/index.js +1253 -30
- package/dist/universalFile/index.js.map +1 -1
- package/dist/universalFile/index.mjs +1244 -23
- package/dist/universalFile/index.mjs.map +1 -1
- package/dist/utils/index.d.mts +5 -1
- package/dist/utils/index.d.ts +5 -1
- package/dist/utils/index.js +13 -9
- package/dist/utils/index.mjs +1 -1
- package/package.json +18 -3
- package/dist/chunk-6BL3AZGD.js.map +0 -1
- package/dist/chunk-EBP7AE6F.js.map +0 -1
- package/dist/chunk-MBG4DBGP.mjs.map +0 -1
- package/dist/chunk-NMF4ANIC.js.map +0 -1
- package/dist/chunk-RCNNVNLT.mjs.map +0 -1
- package/dist/chunk-U2L6V7KD.mjs.map +0 -1
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunk2ODO4HEI_js = require('./chunk-2ODO4HEI.js');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var useSWR = require('swr');
|
|
6
|
+
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var useSWR__default = /*#__PURE__*/_interopDefault(useSWR);
|
|
10
|
+
|
|
11
|
+
// src/music/adapters/kugou.ts
|
|
12
|
+
var kugouAdapter = {
|
|
13
|
+
parseSearchResult(data) {
|
|
14
|
+
const root = typeof data === "string" ? JSON.parse(data) : data;
|
|
15
|
+
const info = root.data?.data?.info || root.data?.info || root.info || [];
|
|
16
|
+
const total = root.data?.data?.total || root.data?.total || info.length;
|
|
17
|
+
return {
|
|
18
|
+
tracks: info.map((item) => {
|
|
19
|
+
let pic = item.pic || "";
|
|
20
|
+
if (item.trans_param?.union_cover) {
|
|
21
|
+
pic = item.trans_param.union_cover.replace("{size}", "400");
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
id: item.hash || item.id,
|
|
25
|
+
name: item.songname || item.filename || "Unknown",
|
|
26
|
+
artist: item.singername || "Unknown Artist",
|
|
27
|
+
album: item.album_name || item.album || "",
|
|
28
|
+
pic,
|
|
29
|
+
url: item.url,
|
|
30
|
+
lrc: item.lrc,
|
|
31
|
+
source: "kugou",
|
|
32
|
+
isVip: item.privilege >= 8,
|
|
33
|
+
playable: item.status !== 0
|
|
34
|
+
};
|
|
35
|
+
}),
|
|
36
|
+
total
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
parseGetSongUrl(data) {
|
|
40
|
+
return data.url?.url || data.url?.backup_url?.[0] || null;
|
|
41
|
+
},
|
|
42
|
+
parseGetLyric(data) {
|
|
43
|
+
const root = typeof data === "string" ? JSON.parse(data) : data;
|
|
44
|
+
return root.lyric || root.lrc || root.data?.lyric || root.data || "";
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// src/music/adapters/netease.ts
|
|
49
|
+
var neteaseAdapter = {
|
|
50
|
+
parseSearchResult(data) {
|
|
51
|
+
const root = typeof data === "string" ? JSON.parse(data) : data;
|
|
52
|
+
const songs = root.result?.songs || root.songs || (Array.isArray(root) ? root : []);
|
|
53
|
+
return {
|
|
54
|
+
tracks: songs.map((item) => ({
|
|
55
|
+
id: item.id,
|
|
56
|
+
name: item.name,
|
|
57
|
+
artist: Array.isArray(item.artist) ? item.artist.join(", ") : item.artist,
|
|
58
|
+
album: item.album?.name || item.album,
|
|
59
|
+
pic: item.pic || item.album?.picUrl,
|
|
60
|
+
url: item.url,
|
|
61
|
+
lrc: item.lrc,
|
|
62
|
+
source: "netease",
|
|
63
|
+
isVip: item.fee === 1 || item.fee === 4,
|
|
64
|
+
playable: item.noCopyrightRcmd === null
|
|
65
|
+
})),
|
|
66
|
+
total: root.result?.songCount || songs.length
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
parseGetSongUrl(data) {
|
|
70
|
+
const root = typeof data === "string" ? JSON.parse(data) : data;
|
|
71
|
+
const item = root.data?.[0] || root[0] || root;
|
|
72
|
+
return item.url || null;
|
|
73
|
+
},
|
|
74
|
+
parseGetLyric(data) {
|
|
75
|
+
const root = typeof data === "string" ? JSON.parse(data) : data;
|
|
76
|
+
return root.lyric || root.lrc || root.data?.lyric || "";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// src/music/adapters/tencent.ts
|
|
81
|
+
var tencentAdapter = {
|
|
82
|
+
parseSearchResult(data) {
|
|
83
|
+
const root = typeof data === "string" ? JSON.parse(data) : data;
|
|
84
|
+
const songData = root.data?.data?.song || root.data?.song || root.data || root;
|
|
85
|
+
const list = songData.list || root.songs || [];
|
|
86
|
+
const total = songData.totalnum || root.total || list.length;
|
|
87
|
+
return {
|
|
88
|
+
tracks: list.map((item) => {
|
|
89
|
+
const artist = Array.isArray(item.singer) ? item.singer.map((s) => s.name).join(", ") : item.singer?.[0]?.name || item.artist || "Unknown";
|
|
90
|
+
let pic = item.pic;
|
|
91
|
+
if (!pic && item.album?.mid) {
|
|
92
|
+
pic = `https://y.gtimg.cn/music/photo_new/T002R300x300M000${item.album.mid}.jpg`;
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
id: item.mid || item.id || item.songid,
|
|
96
|
+
name: item.name || item.title || item.songname,
|
|
97
|
+
artist,
|
|
98
|
+
album: item.album?.name || item.albumname || item.album,
|
|
99
|
+
pic: pic || "",
|
|
100
|
+
url: item.url,
|
|
101
|
+
lrc: item.lrc,
|
|
102
|
+
source: "tencent",
|
|
103
|
+
isVip: item.pay?.pay_play === 1,
|
|
104
|
+
playable: item.action?.switch !== 0
|
|
105
|
+
};
|
|
106
|
+
}),
|
|
107
|
+
total
|
|
108
|
+
};
|
|
109
|
+
},
|
|
110
|
+
parseGetSongUrl(data) {
|
|
111
|
+
const root = data;
|
|
112
|
+
const urlData = root.url.url;
|
|
113
|
+
let finalUrl = Object.values(urlData)[0];
|
|
114
|
+
console.log("finalUrl2", finalUrl);
|
|
115
|
+
return finalUrl.startsWith("http") ? finalUrl : `http://${finalUrl}`;
|
|
116
|
+
},
|
|
117
|
+
parseGetLyric(data) {
|
|
118
|
+
const root = typeof data === "string" ? JSON.parse(data) : data;
|
|
119
|
+
return root.lyric || root.lrc || root.data?.lyric || "";
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// src/music/adapters/xiami.ts
|
|
124
|
+
var xiamiAdapter = {
|
|
125
|
+
parseSearchResult(data) {
|
|
126
|
+
const root = typeof data === "string" ? JSON.parse(data) : data;
|
|
127
|
+
const result = root.data?.result || root.result || root;
|
|
128
|
+
const songs = result.songs || (Array.isArray(root) ? root : []);
|
|
129
|
+
return {
|
|
130
|
+
tracks: songs.map((item) => ({
|
|
131
|
+
id: item.id?.toString() || "",
|
|
132
|
+
name: item.name || "Unknown",
|
|
133
|
+
artist: Array.isArray(item.ar) ? item.ar.map((a) => a.name).join(", ") : item.artist || "Unknown Artist",
|
|
134
|
+
album: item.al?.name || item.album || "",
|
|
135
|
+
pic: item.al?.picUrl || item.pic || "",
|
|
136
|
+
url: item.url,
|
|
137
|
+
lrc: item.lrc,
|
|
138
|
+
source: "xiami",
|
|
139
|
+
// 这里的逻辑参考提供的数据结构
|
|
140
|
+
isVip: item.fee === 1 || item.fee === 8,
|
|
141
|
+
playable: item.copyright !== 0
|
|
142
|
+
})),
|
|
143
|
+
total: result.songCount || songs.length
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
parseGetSongUrl(data) {
|
|
147
|
+
const root = typeof data === "string" ? JSON.parse(data) : data;
|
|
148
|
+
const item = root.data?.[0] || root.data || root[0] || root;
|
|
149
|
+
return item.url || null;
|
|
150
|
+
},
|
|
151
|
+
parseGetLyric(data) {
|
|
152
|
+
const root = typeof data === "string" ? JSON.parse(data) : data;
|
|
153
|
+
return root.lyric || root.lrc || root.data?.lyric || root.data || "";
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// src/music/hooks/useMusic.ts
|
|
158
|
+
var fetcher = (url) => fetch(url).then((res) => res.json());
|
|
159
|
+
var ADAPTERS = {
|
|
160
|
+
kugou: kugouAdapter,
|
|
161
|
+
netease: neteaseAdapter,
|
|
162
|
+
tencent: tencentAdapter,
|
|
163
|
+
xiami: xiamiAdapter
|
|
164
|
+
};
|
|
165
|
+
function useMusic() {
|
|
166
|
+
const [searchOptions, setSearchOptions] = react.useState(null);
|
|
167
|
+
const { data: rawData, error: searchError, isLoading: isSearching } = useSWR__default.default(
|
|
168
|
+
searchOptions ? `/api/music/search?keyword=${encodeURIComponent(searchOptions.keyword)}&source=${searchOptions.source || chunk2ODO4HEI_js.DEFAULT_MUSIC_SOURCE}&limit=${searchOptions.limit || 20}&offset=${searchOptions.offset || 0}${searchOptions.miku ? "&miku=true" : ""}` : null,
|
|
169
|
+
fetcher
|
|
170
|
+
);
|
|
171
|
+
const searchResult = react.useMemo(() => {
|
|
172
|
+
if (!rawData?.data || !searchOptions) return void 0;
|
|
173
|
+
const adapter = ADAPTERS[searchOptions.source || chunk2ODO4HEI_js.DEFAULT_MUSIC_SOURCE];
|
|
174
|
+
if (adapter) {
|
|
175
|
+
return adapter.parseSearchResult(rawData.data);
|
|
176
|
+
}
|
|
177
|
+
return void 0;
|
|
178
|
+
}, [rawData, searchOptions]);
|
|
179
|
+
const search = react.useCallback((options) => {
|
|
180
|
+
setSearchOptions(options);
|
|
181
|
+
}, []);
|
|
182
|
+
const getSongUrl = react.useCallback(async (id, source = chunk2ODO4HEI_js.DEFAULT_MUSIC_SOURCE) => {
|
|
183
|
+
try {
|
|
184
|
+
const res = await fetch(`/api/music/url?id=${id}&source=${source}`);
|
|
185
|
+
const json = await res.json();
|
|
186
|
+
const adapter = ADAPTERS[source];
|
|
187
|
+
console.log("json2", json.data, source, adapter);
|
|
188
|
+
if (adapter && json.data) {
|
|
189
|
+
console.log("getSongUrl2", json.data);
|
|
190
|
+
return adapter.parseGetSongUrl(json.data) || void 0;
|
|
191
|
+
}
|
|
192
|
+
return json.data?.url;
|
|
193
|
+
} catch (err) {
|
|
194
|
+
console.error("[Music] Failed to get song URL:", err);
|
|
195
|
+
return void 0;
|
|
196
|
+
}
|
|
197
|
+
}, []);
|
|
198
|
+
const getLyric = react.useCallback(async (id, source = chunk2ODO4HEI_js.DEFAULT_MUSIC_SOURCE) => {
|
|
199
|
+
try {
|
|
200
|
+
const res = await fetch(`/api/music/lyric?id=${id}&source=${source}`);
|
|
201
|
+
const json = await res.json();
|
|
202
|
+
const adapter = ADAPTERS[source];
|
|
203
|
+
if (adapter && json.data) {
|
|
204
|
+
return adapter.parseGetLyric(json.data);
|
|
205
|
+
}
|
|
206
|
+
return json.data?.lyric;
|
|
207
|
+
} catch (err) {
|
|
208
|
+
console.error("[Music] Failed to get lyric:", err);
|
|
209
|
+
return void 0;
|
|
210
|
+
}
|
|
211
|
+
}, []);
|
|
212
|
+
return {
|
|
213
|
+
search,
|
|
214
|
+
searchResult,
|
|
215
|
+
isSearching,
|
|
216
|
+
searchError,
|
|
217
|
+
getSongUrl,
|
|
218
|
+
getLyric
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
exports.kugouAdapter = kugouAdapter;
|
|
223
|
+
exports.neteaseAdapter = neteaseAdapter;
|
|
224
|
+
exports.tencentAdapter = tencentAdapter;
|
|
225
|
+
exports.useMusic = useMusic;
|
|
226
|
+
exports.xiamiAdapter = xiamiAdapter;
|
|
227
|
+
//# sourceMappingURL=chunk-GAC4J5GX.js.map
|
|
228
|
+
//# sourceMappingURL=chunk-GAC4J5GX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/music/adapters/kugou.ts","../src/music/adapters/netease.ts","../src/music/adapters/tencent.ts","../src/music/adapters/xiami.ts","../src/music/hooks/useMusic.ts"],"names":["useState","useSWR","DEFAULT_MUSIC_SOURCE","useMemo","useCallback"],"mappings":"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","file":"chunk-GAC4J5GX.js","sourcesContent":["import { SearchResult } from '../types';\nimport { MusicSourceAdapter } from './types';\n\nexport const kugouAdapter: MusicSourceAdapter = {\n parseSearchResult(data: any): SearchResult {\n const root = typeof data === 'string' ? JSON.parse(data) : data;\n const info = root.data?.data?.info || root.data?.info || root.info || [];\n const total = root.data?.data?.total || root.data?.total || info.length;\n return {\n tracks: info.map((item: any) => {\n // 优先从 trans_param.union_cover 提取封面,并替换 {size} 为 400\n let pic = item.pic || '';\n if (item.trans_param?.union_cover) {\n pic = item.trans_param.union_cover.replace('{size}', '400');\n }\n\n return {\n id: item.hash || item.id,\n name: item.songname || item.filename || 'Unknown',\n artist: item.singername || 'Unknown Artist',\n album: item.album_name || item.album || '',\n pic: pic,\n url: item.url,\n lrc: item.lrc,\n source: 'kugou',\n isVip: item.privilege >= 8,\n playable: item.status !== 0,\n };\n }),\n total: total,\n };\n },\n\n parseGetSongUrl(data: any): string | null {\n return data.url?.url || data.url?.backup_url?.[0] || null;\n },\n\n parseGetLyric(data: any): any {\n const root = typeof data === 'string' ? JSON.parse(data) : data;\n return root.lyric || root.lrc || root.data?.lyric || root.data || '';\n }\n};\n","import { SearchResult } from '../types';\nimport { MusicSourceAdapter } from './types';\n\nexport const neteaseAdapter: MusicSourceAdapter = {\n parseSearchResult(data: any): SearchResult {\n const root = typeof data === 'string' ? JSON.parse(data) : data;\n const songs = root.result?.songs || root.songs || (Array.isArray(root) ? root : []);\n \n return {\n tracks: songs.map((item: any) => ({\n id: item.id,\n name: item.name,\n artist: Array.isArray(item.artist) ? item.artist.join(', ') : item.artist,\n album: item.album?.name || item.album,\n pic: item.pic || item.album?.picUrl,\n url: item.url,\n lrc: item.lrc,\n source: 'netease',\n isVip: item.fee === 1 || item.fee === 4,\n playable: item.noCopyrightRcmd === null,\n })),\n total: root.result?.songCount || songs.length,\n };\n },\n\n parseGetSongUrl(data: any): any {\n const root = typeof data === 'string' ? JSON.parse(data) : data;\n const item = root.data?.[0] || root[0] || root;\n return item.url || null;\n },\n\n parseGetLyric(data: any): any {\n const root = typeof data === 'string' ? JSON.parse(data) : data;\n return root.lyric || root.lrc || root.data?.lyric || '';\n }\n};\n\n","import { SearchResult } from '../types';\nimport { MusicSourceAdapter } from './types';\n\nexport const tencentAdapter: MusicSourceAdapter = {\n parseSearchResult(data: any): SearchResult {\n const root = typeof data === 'string' ? JSON.parse(data) : data;\n \n // 兼容多种 QQ 音乐返回结构\n const songData = root.data?.data?.song || root.data?.song || root.data || root;\n const list = songData.list || root.songs || [];\n const total = songData.totalnum || root.total || list.length;\n \n return {\n tracks: list.map((item: any) => {\n // 解析歌手名\n const artist = Array.isArray(item.singer) \n ? item.singer.map((s: any) => s.name).join(', ') \n : (item.singer?.[0]?.name || item.artist || 'Unknown');\n\n // 处理封面图 (QQ 音乐封面通常基于 album mid)\n let pic = item.pic;\n if (!pic && item.album?.mid) {\n pic = `https://y.gtimg.cn/music/photo_new/T002R300x300M000${item.album.mid}.jpg`;\n }\n\n return {\n id: item.mid || item.id || item.songid,\n name: item.name || item.title || item.songname,\n artist: artist,\n album: item.album?.name || item.albumname || item.album,\n pic: pic || '',\n url: item.url,\n lrc: item.lrc,\n source: 'tencent',\n isVip: item.pay?.pay_play === 1,\n playable: item.action?.switch !== 0,\n };\n }),\n total: total,\n };\n },\n\n parseGetSongUrl(data: any): string | null {\n\n const root = data\n\n const urlData = root.url.url;\n let finalUrl = Object.values(urlData)[0] as string;\n console.log('finalUrl2', finalUrl);\n return finalUrl.startsWith('http') ? finalUrl : `http://${finalUrl}`;\n },\n\n parseGetLyric(data: any): any {\n const root = typeof data === 'string' ? JSON.parse(data) : data;\n return root.lyric || root.lrc || root.data?.lyric || '';\n }\n};\n\n","import { SearchResult } from '../types';\nimport { MusicSourceAdapter } from './types';\n\nexport const xiamiAdapter: MusicSourceAdapter = {\n parseSearchResult(data: any): SearchResult {\n const root = typeof data === 'string' ? JSON.parse(data) : data;\n // 虾米返回的结构(根据提供的数据,类似于网易云的结构)\n const result = root.data?.result || root.result || root;\n const songs = result.songs || (Array.isArray(root) ? root : []);\n \n return {\n tracks: songs.map((item: any) => ({\n id: item.id?.toString() || '',\n name: item.name || 'Unknown',\n artist: Array.isArray(item.ar) \n ? item.ar.map((a: any) => a.name).join(', ') \n : (item.artist || 'Unknown Artist'),\n album: item.al?.name || item.album || '',\n pic: item.al?.picUrl || item.pic || '',\n url: item.url,\n lrc: item.lrc,\n source: 'xiami',\n // 这里的逻辑参考提供的数据结构\n isVip: item.fee === 1 || item.fee === 8,\n playable: item.copyright !== 0,\n })),\n total: result.songCount || songs.length,\n };\n },\n\n parseGetSongUrl(data: any): any {\n const root = typeof data === 'string' ? JSON.parse(data) : data;\n // 兼容多种可能的包装结构\n const item = root.data?.[0] || root.data || root[0] || root;\n return item.url || null;\n },\n\n parseGetLyric(data: any): any {\n const root = typeof data === 'string' ? JSON.parse(data) : data;\n return root.lyric || root.lrc || root.data?.lyric || root.data || '';\n }\n};\n\n","import useSWR from 'swr';\nimport { useState, useCallback, useMemo } from 'react';\nimport { MusicTrack, SearchOptions, SearchResult, MusicApiResponse } from '../types';\nimport { DEFAULT_MUSIC_SOURCE } from '../constants';\nimport { \n kugouAdapter, \n neteaseAdapter, \n tencentAdapter, \n xiamiAdapter,\n MusicSourceAdapter \n} from '../adapters';\n\nconst fetcher = (url: string) => fetch(url).then(res => res.json());\n\nconst ADAPTERS: Record<string, MusicSourceAdapter> = {\n kugou: kugouAdapter,\n netease: neteaseAdapter,\n tencent: tencentAdapter,\n xiami: xiamiAdapter,\n};\n\nexport function useMusic() {\n const [searchOptions, setSearchOptions] = useState<SearchOptions | null>(null);\n\n // 搜索歌曲\n const { data: rawData, error: searchError, isLoading: isSearching } = useSWR<MusicApiResponse<any>>(\n searchOptions ? `/api/music/search?keyword=${encodeURIComponent(searchOptions.keyword)}&source=${searchOptions.source || DEFAULT_MUSIC_SOURCE}&limit=${searchOptions.limit || 20}&offset=${searchOptions.offset || 0}${searchOptions.miku ? '&miku=true' : ''}` : null,\n fetcher\n );\n\n const searchResult = useMemo(() => {\n if (!rawData?.data || !searchOptions) return undefined;\n const adapter = ADAPTERS[searchOptions.source || DEFAULT_MUSIC_SOURCE];\n if (adapter) {\n return adapter.parseSearchResult(rawData.data);\n }\n return undefined;\n }, [rawData, searchOptions]);\n\n const search = useCallback((options: SearchOptions) => {\n setSearchOptions(options);\n }, []);\n\n // 获取播放链接\n const getSongUrl = useCallback(async (id: string, source: string = DEFAULT_MUSIC_SOURCE): Promise<string | undefined> => {\n try {\n const res = await fetch(`/api/music/url?id=${id}&source=${source}`);\n const json: MusicApiResponse<any> = await res.json();\n const adapter = ADAPTERS[source];\n console.log('json2', json.data,source,adapter);\n if (adapter && json.data) {\n console.log('getSongUrl2', json.data);\n return adapter.parseGetSongUrl(json.data) || undefined;\n }\n return json.data?.url;\n } catch (err) {\n console.error('[Music] Failed to get song URL:', err);\n return undefined;\n }\n }, []);\n\n // 获取歌词\n const getLyric = useCallback(async (id: string, source: string = DEFAULT_MUSIC_SOURCE): Promise<string | undefined> => {\n try {\n const res = await fetch(`/api/music/lyric?id=${id}&source=${source}`);\n const json: MusicApiResponse<any> = await res.json();\n const adapter = ADAPTERS[source];\n if (adapter && json.data) {\n return adapter.parseGetLyric(json.data);\n }\n return json.data?.lyric;\n } catch (err) {\n console.error('[Music] Failed to get lyric:', err);\n return undefined;\n }\n }, []);\n\n return {\n search,\n searchResult,\n isSearching,\n searchError,\n getSongUrl,\n getLyric,\n };\n}\n\n"]}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
|
|
5
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
|
+
|
|
7
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
8
|
+
|
|
9
|
+
// src/components/SearchBox.tsx
|
|
10
|
+
var SearchBox = ({
|
|
11
|
+
searchQuery,
|
|
12
|
+
onSearchChange,
|
|
13
|
+
placeholder = "\u641C\u7D22\u5B9E\u9A8C\u9879\u76EE\u7684\u6807\u9898\u3001\u63CF\u8FF0\u6216\u6807\u7B7E...",
|
|
14
|
+
size = "large"
|
|
15
|
+
}) => {
|
|
16
|
+
const getSizeStyles = () => {
|
|
17
|
+
switch (size) {
|
|
18
|
+
case "small":
|
|
19
|
+
return {
|
|
20
|
+
container: "h-10",
|
|
21
|
+
input: "pl-10 pr-10 text-sm",
|
|
22
|
+
icon: "w-4 h-4",
|
|
23
|
+
iconPosition: "left-3",
|
|
24
|
+
clearButton: "right-2 w-6 h-6",
|
|
25
|
+
clearIcon: "w-3 h-3"
|
|
26
|
+
};
|
|
27
|
+
case "medium":
|
|
28
|
+
return {
|
|
29
|
+
container: "h-12",
|
|
30
|
+
input: "pl-12 pr-12 text-base",
|
|
31
|
+
icon: "w-5 h-5",
|
|
32
|
+
iconPosition: "left-3",
|
|
33
|
+
clearButton: "right-3 w-7 h-7",
|
|
34
|
+
clearIcon: "w-4 h-4"
|
|
35
|
+
};
|
|
36
|
+
case "large":
|
|
37
|
+
default:
|
|
38
|
+
return {
|
|
39
|
+
container: "h-16",
|
|
40
|
+
input: "pl-6 pr-16 text-lg",
|
|
41
|
+
icon: "w-6 h-6",
|
|
42
|
+
iconPosition: "left-6",
|
|
43
|
+
clearButton: "right-4 w-8 h-8",
|
|
44
|
+
clearIcon: "w-4 h-4"
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const styles = getSizeStyles();
|
|
49
|
+
const isLarge = size === "large";
|
|
50
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: "relative group w-full" }, /* @__PURE__ */ React__default.default.createElement(
|
|
51
|
+
"input",
|
|
52
|
+
{
|
|
53
|
+
type: "text",
|
|
54
|
+
placeholder,
|
|
55
|
+
value: searchQuery,
|
|
56
|
+
onChange: (e) => onSearchChange(e.target.value),
|
|
57
|
+
className: `
|
|
58
|
+
w-full ${styles.container} ${styles.input}
|
|
59
|
+
${isLarge ? "border-2 border-gray-200 rounded-2xl shadow-lg" : "border border-gray-300 rounded-lg shadow-sm"}
|
|
60
|
+
bg-white
|
|
61
|
+
focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500
|
|
62
|
+
hover:border-gray-400 ${isLarge ? "hover:shadow-xl" : "hover:shadow-md"}
|
|
63
|
+
transition-all duration-300 ease-out
|
|
64
|
+
text-gray-800 placeholder-gray-500
|
|
65
|
+
${isLarge ? "font-medium" : "font-normal"}
|
|
66
|
+
`
|
|
67
|
+
}
|
|
68
|
+
), searchQuery && /* @__PURE__ */ React__default.default.createElement(
|
|
69
|
+
"button",
|
|
70
|
+
{
|
|
71
|
+
onClick: () => onSearchChange(""),
|
|
72
|
+
className: `
|
|
73
|
+
absolute top-1/2 ${styles.clearButton} transform -translate-y-1/2
|
|
74
|
+
z-10 group/clear
|
|
75
|
+
`
|
|
76
|
+
},
|
|
77
|
+
/* @__PURE__ */ React__default.default.createElement("div", { className: `
|
|
78
|
+
${styles.clearButton} flex items-center justify-center
|
|
79
|
+
rounded-full
|
|
80
|
+
bg-gray-100 hover:bg-gray-200
|
|
81
|
+
transition-all duration-200
|
|
82
|
+
group-hover/clear:scale-105
|
|
83
|
+
` }, /* @__PURE__ */ React__default.default.createElement(
|
|
84
|
+
"svg",
|
|
85
|
+
{
|
|
86
|
+
className: `${styles.clearIcon} text-gray-500 group-hover/clear:text-gray-700`,
|
|
87
|
+
fill: "none",
|
|
88
|
+
stroke: "currentColor",
|
|
89
|
+
viewBox: "0 0 24 24"
|
|
90
|
+
},
|
|
91
|
+
/* @__PURE__ */ React__default.default.createElement(
|
|
92
|
+
"path",
|
|
93
|
+
{
|
|
94
|
+
strokeLinecap: "round",
|
|
95
|
+
strokeLinejoin: "round",
|
|
96
|
+
strokeWidth: 2,
|
|
97
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
))
|
|
101
|
+
));
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
exports.SearchBox = SearchBox;
|
|
105
|
+
//# sourceMappingURL=chunk-IEA55H3G.js.map
|
|
106
|
+
//# sourceMappingURL=chunk-IEA55H3G.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/SearchBox.tsx"],"names":["React"],"mappings":"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","file":"chunk-IEA55H3G.js","sourcesContent":["import React from 'react';\n\ninterface SearchBoxProps {\n searchQuery: string;\n onSearchChange: (query: string) => void;\n placeholder?: string;\n size?: 'small' | 'medium' | 'large';\n}\n\nexport const SearchBox: React.FC<SearchBoxProps> = ({ \n searchQuery, \n onSearchChange, \n placeholder = \"搜索实验项目的标题、描述或标签...\",\n size = 'large'\n}) => {\n // 根据尺寸获取样式\n const getSizeStyles = () => {\n switch (size) {\n case 'small':\n return {\n container: 'h-10',\n input: 'pl-10 pr-10 text-sm',\n icon: 'w-4 h-4',\n iconPosition: 'left-3',\n clearButton: 'right-2 w-6 h-6',\n clearIcon: 'w-3 h-3'\n };\n case 'medium':\n return {\n container: 'h-12',\n input: 'pl-12 pr-12 text-base',\n icon: 'w-5 h-5',\n iconPosition: 'left-3',\n clearButton: 'right-3 w-7 h-7',\n clearIcon: 'w-4 h-4'\n };\n case 'large':\n default:\n return {\n container: 'h-16',\n input: 'pl-6 pr-16 text-lg',\n icon: 'w-6 h-6',\n iconPosition: 'left-6',\n clearButton: 'right-4 w-8 h-8',\n clearIcon: 'w-4 h-4'\n };\n }\n };\n\n const styles = getSizeStyles();\n const isLarge = size === 'large';\n\n return (\n <div className=\"relative group w-full\">\n {/* 搜索输入框 */}\n <input\n type=\"text\"\n placeholder={placeholder}\n value={searchQuery}\n onChange={(e) => onSearchChange(e.target.value)}\n className={`\n w-full ${styles.container} ${styles.input}\n ${isLarge ? 'border-2 border-gray-200 rounded-2xl shadow-lg' : 'border border-gray-300 rounded-lg shadow-sm'}\n bg-white \n focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 \n hover:border-gray-400 ${isLarge ? 'hover:shadow-xl' : 'hover:shadow-md'}\n transition-all duration-300 ease-out\n text-gray-800 placeholder-gray-500\n ${isLarge ? 'font-medium' : 'font-normal'}\n `}\n />\n\n {/* 清除按钮 */}\n {searchQuery && (\n <button\n onClick={() => onSearchChange('')}\n className={`\n absolute top-1/2 ${styles.clearButton} transform -translate-y-1/2\n z-10 group/clear\n `}\n >\n <div className={`\n ${styles.clearButton} flex items-center justify-center\n rounded-full \n bg-gray-100 hover:bg-gray-200 \n transition-all duration-200 \n group-hover/clear:scale-105\n `}>\n <svg \n className={`${styles.clearIcon} text-gray-500 group-hover/clear:text-gray-700`}\n fill=\"none\" \n stroke=\"currentColor\" \n viewBox=\"0 0 24 24\"\n >\n <path \n strokeLinecap=\"round\" \n strokeLinejoin=\"round\" \n strokeWidth={2} \n d=\"M6 18L18 6M6 6l12 12\" \n />\n </svg>\n </div>\n </button>\n )}\n </div>\n );\n}"]}
|
|
@@ -269,5 +269,5 @@ var DrizzleAuthService = class {
|
|
|
269
269
|
};
|
|
270
270
|
|
|
271
271
|
export { DrizzleAuthService, generateToken, getTokenFromRequest, hashPassword, verifyJwtToken, verifyPassword };
|
|
272
|
-
//# sourceMappingURL=chunk-
|
|
273
|
-
//# sourceMappingURL=chunk-
|
|
272
|
+
//# sourceMappingURL=chunk-OCR5DS4C.mjs.map
|
|
273
|
+
//# sourceMappingURL=chunk-OCR5DS4C.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/auth/services/password-utils.ts","../src/auth/services/token-utils.ts","../src/auth/services/drizzle-auth-service.ts"],"names":[],"mappings":"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","file":"chunk-OCR5DS4C.mjs","sourcesContent":["/**\n * Auth Services - Password Utilities\n * 密码哈希相关工具函数\n */\n\nimport bcrypt from 'bcryptjs';\n\n/**\n * 哈希密码\n */\nexport async function hashPassword(password: string, saltRounds: number = 12): Promise<string> {\n return bcrypt.hash(password, saltRounds);\n}\n\n/**\n * 验证密码\n */\nexport async function verifyPassword(password: string, hashedPassword: string): Promise<boolean> {\n return bcrypt.compare(password, hashedPassword);\n}\n\n","/**\n * Auth Services - Token Utilities\n * Token 相关工具函数\n */\n\nimport jwt from 'jsonwebtoken';\nimport type { UserRole } from '../schema/enums';\n\n/**\n * JWT Payload\n */\nexport interface JwtPayload {\n userId: string;\n email: string;\n username?: string;\n role: UserRole;\n iat?: number;\n exp?: number;\n}\n\n/**\n * 生成 JWT Token\n */\nexport function generateToken(\n payload: Omit<JwtPayload, 'iat' | 'exp'>,\n secret: string,\n expiresIn: string | number = '7d'\n): string {\n return jwt.sign(payload, secret, { expiresIn } as jwt.SignOptions);\n}\n\n/**\n * 验证 JWT Token\n */\nexport function verifyJwtToken(token: string, secret: string): JwtPayload {\n return jwt.verify(token, secret) as JwtPayload;\n}\n\n/**\n * 从请求中获取 Token\n * 优先从 Cookie 读取(Web),兼容 Authorization Header(Mobile/API)\n */\nexport function getTokenFromRequest(request: Request): string | null {\n // 🔐 优先从 httpOnly Cookie 读取(Web 管理后台,更安全)\n const cookieHeader = request.headers.get('Cookie');\n if (cookieHeader) {\n // 匹配 auth_token\n const match = cookieHeader.match(/auth_token=([^;]+)/);\n if (match && match[1]) {\n return match[1];\n }\n }\n\n // 🔄 兼容从 Authorization Header 读取(移动端、小程序、API 调用)\n const authHeader = request.headers.get('Authorization');\n if (authHeader && authHeader.startsWith('Bearer ')) {\n const token = authHeader.substring(7);\n return token || null;\n }\n\n return null;\n}\n\n","/**\n * Auth Services - Drizzle Auth Service\n * 基于 Drizzle ORM 的认证服务\n */\n\nimport { eq, and, gt } from 'drizzle-orm';\nimport { randomBytes } from 'crypto';\nimport { user, session } from '../schema';\nimport { hashPassword, verifyPassword } from './password-utils';\nimport { generateToken, verifyJwtToken } from './token-utils';\nimport type {\n AuthServiceConfig,\n AuthResult,\n VerifyResult,\n UserInfo,\n SessionInfo,\n} from './types';\nimport type { UserRole } from '../schema/enums';\n\n/**\n * Drizzle 认证服务类\n *\n * @example\n * ```typescript\n * import { DrizzleAuthService } from '@qhr123/sa2kit/auth/services';\n * import { db } from './db';\n *\n * const authService = new DrizzleAuthService({\n * db,\n * jwtSecret: process.env.JWT_SECRET!,\n * jwtExpiresIn: '7d',\n * });\n *\n * // 用户注册\n * const result = await authService.signUp('user@example.com', 'password123', 'username');\n *\n * // 用户登录\n * const loginResult = await authService.signIn('user@example.com', 'password123');\n * ```\n */\nexport class DrizzleAuthService {\n private config: Required<AuthServiceConfig>;\n\n constructor(config: AuthServiceConfig) {\n // 设置默认值\n this.config = {\n db: config.db,\n jwtSecret: config.jwtSecret,\n jwtExpiresIn: config.jwtExpiresIn || '7d',\n saltRounds: config.saltRounds || 12,\n checkSecretStrength: config.checkSecretStrength !== false,\n };\n\n // 验证配置\n this.validateConfig();\n }\n\n /**\n * 验证配置\n */\n private validateConfig(): void {\n if (!this.config.jwtSecret) {\n throw new Error(\n 'JWT_SECRET is required. Please provide jwtSecret in config. ' +\n \"You can generate a secure secret with: node -e \\\"console.log(require('crypto').randomBytes(64).toString('hex'))\\\"\"\n );\n }\n\n // 生产环境检查密钥强度\n if (\n this.config.checkSecretStrength &&\n process.env.NODE_ENV === 'production' &&\n this.config.jwtSecret.length < 32\n ) {\n throw new Error(\n `JWT_SECRET is too short (${this.config.jwtSecret.length} chars, minimum 32 required in production)`\n );\n }\n }\n\n /**\n * 用户注册\n */\n async signUp(\n email: string,\n password: string,\n username?: string,\n role: UserRole = 'USER'\n ): Promise<AuthResult> {\n try {\n // 检查用户是否已存在\n const existingUser = await this.config.db\n .select()\n .from(user)\n .where(eq(user.email, email))\n .limit(1);\n\n if (existingUser.length > 0) {\n throw new Error('用户已存在');\n }\n\n // 哈希密码\n const hashedPassword = await hashPassword(password, this.config.saltRounds);\n\n // 创建用户\n const [newUser] = await this.config.db\n .insert(user)\n .values({\n id: randomBytes(16).toString('hex'),\n email,\n password: hashedPassword,\n username: username || email.split('@')[0],\n role,\n emailVerified: false,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n })\n .returning();\n\n // 生成 JWT token\n const token = generateToken(\n {\n userId: newUser.id,\n email: newUser.email,\n role: newUser.role as UserRole,\n },\n this.config.jwtSecret,\n this.config.jwtExpiresIn\n );\n\n // 创建会话\n await this.createSession(newUser.id, token);\n\n return {\n user: {\n id: newUser.id,\n email: newUser.email,\n username: newUser.username,\n role: newUser.role as UserRole,\n },\n token,\n };\n } catch (error) {\n throw error;\n }\n }\n\n /**\n * 用户登录\n */\n async signIn(email: string, password: string): Promise<AuthResult> {\n try {\n // 查找用户\n const [foundUser] = await this.config.db\n .select()\n .from(user)\n .where(eq(user.email, email))\n .limit(1);\n\n if (!foundUser) {\n throw new Error('邮箱或密码错误');\n }\n\n // 验证密码\n if (!foundUser.password) {\n throw new Error('用户密码未设置');\n }\n\n const isPasswordValid = await verifyPassword(password, foundUser.password);\n if (!isPasswordValid) {\n throw new Error('邮箱或密码错误');\n }\n\n // 生成 JWT token\n const token = generateToken(\n {\n userId: foundUser.id,\n email: foundUser.email,\n role: foundUser.role as UserRole,\n },\n this.config.jwtSecret,\n this.config.jwtExpiresIn\n );\n\n // 创建会话\n await this.createSession(foundUser.id, token);\n\n return {\n user: {\n id: foundUser.id,\n email: foundUser.email,\n username: foundUser.username,\n role: foundUser.role as UserRole,\n },\n token,\n };\n } catch (error) {\n throw error;\n }\n }\n\n /**\n * 验证 Token\n */\n async verifyToken(token: string): Promise<VerifyResult> {\n try {\n // 验证 JWT\n const decoded = verifyJwtToken(token, this.config.jwtSecret);\n\n // 检查会话是否存在且未过期\n const [foundSession] = await this.config.db\n .select()\n .from(session)\n .where(\n and(eq(session.token, token), gt(session.expiresAt, new Date().toISOString()))\n )\n .limit(1);\n\n if (!foundSession) {\n throw new Error('会话无效或已过期');\n }\n\n // 获取用户信息\n const [foundUser] = await this.config.db\n .select()\n .from(user)\n .where(eq(user.id, decoded.userId))\n .limit(1);\n\n if (!foundUser) {\n throw new Error('用户不存在');\n }\n\n return {\n user: {\n id: foundUser.id,\n email: foundUser.email,\n username: foundUser.username,\n role: foundUser.role as UserRole,\n },\n session: foundSession as SessionInfo,\n };\n } catch (error) {\n throw error;\n }\n }\n\n /**\n * 创建会话\n */\n async createSession(\n userId: string,\n token: string,\n ipAddress?: string,\n userAgent?: string\n ): Promise<void> {\n const expiresAt = new Date();\n expiresAt.setDate(expiresAt.getDate() + 7); // 7天后过期\n\n await this.config.db.insert(session).values({\n id: randomBytes(16).toString('hex'),\n userId,\n token,\n expiresAt: expiresAt.toISOString(),\n ipAddress,\n userAgent,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n });\n }\n\n /**\n * 删除会话(登出)\n */\n async signOut(token: string): Promise<{ success: boolean }> {\n try {\n await this.config.db.delete(session).where(eq(session.token, token));\n return { success: true };\n } catch (error) {\n throw error;\n }\n }\n\n /**\n * 获取会话\n */\n async getSession(token: string): Promise<VerifyResult | null> {\n try {\n return await this.verifyToken(token);\n } catch (error) {\n return null;\n }\n }\n\n /**\n * 检查管理员权限\n */\n async requireAdmin(token: string): Promise<VerifyResult> {\n const result = await this.verifyToken(token);\n if (!['ADMIN', 'SUPER_ADMIN'].includes(result.user.role)) {\n throw new Error('需要管理员权限');\n }\n return result;\n }\n\n /**\n * 检查超级管理员权限\n */\n async requireSuperAdmin(token: string): Promise<VerifyResult> {\n const result = await this.verifyToken(token);\n if (result.user.role !== 'SUPER_ADMIN') {\n throw new Error('需要超级管理员权限');\n }\n return result;\n }\n\n /**\n * 通过用户 ID 获取用户信息\n */\n async getUserById(userId: string): Promise<UserInfo | null> {\n try {\n const [foundUser] = await this.config.db\n .select()\n .from(user)\n .where(eq(user.id, userId))\n .limit(1);\n\n if (!foundUser) {\n return null;\n }\n\n return {\n id: foundUser.id,\n email: foundUser.email,\n username: foundUser.username,\n role: foundUser.role as UserRole,\n };\n } catch (error) {\n return null;\n }\n }\n\n /**\n * 通过邮箱获取用户信息\n */\n async getUserByEmail(email: string): Promise<UserInfo | null> {\n try {\n const [foundUser] = await this.config.db\n .select()\n .from(user)\n .where(eq(user.email, email))\n .limit(1);\n\n if (!foundUser) {\n return null;\n }\n\n return {\n id: foundUser.id,\n email: foundUser.email,\n username: foundUser.username,\n role: foundUser.role as UserRole,\n };\n } catch (error) {\n return null;\n }\n }\n}\n\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getTokenFromRequest } from './chunk-
|
|
1
|
+
import { getTokenFromRequest } from './chunk-OCR5DS4C.mjs';
|
|
2
2
|
|
|
3
3
|
// src/auth/routes/login.ts
|
|
4
4
|
function addCorsHeaders(response, config, request) {
|
|
@@ -556,5 +556,5 @@ function createAnalyticsAdapter(analyticsService, options) {
|
|
|
556
556
|
}
|
|
557
557
|
|
|
558
558
|
export { createAnalyticsAdapter, createDefaultBaseConfig, createDefaultLoginConfig, createDefaultRegisterConfig, createLoginHandler, createLoginOptionsHandler, createLogoutHandler, createLogoutOptionsHandler, createMeHandler, createMeOptionsHandler, createRegisterHandler, createRegisterOptionsHandler };
|
|
559
|
-
//# sourceMappingURL=chunk-
|
|
560
|
-
//# sourceMappingURL=chunk-
|
|
559
|
+
//# sourceMappingURL=chunk-QAT2RWAO.mjs.map
|
|
560
|
+
//# sourceMappingURL=chunk-QAT2RWAO.mjs.map
|