coh-content-db 2.0.0-rc.9 → 2.0.0
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.
- package/.github/workflows/build.yml +3 -1
- package/CHANGELOG.md +11 -2
- package/README.md +33 -19
- package/dist/coh-content-db.d.ts +230 -170
- package/dist/coh-content-db.js +495 -296
- package/dist/coh-content-db.js.map +1 -1
- package/dist/coh-content-db.mjs +488 -294
- package/dist/coh-content-db.mjs.map +1 -1
- package/jest.config.mjs +1 -0
- package/package.json +14 -14
- package/src/main/api/badge-data.ts +13 -7
- package/src/main/api/bundle-data.ts +1 -1
- package/src/main/api/bundle-header-data.ts +13 -6
- package/src/main/api/contact-data.ts +2 -1
- package/src/main/api/level-range-data.ts +4 -0
- package/src/main/api/mission-data.ts +3 -29
- package/src/main/api/mission-flashback-data.ts +31 -0
- package/src/main/api/morality.ts +27 -9
- package/src/main/api/set-title-data.ts +4 -0
- package/src/main/api/variant-context.ts +11 -0
- package/src/main/api/{alternate-data.ts → variant-data.ts} +4 -4
- package/src/main/api/zone-data.ts +24 -0
- package/src/main/api/zone-type.ts +59 -0
- package/src/main/db/abstract-index.ts +12 -16
- package/src/main/db/badge-index.ts +53 -27
- package/src/main/db/badge-requirement.ts +1 -1
- package/src/main/db/badge-search-options.ts +15 -14
- package/src/main/db/badge.ts +46 -29
- package/src/main/db/bundle-header.ts +18 -10
- package/src/main/db/coh-content-database.ts +17 -17
- package/src/main/db/contact.ts +5 -4
- package/src/main/db/level-range.ts +15 -0
- package/src/main/db/mission.ts +11 -10
- package/src/main/db/paged.ts +7 -3
- package/src/main/db/set-title-ids.ts +10 -0
- package/src/main/db/variants.ts +84 -0
- package/src/main/db/zone.ts +29 -0
- package/src/main/index.ts +11 -4
- package/src/main/util/coalesce-to-array.ts +13 -0
- package/src/main/{util.ts → util/links.ts} +8 -22
- package/src/main/util/to-date.ts +9 -0
- package/src/test/api/alignment.test.ts +2 -2
- package/src/test/api/badge-data.fixture.ts +1 -0
- package/src/test/api/badge-data.test.ts +1 -0
- package/src/test/api/bundle-data.fixture.ts +3 -2
- package/src/test/api/bundle-header-data.fixture.ts +4 -2
- package/src/test/api/morality.test.ts +31 -0
- package/src/test/api/sex.test.ts +2 -2
- package/src/test/api/zone-data.fixture.ts +1 -0
- package/src/test/db/abstract-index.test.ts +12 -43
- package/src/test/db/badge-index.test.ts +197 -101
- package/src/test/db/badge.test.ts +122 -16
- package/src/test/db/bundle-header.test.ts +25 -12
- package/src/test/db/coh-content-database.test.ts +134 -175
- package/src/test/db/contact.test.ts +2 -1
- package/src/test/db/level-range.test.ts +47 -0
- package/src/test/db/mission.test.ts +8 -6
- package/src/test/db/morality-list.test.ts +1 -1
- package/src/test/db/set-title-ids.test.ts +19 -0
- package/src/test/db/{alternates.test.ts → variants.test.ts} +24 -24
- package/src/test/db/zone.test.ts +45 -0
- package/src/test/integration.test.ts +3 -3
- package/src/test/util/coalese-to-array.test.ts +17 -0
- package/src/test/{util.test.ts → util/links.test.ts} +5 -21
- package/src/test/util/to-date.test.ts +15 -0
- package/src/main/db/alternates.ts +0 -67
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Badge,
|
|
1
|
+
import { Badge, compareByName, compareByReleaseDate, compareByZoneKey } from '../../main'
|
|
2
2
|
import { badgeDataFixture } from '../api/badge-data.fixture'
|
|
3
3
|
import { badgeRequirementDataFixture } from '../api/badge-requirement-data.fixture'
|
|
4
4
|
|
|
@@ -28,6 +28,24 @@ describe(Badge.name, () => {
|
|
|
28
28
|
const badge = new Badge(badgeDataFixture.create({ name: [{ value: 'foo' }] }))
|
|
29
29
|
expect(badge.name.default).toEqual({ value: 'foo' })
|
|
30
30
|
})
|
|
31
|
+
|
|
32
|
+
test('should accept a string', () => {
|
|
33
|
+
const badge = new Badge(badgeDataFixture.create({ name: 'foo' }))
|
|
34
|
+
expect(badge.name.default).toEqual({ value: 'foo' })
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe('releaseDate', () => {
|
|
39
|
+
test('should be set from the data', () => {
|
|
40
|
+
const badge = new Badge(badgeDataFixture.create({ releaseDate: '2025-08-08' }))
|
|
41
|
+
expect(badge.releaseDate).toEqual(new Date('2025-08-08'))
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('should not accept an invalid date', () => {
|
|
45
|
+
expect(() =>
|
|
46
|
+
new Badge(badgeDataFixture.create({ releaseDate: '2025-??-08' })),
|
|
47
|
+
).toThrow('Invalid date')
|
|
48
|
+
})
|
|
31
49
|
})
|
|
32
50
|
|
|
33
51
|
describe('morality', () => {
|
|
@@ -55,6 +73,11 @@ describe(Badge.name, () => {
|
|
|
55
73
|
expect(badge.badgeText.default).toEqual({ value: 'foo' })
|
|
56
74
|
})
|
|
57
75
|
|
|
76
|
+
test('should accept a string', () => {
|
|
77
|
+
const badge = new Badge(badgeDataFixture.create({ badgeText: 'foo' }))
|
|
78
|
+
expect(badge.badgeText.default).toEqual({ value: 'foo' })
|
|
79
|
+
})
|
|
80
|
+
|
|
58
81
|
test('should be optional', () => {
|
|
59
82
|
const badge = new Badge(badgeDataFixture.omit('badgeText').create())
|
|
60
83
|
expect(badge.badgeText.default).toBeUndefined()
|
|
@@ -79,6 +102,11 @@ describe(Badge.name, () => {
|
|
|
79
102
|
expect(badge.icon.default).toEqual({ value: 'foo' })
|
|
80
103
|
})
|
|
81
104
|
|
|
105
|
+
test('should accept a string', () => {
|
|
106
|
+
const badge = new Badge(badgeDataFixture.create({ icon: 'foo' }))
|
|
107
|
+
expect(badge.icon.default).toEqual({ value: 'foo' })
|
|
108
|
+
})
|
|
109
|
+
|
|
82
110
|
test('should be optional', () => {
|
|
83
111
|
const badge = new Badge(badgeDataFixture.omit('icon').create())
|
|
84
112
|
expect(badge.icon.default).toBeUndefined()
|
|
@@ -124,12 +152,14 @@ describe(Badge.name, () => {
|
|
|
124
152
|
describe('setTitle', () => {
|
|
125
153
|
test('should be set from the data', () => {
|
|
126
154
|
const badge = new Badge(badgeDataFixture.create({ setTitleId: [123, 456] }))
|
|
127
|
-
expect(badge.setTitleId).
|
|
155
|
+
expect(badge.setTitleId?.primal).toEqual(123)
|
|
156
|
+
expect(badge.setTitleId?.praetorian).toEqual(456)
|
|
128
157
|
})
|
|
129
158
|
|
|
130
159
|
test('should treat the praetorian id as optional', () => {
|
|
131
160
|
const badge = new Badge(badgeDataFixture.create({ setTitleId: [123] }))
|
|
132
|
-
expect(badge.setTitleId).
|
|
161
|
+
expect(badge.setTitleId?.primal).toEqual(123)
|
|
162
|
+
expect(badge.setTitleId?.praetorian).toBeUndefined()
|
|
133
163
|
})
|
|
134
164
|
|
|
135
165
|
test('should be optional', () => {
|
|
@@ -159,7 +189,19 @@ describe(Badge.name, () => {
|
|
|
159
189
|
badgeRequirementDataFixture.create({ key: 'foo' }),
|
|
160
190
|
],
|
|
161
191
|
})
|
|
162
|
-
expect(() => new Badge(data)).toThrow('Duplicate
|
|
192
|
+
expect(() => new Badge(data)).toThrow('Duplicate key [foo]')
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
test(`should return requirement list`, () => {
|
|
196
|
+
const data = badgeDataFixture.create({
|
|
197
|
+
requirements: [
|
|
198
|
+
badgeRequirementDataFixture.create({ key: 'foo' }),
|
|
199
|
+
badgeRequirementDataFixture.create({ key: 'bar' }),
|
|
200
|
+
],
|
|
201
|
+
})
|
|
202
|
+
const badge = new Badge(data)
|
|
203
|
+
|
|
204
|
+
expect(badge.requirements.map(x => x.key)).toStrictEqual(['foo', 'bar'])
|
|
163
205
|
})
|
|
164
206
|
})
|
|
165
207
|
|
|
@@ -172,12 +214,12 @@ describe(Badge.name, () => {
|
|
|
172
214
|
expect(new Badge(data).getRequirement('foo')).not.toBeUndefined()
|
|
173
215
|
})
|
|
174
216
|
|
|
175
|
-
test(`should
|
|
217
|
+
test(`should return undefined for unknown requirement`, () => {
|
|
176
218
|
const data = badgeDataFixture.create({
|
|
177
219
|
requirements: [],
|
|
178
220
|
})
|
|
179
221
|
|
|
180
|
-
expect(
|
|
222
|
+
expect(new Badge(data).getRequirement('foo')).toBeUndefined()
|
|
181
223
|
})
|
|
182
224
|
})
|
|
183
225
|
|
|
@@ -214,6 +256,17 @@ describe(Badge.name, () => {
|
|
|
214
256
|
}))
|
|
215
257
|
expect(badge.zoneKeys).toStrictEqual(['a', 'c'])
|
|
216
258
|
})
|
|
259
|
+
|
|
260
|
+
test(`should ignore locations with no zone key`, () => {
|
|
261
|
+
const badge = new Badge(badgeDataFixture.create({
|
|
262
|
+
requirements: [
|
|
263
|
+
badgeRequirementDataFixture.create({ location: { zoneKey: 'a' } }),
|
|
264
|
+
badgeRequirementDataFixture.create({ location: { coords: [1, 2, 3] } }),
|
|
265
|
+
badgeRequirementDataFixture.create({ location: { zoneKey: 'c' } }),
|
|
266
|
+
],
|
|
267
|
+
}))
|
|
268
|
+
expect(badge.zoneKeys).toStrictEqual(['a', 'c'])
|
|
269
|
+
})
|
|
217
270
|
})
|
|
218
271
|
|
|
219
272
|
describe('zoneKey', () => {
|
|
@@ -246,31 +299,53 @@ describe(Badge.name, () => {
|
|
|
246
299
|
})
|
|
247
300
|
})
|
|
248
301
|
|
|
249
|
-
describe(
|
|
302
|
+
describe(compareByName.name, () => {
|
|
250
303
|
test(`should compare two badges by name`, () => {
|
|
251
304
|
const badgeA = new Badge(badgeDataFixture.create({ name: 'A' }))
|
|
252
305
|
const badgeB = new Badge(badgeDataFixture.create({ name: 'B' }))
|
|
253
|
-
expect(
|
|
254
|
-
expect([badgeB, badgeA].
|
|
306
|
+
expect(compareByName(badgeA, badgeB)).toBeLessThan(0)
|
|
307
|
+
expect([badgeB, badgeA].toSorted(compareByName)).toStrictEqual([badgeA, badgeB])
|
|
255
308
|
})
|
|
256
309
|
|
|
257
310
|
test(`should return 0 for equal names`, () => {
|
|
258
311
|
const badgeA = new Badge(badgeDataFixture.create({ name: 'A' }))
|
|
259
312
|
const badgeB = new Badge(badgeDataFixture.create({ name: 'A' }))
|
|
260
|
-
expect(
|
|
313
|
+
expect(compareByName(badgeA, badgeB)).toEqual(0)
|
|
261
314
|
})
|
|
262
315
|
|
|
263
316
|
test(`should compare two undefined values`, () => {
|
|
264
317
|
const badgeA = new Badge(badgeDataFixture.create({ name: [] }))
|
|
265
318
|
const badgeB = new Badge(badgeDataFixture.create({ name: [] }))
|
|
266
|
-
expect(
|
|
319
|
+
expect(compareByName(badgeA, badgeB)).toEqual(0)
|
|
267
320
|
})
|
|
268
321
|
|
|
269
322
|
test(`should sort undefined values last`, () => {
|
|
270
323
|
const badgeA = new Badge(badgeDataFixture.create({ name: 'A' }))
|
|
271
324
|
const badgeB = new Badge(badgeDataFixture.create({ name: [] }))
|
|
272
|
-
expect([badgeA, badgeB].
|
|
273
|
-
expect([badgeB, badgeA].
|
|
325
|
+
expect([badgeA, badgeB].toSorted(compareByName)).toStrictEqual([badgeA, badgeB])
|
|
326
|
+
expect([badgeB, badgeA].toSorted(compareByName)).toStrictEqual([badgeA, badgeB])
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
test(`should take morality context into account`, () => {
|
|
330
|
+
const badgeA = new Badge(badgeDataFixture.create({ name: [{ value: 'ZZZ' }, { alignment: 'villain', value: 'AAA' }] }))
|
|
331
|
+
const badgeB = new Badge(badgeDataFixture.create({ name: 'B' }))
|
|
332
|
+
expect([badgeA, badgeB].toSorted((a, b) => compareByName(a, b, { morality: 'villain' }))).toStrictEqual([badgeA, badgeB])
|
|
333
|
+
expect([badgeA, badgeB].toSorted((a, b) => compareByName(a, b, {}))).toStrictEqual([badgeB, badgeA])
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
test(`should take sex context into account`, () => {
|
|
337
|
+
const badgeA = new Badge(badgeDataFixture.create({ name: [{ value: 'ZZZ' }, { sex: 'F', value: 'AAA' }] }))
|
|
338
|
+
const badgeB = new Badge(badgeDataFixture.create({ name: 'B' }))
|
|
339
|
+
expect([badgeA, badgeB].toSorted((a, b) => compareByName(a, b, { sex: 'F' }))).toStrictEqual([badgeA, badgeB])
|
|
340
|
+
expect([badgeA, badgeB].toSorted((a, b) => compareByName(a, b, {}))).toStrictEqual([badgeB, badgeA])
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
test(`should take full variant context into account`, () => {
|
|
344
|
+
const badgeA = new Badge(badgeDataFixture.create({ name: [{ value: 'A' }, { sex: 'F', value: 'B' }] }))
|
|
345
|
+
const badgeB = new Badge(badgeDataFixture.create({ name: [{ value: 'B' }, { alignment: 'praetorian', sex: 'F', value: 'A' }] }))
|
|
346
|
+
const badgeC = new Badge(badgeDataFixture.create({ name: 'C' }))
|
|
347
|
+
expect([badgeA, badgeB, badgeC].toSorted((a, b) => compareByName(a, b, { morality: 'resistance', sex: 'F' }))).toStrictEqual([badgeB, badgeA, badgeC])
|
|
348
|
+
expect([badgeA, badgeB, badgeC].toSorted((a, b) => compareByName(a, b, {}))).toStrictEqual([badgeA, badgeB, badgeC])
|
|
274
349
|
})
|
|
275
350
|
})
|
|
276
351
|
|
|
@@ -287,7 +362,7 @@ describe(Badge.name, () => {
|
|
|
287
362
|
],
|
|
288
363
|
}))
|
|
289
364
|
expect(compareByZoneKey(badgeA, badgeB)).toBeLessThan(0)
|
|
290
|
-
expect([badgeB, badgeA].
|
|
365
|
+
expect([badgeB, badgeA].toSorted(compareByZoneKey)).toStrictEqual([badgeA, badgeB])
|
|
291
366
|
})
|
|
292
367
|
|
|
293
368
|
test(`should return 0 for equal zoneKeys`, () => {
|
|
@@ -330,8 +405,39 @@ describe(Badge.name, () => {
|
|
|
330
405
|
badgeRequirementDataFixture.create({ location: { zoneKey: 'c' } }),
|
|
331
406
|
],
|
|
332
407
|
}))
|
|
333
|
-
expect([badgeA, badgeB].
|
|
334
|
-
expect([badgeB, badgeA].
|
|
408
|
+
expect([badgeA, badgeB].toSorted(compareByZoneKey)).toStrictEqual([badgeA, badgeB])
|
|
409
|
+
expect([badgeB, badgeA].toSorted(compareByZoneKey)).toStrictEqual([badgeA, badgeB])
|
|
410
|
+
})
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
describe(compareByReleaseDate.name, () => {
|
|
414
|
+
test(`should compare two badges by releaseDate`, () => {
|
|
415
|
+
const badgeA = new Badge(badgeDataFixture.create({ releaseDate: '2024-01-01' }))
|
|
416
|
+
const badgeB = new Badge(badgeDataFixture.create({ releaseDate: '2025-01-01' }))
|
|
417
|
+
expect(compareByReleaseDate(badgeA, badgeB)).toBeLessThan(0)
|
|
418
|
+
expect([badgeB, badgeA].toSorted(compareByReleaseDate)).toStrictEqual([badgeA, badgeB])
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
test(`should return 0 for equal releaseDates`, () => {
|
|
422
|
+
const badgeA = new Badge(badgeDataFixture.create({ releaseDate: '2025-01-01' }))
|
|
423
|
+
const badgeB = new Badge(badgeDataFixture.create({ releaseDate: '2025-01-01' }))
|
|
424
|
+
expect(compareByReleaseDate(badgeA, badgeB)).toEqual(0)
|
|
425
|
+
})
|
|
426
|
+
|
|
427
|
+
test(`should equate two undefined values`, () => {
|
|
428
|
+
const badgeA = undefined
|
|
429
|
+
const badgeB = undefined
|
|
430
|
+
expect(compareByReleaseDate(badgeA, badgeB)).toEqual(0)
|
|
431
|
+
})
|
|
432
|
+
|
|
433
|
+
test(`should compare undefined value as higher`, () => {
|
|
434
|
+
const badgeA = undefined
|
|
435
|
+
const badgeB = new Badge(badgeDataFixture.create({ releaseDate: '2025-01-01' }))
|
|
436
|
+
expect(compareByReleaseDate(badgeA, badgeB)).toBeGreaterThan(0)
|
|
437
|
+
expect([badgeA, badgeB].toSorted(compareByReleaseDate)).toStrictEqual([badgeB, badgeA])
|
|
438
|
+
|
|
439
|
+
expect(compareByReleaseDate(badgeB, badgeA)).toBeLessThan(0)
|
|
440
|
+
expect([badgeB, badgeA].toSorted(compareByReleaseDate)).toStrictEqual([badgeB, badgeA])
|
|
335
441
|
})
|
|
336
442
|
})
|
|
337
443
|
})
|
|
@@ -14,6 +14,31 @@ describe(BundleHeader.name, () => {
|
|
|
14
14
|
})
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
+
describe('version', () => {
|
|
18
|
+
test(`should be set from the data`, () => {
|
|
19
|
+
const header = new BundleHeader(bundleHeaderDataFixture.create({ version: 'foo' }))
|
|
20
|
+
expect(header.version).toEqual('foo')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test(`should be optional`, () => {
|
|
24
|
+
const header = new BundleHeader(bundleHeaderDataFixture.omit('version').create())
|
|
25
|
+
expect(header.version).toBeUndefined()
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
describe('releaseDate', () => {
|
|
30
|
+
test('should be set from the data', () => {
|
|
31
|
+
const header = new BundleHeader(bundleHeaderDataFixture.create({ lastUpdateTime: '2025-04-21T01:02:03Z' }))
|
|
32
|
+
expect(header.lastUpdateTime).toStrictEqual(new Date('2025-04-21T01:02:03Z'))
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('should not accept an invalid date', () => {
|
|
36
|
+
expect(() =>
|
|
37
|
+
new BundleHeader(bundleHeaderDataFixture.create({ lastUpdateTime: 'blah' })),
|
|
38
|
+
).toThrow('Invalid date')
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
17
42
|
describe('description', () => {
|
|
18
43
|
test(`should be set from the data`, () => {
|
|
19
44
|
const header = new BundleHeader(bundleHeaderDataFixture.create({ description: 'foo' }))
|
|
@@ -61,16 +86,4 @@ describe(BundleHeader.name, () => {
|
|
|
61
86
|
expect(header.links).toHaveLength(0)
|
|
62
87
|
})
|
|
63
88
|
})
|
|
64
|
-
|
|
65
|
-
describe('version', () => {
|
|
66
|
-
test(`should be set from the data`, () => {
|
|
67
|
-
const header = new BundleHeader(bundleHeaderDataFixture.create({ version: 'foo' }))
|
|
68
|
-
expect(header.version).toEqual('foo')
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
test(`should be optional`, () => {
|
|
72
|
-
const header = new BundleHeader(bundleHeaderDataFixture.omit('version').create())
|
|
73
|
-
expect(header.version).toBeUndefined()
|
|
74
|
-
})
|
|
75
|
-
})
|
|
76
89
|
})
|