coh-content-db 2.0.0-rc.7 → 2.0.0-rc.9
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/.github/workflows/pull-request.yml +1 -1
- package/.github/workflows/release.yml +1 -1
- package/CHANGELOG.md +38 -0
- package/README.md +24 -7
- package/dist/coh-content-db.d.ts +108 -64
- package/dist/coh-content-db.js +232 -210
- package/dist/coh-content-db.js.map +1 -1
- package/dist/coh-content-db.mjs +232 -209
- package/dist/coh-content-db.mjs.map +1 -1
- package/package.json +1 -1
- package/src/main/api/{content-bundle.ts → bundle-data.ts} +5 -27
- package/src/main/api/bundle-header-data.ts +37 -0
- package/src/main/db/abstract-index.ts +41 -0
- package/src/main/db/badge-index.ts +7 -18
- package/src/main/db/bundle-header.ts +44 -0
- package/src/main/db/coh-content-database.ts +81 -72
- package/src/main/index.ts +3 -4
- package/src/test/api/bundle-data.fixture.ts +6 -0
- package/src/test/api/bundle-header-data.fixture.ts +6 -0
- package/src/test/db/abstract-index.test.ts +86 -0
- package/src/test/db/badge-index.test.ts +149 -122
- package/src/test/db/bundle-header.test.ts +76 -0
- package/src/test/db/coh-content-database.test.ts +164 -79
- package/src/test/integration.test.ts +16 -0
- package/src/main/api/change.ts +0 -17
- package/src/main/changelog.ts +0 -29
- package/src/main/db/bundle-metadata.ts +0 -39
- package/src/test/api/content-bundle.fixture.ts +0 -6
- package/src/test/api/content-bundle.test.ts +0 -14
- package/src/test/changelog.test.ts +0 -36
- package/src/test/db/bundle-metadata.test.ts +0 -67
- package/src/test/index.test.ts +0 -14
|
@@ -1,120 +1,129 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BundleData } from '../api/bundle-data'
|
|
2
2
|
import { Archetype } from './archetype'
|
|
3
3
|
import { Zone } from './zone'
|
|
4
4
|
import { Badge } from './badge'
|
|
5
|
-
import {
|
|
5
|
+
import { BundleHeader } from './bundle-header'
|
|
6
6
|
import { BadgeIndex } from './badge-index'
|
|
7
7
|
import { BadgeSearchOptions } from './badge-search-options'
|
|
8
8
|
import { Paged } from './paged'
|
|
9
9
|
import { Contact } from './contact'
|
|
10
10
|
import { Mission } from './mission'
|
|
11
|
+
import { AbstractIndex } from './abstract-index'
|
|
11
12
|
|
|
12
13
|
export class CohContentDatabase {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
#archetypeIndex = new AbstractIndex<Archetype>('key')
|
|
15
|
+
#zoneIndex = new AbstractIndex<Zone>('key')
|
|
16
|
+
#contactIndex = new AbstractIndex<Contact>('key')
|
|
17
|
+
#missionIndex = new AbstractIndex<Mission>('key')
|
|
18
|
+
#badgeIndex = new BadgeIndex()
|
|
19
|
+
|
|
20
|
+
#header?: BundleHeader
|
|
21
|
+
#servers?: string[]
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Load the given content bundle, resetting the db if a bundle is already loaded.
|
|
25
|
+
* @param bundle The bundle to load.
|
|
26
|
+
*/
|
|
27
|
+
load(bundle: BundleData): void {
|
|
28
|
+
this.#header = new BundleHeader(bundle.header)
|
|
29
|
+
this.#servers = bundle.servers ?? []
|
|
30
|
+
|
|
31
|
+
this.#archetypeIndex.load(bundle.archetypes?.map(x => new Archetype(x)))
|
|
32
|
+
this.#zoneIndex.load(bundle.zones?.map(x => new Zone(x)))
|
|
33
|
+
this.#contactIndex.load(bundle.contacts?.map(x => new Contact(x)))
|
|
34
|
+
this.#missionIndex.load(bundle.missions?.map(x => new Mission(x)))
|
|
35
|
+
this.#badgeIndex.load(bundle.badges?.map(x => new Badge(x)))
|
|
36
|
+
}
|
|
18
37
|
|
|
19
38
|
/**
|
|
20
|
-
*
|
|
39
|
+
* Header information about the content bundle.
|
|
21
40
|
*/
|
|
22
|
-
|
|
41
|
+
get header(): BundleHeader | undefined {
|
|
42
|
+
return this.#header
|
|
43
|
+
}
|
|
23
44
|
|
|
24
45
|
/**
|
|
25
46
|
* List of the game server names.
|
|
26
47
|
*
|
|
27
48
|
* Torchbearer, Excelsior, etc.
|
|
28
49
|
*/
|
|
29
|
-
|
|
50
|
+
get servers(): string[] {
|
|
51
|
+
return this.#servers ?? []
|
|
52
|
+
}
|
|
30
53
|
|
|
31
54
|
/**
|
|
32
55
|
* List of archetypes.
|
|
33
56
|
*/
|
|
34
|
-
|
|
57
|
+
get archetypes(): Archetype[] {
|
|
58
|
+
return this.#archetypeIndex.values
|
|
59
|
+
}
|
|
35
60
|
|
|
36
61
|
/**
|
|
37
|
-
*
|
|
62
|
+
* Get archetype by key.
|
|
63
|
+
* @param key The key.
|
|
38
64
|
*/
|
|
39
|
-
|
|
65
|
+
getArchetype(key: string | undefined): Archetype | undefined {
|
|
66
|
+
return this.#archetypeIndex.get(key)
|
|
67
|
+
}
|
|
40
68
|
|
|
41
69
|
/**
|
|
42
|
-
* List of
|
|
70
|
+
* List of game zones.
|
|
43
71
|
*/
|
|
44
|
-
|
|
72
|
+
get zones(): Zone[] {
|
|
73
|
+
return this.#zoneIndex.values
|
|
74
|
+
}
|
|
45
75
|
|
|
46
76
|
/**
|
|
47
|
-
*
|
|
77
|
+
* Get zone by key.
|
|
78
|
+
* @param key The key.
|
|
48
79
|
*/
|
|
49
|
-
|
|
80
|
+
getZone(key: string | undefined): Zone | undefined {
|
|
81
|
+
return this.#zoneIndex.get(key)
|
|
82
|
+
}
|
|
50
83
|
|
|
51
84
|
/**
|
|
52
|
-
* List of
|
|
85
|
+
* List of contacts.
|
|
53
86
|
*/
|
|
54
|
-
|
|
87
|
+
get contacts(): Contact[] {
|
|
88
|
+
return this.#contactIndex.values
|
|
89
|
+
}
|
|
55
90
|
|
|
56
91
|
/**
|
|
57
|
-
*
|
|
58
|
-
* @param
|
|
92
|
+
* Get contact by key.
|
|
93
|
+
* @param key The key.
|
|
59
94
|
*/
|
|
60
|
-
|
|
61
|
-
this.
|
|
62
|
-
this.servers = bundle.servers ?? []
|
|
63
|
-
|
|
64
|
-
this.archetypes = bundle.archetypes?.map((data) => {
|
|
65
|
-
if (this.#archetypeIndex[data.key] !== undefined) throw new Error(`Duplicate archetype key '${data.key}'`)
|
|
66
|
-
const archetype = new Archetype(data)
|
|
67
|
-
this.#archetypeIndex[archetype.key] = archetype
|
|
68
|
-
return archetype
|
|
69
|
-
}) ?? []
|
|
70
|
-
|
|
71
|
-
this.zones = bundle.zones?.map((data) => {
|
|
72
|
-
if (this.#zoneIndex[data.key] !== undefined) throw new Error(`Duplicate zone key '${data.key}'`)
|
|
73
|
-
const zone = new Zone(data)
|
|
74
|
-
this.#zoneIndex[zone.key] = zone
|
|
75
|
-
return zone
|
|
76
|
-
}) ?? []
|
|
77
|
-
|
|
78
|
-
this.contacts = bundle.contacts?.map((data) => {
|
|
79
|
-
if (this.#contactIndex[data.key] !== undefined) throw new Error(`Duplicate contact key '${data.key}'`)
|
|
80
|
-
const contact = new Contact(data)
|
|
81
|
-
this.#contactIndex[contact.key] = contact
|
|
82
|
-
return contact
|
|
83
|
-
}) ?? []
|
|
84
|
-
|
|
85
|
-
this.missions = bundle.missions?.map((data) => {
|
|
86
|
-
if (this.#missionIndex[data.key] !== undefined) throw new Error(`Duplicate mission key '${data.key}'`)
|
|
87
|
-
const mission = new Mission(data)
|
|
88
|
-
this.#missionIndex[mission.key] = mission
|
|
89
|
-
return mission
|
|
90
|
-
}) ?? []
|
|
91
|
-
|
|
92
|
-
this.badges = bundle.badges?.map(data => new Badge(data)) ?? []
|
|
93
|
-
this.#badgeIndex = new BadgeIndex(this.badges)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
getArchetype(key?: string): Archetype | undefined {
|
|
97
|
-
if (!key) return undefined
|
|
98
|
-
return this.#archetypeIndex[key]
|
|
95
|
+
getContact(key: string | undefined): Contact | undefined {
|
|
96
|
+
return this.#contactIndex.get(key)
|
|
99
97
|
}
|
|
100
98
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
/**
|
|
100
|
+
* List of missions.
|
|
101
|
+
*/
|
|
102
|
+
get missions(): Mission[] {
|
|
103
|
+
return this.#missionIndex.values
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Get mission by key.
|
|
108
|
+
* @param key The key.
|
|
109
|
+
*/
|
|
110
|
+
getMission(key: string | undefined): Mission | undefined {
|
|
111
|
+
return this.#missionIndex.get(key)
|
|
109
112
|
}
|
|
110
113
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
/**
|
|
115
|
+
* List of badges.
|
|
116
|
+
*/
|
|
117
|
+
get badges(): Badge[] {
|
|
118
|
+
return this.#badgeIndex.values
|
|
114
119
|
}
|
|
115
120
|
|
|
116
|
-
|
|
117
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Get badge by key.
|
|
123
|
+
* @param key The key.
|
|
124
|
+
*/
|
|
125
|
+
getBadge(key: string | undefined): Badge | undefined {
|
|
126
|
+
return this.#badgeIndex.get(key)
|
|
118
127
|
}
|
|
119
128
|
|
|
120
129
|
/**
|
|
@@ -124,6 +133,6 @@ export class CohContentDatabase {
|
|
|
124
133
|
* @param options {@link BadgeSearchOptions}
|
|
125
134
|
*/
|
|
126
135
|
searchBadges(options?: BadgeSearchOptions): Paged<Badge> {
|
|
127
|
-
return this.#badgeIndex.
|
|
136
|
+
return this.#badgeIndex.search(options)
|
|
128
137
|
}
|
|
129
138
|
}
|
package/src/main/index.ts
CHANGED
|
@@ -6,9 +6,9 @@ export * from './api/badge-data'
|
|
|
6
6
|
export * from './api/badge-requirement-data'
|
|
7
7
|
export * from './api/badge-requirement-type'
|
|
8
8
|
export * from './api/badge-type'
|
|
9
|
-
export * from './api/
|
|
9
|
+
export * from './api/bundle-data'
|
|
10
|
+
export * from './api/bundle-header-data'
|
|
10
11
|
export * from './api/contact-data'
|
|
11
|
-
export * from './api/content-bundle'
|
|
12
12
|
export * from './api/enhancement-category'
|
|
13
13
|
export * from './api/link'
|
|
14
14
|
export * from './api/location-data'
|
|
@@ -27,7 +27,7 @@ export * from './db/badge'
|
|
|
27
27
|
export * from './db/badge-index'
|
|
28
28
|
export * from './db/badge-requirement'
|
|
29
29
|
export * from './db/badge-search-options'
|
|
30
|
-
export * from './db/bundle-
|
|
30
|
+
export * from './db/bundle-header'
|
|
31
31
|
export * from './db/coh-content-database'
|
|
32
32
|
export * from './db/contact'
|
|
33
33
|
export * from './db/key'
|
|
@@ -38,5 +38,4 @@ export * from './db/paged'
|
|
|
38
38
|
export * from './db/zone'
|
|
39
39
|
|
|
40
40
|
// ROOT
|
|
41
|
-
export { CHANGELOG } from './changelog'
|
|
42
41
|
export * from './util'
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { AbstractIndex } from '../../main/db/abstract-index'
|
|
2
|
+
|
|
3
|
+
interface TestObject {
|
|
4
|
+
key: string
|
|
5
|
+
otherValue: number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
describe(AbstractIndex.name, () => {
|
|
9
|
+
describe('Constructor', () => {
|
|
10
|
+
test(`should accept the key field`, () => {
|
|
11
|
+
new AbstractIndex<TestObject>('key')
|
|
12
|
+
})
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
describe('value', () => {
|
|
16
|
+
test(`should return the original values`, () => {
|
|
17
|
+
const values = [
|
|
18
|
+
{ key: '1', otherValue: 1 },
|
|
19
|
+
{ key: '2', otherValue: 2 },
|
|
20
|
+
]
|
|
21
|
+
const index = new AbstractIndex<TestObject>('key')
|
|
22
|
+
index.load(values)
|
|
23
|
+
|
|
24
|
+
expect(index.values).toStrictEqual(values)
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
describe('get', () => {
|
|
29
|
+
test(`should return the indexed value on match`, () => {
|
|
30
|
+
const index = new AbstractIndex<TestObject>('key')
|
|
31
|
+
index.load([
|
|
32
|
+
{ key: '1', otherValue: 1 },
|
|
33
|
+
{ key: '2', otherValue: 2 },
|
|
34
|
+
])
|
|
35
|
+
|
|
36
|
+
expect(index.get('2')).toStrictEqual({ key: '2', otherValue: 2 })
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test(`should return undefined on no match`, () => {
|
|
40
|
+
const index = new AbstractIndex<TestObject>('key')
|
|
41
|
+
|
|
42
|
+
expect(index.get('2')).toBeUndefined()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test(`should return undefined on undefined key`, () => {
|
|
46
|
+
const index = new AbstractIndex<TestObject>('key')
|
|
47
|
+
const key = undefined
|
|
48
|
+
expect(index.get(key)).toBeUndefined()
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe('load', () => {
|
|
53
|
+
test(`should reset the index when used`, () => {
|
|
54
|
+
const index = new AbstractIndex<TestObject>('key')
|
|
55
|
+
index.load([
|
|
56
|
+
{ key: '1', otherValue: 1 },
|
|
57
|
+
{ key: '2', otherValue: 2 },
|
|
58
|
+
])
|
|
59
|
+
|
|
60
|
+
expect(index.get('2')).toStrictEqual({ key: '2', otherValue: 2 })
|
|
61
|
+
|
|
62
|
+
index.load([
|
|
63
|
+
{ key: '3', otherValue: 3 },
|
|
64
|
+
])
|
|
65
|
+
expect(index.get('1')).toBeUndefined()
|
|
66
|
+
expect(index.get('2')).toBeUndefined()
|
|
67
|
+
expect(index.get('3')).toStrictEqual({ key: '3', otherValue: 3 })
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
test(`should accept an undefined value`, () => {
|
|
71
|
+
const index = new AbstractIndex<TestObject>('key')
|
|
72
|
+
const values = undefined
|
|
73
|
+
index.load(values)
|
|
74
|
+
|
|
75
|
+
expect(index.values).toHaveLength(0)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test(`should throw an error on duplicate key`, () => {
|
|
79
|
+
const index = new AbstractIndex<TestObject>('key')
|
|
80
|
+
expect(() => index.load([
|
|
81
|
+
{ key: '1', otherValue: 1 },
|
|
82
|
+
{ key: '1', otherValue: 1 },
|
|
83
|
+
])).toThrow('Duplicate key [1]')
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
})
|