coh-content-db 2.0.0-rc.10 → 2.0.0-rc.12

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.
@@ -1,5 +1,7 @@
1
1
  name: Build
2
- on: push
2
+ on:
3
+ push:
4
+ branches: '*'
3
5
  jobs:
4
6
  build:
5
7
  runs-on: ubuntu-latest
package/CHANGELOG.md CHANGED
@@ -5,12 +5,13 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [2.0.0-rc.10] - 2025-04-16
8
+ ## [2.0.0-rc.12] - 2025-04-21
9
9
 
10
10
  ### Added
11
11
 
12
12
  - Introduced a simple indexing and search function for badge names, text, and acquisition info.
13
13
  - Enabled formal support for Missions and Contacts in badge requirements.
14
+ - Badges now require a `releaseDate`.
14
15
  - Added GitHub Actions for continuous integration (CI).
15
16
  - Included `eslint` for linting.
16
17
  - Added `jest` for unit testing.
@@ -24,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
24
25
  - Database instance is now immutable and bundle data is loaded in the constructor.
25
26
  - `GameMap` was renamed to `Zone`.
26
27
  - Badge partials are now referred to as badge requirements.
28
+ - `Badge.getRequirement()` now returns undefined instead of throwing an error on unknown key.
27
29
  - Exploration badge locations were moved into the badge requirements list.
28
30
  - References to zones and badges now use a standard Markdown link format (`badge://`, `map://`).
29
31
  - Some field names were updated for consistent pluralization (e.g., `name`, `icon`).
package/README.md CHANGED
@@ -41,6 +41,7 @@ export const TEST_BADGE: BadgeData = {
41
41
  key: 'test-badge',
42
42
  type: 'achievement',
43
43
  name: [{ value: 'Test Badge' }, { alignment: 'praetorian', value: 'My Badge for Praetorians' }],
44
+ releaseDate: '2020-03-01',
44
45
  alignment: ['hero', 'praetorian'],
45
46
  }
46
47
  ```
@@ -180,6 +180,10 @@ interface BadgeData {
180
180
  * If the value differs by sex or alignment, include an {@link AlternateData} for each variant.
181
181
  */
182
182
  readonly name: string | AlternateData<string>[];
183
+ /**
184
+ * The date that the badge was added to the game.
185
+ */
186
+ readonly releaseDate: string;
183
187
  /**
184
188
  * The {@link MoralityExtended|moralities} that this badge is available to. If undefined then all moralities will be assumed.
185
189
  */
@@ -560,6 +564,10 @@ declare class Badge {
560
564
  * May vary by character sex or alignment.
561
565
  */
562
566
  readonly name: Alternates<string>;
567
+ /**
568
+ * The date that the badge was added to the game.
569
+ */
570
+ readonly releaseDate: Date;
563
571
  /**
564
572
  * The character moralities that this badge is available to.
565
573
  */
@@ -595,16 +603,16 @@ declare class Badge {
595
603
  * A description of the effect the badge will have, such as a buff or granting a temporary power.
596
604
  */
597
605
  readonly effect?: MarkdownString;
598
- /**
599
- * Represents the requirements for badges with multiple fulfillment steps, such as visiting monuments for history badges, completing missions, or collecting other badges.
600
- */
601
- readonly requirements?: BadgeRequirement[];
602
606
  /**
603
607
  * Some badges are not included in the badge total count... such as Flames of Prometheus, which can be removed by redeeming it for a Notice of the Well.
604
608
  */
605
609
  readonly ignoreInTotals: boolean;
606
610
  constructor(badgeData: BadgeData);
607
- getRequirement(key: string): BadgeRequirement;
611
+ /**
612
+ * Represents the requirements for badges with multiple fulfillment steps, such as visiting monuments for history badges, completing missions, or collecting other badges.
613
+ */
614
+ get requirements(): BadgeRequirement[];
615
+ getRequirement(key: string): BadgeRequirement | undefined;
608
616
  /**
609
617
  * Return a list of all the zone keys referenced by this badge.
610
618
  */
@@ -616,7 +624,10 @@ declare class Badge {
616
624
  }
617
625
  declare function compareByDefaultName(a?: Badge, b?: Badge): number;
618
626
  declare function compareByZoneKey(a?: Badge, b?: Badge): number;
627
+ declare function compareByReleaseDate(a?: Badge, b?: Badge): number;
619
628
 
629
+ type BadgeQueryableField = 'name' | 'badge-text' | 'acquisition' | 'notes' | 'effect' | 'set-title-id';
630
+ type BadgeSortableField = 'canonical' | 'badge-name' | 'zone-key' | 'release-date';
620
631
  interface BadgeSearchOptions {
621
632
  /**
622
633
  * Text-based search.
@@ -625,14 +636,7 @@ interface BadgeSearchOptions {
625
636
  */
626
637
  query?: {
627
638
  str?: string;
628
- on?: {
629
- name?: boolean;
630
- badgeText?: boolean;
631
- acquisition?: boolean;
632
- notes?: boolean;
633
- effect?: boolean;
634
- setTitle?: boolean;
635
- };
639
+ fields?: BadgeQueryableField[];
636
640
  };
637
641
  /**
638
642
  * Filter results matching the given values.
@@ -648,7 +652,7 @@ interface BadgeSearchOptions {
648
652
  * Badges are assumed to be in canonical order in the content bundle, and should match the in-game display order.
649
653
  */
650
654
  sort?: {
651
- by?: 'canonical' | 'badge-name' | 'zone-key';
655
+ by?: BadgeSortableField;
652
656
  dir?: 'asc' | 'desc';
653
657
  };
654
658
  /**
@@ -999,4 +1003,4 @@ declare function zoneLink(target: string | Zone | ZoneData): string;
999
1003
  */
1000
1004
  declare function coalesceToArray<T>(value?: T | T[]): T[] | undefined;
1001
1005
 
1002
- export { ALIGNMENT, type Alignment, type AlignmentExtended, AlignmentList, type AlternateData, Alternates, Archetype, type ArchetypeData, BADGE_REQUIREMENT_TYPE, BADGE_TYPE, Badge, type BadgeData, BadgeIndex, BadgeRequirement, type BadgeRequirementData, type BadgeRequirementType, type BadgeSearchOptions, type BadgeType, type BundleData, BundleHeader, type BundleHeaderData, CohContentDatabase, Contact, type ContactData, type Coords, ENHANCEMENT_CATEGORY, type EnhancementCategory, Key, type Link, Location, type LocationData, type LocationIcon, MISSION_TYPE, MORALITY, type MarkdownString, Mission, type MissionData, type MissionFlashbackData, type MissionType, type Morality, type MoralityExtended, MoralityList, type Paged, SEX, type Sex, Zone, type ZoneData, badgeLink, badgeUri, coalesceToArray, compareAlignment, compareByDefaultName, compareByZoneKey, compareSex, contactLink, contactUri, missionLink, missionUri, zoneLink, zoneUri };
1006
+ export { ALIGNMENT, type Alignment, type AlignmentExtended, AlignmentList, type AlternateData, Alternates, Archetype, type ArchetypeData, BADGE_REQUIREMENT_TYPE, BADGE_TYPE, Badge, type BadgeData, BadgeIndex, type BadgeQueryableField, BadgeRequirement, type BadgeRequirementData, type BadgeRequirementType, type BadgeSearchOptions, type BadgeSortableField, type BadgeType, type BundleData, BundleHeader, type BundleHeaderData, CohContentDatabase, Contact, type ContactData, type Coords, ENHANCEMENT_CATEGORY, type EnhancementCategory, Key, type Link, Location, type LocationData, type LocationIcon, MISSION_TYPE, MORALITY, type MarkdownString, Mission, type MissionData, type MissionFlashbackData, type MissionType, type Morality, type MoralityExtended, MoralityList, type Paged, SEX, type Sex, Zone, type ZoneData, badgeLink, badgeUri, coalesceToArray, compareAlignment, compareByDefaultName, compareByReleaseDate, compareByZoneKey, compareSex, contactLink, contactUri, missionLink, missionUri, zoneLink, zoneUri };
@@ -107,7 +107,7 @@ var __publicField$a = (obj, key, value) => __defNormalProp$a(obj, typeof key !==
107
107
  var __accessCheck$6 = (obj, member, msg) => member.has(obj) || __typeError$6("Cannot " + msg);
108
108
  var __privateGet$5 = (obj, member, getter) => (__accessCheck$6(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
109
109
  var __privateAdd$6 = (obj, member, value) => member.has(obj) ? __typeError$6("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
110
- var __privateSet$4 = (obj, member, value, setter) => (__accessCheck$6(obj, member, "write to private field"), member.set(obj, value), value);
110
+ var __privateSet$5 = (obj, member, value, setter) => (__accessCheck$6(obj, member, "write to private field"), member.set(obj, value), value);
111
111
  var _items$1;
112
112
  class AlignmentList {
113
113
  constructor(items) {
@@ -123,7 +123,7 @@ class AlignmentList {
123
123
  this.praetorian = set.has("praetorian") || set.has("all");
124
124
  this.primal = this.hero && this.villain;
125
125
  this.all = this.hero && this.villain && this.praetorian;
126
- __privateSet$4(this, _items$1, /* @__PURE__ */ new Set());
126
+ __privateSet$5(this, _items$1, /* @__PURE__ */ new Set());
127
127
  if (this.hero) __privateGet$5(this, _items$1).add("hero");
128
128
  if (this.villain) __privateGet$5(this, _items$1).add("villain");
129
129
  if (this.praetorian) __privateGet$5(this, _items$1).add("praetorian");
@@ -162,7 +162,7 @@ var __typeError$5 = (msg) => {
162
162
  var __accessCheck$5 = (obj, member, msg) => member.has(obj) || __typeError$5("Cannot " + msg);
163
163
  var __privateGet$4 = (obj, member, getter) => (__accessCheck$5(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
164
164
  var __privateAdd$5 = (obj, member, value) => member.has(obj) ? __typeError$5("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
165
- var __privateSet$3 = (obj, member, value, setter) => (__accessCheck$5(obj, member, "write to private field"), member.set(obj, value), value);
165
+ var __privateSet$4 = (obj, member, value, setter) => (__accessCheck$5(obj, member, "write to private field"), member.set(obj, value), value);
166
166
  var __privateMethod$2 = (obj, member, method) => (__accessCheck$5(obj, member, "access private method"), method);
167
167
  var _sortedValues, _Alternates_instances, compareAlternates_fn;
168
168
  class Alternates {
@@ -174,10 +174,10 @@ class Alternates {
174
174
  __privateAdd$5(this, _Alternates_instances);
175
175
  __privateAdd$5(this, _sortedValues, []);
176
176
  if (Array.isArray(value)) {
177
- __privateSet$3(this, _sortedValues, value.sort());
177
+ __privateSet$4(this, _sortedValues, value.sort());
178
178
  __privateGet$4(this, _sortedValues).sort((a, b) => __privateMethod$2(this, _Alternates_instances, compareAlternates_fn).call(this, a, b));
179
179
  } else {
180
- __privateSet$3(this, _sortedValues, [{ value }]);
180
+ __privateSet$4(this, _sortedValues, [{ value }]);
181
181
  }
182
182
  }
183
183
  getValue(alignment, sex) {
@@ -226,7 +226,7 @@ var __typeError$4 = (msg) => {
226
226
  var __accessCheck$4 = (obj, member, msg) => member.has(obj) || __typeError$4("Cannot " + msg);
227
227
  var __privateGet$3 = (obj, member, getter) => (__accessCheck$4(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
228
228
  var __privateAdd$4 = (obj, member, value) => member.has(obj) ? __typeError$4("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
229
- var __privateSet$2 = (obj, member, value, setter) => (__accessCheck$4(obj, member, "write to private field"), member.set(obj, value), value);
229
+ var __privateSet$3 = (obj, member, value, setter) => (__accessCheck$4(obj, member, "write to private field"), member.set(obj, value), value);
230
230
  var __privateMethod$1 = (obj, member, method) => (__accessCheck$4(obj, member, "access private method"), method);
231
231
  var _value, _Key_instances, validateKey_fn;
232
232
  const INVALID_KEY_PATTERN = /[^a-z0-9-]/;
@@ -235,7 +235,7 @@ class Key {
235
235
  __privateAdd$4(this, _Key_instances);
236
236
  __privateAdd$4(this, _value);
237
237
  __privateMethod$1(this, _Key_instances, validateKey_fn).call(this, value);
238
- __privateSet$2(this, _value, value);
238
+ __privateSet$3(this, _value, value);
239
239
  }
240
240
  get value() {
241
241
  return __privateGet$3(this, _value);
@@ -372,7 +372,7 @@ var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, typeof key !==
372
372
  var __accessCheck$3 = (obj, member, msg) => member.has(obj) || __typeError$3("Cannot " + msg);
373
373
  var __privateGet$2 = (obj, member, getter) => (__accessCheck$3(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
374
374
  var __privateAdd$3 = (obj, member, value) => member.has(obj) ? __typeError$3("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
375
- var __privateSet$1 = (obj, member, value, setter) => (__accessCheck$3(obj, member, "write to private field"), member.set(obj, value), value);
375
+ var __privateSet$2 = (obj, member, value, setter) => (__accessCheck$3(obj, member, "write to private field"), member.set(obj, value), value);
376
376
  var _items;
377
377
  class MoralityList {
378
378
  constructor(items) {
@@ -404,7 +404,7 @@ class MoralityList {
404
404
  this.paragonCityAccess = this.heroic && this.rogue;
405
405
  this.rogueIslesAccess = this.villainous && this.vigilante;
406
406
  this.all = this.primal && this.praetorian;
407
- __privateSet$1(this, _items, /* @__PURE__ */ new Set());
407
+ __privateSet$2(this, _items, /* @__PURE__ */ new Set());
408
408
  if (this.hero) __privateGet$2(this, _items).add("hero");
409
409
  if (this.vigilante) __privateGet$2(this, _items).add("vigilante");
410
410
  if (this.villain) __privateGet$2(this, _items).add("villain");
@@ -465,79 +465,117 @@ class MoralityList {
465
465
  _items = new WeakMap();
466
466
 
467
467
  var __defProp$6 = Object.defineProperty;
468
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
469
+ var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
470
+ class AbstractIndex {
471
+ /**
472
+ * Create a new index.
473
+ * @param keyField The field of the values that will act as the key.
474
+ * @param values Values to index.
475
+ */
476
+ constructor(keyField, values) {
477
+ __publicField$6(this, "_values", []);
478
+ __publicField$6(this, "_hashTable", {});
479
+ this._values = values ?? [];
480
+ this._hashTable = {};
481
+ for (const value of this.values) {
482
+ const key = value[keyField];
483
+ if (this._hashTable[key] !== void 0) throw new Error(`Duplicate key [${key}]`);
484
+ this._hashTable[key] = value;
485
+ }
486
+ }
487
+ /**
488
+ * Return all indexed values
489
+ */
490
+ get values() {
491
+ return this._values;
492
+ }
493
+ /**
494
+ * Get a value from the index
495
+ * @param key Key string
496
+ */
497
+ get(key) {
498
+ if (!key) return void 0;
499
+ return this._hashTable[key];
500
+ }
501
+ }
502
+
503
+ var __defProp$5 = Object.defineProperty;
468
504
  var __typeError$2 = (msg) => {
469
505
  throw TypeError(msg);
470
506
  };
471
- var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
472
- var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
507
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
508
+ var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
473
509
  var __accessCheck$2 = (obj, member, msg) => member.has(obj) || __typeError$2("Cannot " + msg);
474
510
  var __privateGet$1 = (obj, member, getter) => (__accessCheck$2(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
475
511
  var __privateAdd$2 = (obj, member, value) => member.has(obj) ? __typeError$2("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
512
+ var __privateSet$1 = (obj, member, value, setter) => (__accessCheck$2(obj, member, "write to private field"), member.set(obj, value), value);
476
513
  var _requirementsIndex, _zoneKeys;
477
514
  class Badge {
478
515
  constructor(badgeData) {
479
- __privateAdd$2(this, _requirementsIndex, {});
516
+ __privateAdd$2(this, _requirementsIndex);
480
517
  __privateAdd$2(this, _zoneKeys, /* @__PURE__ */ new Set());
481
518
  /**
482
519
  * The database key for this badge.
483
520
  */
484
- __publicField$6(this, "key");
521
+ __publicField$5(this, "key");
485
522
  /**
486
523
  * The type of badge.
487
524
  */
488
- __publicField$6(this, "type");
525
+ __publicField$5(this, "type");
489
526
  /**
490
527
  * The name of this badge.
491
528
  *
492
529
  * May vary by character sex or alignment.
493
530
  */
494
- __publicField$6(this, "name");
531
+ __publicField$5(this, "name");
532
+ /**
533
+ * The date that the badge was added to the game.
534
+ */
535
+ __publicField$5(this, "releaseDate");
495
536
  /**
496
537
  * The character moralities that this badge is available to.
497
538
  */
498
- __publicField$6(this, "morality");
539
+ __publicField$5(this, "morality");
499
540
  /**
500
541
  * The badge text as it appears in-game. May vary by character sex or alignment.
501
542
  */
502
- __publicField$6(this, "badgeText");
543
+ __publicField$5(this, "badgeText");
503
544
  /**
504
545
  * Short description of how to acquire the badge. Detailed instructions will be in the notes field.
505
546
  */
506
- __publicField$6(this, "acquisition");
547
+ __publicField$5(this, "acquisition");
507
548
  /**
508
549
  * Absolute URL to this badge's icon.
509
550
  *
510
551
  * May vary by character sex or alignment.
511
552
  */
512
- __publicField$6(this, "icon");
553
+ __publicField$5(this, "icon");
513
554
  /**
514
555
  * Freeform notes or tips about the badge.
515
556
  */
516
- __publicField$6(this, "notes");
557
+ __publicField$5(this, "notes");
517
558
  /**
518
559
  * List of external links. Wiki, forums, etc.
519
560
  */
520
- __publicField$6(this, "links");
561
+ __publicField$5(this, "links");
521
562
  /**
522
563
  * The id used with the in-game `/settitle` command to apply the badge.
523
564
  * The first value is the id for primal characters and the (optional) second number is the id for praetorian characters.
524
565
  */
525
- __publicField$6(this, "setTitleId");
566
+ __publicField$5(this, "setTitleId");
526
567
  /**
527
568
  * A description of the effect the badge will have, such as a buff or granting a temporary power.
528
569
  */
529
- __publicField$6(this, "effect");
530
- /**
531
- * Represents the requirements for badges with multiple fulfillment steps, such as visiting monuments for history badges, completing missions, or collecting other badges.
532
- */
533
- __publicField$6(this, "requirements");
570
+ __publicField$5(this, "effect");
534
571
  /**
535
572
  * Some badges are not included in the badge total count... such as Flames of Prometheus, which can be removed by redeeming it for a Notice of the Well.
536
573
  */
537
- __publicField$6(this, "ignoreInTotals");
574
+ __publicField$5(this, "ignoreInTotals");
538
575
  this.key = new Key(badgeData.key).value;
539
576
  this.type = badgeData.type;
540
577
  this.name = new Alternates(badgeData.name);
578
+ this.releaseDate = new Date(badgeData.releaseDate);
541
579
  this.morality = new MoralityList(coalesceToArray(badgeData.morality));
542
580
  this.badgeText = new Alternates(badgeData.badgeText ?? []);
543
581
  this.acquisition = badgeData.acquisition;
@@ -547,20 +585,21 @@ class Badge {
547
585
  this.effect = badgeData.effect;
548
586
  this.setTitleId = badgeData.setTitleId;
549
587
  this.ignoreInTotals = badgeData.ignoreInTotals ?? false;
550
- this.requirements = badgeData.requirements?.map((requirementData) => {
551
- if (__privateGet$1(this, _requirementsIndex)[requirementData.key]) throw new Error(`Duplicate badge requirement key [${badgeData.key}:${requirementData.key}]`);
552
- const requirement = new BadgeRequirement(requirementData);
553
- __privateGet$1(this, _requirementsIndex)[requirement.key] = requirement;
588
+ __privateSet$1(this, _requirementsIndex, new AbstractIndex("key", badgeData.requirements?.map((x) => new BadgeRequirement(x))));
589
+ for (const requirement of __privateGet$1(this, _requirementsIndex).values) {
554
590
  if (requirement.location) for (const location of requirement.location) {
555
591
  if (location.zoneKey) __privateGet$1(this, _zoneKeys).add(location.zoneKey);
556
592
  }
557
- return requirement;
558
- });
593
+ }
594
+ }
595
+ /**
596
+ * Represents the requirements for badges with multiple fulfillment steps, such as visiting monuments for history badges, completing missions, or collecting other badges.
597
+ */
598
+ get requirements() {
599
+ return __privateGet$1(this, _requirementsIndex).values;
559
600
  }
560
601
  getRequirement(key) {
561
- const result = __privateGet$1(this, _requirementsIndex)[key];
562
- if (result === void 0) throw new Error(`Unknown badge requirement key [${key}]`);
563
- return result;
602
+ return __privateGet$1(this, _requirementsIndex).get(key);
564
603
  }
565
604
  /**
566
605
  * Return a list of all the zone keys referenced by this badge.
@@ -593,41 +632,13 @@ function compareByZoneKey(a, b) {
593
632
  if (!bZone) return -1;
594
633
  return aZone.localeCompare(bZone);
595
634
  }
596
-
597
- var __defProp$5 = Object.defineProperty;
598
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
599
- var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
600
- class AbstractIndex {
601
- /**
602
- * Create a new index.
603
- * @param keyField The field of the values that will act as the key.
604
- * @param values Values to index.
605
- */
606
- constructor(keyField, values) {
607
- __publicField$5(this, "_values", []);
608
- __publicField$5(this, "_hashTable", {});
609
- this._values = values ?? [];
610
- this._hashTable = {};
611
- for (const value of this.values) {
612
- const key = value[keyField];
613
- if (this._hashTable[key] !== void 0) throw new Error(`Duplicate key [${key}]`);
614
- this._hashTable[key] = value;
615
- }
616
- }
617
- /**
618
- * Return all indexed values
619
- */
620
- get values() {
621
- return this._values;
622
- }
623
- /**
624
- * Get a value from the index
625
- * @param key Key string
626
- */
627
- get(key) {
628
- if (!key) return void 0;
629
- return this._hashTable[key];
630
- }
635
+ function compareByReleaseDate(a, b) {
636
+ const aReleaseDate = a?.releaseDate?.getTime();
637
+ const bReleaseDate = b?.releaseDate?.getTime();
638
+ if (aReleaseDate === bReleaseDate) return 0;
639
+ if (!aReleaseDate) return 1;
640
+ if (!bReleaseDate) return -1;
641
+ return aReleaseDate < bReleaseDate ? -1 : 1;
631
642
  }
632
643
 
633
644
  var __typeError$1 = (msg) => {
@@ -660,7 +671,9 @@ class BadgeIndex extends AbstractIndex {
660
671
  _BadgeIndex_instances = new WeakSet();
661
672
  satisfiesQueryPredicate_fn = function(badge, query) {
662
673
  const queryString = query?.str?.toLowerCase() ?? "";
663
- return !!((query?.on?.name ?? true) && badge.name.canonical.some((x) => x.value.toLowerCase().includes(queryString)) || query?.on?.badgeText && badge.badgeText.canonical.some((x) => x.value.toLowerCase().includes(queryString)) || query?.on?.acquisition && badge.acquisition?.toLowerCase().includes(queryString) || query?.on?.effect && badge.effect?.toLowerCase().includes(queryString) || query?.on?.notes && badge.notes?.toLowerCase().includes(queryString) || query?.on?.setTitle && badge.setTitleId?.some((x) => x?.toString().includes(queryString)));
674
+ const fields = query?.fields ? new Set(query?.fields) : /* @__PURE__ */ new Set(["name"]);
675
+ if (fields.size === 0) return true;
676
+ return !!(fields.has("name") && badge.name.canonical.some((x) => x.value.toLowerCase().includes(queryString)) || fields.has("badge-text") && badge.badgeText.canonical.some((x) => x.value.toLowerCase().includes(queryString)) || fields.has("acquisition") && badge.acquisition?.toLowerCase().includes(queryString) || fields.has("effect") && badge.effect?.toLowerCase().includes(queryString) || fields.has("notes") && badge.notes?.toLowerCase().includes(queryString) || fields.has("set-title-id") && badge.setTitleId?.some((x) => x?.toString().includes(queryString)));
664
677
  };
665
678
  satisfiesFilterPredicate_fn = function(badge, filter) {
666
679
  return (!filter?.type || badge.type === filter.type) && (!filter?.zoneKey || badge.zoneKey === filter.zoneKey) && (!filter?.morality || badge.morality.has(filter.morality));
@@ -670,6 +683,7 @@ sort_fn = function(badges, sort) {
670
683
  const ascending = sort.dir !== "desc";
671
684
  if (sort.by === "badge-name") return badges.sort((a, b) => ascending ? compareByDefaultName(a, b) : compareByDefaultName(b, a));
672
685
  if (sort.by === "zone-key") return badges.sort((a, b) => ascending ? compareByZoneKey(a, b) : compareByZoneKey(b, a));
686
+ if (sort.by === "release-date") return badges.sort((a, b) => ascending ? compareByReleaseDate(a, b) : compareByReleaseDate(b, a));
673
687
  return sort.dir === "desc" ? badges.reverse() : badges;
674
688
  };
675
689
 
@@ -1033,6 +1047,7 @@ exports.badgeUri = badgeUri;
1033
1047
  exports.coalesceToArray = coalesceToArray;
1034
1048
  exports.compareAlignment = compareAlignment;
1035
1049
  exports.compareByDefaultName = compareByDefaultName;
1050
+ exports.compareByReleaseDate = compareByReleaseDate;
1036
1051
  exports.compareByZoneKey = compareByZoneKey;
1037
1052
  exports.compareSex = compareSex;
1038
1053
  exports.contactLink = contactLink;