From 899b9ff9eacfe3c590ead36ffdcb628bc124ba21 Mon Sep 17 00:00:00 2001 From: Matt Isenhower Date: Sat, 5 Sep 2026 10:30:11 -0700 Subject: [PATCH] Move getTopOfCurrentHour out of utilities.js utilities.js is the filesystem helper module the posters still use, and the schedules updater only needed the time helper from it. With the helper in its own module the updater import graph no longer pulls in node:fs, which is what the Worker bundle needs. Also applies the remaining ESLint fixes outside src/web. Co-Authored-By: Claude Fable 5.1 --- babel.config.js | 4 +-- postcss.config.js | 14 +++++----- src/app/twitter/tweets/GearTweet.js | 3 ++- src/app/twitter/tweets/NewWeaponTweet.js | 4 +-- src/app/twitter/tweets/SplatfestTweet.js | 2 +- src/app/twitter/tweets/TwitterPostBase.js | 5 ++-- .../updater/updaters/CoopSchedulesUpdater.js | 2 +- src/app/updater/updaters/FestivalsUpdater.js | 10 +++---- .../updater/updaters/MerchandisesUpdater.js | 2 +- src/app/updater/updaters/SchedulesUpdater.js | 2 +- src/common/time.js | 7 +++++ src/common/utilities.js | 7 ----- test/updater/LocalizationProcessor.test.js | 1 - test/updater/updaters.test.js | 2 +- vue.config.js | 26 +++++++++---------- 15 files changed, 46 insertions(+), 45 deletions(-) create mode 100644 src/common/time.js diff --git a/babel.config.js b/babel.config.js index 5f710a5..91be244 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,5 +1,5 @@ module.exports = { presets: [ - '@vue/app' + '@vue/app', ], -} +}; diff --git a/postcss.config.js b/postcss.config.js index e724d57..66f82d9 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,15 +1,15 @@ -const IN_PRODUCTION = process.env.NODE_ENV === 'production' +const IN_PRODUCTION = process.env.NODE_ENV === 'production'; module.exports = { plugins: [ IN_PRODUCTION && require('@fullhuman/postcss-purgecss')({ content: [ - `./src/web/html/**/*.html`, - `./src/web/components/**/*.vue` + './src/web/html/**/*.html', + './src/web/components/**/*.vue', ], defaultExtractor (content) { - const contentWithoutStyleBlocks = content.replace(//gi, '') - return contentWithoutStyleBlocks.match(/[A-Za-z0-9-_/:]*[A-Za-z0-9-_/]+/g) || [] + const contentWithoutStyleBlocks = content.replace(//gi, ''); + return contentWithoutStyleBlocks.match(/[A-Za-z0-9-_/:]*[A-Za-z0-9-_/]+/g) || []; }, safelist: { standard: [ @@ -24,6 +24,6 @@ module.exports = { /data-v-.*/, ], }, - }) + }), ], -} +}; diff --git a/src/app/twitter/tweets/GearTweet.js b/src/app/twitter/tweets/GearTweet.js index 3d36f48..a2f0e6a 100644 --- a/src/app/twitter/tweets/GearTweet.js +++ b/src/app/twitter/tweets/GearTweet.js @@ -1,6 +1,7 @@ import TwitterPostBase from './TwitterPostBase.js'; import { captureGearScreenshot } from '../../screenshots/index.js'; -import { readData, getTopOfCurrentHour } from '../../../common/utilities.js'; +import { readData } from '../../../common/utilities.js'; +import { getTopOfCurrentHour } from '../../../common/time.js'; export default class GearTweet extends TwitterPostBase { getKey() { return 'gear'; } diff --git a/src/app/twitter/tweets/NewWeaponTweet.js b/src/app/twitter/tweets/NewWeaponTweet.js index 3027499..8aa526c 100644 --- a/src/app/twitter/tweets/NewWeaponTweet.js +++ b/src/app/twitter/tweets/NewWeaponTweet.js @@ -25,7 +25,7 @@ export default class NewWeaponTweet extends TwitterPostBase { } getTestData() { - let availabilities = this.getNewWeaponAvailabilities() + let availabilities = this.getNewWeaponAvailabilities(); if (availabilities.length) return availabilities; } @@ -41,7 +41,7 @@ export default class NewWeaponTweet extends TwitterPostBase { // Make sure we don't exceed the max tweet text length const names = data.map(availability => `- ${availability.weapon.name}`); for (let i = names.length; i > 0; i--) { - let text = `New weapons now available:\n`; + let text = 'New weapons now available:\n'; text += names.slice(0, i).join('\n'); text += '\n'; if (i < names.length) { diff --git a/src/app/twitter/tweets/SplatfestTweet.js b/src/app/twitter/tweets/SplatfestTweet.js index bbc3462..20564e2 100644 --- a/src/app/twitter/tweets/SplatfestTweet.js +++ b/src/app/twitter/tweets/SplatfestTweet.js @@ -83,7 +83,7 @@ export default class SplatfestTweet extends TwitterPostBase { // Is the current event (e.g., announcement, results, etc.) occurring simultaneously across all regions? isSimultaneous() { - return this.regions().every(region => this.getData(region)) + return this.regions().every(region => this.getData(region)); } shouldPostForCurrentTime() { diff --git a/src/app/twitter/tweets/TwitterPostBase.js b/src/app/twitter/tweets/TwitterPostBase.js index d82d66e..58ff733 100644 --- a/src/app/twitter/tweets/TwitterPostBase.js +++ b/src/app/twitter/tweets/TwitterPostBase.js @@ -3,7 +3,8 @@ import fs from 'node:fs'; import { mkdirpSync as mkdirp } from 'mkdirp'; import BlueskyClient from '../clients/BlueskyClient.js'; import TwitterClient from '../clients/TwitterClient.js'; -import { getTopOfCurrentHour, readJson, writeJson } from '../../../common/utilities.js'; +import { readJson, writeJson } from '../../../common/utilities.js'; +import { getTopOfCurrentHour } from '../../../common/time.js'; const blueskyLastTimesPath = path.resolve('storage/bluesky-lastPostTimes.json'); const twitterLastTimesPath = path.resolve('storage/twitter-lastTweetTimes.json'); @@ -101,7 +102,7 @@ export default class TwitterPostBase { let image = await this.getImage(data); fs.writeFileSync(filename, image); - this.info('Saved screenshot') + this.info('Saved screenshot'); } catch (e) { this.error('Couldn\'t save screenshot'); diff --git a/src/app/updater/updaters/CoopSchedulesUpdater.js b/src/app/updater/updaters/CoopSchedulesUpdater.js index 77437a1..28c2cc6 100644 --- a/src/app/updater/updaters/CoopSchedulesUpdater.js +++ b/src/app/updater/updaters/CoopSchedulesUpdater.js @@ -10,7 +10,7 @@ export default class CoopSchedulesUpdater extends Updater { imagePaths: [ '$..stage.image', '$..weapons[*].weapon.image', - '$..coop_special_weapon.image' + '$..coop_special_weapon.image', ], localization: [ { diff --git a/src/app/updater/updaters/FestivalsUpdater.js b/src/app/updater/updaters/FestivalsUpdater.js index abba4aa..7313970 100644 --- a/src/app/updater/updaters/FestivalsUpdater.js +++ b/src/app/updater/updaters/FestivalsUpdater.js @@ -42,12 +42,12 @@ export default class FestivalsUpdater extends Updater { // For some reason these got swapped out with images that have an opaque background // even though they started out with transparent images. jsonpath.apply(regionData, '$..images.alpha', value => value.replace( - "/images/festival/a070cc6b405b4fb335992d824097acd8.png", - "/images/festival/06b3b0b7773d9e6c4ac0a5cc5371fc32.png" + '/images/festival/a070cc6b405b4fb335992d824097acd8.png', + '/images/festival/06b3b0b7773d9e6c4ac0a5cc5371fc32.png', )); jsonpath.apply(regionData, '$..images.bravo', value => value.replace( - "/images/festival/00e4c5fdccd3720d07127084fc1f4152.png", - "/images/festival/d93df77468714c6211e9377f39a559f4.png" + '/images/festival/00e4c5fdccd3720d07127084fc1f4152.png', + '/images/festival/d93df77468714c6211e9377f39a559f4.png', )); // Download result ranking data @@ -63,7 +63,7 @@ export default class FestivalsUpdater extends Updater { let rankings = await this.handleRequest(splatnet.getFestivalRankings(id)); await this.publicStorage.writeJson(key, rankings, { cacheControl: DATA_CACHE_CONTROL }); } - catch (e) { + catch { // Do nothing } } diff --git a/src/app/updater/updaters/MerchandisesUpdater.js b/src/app/updater/updaters/MerchandisesUpdater.js index 624ba61..f27d449 100644 --- a/src/app/updater/updaters/MerchandisesUpdater.js +++ b/src/app/updater/updaters/MerchandisesUpdater.js @@ -49,7 +49,7 @@ export default class MerchandisesUpdater extends Updater { // We don't need the brand data since it should match the SplatNet gear's brand if (originalGear) - delete originalGear.brand + delete originalGear.brand; merchandise.original_gear = originalGear; } diff --git a/src/app/updater/updaters/SchedulesUpdater.js b/src/app/updater/updaters/SchedulesUpdater.js index 735d74f..4145d93 100644 --- a/src/app/updater/updaters/SchedulesUpdater.js +++ b/src/app/updater/updaters/SchedulesUpdater.js @@ -1,6 +1,6 @@ import Updater from './Updater.js'; import SplatNet from '../../../common/splatnet.js'; -import { getTopOfCurrentHour } from '../../../common/utilities.js'; +import { getTopOfCurrentHour } from '../../../common/time.js'; const STAGES_KEY = 'stages.json'; // private storage diff --git a/src/common/time.js b/src/common/time.js new file mode 100644 index 0000000..eb9c82d --- /dev/null +++ b/src/common/time.js @@ -0,0 +1,7 @@ +/** Unix timestamp (seconds) for the top of the current hour. */ +export function getTopOfCurrentHour() { + let date = new Date; + date.setUTCMinutes(0); + date.setUTCSeconds(0); + return Math.floor(date.getTime() / 1000); +} diff --git a/src/common/utilities.js b/src/common/utilities.js index 23227f9..da239ff 100644 --- a/src/common/utilities.js +++ b/src/common/utilities.js @@ -5,13 +5,6 @@ import stringify from 'json-stable-stringify'; const dataPath = path.resolve('dist/data'); -export function getTopOfCurrentHour() { - let date = new Date; - date.setUTCMinutes(0); - date.setUTCSeconds(0); - return Math.floor(date.getTime() / 1000); -} - export function readJson(filename) { return JSON.parse(fs.readFileSync(filename)); } diff --git a/test/updater/LocalizationProcessor.test.js b/test/updater/LocalizationProcessor.test.js index 8cc6d6f..854f1b3 100644 --- a/test/updater/LocalizationProcessor.test.js +++ b/test/updater/LocalizationProcessor.test.js @@ -5,7 +5,6 @@ import { MemoryBucket, BucketStorage } from '../../src/common/storage/index.js'; import LocalizationProcessor from '../../src/app/updater/LocalizationProcessor.js'; const en = { region: 'NA', language: 'en' }; -const ja = { region: 'JP', language: 'ja' }; const stages = { name: 'stages', entities: ['$..stage_a', '$..stage_b'], id: 'id', values: 'name' }; const rules = { name: 'rules', entities: '$..rule', id: 'key', values: ['name', 'multiline_name'] }; const gear = { name: 'gear', entities: '$..gear', id: ['kind', 'id'], values: 'name' }; diff --git a/test/updater/updaters.test.js b/test/updater/updaters.test.js index 5448d25..c025c03 100644 --- a/test/updater/updaters.test.js +++ b/test/updater/updaters.test.js @@ -7,7 +7,7 @@ import MerchandisesUpdater from '../../src/app/updater/updaters/MerchandisesUpda import FestivalsUpdater from '../../src/app/updater/updaters/FestivalsUpdater.js'; import OriginalGearImageUpdater from '../../src/app/updater/updaters/OriginalGearImageUpdater.js'; import { createUpdaters } from '../../src/app/updater/updateAll.js'; -import { getTopOfCurrentHour } from '../../src/common/utilities.js'; +import { getTopOfCurrentHour } from '../../src/common/time.js'; import gearData from '../../src/common/data/gear.json' with { type: 'json' }; import skills from '../../src/common/data/skills.json' with { type: 'json' }; import { fakeSplatNet, buckets, json, keys, setSessionEnvironment } from './support.js'; diff --git a/vue.config.js b/vue.config.js index 8cc0806..e011297 100644 --- a/vue.config.js +++ b/vue.config.js @@ -1,4 +1,4 @@ -const path = require('path') +const path = require('path'); module.exports = { assetsDir: 'assets', @@ -11,13 +11,13 @@ module.exports = { // and only used for the screenshots page (which is never served to the client). // An alternative method would be to set minChunks to 2 here. vendors: { - test: /[\\/]node_modules[\\/](?!(moment|moment-timezone)[\\/])/ + test: /[\\/]node_modules[\\/](?!(moment|moment-timezone)[\\/])/, }, // The common chunk doesn't really make sense here since the only reason we're splitting // pages is for the server-side screenshots page. Disabling it to save an HTTP request. - common: false - } - } + common: false, + }, + }, }, plugins: [], }, @@ -35,20 +35,20 @@ module.exports = { .rule('vue') .use('vue-loader') .tap(args => { - args.compilerOptions.whitespace = 'preserve' - }) + args.compilerOptions.whitespace = 'preserve'; + }); }, devServer: { static: { directory: path.join(__dirname, 'dist'), - } + }, }, pages: { index: { - entry: 'src/web/main.js' + entry: 'src/web/main.js', }, screenshots: { - entry: 'src/web/screenshots.js' - } - } -} + entry: 'src/web/screenshots.js', + }, + }, +};