@tiny-codes/react-easy 1.4.11 → 1.4.13

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.
@@ -34,6 +34,12 @@ var AudioPlayer = class {
34
34
  this.audioContext = null;
35
35
  this.gainNode = null;
36
36
  this.sourceNode = null;
37
+ this.mediaSource = null;
38
+ this.sourceBuffer = null;
39
+ this.chunkQueue = [];
40
+ this.appending = false;
41
+ this.streamEnded = false;
42
+ this.stopLoadingSource = false;
37
43
  /**
38
44
  * - **EN:** Add audio event listener
39
45
  * - **CN:** 添加音频事件监听器
@@ -74,8 +80,7 @@ var AudioPlayer = class {
74
80
  * - **CN:** 检查音频是否正在播放
75
81
  */
76
82
  get isPlaying() {
77
- var _a;
78
- return ((_a = this.audioContext) == null ? void 0 : _a.state) === "running";
83
+ return !this.audio.paused && !this.audio.ended;
79
84
  }
80
85
  /**
81
86
  * - **EN:** Get current playback time (seconds)
@@ -189,10 +194,15 @@ var AudioPlayer = class {
189
194
  async setAudioSource(source) {
190
195
  this.audio.pause();
191
196
  this.audio.src = "";
197
+ this.disposeMediaSourceInternal();
192
198
  if (typeof source === "string") {
193
199
  this.audio.src = source;
200
+ return {
201
+ stopLoading: () => {
202
+ }
203
+ };
194
204
  } else {
195
- await this.handleStreamSource(source);
205
+ return await this.handleStreamSource(source);
196
206
  }
197
207
  }
198
208
  /**
@@ -244,41 +254,45 @@ var AudioPlayer = class {
244
254
  this.sourceNode = null;
245
255
  this.gainNode = null;
246
256
  }
247
- /** Process streaming data source */
257
+ disposeMediaSourceInternal() {
258
+ this.mediaSource = null;
259
+ this.sourceBuffer = null;
260
+ this.chunkQueue = [];
261
+ this.appending = false;
262
+ this.streamEnded = false;
263
+ }
264
+ /** Process streaming data source /ArrayBuffer/Uint8Array/Blob */
248
265
  async handleStreamSource(source) {
266
+ var _a, _b, _c;
267
+ const result = {
268
+ stopLoading: () => {
269
+ }
270
+ };
249
271
  if (!source)
250
- return;
272
+ return result;
251
273
  try {
252
- let blob;
253
274
  if (source instanceof Blob) {
254
- blob = source;
275
+ const url = URL.createObjectURL(source);
276
+ this.audio.src = url;
277
+ return result;
255
278
  } else if (source instanceof ArrayBuffer || source instanceof Uint8Array) {
256
- blob = new Blob([source]);
279
+ const blob = source instanceof Uint8Array ? new Blob([source]) : new Blob([new Uint8Array(source)]);
280
+ const url = URL.createObjectURL(blob);
281
+ this.audio.src = url;
282
+ this.audio.onloadeddata = () => URL.revokeObjectURL(url);
283
+ return result;
257
284
  } else {
258
- const stream = new ReadableStream({
259
- async pull(controller) {
260
- try {
261
- const { done, value } = await source.read();
262
- if (done) {
263
- controller.close();
264
- } else {
265
- controller.enqueue(value);
266
- }
267
- } catch (err) {
268
- controller.error(err);
269
- }
270
- }
271
- });
272
- const response = new Response(stream);
273
- blob = await response.blob();
285
+ const mime = ((_a = this.options) == null ? void 0 : _a.mimeType) || "audio/mpeg";
286
+ result.stopLoading = () => {
287
+ this.stopLoadingSource = true;
288
+ };
289
+ await this.initMediaSourceForReader(source, mime);
290
+ return result;
274
291
  }
275
- const url = URL.createObjectURL(blob);
276
- this.audio.src = url;
277
- this.audio.onload = () => {
278
- URL.revokeObjectURL(url);
279
- };
280
292
  } catch (error) {
281
293
  console.error("Error processing audio stream:", error);
294
+ (_c = (_b = this.options) == null ? void 0 : _b.onError) == null ? void 0 : _c.call(_b, error);
295
+ throw error;
282
296
  }
283
297
  }
284
298
  /** Initialize Web Audio API for better volume control */
@@ -300,6 +314,110 @@ var AudioPlayer = class {
300
314
  this.audio.volume = this._volume;
301
315
  }
302
316
  }
317
+ /** Initialize MediaSource and push reader chunks into SourceBuffer */
318
+ async initMediaSourceForReader(reader, mime) {
319
+ if (typeof MediaSource === "undefined") {
320
+ console.warn("MediaSource is not supported, falling back to one-time buffering.");
321
+ await this.fallbackReaderToBlob(reader);
322
+ return;
323
+ }
324
+ if (typeof MediaSource !== "undefined" && !MediaSource.isTypeSupported(mime)) {
325
+ console.warn("MIME type is not supported, falling back to one-time buffering.");
326
+ await this.fallbackReaderToBlob(reader);
327
+ return;
328
+ }
329
+ this.mediaSource = new MediaSource();
330
+ const objectURL = URL.createObjectURL(this.mediaSource);
331
+ this.audio.src = objectURL;
332
+ this.stopLoadingSource = false;
333
+ this.mediaSource.addEventListener("sourceopen", () => {
334
+ if (!this.mediaSource)
335
+ return;
336
+ this.sourceBuffer = this.mediaSource.addSourceBuffer(mime);
337
+ this.sourceBuffer.addEventListener("updateend", () => {
338
+ this.appending = false;
339
+ this.tryAppendNext();
340
+ this.finalizeMediaSourceIfPossible();
341
+ });
342
+ this.readLoop(reader);
343
+ });
344
+ }
345
+ /** Loop to read data from the reader */
346
+ async readLoop(reader) {
347
+ var _a, _b;
348
+ try {
349
+ if (this.audio.paused) {
350
+ void this.play();
351
+ }
352
+ while (true) {
353
+ const { done, value } = await reader.read();
354
+ if (done || this.stopLoadingSource) {
355
+ this.streamEnded = true;
356
+ break;
357
+ }
358
+ if (value && value.byteLength) {
359
+ this.chunkQueue.push(value);
360
+ this.tryAppendNext();
361
+ }
362
+ await new Promise((resolve) => setTimeout(resolve, 100));
363
+ }
364
+ this.finalizeMediaSourceIfPossible();
365
+ } catch (e) {
366
+ console.error("Error reading stream:", e);
367
+ (_b = (_a = this.options) == null ? void 0 : _a.onError) == null ? void 0 : _b.call(_a, e);
368
+ }
369
+ }
370
+ /** Try to append the next chunk from the queue to the SourceBuffer */
371
+ tryAppendNext() {
372
+ var _a, _b;
373
+ if (!this.sourceBuffer || this.appending)
374
+ return;
375
+ if (!this.chunkQueue.length)
376
+ return;
377
+ const chunk = this.chunkQueue.shift();
378
+ this.appending = true;
379
+ try {
380
+ this.sourceBuffer.appendBuffer(chunk);
381
+ } catch (e) {
382
+ console.error("Error appending buffer:", e);
383
+ this.appending = false;
384
+ (_b = (_a = this.options) == null ? void 0 : _a.onError) == null ? void 0 : _b.call(_a, e);
385
+ this.finalizeMediaSourceIfPossible();
386
+ }
387
+ }
388
+ /** Finalize MediaSource if possible (stream ended, no pending chunks, and not updating) */
389
+ finalizeMediaSourceIfPossible(receivedAnyChunk = true) {
390
+ var _a;
391
+ if (this.mediaSource && this.mediaSource.readyState === "open" && this.streamEnded && !((_a = this.sourceBuffer) == null ? void 0 : _a.updating) && this.chunkQueue.length === 0) {
392
+ try {
393
+ this.mediaSource.endOfStream();
394
+ } catch (e) {
395
+ console.warn("endOfStream error:", e);
396
+ }
397
+ }
398
+ }
399
+ /** Fallback to one-time Blob synthesis when streaming is not supported */
400
+ async fallbackReaderToBlob(reader) {
401
+ const stream = new ReadableStream({
402
+ async pull(controller) {
403
+ try {
404
+ const { done, value } = await reader.read();
405
+ if (done) {
406
+ controller.close();
407
+ } else {
408
+ controller.enqueue(value);
409
+ }
410
+ } catch (err) {
411
+ controller.error(err);
412
+ }
413
+ }
414
+ });
415
+ const response = new Response(stream);
416
+ const blob = await response.blob();
417
+ const url = URL.createObjectURL(blob);
418
+ this.audio.src = url;
419
+ this.audio.onloadeddata = () => URL.revokeObjectURL(url);
420
+ }
303
421
  };
304
422
  var AudioPlayer_default = AudioPlayer;
305
423
  //# sourceMappingURL=AudioPlayer.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/AudioPlayer.ts"],
4
- "sourcesContent": ["export type AudioSource = string | ReadableStreamDefaultReader<Uint8Array> | ArrayBuffer | Uint8Array | Blob;\n\nexport interface AudioPlayerInit {\n /**\n * - **EN:** Audio source (URL or streaming data)\n * - **CN:** 音频源(URL或流数据)\n */\n source?: AudioSource | (() => AudioSource | Promise<AudioSource>);\n /**\n * - **EN:** Initial volume level (0-1). Default is `0.5`\n * - **CN:** 初始音量级别(0-1)。默认值为`0.5`\n */\n volume?: number;\n /**\n * - **EN:** Callback when audio starts playing\n * - **CN:** 音频开始播放时的回调\n */\n onPlay?: () => void;\n /**\n * - **EN:** Callback when audio is paused\n * - **CN:** 音频暂停时的回调\n */\n onPause?: () => void;\n /**\n * - **EN:** Callback when audio is stopped\n * - **CN:** 音频停止时的回调\n */\n onStop?: () => void;\n\n /**\n * - **EN:** Callback when audio playback ends\n * - **CN:** 音频播放结束时的回调\n */\n onPlayEnd?: () => void;\n /**\n * - **EN:** Callback when an error occurs\n * - **CN:** 发生错误时的回调\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onError?: (error: any) => void;\n}\n\n/**\n * - **EN:** An audio player class that supports URL or streaming data input\n * - **CN:** 一个音频播放器类,支持URL或流数据输入\n */\nclass AudioPlayer {\n private audio: HTMLAudioElement;\n private _volume: number;\n private audioContext: AudioContext | null = null;\n private gainNode: GainNode | null = null;\n private sourceNode: MediaElementAudioSourceNode | null = null;\n private options: AudioPlayerInit | undefined;\n private onPlayEnd: () => void;\n\n /**\n * - **EN:** Creates an audio player instance\n * - **CN:** 创建音频播放器实例\n *\n * @param source - can be a URL string or ReadableStreamDefaultReader |\n * 可以是URL字符串或ReadableStreamDefaultReader\n */\n constructor(options?: AudioPlayerInit) {\n const { source, volume } = options || {};\n this.options = options;\n this.audio = new Audio();\n this._volume = volume != null ? Math.min(1.0, Math.max(0, volume)) : 0.5; // Default volume 50%\n this.audio.volume = this._volume;\n if (typeof source === 'function') {\n const result = source();\n if (typeof result === 'object' && 'then' in result && typeof result.then === 'function') {\n result.then((data) => this.setAudioSource(data));\n } else {\n this.setAudioSource(result as AudioSource);\n }\n } else {\n this.setAudioSource(source);\n }\n this.onPlayEnd = () => {\n this.options?.onPlayEnd?.();\n };\n this.addEventListener('ended', this.onPlayEnd);\n }\n\n /**\n * - **EN:** Check if audio is currently playing\n * - **CN:** 检查音频是否正在播放\n */\n public get isPlaying() {\n return this.audioContext?.state === 'running';\n }\n /**\n * - **EN:** Get current playback time (seconds)\n * - **CN:** 获取当前播放时间(秒)\n */\n get currentTime(): number {\n return this.audio.currentTime;\n }\n /**\n * - **EN:** Get total audio duration (seconds)\n * - **CN:** 获取音频总时长(秒)\n */\n get duration(): number {\n return this.audio.duration;\n }\n /**\n * - **EN:** Get current volume value (0-1)\n * - **CN:** 获取当前音量值(0-1)\n */\n get volume(): number {\n return this._volume;\n }\n\n /**\n * - **EN:** Play audio. If previously paused, will resume from the pause position\n * - **CN:** 播放音频 如果之前暂停过,将从暂停位置继续播放\n */\n async play(): Promise<void> {\n if (!this.audioContext) {\n this.initAudioContext();\n }\n\n if (this.audioContext?.state === 'suspended') {\n await this.audioContext.resume();\n }\n\n try {\n await this.audio.play();\n this.options?.onPlay?.();\n } catch (error) {\n console.error('Error playing audio:', error);\n this.options?.onError?.(error);\n }\n }\n\n /**\n * - **EN:** Seek forward by a certain number of seconds\n * - **CN:** 向前跳转一定秒数\n *\n * @param seconds - number of seconds to seek forward | 要向前跳转的秒数\n */\n seekForward(seconds: number) {\n if (seconds < 0) {\n return;\n }\n if (!isNaN(this.audio.duration)) {\n this.audio.currentTime = Math.min(this.audio.currentTime + seconds, this.audio.duration);\n } else {\n this.audio.currentTime += seconds;\n }\n }\n /**\n * - **EN:** Seek backward by a certain number of seconds\n * - **CN:** 向后跳转一定秒数\n *\n * @param seconds - number of seconds to seek backward | 要向后跳转的秒数\n */\n seekBackward(seconds: number) {\n if (seconds < 0) {\n return;\n }\n this.audio.currentTime = Math.max(this.audio.currentTime - seconds, 0);\n }\n /**\n * - **EN:** Set current playback time (in seconds)\n * - **CN:** 设置当前播放时间(以秒为单位)\n *\n * @param time - time in seconds | 时间(秒)\n */\n seek(time: number) {\n // Ensure time is not less than 0\n const newTime = Math.max(0, time);\n // Ensure time is not greater than duration (if known)\n if (!isNaN(this.audio.duration)) {\n this.audio.currentTime = Math.min(newTime, this.audio.duration);\n } else {\n this.audio.currentTime = newTime;\n }\n }\n\n /**\n * - **EN:** Pause audio playback. When played again, will continue from current position\n * - **CN:** 暂停音频播放 再次播放时将从当前位置继续\n */\n pause(): void {\n this.audio.pause();\n this.options?.onPause?.();\n }\n\n /**\n * - **EN:** Stop audio playback. Progress will reset to the beginning\n * - **CN:** 停止音频播放 进度会重置到开始位置\n */\n stop(): void {\n this.audio.pause();\n this.audio.currentTime = 0;\n this.options?.onStop?.();\n }\n\n /**\n * - **EN:** Update audio source\n * - **CN:** 更新音频源\n *\n * @param source - can be a URL `string` or `ReadableStreamDefaultReader` |\n * 可以是URL字符串或`ReadableStreamDefaultReader`\n */\n async setAudioSource(source?: AudioSource) {\n this.audio.pause();\n this.audio.src = '';\n\n if (typeof source === 'string') {\n this.audio.src = source;\n } else {\n await this.handleStreamSource(source);\n }\n }\n\n /**\n * - **EN:** Increase volume (by 10% each time)\n * - **CN:** 增加音量(每次增加10%)\n *\n * @param percent - increase percentage (default 10%) | 增加百分比(默认10%)\n */\n volumeUp(percent = 0.1): void {\n this._volume = Math.min(1.0, this._volume + percent);\n this.updateVolume();\n }\n\n /**\n * - **EN:** Decrease volume (by 10% each time)\n * - **CN:** 降低音量(每次降低10%)\n *\n * @param percent - decrease percentage (default 10%) | 降低百分比(默认10%)\n */\n volumeDown(percent = 0.1): void {\n this._volume = Math.max(0, this._volume - percent);\n this.updateVolume();\n }\n\n /**\n * - **EN:** Set volume to a specific value (0-1)\n * - **CN:** 将音量设置为特定值(0-1)\n *\n * @param value - new volume value (0-1) | 新的音量值(0-1)\n */\n setVolume(value: number): void {\n this._volume = Math.min(1.0, Math.max(0, value));\n this.updateVolume();\n }\n\n /**\n * - **EN:** Add audio event listener\n * - **CN:** 添加音频事件监听器\n */\n addEventListener: HTMLAudioElement['addEventListener'] = (\n event: string,\n listener: EventListenerOrEventListenerObject\n ): void => {\n this.audio.addEventListener(event, listener);\n };\n\n /**\n * - **EN:** Remove audio event listener\n * - **CN:** 移除音频事件监听器\n */\n removeEventListener: HTMLAudioElement['removeEventListener'] = (\n event: string,\n listener: EventListenerOrEventListenerObject\n ): void => {\n this.audio.removeEventListener(event, listener);\n };\n\n /**\n * - **EN:** Release resources\n * - **CN:** 释放资源\n */\n dispose(): void {\n this.audio.pause();\n this.audio.src = '';\n this.removeEventListener('ended', this.onPlayEnd);\n\n if (this.audioContext) {\n try {\n this.audioContext.close();\n } catch (error) {\n console.error('Error closing AudioContext:', error);\n }\n this.audioContext = null;\n }\n\n this.sourceNode = null;\n this.gainNode = null;\n }\n\n /** Process streaming data source */\n private async handleStreamSource(source: Exclude<AudioSource, string> | undefined) {\n if (!source) return;\n try {\n let blob: Blob;\n if (source instanceof Blob) {\n blob = source;\n } else if (source instanceof ArrayBuffer || source instanceof Uint8Array) {\n blob = new Blob([source]);\n } else {\n // Create a new ReadableStream to read data from the reader\n const stream = new ReadableStream({\n async pull(controller) {\n try {\n const { done, value } = await source.read();\n if (done) {\n controller.close();\n } else {\n controller.enqueue(value);\n }\n } catch (err) {\n controller.error(err);\n }\n },\n });\n // Convert stream to Blob and create URL\n const response = new Response(stream);\n blob = await response.blob();\n }\n\n const url = URL.createObjectURL(blob);\n\n this.audio.src = url;\n\n // Release Blob URL after audio loads\n this.audio.onload = () => {\n URL.revokeObjectURL(url);\n };\n } catch (error) {\n console.error('Error processing audio stream:', error);\n }\n }\n\n /** Initialize Web Audio API for better volume control */\n private initAudioContext() {\n if (this.audioContext) return;\n\n this.audioContext = new AudioContext();\n this.sourceNode = this.audioContext.createMediaElementSource(this.audio);\n this.gainNode = this.audioContext.createGain();\n\n this.sourceNode.connect(this.gainNode);\n this.gainNode.connect(this.audioContext.destination);\n\n this.gainNode.gain.value = this._volume;\n }\n\n /** Update audio playback volume */\n private updateVolume(): void {\n if (this.gainNode) {\n this.gainNode.gain.value = this._volume;\n } else {\n this.audio.volume = this._volume;\n }\n }\n}\n\nexport default AudioPlayer;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8CA,IAAM,cAAN,MAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBhB,YAAY,SAA2B;AAbvC,SAAQ,eAAoC;AAC5C,SAAQ,WAA4B;AACpC,SAAQ,aAAiD;AA2MzD;AAAA;AAAA;AAAA;AAAA,4BAAyD,CACvD,OACA,aACS;AACT,WAAK,MAAM,iBAAiB,OAAO,QAAQ;AAAA,IAC7C;AAMA;AAAA;AAAA;AAAA;AAAA,+BAA+D,CAC7D,OACA,aACS;AACT,WAAK,MAAM,oBAAoB,OAAO,QAAQ;AAAA,IAChD;AA/ME,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW,CAAC;AACvC,SAAK,UAAU;AACf,SAAK,QAAQ,IAAI,MAAM;AACvB,SAAK,UAAU,UAAU,OAAO,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI;AACrE,SAAK,MAAM,SAAS,KAAK;AACzB,QAAI,OAAO,WAAW,YAAY;AAChC,YAAM,SAAS,OAAO;AACtB,UAAI,OAAO,WAAW,YAAY,UAAU,UAAU,OAAO,OAAO,SAAS,YAAY;AACvF,eAAO,KAAK,CAAC,SAAS,KAAK,eAAe,IAAI,CAAC;AAAA,MACjD,OAAO;AACL,aAAK,eAAe,MAAqB;AAAA,MAC3C;AAAA,IACF,OAAO;AACL,WAAK,eAAe,MAAM;AAAA,IAC5B;AACA,SAAK,YAAY,MAAM;AA9E3B;AA+EM,uBAAK,YAAL,mBAAc,cAAd;AAAA,IACF;AACA,SAAK,iBAAiB,SAAS,KAAK,SAAS;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAW,YAAY;AAxFzB;AAyFI,aAAO,UAAK,iBAAL,mBAAmB,WAAU;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,cAAsB;AACxB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAAmB;AACrB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAiB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAsB;AArH9B;AAsHI,QAAI,CAAC,KAAK,cAAc;AACtB,WAAK,iBAAiB;AAAA,IACxB;AAEA,UAAI,UAAK,iBAAL,mBAAmB,WAAU,aAAa;AAC5C,YAAM,KAAK,aAAa,OAAO;AAAA,IACjC;AAEA,QAAI;AACF,YAAM,KAAK,MAAM,KAAK;AACtB,uBAAK,YAAL,mBAAc,WAAd;AAAA,IACF,SAAS,OAAP;AACA,cAAQ,MAAM,wBAAwB,KAAK;AAC3C,uBAAK,YAAL,mBAAc,YAAd,4BAAwB;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAY,SAAiB;AAC3B,QAAI,UAAU,GAAG;AACf;AAAA,IACF;AACA,QAAI,CAAC,MAAM,KAAK,MAAM,QAAQ,GAAG;AAC/B,WAAK,MAAM,cAAc,KAAK,IAAI,KAAK,MAAM,cAAc,SAAS,KAAK,MAAM,QAAQ;AAAA,IACzF,OAAO;AACL,WAAK,MAAM,eAAe;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,SAAiB;AAC5B,QAAI,UAAU,GAAG;AACf;AAAA,IACF;AACA,SAAK,MAAM,cAAc,KAAK,IAAI,KAAK,MAAM,cAAc,SAAS,CAAC;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAK,MAAc;AAEjB,UAAM,UAAU,KAAK,IAAI,GAAG,IAAI;AAEhC,QAAI,CAAC,MAAM,KAAK,MAAM,QAAQ,GAAG;AAC/B,WAAK,MAAM,cAAc,KAAK,IAAI,SAAS,KAAK,MAAM,QAAQ;AAAA,IAChE,OAAO;AACL,WAAK,MAAM,cAAc;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAc;AAxLhB;AAyLI,SAAK,MAAM,MAAM;AACjB,qBAAK,YAAL,mBAAc,YAAd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAa;AAjMf;AAkMI,SAAK,MAAM,MAAM;AACjB,SAAK,MAAM,cAAc;AACzB,qBAAK,YAAL,mBAAc,WAAd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eAAe,QAAsB;AACzC,SAAK,MAAM,MAAM;AACjB,SAAK,MAAM,MAAM;AAEjB,QAAI,OAAO,WAAW,UAAU;AAC9B,WAAK,MAAM,MAAM;AAAA,IACnB,OAAO;AACL,YAAM,KAAK,mBAAmB,MAAM;AAAA,IACtC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS,UAAU,KAAW;AAC5B,SAAK,UAAU,KAAK,IAAI,GAAK,KAAK,UAAU,OAAO;AACnD,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,UAAU,KAAW;AAC9B,SAAK,UAAU,KAAK,IAAI,GAAG,KAAK,UAAU,OAAO;AACjD,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,OAAqB;AAC7B,SAAK,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,KAAK,CAAC;AAC/C,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EA4BA,UAAgB;AACd,SAAK,MAAM,MAAM;AACjB,SAAK,MAAM,MAAM;AACjB,SAAK,oBAAoB,SAAS,KAAK,SAAS;AAEhD,QAAI,KAAK,cAAc;AACrB,UAAI;AACF,aAAK,aAAa,MAAM;AAAA,MAC1B,SAAS,OAAP;AACA,gBAAQ,MAAM,+BAA+B,KAAK;AAAA,MACpD;AACA,WAAK,eAAe;AAAA,IACtB;AAEA,SAAK,aAAa;AAClB,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA,EAGA,MAAc,mBAAmB,QAAkD;AACjF,QAAI,CAAC;AAAQ;AACb,QAAI;AACF,UAAI;AACJ,UAAI,kBAAkB,MAAM;AAC1B,eAAO;AAAA,MACT,WAAW,kBAAkB,eAAe,kBAAkB,YAAY;AACxE,eAAO,IAAI,KAAK,CAAC,MAAM,CAAC;AAAA,MAC1B,OAAO;AAEL,cAAM,SAAS,IAAI,eAAe;AAAA,UAChC,MAAM,KAAK,YAAY;AACrB,gBAAI;AACF,oBAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,kBAAI,MAAM;AACR,2BAAW,MAAM;AAAA,cACnB,OAAO;AACL,2BAAW,QAAQ,KAAK;AAAA,cAC1B;AAAA,YACF,SAAS,KAAP;AACA,yBAAW,MAAM,GAAG;AAAA,YACtB;AAAA,UACF;AAAA,QACF,CAAC;AAED,cAAM,WAAW,IAAI,SAAS,MAAM;AACpC,eAAO,MAAM,SAAS,KAAK;AAAA,MAC7B;AAEA,YAAM,MAAM,IAAI,gBAAgB,IAAI;AAEpC,WAAK,MAAM,MAAM;AAGjB,WAAK,MAAM,SAAS,MAAM;AACxB,YAAI,gBAAgB,GAAG;AAAA,MACzB;AAAA,IACF,SAAS,OAAP;AACA,cAAQ,MAAM,kCAAkC,KAAK;AAAA,IACvD;AAAA,EACF;AAAA;AAAA,EAGQ,mBAAmB;AACzB,QAAI,KAAK;AAAc;AAEvB,SAAK,eAAe,IAAI,aAAa;AACrC,SAAK,aAAa,KAAK,aAAa,yBAAyB,KAAK,KAAK;AACvE,SAAK,WAAW,KAAK,aAAa,WAAW;AAE7C,SAAK,WAAW,QAAQ,KAAK,QAAQ;AACrC,SAAK,SAAS,QAAQ,KAAK,aAAa,WAAW;AAEnD,SAAK,SAAS,KAAK,QAAQ,KAAK;AAAA,EAClC;AAAA;AAAA,EAGQ,eAAqB;AAC3B,QAAI,KAAK,UAAU;AACjB,WAAK,SAAS,KAAK,QAAQ,KAAK;AAAA,IAClC,OAAO;AACL,WAAK,MAAM,SAAS,KAAK;AAAA,IAC3B;AAAA,EACF;AACF;AAEA,IAAO,sBAAQ;",
4
+ "sourcesContent": ["export type AudioSource = string | ReadableStreamDefaultReader<Uint8Array> | ArrayBuffer | Uint8Array | Blob;\n\nexport interface AudioPlayerInit {\n /**\n * - **EN:** Audio source (URL or streaming data)\n * - **CN:** 音频源(URL或流数据)\n */\n source?: AudioSource | (() => AudioSource | Promise<AudioSource>);\n /**\n * - **EN:** MIME type of the audio (e.g., 'audio/mpeg', 'audio/wav'). Optional.\n * - **CN:** 音频的MIME类型(例如,'audio/mpeg','audio/wav')。可选。\n */\n mimeType?: string;\n /**\n * - **EN:** Initial volume level (0-1). Default is `0.5`\n * - **CN:** 初始音量级别(0-1)。默认值为`0.5`\n */\n volume?: number;\n /**\n * - **EN:** Callback when audio starts playing\n * - **CN:** 音频开始播放时的回调\n */\n onPlay?: () => void;\n /**\n * - **EN:** Callback when audio is paused\n * - **CN:** 音频暂停时的回调\n */\n onPause?: () => void;\n /**\n * - **EN:** Callback when audio is stopped\n * - **CN:** 音频停止时的回调\n */\n onStop?: () => void;\n\n /**\n * - **EN:** Callback when audio playback ends\n * - **CN:** 音频播放结束时的回调\n */\n onPlayEnd?: () => void;\n /**\n * - **EN:** Callback when an error occurs\n * - **CN:** 发生错误时的回调\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onError?: (error: any) => void;\n}\n\n/**\n * - **EN:** An audio player class that supports URL or streaming data input\n * - **CN:** 一个音频播放器类,支持URL或流数据输入\n */\nclass AudioPlayer {\n private audio: HTMLAudioElement;\n private _volume: number;\n private audioContext: AudioContext | null = null;\n private gainNode: GainNode | null = null;\n private sourceNode: MediaElementAudioSourceNode | null = null;\n private options: AudioPlayerInit | undefined;\n private mediaSource: MediaSource | null = null;\n private sourceBuffer: SourceBuffer | null = null;\n private chunkQueue: Uint8Array[] = [];\n private appending = false;\n private streamEnded = false;\n private stopLoadingSource = false;\n private onPlayEnd: () => void;\n\n /**\n * - **EN:** Creates an audio player instance\n * - **CN:** 创建音频播放器实例\n *\n * @param source - can be a URL string or ReadableStreamDefaultReader |\n * 可以是URL字符串或ReadableStreamDefaultReader\n */\n constructor(options?: AudioPlayerInit) {\n const { source, volume } = options || {};\n this.options = options;\n this.audio = new Audio();\n this._volume = volume != null ? Math.min(1.0, Math.max(0, volume)) : 0.5; // Default volume 50%\n this.audio.volume = this._volume;\n if (typeof source === 'function') {\n const result = source();\n if (typeof result === 'object' && 'then' in result && typeof result.then === 'function') {\n result.then((data) => this.setAudioSource(data));\n } else {\n this.setAudioSource(result as AudioSource);\n }\n } else {\n this.setAudioSource(source);\n }\n this.onPlayEnd = () => {\n this.options?.onPlayEnd?.();\n };\n this.addEventListener('ended', this.onPlayEnd);\n }\n\n /**\n * - **EN:** Check if audio is currently playing\n * - **CN:** 检查音频是否正在播放\n */\n public get isPlaying() {\n return !this.audio.paused && !this.audio.ended;\n }\n /**\n * - **EN:** Get current playback time (seconds)\n * - **CN:** 获取当前播放时间(秒)\n */\n get currentTime(): number {\n return this.audio.currentTime;\n }\n /**\n * - **EN:** Get total audio duration (seconds)\n * - **CN:** 获取音频总时长(秒)\n */\n get duration(): number {\n return this.audio.duration;\n }\n /**\n * - **EN:** Get current volume value (0-1)\n * - **CN:** 获取当前音量值(0-1)\n */\n get volume(): number {\n return this._volume;\n }\n\n /**\n * - **EN:** Play audio. If previously paused, will resume from the pause position\n * - **CN:** 播放音频 如果之前暂停过,将从暂停位置继续播放\n */\n async play(): Promise<void> {\n if (!this.audioContext) {\n this.initAudioContext();\n }\n\n if (this.audioContext?.state === 'suspended') {\n await this.audioContext.resume();\n }\n\n try {\n await this.audio.play();\n this.options?.onPlay?.();\n } catch (error) {\n console.error('Error playing audio:', error);\n this.options?.onError?.(error);\n }\n }\n\n /**\n * - **EN:** Seek forward by a certain number of seconds\n * - **CN:** 向前跳转一定秒数\n *\n * @param seconds - number of seconds to seek forward | 要向前跳转的秒数\n */\n seekForward(seconds: number) {\n if (seconds < 0) {\n return;\n }\n if (!isNaN(this.audio.duration)) {\n this.audio.currentTime = Math.min(this.audio.currentTime + seconds, this.audio.duration);\n } else {\n this.audio.currentTime += seconds;\n }\n }\n /**\n * - **EN:** Seek backward by a certain number of seconds\n * - **CN:** 向后跳转一定秒数\n *\n * @param seconds - number of seconds to seek backward | 要向后跳转的秒数\n */\n seekBackward(seconds: number) {\n if (seconds < 0) {\n return;\n }\n this.audio.currentTime = Math.max(this.audio.currentTime - seconds, 0);\n }\n /**\n * - **EN:** Set current playback time (in seconds)\n * - **CN:** 设置当前播放时间(以秒为单位)\n *\n * @param time - time in seconds | 时间(秒)\n */\n seek(time: number) {\n // Ensure time is not less than 0\n const newTime = Math.max(0, time);\n // Ensure time is not greater than duration (if known)\n if (!isNaN(this.audio.duration)) {\n this.audio.currentTime = Math.min(newTime, this.audio.duration);\n } else {\n this.audio.currentTime = newTime;\n }\n }\n\n /**\n * - **EN:** Pause audio playback. When played again, will continue from current position\n * - **CN:** 暂停音频播放 再次播放时将从当前位置继续\n */\n pause(): void {\n this.audio.pause();\n this.options?.onPause?.();\n }\n\n /**\n * - **EN:** Stop audio playback. Progress will reset to the beginning\n * - **CN:** 停止音频播放 进度会重置到开始位置\n */\n stop(): void {\n this.audio.pause();\n this.audio.currentTime = 0;\n this.options?.onStop?.();\n }\n\n /**\n * - **EN:** Update audio source\n * - **CN:** 更新音频源\n *\n * @param source - can be a URL `string` or `ReadableStreamDefaultReader` |\n * 可以是URL字符串或`ReadableStreamDefaultReader`\n */\n async setAudioSource(source?: AudioSource): Promise<{ stopLoading: () => void }> {\n this.audio.pause();\n this.audio.src = '';\n this.disposeMediaSourceInternal();\n\n if (typeof source === 'string') {\n this.audio.src = source;\n return {\n stopLoading: () => {\n // empty function\n },\n };\n } else {\n return await this.handleStreamSource(source);\n }\n }\n\n /**\n * - **EN:** Increase volume (by 10% each time)\n * - **CN:** 增加音量(每次增加10%)\n *\n * @param percent - increase percentage (default 10%) | 增加百分比(默认10%)\n */\n volumeUp(percent = 0.1): void {\n this._volume = Math.min(1.0, this._volume + percent);\n this.updateVolume();\n }\n\n /**\n * - **EN:** Decrease volume (by 10% each time)\n * - **CN:** 降低音量(每次降低10%)\n *\n * @param percent - decrease percentage (default 10%) | 降低百分比(默认10%)\n */\n volumeDown(percent = 0.1): void {\n this._volume = Math.max(0, this._volume - percent);\n this.updateVolume();\n }\n\n /**\n * - **EN:** Set volume to a specific value (0-1)\n * - **CN:** 将音量设置为特定值(0-1)\n *\n * @param value - new volume value (0-1) | 新的音量值(0-1)\n */\n setVolume(value: number): void {\n this._volume = Math.min(1.0, Math.max(0, value));\n this.updateVolume();\n }\n\n /**\n * - **EN:** Add audio event listener\n * - **CN:** 添加音频事件监听器\n */\n addEventListener: HTMLAudioElement['addEventListener'] = (\n event: string,\n listener: EventListenerOrEventListenerObject\n ): void => {\n this.audio.addEventListener(event, listener);\n };\n\n /**\n * - **EN:** Remove audio event listener\n * - **CN:** 移除音频事件监听器\n */\n removeEventListener: HTMLAudioElement['removeEventListener'] = (\n event: string,\n listener: EventListenerOrEventListenerObject\n ): void => {\n this.audio.removeEventListener(event, listener);\n };\n\n /**\n * - **EN:** Release resources\n * - **CN:** 释放资源\n */\n dispose(): void {\n this.audio.pause();\n this.audio.src = '';\n this.removeEventListener('ended', this.onPlayEnd);\n\n if (this.audioContext) {\n try {\n this.audioContext.close();\n } catch (error) {\n console.error('Error closing AudioContext:', error);\n }\n this.audioContext = null;\n }\n\n this.sourceNode = null;\n this.gainNode = null;\n }\n private disposeMediaSourceInternal() {\n this.mediaSource = null;\n this.sourceBuffer = null;\n this.chunkQueue = [];\n this.appending = false;\n this.streamEnded = false;\n }\n\n /** Process streaming data source /ArrayBuffer/Uint8Array/Blob */\n private async handleStreamSource(\n source: Exclude<AudioSource, string> | undefined\n ): Promise<{ stopLoading: () => void }> {\n const result = {\n stopLoading: () => {\n // empty function\n },\n };\n if (!source) return result;\n try {\n if (source instanceof Blob) {\n const url = URL.createObjectURL(source);\n this.audio.src = url;\n return result;\n } else if (source instanceof ArrayBuffer || source instanceof Uint8Array) {\n const blob = source instanceof Uint8Array ? new Blob([source]) : new Blob([new Uint8Array(source)]);\n const url = URL.createObjectURL(blob);\n this.audio.src = url;\n this.audio.onloadeddata = () => URL.revokeObjectURL(url);\n return result;\n } else {\n // Create a new ReadableStream to read data from the reader\n const mime = this.options?.mimeType || 'audio/mpeg';\n result.stopLoading = () => {\n this.stopLoadingSource = true;\n };\n await this.initMediaSourceForReader(source, mime);\n return result;\n }\n } catch (error) {\n console.error('Error processing audio stream:', error);\n this.options?.onError?.(error);\n throw error;\n }\n }\n\n /** Initialize Web Audio API for better volume control */\n private initAudioContext() {\n if (this.audioContext) return;\n\n this.audioContext = new AudioContext();\n this.sourceNode = this.audioContext.createMediaElementSource(this.audio);\n this.gainNode = this.audioContext.createGain();\n\n this.sourceNode.connect(this.gainNode);\n this.gainNode.connect(this.audioContext.destination);\n\n this.gainNode.gain.value = this._volume;\n }\n\n /** Update audio playback volume */\n private updateVolume(): void {\n if (this.gainNode) {\n this.gainNode.gain.value = this._volume;\n } else {\n this.audio.volume = this._volume;\n }\n }\n\n /** Initialize MediaSource and push reader chunks into SourceBuffer */\n private async initMediaSourceForReader(reader: ReadableStreamDefaultReader<Uint8Array>, mime: string) {\n if (typeof MediaSource === 'undefined') {\n console.warn('MediaSource is not supported, falling back to one-time buffering.');\n await this.fallbackReaderToBlob(reader);\n return;\n }\n if (typeof MediaSource !== 'undefined' && !MediaSource.isTypeSupported(mime)) {\n console.warn('MIME type is not supported, falling back to one-time buffering.');\n await this.fallbackReaderToBlob(reader);\n return;\n }\n\n this.mediaSource = new MediaSource();\n const objectURL = URL.createObjectURL(this.mediaSource);\n this.audio.src = objectURL;\n this.stopLoadingSource = false;\n\n this.mediaSource.addEventListener('sourceopen', () => {\n if (!this.mediaSource) return;\n this.sourceBuffer = this.mediaSource.addSourceBuffer(mime);\n\n this.sourceBuffer.addEventListener('updateend', () => {\n this.appending = false;\n this.tryAppendNext();\n this.finalizeMediaSourceIfPossible();\n });\n\n // Start reading loop\n this.readLoop(reader);\n });\n }\n\n /** Loop to read data from the reader */\n private async readLoop(reader: ReadableStreamDefaultReader<Uint8Array>) {\n try {\n // Auto play (optional)\n if (this.audio.paused) {\n void this.play();\n }\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const { done, value } = await reader.read();\n if (done || this.stopLoadingSource) {\n this.streamEnded = true;\n break;\n }\n if (value && value.byteLength) {\n this.chunkQueue.push(value);\n this.tryAppendNext();\n }\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n // Try to finalize after the loop exits (including 0 chunk case)\n this.finalizeMediaSourceIfPossible();\n } catch (e) {\n console.error('Error reading stream:', e);\n this.options?.onError?.(e);\n }\n }\n\n /** Try to append the next chunk from the queue to the SourceBuffer */\n private tryAppendNext() {\n if (!this.sourceBuffer || this.appending) return;\n if (!this.chunkQueue.length) return;\n\n const chunk = this.chunkQueue.shift()!;\n this.appending = true;\n try {\n this.sourceBuffer.appendBuffer(chunk);\n } catch (e) {\n console.error('Error appending buffer:', e);\n this.appending = false;\n this.options?.onError?.(e);\n this.finalizeMediaSourceIfPossible();\n }\n }\n\n /** Finalize MediaSource if possible (stream ended, no pending chunks, and not updating) */\n private finalizeMediaSourceIfPossible(receivedAnyChunk = true) {\n if (\n this.mediaSource &&\n this.mediaSource.readyState === 'open' &&\n this.streamEnded &&\n !this.sourceBuffer?.updating &&\n this.chunkQueue.length === 0\n ) {\n try {\n this.mediaSource.endOfStream();\n } catch (e) {\n console.warn('endOfStream error:', e);\n }\n }\n }\n\n /** Fallback to one-time Blob synthesis when streaming is not supported */\n private async fallbackReaderToBlob(reader: ReadableStreamDefaultReader<Uint8Array>) {\n const stream = new ReadableStream({\n async pull(controller) {\n try {\n const { done, value } = await reader.read();\n if (done) {\n controller.close();\n } else {\n controller.enqueue(value);\n }\n } catch (err) {\n controller.error(err);\n }\n },\n });\n // Convert stream to Blob and create URL\n const response = new Response(stream);\n const blob = await response.blob();\n const url = URL.createObjectURL(blob);\n this.audio.src = url;\n this.audio.onloadeddata = () => URL.revokeObjectURL(url);\n }\n}\n\nexport default AudioPlayer;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAmDA,IAAM,cAAN,MAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBhB,YAAY,SAA2B;AAnBvC,SAAQ,eAAoC;AAC5C,SAAQ,WAA4B;AACpC,SAAQ,aAAiD;AAEzD,SAAQ,cAAkC;AAC1C,SAAQ,eAAoC;AAC5C,SAAQ,aAA2B,CAAC;AACpC,SAAQ,YAAY;AACpB,SAAQ,cAAc;AACtB,SAAQ,oBAAoB;AAgN5B;AAAA;AAAA;AAAA;AAAA,4BAAyD,CACvD,OACA,aACS;AACT,WAAK,MAAM,iBAAiB,OAAO,QAAQ;AAAA,IAC7C;AAMA;AAAA;AAAA;AAAA;AAAA,+BAA+D,CAC7D,OACA,aACS;AACT,WAAK,MAAM,oBAAoB,OAAO,QAAQ;AAAA,IAChD;AArNE,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW,CAAC;AACvC,SAAK,UAAU;AACf,SAAK,QAAQ,IAAI,MAAM;AACvB,SAAK,UAAU,UAAU,OAAO,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI;AACrE,SAAK,MAAM,SAAS,KAAK;AACzB,QAAI,OAAO,WAAW,YAAY;AAChC,YAAM,SAAS,OAAO;AACtB,UAAI,OAAO,WAAW,YAAY,UAAU,UAAU,OAAO,OAAO,SAAS,YAAY;AACvF,eAAO,KAAK,CAAC,SAAS,KAAK,eAAe,IAAI,CAAC;AAAA,MACjD,OAAO;AACL,aAAK,eAAe,MAAqB;AAAA,MAC3C;AAAA,IACF,OAAO;AACL,WAAK,eAAe,MAAM;AAAA,IAC5B;AACA,SAAK,YAAY,MAAM;AAzF3B;AA0FM,uBAAK,YAAL,mBAAc,cAAd;AAAA,IACF;AACA,SAAK,iBAAiB,SAAS,KAAK,SAAS;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAW,YAAY;AACrB,WAAO,CAAC,KAAK,MAAM,UAAU,CAAC,KAAK,MAAM;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,cAAsB;AACxB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAAmB;AACrB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAiB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAsB;AAhI9B;AAiII,QAAI,CAAC,KAAK,cAAc;AACtB,WAAK,iBAAiB;AAAA,IACxB;AAEA,UAAI,UAAK,iBAAL,mBAAmB,WAAU,aAAa;AAC5C,YAAM,KAAK,aAAa,OAAO;AAAA,IACjC;AAEA,QAAI;AACF,YAAM,KAAK,MAAM,KAAK;AACtB,uBAAK,YAAL,mBAAc,WAAd;AAAA,IACF,SAAS,OAAP;AACA,cAAQ,MAAM,wBAAwB,KAAK;AAC3C,uBAAK,YAAL,mBAAc,YAAd,4BAAwB;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAY,SAAiB;AAC3B,QAAI,UAAU,GAAG;AACf;AAAA,IACF;AACA,QAAI,CAAC,MAAM,KAAK,MAAM,QAAQ,GAAG;AAC/B,WAAK,MAAM,cAAc,KAAK,IAAI,KAAK,MAAM,cAAc,SAAS,KAAK,MAAM,QAAQ;AAAA,IACzF,OAAO;AACL,WAAK,MAAM,eAAe;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,SAAiB;AAC5B,QAAI,UAAU,GAAG;AACf;AAAA,IACF;AACA,SAAK,MAAM,cAAc,KAAK,IAAI,KAAK,MAAM,cAAc,SAAS,CAAC;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAK,MAAc;AAEjB,UAAM,UAAU,KAAK,IAAI,GAAG,IAAI;AAEhC,QAAI,CAAC,MAAM,KAAK,MAAM,QAAQ,GAAG;AAC/B,WAAK,MAAM,cAAc,KAAK,IAAI,SAAS,KAAK,MAAM,QAAQ;AAAA,IAChE,OAAO;AACL,WAAK,MAAM,cAAc;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAc;AAnMhB;AAoMI,SAAK,MAAM,MAAM;AACjB,qBAAK,YAAL,mBAAc,YAAd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAa;AA5Mf;AA6MI,SAAK,MAAM,MAAM;AACjB,SAAK,MAAM,cAAc;AACzB,qBAAK,YAAL,mBAAc,WAAd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eAAe,QAA4D;AAC/E,SAAK,MAAM,MAAM;AACjB,SAAK,MAAM,MAAM;AACjB,SAAK,2BAA2B;AAEhC,QAAI,OAAO,WAAW,UAAU;AAC9B,WAAK,MAAM,MAAM;AACjB,aAAO;AAAA,QACL,aAAa,MAAM;AAAA,QAEnB;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAO,MAAM,KAAK,mBAAmB,MAAM;AAAA,IAC7C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS,UAAU,KAAW;AAC5B,SAAK,UAAU,KAAK,IAAI,GAAK,KAAK,UAAU,OAAO;AACnD,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,UAAU,KAAW;AAC9B,SAAK,UAAU,KAAK,IAAI,GAAG,KAAK,UAAU,OAAO;AACjD,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,OAAqB;AAC7B,SAAK,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,KAAK,CAAC;AAC/C,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EA4BA,UAAgB;AACd,SAAK,MAAM,MAAM;AACjB,SAAK,MAAM,MAAM;AACjB,SAAK,oBAAoB,SAAS,KAAK,SAAS;AAEhD,QAAI,KAAK,cAAc;AACrB,UAAI;AACF,aAAK,aAAa,MAAM;AAAA,MAC1B,SAAS,OAAP;AACA,gBAAQ,MAAM,+BAA+B,KAAK;AAAA,MACpD;AACA,WAAK,eAAe;AAAA,IACtB;AAEA,SAAK,aAAa;AAClB,SAAK,WAAW;AAAA,EAClB;AAAA,EACQ,6BAA6B;AACnC,SAAK,cAAc;AACnB,SAAK,eAAe;AACpB,SAAK,aAAa,CAAC;AACnB,SAAK,YAAY;AACjB,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA,EAGA,MAAc,mBACZ,QACsC;AAjU1C;AAkUI,UAAM,SAAS;AAAA,MACb,aAAa,MAAM;AAAA,MAEnB;AAAA,IACF;AACA,QAAI,CAAC;AAAQ,aAAO;AACpB,QAAI;AACF,UAAI,kBAAkB,MAAM;AAC1B,cAAM,MAAM,IAAI,gBAAgB,MAAM;AACtC,aAAK,MAAM,MAAM;AACjB,eAAO;AAAA,MACT,WAAW,kBAAkB,eAAe,kBAAkB,YAAY;AACxE,cAAM,OAAO,kBAAkB,aAAa,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,WAAW,MAAM,CAAC,CAAC;AAClG,cAAM,MAAM,IAAI,gBAAgB,IAAI;AACpC,aAAK,MAAM,MAAM;AACjB,aAAK,MAAM,eAAe,MAAM,IAAI,gBAAgB,GAAG;AACvD,eAAO;AAAA,MACT,OAAO;AAEL,cAAM,SAAO,UAAK,YAAL,mBAAc,aAAY;AACvC,eAAO,cAAc,MAAM;AACzB,eAAK,oBAAoB;AAAA,QAC3B;AACA,cAAM,KAAK,yBAAyB,QAAQ,IAAI;AAChD,eAAO;AAAA,MACT;AAAA,IACF,SAAS,OAAP;AACA,cAAQ,MAAM,kCAAkC,KAAK;AACrD,uBAAK,YAAL,mBAAc,YAAd,4BAAwB;AACxB,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGQ,mBAAmB;AACzB,QAAI,KAAK;AAAc;AAEvB,SAAK,eAAe,IAAI,aAAa;AACrC,SAAK,aAAa,KAAK,aAAa,yBAAyB,KAAK,KAAK;AACvE,SAAK,WAAW,KAAK,aAAa,WAAW;AAE7C,SAAK,WAAW,QAAQ,KAAK,QAAQ;AACrC,SAAK,SAAS,QAAQ,KAAK,aAAa,WAAW;AAEnD,SAAK,SAAS,KAAK,QAAQ,KAAK;AAAA,EAClC;AAAA;AAAA,EAGQ,eAAqB;AAC3B,QAAI,KAAK,UAAU;AACjB,WAAK,SAAS,KAAK,QAAQ,KAAK;AAAA,IAClC,OAAO;AACL,WAAK,MAAM,SAAS,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,yBAAyB,QAAiD,MAAc;AACpG,QAAI,OAAO,gBAAgB,aAAa;AACtC,cAAQ,KAAK,mEAAmE;AAChF,YAAM,KAAK,qBAAqB,MAAM;AACtC;AAAA,IACF;AACA,QAAI,OAAO,gBAAgB,eAAe,CAAC,YAAY,gBAAgB,IAAI,GAAG;AAC5E,cAAQ,KAAK,iEAAiE;AAC9E,YAAM,KAAK,qBAAqB,MAAM;AACtC;AAAA,IACF;AAEA,SAAK,cAAc,IAAI,YAAY;AACnC,UAAM,YAAY,IAAI,gBAAgB,KAAK,WAAW;AACtD,SAAK,MAAM,MAAM;AACjB,SAAK,oBAAoB;AAEzB,SAAK,YAAY,iBAAiB,cAAc,MAAM;AACpD,UAAI,CAAC,KAAK;AAAa;AACvB,WAAK,eAAe,KAAK,YAAY,gBAAgB,IAAI;AAEzD,WAAK,aAAa,iBAAiB,aAAa,MAAM;AACpD,aAAK,YAAY;AACjB,aAAK,cAAc;AACnB,aAAK,8BAA8B;AAAA,MACrC,CAAC;AAGD,WAAK,SAAS,MAAM;AAAA,IACtB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAc,SAAS,QAAiD;AA5Z1E;AA6ZI,QAAI;AAEF,UAAI,KAAK,MAAM,QAAQ;AACrB,aAAK,KAAK,KAAK;AAAA,MACjB;AAEA,aAAO,MAAM;AACX,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI,QAAQ,KAAK,mBAAmB;AAClC,eAAK,cAAc;AACnB;AAAA,QACF;AACA,YAAI,SAAS,MAAM,YAAY;AAC7B,eAAK,WAAW,KAAK,KAAK;AAC1B,eAAK,cAAc;AAAA,QACrB;AACA,cAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG,CAAC;AAAA,MACzD;AAEA,WAAK,8BAA8B;AAAA,IACrC,SAAS,GAAP;AACA,cAAQ,MAAM,yBAAyB,CAAC;AACxC,uBAAK,YAAL,mBAAc,YAAd,4BAAwB;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA,EAGQ,gBAAgB;AAxb1B;AAybI,QAAI,CAAC,KAAK,gBAAgB,KAAK;AAAW;AAC1C,QAAI,CAAC,KAAK,WAAW;AAAQ;AAE7B,UAAM,QAAQ,KAAK,WAAW,MAAM;AACpC,SAAK,YAAY;AACjB,QAAI;AACF,WAAK,aAAa,aAAa,KAAK;AAAA,IACtC,SAAS,GAAP;AACA,cAAQ,MAAM,2BAA2B,CAAC;AAC1C,WAAK,YAAY;AACjB,uBAAK,YAAL,mBAAc,YAAd,4BAAwB;AACxB,WAAK,8BAA8B;AAAA,IACrC;AAAA,EACF;AAAA;AAAA,EAGQ,8BAA8B,mBAAmB,MAAM;AAzcjE;AA0cI,QACE,KAAK,eACL,KAAK,YAAY,eAAe,UAChC,KAAK,eACL,GAAC,UAAK,iBAAL,mBAAmB,aACpB,KAAK,WAAW,WAAW,GAC3B;AACA,UAAI;AACF,aAAK,YAAY,YAAY;AAAA,MAC/B,SAAS,GAAP;AACA,gBAAQ,KAAK,sBAAsB,CAAC;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,qBAAqB,QAAiD;AAClF,UAAM,SAAS,IAAI,eAAe;AAAA,MAChC,MAAM,KAAK,YAAY;AACrB,YAAI;AACF,gBAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,cAAI,MAAM;AACR,uBAAW,MAAM;AAAA,UACnB,OAAO;AACL,uBAAW,QAAQ,KAAK;AAAA,UAC1B;AAAA,QACF,SAAS,KAAP;AACA,qBAAW,MAAM,GAAG;AAAA,QACtB;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,WAAW,IAAI,SAAS,MAAM;AACpC,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAM,MAAM,IAAI,gBAAgB,IAAI;AACpC,SAAK,MAAM,MAAM;AACjB,SAAK,MAAM,eAAe,MAAM,IAAI,gBAAgB,GAAG;AAAA,EACzD;AACF;AAEA,IAAO,sBAAQ;",
6
6
  "names": []
7
7
  }
@@ -169,23 +169,23 @@ async function encryptWithCryptoJS(text, key) {
169
169
  async function decryptWithCryptoJS(encryptedText, key) {
170
170
  const [ivBase64, encryptedBase64] = encryptedText.split(":");
171
171
  const [
172
+ { default: Base64 },
173
+ { default: Utf8 },
172
174
  {
173
175
  default: {
174
176
  mode: { CBC }
175
177
  }
176
178
  },
177
179
  { default: Pkcs7 },
178
- { default: Base64 },
179
- { default: Utf8 },
180
180
  { default: SHA256 },
181
181
  {
182
182
  default: { decrypt }
183
183
  }
184
184
  ] = await Promise.all([
185
- import("crypto-js/core.js"),
186
- import("crypto-js/pad-pkcs7.js"),
187
185
  import("crypto-js/enc-base64.js"),
188
186
  import("crypto-js/enc-utf8.js"),
187
+ import("crypto-js/core.js"),
188
+ import("crypto-js/pad-pkcs7.js"),
189
189
  import("crypto-js/sha256.js"),
190
190
  import("crypto-js/aes.js")
191
191
  ]);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/crypto.ts"],
4
- "sourcesContent": ["import { base64ToString, stringToBase64 } from './base64';\nimport { random } from './math';\nimport { randomChars } from './string';\n\n/** Secret. No description provided */\nexport async function advancedEncrypt(plainText: string, key: string) {\n const k1 = randomChars(36);\n let e = await encryptAES(plainText, k1);\n const b = stringToBase64(k1);\n const l = b.length;\n const s = random(0, e.length);\n e = e.substring(0, s) + b + e.substring(s);\n const r = stringToBase64(`${s}-${l}`);\n const t = `${e}.${r}`;\n return encryptAES(t, key);\n}\n\n/** Secret. No description provided */\nexport async function advancedDecrypt(encryptedText: string, key: string) {\n const decrypted = await decryptAES(encryptedText, key);\n const [e, r] = decrypted.split('.');\n const [s, l] = base64ToString(r).split('-').map(Number);\n const k1 = base64ToString(e.substring(s, s + l));\n return decryptAES(e.substring(0, s) + e.substring(s + l), k1);\n}\n\n/**\n * **EN**: General AES encryption function - supports both Node.js and browser environments\n *\n * **CN**: 通用 AES 加密函数 - 同时支持 Node.js 和浏览器环境\n *\n * @param {string} text The text to be encrypted | 要加密的文本\n * @param {string} key The encryption key | 加密密钥\n *\n * @returns {Promise<string>} The encrypted text | 加密后的文本\n */\nexport async function encryptAES(text: string, key: string): Promise<string> {\n const isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;\n\n if (isNode) {\n // Node.js\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const crypto = require('crypto');\n const derivedKey = crypto.createHash('sha256').update(key).digest();\n const iv = crypto.randomBytes(16);\n const cipher = crypto.createCipheriv('aes-256-cbc', derivedKey, iv);\n let encrypted = cipher.update(text, 'utf8', 'base64');\n encrypted += cipher.final('base64');\n return `${iv.toString('base64')}:${encrypted}`;\n } else {\n if (crypto.subtle) {\n // Browsers\n try {\n const iv = crypto.getRandomValues(new Uint8Array(16));\n const encoder = new TextEncoder();\n const keyData = encoder.encode(key);\n const hashBuffer = await crypto.subtle.digest('SHA-256', keyData);\n const cryptoKey = await crypto.subtle.importKey('raw', hashBuffer, { name: 'AES-CBC' }, false, ['encrypt']);\n const textBytes = encoder.encode(text);\n const encryptedBuffer = await crypto.subtle.encrypt({ name: 'AES-CBC', iv }, cryptoKey, textBytes);\n const ivBase64 = btoa(String.fromCharCode(...iv));\n const encryptedBase64 = btoa(String.fromCharCode(...new Uint8Array(encryptedBuffer)));\n return `${ivBase64}:${encryptedBase64}`;\n } catch (error) {\n console.error('Encryption error:', error);\n throw error;\n }\n } else {\n // let encrypt: typeof CryptoJS.AES.encrypt;\n // try {\n // const aes = await import('crypto-js/aes');\n // encrypt = aes.encrypt;\n // } catch (error) {\n // console.error('Load \"crypto-js/aes\" error:', error);\n // throw error;\n // }\n // try {\n // return encrypt(text, key).toString();\n // } catch (error) {\n // console.error('Encryption error:', error);\n // throw error;\n // }\n return encryptWithCryptoJS(text, key);\n }\n }\n}\n\n/**\n * **EN**: General AES decryption function - supports both Node.js and browser environments\n *\n * **CN**: 通用 AES 解密函数 - 同时支持 Node.js 和浏览器环境\n *\n * @param encryptedText The encrypted text (format: iv:encryptedContent, base64 encoded)\n * @param key The decryption key\n *\n * @returns The decrypted text\n */\nexport async function decryptAES(encryptedText: string, key: string): Promise<string> {\n const isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;\n try {\n const [ivBase64, encryptedBase64] = encryptedText.split(':');\n if (!ivBase64 || !encryptedBase64) {\n throw new Error('Invalid encrypted format');\n }\n if (isNode) {\n // Node.js\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const crypto = require('crypto');\n const iv = Buffer.from(ivBase64, 'base64');\n const encryptedBuffer = Buffer.from(encryptedBase64, 'base64');\n const derivedKey = crypto.createHash('sha256').update(key).digest();\n const decipher = crypto.createDecipheriv('aes-256-cbc', derivedKey, iv);\n let decrypted = decipher.update(encryptedBuffer);\n decrypted = Buffer.concat([decrypted, decipher.final()]);\n return decrypted.toString('utf8');\n } else {\n if (crypto.subtle) {\n // Browsers with Web Crypto API, in secure contexts (HTTPS)\n const iv = Uint8Array.from(atob(ivBase64), (c) => c.charCodeAt(0));\n const encryptedData = Uint8Array.from(atob(encryptedBase64), (c) => c.charCodeAt(0));\n const encoder = new TextEncoder();\n const keyData = encoder.encode(key);\n const hashBuffer = await crypto.subtle.digest('SHA-256', keyData);\n const cryptoKey = await crypto.subtle.importKey('raw', hashBuffer, { name: 'AES-CBC' }, false, ['decrypt']);\n const decryptedBuffer = await crypto.subtle.decrypt({ name: 'AES-CBC', iv }, cryptoKey, encryptedData);\n const decoder = new TextDecoder();\n return decoder.decode(decryptedBuffer);\n } else {\n // Browsers without Web Crypto API, or insecure contexts (HTTP), fallback to CryptoJS\n // let decrypt: typeof CryptoJS.AES.decrypt;\n // let utf8: typeof CryptoJS.enc.Utf8;\n // try {\n // const [aes, encUtf8] = await Promise.all([import('crypto-js/aes'), import('crypto-js/enc-utf8')]);\n // decrypt = aes.decrypt;\n // utf8 = encUtf8.default;\n // } catch (error) {\n // console.error('Load \"crypto-js/aes\" error:', error);\n // throw error;\n // }\n // try {\n // const decrypted = decrypt(encryptedText, key);\n // return decrypted.toString(utf8);\n // } catch (error) {\n // console.error('Decryption error:', error);\n // throw error;\n // }\n return decryptWithCryptoJS(encryptedText, key);\n }\n }\n } catch (error) {\n console.error('Decryption error:', error);\n return '';\n }\n}\nexport async function encryptWithCryptoJS(text: string, key: string) {\n const [\n {\n default: {\n mode: { CBC },\n lib: { WordArray },\n },\n },\n { default: Pkcs7 },\n { default: Base64 },\n { default: Utf8 },\n { default: SHA256 },\n {\n default: { encrypt },\n },\n ] = await Promise.all([\n import('crypto-js/core.js'),\n import('crypto-js/pad-pkcs7.js'),\n import('crypto-js/enc-base64.js'),\n import('crypto-js/enc-utf8.js'),\n import('crypto-js/sha256.js'),\n import('crypto-js/aes.js'),\n ]);\n\n try {\n // Convert text and key to WordArray objects\n const wordArray = Utf8.parse(text);\n const keyArray = SHA256(key);\n const iv = WordArray.random(16);\n\n const encryptedBase64 = Base64.stringify(\n encrypt(wordArray, keyArray, {\n iv,\n mode: CBC,\n padding: Pkcs7,\n }).ciphertext\n );\n return `${Base64.stringify(iv)}:${encryptedBase64}`;\n } catch (error) {\n console.error('Encryption error:', error);\n throw error;\n }\n}\n\nexport async function decryptWithCryptoJS(encryptedText: string, key: string) {\n const [ivBase64, encryptedBase64] = encryptedText.split(':');\n\n const [\n {\n default: {\n mode: { CBC },\n },\n },\n { default: Pkcs7 },\n { default: Base64 },\n { default: Utf8 },\n { default: SHA256 },\n {\n default: { decrypt },\n },\n ] = await Promise.all([\n import('crypto-js/core.js'),\n import('crypto-js/pad-pkcs7.js'),\n import('crypto-js/enc-base64.js'),\n import('crypto-js/enc-utf8.js'),\n import('crypto-js/sha256.js'),\n import('crypto-js/aes.js'),\n ]);\n\n try {\n // Convert base64 strings to WordArray objects\n const iv = Base64.parse(ivBase64);\n // Derive key using SHA-256 (matching native implementation)\n const derivedKey = SHA256(key);\n const decrypted = decrypt(encryptedBase64, derivedKey, {\n iv,\n mode: CBC,\n padding: Pkcs7,\n });\n return decrypted.toString(Utf8);\n } catch (error) {\n console.error('Decryption error:', error);\n throw error;\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { base64ToString, stringToBase64 } from './base64';\nimport { random } from './math';\nimport { randomChars } from './string';\n\n/** Secret. No description provided */\nexport async function advancedEncrypt(plainText: string, key: string) {\n const k1 = randomChars(36);\n let e = await encryptAES(plainText, k1);\n const b = stringToBase64(k1);\n const l = b.length;\n const s = random(0, e.length);\n e = e.substring(0, s) + b + e.substring(s);\n const r = stringToBase64(`${s}-${l}`);\n const t = `${e}.${r}`;\n return encryptAES(t, key);\n}\n\n/** Secret. No description provided */\nexport async function advancedDecrypt(encryptedText: string, key: string) {\n const decrypted = await decryptAES(encryptedText, key);\n const [e, r] = decrypted.split('.');\n const [s, l] = base64ToString(r).split('-').map(Number);\n const k1 = base64ToString(e.substring(s, s + l));\n return decryptAES(e.substring(0, s) + e.substring(s + l), k1);\n}\n\n/**\n * **EN**: General AES encryption function - supports both Node.js and browser environments\n *\n * **CN**: 通用 AES 加密函数 - 同时支持 Node.js 和浏览器环境\n *\n * @param {string} text The text to be encrypted | 要加密的文本\n * @param {string} key The encryption key | 加密密钥\n *\n * @returns {Promise<string>} The encrypted text | 加密后的文本\n */\nexport async function encryptAES(text: string, key: string): Promise<string> {\n const isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;\n\n if (isNode) {\n // Node.js\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const crypto = require('crypto');\n const derivedKey = crypto.createHash('sha256').update(key).digest();\n const iv = crypto.randomBytes(16);\n const cipher = crypto.createCipheriv('aes-256-cbc', derivedKey, iv);\n let encrypted = cipher.update(text, 'utf8', 'base64');\n encrypted += cipher.final('base64');\n return `${iv.toString('base64')}:${encrypted}`;\n } else {\n if (crypto.subtle) {\n // Browsers\n try {\n const iv = crypto.getRandomValues(new Uint8Array(16));\n const encoder = new TextEncoder();\n const keyData = encoder.encode(key);\n const hashBuffer = await crypto.subtle.digest('SHA-256', keyData);\n const cryptoKey = await crypto.subtle.importKey('raw', hashBuffer, { name: 'AES-CBC' }, false, ['encrypt']);\n const textBytes = encoder.encode(text);\n const encryptedBuffer = await crypto.subtle.encrypt({ name: 'AES-CBC', iv }, cryptoKey, textBytes);\n const ivBase64 = btoa(String.fromCharCode(...iv));\n const encryptedBase64 = btoa(String.fromCharCode(...new Uint8Array(encryptedBuffer)));\n return `${ivBase64}:${encryptedBase64}`;\n } catch (error) {\n console.error('Encryption error:', error);\n throw error;\n }\n } else {\n // let encrypt: typeof CryptoJS.AES.encrypt;\n // try {\n // const aes = await import('crypto-js/aes');\n // encrypt = aes.encrypt;\n // } catch (error) {\n // console.error('Load \"crypto-js/aes\" error:', error);\n // throw error;\n // }\n // try {\n // return encrypt(text, key).toString();\n // } catch (error) {\n // console.error('Encryption error:', error);\n // throw error;\n // }\n return encryptWithCryptoJS(text, key);\n }\n }\n}\n\n/**\n * **EN**: General AES decryption function - supports both Node.js and browser environments\n *\n * **CN**: 通用 AES 解密函数 - 同时支持 Node.js 和浏览器环境\n *\n * @param encryptedText The encrypted text (format: iv:encryptedContent, base64 encoded)\n * @param key The decryption key\n *\n * @returns The decrypted text\n */\nexport async function decryptAES(encryptedText: string, key: string): Promise<string> {\n const isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;\n try {\n const [ivBase64, encryptedBase64] = encryptedText.split(':');\n if (!ivBase64 || !encryptedBase64) {\n throw new Error('Invalid encrypted format');\n }\n if (isNode) {\n // Node.js\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const crypto = require('crypto');\n const iv = Buffer.from(ivBase64, 'base64');\n const encryptedBuffer = Buffer.from(encryptedBase64, 'base64');\n const derivedKey = crypto.createHash('sha256').update(key).digest();\n const decipher = crypto.createDecipheriv('aes-256-cbc', derivedKey, iv);\n let decrypted = decipher.update(encryptedBuffer);\n decrypted = Buffer.concat([decrypted, decipher.final()]);\n return decrypted.toString('utf8');\n } else {\n if (crypto.subtle) {\n // Browsers with Web Crypto API, in secure contexts (HTTPS)\n const iv = Uint8Array.from(atob(ivBase64), (c) => c.charCodeAt(0));\n const encryptedData = Uint8Array.from(atob(encryptedBase64), (c) => c.charCodeAt(0));\n const encoder = new TextEncoder();\n const keyData = encoder.encode(key);\n const hashBuffer = await crypto.subtle.digest('SHA-256', keyData);\n const cryptoKey = await crypto.subtle.importKey('raw', hashBuffer, { name: 'AES-CBC' }, false, ['decrypt']);\n const decryptedBuffer = await crypto.subtle.decrypt({ name: 'AES-CBC', iv }, cryptoKey, encryptedData);\n const decoder = new TextDecoder();\n return decoder.decode(decryptedBuffer);\n } else {\n // Browsers without Web Crypto API, or insecure contexts (HTTP), fallback to CryptoJS\n // let decrypt: typeof CryptoJS.AES.decrypt;\n // let utf8: typeof CryptoJS.enc.Utf8;\n // try {\n // const [aes, encUtf8] = await Promise.all([import('crypto-js/aes'), import('crypto-js/enc-utf8')]);\n // decrypt = aes.decrypt;\n // utf8 = encUtf8.default;\n // } catch (error) {\n // console.error('Load \"crypto-js/aes\" error:', error);\n // throw error;\n // }\n // try {\n // const decrypted = decrypt(encryptedText, key);\n // return decrypted.toString(utf8);\n // } catch (error) {\n // console.error('Decryption error:', error);\n // throw error;\n // }\n return decryptWithCryptoJS(encryptedText, key);\n }\n }\n } catch (error) {\n console.error('Decryption error:', error);\n return '';\n }\n}\nexport async function encryptWithCryptoJS(text: string, key: string) {\n const [\n {\n default: {\n mode: { CBC },\n lib: { WordArray },\n },\n },\n { default: Pkcs7 },\n { default: Base64 },\n { default: Utf8 },\n { default: SHA256 },\n {\n default: { encrypt },\n },\n ] = await Promise.all([\n import('crypto-js/core.js'),\n import('crypto-js/pad-pkcs7.js'),\n import('crypto-js/enc-base64.js'),\n import('crypto-js/enc-utf8.js'),\n import('crypto-js/sha256.js'),\n import('crypto-js/aes.js'),\n ]);\n\n try {\n // Convert text and key to WordArray objects\n const wordArray = Utf8.parse(text);\n const keyArray = SHA256(key);\n const iv = WordArray.random(16);\n\n const encryptedBase64 = Base64.stringify(\n encrypt(wordArray, keyArray, {\n iv,\n mode: CBC,\n padding: Pkcs7,\n }).ciphertext\n );\n return `${Base64.stringify(iv)}:${encryptedBase64}`;\n } catch (error) {\n console.error('Encryption error:', error);\n throw error;\n }\n}\n\nexport async function decryptWithCryptoJS(encryptedText: string, key: string) {\n const [ivBase64, encryptedBase64] = encryptedText.split(':');\n\n const [\n { default: Base64 },\n { default: Utf8 },\n {\n default: {\n mode: { CBC },\n },\n },\n { default: Pkcs7 },\n { default: SHA256 },\n {\n default: { decrypt },\n },\n ] = await Promise.all([\n import('crypto-js/enc-base64.js'),\n import('crypto-js/enc-utf8.js'),\n import('crypto-js/core.js'),\n import('crypto-js/pad-pkcs7.js'),\n import('crypto-js/sha256.js'),\n import('crypto-js/aes.js'),\n ]);\n\n try {\n // Convert base64 strings to WordArray objects\n const iv = Base64.parse(ivBase64);\n // Derive key using SHA-256 (matching native implementation)\n const derivedKey = SHA256(key);\n const decrypted = decrypt(encryptedBase64, derivedKey, {\n iv,\n mode: CBC,\n padding: Pkcs7,\n });\n return decrypted.toString(Utf8);\n } catch (error) {\n console.error('Decryption error:', error);\n throw error;\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["crypto"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiny-codes/react-easy",
3
- "version": "1.4.11",
3
+ "version": "1.4.13",
4
4
  "description": "Simplify React and AntDesign development with practical components and hooks",
5
5
  "keywords": [
6
6
  "react",