diff --git a/doc/adr/0006-fully-resolved-module-paths.md b/doc/adr/0006-fully-resolved-module-paths.md new file mode 100644 index 000000000..4e27f2a1d --- /dev/null +++ b/doc/adr/0006-fully-resolved-module-paths.md @@ -0,0 +1,37 @@ +# 6. Fully-resolved Module Paths + +Date: 2024-09-02 + +## Status + +Accepted + +## Context + +Farmhand's Vercel-based API code imports a subset of the browser-based game code in order to function. The browser code is processed by Vite at build time and therefore doesn't require fully-resolved module paths. So, this would be a valid import: + +```js +import Farmhand from './components/Farmhand' +``` + +Which would resolve to `./components/Farmhand/index.js`. However, Vercel executes serverless function code as raw, [standard ES6 modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) via Node. So, code with shorthand paths such as this break the Vercel API. Fully-resolved import paths that look like this work in both environments: + +```js +import Farmhand from './components/Farmhand/index.js' +``` + +--- + +See: + +- https://github.com/jeremyckahn/farmhand/pull/506 (reverted) +- https://github.com/jeremyckahn/farmhand/pull/509 (contains #506 along with fixes) + +## Decision + +In order to keep code compatible with both client-side web app and the server-side API, modules paths must be fully resolved. So, they must include the trailing `.js` file extension. + +## Consequences + +- Code can be consumed by both Vite for the web app and Node in Vercel for the server API +- Module paths are more verbose and less flexible diff --git a/package-lock.json b/package-lock.json index 5e4925db8..91a98d341 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@jeremyckahn/farmhand", - "version": "1.18.18", + "version": "1.18.19", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@jeremyckahn/farmhand", - "version": "1.18.18", + "version": "1.18.19", "license": "GPL-2.0-or-later", "dependencies": { "@emotion/react": "^11.11.1", @@ -28,7 +28,7 @@ "compass-mixins": "^0.12.12", "dinero.js": "^1.7.0", "electron-is-dev": "^2.0.0", - "electron-updater": "^5.0.5", + "electron-updater": "^6.3.0", "fast-memoize": "^2.5.2", "file-saver": "^2.0.2", "fs": "npm:browserify-fs@^1.0.0", @@ -7478,11 +7478,6 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" - }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -9952,9 +9947,9 @@ } }, "node_modules/axios": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", - "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.6.tgz", + "integrity": "sha512-Ekur6XDwhnJ5RgOCaxFnXyqlPALI3rVeukZMwOdfghW7/wGz784BYKiQq+QD8NPcr91KRo30KfHOchyijwWw7g==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -13626,25 +13621,24 @@ "dev": true }, "node_modules/electron-updater": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-5.3.0.tgz", - "integrity": "sha512-iKEr7yQBcvnQUPnSDYGSWC9t0eF2YbZWeYYYZzYxdl+HiRejXFENjYMnYjoOm2zxyD6Cr2JTHZhp9pqxiXuCOw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.3.0.tgz", + "integrity": "sha512-3Xlezhk+dKaSQrOnkQNqCGiuGSSUPO9BV9TQZ4Iig6AyTJ4FzJONE5gFFc382sY53Sh9dwJfzKsA3DxRHt2btw==", "dependencies": { - "@types/semver": "^7.3.6", - "builder-util-runtime": "9.1.1", - "fs-extra": "^10.0.0", + "builder-util-runtime": "9.2.5", + "fs-extra": "^10.1.0", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", "lodash.escaperegexp": "^4.1.2", "lodash.isequal": "^4.5.0", - "semver": "^7.3.5", - "typed-emitter": "^2.1.0" + "semver": "^7.3.8", + "tiny-typed-emitter": "^2.1.0" } }, "node_modules/electron-updater/node_modules/builder-util-runtime": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.1.1.tgz", - "integrity": "sha512-azRhYLEoDvRDR8Dhis4JatELC/jUvYjm4cVSj7n9dauGTOM2eeNn9KS0z6YA6oDsjI1xphjNbY6PZZeHPzzqaw==", + "version": "9.2.5", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.5.tgz", + "integrity": "sha512-HjIDfhvqx/8B3TDN4GbABQcgpewTU4LMRTQPkVpKYV3lsuxEJoIfvg09GyWTNmfVNSUAYf+fbTN//JX4TH20pg==", "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" @@ -27459,7 +27453,7 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "devOptional": true, + "dev": true, "dependencies": { "tslib": "^2.1.0" } @@ -29674,6 +29668,11 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" }, + "node_modules/tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==" + }, "node_modules/tiny-warning": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", @@ -30261,14 +30260,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz", - "integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==", - "optionalDependencies": { - "rxjs": "*" - } - }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -38610,11 +38601,6 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, - "@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" - }, "@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -40374,9 +40360,9 @@ "dev": true }, "axios": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", - "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.6.tgz", + "integrity": "sha512-Ekur6XDwhnJ5RgOCaxFnXyqlPALI3rVeukZMwOdfghW7/wGz784BYKiQq+QD8NPcr91KRo30KfHOchyijwWw7g==", "requires": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -43146,25 +43132,24 @@ "dev": true }, "electron-updater": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-5.3.0.tgz", - "integrity": "sha512-iKEr7yQBcvnQUPnSDYGSWC9t0eF2YbZWeYYYZzYxdl+HiRejXFENjYMnYjoOm2zxyD6Cr2JTHZhp9pqxiXuCOw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.3.0.tgz", + "integrity": "sha512-3Xlezhk+dKaSQrOnkQNqCGiuGSSUPO9BV9TQZ4Iig6AyTJ4FzJONE5gFFc382sY53Sh9dwJfzKsA3DxRHt2btw==", "requires": { - "@types/semver": "^7.3.6", - "builder-util-runtime": "9.1.1", - "fs-extra": "^10.0.0", + "builder-util-runtime": "9.2.5", + "fs-extra": "^10.1.0", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", "lodash.escaperegexp": "^4.1.2", "lodash.isequal": "^4.5.0", - "semver": "^7.3.5", - "typed-emitter": "^2.1.0" + "semver": "^7.3.8", + "tiny-typed-emitter": "^2.1.0" }, "dependencies": { "builder-util-runtime": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.1.1.tgz", - "integrity": "sha512-azRhYLEoDvRDR8Dhis4JatELC/jUvYjm4cVSj7n9dauGTOM2eeNn9KS0z6YA6oDsjI1xphjNbY6PZZeHPzzqaw==", + "version": "9.2.5", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.5.tgz", + "integrity": "sha512-HjIDfhvqx/8B3TDN4GbABQcgpewTU4LMRTQPkVpKYV3lsuxEJoIfvg09GyWTNmfVNSUAYf+fbTN//JX4TH20pg==", "requires": { "debug": "^4.3.4", "sax": "^1.2.4" @@ -53586,7 +53571,7 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "devOptional": true, + "dev": true, "requires": { "tslib": "^2.1.0" } @@ -55324,6 +55309,11 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" }, + "tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==" + }, "tiny-warning": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", @@ -55770,14 +55760,6 @@ "possible-typed-array-names": "^1.0.0" } }, - "typed-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz", - "integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==", - "requires": { - "rxjs": "*" - } - }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", diff --git a/package.json b/package.json index 5c159eab6..18127169a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@jeremyckahn/farmhand", - "version": "1.18.18", + "version": "1.18.19", "publishConfig": { "access": "public" }, @@ -112,7 +112,7 @@ "compass-mixins": "^0.12.12", "dinero.js": "^1.7.0", "electron-is-dev": "^2.0.0", - "electron-updater": "^5.0.5", + "electron-updater": "^6.3.0", "fast-memoize": "^2.5.2", "file-saver": "^2.0.2", "fs": "npm:browserify-fs@^1.0.0", diff --git a/src/constants.js b/src/constants.js index ed5b65a91..007359f96 100644 --- a/src/constants.js +++ b/src/constants.js @@ -44,8 +44,8 @@ export const INITIAL_FIELD_HEIGHT = 10 export const PURCHASEABLE_FIELD_SIZES = freeze( new Map([ [1, { columns: 8, rows: 12, price: 1_000 }], - [2, { columns: 10, rows: 16, price: 2_000 }], - [3, { columns: 12, rows: 18, price: 3_000 }], + [2, { columns: 10, rows: 16, price: 5_000 }], + [3, { columns: 12, rows: 18, price: 20_000 }], ]) ) @@ -53,7 +53,7 @@ export const INITIAL_FOREST_WIDTH = 4 export const INITIAL_FOREST_HEIGHT = 1 /** - * @type Map + * @type Map */ export const PURCHASABLE_FOREST_SIZES = freeze( new Map([ @@ -68,7 +68,7 @@ export const LARGEST_PURCHASABLE_FIELD_SIZE = /** @type {farmhand.purchaseableFi )) export const PURCHASEABLE_COMBINES = freeze( - new Map([[1, { type: 'Basic', price: 500_000 }]]) + new Map([[1, { type: 'Basic', price: 250_000 }]]) ) export const PURCHASEABLE_COMPOSTERS = freeze( @@ -76,22 +76,22 @@ export const PURCHASEABLE_COMPOSTERS = freeze( ) export const PURCHASEABLE_SMELTERS = freeze( - new Map([[1, { type: 'Basic', price: 500_000 }]]) + new Map([[1, { type: 'Basic', price: 250_000 }]]) ) export const PURCHASEABLE_COW_PENS = freeze( new Map([ - [1, { cows: 10, price: 1500 }], - [2, { cows: 20, price: 2500 }], - [3, { cows: 30, price: 3500 }], + [1, { cows: 10, price: 1_500 }], + [2, { cows: 20, price: 10_000 }], + [3, { cows: 30, price: 50_000 }], ]) ) export const PURCHASEABLE_CELLARS = freeze( new Map([ [1, { space: 10, price: 250_000 }], - [2, { space: 20, price: 400_000 }], - [3, { space: 30, price: 500_000 }], + [2, { space: 20, price: 750_000 }], + [3, { space: 30, price: 2_000_000 }], ]) ) diff --git a/src/game-logic/reducers/purchaseCombine.test.js b/src/game-logic/reducers/purchaseCombine.test.js index 0af94ec25..7d61b8b18 100644 --- a/src/game-logic/reducers/purchaseCombine.test.js +++ b/src/game-logic/reducers/purchaseCombine.test.js @@ -14,7 +14,10 @@ describe('purchaseCombine', () => { }) test('deducts money', () => { - const { money } = purchaseCombine({ money: 500000 }, 1) - expect(money).toEqual(PURCHASEABLE_COMBINES.get(1).price - 500000) + const { money } = purchaseCombine( + { money: (PURCHASEABLE_COMBINES.get(1)?.price ?? 0) + 10 }, + 1 + ) + expect(money).toEqual(10) }) }) diff --git a/tsconfig.json b/tsconfig.json index c295a38cc..3b5ce50b5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,8 +5,10 @@ /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */, - "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, - // "lib": [], /* Specify library files to be included in the compilation. */ + "module": "ES2022" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + "lib": [ + "ES2022" + ] /* Specify library files to be included in the compilation. */, // "allowJs": true, /* Allow javascript files to be compiled. */ "checkJs": true /* Report errors in .js files. */, "jsx": "preserve" /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */, diff --git a/vercel.json b/vercel.json index 266b51aef..c577aa7d8 100644 --- a/vercel.json +++ b/vercel.json @@ -1,5 +1,5 @@ { - "ignoreCommand": "stat static", + "ignoreCommand": "stat static || (git log -1 --pretty=oneline --abbrev-commit | grep -w \"\\[skip deploy\\]\" && exit 0 || exit 1)", "framework": "vite", "outputDirectory": "dist", "rewrites": [