wiki-data.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import CacheableObject from '#cacheable-object';
  2. import find from '#find';
  3. import {withEntries} from '#sugar';
  4. import Thing from '#thing';
  5. import thingConstructors from '#things';
  6. import {linkWikiDataArrays} from '#yaml';
  7. export function linkAndBindWikiData(wikiData, {
  8. inferAlbumsOwnTrackData = true,
  9. } = {}) {
  10. function customLinkWikiDataArrays(wikiData, options = {}) {
  11. linkWikiDataArrays(
  12. (options.XXX_decacheWikiData
  13. ? withEntries(wikiData, entries => entries
  14. .map(([key, value]) => [key, value.slice()]))
  15. : wikiData));
  16. }
  17. customLinkWikiDataArrays(wikiData);
  18. return {
  19. // Mutate to make the below functions aware of new data objects, or of
  20. // reordering the existing ones. Don't mutate arrays such as trackData
  21. // in-place; assign completely new arrays to this wikiData object instead.
  22. wikiData,
  23. // Use this after you've mutated wikiData to assign new data arrays.
  24. // It'll automatically relink everything on wikiData so all the objects
  25. // are caught up to date.
  26. linkWikiDataArrays:
  27. customLinkWikiDataArrays
  28. .bind(null, wikiData),
  29. // Use this if you HAVEN'T mutated wikiData and just need to decache
  30. // indirect dependencies on exposed properties of other data objects.
  31. //
  32. // XXX_decacheWikiData option should be used specifically to mark points
  33. // where you *aren't* replacing any of the arrays under wikiData with
  34. // new values, and are using linkWikiDataArrays to instead "decache" data
  35. // properties which depend on any of them. It's currently not possible for
  36. // a CacheableObject to depend directly on the value of a property exposed
  37. // on some other CacheableObject, so when those values change, you have to
  38. // manually decache before the object will realize its cache isn't valid
  39. // anymore.
  40. //
  41. // The previous implementation for this involved overwriting the relevant
  42. // wikiData properties with null, then replacing it with the original
  43. // array, which effectively cleared a CacheableObject cache. But it isn't
  44. // enough to clear other caches that depend on the identity of wikiData
  45. // arrays, such as withReverseReferenceList, so now it replaces with fresh
  46. // copies of the data arrays instead; the original identities don't get
  47. // reused.
  48. XXX_decacheWikiData:
  49. customLinkWikiDataArrays
  50. .bind(null, wikiData, {XXX_decacheWikiData: true}),
  51. };
  52. }
  53. export function stubWikiData() {
  54. return {
  55. albumData: [],
  56. artistData: [],
  57. artTagData: [],
  58. flashData: [],
  59. flashActData: [],
  60. flashSideData: [],
  61. groupData: [],
  62. groupCategoryData: [],
  63. newsData: [],
  64. staticPageData: [],
  65. trackData: [],
  66. trackSectionData: [],
  67. };
  68. }
  69. export function stubThing(wikiData, constructor, properties = {}) {
  70. const thing = Reflect.construct(constructor, []);
  71. Object.assign(thing, properties);
  72. const wikiDataSpec = {
  73. Album: 'albumData',
  74. Artist: 'artistData',
  75. ArtTag: 'artTagData',
  76. Flash: 'flashData',
  77. FlashAct: 'flashActData',
  78. FlashSide: 'flashSideData',
  79. Group: 'groupData',
  80. GroupCategory: 'groupCategoryData',
  81. NewsEntry: 'newsData',
  82. StaticPage: 'staticPageData',
  83. Track: 'trackData',
  84. TrackSection: 'trackSectionData',
  85. };
  86. const wikiDataMap =
  87. new Map(
  88. Object.entries(wikiDataSpec)
  89. .map(([thingKey, wikiDataKey]) => [
  90. thingConstructors[thingKey],
  91. wikiData[wikiDataKey],
  92. ]));
  93. const wikiDataArray =
  94. wikiDataMap.get(constructor);
  95. wikiDataArray.push(thing);
  96. return thing;
  97. }
  98. export function stubTrackAndAlbum(wikiData, trackDirectory = null, albumDirectory = null) {
  99. const {Track, TrackSection, Album} = thingConstructors;
  100. const track =
  101. stubThing(wikiData, Track, {directory: trackDirectory});
  102. const section =
  103. stubThing(wikiData, TrackSection, {tracks: [track]});
  104. const album =
  105. stubThing(wikiData, Album, {directory: albumDirectory, trackSections: [section]});
  106. return {track, album, section};
  107. }
  108. export function stubArtistAndContribs(wikiData, artistName = `Test Artist`) {
  109. const {Artist} = thingConstructors;
  110. const artist =
  111. stubThing(wikiData, Artist, {name: artistName});
  112. const contribs =
  113. [{artist: artistName, annotation: null}];
  114. const badContribs =
  115. [{artist: `Figment of Your Imagination`, annotation: null}];
  116. return {artist, contribs, badContribs};
  117. }
  118. export function stubFlashAndAct(wikiData, flashDirectory = null) {
  119. const {Flash, FlashAct} = thingConstructors;
  120. const flash =
  121. stubThing(wikiData, Flash, {directory: flashDirectory});
  122. const flashAct =
  123. stubThing(wikiData, FlashAct, {
  124. flashes: [Thing.getReference(flash)],
  125. });
  126. return {flash, flashAct};
  127. }