taglib-wasm 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/index.browser.js +54 -12
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +2 -4
  5. package/dist/simple.browser.js +113 -13
  6. package/dist/src/constants/properties.d.ts +14 -0
  7. package/dist/src/constants/properties.d.ts.map +1 -1
  8. package/dist/src/constants/specialized-properties.d.ts +14 -0
  9. package/dist/src/constants/specialized-properties.d.ts.map +1 -1
  10. package/dist/src/constants/specialized-properties.js +22 -0
  11. package/dist/src/folder-api/folder-operations.d.ts +2 -30
  12. package/dist/src/folder-api/folder-operations.d.ts.map +1 -1
  13. package/dist/src/folder-api/folder-operations.js +1 -36
  14. package/dist/src/folder-api/index.d.ts +2 -2
  15. package/dist/src/folder-api/index.d.ts.map +1 -1
  16. package/dist/src/folder-api/index.js +2 -7
  17. package/dist/src/folder-api/types.d.ts +0 -21
  18. package/dist/src/folder-api/types.d.ts.map +1 -1
  19. package/dist/src/folder-api/types.js +1 -13
  20. package/dist/src/simple/batch-operations.d.ts +74 -2
  21. package/dist/src/simple/batch-operations.d.ts.map +1 -1
  22. package/dist/src/simple/batch-operations.js +66 -6
  23. package/dist/src/simple/index.d.ts +2 -2
  24. package/dist/src/simple/index.d.ts.map +1 -1
  25. package/dist/src/simple/index.js +6 -2
  26. package/dist/src/simple/tag-operations.d.ts +5 -1
  27. package/dist/src/simple/tag-operations.d.ts.map +1 -1
  28. package/dist/src/simple/tag-operations.js +5 -2
  29. package/dist/src/types/metadata-mappings.d.ts +1 -1
  30. package/dist/src/types/metadata-mappings.d.ts.map +1 -1
  31. package/dist/src/types/metadata-mappings.js +5 -0
  32. package/dist/src/types/tags.d.ts +13 -0
  33. package/dist/src/types/tags.d.ts.map +1 -1
  34. package/dist/src/utils/tag-mapping.d.ts +9 -1
  35. package/dist/src/utils/tag-mapping.d.ts.map +1 -1
  36. package/dist/src/utils/tag-mapping.js +22 -5
  37. package/dist/src/version.d.ts +1 -1
  38. package/dist/src/version.js +1 -1
  39. package/dist/taglib-wasi.wasm +0 -0
  40. package/dist/taglib-web.wasm +0 -0
  41. package/package.json +1 -1
@@ -1387,6 +1387,28 @@ var init_specialized_properties = __esm({
1387
1387
  mp4: "----:com.apple.iTunes:MusicBrainz Album Type"
1388
1388
  }
1389
1389
  },
1390
+ releaseCountry: {
1391
+ key: "RELEASECOUNTRY",
1392
+ description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY",
1393
+ type: "string",
1394
+ supportedFormats: [
1395
+ "ID3v2",
1396
+ "MP4",
1397
+ "Vorbis",
1398
+ "APE",
1399
+ "ASF",
1400
+ "Matroska",
1401
+ "WAV"
1402
+ ],
1403
+ mappings: {
1404
+ id3v2: {
1405
+ frame: "TXXX",
1406
+ description: "MusicBrainz Album Release Country"
1407
+ },
1408
+ vorbis: "RELEASECOUNTRY",
1409
+ mp4: "----:com.apple.iTunes:MusicBrainz Album Release Country"
1410
+ }
1411
+ },
1390
1412
  itunesAdvisory: {
1391
1413
  key: "ITUNESADVISORY",
1392
1414
  description: "Content advisory in the ITUNESADVISORY convention ('1' = explicit, '2' = clean, '0' = unspecified). On MP4 the value is stored in the native rtng atom and surfaced here. The typed tri-state lives on ExtendedTag.advisory; aliases CONTENTADVISORY and EXPLICIT resolve here",
@@ -2765,8 +2787,9 @@ var init_mirror_fields = __esm({
2765
2787
  });
2766
2788
 
2767
2789
  // src/utils/tag-mapping.ts
2768
- function readExtendedTag(audioFile) {
2769
- const tag = mapPropertiesToExtendedTag(audioFile.properties());
2790
+ function readExtendedTag(audioFile, includeProperties) {
2791
+ const props = audioFile.properties();
2792
+ const tag = mapPropertiesToExtendedTag(props);
2770
2793
  const pictures = audioFile.getPictures();
2771
2794
  if (pictures.length > 0) tag.pictures = pictures;
2772
2795
  const ratings = audioFile.getRatings();
@@ -2781,6 +2804,18 @@ function readExtendedTag(audioFile) {
2781
2804
  if (bextData !== void 0) tag.bextData = bextData;
2782
2805
  const ixml = audioFile.getIxml();
2783
2806
  if (ixml !== void 0) tag.ixml = ixml;
2807
+ if (includeProperties !== void 0 && includeProperties.length > 0) {
2808
+ const extraProperties = {};
2809
+ for (const wireKey of includeProperties) {
2810
+ const values = props[fromTagLibKey(wireKey)]?.filter((v) => v !== "");
2811
+ if (values !== void 0 && values.length > 0) {
2812
+ extraProperties[wireKey] = values;
2813
+ }
2814
+ }
2815
+ if (Object.keys(extraProperties).length > 0) {
2816
+ tag.extraProperties = extraProperties;
2817
+ }
2818
+ }
2784
2819
  return tag;
2785
2820
  }
2786
2821
  function mapPropertiesToExtendedTag(props) {
@@ -2844,14 +2879,16 @@ function mapPropertiesToExtendedTag(props) {
2844
2879
  }
2845
2880
  return tag;
2846
2881
  }
2847
- function mergeTagUpdates(file, tags) {
2848
- const currentProps = file.properties();
2882
+ function mergeTagUpdatesInto(currentProps, tags) {
2849
2883
  const newProps = normalizeTagInput(tags);
2850
2884
  reconcilePairFields(currentProps, newProps, tags);
2851
2885
  if (newProps.date !== void 0 || newProps.year !== void 0) {
2852
2886
  currentProps.YEAR = [];
2853
2887
  }
2854
- file.setProperties({ ...currentProps, ...newProps });
2888
+ return { ...currentProps, ...newProps };
2889
+ }
2890
+ function mergeTagUpdates(file, tags) {
2891
+ file.setProperties(mergeTagUpdatesInto(file.properties(), tags));
2855
2892
  }
2856
2893
  function reconcilePairFields(currentProps, newProps, input) {
2857
2894
  const pairs = [
@@ -2900,6 +2937,7 @@ function normalizeTagInput(input) {
2900
2937
  }
2901
2938
  for (const [field, val] of Object.entries(input)) {
2902
2939
  if (BASIC_FIELDS.has(field) || val === void 0) continue;
2940
+ if (field === "extraProperties") continue;
2903
2941
  if (field === "compilation") {
2904
2942
  props[field] = [val ? "1" : "0"];
2905
2943
  } else if (field === "advisory") {
@@ -2966,7 +3004,7 @@ var VERSION;
2966
3004
  var init_version = __esm({
2967
3005
  "src/version.ts"() {
2968
3006
  "use strict";
2969
- VERSION = "2.1.0";
3007
+ VERSION = "2.2.1";
2970
3008
  }
2971
3009
  });
2972
3010
 
@@ -3321,8 +3359,11 @@ async function withAudioFileSaveToFile(file, fn) {
3321
3359
  }
3322
3360
 
3323
3361
  // src/simple/tag-operations.ts
3324
- async function readTags(file) {
3325
- return withAudioFile(file, (audioFile) => readExtendedTag(audioFile));
3362
+ async function readTags(file, options = {}) {
3363
+ return withAudioFile(
3364
+ file,
3365
+ (audioFile) => readExtendedTag(audioFile, options.includeProperties)
3366
+ );
3326
3367
  }
3327
3368
  async function applyTags(file, tags) {
3328
3369
  return withAudioFileSave(file, (audioFile) => {
@@ -3453,6 +3494,7 @@ async function readPictureMetadata(file) {
3453
3494
  // src/simple/batch-operations.ts
3454
3495
  init_audio_formats();
3455
3496
  init_errors2();
3497
+ init_properties();
3456
3498
  init_tag_mapping();
3457
3499
  async function executeBatch(files, options, processor) {
3458
3500
  if (files.length === 0) return { items: [], duration: 0 };
@@ -3500,7 +3542,7 @@ async function readTagsBatch(files, options = {}) {
3500
3542
  return executeBatch(
3501
3543
  files,
3502
3544
  options,
3503
- (audioFile) => readExtendedTag(audioFile)
3545
+ (audioFile) => readExtendedTag(audioFile, options.includeProperties)
3504
3546
  );
3505
3547
  }
3506
3548
  async function readPropertiesBatch(files, options = {}) {
@@ -3529,7 +3571,7 @@ function extractDynamics(audioFile) {
3529
3571
  if (appleSoundCheck) dynamics.appleSoundCheck = appleSoundCheck;
3530
3572
  return Object.keys(dynamics).length > 0 ? dynamics : void 0;
3531
3573
  }
3532
- async function readMetadata(file) {
3574
+ async function readMetadata(file, options = {}) {
3533
3575
  const taglib = await getTagLib();
3534
3576
  const audioFile = await taglib.open(file);
3535
3577
  try {
@@ -3550,7 +3592,7 @@ async function readMetadata(file) {
3550
3592
  }
3551
3593
  const dynamics = extractDynamics(audioFile);
3552
3594
  return {
3553
- tags: readExtendedTag(audioFile),
3595
+ tags: readExtendedTag(audioFile, options.includeProperties),
3554
3596
  properties: audioFile.audioProperties(),
3555
3597
  hasCoverArt: audioFile.getPictures().length > 0,
3556
3598
  ...dynamics !== void 0 ? { dynamics } : {}
@@ -3563,7 +3605,7 @@ async function readMetadataBatch(files, options = {}) {
3563
3605
  return executeBatch(files, options, (audioFile) => {
3564
3606
  const dynamics = extractDynamics(audioFile);
3565
3607
  return {
3566
- tags: readExtendedTag(audioFile),
3608
+ tags: readExtendedTag(audioFile, options.includeProperties),
3567
3609
  properties: audioFile.audioProperties(),
3568
3610
  hasCoverArt: audioFile.getPictures().length > 0,
3569
3611
  ...dynamics !== void 0 ? { dynamics } : {}
package/dist/index.d.ts CHANGED
@@ -43,7 +43,7 @@ export { addPicture, applyCoverArt, applyPictures, applyTags, applyTagsToFile, t
43
43
  export { FormatMappings, getAllProperties, getAllPropertyKeys, getPropertiesByFormat, getPropertyMetadata, isValidProperty, PROPERTIES, propertyValue, propertyValues, } from "./src/constants.js";
44
44
  export type { PropertyMetadata } from "./src/constants/property-types.js";
45
45
  export { copyCoverArt, exportAllPictures, exportCoverArt, exportPictureByType, findCoverArtFiles, importCoverArt, importPictureWithType, loadPictureFromFile, savePictureToFile, } from "./src/file-utils/index.js";
46
- export { type AlbumDisc, type AlbumGroup, type AlbumGroupingResult, type AlbumGroupItem, type AlbumGroupKey, type AudioDynamics, type AudioFileMetadata, type DiscConfidence, type DiscFolderInfo, discFolderInfo, type DuplicateGroup, exportFolderMetadata, findDuplicates, type FolderScanItem, type FolderScanOptions, type FolderScanResult, type FolderUpdateItem, type FolderUpdateResult, groupAlbums, type GroupAlbumsOptions, scanFolder, scanForAlbums, type ScanForAlbumsOptions, updateFolderTags, } from "./src/folder-api/index.js";
46
+ export { type AlbumDisc, type AlbumGroup, type AlbumGroupingResult, type AlbumGroupItem, type AlbumGroupKey, type AudioDynamics, type AudioFileMetadata, type DiscConfidence, type DiscFolderInfo, discFolderInfo, type DuplicateGroup, exportFolderMetadata, findDuplicates, type FolderScanItem, type FolderScanOptions, type FolderScanResult, groupAlbums, type GroupAlbumsOptions, scanFolder, scanForAlbums, type ScanForAlbumsOptions, } from "./src/folder-api/index.js";
47
47
  export { canvasToPicture, createPictureDownloadURL, createPictureGallery, dataURLToPicture, displayPicture, imageFileToPicture, pictureToDataURL, setCoverArtFromCanvas, } from "./src/web-utils/index.js";
48
48
  export type { AudioCodec, AudioFileInput, AudioProperties, BitrateControlMode, BroadcastAudioExtension, Chapter, ContainerFormat, ExtendedTag, FieldMapping, FileType, NamedAudioInput, OpenOptions, Picture, PictureType, PropertyMap, SetChaptersOptions, Tag, TagInput, } from "./src/types.js";
49
49
  export { BITRATE_CONTROL_MODE_NAMES, BITRATE_CONTROL_MODE_VALUES, PICTURE_TYPE_NAMES, PICTURE_TYPE_VALUES, } from "./src/types.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -75,8 +75,7 @@ import {
75
75
  findDuplicates,
76
76
  groupAlbums,
77
77
  scanFolder,
78
- scanForAlbums,
79
- updateFolderTags
78
+ scanForAlbums
80
79
  } from "./src/folder-api/index.js";
81
80
  import {
82
81
  canvasToPicture,
@@ -180,6 +179,5 @@ export {
180
179
  scanFolder,
181
180
  scanForAlbums,
182
181
  setBufferMode,
183
- setCoverArtFromCanvas,
184
- updateFolderTags
182
+ setCoverArtFromCanvas
185
183
  };
@@ -1319,6 +1319,28 @@ var init_specialized_properties = __esm({
1319
1319
  mp4: "----:com.apple.iTunes:MusicBrainz Album Type"
1320
1320
  }
1321
1321
  },
1322
+ releaseCountry: {
1323
+ key: "RELEASECOUNTRY",
1324
+ description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY",
1325
+ type: "string",
1326
+ supportedFormats: [
1327
+ "ID3v2",
1328
+ "MP4",
1329
+ "Vorbis",
1330
+ "APE",
1331
+ "ASF",
1332
+ "Matroska",
1333
+ "WAV"
1334
+ ],
1335
+ mappings: {
1336
+ id3v2: {
1337
+ frame: "TXXX",
1338
+ description: "MusicBrainz Album Release Country"
1339
+ },
1340
+ vorbis: "RELEASECOUNTRY",
1341
+ mp4: "----:com.apple.iTunes:MusicBrainz Album Release Country"
1342
+ }
1343
+ },
1322
1344
  itunesAdvisory: {
1323
1345
  key: "ITUNESADVISORY",
1324
1346
  description: "Content advisory in the ITUNESADVISORY convention ('1' = explicit, '2' = clean, '0' = unspecified). On MP4 the value is stored in the native rtng atom and surfaced here. The typed tri-state lives on ExtendedTag.advisory; aliases CONTENTADVISORY and EXPLICIT resolve here",
@@ -2697,8 +2719,9 @@ var init_mirror_fields = __esm({
2697
2719
  });
2698
2720
 
2699
2721
  // src/utils/tag-mapping.ts
2700
- function readExtendedTag(audioFile) {
2701
- const tag = mapPropertiesToExtendedTag(audioFile.properties());
2722
+ function readExtendedTag(audioFile, includeProperties) {
2723
+ const props = audioFile.properties();
2724
+ const tag = mapPropertiesToExtendedTag(props);
2702
2725
  const pictures = audioFile.getPictures();
2703
2726
  if (pictures.length > 0) tag.pictures = pictures;
2704
2727
  const ratings = audioFile.getRatings();
@@ -2713,6 +2736,18 @@ function readExtendedTag(audioFile) {
2713
2736
  if (bextData !== void 0) tag.bextData = bextData;
2714
2737
  const ixml = audioFile.getIxml();
2715
2738
  if (ixml !== void 0) tag.ixml = ixml;
2739
+ if (includeProperties !== void 0 && includeProperties.length > 0) {
2740
+ const extraProperties = {};
2741
+ for (const wireKey of includeProperties) {
2742
+ const values = props[fromTagLibKey(wireKey)]?.filter((v) => v !== "");
2743
+ if (values !== void 0 && values.length > 0) {
2744
+ extraProperties[wireKey] = values;
2745
+ }
2746
+ }
2747
+ if (Object.keys(extraProperties).length > 0) {
2748
+ tag.extraProperties = extraProperties;
2749
+ }
2750
+ }
2716
2751
  return tag;
2717
2752
  }
2718
2753
  function mapPropertiesToExtendedTag(props) {
@@ -2776,14 +2811,16 @@ function mapPropertiesToExtendedTag(props) {
2776
2811
  }
2777
2812
  return tag;
2778
2813
  }
2779
- function mergeTagUpdates(file, tags) {
2780
- const currentProps = file.properties();
2814
+ function mergeTagUpdatesInto(currentProps, tags) {
2781
2815
  const newProps = normalizeTagInput(tags);
2782
2816
  reconcilePairFields(currentProps, newProps, tags);
2783
2817
  if (newProps.date !== void 0 || newProps.year !== void 0) {
2784
2818
  currentProps.YEAR = [];
2785
2819
  }
2786
- file.setProperties({ ...currentProps, ...newProps });
2820
+ return { ...currentProps, ...newProps };
2821
+ }
2822
+ function mergeTagUpdates(file, tags) {
2823
+ file.setProperties(mergeTagUpdatesInto(file.properties(), tags));
2787
2824
  }
2788
2825
  function reconcilePairFields(currentProps, newProps, input) {
2789
2826
  const pairs = [
@@ -2832,6 +2869,7 @@ function normalizeTagInput(input) {
2832
2869
  }
2833
2870
  for (const [field, val] of Object.entries(input)) {
2834
2871
  if (BASIC_FIELDS.has(field) || val === void 0) continue;
2872
+ if (field === "extraProperties") continue;
2835
2873
  if (field === "compilation") {
2836
2874
  props[field] = [val ? "1" : "0"];
2837
2875
  } else if (field === "advisory") {
@@ -2898,7 +2936,7 @@ var VERSION;
2898
2936
  var init_version = __esm({
2899
2937
  "src/version.ts"() {
2900
2938
  "use strict";
2901
- VERSION = "2.1.0";
2939
+ VERSION = "2.2.1";
2902
2940
  }
2903
2941
  });
2904
2942
 
@@ -3247,8 +3285,11 @@ async function withAudioFileSaveToFile(file, fn) {
3247
3285
  }
3248
3286
 
3249
3287
  // src/simple/tag-operations.ts
3250
- async function readTags(file) {
3251
- return withAudioFile(file, (audioFile) => readExtendedTag(audioFile));
3288
+ async function readTags(file, options = {}) {
3289
+ return withAudioFile(
3290
+ file,
3291
+ (audioFile) => readExtendedTag(audioFile, options.includeProperties)
3292
+ );
3252
3293
  }
3253
3294
  async function applyTags(file, tags) {
3254
3295
  return withAudioFileSave(file, (audioFile) => {
@@ -3379,6 +3420,7 @@ async function readPictureMetadata(file) {
3379
3420
  // src/simple/batch-operations.ts
3380
3421
  init_audio_formats();
3381
3422
  init_errors2();
3423
+ init_properties();
3382
3424
  init_tag_mapping();
3383
3425
  async function executeBatch(files, options, processor) {
3384
3426
  if (files.length === 0) return { items: [], duration: 0 };
@@ -3426,7 +3468,7 @@ async function readTagsBatch(files, options = {}) {
3426
3468
  return executeBatch(
3427
3469
  files,
3428
3470
  options,
3429
- (audioFile) => readExtendedTag(audioFile)
3471
+ (audioFile) => readExtendedTag(audioFile, options.includeProperties)
3430
3472
  );
3431
3473
  }
3432
3474
  async function readPropertiesBatch(files, options = {}) {
@@ -3455,7 +3497,7 @@ function extractDynamics(audioFile) {
3455
3497
  if (appleSoundCheck) dynamics.appleSoundCheck = appleSoundCheck;
3456
3498
  return Object.keys(dynamics).length > 0 ? dynamics : void 0;
3457
3499
  }
3458
- async function readMetadata(file) {
3500
+ async function readMetadata(file, options = {}) {
3459
3501
  const taglib = await getTagLib();
3460
3502
  const audioFile = await taglib.open(file);
3461
3503
  try {
@@ -3476,7 +3518,7 @@ async function readMetadata(file) {
3476
3518
  }
3477
3519
  const dynamics = extractDynamics(audioFile);
3478
3520
  return {
3479
- tags: readExtendedTag(audioFile),
3521
+ tags: readExtendedTag(audioFile, options.includeProperties),
3480
3522
  properties: audioFile.audioProperties(),
3481
3523
  hasCoverArt: audioFile.getPictures().length > 0,
3482
3524
  ...dynamics !== void 0 ? { dynamics } : {}
@@ -3489,13 +3531,69 @@ async function readMetadataBatch(files, options = {}) {
3489
3531
  return executeBatch(files, options, (audioFile) => {
3490
3532
  const dynamics = extractDynamics(audioFile);
3491
3533
  return {
3492
- tags: readExtendedTag(audioFile),
3534
+ tags: readExtendedTag(audioFile, options.includeProperties),
3493
3535
  properties: audioFile.audioProperties(),
3494
3536
  hasCoverArt: audioFile.getPictures().length > 0,
3495
3537
  ...dynamics !== void 0 ? { dynamics } : {}
3496
3538
  };
3497
3539
  });
3498
3540
  }
3541
+ function entryPath(entry) {
3542
+ return typeof entry === "string" ? entry : entry.path;
3543
+ }
3544
+ async function executeWriteBatch(entries, options, writer) {
3545
+ if (entries.length === 0) return { items: [], duration: 0 };
3546
+ await getTagLib();
3547
+ const startTime = Date.now();
3548
+ const { concurrency = 4, continueOnError = true, onProgress, signal } = options;
3549
+ const items = new Array(entries.length);
3550
+ let processed = 0;
3551
+ const total = entries.length;
3552
+ for (let i = 0; i < entries.length; i += concurrency) {
3553
+ signal?.throwIfAborted();
3554
+ const chunk = entries.slice(i, i + concurrency);
3555
+ const chunkPromises = chunk.map(async (entry, idx) => {
3556
+ const index = i + idx;
3557
+ const path = entryPath(entry);
3558
+ try {
3559
+ await writer(path);
3560
+ items[index] = { status: "ok", path, data: void 0 };
3561
+ } catch (error) {
3562
+ const err = error instanceof Error ? error : new Error(String(error));
3563
+ items[index] = { status: "error", path, error: err };
3564
+ if (!continueOnError) throw err;
3565
+ }
3566
+ processed++;
3567
+ onProgress?.(processed, total, path);
3568
+ });
3569
+ await Promise.all(chunkPromises);
3570
+ }
3571
+ return { items, duration: Date.now() - startTime };
3572
+ }
3573
+ async function writeTagsBatch(updates, options = {}) {
3574
+ const byPath = new Map(updates.map((u) => [u.path, u]));
3575
+ return executeWriteBatch(
3576
+ updates,
3577
+ options,
3578
+ (path) => withAudioFileSaveToFile(path, (audioFile) => {
3579
+ const update = byPath.get(path);
3580
+ const merged = update.tags !== void 0 ? mergeTagUpdatesInto(audioFile.properties(), update.tags) : audioFile.properties();
3581
+ if (update.properties !== void 0) {
3582
+ for (const [key, values] of Object.entries(update.properties)) {
3583
+ merged[fromTagLibKey(key)] = values;
3584
+ }
3585
+ }
3586
+ audioFile.setProperties(merged);
3587
+ })
3588
+ );
3589
+ }
3590
+ async function editTagsBatch(files, mutator, options = {}) {
3591
+ return executeWriteBatch(
3592
+ files,
3593
+ options,
3594
+ (path) => withAudioFileSaveToFile(path, (audioFile) => mutator(audioFile, path))
3595
+ );
3596
+ }
3499
3597
 
3500
3598
  // src/simple/index.ts
3501
3599
  init_types2();
@@ -3509,6 +3607,7 @@ export {
3509
3607
  applyTagsToFile,
3510
3608
  clearPictures,
3511
3609
  clearTags,
3610
+ editTagsBatch,
3512
3611
  findPictureByType,
3513
3612
  getTagLib,
3514
3613
  isValidAudioFile,
@@ -3523,5 +3622,6 @@ export {
3523
3622
  readTags,
3524
3623
  readTagsBatch,
3525
3624
  replacePictureByType,
3526
- setBufferMode
3625
+ setBufferMode,
3626
+ writeTagsBatch
3527
3627
  };
@@ -311,6 +311,20 @@ export declare const PROPERTIES: {
311
311
  readonly mp4: "----:com.apple.iTunes:MusicBrainz Album Type";
312
312
  };
313
313
  };
314
+ readonly releaseCountry: {
315
+ readonly key: "RELEASECOUNTRY";
316
+ readonly description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY";
317
+ readonly type: "string";
318
+ readonly supportedFormats: readonly ["ID3v2", "MP4", "Vorbis", "APE", "ASF", "Matroska", "WAV"];
319
+ readonly mappings: {
320
+ readonly id3v2: {
321
+ readonly frame: "TXXX";
322
+ readonly description: "MusicBrainz Album Release Country";
323
+ };
324
+ readonly vorbis: "RELEASECOUNTRY";
325
+ readonly mp4: "----:com.apple.iTunes:MusicBrainz Album Release Country";
326
+ };
327
+ };
314
328
  readonly itunesAdvisory: {
315
329
  readonly key: "ITUNESADVISORY";
316
330
  readonly description: "Content advisory in the ITUNESADVISORY convention ('1' = explicit, '2' = clean, '0' = unspecified). On MP4 the value is stored in the native rtng atom and surfaced here. The typed tri-state lives on ExtendedTag.advisory; aliases CONTENTADVISORY and EXPLICIT resolve here";
@@ -1 +1 @@
1
- {"version":3,"file":"properties.d.ts","sourceRoot":"","sources":["../../../src/constants/properties.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKb,CAAC;AAEX;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,UAAU,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,WAAW,IAC7C,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,QAAQ,GAAG,MAAM,GAClD,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,QAAQ,GAAG,MAAM,GACtD,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,SAAS,GAAG,OAAO,GACxD,MAAM,CAAC;AAkDb,mGAAmG;AACnG,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAsDD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAOzE;AAED,mGAAmG;AACnG,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GACrB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CASnB;AAGD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"properties.d.ts","sourceRoot":"","sources":["../../../src/constants/properties.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKb,CAAC;AAEX;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,UAAU,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,WAAW,IAC7C,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,QAAQ,GAAG,MAAM,GAClD,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,QAAQ,GAAG,MAAM,GACtD,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,SAAS,GAAG,OAAO,GACxD,MAAM,CAAC;AAkDb,mGAAmG;AACnG,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAsDD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAOzE;AAED,mGAAmG;AACnG,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GACrB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CASnB;AAGD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -73,6 +73,20 @@ export declare const SPECIALIZED_PROPERTIES: {
73
73
  readonly mp4: "----:com.apple.iTunes:MusicBrainz Album Type";
74
74
  };
75
75
  };
76
+ readonly releaseCountry: {
77
+ readonly key: "RELEASECOUNTRY";
78
+ readonly description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY";
79
+ readonly type: "string";
80
+ readonly supportedFormats: readonly ["ID3v2", "MP4", "Vorbis", "APE", "ASF", "Matroska", "WAV"];
81
+ readonly mappings: {
82
+ readonly id3v2: {
83
+ readonly frame: "TXXX";
84
+ readonly description: "MusicBrainz Album Release Country";
85
+ };
86
+ readonly vorbis: "RELEASECOUNTRY";
87
+ readonly mp4: "----:com.apple.iTunes:MusicBrainz Album Release Country";
88
+ };
89
+ };
76
90
  readonly itunesAdvisory: {
77
91
  readonly key: "ITUNESADVISORY";
78
92
  readonly description: "Content advisory in the ITUNESADVISORY convention ('1' = explicit, '2' = clean, '0' = unspecified). On MP4 the value is stored in the native rtng atom and surfaced here. The typed tri-state lives on ExtendedTag.advisory; aliases CONTENTADVISORY and EXPLICIT resolve here";
@@ -1 +1 @@
1
- {"version":3,"file":"specialized-properties.d.ts","sourceRoot":"","sources":["../../../src/constants/specialized-properties.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAwLjC;;;;;;;;OAQG;;;;;;;;;;;;;;;CAYK,CAAC"}
1
+ {"version":3,"file":"specialized-properties.d.ts","sourceRoot":"","sources":["../../../src/constants/specialized-properties.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA+MjC;;;;;;;;OAQG;;;;;;;;;;;;;;;CAYK,CAAC"}
@@ -62,6 +62,28 @@ const SPECIALIZED_PROPERTIES = {
62
62
  mp4: "----:com.apple.iTunes:MusicBrainz Album Type"
63
63
  }
64
64
  },
65
+ releaseCountry: {
66
+ key: "RELEASECOUNTRY",
67
+ description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY",
68
+ type: "string",
69
+ supportedFormats: [
70
+ "ID3v2",
71
+ "MP4",
72
+ "Vorbis",
73
+ "APE",
74
+ "ASF",
75
+ "Matroska",
76
+ "WAV"
77
+ ],
78
+ mappings: {
79
+ id3v2: {
80
+ frame: "TXXX",
81
+ description: "MusicBrainz Album Release Country"
82
+ },
83
+ vorbis: "RELEASECOUNTRY",
84
+ mp4: "----:com.apple.iTunes:MusicBrainz Album Release Country"
85
+ }
86
+ },
65
87
  itunesAdvisory: {
66
88
  key: "ITUNESADVISORY",
67
89
  description: "Content advisory in the ITUNESADVISORY convention ('1' = explicit, '2' = clean, '0' = unspecified). On MP4 the value is stored in the native rtng atom and surfaced here. The typed tri-state lives on ExtendedTag.advisory; aliases CONTENTADVISORY and EXPLICIT resolve here",
@@ -1,35 +1,7 @@
1
1
  /**
2
- * Folder-level operations: batch updates, duplicates, metadata export
2
+ * Folder-level operations: duplicates, metadata export
3
3
  */
4
- import type { TagInput } from "../simple/index.js";
5
- import type { DuplicateGroup, FolderScanOptions, FolderUpdateResult } from "./types.js";
6
- /**
7
- * Update metadata for multiple files in a folder
8
- *
9
- * @param updates - Array of objects containing path and tags to update
10
- * @param options - Update options
11
- * @returns Results of the update operation
12
- *
13
- * @example
14
- * ```typescript
15
- * const updates = [
16
- * { path: "/music/song1.mp3", tags: { artist: "New Artist" } },
17
- * { path: "/music/song2.mp3", tags: { album: "New Album" } }
18
- * ];
19
- *
20
- * const result = await updateFolderTags(updates);
21
- * const updated = result.items.filter((i) => i.status === "ok").length;
22
- * console.log(`Updated ${updated} files`);
23
- * ```
24
- */
25
- export declare function updateFolderTags(updates: Array<{
26
- path: string;
27
- tags: Partial<TagInput>;
28
- }>, options?: {
29
- continueOnError?: boolean;
30
- concurrency?: number;
31
- signal?: AbortSignal;
32
- }): Promise<FolderUpdateResult>;
4
+ import type { DuplicateGroup, FolderScanOptions } from "./types.js";
33
5
  /**
34
6
  * Find duplicate audio files based on metadata
35
7
  *
@@ -1 +1 @@
1
- {"version":3,"file":"folder-operations.d.ts","sourceRoot":"","sources":["../../../src/folder-api/folder-operations.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAO,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAKxD,OAAO,KAAK,EAEV,cAAc,EACd,iBAAiB,EAEjB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAGpB;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;CAAE,CAAC,EACzD,OAAO,GAAE;IACP,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;CACjB,GACL,OAAO,CAAC,kBAAkB,CAAC,CAgC7B;AAiBD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,cAAc,EAAE,CAAC,CAuB3B;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAoBf"}
1
+ {"version":3,"file":"folder-operations.d.ts","sourceRoot":"","sources":["../../../src/folder-api/folder-operations.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAEV,cAAc,EACd,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAiBpB;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,cAAc,EAAE,CAAC,CAuB3B;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAoBf"}
@@ -1,39 +1,5 @@
1
- import { applyTagsToFile } from "../simple/index.js";
2
1
  import { writeFileData } from "../utils/write.js";
3
- import { processBatch } from "./file-processors.js";
4
2
  import { scanFolder } from "./scan-operations.js";
5
- import { EMPTY_TAG } from "./types.js";
6
- async function updateFolderTags(updates, options = {}) {
7
- const startTime = Date.now();
8
- const { continueOnError = true, concurrency = 4, signal } = options;
9
- const items = [];
10
- const batchSize = concurrency * 10;
11
- for (let i = 0; i < updates.length; i += batchSize) {
12
- signal?.throwIfAborted();
13
- const batch = updates.slice(i, Math.min(i + batchSize, updates.length));
14
- const updateMap = new Map(batch.map((u) => [u.path, u]));
15
- await processBatch(
16
- batch.map((u) => u.path),
17
- async (path) => {
18
- const update = updateMap.get(path);
19
- try {
20
- await applyTagsToFile(update.path, update.tags);
21
- items.push({ status: "ok", path: update.path });
22
- } catch (error) {
23
- const err = error instanceof Error ? error : new Error(String(error));
24
- if (continueOnError) {
25
- items.push({ status: "error", path: update.path, error: err });
26
- } else {
27
- throw err;
28
- }
29
- }
30
- return { path, tags: EMPTY_TAG };
31
- },
32
- concurrency
33
- );
34
- }
35
- return { items, duration: Date.now() - startTime };
36
- }
37
3
  function buildCriteriaKey(tags, criteria) {
38
4
  const record = {};
39
5
  for (const field of criteria) {
@@ -84,6 +50,5 @@ async function exportFolderMetadata(folderPath, outputPath, options) {
84
50
  }
85
51
  export {
86
52
  exportFolderMetadata,
87
- findDuplicates,
88
- updateFolderTags
53
+ findDuplicates
89
54
  };
@@ -2,9 +2,9 @@
2
2
  * Batch folder operations for TagLib-Wasm
3
3
  * Provides APIs for scanning directories and processing multiple audio files
4
4
  */
5
- export type { AudioDynamics, AudioFileMetadata, DuplicateGroup, FolderScanItem, FolderScanOptions, FolderScanResult, FolderUpdateItem, FolderUpdateResult, } from "./types.js";
5
+ export type { AudioDynamics, AudioFileMetadata, DuplicateGroup, FolderScanItem, FolderScanOptions, FolderScanResult, } from "./types.js";
6
6
  export { scanFolder } from "./scan-operations.js";
7
- export { exportFolderMetadata, findDuplicates, updateFolderTags, } from "./folder-operations.js";
7
+ export { exportFolderMetadata, findDuplicates } from "./folder-operations.js";
8
8
  export { type AlbumDisc, type AlbumGroup, type AlbumGroupingResult, type AlbumGroupItem, type AlbumGroupKey, type DiscConfidence, type DiscFolderInfo, discFolderInfo, groupAlbums, type GroupAlbumsOptions, } from "./group-albums.js";
9
9
  export { scanForAlbums, type ScanForAlbumsOptions } from "./scan-for-albums.js";
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/folder-api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,cAAc,EACd,WAAW,EACX,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/folder-api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,EACL,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,cAAc,EACd,WAAW,EACX,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,9 +1,5 @@
1
1
  import { scanFolder } from "./scan-operations.js";
2
- import {
3
- exportFolderMetadata,
4
- findDuplicates,
5
- updateFolderTags
6
- } from "./folder-operations.js";
2
+ import { exportFolderMetadata, findDuplicates } from "./folder-operations.js";
7
3
  import {
8
4
  discFolderInfo,
9
5
  groupAlbums
@@ -15,6 +11,5 @@ export {
15
11
  findDuplicates,
16
12
  groupAlbums,
17
13
  scanFolder,
18
- scanForAlbums,
19
- updateFolderTags
14
+ scanForAlbums
20
15
  };