coh-content-db 2.0.0-rc.14 → 2.0.0-rc.16

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.
@@ -5,10 +5,10 @@ import { BadgeRequirement } from './badge-requirement'
5
5
  import { Key } from './key'
6
6
  import { Alternates } from './alternates'
7
7
  import { MarkdownString } from '../api/markdown-string'
8
- import { coalesceToArray } from '../util'
9
8
  import { MoralityList } from './morality-list'
10
9
  import { AbstractIndex } from './abstract-index'
11
- import { toDate } from '../to-date'
10
+ import { toDate } from '../util/to-date'
11
+ import { coalesceToArray } from '../util/coalesce-to-array'
12
12
 
13
13
  export class Badge {
14
14
  readonly #requirementsIndex: AbstractIndex<BadgeRequirement>
@@ -1,7 +1,7 @@
1
1
  import { Link } from '../api/link'
2
2
  import { MarkdownString } from '../api/markdown-string'
3
3
  import { BundleHeaderData } from '../api/bundle-header-data'
4
- import { toDate } from '../to-date'
4
+ import { toDate } from '../util/to-date'
5
5
 
6
6
  export class BundleHeader {
7
7
  /**
@@ -4,7 +4,7 @@ import { MarkdownString } from '../api/markdown-string'
4
4
  import { ContactData } from '../api/contact-data'
5
5
  import { Location } from './location'
6
6
  import { MoralityList } from './morality-list'
7
- import { coalesceToArray } from '../util'
7
+ import { coalesceToArray } from '../util/coalesce-to-array'
8
8
 
9
9
  export class Contact {
10
10
  /**
@@ -3,8 +3,8 @@ import { MarkdownString } from '../api/markdown-string'
3
3
  import { Link } from '../api/link'
4
4
  import { MissionData } from '../api/mission-data'
5
5
  import { Key } from './key'
6
- import { coalesceToArray } from '../util'
7
6
  import { MoralityList } from './morality-list'
7
+ import { coalesceToArray } from '../util/coalesce-to-array'
8
8
 
9
9
  export class Mission {
10
10
  /**
package/src/main/index.ts CHANGED
@@ -37,5 +37,5 @@ export * from './db/morality-list'
37
37
  export * from './db/paged'
38
38
  export * from './db/zone'
39
39
 
40
- // ROOT
41
- export * from './util'
40
+ // UTILS
41
+ export * from './util/links'
@@ -0,0 +1,13 @@
1
+ /**
2
+ * For fields that accept either an array of values or a single value, coalesces the value to an array.
3
+ *
4
+ * Arrays are returned as-is.
5
+ * Single values are returned as a single-value array.
6
+ * Undefined values are returned as undefined.
7
+ *
8
+ * @param value The value to coalesce.
9
+ */
10
+ export function coalesceToArray<T>(value?: T | T[]): T[] | undefined {
11
+ if (!value) return undefined
12
+ return Array.isArray(value) ? value as T[] : [value]
13
+ }
@@ -1,11 +1,11 @@
1
- import { BadgeData } from './api/badge-data'
2
- import { Badge } from './db/badge'
3
- import { ZoneData } from './api/zone-data'
4
- import { Zone } from './db/zone'
5
- import { Contact } from './db/contact'
6
- import { ContactData } from './api/contact-data'
7
- import { Mission } from './db/mission'
8
- import { MissionData } from './api/mission-data'
1
+ import { BadgeData } from '../api/badge-data'
2
+ import { Badge } from '../db/badge'
3
+ import { ZoneData } from '../api/zone-data'
4
+ import { Zone } from '../db/zone'
5
+ import { Contact } from '../db/contact'
6
+ import { ContactData } from '../api/contact-data'
7
+ import { Mission } from '../db/mission'
8
+ import { MissionData } from '../api/mission-data'
9
9
 
10
10
  /**
11
11
  * Returns the URI of the given badge that can be used in {@link MarkdownString} fields.
@@ -102,17 +102,3 @@ export function zoneLink(target: string | Zone | ZoneData): string {
102
102
  const key = typeof target === 'string' ? target : target.key
103
103
  return `[${key}](${zoneUri(target)})`
104
104
  }
105
-
106
- /**
107
- * For fields that accept either an array of values or a single value, coalesces the value to an array.
108
- *
109
- * Arrays are returned as-is.
110
- * Single values are returned as a single-value array.
111
- * Undefined values are returned as undefined.
112
- *
113
- * @param value The value to coalesce.
114
- */
115
- export function coalesceToArray<T>(value?: T | T[]): T[] | undefined {
116
- if (!value) return undefined
117
- return Array.isArray(value) ? value as T[] : [value]
118
- }
@@ -51,14 +51,14 @@ describe('compareAlignment', () => {
51
51
 
52
52
  test('should work as a compare function', () => {
53
53
  const unsorted: (Alignment | undefined)[] = [undefined, 'hero', 'villain', 'praetorian', undefined, 'villain', 'praetorian']
54
- const sorted = unsorted.sort(compareAlignment)
54
+ const sorted = unsorted.toSorted(compareAlignment)
55
55
 
56
56
  expect(sorted).toStrictEqual(['hero', 'villain', 'villain', 'praetorian', 'praetorian', undefined, undefined])
57
57
  })
58
58
 
59
59
  test('should sort against undefined', () => {
60
60
  const unsorted: (Alignment | undefined)[] = [undefined, 'hero']
61
- const sorted = unsorted.sort(compareAlignment)
61
+ const sorted = unsorted.toSorted(compareAlignment)
62
62
 
63
63
  expect(sorted).toStrictEqual(['hero', undefined])
64
64
  })
@@ -49,14 +49,14 @@ describe('compareSex', () => {
49
49
 
50
50
  test('should work as a compare function', () => {
51
51
  const unsorted: (Sex | undefined)[] = [undefined, 'M', 'F', 'M', undefined, 'F', 'M']
52
- const sorted = unsorted.sort(compareSex)
52
+ const sorted = unsorted.toSorted(compareSex)
53
53
 
54
54
  expect(sorted).toStrictEqual(['M', 'M', 'M', 'F', 'F', undefined, undefined])
55
55
  })
56
56
 
57
57
  test('should sort against undefined', () => {
58
58
  const unsorted: (Sex | undefined)[] = [undefined, 'M']
59
- const sorted = unsorted.sort(compareSex)
59
+ const sorted = unsorted.toSorted(compareSex)
60
60
 
61
61
  expect(sorted).toStrictEqual(['M', undefined])
62
62
  })
@@ -433,7 +433,7 @@ describe(BadgeIndex.name, () => {
433
433
  new Badge(badgeDataFixture.create({ key: 'badge-4' })),
434
434
  ])
435
435
 
436
- const result = index.search({ sort: { by: 'canonical' } })
436
+ const result = index.search({ sort: 'canonical.asc' })
437
437
  const keys = result.items.map(x => x.key)
438
438
  expect(keys).toStrictEqual(['badge-1', 'badge-2', 'badge-3', 'badge-4'])
439
439
  })
@@ -446,7 +446,7 @@ describe(BadgeIndex.name, () => {
446
446
  new Badge(badgeDataFixture.create({ key: 'badge-4' })),
447
447
  ])
448
448
 
449
- const result = index.search({ sort: { dir: 'desc' } })
449
+ const result = index.search({ sort: 'canonical.desc' })
450
450
  const keys = result.items.map(x => x.key)
451
451
  expect(keys).toStrictEqual(['badge-4', 'badge-3', 'badge-2', 'badge-1'])
452
452
  })
@@ -458,7 +458,7 @@ describe(BadgeIndex.name, () => {
458
458
  new Badge(badgeDataFixture.create({ key: 'badge-3', name: [{ value: 'AAB' }] })),
459
459
  ])
460
460
 
461
- const result = index.search({ sort: { by: 'badge-name' } })
461
+ const result = index.search({ sort: 'name.asc' })
462
462
  const keys = result.items.map(x => x.key)
463
463
  expect(keys).toStrictEqual(['badge-3', 'badge-1', 'badge-2'])
464
464
  })
@@ -470,7 +470,7 @@ describe(BadgeIndex.name, () => {
470
470
  new Badge(badgeDataFixture.create({ key: 'badge-3', name: [{ value: 'AAB' }] })),
471
471
  ])
472
472
 
473
- const result = index.search({ sort: { by: 'badge-name', dir: 'desc' } })
473
+ const result = index.search({ sort: 'name.desc' })
474
474
  const keys = result.items.map(x => x.key)
475
475
  expect(keys).toStrictEqual(['badge-2', 'badge-1', 'badge-3'])
476
476
  })
@@ -482,7 +482,7 @@ describe(BadgeIndex.name, () => {
482
482
  new Badge(badgeDataFixture.create({ key: 'badge-3', name: [{ value: 'AAB' }] })),
483
483
  ])
484
484
 
485
- const result = index.search({ sort: { by: 'badge-name' } })
485
+ const result = index.search({ sort: 'name.asc' })
486
486
  const keys = result.items.map(x => x.key)
487
487
  expect(keys).toStrictEqual(['badge-3', 'badge-1', 'badge-2'])
488
488
  })
@@ -494,7 +494,7 @@ describe(BadgeIndex.name, () => {
494
494
  new Badge(badgeDataFixture.create({ key: 'badge-3', requirements: [{ location: { zoneKey: 'abandoned-sewer-network' } }] })),
495
495
  ])
496
496
 
497
- const result = index.search({ sort: { by: 'zone-key' } })
497
+ const result = index.search({ sort: 'zone-key.asc' })
498
498
  const keys = result.items.map(x => x.key)
499
499
  expect(keys).toStrictEqual(['badge-3', 'badge-1', 'badge-2'])
500
500
  })
@@ -506,7 +506,7 @@ describe(BadgeIndex.name, () => {
506
506
  new Badge(badgeDataFixture.create({ key: 'badge-3', requirements: [{ location: { zoneKey: 'abandoned-sewer-network' } }] })),
507
507
  ])
508
508
 
509
- const result = index.search({ sort: { by: 'zone-key', dir: 'desc' } })
509
+ const result = index.search({ sort: 'zone-key.desc' })
510
510
  const keys = result.items.map(x => x.key)
511
511
  expect(keys).toStrictEqual(['badge-2', 'badge-1', 'badge-3'])
512
512
  })
@@ -519,7 +519,7 @@ describe(BadgeIndex.name, () => {
519
519
  new Badge(badgeDataFixture.create({ key: 'badge-4', requirements: [{ location: { zoneKey: 'abandoned-sewer-network' } }] })),
520
520
  ])
521
521
 
522
- const result = index.search({ sort: { by: 'zone-key' } })
522
+ const result = index.search({ sort: 'zone-key.asc' })
523
523
  const keys = result.items.map(x => x.key)
524
524
  expect(keys).toStrictEqual(['badge-4', 'badge-1', 'badge-3', 'badge-2'])
525
525
  })
@@ -538,7 +538,7 @@ describe(BadgeIndex.name, () => {
538
538
  new Badge(badgeDataFixture.create({ key: 'badge-5', requirements: [{ location: { zoneKey: 'abandoned-sewer-network' } }] })),
539
539
  ])
540
540
 
541
- const result = index.search({ sort: { by: 'zone-key' } })
541
+ const result = index.search({ sort: 'zone-key.asc' })
542
542
  const keys = result.items.map(x => x.key)
543
543
  expect(keys).toStrictEqual(['badge-5', 'badge-1', 'badge-3', 'badge-2', 'badge-4'])
544
544
  })
@@ -550,7 +550,7 @@ describe(BadgeIndex.name, () => {
550
550
  new Badge(badgeDataFixture.create({ key: 'badge-3', releaseDate: '2020-01-01' })),
551
551
  ])
552
552
 
553
- const result = index.search({ sort: { by: 'release-date' } })
553
+ const result = index.search({ sort: 'release-date.asc' })
554
554
  const keys = result.items.map(x => x.key)
555
555
  expect(keys).toStrictEqual(['badge-3', 'badge-1', 'badge-2'])
556
556
  })
@@ -562,10 +562,31 @@ describe(BadgeIndex.name, () => {
562
562
  new Badge(badgeDataFixture.create({ key: 'badge-3', releaseDate: '2025-02-03' })),
563
563
  ])
564
564
 
565
- const result = index.search({ sort: { by: 'release-date', dir: 'desc' } })
565
+ const result = index.search({ sort: 'release-date.desc' })
566
566
  const keys = result.items.map(x => x.key)
567
567
  expect(keys).toStrictEqual(['badge-1', 'badge-3', 'badge-2'])
568
568
  })
569
+
570
+ test(`sort should apply before paging`, () => {
571
+ const index = new BadgeIndex([
572
+ new Badge(badgeDataFixture.create({ key: 'badge-a', name: 'A' })),
573
+ new Badge(badgeDataFixture.create({ key: 'badge-c', name: 'C' })),
574
+ new Badge(badgeDataFixture.create({ key: 'badge-e', name: 'E' })),
575
+ new Badge(badgeDataFixture.create({ key: 'badge-d', name: 'D' })),
576
+ new Badge(badgeDataFixture.create({ key: 'badge-b', name: 'B' })),
577
+ new Badge(badgeDataFixture.create({ key: 'badge-f', name: 'F' })),
578
+ ])
579
+
580
+ const page1 = index.search({ sort: 'name.asc', page: 1, pageSize: 2 })
581
+ const page2 = index.search({ sort: 'name.asc', page: 2, pageSize: 2 })
582
+ const page3 = index.search({ sort: 'name.asc', page: 3, pageSize: 2 })
583
+ const page1Keys = page1.items.map(x => x.key)
584
+ const page2Keys = page2.items.map(x => x.key)
585
+ const page3Keys = page3.items.map(x => x.key)
586
+ expect(page1Keys).toStrictEqual(['badge-a', 'badge-b'])
587
+ expect(page2Keys).toStrictEqual(['badge-c', 'badge-d'])
588
+ expect(page3Keys).toStrictEqual(['badge-e', 'badge-f'])
589
+ })
569
590
  })
570
591
  })
571
592
  })
@@ -254,6 +254,17 @@ describe(Badge.name, () => {
254
254
  }))
255
255
  expect(badge.zoneKeys).toStrictEqual(['a', 'c'])
256
256
  })
257
+
258
+ test(`should ignore locations with no zone key`, () => {
259
+ const badge = new Badge(badgeDataFixture.create({
260
+ requirements: [
261
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'a' } }),
262
+ badgeRequirementDataFixture.create({ location: { coords: [1, 2, 3] } }),
263
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'c' } }),
264
+ ],
265
+ }))
266
+ expect(badge.zoneKeys).toStrictEqual(['a', 'c'])
267
+ })
257
268
  })
258
269
 
259
270
  describe('zoneKey', () => {
@@ -291,7 +302,7 @@ describe(Badge.name, () => {
291
302
  const badgeA = new Badge(badgeDataFixture.create({ name: 'A' }))
292
303
  const badgeB = new Badge(badgeDataFixture.create({ name: 'B' }))
293
304
  expect(compareByDefaultName(badgeA, badgeB)).toBeLessThan(0)
294
- expect([badgeB, badgeA].sort(compareByDefaultName)).toStrictEqual([badgeA, badgeB])
305
+ expect([badgeB, badgeA].toSorted(compareByDefaultName)).toStrictEqual([badgeA, badgeB])
295
306
  })
296
307
 
297
308
  test(`should return 0 for equal names`, () => {
@@ -309,8 +320,8 @@ describe(Badge.name, () => {
309
320
  test(`should sort undefined values last`, () => {
310
321
  const badgeA = new Badge(badgeDataFixture.create({ name: 'A' }))
311
322
  const badgeB = new Badge(badgeDataFixture.create({ name: [] }))
312
- expect([badgeA, badgeB].sort(compareByDefaultName)).toStrictEqual([badgeA, badgeB])
313
- expect([badgeB, badgeA].sort(compareByDefaultName)).toStrictEqual([badgeA, badgeB])
323
+ expect([badgeA, badgeB].toSorted(compareByDefaultName)).toStrictEqual([badgeA, badgeB])
324
+ expect([badgeB, badgeA].toSorted(compareByDefaultName)).toStrictEqual([badgeA, badgeB])
314
325
  })
315
326
  })
316
327
 
@@ -327,7 +338,7 @@ describe(Badge.name, () => {
327
338
  ],
328
339
  }))
329
340
  expect(compareByZoneKey(badgeA, badgeB)).toBeLessThan(0)
330
- expect([badgeB, badgeA].sort(compareByZoneKey)).toStrictEqual([badgeA, badgeB])
341
+ expect([badgeB, badgeA].toSorted(compareByZoneKey)).toStrictEqual([badgeA, badgeB])
331
342
  })
332
343
 
333
344
  test(`should return 0 for equal zoneKeys`, () => {
@@ -370,8 +381,8 @@ describe(Badge.name, () => {
370
381
  badgeRequirementDataFixture.create({ location: { zoneKey: 'c' } }),
371
382
  ],
372
383
  }))
373
- expect([badgeA, badgeB].sort(compareByZoneKey)).toStrictEqual([badgeA, badgeB])
374
- expect([badgeB, badgeA].sort(compareByZoneKey)).toStrictEqual([badgeA, badgeB])
384
+ expect([badgeA, badgeB].toSorted(compareByZoneKey)).toStrictEqual([badgeA, badgeB])
385
+ expect([badgeB, badgeA].toSorted(compareByZoneKey)).toStrictEqual([badgeA, badgeB])
375
386
  })
376
387
  })
377
388
 
@@ -380,7 +391,7 @@ describe(Badge.name, () => {
380
391
  const badgeA = new Badge(badgeDataFixture.create({ releaseDate: '2024-01-01' }))
381
392
  const badgeB = new Badge(badgeDataFixture.create({ releaseDate: '2025-01-01' }))
382
393
  expect(compareByReleaseDate(badgeA, badgeB)).toBeLessThan(0)
383
- expect([badgeB, badgeA].sort(compareByReleaseDate)).toStrictEqual([badgeA, badgeB])
394
+ expect([badgeB, badgeA].toSorted(compareByReleaseDate)).toStrictEqual([badgeA, badgeB])
384
395
  })
385
396
 
386
397
  test(`should return 0 for equal releaseDates`, () => {
@@ -399,10 +410,10 @@ describe(Badge.name, () => {
399
410
  const badgeA = undefined
400
411
  const badgeB = new Badge(badgeDataFixture.create({ releaseDate: '2025-01-01' }))
401
412
  expect(compareByReleaseDate(badgeA, badgeB)).toBeGreaterThan(0)
402
- expect([badgeA, badgeB].sort(compareByReleaseDate)).toStrictEqual([badgeB, badgeA])
413
+ expect([badgeA, badgeB].toSorted(compareByReleaseDate)).toStrictEqual([badgeB, badgeA])
403
414
 
404
415
  expect(compareByReleaseDate(badgeB, badgeA)).toBeLessThan(0)
405
- expect([badgeB, badgeA].sort(compareByReleaseDate)).toStrictEqual([badgeB, badgeA])
416
+ expect([badgeB, badgeA].toSorted(compareByReleaseDate)).toStrictEqual([badgeB, badgeA])
406
417
  })
407
418
  })
408
419
  })
@@ -0,0 +1,17 @@
1
+ import { coalesceToArray } from '../../main/util/coalesce-to-array'
2
+
3
+ describe(coalesceToArray.name, () => {
4
+ test('should return an array unmodified', () => {
5
+ expect(coalesceToArray(['a', 'b'])).toStrictEqual(['a', 'b'])
6
+ expect(coalesceToArray([1, 2])).toStrictEqual([1, 2])
7
+ })
8
+
9
+ test('should return a single value as a single-value array', () => {
10
+ expect(coalesceToArray('a')).toStrictEqual(['a'])
11
+ expect(coalesceToArray(1)).toStrictEqual([1])
12
+ })
13
+
14
+ test('should return undefined value as undefined', () => {
15
+ expect(coalesceToArray()).toBeUndefined()
16
+ })
17
+ })
@@ -1,8 +1,8 @@
1
- import { Badge, badgeLink, badgeUri, coalesceToArray, Contact, contactLink, contactUri, Mission, missionLink, missionUri, Zone, zoneLink, zoneUri } from '../main'
2
- import { badgeDataFixture } from './api/badge-data.fixture'
3
- import { zoneDataFixture } from './api/zone-data.fixture'
4
- import { contactDataFixture } from './api/contact-data.fixture'
5
- import { missionDataFixture } from './api/mission-data.fixture'
1
+ import { Badge, badgeLink, badgeUri, Contact, contactLink, contactUri, Mission, missionLink, missionUri, Zone, zoneLink, zoneUri } from '../../main'
2
+ import { badgeDataFixture } from '../api/badge-data.fixture'
3
+ import { zoneDataFixture } from '../api/zone-data.fixture'
4
+ import { contactDataFixture } from '../api/contact-data.fixture'
5
+ import { missionDataFixture } from '../api/mission-data.fixture'
6
6
 
7
7
  describe(badgeUri.name, () => {
8
8
  test('should return the expected pattern', () => {
@@ -147,19 +147,3 @@ describe(zoneLink.name, () => {
147
147
  expect(zoneLink(zone)).toBe('[foo](zone://foo)')
148
148
  })
149
149
  })
150
-
151
- describe(coalesceToArray.name, () => {
152
- test('should return an array unmodified', () => {
153
- expect(coalesceToArray(['a', 'b'])).toStrictEqual(['a', 'b'])
154
- expect(coalesceToArray([1, 2])).toStrictEqual([1, 2])
155
- })
156
-
157
- test('should return a single value as a single-value array', () => {
158
- expect(coalesceToArray('a')).toStrictEqual(['a'])
159
- expect(coalesceToArray(1)).toStrictEqual([1])
160
- })
161
-
162
- test('should return undefined value as undefined', () => {
163
- expect(coalesceToArray()).toBeUndefined()
164
- })
165
- })
@@ -1,4 +1,4 @@
1
- import { toDate } from '../main/to-date'
1
+ import { toDate } from '../../main/util/to-date'
2
2
 
3
3
  describe(toDate.name, () => {
4
4
  test('should return a valid date', () => {
File without changes