warframe-worldstate-parser 3.0.11 → 4.0.1

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/README.md CHANGED
@@ -23,11 +23,12 @@ For the most part, you'll have a better experience consuming the product of this
23
23
  ## Example usage
24
24
 
25
25
  ```javascript
26
- const worldstateData = await require('request-promise')('http://content.warframe.com/dynamic/worldState.php');
26
+ // import WorldState from 'warframe-worldstate-data';
27
+ // using this syntax to make it precisely testable in a test
28
+ const WorldStateParser = await import('warframe-worldstate-parser');
29
+ const worldstateData = await fetch('https://content.warframe.com/dynamic/worldState.php').then((data) => data.text());
27
30
 
28
- const WorldState = require('warframe-worldstate-parser');
29
-
30
- const ws = new WorldState(worldstateData);
31
+ const ws = await WorldStateParser(worldstateData);
31
32
 
32
33
  console.log(ws.alerts[0].toString());
33
34
  ```
package/lib/WorldState.js CHANGED
@@ -58,7 +58,7 @@ export function parseArray(ParserClass, dataArray, deps, uniqueField) {
58
58
  const arr = (dataArray || []).map((d) => new ParserClass(d, deps));
59
59
  if (uniqueField) {
60
60
  const utemp = {};
61
- arr.sort((a, b) => a.id.localeCompare(b.id));
61
+ arr.sort((a, b) => a.id?.localeCompare(b.id));
62
62
  arr.forEach((obj) => {
63
63
  utemp[obj[uniqueField]] = obj;
64
64
  });
@@ -71,14 +71,55 @@ export function parseArray(ParserClass, dataArray, deps, uniqueField) {
71
71
  return arr;
72
72
  }
73
73
 
74
+ /**
75
+ * Parse array of objects that requires async parsing
76
+ * @param {object} ParserClass class for parsing data - must expose a static build method
77
+ * @param {Array<BaseContentObject>} dataArray array of raw data
78
+ * @param {Dependency} deps shared dependency object
79
+ * @param {*} [uniqueField] field to treat as unique
80
+ * @returns {Promise<WorldstateObject[]>} array of parsed objects
81
+ */
82
+ export const parseAsyncArray = async (ParserClass, dataArray, deps, uniqueField) => {
83
+ const arr = [];
84
+ // eslint-disable-next-line no-restricted-syntax
85
+ for await (const d of dataArray ?? []) {
86
+ arr.push(await ParserClass.build(d, deps));
87
+ }
88
+ if (uniqueField) {
89
+ const utemp = {};
90
+ arr.sort((a, b) => a.id?.localeCompare(b.id));
91
+ arr.forEach((obj) => {
92
+ utemp[obj[uniqueField]] = obj;
93
+ });
94
+ return Array.from(arr).filter((obj) => {
95
+ if (obj && obj.active && typeof obj.active !== 'undefined') return obj.active;
96
+ /* istanbul ignore next */
97
+ return true;
98
+ });
99
+ }
100
+ return arr;
101
+ };
102
+
74
103
  /**
75
104
  * Parses Warframe Worldstate JSON
76
105
  */
77
- export default class WorldState {
106
+ export class WorldState {
107
+ static async build(json, deps = defaultDeps) {
108
+ const ws = new WorldState(json, deps);
109
+ const data = JSON.parse(json);
110
+
111
+ ws.events = await parseAsyncArray(WorldEvent, data.Goals, deps);
112
+ ws.syndicateMissions = await parseAsyncArray(SyndicateMission, data.SyndicateMissions, deps, 'syndicate');
113
+
114
+ return ws;
115
+ }
116
+
78
117
  /**
79
118
  * Generates the worldstate json as a string into usable objects
80
119
  * @param {string} json The worldstate JSON string
81
120
  * @param {Dependency} [deps] The options object
121
+ * @class
122
+ * @async
82
123
  */
83
124
  constructor(json, deps = defaultDeps) {
84
125
  if (typeof json !== 'string') {
@@ -114,7 +155,7 @@ export default class WorldState {
114
155
  * The current events
115
156
  * @type {Array.<WorldEvent>}
116
157
  */
117
- this.events = parseArray(WorldEvent, data.Goals, deps);
158
+ this.events = [];
118
159
 
119
160
  /**
120
161
  * The current alerts
@@ -132,7 +173,7 @@ export default class WorldState {
132
173
  * The current syndicate missions
133
174
  * @type {Array.<SyndicateMission>}
134
175
  */
135
- this.syndicateMissions = parseArray(SyndicateMission, data.SyndicateMissions, deps, 'syndicate');
176
+ this.syndicateMissions = [];
136
177
 
137
178
  /**
138
179
  * The current fissures: 'ActiveMissions' & 'VoidStorms'
@@ -298,7 +339,7 @@ export default class WorldState {
298
339
  }
299
340
 
300
341
  /**
301
- * Current syndicate outposts
342
+ * Current sentient outposts
302
343
  * @type {SentientOutpost}
303
344
  */
304
345
  this.sentientOutposts = new SentientOutpost(data.Tmp, deps);
@@ -322,3 +363,5 @@ export default class WorldState {
322
363
  this.duviriCycle = new DuviriCycle(deps);
323
364
  }
324
365
  }
366
+
367
+ export default async (json, deps) => WorldState.build(json, deps);
@@ -84,10 +84,28 @@ const FIFTY_MINUTES = 3000000;
84
84
  */
85
85
  export default class SyndicateJob extends WorldstateObject {
86
86
  /**
87
+ * Generate a job with async data (reward pool)
87
88
  * @param {object} data The syndicate mission data
88
89
  * @param {Date} expiry The syndicate job expiration
89
90
  * @param {object} deps The dependencies object
90
91
  * @param {string} deps.locale Locale to use for translations
92
+ * @returns {Promise<SyndicateJob>} The created SyndicateJob object with rewardPool
93
+ */
94
+ static async build(data, expiry, deps) {
95
+ const job = new SyndicateJob(data, expiry, deps);
96
+ job.rewardPool = await getBountyRewards(data.rewards, data.isVault, data);
97
+
98
+ return job;
99
+ }
100
+
101
+ /**
102
+ * Construct a job without async data (reward pool)
103
+ * @param {object} data The syndicate mission data
104
+ * @param {Date} expiry The syndicate job expiration
105
+ * @param {object} deps The dependencies object
106
+ * @param {string} deps.locale Locale to use for translations
107
+ *
108
+ * This DOES NOT populate the reward pool
91
109
  */
92
110
  constructor(data, expiry, { locale = 'en' }) {
93
111
  super({
@@ -103,9 +121,6 @@ export default class SyndicateJob extends WorldstateObject {
103
121
  * @type {Array.<string>}
104
122
  */
105
123
  this.rewardPool = [];
106
- getBountyRewards(data.rewards, data.isVault, data).then((rewards) => {
107
- this.rewardPool = rewards;
108
- });
109
124
 
110
125
  const chamber = ((data.locationTag || '').match(/[A-Z]+(?![a-z])|[A-Z]?[a-z]+|\d+/g) || []).join(' ');
111
126
 
@@ -10,6 +10,27 @@ import WorldstateObject from './WorldstateObject.js';
10
10
  * @augments {WorldstateObject}
11
11
  */
12
12
  export default class SyndicateMission extends WorldstateObject {
13
+ /**
14
+ * Build a new SyndicateMission with async operations & data
15
+ * @param {object} data The syndicate mission data
16
+ * @param {object} deps The dependencies object
17
+ * @param {string} deps.locale Locale to use for translations
18
+ * @returns {Promise.<SyndicateMission>} SyndicateMission object w/ async resolution of jobs
19
+ */
20
+ static async build(data, deps) {
21
+ const syndicateMission = new SyndicateMission(data, deps);
22
+ if (data.Jobs) {
23
+ const jobs = [];
24
+ // eslint-disable-next-line no-restricted-syntax
25
+ for await (const job of data.Jobs ?? []) {
26
+ jobs.push(await SyndicateJob.build(job, syndicateMission.expiry, deps));
27
+ }
28
+ syndicateMission.jobs = jobs;
29
+ }
30
+
31
+ return syndicateMission;
32
+ }
33
+
13
34
  /**
14
35
  * @param {object} data The syndicate mission data
15
36
  * @param {object} deps The dependencies object
@@ -18,10 +39,6 @@ export default class SyndicateMission extends WorldstateObject {
18
39
  constructor(data, { locale = 'en' } = { locale: 'en' }) {
19
40
  super(data);
20
41
 
21
- const deps = {
22
- locale,
23
- };
24
-
25
42
  /**
26
43
  * The date and time at which the syndicate mission starts
27
44
  * @type {Date}
@@ -56,7 +73,7 @@ export default class SyndicateMission extends WorldstateObject {
56
73
  * The jobs for this syndicate. Will normally be []
57
74
  * @type {Array.<SyndicateJob>}
58
75
  */
59
- this.jobs = (data.Jobs || []).map((j) => new SyndicateJob(j, this.expiry, deps));
76
+ this.jobs = [];
60
77
 
61
78
  /**
62
79
  * Unique identifier for this mission set built from the end time and syndicate
@@ -27,6 +27,34 @@ import Reward from './Reward.js';
27
27
  * @augments {WorldstateObject}
28
28
  */
29
29
  export default class WorldEvent extends WorldstateObject {
30
+ /**
31
+ * Asynchronously build a new WorldEvent
32
+ * @param {object} data The event data
33
+ * @param {object} deps The dependencies object
34
+ * @param {string} deps.locale Locale to use for translations
35
+ * @returns {Promise.<WorldEvent>} The created WorldEvent object
36
+ */
37
+ static async build(data, deps) {
38
+ const event = new WorldEvent(data, deps);
39
+ if (data.Jobs) {
40
+ const jobs = [];
41
+ // eslint-disable-next-line no-restricted-syntax
42
+ for await (const job of data.Jobs ?? []) {
43
+ jobs.push(await SyndicateJob.build(job, event.expiry, deps));
44
+ }
45
+ event.jobs = jobs;
46
+ }
47
+ if (data.PreviousJobs) {
48
+ const previousJobs = [];
49
+ // eslint-disable-next-line no-restricted-syntax
50
+ for await (const job of data.PreviousJobs ?? []) {
51
+ previousJobs.push(await SyndicateJob.build(job, event.expiry, deps));
52
+ }
53
+ event.previousJobs = previousJobs;
54
+ }
55
+ return event;
56
+ }
57
+
30
58
  /**
31
59
  * @param {object} data The event data
32
60
  * @param {object} deps The dependencies object
@@ -132,13 +160,8 @@ export default class WorldEvent extends WorldstateObject {
132
160
  this.health =
133
161
  typeof data.HealthPct !== 'undefined' ? Number.parseFloat(((data.HealthPct || 0.0) * 100).toFixed(2)) : undefined;
134
162
 
135
- if (data.JobAffiliationTag) {
136
- this.affiliatedWith = syndicate(data.JobAffiliationTag, locale);
137
- if (data.Jobs) {
138
- this.jobs = (data.Jobs || []).map((j) => new SyndicateJob(j, this.expiry, opts));
139
- this.previousJobs = (data.PreviousJobs || []).map((j) => new SyndicateJob(j, this.expiry, opts));
140
- }
141
- }
163
+ this.jobs = [];
164
+ this.previousJobs = [];
142
165
 
143
166
  /**
144
167
  * Previous job id
@@ -191,22 +214,22 @@ export default class WorldEvent extends WorldstateObject {
191
214
  }
192
215
 
193
216
  /**
194
- * Whether or not to show the total score at the end of the mission
217
+ * Whether to show the total score at the end of the mission
195
218
  * @type {boolean}
196
219
  */
197
220
  this.showTotalAtEndOfMission = data.ShowTotalAtEOM;
198
221
  /**
199
- * Whether or not the event is personal
222
+ * Whether the event is personal
200
223
  * @type {boolean}
201
224
  */
202
225
  this.isPersonal = data.Personal;
203
226
  /**
204
- * Whether or not the event is community
227
+ * Whether the event is community
205
228
  * @type {boolean}
206
229
  */
207
230
  this.isCommunity = data.Community;
208
231
 
209
- /**
232
+ /*
210
233
  * Affectors for this mission
211
234
  * @type {string[]}
212
235
  */
@@ -241,10 +264,14 @@ export default class WorldEvent extends WorldstateObject {
241
264
  expiry: parseDate(data.NextAltExpiry),
242
265
  activation: parseDate(data.NextAltActivation),
243
266
  };
267
+
268
+ if (data.JobAffiliationTag) {
269
+ this.affiliatedWith = syndicate(data.JobAffiliationTag, locale);
270
+ }
244
271
  }
245
272
 
246
273
  /**
247
- * Get whether or not the event has expired
274
+ * Get whether the event has expired
248
275
  * @returns {boolean} whether the event has expired
249
276
  */
250
277
  getExpired() {
@@ -242,7 +242,7 @@ export default [
242
242
  {
243
243
  name: 'endo',
244
244
  description: 'Endo',
245
- test: (s) => /\d+\sendo/i.test(s),
245
+ test: (s) => /^\d+x?\sendo/i.test(s),
246
246
  thumbnail: wfCdn('endo.png'),
247
247
  color: 0xc2a24c,
248
248
  },
package/main.js CHANGED
@@ -1,3 +1,4 @@
1
- import WorldState from './lib/WorldState.js';
1
+ import { WorldState } from './lib/WorldState.js';
2
2
 
3
3
  export default WorldState;
4
+ export * from './lib/WorldState.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "warframe-worldstate-parser",
3
- "version": "3.0.11",
3
+ "version": "4.0.1",
4
4
  "description": "An Open parser for Warframe's Worldstate in Javascript",
5
5
  "keywords": [
6
6
  "warframe-worldstate",
@@ -17,6 +17,12 @@
17
17
  "nspacestd (https://github.com/nspacestd)"
18
18
  ],
19
19
  "type": "module",
20
+ "exports": {
21
+ ".": {
22
+ "import": "./main.js",
23
+ "types": "./types/index.d.ts"
24
+ }
25
+ },
20
26
  "main": "main.js",
21
27
  "types": "./types/main.d.ts",
22
28
  "files": [
@@ -25,16 +31,6 @@
25
31
  "LICENSE",
26
32
  "types"
27
33
  ],
28
- "commitlint": {
29
- "extends": [
30
- "@commitlint/config-conventional"
31
- ],
32
- "rules": {
33
- "body-max-line-length": [
34
- 0
35
- ]
36
- }
37
- },
38
34
  "peerDependencies": {
39
35
  "warframe-worldstate-data": ">=2.0.3"
40
36
  },
@@ -7,14 +7,18 @@
7
7
  * @returns {WorldstateObject[]} array of parsed objects
8
8
  */
9
9
  export function parseArray(ParserClass: object, dataArray: Array<BaseContentObject>, deps: Dependency, uniqueField?: any): WorldstateObject[];
10
+ export function parseAsyncArray(ParserClass: object, dataArray: Array<BaseContentObject>, deps: Dependency, uniqueField?: any): Promise<WorldstateObject[]>;
10
11
  /**
11
12
  * Parses Warframe Worldstate JSON
12
13
  */
13
- export default class WorldState {
14
+ export class WorldState {
15
+ static build(json: any, deps?: Dependency): Promise<WorldState>;
14
16
  /**
15
17
  * Generates the worldstate json as a string into usable objects
16
18
  * @param {string} json The worldstate JSON string
17
19
  * @param {Dependency} [deps] The options object
20
+ * @class
21
+ * @async
18
22
  */
19
23
  constructor(json: string, deps?: Dependency);
20
24
  /**
@@ -134,7 +138,7 @@ export default class WorldState {
134
138
  nightwave: Nightwave;
135
139
  arbitration: any;
136
140
  /**
137
- * Current syndicate outposts
141
+ * Current sentient outposts
138
142
  * @type {SentientOutpost}
139
143
  */
140
144
  sentientOutposts: SentientOutpost;
@@ -145,6 +149,8 @@ export default class WorldState {
145
149
  steelPath: SteelPathOffering;
146
150
  duviriCycle: DuviriCycle;
147
151
  }
152
+ declare function _default(json: any, deps: any): Promise<WorldState>;
153
+ export default _default;
148
154
  import Dependency from './supporting/Dependency.js';
149
155
  import News from './models/News.js';
150
156
  import WorldEvent from './models/WorldEvent.js';
@@ -4,10 +4,24 @@
4
4
  */
5
5
  export default class SyndicateJob extends WorldstateObject {
6
6
  /**
7
+ * Generate a job with async data (reward pool)
7
8
  * @param {object} data The syndicate mission data
8
9
  * @param {Date} expiry The syndicate job expiration
9
10
  * @param {object} deps The dependencies object
10
11
  * @param {string} deps.locale Locale to use for translations
12
+ * @returns {Promise<SyndicateJob>} The created SyndicateJob object with rewardPool
13
+ */
14
+ static build(data: object, expiry: Date, deps: {
15
+ locale: string;
16
+ }): Promise<SyndicateJob>;
17
+ /**
18
+ * Construct a job without async data (reward pool)
19
+ * @param {object} data The syndicate mission data
20
+ * @param {Date} expiry The syndicate job expiration
21
+ * @param {object} deps The dependencies object
22
+ * @param {string} deps.locale Locale to use for translations
23
+ *
24
+ * This DOES NOT populate the reward pool
11
25
  */
12
26
  constructor(data: object, expiry: Date, { locale }: {
13
27
  locale: string;
@@ -3,6 +3,16 @@
3
3
  * @augments {WorldstateObject}
4
4
  */
5
5
  export default class SyndicateMission extends WorldstateObject {
6
+ /**
7
+ * Build a new SyndicateMission with async operations & data
8
+ * @param {object} data The syndicate mission data
9
+ * @param {object} deps The dependencies object
10
+ * @param {string} deps.locale Locale to use for translations
11
+ * @returns {Promise.<SyndicateMission>} SyndicateMission object w/ async resolution of jobs
12
+ */
13
+ static build(data: object, deps: {
14
+ locale: string;
15
+ }): Promise<SyndicateMission>;
6
16
  /**
7
17
  * @param {object} data The syndicate mission data
8
18
  * @param {object} deps The dependencies object
@@ -17,6 +17,16 @@
17
17
  * @augments {WorldstateObject}
18
18
  */
19
19
  export default class WorldEvent extends WorldstateObject {
20
+ /**
21
+ * Asynchronously build a new WorldEvent
22
+ * @param {object} data The event data
23
+ * @param {object} deps The dependencies object
24
+ * @param {string} deps.locale Locale to use for translations
25
+ * @returns {Promise.<WorldEvent>} The created WorldEvent object
26
+ */
27
+ static build(data: object, deps: {
28
+ locale: string;
29
+ }): Promise<WorldEvent>;
20
30
  /**
21
31
  * @param {object} data The event data
22
32
  * @param {object} deps The dependencies object
@@ -95,9 +105,8 @@ export default class WorldEvent extends WorldstateObject {
95
105
  * @type {number}
96
106
  */
97
107
  health: number;
98
- affiliatedWith: any;
99
- jobs: any;
100
- previousJobs: any;
108
+ jobs: any[];
109
+ previousJobs: any[];
101
110
  /**
102
111
  * Previous job id
103
112
  * @type {string}
@@ -119,25 +128,21 @@ export default class WorldEvent extends WorldstateObject {
119
128
  */
120
129
  progressTotal: number;
121
130
  /**
122
- * Whether or not to show the total score at the end of the mission
131
+ * Whether to show the total score at the end of the mission
123
132
  * @type {boolean}
124
133
  */
125
134
  showTotalAtEndOfMission: boolean;
126
135
  /**
127
- * Whether or not the event is personal
136
+ * Whether the event is personal
128
137
  * @type {boolean}
129
138
  */
130
139
  isPersonal: boolean;
131
140
  /**
132
- * Whether or not the event is community
141
+ * Whether the event is community
133
142
  * @type {boolean}
134
143
  */
135
144
  isCommunity: boolean;
136
- /**
137
- * Affectors for this mission
138
- * @type {string[]}
139
- */
140
- regionDrops: string[];
145
+ regionDrops: any;
141
146
  /**
142
147
  * Archwing Drops in effect while this event is active
143
148
  * @type {string[]}
@@ -161,8 +166,9 @@ export default class WorldEvent extends WorldstateObject {
161
166
  expiry: any;
162
167
  activation: any;
163
168
  };
169
+ affiliatedWith: any;
164
170
  /**
165
- * Get whether or not the event has expired
171
+ * Get whether the event has expired
166
172
  * @returns {boolean} whether the event has expired
167
173
  */
168
174
  getExpired(): boolean;
package/types/main.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export default WorldState;
2
- import WorldState from './lib/WorldState.js';
2
+ export * from "./lib/WorldState.js";
3
+ import { WorldState } from './lib/WorldState.js';