coh-content-db 2.0.0-rc.16 → 2.0.0-rc.18
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 +1 -1
- package/CHANGELOG.md +3 -1
- package/dist/coh-content-db.d.ts +95 -37
- package/dist/coh-content-db.js +189 -80
- package/dist/coh-content-db.js.map +1 -1
- package/dist/coh-content-db.mjs +187 -81
- package/dist/coh-content-db.mjs.map +1 -1
- package/jest.config.mjs +1 -0
- package/package.json +1 -1
- package/src/main/api/badge-data.ts +2 -1
- 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/set-title-data.ts +4 -0
- package/src/main/api/zone-data.ts +24 -0
- package/src/main/api/zone-type.ts +59 -0
- package/src/main/db/badge-index.ts +3 -1
- package/src/main/db/badge.ts +3 -2
- package/src/main/db/contact.ts +4 -3
- package/src/main/db/level-range.ts +15 -0
- package/src/main/db/mission.ts +10 -9
- package/src/main/db/set-title-ids.ts +10 -0
- package/src/main/db/zone.ts +29 -0
- package/src/main/index.ts +6 -0
- package/src/test/api/zone-data.fixture.ts +1 -0
- package/src/test/db/badge.test.ts +4 -2
- 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/zone.test.ts +45 -0
package/src/main/db/contact.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { ContactData } from '../api/contact-data'
|
|
|
5
5
|
import { Location } from './location'
|
|
6
6
|
import { MoralityList } from './morality-list'
|
|
7
7
|
import { coalesceToArray } from '../util/coalesce-to-array'
|
|
8
|
+
import { LevelRange } from './level-range'
|
|
8
9
|
|
|
9
10
|
export class Contact {
|
|
10
11
|
/**
|
|
@@ -27,7 +28,7 @@ export class Contact {
|
|
|
27
28
|
/**
|
|
28
29
|
* The character moralities that this contact will interact with.
|
|
29
30
|
*/
|
|
30
|
-
readonly morality
|
|
31
|
+
readonly morality: MoralityList
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* The location of this contact.
|
|
@@ -37,7 +38,7 @@ export class Contact {
|
|
|
37
38
|
/**
|
|
38
39
|
* The level range this contact will offer missions for.
|
|
39
40
|
*/
|
|
40
|
-
readonly levelRange?:
|
|
41
|
+
readonly levelRange?: LevelRange
|
|
41
42
|
|
|
42
43
|
/**
|
|
43
44
|
* Freeform notes or tips about the contact.
|
|
@@ -55,7 +56,7 @@ export class Contact {
|
|
|
55
56
|
this.title = data.title
|
|
56
57
|
this.morality = new MoralityList(coalesceToArray(data.morality))
|
|
57
58
|
this.location = data.location
|
|
58
|
-
this.levelRange = data.levelRange
|
|
59
|
+
this.levelRange = data.levelRange ? new LevelRange(data.levelRange) : undefined
|
|
59
60
|
this.notes = data.notes
|
|
60
61
|
this.links = data.links ?? []
|
|
61
62
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { LevelRangeData } from '../api/level-range-data'
|
|
2
|
+
|
|
3
|
+
export class LevelRange {
|
|
4
|
+
readonly min: number
|
|
5
|
+
readonly max?: number
|
|
6
|
+
|
|
7
|
+
constructor(value: LevelRangeData) {
|
|
8
|
+
if (Array.isArray(value)) {
|
|
9
|
+
this.min = value[0]
|
|
10
|
+
this.max = value[1] === undefined ? undefined : value[1]
|
|
11
|
+
} else {
|
|
12
|
+
this.min = value
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
package/src/main/db/mission.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { MissionData } from '../api/mission-data'
|
|
|
5
5
|
import { Key } from './key'
|
|
6
6
|
import { MoralityList } from './morality-list'
|
|
7
7
|
import { coalesceToArray } from '../util/coalesce-to-array'
|
|
8
|
+
import { LevelRange } from './level-range'
|
|
8
9
|
|
|
9
10
|
export class Mission {
|
|
10
11
|
/**
|
|
@@ -39,7 +40,7 @@ export class Mission {
|
|
|
39
40
|
/**
|
|
40
41
|
* The level range this mission is available for.
|
|
41
42
|
*/
|
|
42
|
-
readonly levelRange?:
|
|
43
|
+
readonly levelRange?: LevelRange
|
|
43
44
|
|
|
44
45
|
/**
|
|
45
46
|
* Freeform notes or tips about the mission.
|
|
@@ -62,19 +63,19 @@ export class Mission {
|
|
|
62
63
|
readonly id: string
|
|
63
64
|
|
|
64
65
|
/**
|
|
65
|
-
* The level range this mission appears under as a Flashback.
|
|
66
|
+
* The level range this mission appears under as a Flashback.
|
|
66
67
|
*/
|
|
67
|
-
readonly levelRange?:
|
|
68
|
+
readonly levelRange?: LevelRange
|
|
68
69
|
|
|
69
70
|
/**
|
|
70
|
-
* The name as it appears in the Flashback list.
|
|
71
|
+
* The name as it appears in the Flashback list.
|
|
71
72
|
*/
|
|
72
|
-
readonly name
|
|
73
|
+
readonly name: string
|
|
73
74
|
|
|
74
75
|
/**
|
|
75
|
-
* The character moralities that the mission will appear for in the Flashback list.
|
|
76
|
+
* The character moralities that the mission will appear for in the Flashback list.
|
|
76
77
|
*/
|
|
77
|
-
readonly morality
|
|
78
|
+
readonly morality: MoralityList
|
|
78
79
|
|
|
79
80
|
/**
|
|
80
81
|
* Freeform notes or tips about the Flashback version of the mission.
|
|
@@ -88,7 +89,7 @@ export class Mission {
|
|
|
88
89
|
this.type = data.type
|
|
89
90
|
this.morality = new MoralityList(coalesceToArray(data.morality))
|
|
90
91
|
this.contactKeys = coalesceToArray(data.contactKeys)
|
|
91
|
-
this.levelRange = data.levelRange
|
|
92
|
+
this.levelRange = data.levelRange ? new LevelRange(data.levelRange) : undefined
|
|
92
93
|
this.notes = data.notes
|
|
93
94
|
this.links = data.links ?? []
|
|
94
95
|
this.flashback = createFlashback(data)
|
|
@@ -99,7 +100,7 @@ function createFlashback(data: MissionData): Mission['flashback'] {
|
|
|
99
100
|
if (!data.flashback) return undefined
|
|
100
101
|
return {
|
|
101
102
|
id: data.flashback.id,
|
|
102
|
-
levelRange: data.flashback.levelRange
|
|
103
|
+
levelRange: data.flashback.levelRange ? new LevelRange(data.flashback.levelRange) : undefined,
|
|
103
104
|
name: data.flashback.name ?? data.name,
|
|
104
105
|
morality: new MoralityList(coalesceToArray(data.flashback.morality ?? data.morality)),
|
|
105
106
|
notes: data.flashback.notes,
|
package/src/main/db/zone.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { Link } from '../api/link'
|
|
2
2
|
import { ZoneData } from '../api/zone-data'
|
|
3
3
|
import { Key } from './key'
|
|
4
|
+
import { MoralityList } from './morality-list'
|
|
5
|
+
import { coalesceToArray } from '../util/coalesce-to-array'
|
|
6
|
+
import { ZoneType } from '../api/zone-type'
|
|
7
|
+
import { MarkdownString } from '../api/markdown-string'
|
|
8
|
+
import { LevelRange } from './level-range'
|
|
4
9
|
|
|
5
10
|
export class Zone {
|
|
6
11
|
/**
|
|
@@ -15,6 +20,26 @@ export class Zone {
|
|
|
15
20
|
*/
|
|
16
21
|
readonly name: string
|
|
17
22
|
|
|
23
|
+
/**
|
|
24
|
+
* The type of zone.
|
|
25
|
+
*/
|
|
26
|
+
readonly type: ZoneType
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The character moralities that this zone is accessible by.
|
|
30
|
+
*/
|
|
31
|
+
readonly morality: MoralityList
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The level range this zone is recommended for.
|
|
35
|
+
*/
|
|
36
|
+
readonly levelRange?: LevelRange
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Freeform notes or tips about the zone.
|
|
40
|
+
*/
|
|
41
|
+
readonly notes?: MarkdownString
|
|
42
|
+
|
|
18
43
|
/**
|
|
19
44
|
* List of external links. Wiki, forums, etc.
|
|
20
45
|
*/
|
|
@@ -23,6 +48,10 @@ export class Zone {
|
|
|
23
48
|
constructor(data: ZoneData) {
|
|
24
49
|
this.key = new Key(data.key).value
|
|
25
50
|
this.name = data.name
|
|
51
|
+
this.type = data.type
|
|
52
|
+
this.morality = new MoralityList(coalesceToArray(data.morality))
|
|
53
|
+
this.levelRange = data.levelRange ? new LevelRange(data.levelRange) : undefined
|
|
54
|
+
this.notes = data.notes
|
|
26
55
|
this.links = data.links ?? []
|
|
27
56
|
}
|
|
28
57
|
}
|
package/src/main/index.ts
CHANGED
|
@@ -12,12 +12,16 @@ export * from './api/contact-data'
|
|
|
12
12
|
export * from './api/enhancement-category'
|
|
13
13
|
export * from './api/link'
|
|
14
14
|
export * from './api/location-data'
|
|
15
|
+
export * from './api/level-range-data'
|
|
15
16
|
export * from './api/markdown-string'
|
|
16
17
|
export * from './api/mission-data'
|
|
18
|
+
export * from './api/mission-flashback-data'
|
|
17
19
|
export * from './api/mission-type'
|
|
18
20
|
export * from './api/morality'
|
|
21
|
+
export * from './api/set-title-data'
|
|
19
22
|
export * from './api/sex'
|
|
20
23
|
export * from './api/zone-data'
|
|
24
|
+
export * from './api/zone-type'
|
|
21
25
|
|
|
22
26
|
// DB
|
|
23
27
|
export * from './db/alignment-list'
|
|
@@ -32,9 +36,11 @@ export * from './db/coh-content-database'
|
|
|
32
36
|
export * from './db/contact'
|
|
33
37
|
export * from './db/key'
|
|
34
38
|
export * from './db/location'
|
|
39
|
+
export * from './db/level-range'
|
|
35
40
|
export * from './db/mission'
|
|
36
41
|
export * from './db/morality-list'
|
|
37
42
|
export * from './db/paged'
|
|
43
|
+
export * from './db/set-title-ids'
|
|
38
44
|
export * from './db/zone'
|
|
39
45
|
|
|
40
46
|
// UTILS
|
|
@@ -4,5 +4,6 @@ import { defineFixture } from 'efate'
|
|
|
4
4
|
export const zoneDataFixture = defineFixture<ZoneData>((t) => {
|
|
5
5
|
t.key.as(index => `zone-${index}`)
|
|
6
6
|
t.name.as(index => `Zone ${index}`)
|
|
7
|
+
t.type.withValue('city')
|
|
7
8
|
t.links?.as(() => [{ title: 'foo', href: 'https://nouri.org' }])
|
|
8
9
|
})
|
|
@@ -152,12 +152,14 @@ describe(Badge.name, () => {
|
|
|
152
152
|
describe('setTitle', () => {
|
|
153
153
|
test('should be set from the data', () => {
|
|
154
154
|
const badge = new Badge(badgeDataFixture.create({ setTitleId: [123, 456] }))
|
|
155
|
-
expect(badge.setTitleId).
|
|
155
|
+
expect(badge.setTitleId?.primal).toEqual(123)
|
|
156
|
+
expect(badge.setTitleId?.praetorian).toEqual(456)
|
|
156
157
|
})
|
|
157
158
|
|
|
158
159
|
test('should treat the praetorian id as optional', () => {
|
|
159
160
|
const badge = new Badge(badgeDataFixture.create({ setTitleId: [123] }))
|
|
160
|
-
expect(badge.setTitleId).
|
|
161
|
+
expect(badge.setTitleId?.primal).toEqual(123)
|
|
162
|
+
expect(badge.setTitleId?.praetorian).toBeUndefined()
|
|
161
163
|
})
|
|
162
164
|
|
|
163
165
|
test('should be optional', () => {
|
|
@@ -62,7 +62,8 @@ describe(Contact.name, () => {
|
|
|
62
62
|
describe('levelRange', () => {
|
|
63
63
|
test(`should be set from the data`, () => {
|
|
64
64
|
const contact = new Contact(contactDataFixture.create({ levelRange: [1, 2] }))
|
|
65
|
-
expect(contact
|
|
65
|
+
expect(contact?.levelRange?.min).toEqual(1)
|
|
66
|
+
expect(contact?.levelRange?.max).toEqual(2)
|
|
66
67
|
})
|
|
67
68
|
|
|
68
69
|
test(`should be optional`, () => {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { LevelRange } from '../../main'
|
|
2
|
+
|
|
3
|
+
describe(LevelRange.name, () => {
|
|
4
|
+
describe('Constructor', () => {
|
|
5
|
+
test('should accept a full array (5-10)', () => {
|
|
6
|
+
const range = new LevelRange([5, 10])
|
|
7
|
+
expect(range).toBeDefined()
|
|
8
|
+
expect(range.min).toEqual(5)
|
|
9
|
+
expect(range.max).toEqual(10)
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('should accept a partial array (15+)', () => {
|
|
13
|
+
const range = new LevelRange([15])
|
|
14
|
+
expect(range).toBeDefined()
|
|
15
|
+
expect(range.min).toEqual(15)
|
|
16
|
+
expect(range.max).toBeUndefined()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test('should not coalesce a explicit max of 50 (20-50)', () => {
|
|
20
|
+
const range = new LevelRange([20, 50])
|
|
21
|
+
expect(range).toBeDefined()
|
|
22
|
+
expect(range.min).toEqual(20)
|
|
23
|
+
expect(range.max).toEqual(50)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('should accept a single-level range (1-1)', () => {
|
|
27
|
+
const range = new LevelRange([1, 1])
|
|
28
|
+
expect(range).toBeDefined()
|
|
29
|
+
expect(range.min).toEqual(1)
|
|
30
|
+
expect(range.max).toEqual(1)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('should accept a zero value (0-0)', () => {
|
|
34
|
+
const range = new LevelRange([0, 0])
|
|
35
|
+
expect(range).toBeDefined()
|
|
36
|
+
expect(range.min).toEqual(0)
|
|
37
|
+
expect(range.max).toEqual(0)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('should accept a number (5+)', () => {
|
|
41
|
+
const range = new LevelRange(5)
|
|
42
|
+
expect(range).toBeDefined()
|
|
43
|
+
expect(range.min).toEqual(5)
|
|
44
|
+
expect(range.max).toBeUndefined()
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
})
|
|
@@ -56,8 +56,9 @@ describe(Mission.name, () => {
|
|
|
56
56
|
|
|
57
57
|
describe('levelRange', () => {
|
|
58
58
|
test(`should be set from the data`, () => {
|
|
59
|
-
const mission = new Mission(missionDataFixture.create({ levelRange:
|
|
60
|
-
expect(mission
|
|
59
|
+
const mission = new Mission(missionDataFixture.create({ levelRange: 25 }))
|
|
60
|
+
expect(mission?.levelRange?.min).toEqual(25)
|
|
61
|
+
expect(mission?.levelRange?.max).toBeUndefined()
|
|
61
62
|
})
|
|
62
63
|
|
|
63
64
|
test(`should be optional`, () => {
|
|
@@ -105,13 +106,14 @@ describe(Mission.name, () => {
|
|
|
105
106
|
|
|
106
107
|
describe('levelRange', () => {
|
|
107
108
|
test(`should be set from the data`, () => {
|
|
108
|
-
const mission = new Mission(missionDataFixture.create({ flashback: { levelRange: [1,
|
|
109
|
-
expect(mission.flashback?.levelRange).
|
|
109
|
+
const mission = new Mission(missionDataFixture.create({ flashback: { levelRange: [1, 20] } }))
|
|
110
|
+
expect(mission.flashback?.levelRange?.min).toEqual(1)
|
|
111
|
+
expect(mission.flashback?.levelRange?.max).toEqual(20)
|
|
110
112
|
})
|
|
111
113
|
|
|
112
|
-
test(`should default to the mission value`, () => {
|
|
114
|
+
test(`should *not* default to the mission value due to Ouro level grouping`, () => {
|
|
113
115
|
const mission = new Mission(missionDataFixture.create({ levelRange: [1, 2], flashback: missionFlashbackDataFixture.omit('levelRange').create() }))
|
|
114
|
-
expect(mission.flashback?.levelRange).
|
|
116
|
+
expect(mission.flashback?.levelRange).toBeUndefined()
|
|
115
117
|
})
|
|
116
118
|
|
|
117
119
|
test(`should be optional`, () => {
|
|
@@ -29,7 +29,7 @@ describe(MoralityList.name, () => {
|
|
|
29
29
|
expect(new MoralityList().items).toStrictEqual(['hero', 'vigilante', 'villain', 'rogue', 'resistance', 'loyalist'])
|
|
30
30
|
})
|
|
31
31
|
|
|
32
|
-
test('should treat empty as no values', () => {
|
|
32
|
+
test('should treat explicit empty as no values', () => {
|
|
33
33
|
expect(new MoralityList([]).items).toStrictEqual([])
|
|
34
34
|
})
|
|
35
35
|
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SetTitleIds } from '../../main'
|
|
2
|
+
|
|
3
|
+
describe(SetTitleIds.name, () => {
|
|
4
|
+
describe('Constructor', () => {
|
|
5
|
+
test('should accept both primal and praetorian values', () => {
|
|
6
|
+
const ids = new SetTitleIds([5, 10])
|
|
7
|
+
expect(ids).toBeDefined()
|
|
8
|
+
expect(ids.primal).toEqual(5)
|
|
9
|
+
expect(ids.praetorian).toEqual(10)
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('should accept primal only', () => {
|
|
13
|
+
const ids = new SetTitleIds([1])
|
|
14
|
+
expect(ids).toBeDefined()
|
|
15
|
+
expect(ids.primal).toEqual(1)
|
|
16
|
+
expect(ids.praetorian).toBeUndefined()
|
|
17
|
+
})
|
|
18
|
+
})
|
|
19
|
+
})
|
package/src/test/db/zone.test.ts
CHANGED
|
@@ -22,6 +22,51 @@ describe(Zone.name, () => {
|
|
|
22
22
|
})
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
+
describe('type', () => {
|
|
26
|
+
test(`should be set from the data`, () => {
|
|
27
|
+
const zone = new Zone(zoneDataFixture.create({ type: 'city' }))
|
|
28
|
+
expect(zone.type).toEqual('city')
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
describe('morality', () => {
|
|
33
|
+
test(`should be set from the data`, () => {
|
|
34
|
+
const zone = new Zone(zoneDataFixture.create({ morality: ['hero'] }))
|
|
35
|
+
expect(zone.morality?.hero).toBeTruthy()
|
|
36
|
+
expect(zone.morality?.vigilante).toBeFalsy()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test(`should be optional`, () => {
|
|
40
|
+
const zone = new Zone(zoneDataFixture.omit('morality').create())
|
|
41
|
+
expect(zone.morality?.all).toBeTruthy()
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
describe('levelRange', () => {
|
|
46
|
+
test(`should be set from the data`, () => {
|
|
47
|
+
const zone = new Zone(zoneDataFixture.create({ levelRange: [10] }))
|
|
48
|
+
expect(zone.levelRange?.min).toEqual(10)
|
|
49
|
+
expect(zone.levelRange?.max).toBeUndefined()
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test(`should be optional`, () => {
|
|
53
|
+
const zone = new Zone(zoneDataFixture.omit('levelRange').create())
|
|
54
|
+
expect(zone.levelRange).toBeUndefined()
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
describe('notes', () => {
|
|
59
|
+
test(`should be set from the data`, () => {
|
|
60
|
+
const zone = new Zone(zoneDataFixture.create({ notes: 'foo' }))
|
|
61
|
+
expect(zone.notes).toEqual('foo')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test(`should be optional`, () => {
|
|
65
|
+
const zone = new Zone(zoneDataFixture.omit('notes').create())
|
|
66
|
+
expect(zone.notes).toBeUndefined()
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
|
|
25
70
|
describe('links', () => {
|
|
26
71
|
test(`should be set from the data`, () => {
|
|
27
72
|
const zone = new Zone(zoneDataFixture.create({ links: [{ title: 'foo', href: 'bar' }] }))
|