diff --git a/.env b/.env index aba3261ed..eaae24c66 100644 --- a/.env +++ b/.env @@ -1,6 +1,6 @@ BROWSER=none -REACT_APP_API_ROOT=https://farmhand.vercel.app/ -REACT_APP_NAME=$npm_package_name -REACT_APP_VERSION=$npm_package_version -REACT_APP_TURN_USERNAME= -REACT_APP_TURN_CREDENTIAL= +VITE_API_ROOT=https://farmhand.vercel.app/ +VITE_NAME=$npm_package_name +VITE_FARMHAND_PACKAGE_VERSION=$npm_package_version +VITE_TURN_USERNAME= +VITE_TURN_CREDENTIAL= diff --git a/.env.development.local b/.env.development.local index 823eb23bd..9df7ac181 100644 --- a/.env.development.local +++ b/.env.development.local @@ -1,5 +1,5 @@ -REACT_APP_API_ROOT=http://localhost:3001/ -REACT_APP_ENABLE_FOREST=true +VITE_API_ROOT=http://localhost:3001/ +VITE_ENABLE_FOREST=true # Silence warnings from dev server # https://stackoverflow.com/a/70834076 diff --git a/.eslintrc.json b/.eslintrc.json index 3e6205b80..082a5133e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,9 +1,13 @@ { + "globals": { + "vitest": true + }, "extends": ["react-app"], "rules": { "import/order": [ "error", { "newlines-between": "always-and-inside-groups" } - ] + ], + "import/extensions": ["error", "always"] } } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7e0fadb6a..61758a1fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,15 +23,11 @@ jobs: - name: 'Install dependencies' run: npm ci - - name: 'Run tests' - run: npm test -- --reporters=default --reporters=jest-junit + - name: 'Lint code' + run: npm run lint - - name: Test Report - uses: dorny/test-reporter@v1 - with: - name: Jest Tests # Name of the check run which will be created - path: reports/jest-*.xml # Path to test results - reporter: jest-junit # Format of test results + - name: 'Run tests' + run: npm test -- --coverage --run - name: 'Check types' # TODO: Change this to check:types when all type errors are fixed @@ -44,4 +40,4 @@ jobs: - uses: actions/upload-artifact@v3 with: name: build-output - path: build + path: dist diff --git a/.github/workflows/run-release.yml b/.github/workflows/run-release.yml index 943ad52ae..aaf9bebd1 100644 --- a/.github/workflows/run-release.yml +++ b/.github/workflows/run-release.yml @@ -61,13 +61,13 @@ jobs: tags: true branch: main - - run: PUBLIC_URL='./' npm run build + - run: npm run build -- --base="./" - run: npm publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Prepare Web Artifacts - run: zip farmhand-web-${{ env.PACKAGE_VERSION }}.zip -r build/* + run: zip farmhand-web-${{ env.PACKAGE_VERSION }}.zip -r dist/* - name: Create Release id: create_release @@ -82,7 +82,7 @@ jobs: files: | ./farmhand-web-${{ env.PACKAGE_VERSION }}.zip - - run: node -e "console.log(require('./package.json').version)" > build/version.txt + - run: node -e "console.log(require('./package.json').version)" > dist/version.txt - name: Publish itch.io build uses: josephbmanley/butler-publish-itchio-action@master env: @@ -90,18 +90,18 @@ jobs: CHANNEL: html5 ITCH_GAME: Farmhand ITCH_USER: jeremyckahn - PACKAGE: build - VERSION_FILE: build/version.txt + PACKAGE: dist + VERSION_FILE: dist/version.txt - run: | - PUBLIC_URL='/farmhand' npm run build + npm run build -- --base='/farmhand' # https://github.com/marketplace/actions/deploy-to-github-pages - name: Deploy to jeremyckahn.github.io/farmhand uses: JamesIves/github-pages-deploy-action@v4 with: branch: gh-pages - folder: build + folder: dist clean: true single-commit: true diff --git a/.gitignore b/.gitignore index 8dca9e3b9..5a00c1ad1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ build Session.vim .DS_Store .idea +coverage .vercel diff --git a/README.md b/README.md index 8a48b6e1f..2d579be36 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Farmhand uses a [SemVer](https://semver.org/)-like versioning system. It differs ## Project overview -- This project is built with [Create React App](https://create-react-app.dev/), so please refer to the documentation of that project to learn about the development toolchain. +- This project uses [Vite](https://vitejs.dev/), so please refer to the documentation of that project to learn about the development toolchain. - Farmhand uses [Piskel](https://www.piskelapp.com/) for the art assets. ## Running locally @@ -138,13 +138,13 @@ The process will take several minutes to complete and it will notify the Discord Farmhand supports feature flags for code that should only be enabled in specific environments. To create a feature flag, add a line that looks like this in the relevant `.env` file: ``` -REACT_APP_ENABLE_[FEATURE_NAME]=true +VITE_ENABLE_[FEATURE_NAME]=true ``` Where `[FEATURE_NAME]` is replaced with the name of your feature. So, adding this to `.env.development.local`: ``` -REACT_APP_ENABLE_MINING=true +VITE_ENABLE_MINING=true ``` Would enable the `MINING` feature only for the local development environment. You can access the enabled feature flags at runtime by `import`ing the `features` Object from [`config.js`](https://github.com/jeremyckahn/farmhand/blob/develop/src/config.js). See [Adding Custom Environment Variables](https://create-react-app.dev/docs/adding-custom-environment-variables/) for more information on how to use environment variables. diff --git a/api-etc/templates.js b/api-etc/templates.js index 2aefc9db4..046fbdfd6 100644 --- a/api-etc/templates.js +++ b/api-etc/templates.js @@ -1,4 +1,4 @@ -import { itemsMap } from '../src/data/maps' +import { itemsMap } from '../src/data/maps.js' export const MARKET_SUMMARY_FOR_DISCORD = (_, room, valueAdjustments) => { let string = `Current market values for the **${room}** room:\n` diff --git a/api-etc/utils.js b/api-etc/utils.js index de2462d9a..54085afe4 100644 --- a/api-etc/utils.js +++ b/api-etc/utils.js @@ -1,11 +1,11 @@ -const redis = require('redis') +import redis from 'redis' -const { generateValueAdjustments } = require('../src/common/utils') -const { MAX_ROOM_NAME_LENGTH } = require('../src/common/constants') +import { generateValueAdjustments } from '../src/common/utils.js' +import { MAX_ROOM_NAME_LENGTH } from '../src/common/constants.js' -const { GLOBAL_ROOM_KEY, ACCEPTED_ORIGINS } = require('./constants') +import { GLOBAL_ROOM_KEY, ACCEPTED_ORIGINS } from './constants.js' -module.exports.getRedisClient = () => { +export const getRedisClient = () => { const client = redis.createClient({ host: process.env.REDIS_ENDPOINT, port: process.env.REDIS_PORT, @@ -26,7 +26,7 @@ module.exports.getRedisClient = () => { return client } -module.exports.getRoomData = async (roomKey, get, set) => { +export const getRoomData = async (roomKey, get, set) => { let roomData = JSON.parse(await get(roomKey)) || {} let { valueAdjustments } = roomData @@ -39,14 +39,14 @@ module.exports.getRoomData = async (roomKey, get, set) => { return roomData } -module.exports.getRoomName = req => +export const getRoomName = req => `room-${(req.query?.room || req.body?.room || GLOBAL_ROOM_KEY).slice( 0, MAX_ROOM_NAME_LENGTH )}` // https://vercel.com/support/articles/how-to-enable-cors -module.exports.allowCors = fn => async (req, res) => { +export const allowCors = fn => async (req, res) => { res.setHeader('Access-Control-Allow-Credentials', true) // origin is not defined when the request is from the same domain as the diff --git a/api/get-market-data.js b/api/get-market-data.js index e2f01a81e..163d9f9f2 100644 --- a/api/get-market-data.js +++ b/api/get-market-data.js @@ -1,25 +1,25 @@ // Dependencies required by ./utils (see below) need to be explicitly required // here to ensure that that they are included in serverless builds. Do NOT // remove them unless they are not needed by any upstream modules. -const { promisify } = require('util') +import { promisify } from 'util' -require('redis') -require('../src/common/utils') +import 'redis' +import '../src/common/utils.js' // End explicit requires for serverless builds -const { +import { allowCors, getRedisClient, getRoomData, getRoomName, -} = require('../api-etc/utils') +} from '../api-etc/utils.js' const client = getRedisClient() const get = promisify(client.get).bind(client) const set = promisify(client.set).bind(client) -module.exports = allowCors(async (req, res) => { +export default allowCors(async (req, res) => { const roomKey = getRoomName(req) const roomData = await getRoomData(roomKey, get, set) diff --git a/api/post-day-results.js b/api/post-day-results.js index e26e9fd42..c4f428f01 100644 --- a/api/post-day-results.js +++ b/api/post-day-results.js @@ -1,21 +1,21 @@ // Dependencies required by ./utils (see below) need to be explicitly required // here to ensure that that they are included in serverless builds. Do NOT // remove them unless they are not needed by any upstream modules. -require('redis') -require('../src/common/utils') -require('../src/common/constants') -require('../api-etc/constants') +import 'redis' +import '../src/common/utils.js' +import '../src/common/constants.js' +import '../api-etc/constants.js' // End explicit requires for serverless builds -const { promisify } = require('util') +import { promisify } from 'util' -const { +import { allowCors, getRedisClient, getRoomData, getRoomName, -} = require('../api-etc/utils') -const { random } = require('../src/common/utils') +} from '../api-etc/utils.js' +import { random } from '../src/common/utils.js' const client = getRedisClient() @@ -56,7 +56,7 @@ const applyPositionsToMarket = (valueAdjustments, positions) => { ) } -module.exports = allowCors(async (req, res) => { +export default allowCors(async (req, res) => { const { body: { positions = {} }, } = req diff --git a/api/publish-global-market-values-to-discord.js b/api/publish-global-market-values-to-discord.js index 119caa118..4d3bd2b00 100644 --- a/api/publish-global-market-values-to-discord.js +++ b/api/publish-global-market-values-to-discord.js @@ -1,25 +1,25 @@ // Dependencies required by ./utils (see below) need to be explicitly required // here to ensure that that they are included in serverless builds. Do NOT // remove them unless they are not needed by any upstream modules. -require('redis') -require('../src/common/utils') -require('../src/common/constants') -require('../api-etc/constants') +import 'redis' +import '../src/common/utils.js' +import '../src/common/constants.js' +import '../api-etc/constants.js' // End explicit requires for serverless builds -const { promisify } = require('util') +import { promisify } from 'util' -const axios = require('axios') +import axios from 'axios' -const { MARKET_SUMMARY_FOR_DISCORD } = require('../api-etc/templates') -const { allowCors, getRedisClient, getRoomData } = require('../api-etc/utils') +import { MARKET_SUMMARY_FOR_DISCORD } from '../api-etc/templates.js' +import { allowCors, getRedisClient, getRoomData } from '../api-etc/utils.js' const client = getRedisClient() const get = promisify(client.get).bind(client) const set = promisify(client.set).bind(client) -module.exports = allowCors(async (req, res) => { +export default allowCors(async (req, res) => { const { valueAdjustments } = await getRoomData('room-global', get, set) const content = MARKET_SUMMARY_FOR_DISCORD`${'global'}${valueAdjustments}` const { status } = await axios.post( diff --git a/public/index.html b/index.html similarity index 82% rename from public/index.html rename to index.html index 87e8afb3e..83fedcd43 100644 --- a/public/index.html +++ b/index.html @@ -6,39 +6,31 @@ + - - - - +