worldstate-emitter 2.4.5 → 2.5.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/dist/index.d.cts CHANGED
@@ -1,11 +1,13 @@
1
1
  import EventEmitter from "node:events";
2
2
  import { RSSItem } from "rss-feed-emitter";
3
3
  import WorldState from "warframe-worldstate-parser";
4
+ import { Logger } from "winston";
4
5
 
5
6
  //#region index.d.ts
6
7
  interface WorldstateEmitterOptions {
7
8
  locale?: string;
8
9
  features?: string[];
10
+ logger?: Logger;
9
11
  }
10
12
  interface RssFeedItem {
11
13
  url: string;
@@ -20,14 +22,16 @@ declare class WorldstateEmitter extends EventEmitter {
20
22
  #private;
21
23
  static make({
22
24
  locale,
23
- features
25
+ features,
26
+ logger: upLogger
24
27
  }?: WorldstateEmitterOptions): Promise<WorldstateEmitter>;
25
28
  /**
26
29
  * Pull in and instantiate emitters
27
30
  * @param options - Configuration options
28
31
  */
29
32
  constructor({
30
- locale
33
+ locale,
34
+ logger: uLogger
31
35
  }?: WorldstateEmitterOptions);
32
36
  /**
33
37
  * Set up internal logging
package/dist/index.d.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  import EventEmitter from "node:events";
2
2
  import { RSSItem } from "rss-feed-emitter";
3
+ import { Logger } from "winston";
3
4
  import WorldState from "warframe-worldstate-parser";
4
5
 
5
6
  //#region index.d.ts
6
7
  interface WorldstateEmitterOptions {
7
8
  locale?: string;
8
9
  features?: string[];
10
+ logger?: Logger;
9
11
  }
10
12
  interface RssFeedItem {
11
13
  url: string;
@@ -20,14 +22,16 @@ declare class WorldstateEmitter extends EventEmitter {
20
22
  #private;
21
23
  static make({
22
24
  locale,
23
- features
25
+ features,
26
+ logger: upLogger
24
27
  }?: WorldstateEmitterOptions): Promise<WorldstateEmitter>;
25
28
  /**
26
29
  * Pull in and instantiate emitters
27
30
  * @param options - Configuration options
28
31
  */
29
32
  constructor({
30
- locale
33
+ locale,
34
+ logger: uLogger
31
35
  }?: WorldstateEmitterOptions);
32
36
  /**
33
37
  * Set up internal logging
package/dist/index.js CHANGED
@@ -191,20 +191,51 @@ const twiClientInfo = {
191
191
  const TWITTER_TIMEOUT = Number(process?.env?.TWITTER_TIMEOUT) || 6e4;
192
192
  //#endregion
193
193
  //#region utilities/index.ts
194
- let tempLogger;
194
+ const levels = {
195
+ ["fatal"]: 0,
196
+ ["error"]: 1,
197
+ ["warn"]: 2,
198
+ ["info"]: 3,
199
+ ["debug"]: 4,
200
+ ["silly"]: 5
201
+ };
202
+ let loggerInstance;
195
203
  try {
196
204
  const { combine, label, printf, colorize } = winston.format;
197
205
  const transport = new winston.transports.Console();
198
206
  const logFormat = printf((info) => `[${info.label}] ${info.level}: ${info.message}`);
199
- tempLogger = (0, winston.createLogger)({
207
+ loggerInstance = (0, winston.createLogger)({
200
208
  format: combine(colorize(), label({ label: "WS" }), logFormat),
201
- transports: [transport]
209
+ transports: [transport],
210
+ level: LOG_LEVEL,
211
+ levels
202
212
  });
203
- tempLogger.level = LOG_LEVEL;
213
+ loggerInstance.level = LOG_LEVEL;
204
214
  } catch (_e) {
205
- tempLogger = (0, winston.createLogger)({ transports: [new winston.transports.Console()] });
215
+ loggerInstance = (0, winston.createLogger)({
216
+ transports: [new winston.transports.Console()],
217
+ level: LOG_LEVEL,
218
+ levels
219
+ });
206
220
  }
207
- const logger = tempLogger;
221
+ /**
222
+ * Replace the module-wide logger used by emitter internals.
223
+ * Call before constructing handlers when injecting a host-provided logger.
224
+ */
225
+ const setLogger = (uLogger) => {
226
+ loggerInstance = uLogger;
227
+ };
228
+ /** Global logger proxy so existing imports pick up setLogger() overrides. */
229
+ const logger = new Proxy({}, {
230
+ get(_target, prop) {
231
+ const value = Reflect.get(loggerInstance, prop, loggerInstance);
232
+ return typeof value === "function" ? value.bind(loggerInstance) : value;
233
+ },
234
+ set(_target, prop, value) {
235
+ Reflect.set(loggerInstance, prop, value);
236
+ return true;
237
+ }
238
+ });
208
239
  /**
209
240
  * Group an array by a field value
210
241
  * @param array - array of objects to group
@@ -472,6 +503,7 @@ const parseTweet = (tweets, watchable) => {
472
503
  */
473
504
  var TwitterCache = class {
474
505
  emitter;
506
+ logger;
475
507
  timeout;
476
508
  clientInfoValid;
477
509
  client;
@@ -489,9 +521,11 @@ var TwitterCache = class {
489
521
  * @param options.clientInfo - Custom Twitter client credentials
490
522
  * @param options.watchList - Custom list of Twitter accounts to watch
491
523
  * @param options.timeout - Polling interval in milliseconds
524
+ * @param options.logger - Custom logger instance (default: uses global logger)
492
525
  */
493
526
  constructor(eventEmitter, options = {}) {
494
527
  this.emitter = eventEmitter;
528
+ this.logger = options.logger || logger;
495
529
  this.timeout = options.timeout ?? TWITTER_TIMEOUT;
496
530
  this.lastUpdated = Date.now() - 6e4;
497
531
  this.disposed = false;
@@ -514,11 +548,11 @@ var TwitterCache = class {
514
548
  this.updateInterval = setInterval(() => this.update(), this.timeout);
515
549
  this.update();
516
550
  } else {
517
- logger.warn(`Twitter client not initialized... invalid token: ${clientInfo.bearer_token}`);
551
+ this.logger.warn(`Twitter client not initialized... invalid token: ${clientInfo.bearer_token}`);
518
552
  this.dispose();
519
553
  }
520
554
  } catch (err) {
521
- logger.error(err);
555
+ this.logger.error(err);
522
556
  this.dispose();
523
557
  }
524
558
  }
@@ -538,11 +572,11 @@ var TwitterCache = class {
538
572
  async update() {
539
573
  if (this.disposed || !this.clientInfoValid) return void 0;
540
574
  if (!this.toWatch || this.toWatch.length === 0) {
541
- logger.verbose("Not processing twitter, no data to watch.");
575
+ this.logger.debug("Not processing twitter, no data to watch.");
542
576
  return;
543
577
  }
544
578
  if (!this.client) {
545
- logger.verbose("Not processing twitter, no client to connect.");
579
+ this.logger.debug("Not processing twitter, no client to connect.");
546
580
  return;
547
581
  }
548
582
  this.updating = this.getParseableData();
@@ -553,7 +587,7 @@ var TwitterCache = class {
553
587
  * @returns Tweets
554
588
  */
555
589
  async getParseableData() {
556
- logger.silly("Starting Twitter update...");
590
+ this.logger.debug("Starting Twitter update...");
557
591
  const parsedData = [];
558
592
  try {
559
593
  await Promise.all((this.toWatch || []).map(async (watchable) => {
@@ -578,9 +612,9 @@ var TwitterCache = class {
578
612
  */
579
613
  onError(error) {
580
614
  if (Array.isArray(error) && error[0] && error[0].code === 32) {
581
- logger.info("wiping twitter client data, could not authenticate...");
615
+ this.logger.info("wiping twitter client data, could not authenticate...");
582
616
  this.dispose();
583
- } else logger.debug(JSON.stringify(error));
617
+ } else this.logger.debug(JSON.stringify(error));
584
618
  }
585
619
  /**
586
620
  * Get the current data or a promise with the current data
@@ -602,7 +636,7 @@ var TwitterCache = class {
602
636
  }
603
637
  this.client = void 0;
604
638
  this.clientInfoValid = false;
605
- logger.verbose("Twitter polling stopped and resources cleaned up");
639
+ this.logger.debug("Twitter polling stopped and resources cleaned up");
606
640
  }
607
641
  };
608
642
  //#endregion
@@ -915,8 +949,8 @@ var CronCache = class CronCache extends node_events.EventEmitter {
915
949
  * @param pattern - Optional cron pattern for update frequency
916
950
  * @returns Initialized CronCache instance
917
951
  */
918
- static async make(url, pattern) {
919
- const cache = new CronCache(url, pattern);
952
+ static async make(url, pattern, uLogger) {
953
+ const cache = new CronCache(url, pattern, uLogger);
920
954
  await cache.#update();
921
955
  return cache;
922
956
  }
@@ -924,11 +958,13 @@ var CronCache = class CronCache extends node_events.EventEmitter {
924
958
  * Create a new CronCache
925
959
  * @param url - The URL to fetch data from
926
960
  * @param pattern - Optional cron pattern for update frequency
961
+ * @param uLogger - Optional logger instance
927
962
  */
928
- constructor(url, pattern) {
963
+ constructor(url, pattern, uLogger) {
929
964
  super();
930
965
  this.#url = url;
931
966
  if (pattern) this.#pattern = pattern;
967
+ if (uLogger) this.#logger = uLogger;
932
968
  this.#job = new cron.CronJob(this.#pattern, () => void this.#update(), void 0, true);
933
969
  this.#job.start();
934
970
  }
@@ -959,12 +995,12 @@ var CronCache = class CronCache extends node_events.EventEmitter {
959
995
  * @private
960
996
  */
961
997
  async #fetch() {
962
- logger.silly(`fetching... ${this.#url}`);
998
+ this.#logger.silly(`fetching... ${this.#url}`);
963
999
  const response = await fetch(this.#url);
964
1000
  if (!response.ok) {
965
1001
  const responseText = await response.text();
966
1002
  const errorMessage = `Failed to fetch ${this.#url}: ${response.status} ${response.statusText}`;
967
- logger.error(errorMessage, { responseText });
1003
+ this.#logger.error(errorMessage, { responseText });
968
1004
  throw new Error(errorMessage);
969
1005
  }
970
1006
  this.#data = await response.text();
@@ -976,14 +1012,14 @@ var CronCache = class CronCache extends node_events.EventEmitter {
976
1012
  */
977
1013
  async get() {
978
1014
  if (this.#updating) {
979
- logger.silly("returning in-progress update promise");
1015
+ this.#logger.silly("returning in-progress update promise");
980
1016
  return this.#updating;
981
1017
  }
982
1018
  if (!this.#data) {
983
- logger.silly("returning new update promise");
1019
+ this.#logger.silly("returning new update promise");
984
1020
  return this.#update();
985
1021
  }
986
- logger.silly("returning cached data");
1022
+ this.#logger.silly("returning cached data");
987
1023
  return this.#data;
988
1024
  }
989
1025
  /**
@@ -1015,12 +1051,13 @@ var WSCache = class {
1015
1051
  * @param options.sentientCache - Cache of sentient outpost data, provided by Semlar
1016
1052
  * @param options.eventEmitter - Emitter to push new worldstate updates to
1017
1053
  */
1018
- constructor({ language, kuvaCache, sentientCache, eventEmitter }) {
1054
+ constructor({ language, kuvaCache, sentientCache, eventEmitter, logger: uLogger }) {
1019
1055
  this.#inner = void 0;
1020
1056
  this.#kuvaCache = kuvaCache;
1021
1057
  this.#sentientCache = sentientCache;
1022
1058
  this.#language = language;
1023
1059
  this.#emitter = eventEmitter;
1060
+ this.#logger = uLogger || logger;
1024
1061
  }
1025
1062
  /**
1026
1063
  * Update the current data with new data
@@ -1031,19 +1068,20 @@ var WSCache = class {
1031
1068
  const deps = {
1032
1069
  locale: this.#language,
1033
1070
  kuvaData: [],
1034
- sentientData: void 0
1071
+ sentientData: void 0,
1072
+ logger: { debug: (message) => this.#logger.debug(message) }
1035
1073
  };
1036
1074
  try {
1037
1075
  const kuvaRaw = await this.#kuvaCache.get();
1038
1076
  if (kuvaRaw) deps.kuvaData = JSON.parse(kuvaRaw);
1039
1077
  } catch (err) {
1040
- logger.debug(`Error parsing kuva data for ${this.#language}: ${err}`);
1078
+ this.#logger.debug(`Error parsing kuva data for ${this.#language}: ${err}`);
1041
1079
  }
1042
1080
  try {
1043
1081
  const sentientRaw = await this.#sentientCache.get();
1044
1082
  if (sentientRaw) deps.sentientData = JSON.parse(sentientRaw);
1045
1083
  } catch (err) {
1046
- logger.warn(`Error parsing sentient data for ${this.#language}: ${err}`);
1084
+ this.#logger.warn(`Error parsing sentient data for ${this.#language}: ${err}`);
1047
1085
  }
1048
1086
  let t;
1049
1087
  try {
@@ -1072,7 +1110,7 @@ var WSCache = class {
1072
1110
  * @param newData - New string data to parse
1073
1111
  */
1074
1112
  set data(newData) {
1075
- logger.debug(`got new data for ${this.#language}, parsing...`);
1113
+ this.#logger.debug(`got new data for ${this.#language}, parsing...`);
1076
1114
  this.#update(newData);
1077
1115
  }
1078
1116
  /**
@@ -1098,6 +1136,7 @@ const debugEvents = [
1098
1136
  var Worldstate = class {
1099
1137
  #emitter;
1100
1138
  #locale;
1139
+ #logger;
1101
1140
  #worldStates = {};
1102
1141
  #wsRawCache;
1103
1142
  #kuvaCache;
@@ -1105,18 +1144,19 @@ var Worldstate = class {
1105
1144
  /**
1106
1145
  * Set up listening for specific platform and locale if provided.
1107
1146
  * @param eventEmitter - Emitter to push new worldstate events to
1108
- * @param locale - Locale (actually just language) to watch
1147
+ * @param options - Configuration options
1109
1148
  */
1110
- constructor(eventEmitter, locale) {
1149
+ constructor(eventEmitter, options = {}) {
1111
1150
  this.#emitter = eventEmitter;
1112
- this.#locale = locale;
1113
- logger.debug("starting up worldstate listener...");
1114
- if (locale) logger.debug(`only listening for ${locale}...`);
1151
+ this.#locale = options.locale;
1152
+ this.#logger = options.logger || logger;
1153
+ this.#logger.debug("starting up worldstate listener...");
1154
+ if (options.locale) this.#logger.debug(`only listening for ${options.locale}...`);
1115
1155
  }
1116
1156
  async init() {
1117
- this.#wsRawCache = await CronCache.make(worldstateUrl, worldstateCron);
1118
- this.#kuvaCache = await CronCache.make(kuvaUrl, externalCron);
1119
- this.#sentientCache = await CronCache.make(sentientUrl, externalCron);
1157
+ this.#wsRawCache = await CronCache.make(worldstateUrl, worldstateCron, this.#logger);
1158
+ this.#kuvaCache = await CronCache.make(kuvaUrl, externalCron, this.#logger);
1159
+ this.#sentientCache = await CronCache.make(sentientUrl, externalCron, this.#logger);
1120
1160
  await this.setUpRawEmitters();
1121
1161
  this.setupParsedEvents();
1122
1162
  }
@@ -1129,7 +1169,8 @@ var Worldstate = class {
1129
1169
  language: locale,
1130
1170
  kuvaCache: this.#kuvaCache,
1131
1171
  sentientCache: this.#sentientCache,
1132
- eventEmitter: this.#emitter
1172
+ eventEmitter: this.#emitter,
1173
+ logger: this.#logger
1133
1174
  });
1134
1175
  this.#wsRawCache.on("update", (dataStr) => {
1135
1176
  this.#emitter.emit("ws:update:raw", {
@@ -1138,7 +1179,7 @@ var Worldstate = class {
1138
1179
  });
1139
1180
  });
1140
1181
  this.#emitter.on("ws:update:raw", ({ data }) => {
1141
- logger.debug("ws:update:raw - updating locales data");
1182
+ this.#logger.debug("ws:update:raw - updating locales data");
1142
1183
  locales.forEach((locale) => {
1143
1184
  if (!this.#locale || this.#locale === locale) this.#worldStates[locale].data = data;
1144
1185
  });
@@ -1190,8 +1231,8 @@ var Worldstate = class {
1190
1231
  * @param packet - Data packet to emit
1191
1232
  */
1192
1233
  emit(id, packet) {
1193
- if (debugEvents.includes(packet.key)) logger.warn(packet.key);
1194
- logger.debug(`ws:update:event - emitting ${packet.id}`);
1234
+ if (debugEvents.includes(packet.key)) this.#logger.warn(packet.key);
1235
+ this.#logger.debug(`ws:update:event - emitting ${packet.id}`);
1195
1236
  delete packet.cycleStart;
1196
1237
  this.#emitter.emit(id, packet);
1197
1238
  }
@@ -1202,7 +1243,7 @@ var Worldstate = class {
1202
1243
  * @throws When the platform or locale aren't tracked and aren't updated
1203
1244
  */
1204
1245
  get(language = "en") {
1205
- logger.debug(`getting worldstate ${language}...`);
1246
+ this.#logger.debug(`getting worldstate ${language}...`);
1206
1247
  if (this.#worldStates?.[language]) return this.#worldStates?.[language]?.data;
1207
1248
  throw new Error(`Language (${language}) not tracked.\nEnsure that the parameters passed are correct`);
1208
1249
  }
@@ -1219,8 +1260,13 @@ var WorldstateEmitter = class WorldstateEmitter extends node_events.default {
1219
1260
  #worldstate;
1220
1261
  #twitter;
1221
1262
  #rss;
1222
- static async make({ locale, features } = {}) {
1223
- const emitter = new WorldstateEmitter({ locale });
1263
+ #logger;
1264
+ static async make({ locale, features, logger: upLogger } = {}) {
1265
+ if (upLogger) setLogger(upLogger);
1266
+ const emitter = new WorldstateEmitter({
1267
+ locale,
1268
+ logger: upLogger
1269
+ });
1224
1270
  await emitter.#init(features?.length ? features : FEATURES);
1225
1271
  return emitter;
1226
1272
  }
@@ -1228,18 +1274,22 @@ var WorldstateEmitter = class WorldstateEmitter extends node_events.default {
1228
1274
  * Pull in and instantiate emitters
1229
1275
  * @param options - Configuration options
1230
1276
  */
1231
- constructor({ locale } = {}) {
1277
+ constructor({ locale, logger: uLogger } = {}) {
1232
1278
  super();
1233
1279
  this.#locale = locale;
1280
+ this.#logger = uLogger || logger;
1234
1281
  }
1235
1282
  async #init(features) {
1236
- if (features.includes("rss")) this.#rss = new RSS(this);
1283
+ if (features.includes("rss")) this.#rss = new RSS(this, { logger: this.#logger });
1237
1284
  if (features.includes("worldstate")) {
1238
- this.#worldstate = new Worldstate(this, this.#locale);
1285
+ this.#worldstate = new Worldstate(this, {
1286
+ locale: this.#locale,
1287
+ logger: this.#logger
1288
+ });
1239
1289
  await this.#worldstate.init();
1240
1290
  }
1241
- if (features.includes("twitter")) this.#twitter = new TwitterCache(this);
1242
- logger.silly("hey look, i started up...");
1291
+ if (features.includes("twitter")) this.#twitter = new TwitterCache(this, { logger: this.#logger });
1292
+ this.#logger.silly("hey look, i started up...");
1243
1293
  this.setupLogging();
1244
1294
  }
1245
1295
  /**
@@ -1247,12 +1297,13 @@ var WorldstateEmitter = class WorldstateEmitter extends node_events.default {
1247
1297
  * @private
1248
1298
  */
1249
1299
  setupLogging() {
1250
- this.on("error", logger.error);
1251
- this.on("rss", (body) => logger.silly(`emitted: ${body.id}`));
1252
- this.on("ws:update:raw", (body) => logger.silly(`emitted raw: ${body.platform}`));
1253
- this.on("ws:update:parsed", (body) => logger.silly(`emitted parsed: ${body.platform} in ${body.language}`));
1254
- this.on("ws:update:event", (body) => logger.silly(`emitted event: ${body.id} ${body.platform} in ${body.language}`));
1255
- this.on("tweet", (body) => logger.silly(`emitted: ${body.id}`));
1300
+ const log = this.#logger;
1301
+ this.on("error", log.error.bind(log));
1302
+ this.on("rss", (body) => log.silly(`emitted: ${body.id}`));
1303
+ this.on("ws:update:raw", (body) => log.silly(`emitted raw: ${body.platform}`));
1304
+ this.on("ws:update:parsed", (body) => log.silly(`emitted parsed: ${body.platform} in ${body.language}`));
1305
+ this.on("ws:update:event", (body) => log.silly(`emitted event: ${body.id} ${body.platform} in ${body.language}`));
1306
+ this.on("tweet", (body) => log.silly(`emitted: ${body.id}`));
1256
1307
  }
1257
1308
  /**
1258
1309
  * Get current rss feed items
@@ -1301,6 +1352,7 @@ var WorldstateEmitter = class WorldstateEmitter extends node_events.default {
1301
1352
  this.#twitter.dispose();
1302
1353
  this.#twitter = void 0;
1303
1354
  }
1355
+ this.#logger.debug("Emitter destroyed");
1304
1356
  }
1305
1357
  };
1306
1358
  //#endregion
package/dist/index.mjs CHANGED
@@ -163,20 +163,51 @@ const twiClientInfo = {
163
163
  const TWITTER_TIMEOUT = Number(process?.env?.TWITTER_TIMEOUT) || 6e4;
164
164
  //#endregion
165
165
  //#region utilities/index.ts
166
- let tempLogger;
166
+ const levels = {
167
+ ["fatal"]: 0,
168
+ ["error"]: 1,
169
+ ["warn"]: 2,
170
+ ["info"]: 3,
171
+ ["debug"]: 4,
172
+ ["silly"]: 5
173
+ };
174
+ let loggerInstance;
167
175
  try {
168
176
  const { combine, label, printf, colorize } = format;
169
177
  const transport = new transports.Console();
170
178
  const logFormat = printf((info) => `[${info.label}] ${info.level}: ${info.message}`);
171
- tempLogger = createLogger({
179
+ loggerInstance = createLogger({
172
180
  format: combine(colorize(), label({ label: "WS" }), logFormat),
173
- transports: [transport]
181
+ transports: [transport],
182
+ level: LOG_LEVEL,
183
+ levels
174
184
  });
175
- tempLogger.level = LOG_LEVEL;
185
+ loggerInstance.level = LOG_LEVEL;
176
186
  } catch (_e) {
177
- tempLogger = createLogger({ transports: [new transports.Console()] });
187
+ loggerInstance = createLogger({
188
+ transports: [new transports.Console()],
189
+ level: LOG_LEVEL,
190
+ levels
191
+ });
178
192
  }
179
- const logger = tempLogger;
193
+ /**
194
+ * Replace the module-wide logger used by emitter internals.
195
+ * Call before constructing handlers when injecting a host-provided logger.
196
+ */
197
+ const setLogger = (uLogger) => {
198
+ loggerInstance = uLogger;
199
+ };
200
+ /** Global logger proxy so existing imports pick up setLogger() overrides. */
201
+ const logger = new Proxy({}, {
202
+ get(_target, prop) {
203
+ const value = Reflect.get(loggerInstance, prop, loggerInstance);
204
+ return typeof value === "function" ? value.bind(loggerInstance) : value;
205
+ },
206
+ set(_target, prop, value) {
207
+ Reflect.set(loggerInstance, prop, value);
208
+ return true;
209
+ }
210
+ });
180
211
  /**
181
212
  * Group an array by a field value
182
213
  * @param array - array of objects to group
@@ -444,6 +475,7 @@ const parseTweet = (tweets, watchable) => {
444
475
  */
445
476
  var TwitterCache = class {
446
477
  emitter;
478
+ logger;
447
479
  timeout;
448
480
  clientInfoValid;
449
481
  client;
@@ -461,9 +493,11 @@ var TwitterCache = class {
461
493
  * @param options.clientInfo - Custom Twitter client credentials
462
494
  * @param options.watchList - Custom list of Twitter accounts to watch
463
495
  * @param options.timeout - Polling interval in milliseconds
496
+ * @param options.logger - Custom logger instance (default: uses global logger)
464
497
  */
465
498
  constructor(eventEmitter, options = {}) {
466
499
  this.emitter = eventEmitter;
500
+ this.logger = options.logger || logger;
467
501
  this.timeout = options.timeout ?? TWITTER_TIMEOUT;
468
502
  this.lastUpdated = Date.now() - 6e4;
469
503
  this.disposed = false;
@@ -486,11 +520,11 @@ var TwitterCache = class {
486
520
  this.updateInterval = setInterval(() => this.update(), this.timeout);
487
521
  this.update();
488
522
  } else {
489
- logger.warn(`Twitter client not initialized... invalid token: ${clientInfo.bearer_token}`);
523
+ this.logger.warn(`Twitter client not initialized... invalid token: ${clientInfo.bearer_token}`);
490
524
  this.dispose();
491
525
  }
492
526
  } catch (err) {
493
- logger.error(err);
527
+ this.logger.error(err);
494
528
  this.dispose();
495
529
  }
496
530
  }
@@ -510,11 +544,11 @@ var TwitterCache = class {
510
544
  async update() {
511
545
  if (this.disposed || !this.clientInfoValid) return void 0;
512
546
  if (!this.toWatch || this.toWatch.length === 0) {
513
- logger.verbose("Not processing twitter, no data to watch.");
547
+ this.logger.debug("Not processing twitter, no data to watch.");
514
548
  return;
515
549
  }
516
550
  if (!this.client) {
517
- logger.verbose("Not processing twitter, no client to connect.");
551
+ this.logger.debug("Not processing twitter, no client to connect.");
518
552
  return;
519
553
  }
520
554
  this.updating = this.getParseableData();
@@ -525,7 +559,7 @@ var TwitterCache = class {
525
559
  * @returns Tweets
526
560
  */
527
561
  async getParseableData() {
528
- logger.silly("Starting Twitter update...");
562
+ this.logger.debug("Starting Twitter update...");
529
563
  const parsedData = [];
530
564
  try {
531
565
  await Promise.all((this.toWatch || []).map(async (watchable) => {
@@ -550,9 +584,9 @@ var TwitterCache = class {
550
584
  */
551
585
  onError(error) {
552
586
  if (Array.isArray(error) && error[0] && error[0].code === 32) {
553
- logger.info("wiping twitter client data, could not authenticate...");
587
+ this.logger.info("wiping twitter client data, could not authenticate...");
554
588
  this.dispose();
555
- } else logger.debug(JSON.stringify(error));
589
+ } else this.logger.debug(JSON.stringify(error));
556
590
  }
557
591
  /**
558
592
  * Get the current data or a promise with the current data
@@ -574,7 +608,7 @@ var TwitterCache = class {
574
608
  }
575
609
  this.client = void 0;
576
610
  this.clientInfoValid = false;
577
- logger.verbose("Twitter polling stopped and resources cleaned up");
611
+ this.logger.debug("Twitter polling stopped and resources cleaned up");
578
612
  }
579
613
  };
580
614
  //#endregion
@@ -887,8 +921,8 @@ var CronCache = class CronCache extends EventEmitter$1 {
887
921
  * @param pattern - Optional cron pattern for update frequency
888
922
  * @returns Initialized CronCache instance
889
923
  */
890
- static async make(url, pattern) {
891
- const cache = new CronCache(url, pattern);
924
+ static async make(url, pattern, uLogger) {
925
+ const cache = new CronCache(url, pattern, uLogger);
892
926
  await cache.#update();
893
927
  return cache;
894
928
  }
@@ -896,11 +930,13 @@ var CronCache = class CronCache extends EventEmitter$1 {
896
930
  * Create a new CronCache
897
931
  * @param url - The URL to fetch data from
898
932
  * @param pattern - Optional cron pattern for update frequency
933
+ * @param uLogger - Optional logger instance
899
934
  */
900
- constructor(url, pattern) {
935
+ constructor(url, pattern, uLogger) {
901
936
  super();
902
937
  this.#url = url;
903
938
  if (pattern) this.#pattern = pattern;
939
+ if (uLogger) this.#logger = uLogger;
904
940
  this.#job = new CronJob(this.#pattern, () => void this.#update(), void 0, true);
905
941
  this.#job.start();
906
942
  }
@@ -931,12 +967,12 @@ var CronCache = class CronCache extends EventEmitter$1 {
931
967
  * @private
932
968
  */
933
969
  async #fetch() {
934
- logger.silly(`fetching... ${this.#url}`);
970
+ this.#logger.silly(`fetching... ${this.#url}`);
935
971
  const response = await fetch(this.#url);
936
972
  if (!response.ok) {
937
973
  const responseText = await response.text();
938
974
  const errorMessage = `Failed to fetch ${this.#url}: ${response.status} ${response.statusText}`;
939
- logger.error(errorMessage, { responseText });
975
+ this.#logger.error(errorMessage, { responseText });
940
976
  throw new Error(errorMessage);
941
977
  }
942
978
  this.#data = await response.text();
@@ -948,14 +984,14 @@ var CronCache = class CronCache extends EventEmitter$1 {
948
984
  */
949
985
  async get() {
950
986
  if (this.#updating) {
951
- logger.silly("returning in-progress update promise");
987
+ this.#logger.silly("returning in-progress update promise");
952
988
  return this.#updating;
953
989
  }
954
990
  if (!this.#data) {
955
- logger.silly("returning new update promise");
991
+ this.#logger.silly("returning new update promise");
956
992
  return this.#update();
957
993
  }
958
- logger.silly("returning cached data");
994
+ this.#logger.silly("returning cached data");
959
995
  return this.#data;
960
996
  }
961
997
  /**
@@ -987,12 +1023,13 @@ var WSCache = class {
987
1023
  * @param options.sentientCache - Cache of sentient outpost data, provided by Semlar
988
1024
  * @param options.eventEmitter - Emitter to push new worldstate updates to
989
1025
  */
990
- constructor({ language, kuvaCache, sentientCache, eventEmitter }) {
1026
+ constructor({ language, kuvaCache, sentientCache, eventEmitter, logger: uLogger }) {
991
1027
  this.#inner = void 0;
992
1028
  this.#kuvaCache = kuvaCache;
993
1029
  this.#sentientCache = sentientCache;
994
1030
  this.#language = language;
995
1031
  this.#emitter = eventEmitter;
1032
+ this.#logger = uLogger || logger;
996
1033
  }
997
1034
  /**
998
1035
  * Update the current data with new data
@@ -1003,19 +1040,20 @@ var WSCache = class {
1003
1040
  const deps = {
1004
1041
  locale: this.#language,
1005
1042
  kuvaData: [],
1006
- sentientData: void 0
1043
+ sentientData: void 0,
1044
+ logger: { debug: (message) => this.#logger.debug(message) }
1007
1045
  };
1008
1046
  try {
1009
1047
  const kuvaRaw = await this.#kuvaCache.get();
1010
1048
  if (kuvaRaw) deps.kuvaData = JSON.parse(kuvaRaw);
1011
1049
  } catch (err) {
1012
- logger.debug(`Error parsing kuva data for ${this.#language}: ${err}`);
1050
+ this.#logger.debug(`Error parsing kuva data for ${this.#language}: ${err}`);
1013
1051
  }
1014
1052
  try {
1015
1053
  const sentientRaw = await this.#sentientCache.get();
1016
1054
  if (sentientRaw) deps.sentientData = JSON.parse(sentientRaw);
1017
1055
  } catch (err) {
1018
- logger.warn(`Error parsing sentient data for ${this.#language}: ${err}`);
1056
+ this.#logger.warn(`Error parsing sentient data for ${this.#language}: ${err}`);
1019
1057
  }
1020
1058
  let t;
1021
1059
  try {
@@ -1044,7 +1082,7 @@ var WSCache = class {
1044
1082
  * @param newData - New string data to parse
1045
1083
  */
1046
1084
  set data(newData) {
1047
- logger.debug(`got new data for ${this.#language}, parsing...`);
1085
+ this.#logger.debug(`got new data for ${this.#language}, parsing...`);
1048
1086
  this.#update(newData);
1049
1087
  }
1050
1088
  /**
@@ -1070,6 +1108,7 @@ const debugEvents = [
1070
1108
  var Worldstate = class {
1071
1109
  #emitter;
1072
1110
  #locale;
1111
+ #logger;
1073
1112
  #worldStates = {};
1074
1113
  #wsRawCache;
1075
1114
  #kuvaCache;
@@ -1077,18 +1116,19 @@ var Worldstate = class {
1077
1116
  /**
1078
1117
  * Set up listening for specific platform and locale if provided.
1079
1118
  * @param eventEmitter - Emitter to push new worldstate events to
1080
- * @param locale - Locale (actually just language) to watch
1119
+ * @param options - Configuration options
1081
1120
  */
1082
- constructor(eventEmitter, locale) {
1121
+ constructor(eventEmitter, options = {}) {
1083
1122
  this.#emitter = eventEmitter;
1084
- this.#locale = locale;
1085
- logger.debug("starting up worldstate listener...");
1086
- if (locale) logger.debug(`only listening for ${locale}...`);
1123
+ this.#locale = options.locale;
1124
+ this.#logger = options.logger || logger;
1125
+ this.#logger.debug("starting up worldstate listener...");
1126
+ if (options.locale) this.#logger.debug(`only listening for ${options.locale}...`);
1087
1127
  }
1088
1128
  async init() {
1089
- this.#wsRawCache = await CronCache.make(worldstateUrl, worldstateCron);
1090
- this.#kuvaCache = await CronCache.make(kuvaUrl, externalCron);
1091
- this.#sentientCache = await CronCache.make(sentientUrl, externalCron);
1129
+ this.#wsRawCache = await CronCache.make(worldstateUrl, worldstateCron, this.#logger);
1130
+ this.#kuvaCache = await CronCache.make(kuvaUrl, externalCron, this.#logger);
1131
+ this.#sentientCache = await CronCache.make(sentientUrl, externalCron, this.#logger);
1092
1132
  await this.setUpRawEmitters();
1093
1133
  this.setupParsedEvents();
1094
1134
  }
@@ -1101,7 +1141,8 @@ var Worldstate = class {
1101
1141
  language: locale,
1102
1142
  kuvaCache: this.#kuvaCache,
1103
1143
  sentientCache: this.#sentientCache,
1104
- eventEmitter: this.#emitter
1144
+ eventEmitter: this.#emitter,
1145
+ logger: this.#logger
1105
1146
  });
1106
1147
  this.#wsRawCache.on("update", (dataStr) => {
1107
1148
  this.#emitter.emit("ws:update:raw", {
@@ -1110,7 +1151,7 @@ var Worldstate = class {
1110
1151
  });
1111
1152
  });
1112
1153
  this.#emitter.on("ws:update:raw", ({ data }) => {
1113
- logger.debug("ws:update:raw - updating locales data");
1154
+ this.#logger.debug("ws:update:raw - updating locales data");
1114
1155
  locales.forEach((locale) => {
1115
1156
  if (!this.#locale || this.#locale === locale) this.#worldStates[locale].data = data;
1116
1157
  });
@@ -1162,8 +1203,8 @@ var Worldstate = class {
1162
1203
  * @param packet - Data packet to emit
1163
1204
  */
1164
1205
  emit(id, packet) {
1165
- if (debugEvents.includes(packet.key)) logger.warn(packet.key);
1166
- logger.debug(`ws:update:event - emitting ${packet.id}`);
1206
+ if (debugEvents.includes(packet.key)) this.#logger.warn(packet.key);
1207
+ this.#logger.debug(`ws:update:event - emitting ${packet.id}`);
1167
1208
  delete packet.cycleStart;
1168
1209
  this.#emitter.emit(id, packet);
1169
1210
  }
@@ -1174,7 +1215,7 @@ var Worldstate = class {
1174
1215
  * @throws When the platform or locale aren't tracked and aren't updated
1175
1216
  */
1176
1217
  get(language = "en") {
1177
- logger.debug(`getting worldstate ${language}...`);
1218
+ this.#logger.debug(`getting worldstate ${language}...`);
1178
1219
  if (this.#worldStates?.[language]) return this.#worldStates?.[language]?.data;
1179
1220
  throw new Error(`Language (${language}) not tracked.\nEnsure that the parameters passed are correct`);
1180
1221
  }
@@ -1191,8 +1232,13 @@ var WorldstateEmitter = class WorldstateEmitter extends EventEmitter {
1191
1232
  #worldstate;
1192
1233
  #twitter;
1193
1234
  #rss;
1194
- static async make({ locale, features } = {}) {
1195
- const emitter = new WorldstateEmitter({ locale });
1235
+ #logger;
1236
+ static async make({ locale, features, logger: upLogger } = {}) {
1237
+ if (upLogger) setLogger(upLogger);
1238
+ const emitter = new WorldstateEmitter({
1239
+ locale,
1240
+ logger: upLogger
1241
+ });
1196
1242
  await emitter.#init(features?.length ? features : FEATURES);
1197
1243
  return emitter;
1198
1244
  }
@@ -1200,18 +1246,22 @@ var WorldstateEmitter = class WorldstateEmitter extends EventEmitter {
1200
1246
  * Pull in and instantiate emitters
1201
1247
  * @param options - Configuration options
1202
1248
  */
1203
- constructor({ locale } = {}) {
1249
+ constructor({ locale, logger: uLogger } = {}) {
1204
1250
  super();
1205
1251
  this.#locale = locale;
1252
+ this.#logger = uLogger || logger;
1206
1253
  }
1207
1254
  async #init(features) {
1208
- if (features.includes("rss")) this.#rss = new RSS(this);
1255
+ if (features.includes("rss")) this.#rss = new RSS(this, { logger: this.#logger });
1209
1256
  if (features.includes("worldstate")) {
1210
- this.#worldstate = new Worldstate(this, this.#locale);
1257
+ this.#worldstate = new Worldstate(this, {
1258
+ locale: this.#locale,
1259
+ logger: this.#logger
1260
+ });
1211
1261
  await this.#worldstate.init();
1212
1262
  }
1213
- if (features.includes("twitter")) this.#twitter = new TwitterCache(this);
1214
- logger.silly("hey look, i started up...");
1263
+ if (features.includes("twitter")) this.#twitter = new TwitterCache(this, { logger: this.#logger });
1264
+ this.#logger.silly("hey look, i started up...");
1215
1265
  this.setupLogging();
1216
1266
  }
1217
1267
  /**
@@ -1219,12 +1269,13 @@ var WorldstateEmitter = class WorldstateEmitter extends EventEmitter {
1219
1269
  * @private
1220
1270
  */
1221
1271
  setupLogging() {
1222
- this.on("error", logger.error);
1223
- this.on("rss", (body) => logger.silly(`emitted: ${body.id}`));
1224
- this.on("ws:update:raw", (body) => logger.silly(`emitted raw: ${body.platform}`));
1225
- this.on("ws:update:parsed", (body) => logger.silly(`emitted parsed: ${body.platform} in ${body.language}`));
1226
- this.on("ws:update:event", (body) => logger.silly(`emitted event: ${body.id} ${body.platform} in ${body.language}`));
1227
- this.on("tweet", (body) => logger.silly(`emitted: ${body.id}`));
1272
+ const log = this.#logger;
1273
+ this.on("error", log.error.bind(log));
1274
+ this.on("rss", (body) => log.silly(`emitted: ${body.id}`));
1275
+ this.on("ws:update:raw", (body) => log.silly(`emitted raw: ${body.platform}`));
1276
+ this.on("ws:update:parsed", (body) => log.silly(`emitted parsed: ${body.platform} in ${body.language}`));
1277
+ this.on("ws:update:event", (body) => log.silly(`emitted event: ${body.id} ${body.platform} in ${body.language}`));
1278
+ this.on("tweet", (body) => log.silly(`emitted: ${body.id}`));
1228
1279
  }
1229
1280
  /**
1230
1281
  * Get current rss feed items
@@ -1273,6 +1324,7 @@ var WorldstateEmitter = class WorldstateEmitter extends EventEmitter {
1273
1324
  this.#twitter.dispose();
1274
1325
  this.#twitter = void 0;
1275
1326
  }
1327
+ this.#logger.debug("Emitter destroyed");
1276
1328
  }
1277
1329
  };
1278
1330
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worldstate-emitter",
3
- "version": "2.4.5",
3
+ "version": "2.5.0",
4
4
  "description": "Event emitter for Warframe worldstate & other events - TypeScript support included",
5
5
  "keywords": [
6
6
  "warframe",