diff --git a/.github/workflows/ci_suite.yml b/.github/workflows/ci_suite.yml
index 1668d2f886c0..342a6b332289 100644
--- a/.github/workflows/ci_suite.yml
+++ b/.github/workflows/ci_suite.yml
@@ -39,7 +39,7 @@ jobs:
bash tools/ci/check_changelogs.sh
bash tools/ci/check_grep.sh
bash tools/ci/check_misc.sh
- tools/build/build --ci lint
+ tools/build/build --ci lint tgui-test
tools/bootstrap/python -m dmi.test
tools/bootstrap/python -m mapmerge2.dmm_test
~/dreamchecker > ${GITHUB_WORKSPACE}/output-annotations.txt 2>&1
@@ -85,15 +85,6 @@ jobs:
with:
path: ~/BYOND
key: ${{ runner.os }}-byond-${{ secrets.CACHE_PURGE_KEY }}
- - name: Restore Yarn cache
- uses: actions/cache@v2
- with:
- path: tgui/.yarn/cache
- key: ${{ runner.os }}-yarn-${{ secrets.CACHE_PURGE_KEY }}-${{ hashFiles('tgui/yarn.lock') }}
- restore-keys: |
- ${{ runner.os }}-build-${{ secrets.CACHE_PURGE_KEY }}-
- ${{ runner.os }}-build-
- ${{ runner.os }}-
- name: Setup database
run: |
sudo systemctl start mysql
@@ -111,7 +102,7 @@ jobs:
run: |
bash tools/ci/install_byond.sh
source $HOME/BYOND/byond/bin/byondsetup
- tools/build/build --ci -DCIBUILDING
+ tools/build/build --ci dm -DCIBUILDING
bash tools/ci/run_server.sh
test_windows:
diff --git a/BUILD.bat b/BUILD.bat
deleted file mode 100644
index 68eaef0c2d35..000000000000
--- a/BUILD.bat
+++ /dev/null
@@ -1,3 +0,0 @@
-@echo off
-call "%~dp0\tools\build\build.bat" %*
-pause
diff --git a/BUILD.cmd b/BUILD.cmd
new file mode 100644
index 000000000000..dc791f60c9b7
--- /dev/null
+++ b/BUILD.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\tools\build\build.bat" --wait-on-error build %*
diff --git a/CLEAN.bat b/CLEAN.bat
deleted file mode 100644
index 47293bb7693e..000000000000
--- a/CLEAN.bat
+++ /dev/null
@@ -1,3 +0,0 @@
-@echo off
-call "%~dp0\tools\build\build.bat" dist-clean
-pause
diff --git a/README.md b/README.md
index c8c0e4028263..e4411c4c13da 100644
--- a/README.md
+++ b/README.md
@@ -30,9 +30,9 @@ Space Station 13 is a paranoia-laden round-based roleplaying game set against th
On **2021-01-04** we have changed the way to compile the codebase.
-Find `BUILD.bat` here in the root folder of tgstation, and double click it to initiate the build. It consists of multiple steps and might take around 1-5 minutes to compile.
+**The quick way**. Find `bin/server.cmd` in this folder and double click it to automatically build and host the server on port 1337.
-After it finishes, you can then [setup the server](.github/RUNNING_A_SERVER.md) normally by opening `tgstation.dmb` in DreamDaemon.
+**The long way**. Find `bin/build.cmd` in this folder, and double click it to initiate the build. It consists of multiple steps and might take around 1-5 minutes to compile. If it closes, it means it has finished its job. You can then [setup the server](.github/RUNNING_A_SERVER.md) normally by opening `tgstation.dmb` in DreamDaemon.
**Building tgstation in DreamMaker directly is now deprecated and might produce errors**, such as `'tgui.bundle.js': cannot find file`.
diff --git a/RUN_SERVER.bat b/RUN_SERVER.bat
deleted file mode 100644
index 93438f0c2e42..000000000000
--- a/RUN_SERVER.bat
+++ /dev/null
@@ -1,3 +0,0 @@
-@echo off
-call "%~dp0\tools\build\build.bat" server %*
-pause
diff --git a/bin/build.cmd b/bin/build.cmd
new file mode 100644
index 000000000000..98c2ef45e15b
--- /dev/null
+++ b/bin/build.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error build %*
diff --git a/bin/clean.cmd b/bin/clean.cmd
new file mode 100644
index 000000000000..8eacd92ebd7a
--- /dev/null
+++ b/bin/clean.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error clean-all %*
diff --git a/bin/server.cmd b/bin/server.cmd
new file mode 100644
index 000000000000..c6e6642baf48
--- /dev/null
+++ b/bin/server.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error server %*
diff --git a/bin/test.cmd b/bin/test.cmd
new file mode 100644
index 000000000000..a76a9c6745c2
--- /dev/null
+++ b/bin/test.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error dm-test %*
diff --git a/bin/tgui-build.cmd b/bin/tgui-build.cmd
new file mode 100644
index 000000000000..7804fc6daaad
--- /dev/null
+++ b/bin/tgui-build.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui tgui-lint tgui-test %*
diff --git a/bin/tgui-dev.cmd b/bin/tgui-dev.cmd
new file mode 100644
index 000000000000..25ff3495d429
--- /dev/null
+++ b/bin/tgui-dev.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui-dev %*
diff --git a/bin/tgui-sonar.cmd b/bin/tgui-sonar.cmd
new file mode 100644
index 000000000000..e083f65362ac
--- /dev/null
+++ b/bin/tgui-sonar.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui-sonar %*
diff --git a/tgui/.editorconfig b/tgui/.editorconfig
index 33092d4928a4..d1d8a4176a41 100644
--- a/tgui/.editorconfig
+++ b/tgui/.editorconfig
@@ -8,6 +8,3 @@ end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
-
-[*.md]
-max_line_length = 80
diff --git a/tgui/.eslintrc-harder.yml b/tgui/.eslintrc-harder.yml
deleted file mode 100644
index d46612596793..000000000000
--- a/tgui/.eslintrc-harder.yml
+++ /dev/null
@@ -1,43 +0,0 @@
-rules:
- ## Enforce a maximum cyclomatic complexity allowed in a program
- # complexity: [warn, { max: 25 }]
- ## Enforce consistent brace style for blocks
- # brace-style: [warn, stroustrup, { allowSingleLine: false }]
- ## Enforce the consistent use of either backticks, double, or single quotes
- # quotes: [warn, single, {
- # avoidEscape: true,
- # allowTemplateLiterals: true,
- # }]
- # react/jsx-closing-bracket-location: [warn, {
- # selfClosing: after-props,
- # nonEmpty: after-props,
- # }]
- # react/display-name: warn
-
- ## Radar
- ## ------------------------------------------------------
- # radar/cognitive-complexity: warn
- radar/max-switch-cases: warn
- radar/no-all-duplicated-branches: warn
- radar/no-collapsible-if: warn
- radar/no-collection-size-mischeck: warn
- radar/no-duplicate-string: warn
- radar/no-duplicated-branches: warn
- radar/no-element-overwrite: warn
- radar/no-extra-arguments: warn
- radar/no-identical-conditions: warn
- radar/no-identical-expressions: warn
- radar/no-identical-functions: warn
- radar/no-inverted-boolean-check: warn
- radar/no-one-iteration-loop: warn
- radar/no-redundant-boolean: warn
- radar/no-redundant-jump: warn
- radar/no-same-line-conditional: warn
- radar/no-small-switch: warn
- radar/no-unused-collection: warn
- radar/no-use-of-empty-return-value: warn
- radar/no-useless-catch: warn
- radar/prefer-immediate-return: warn
- radar/prefer-object-literal: warn
- radar/prefer-single-boolean-return: warn
- radar/prefer-while: warn
diff --git a/tgui/.eslintrc-sonar.yml b/tgui/.eslintrc-sonar.yml
new file mode 100644
index 000000000000..3cdd49f889e2
--- /dev/null
+++ b/tgui/.eslintrc-sonar.yml
@@ -0,0 +1,26 @@
+rules:
+ # radar/cognitive-complexity: error
+ radar/max-switch-cases: error
+ radar/no-all-duplicated-branches: error
+ radar/no-collapsible-if: error
+ radar/no-collection-size-mischeck: error
+ radar/no-duplicate-string: error
+ radar/no-duplicated-branches: error
+ radar/no-element-overwrite: error
+ radar/no-extra-arguments: error
+ radar/no-identical-conditions: error
+ radar/no-identical-expressions: error
+ radar/no-identical-functions: error
+ radar/no-inverted-boolean-check: error
+ radar/no-one-iteration-loop: error
+ radar/no-redundant-boolean: error
+ radar/no-redundant-jump: error
+ radar/no-same-line-conditional: error
+ radar/no-small-switch: error
+ radar/no-unused-collection: error
+ radar/no-use-of-empty-return-value: error
+ radar/no-useless-catch: error
+ radar/prefer-immediate-return: error
+ radar/prefer-object-literal: error
+ radar/prefer-single-boolean-return: error
+ radar/prefer-while: error
diff --git a/tgui/.gitattributes b/tgui/.gitattributes
index 71550f35c1c8..3103a46c2426 100644
--- a/tgui/.gitattributes
+++ b/tgui/.gitattributes
@@ -13,10 +13,9 @@
*.md text eol=lf
*.bat text eol=lf
yarn.lock text eol=lf
-bin/tgui text eol=lf
-## Treat bundles as binary and ignore them during conflicts
-*.bundle.* binary merge=tgui-merge-bundle
-*.chunk.* binary merge=tgui-merge-bundle
+## Treat bundles as binary
+*.bundle.* binary
+*.chunk.* binary
.yarn/releases/**/* binary
.yarn/plugins/**/* binary
diff --git a/tgui/.gitignore b/tgui/.gitignore
index bb1f522883ce..55091b218626 100644
--- a/tgui/.gitignore
+++ b/tgui/.gitignore
@@ -16,6 +16,7 @@ package-lock.json
/public/.tmp/**/*
/public/**/*
!/public/*.html
+/coverage
## Previously ignored locations that are kept to avoid confusing git
## while transitioning to a new project structure.
diff --git a/tgui/README.md b/tgui/README.md
index 6da0de066d37..4103db1d02b6 100644
--- a/tgui/README.md
+++ b/tgui/README.md
@@ -4,124 +4,98 @@
tgui is a robust user interface framework of /tg/station.
-tgui is very different from most UIs you will encounter in BYOND programming.
-It is heavily reliant on Javascript and web technologies as opposed to DM.
-If you are familiar with NanoUI (a library which can be found on almost
-every other SS13 codebase), tgui should be fairly easy to pick up.
+tgui is very different from most UIs you will encounter in BYOND programming. It is heavily reliant on Javascript and web technologies as opposed to DM. If you are familiar with NanoUI (a library which can be found on almost every other SS13 codebase), tgui should be fairly easy to pick up.
## Learn tgui
-People come to tgui from different backgrounds and with different
-learning styles. Whether you prefer a more theoretical or a practical
-approach, we hope you’ll find this section helpful.
+People come to tgui from different backgrounds and with different learning styles. Whether you prefer a more theoretical or a practical approach, we hope you’ll find this section helpful.
### Practical Tutorial
-If you are completely new to frontend and prefer to **learn by doing**,
-start with our [practical tutorial](docs/tutorial-and-examples.md).
+If you are completely new to frontend and prefer to **learn by doing**, start with our [practical tutorial](docs/tutorial-and-examples.md).
### Guides
-This project uses **Inferno** - a very fast UI rendering engine with a similar
-API to React. Take your time to read these guides:
+This project uses **Inferno** - a very fast UI rendering engine with a similar API to React. Take your time to read these guides:
- [React guide](https://reactjs.org/docs/hello-world.html)
-- [Inferno documentation](https://infernojs.org/docs/guides/components) -
-highlights differences with React.
+- [Inferno documentation](https://infernojs.org/docs/guides/components) - highlights differences with React.
-If you were already familiar with an older, Ractive-based tgui, and want
-to translate concepts between old and new tgui, read this
-[interface conversion guide](docs/converting-old-tgui-interfaces.md).
+If you were already familiar with an older, Ractive-based tgui, and want to translate concepts between old and new tgui, read this [interface conversion guide](docs/converting-old-tgui-interfaces.md).
## Pre-requisites
-You will need these programs to start developing in tgui:
+If you are using the tooling provided in this repo, everything is included! Feel free to skip this step.
-- [Node v12.18.3+](https://nodejs.org/en/download/)
-- [Yarn v1.22.4+](https://yarnpkg.com/getting-started/install) (optional)
-- [Git Bash](https://git-scm.com/downloads)
- or [MSys2](https://www.msys2.org/) (optional)
+However, if you want finer control over the installation or build process, you will need these:
-**DO NOT install Chocolatey if Node installer asks you to!**
+- [Node v12.20+](https://nodejs.org/en/download/)
+ - **DO NOT install Chocolatey if Node installer asks you to!**
+- [Yarn v1.22.4+](https://yarnpkg.com/getting-started/install)
+ - You only need to run `npm install -g yarn`.
## Usage
-**For Git Bash, MSys2, WSL, Linux or macOS users:**
+**Via provided cmd scripts (Windows)**:
-Change your directory to `tgui`.
+- `bin/tgui-build` - Build tgui in production mode and run a full suite of code checks.
+- `bin/tgui-dev` - Launch a development server.
+ - `bin/tgui-dev --reload` - Reload byond cache once.
+ - `bin/tgui-dev --debug` - Run server with debug logging enabled.
+ - `bin/tgui-dev --no-hot` - Disable hot module replacement (helps when doing development on IE8).
+- `bin/tgui-sonar` - Analyze code with SonarQube.
-Run `bin/tgui --install-git-hooks` to install merge drivers which will
-assist you in conflict resolution when rebasing your branches. Only has
-to be done once.
+> To open a CMD or PowerShell window in any open folder, right click **while holding Shift** on any free space in the folder, then click on either `Open command window here` or `Open PowerShell window here`.
-Run `bin/tgui` with any of the options listed below.
+**Via Juke Build (cross-platform)**:
-**For Windows CMD or PowerShell users:**
+- `tools/build/build tgui` - Build tgui in production mode.
+- `tools/build/build tgui-dev` - Build tgui in production mode.
+ - `tools/build/build tgui-dev --reload` - Reload byond cache once.
+ - `tools/build/build tgui-dev --debug` - Run server with debug logging enabled.
+ - `tools/build/build tgui-dev --no-hot` - Disable hot module replacement (helps when doing development on IE8).
+- `tools/build/build tgui-lint` - Show (and auto-fix) problems with the code.
+- `tools/build/build tgui-sonar` - Analyze code with SonarQube.
+- `tools/build/build tgui-test` - Run unit and integration tests.
+- `tools/build/build tgui-analyze` - Run a bundle analyzer.
+- `tools/build/build tgui-clean` - Clean up tgui folder.
-If you haven't opened the console already, you can do that by holding
-Shift and right clicking on the `tgui` folder, then pressing
-either `Open command window here` or `Open PowerShell window here`.
+> With Juke Build, you can run multiple targets together, e.g.:
+> ```
+> tools/build/build tgui tgui-lint tgui-tsc tgui-test
+> ```
-Run `.\bin\tgui.bat` with any of the options listed below.
+**Via Yarn (cross-platform)**:
-> If using PowerShell, you will receive errors if trying to run
-> `.\bin\tgui.ps1`, because default Windows policy does not allow direct
-> execution of PS1 scripts. Run `.\bin\tgui.bat` instead.
+Run `yarn install` once to install tgui dependencies.
-**Available commands:**
+- `yarn tgui:build` - Build tgui in production mode.
+ - `yarn tgui:build [options]` - Build tgui with custom webpack options.
+- `yarn tgui:dev` - Launch a development server.
+ - `yarn tgui:dev --reload` - Reload byond cache once.
+ - `yarn tgui:dev --debug` - Run server with debug logging enabled.
+ - `yarn tgui:dev --no-hot` - Disable hot module replacement (helps when doing development on IE8).
+- `yarn tgui:lint` - Show (and auto-fix) problems with the code.
+- `yarn tgui:sonar` - Analyze code with SonarQube.
+- `yarn tgui:tsc` - Check code with TypeScript compiler.
+- `yarn tgui:test` - Run unit and integration tests.
+- `yarn tgui:analyze` - Run a bundle analyzer.
-- `bin/tgui` - Build the project in production mode.
-- `bin/tgui --dev` - Launch a development server.
- - tgui development server provides you with incremental compilation,
- hot module replacement and logging facilities in all running instances
- of tgui. In short, this means that you will instantly see changes in the
- game as you code it. Very useful, highly recommended.
- - In order to use it, you should start the game server first, connect to it
- and wait until the world has been properly loaded and you are no longer
- in the lobby. Start tgui dev server, and once it has finished building,
- press F5 on any tgui window. You'll know that it's hooked correctly if
- you see a green bug icon in titlebar and data gets dumped to the console.
-- `bin/tgui --dev --reload` - Reload byond cache once.
-- `bin/tgui --dev --debug` - Run server with debug logging enabled.
-- `bin/tgui --dev --no-hot` - Disable hot module replacement (helps when
-doing development on IE8).
-- `bin/tgui --lint` - Show problems with the code.
-- `bin/tgui --fix` - Auto-fix problems with the code.
-- `bin/tgui --test` - Run tests.
-- `bin/tgui --analyze` - Run a bundle analyzer.
-- `bin/tgui --clean` - Clean up project repo.
-- `bin/tgui [webpack options]` - Build the project with custom webpack
-options.
+## Important memo
-**For virgins:**
-
-You can double-click these batch files to achieve the same thing:
-
-- `bin\tgui.bat` - Build the project in production mode.
-- `bin\tgui-dev-server.bat` - Launch a development server.
-
-> Remember to always run a full build before submitting a PR. It creates
-> a compressed javascript bundle which is then referenced from DM code.
-> We prefer to keep it version controlled, so that people could build the
-> game just by using Dream Maker.
+Remember to always run a full build of tgui before submitting a PR, because it comes with the full suite of CI checks, and runs much faster on your computer than on GitHub servers. It will save you some time and possibly a few broken commits! Address the issues that are reported by the tooling as much as possible, because maintainers will beat you with a ruler and force you to address them anyway (unless it's a false positive or something unfixable).
## Troubleshooting
**Development server is crashing**
-Make sure path to your working directory does not contain spaces or special
-unicode characters. If so, move codebase to a location which does not contain
-spaces or unicode characters.
+Make sure path to your working directory does not contain spaces, special unicode characters, exclamation marks or any other special symbols. If so, move codebase to a location which does not contain these characters.
-This is a known issue with Yarn Berry, and fix is going to happen someday.
+This is a known issue with Yarn (and some other tools, like Webpack), and fix is going to happen eventually.
**Development server doesn't find my BYOND cache!**
-This happens if your Documents folder in Windows has a custom location, for
-example in `E:\Libraries\Documents`. Development server tries its best to find
-this non-standard location (searches for a Windows Registry key), but it can
-fail. You have to run the dev server with an additional environmental
-variable, with a full path to BYOND cache.
+This happens if your Documents folder in Windows has a custom location, for example in `E:\Libraries\Documents`. Development server tries its best to find this non-standard location (searches for a Windows Registry key), but it can fail. You have to run the dev server with an additional environmental variable, with a full path to BYOND cache.
```
BYOND_CACHE="E:/Libraries/Documents/BYOND/cache"
@@ -131,63 +105,36 @@ BYOND_CACHE="E:/Libraries/Documents/BYOND/cache"
> Example: `No template for dependency: PureExpressionDependency`
-Webpack stores its cache on disk since tgui 4.3, and it is very sensitive
-to build configuration. So if you update webpack, or share the same cache
-directory between development and production build, it will start
-hallucinating.
+Webpack stores its cache on disk since tgui 4.3, and it is very sensitive to build configuration. So if you update webpack, or share the same cache directory between development and production build, it will start hallucinating.
To fix this kind of problem, run `bin/tgui --clean` and try again.
## Developer Tools
-When developing with `tgui-dev-server`, you will have access to certain
-development only features.
+When developing with `tgui-dev-server`, you will have access to certain development only features.
-**Debug Logs.**
-When running server via `bin/tgui --dev --debug`, server will print debug
-logs and time spent on rendering. Use this information to optimize your
-code, and try to keep re-renders below 16ms.
+**Debug Logs**. When running server via `bin/tgui --dev --debug`, server will print debug logs and time spent on rendering. Use this information to optimize your code, and try to keep re-renders below 16ms.
-**Kitchen Sink.**
-Press `F12` to open the KitchenSink interface. This interface is a
-playground to test various tgui components.
+**Kitchen Sink**. Press `F12` to open the KitchenSink interface. This interface is a playground to test various tgui components.
-**Layout Debugger.**
-Press `F11` to toggle the *layout debugger*. It will show outlines of
-all tgui elements, which makes it easy to understand how everything comes
-together, and can reveal certain layout bugs which are not normally visible.
+**Layout Debugger**. Press `F11` to toggle the *layout debugger*. It will show outlines of all tgui elements, which makes it easy to understand how everything comes together, and can reveal certain layout bugs which are not normally visible.
## Project Structure
- `/packages` - Each folder here represents a self-contained Node module.
-- `/packages/common` - Helper functions
+- `/packages/common` - Helper functions that are used throughout all packages.
- `/packages/tgui/index.js` - Application entry point.
- `/packages/tgui/components` - Basic UI building blocks.
- `/packages/tgui/interfaces` - Actual in-game interfaces.
-Interface takes data via the `state` prop and outputs an html-like stucture,
-which you can build using existing UI components.
-- `/packages/tgui/layouts` - Root level UI components, that affect the final
-look and feel of the browser window. They usually hold various window
-elements, like the titlebar and resize handlers, and control the UI theme.
-- `/packages/tgui/routes.js` - This is where tgui decides which interface to
-pull and render.
-- `/packages/tgui/layout.js` - A root-level component, holding the
-window elements, like the titlebar, buttons, resize handlers. Calls
-`routes.js` to decide which component to render.
+- `/packages/tgui/layouts` - Root level UI components, that affect the final look and feel of the browser window. These hold various window elements, like the titlebar and resize handlers, and control the UI theme.
+- `/packages/tgui/routes.js` - This is where tgui decides which interface to pull and render.
- `/packages/tgui/styles/main.scss` - CSS entry point.
-- `/packages/tgui/styles/functions.scss` - Useful SASS functions.
-Stuff like `lighten`, `darken`, `luminance` are defined here.
-- `/packages/tgui/styles/atomic` - Atomic CSS classes.
-These are very simple, tiny, reusable CSS classes which you can use and
-combine to change appearance of your elements. Keep them small.
-- `/packages/tgui/styles/components` - CSS classes which are used
-in UI components. These stylesheets closely follow the
-[BEM](https://en.bem.info/methodology/) methodology.
-- `/packages/tgui/styles/interfaces` - Custom stylesheets for your interfaces.
-Add stylesheets here if you really need a fine control over your UI styles.
+- `/packages/tgui/styles/functions.scss` - Useful SASS functions. Stuff like `lighten`, `darken`, `luminance` are defined here.
+- `/packages/tgui/styles/atomic` - Atomic CSS classes. These are very simple, tiny, reusable CSS classes which you can use and combine to change appearance of your elements. Keep them small.
+- `/packages/tgui/styles/components` - CSS classes which are used in UI components. These stylesheets closely follow the [BEM](https://en.bem.info/methodology/) methodology.
+- `/packages/tgui/styles/interfaces` - Custom stylesheets for your interfaces. Add stylesheets here if you really need a fine control over your UI styles.
- `/packages/tgui/styles/layouts` - Layout-related styles.
-- `/packages/tgui/styles/themes` - Contains all the various themes you can
-use in tgui. Each theme must be registered in `webpack.config.js` file.
+- `/packages/tgui/styles/themes` - Contains themes that you can use in tgui. Each theme must be registered in `/packages/tgui/index.js` file.
## Component Reference
@@ -195,11 +142,8 @@ See: [Component Reference](docs/component-reference.md).
## License
-Source code is covered by /tg/station's parent license - **AGPL-3.0**
-(see the main [README](../README.md)), unless otherwise indicated.
+Source code is covered by /tg/station's parent license - **AGPL-3.0** (see the main [README](../README.md)), unless otherwise indicated.
-Some files are annotated with a copyright header, which explicitly states
-the copyright holder and license of the file. Most of the core tgui
-source code is available under the **MIT** license.
+Some files are annotated with a copyright header, which explicitly states the copyright holder and license of the file. Most of the core tgui source code is available under the **MIT** license.
The Authors retain all copyright to their respective work here submitted.
diff --git a/tgui/bin/tgui b/tgui/bin/tgui
deleted file mode 100755
index b827c9129162..000000000000
--- a/tgui/bin/tgui
+++ /dev/null
@@ -1,207 +0,0 @@
-#!/usr/bin/env bash
-## Copyright (c) 2020 Aleksej Komarov
-## SPDX-License-Identifier: MIT
-
-set -e
-shopt -s globstar
-shopt -s expand_aliases
-
-## Initial set-up
-## --------------------------------------------------------
-
-## Returns an absolute path to file
-alias tgui-realpath="readlink -f"
-
-## Fallbacks for GNU readlink
-## Detecting GNU coreutils http://stackoverflow.com/a/8748344/319952
-if ! readlink --version >/dev/null 2>&1; then
- if hash greadlink 2>/dev/null; then
- alias tgui-realpath="greadlink -f"
- else
- alias tgui-realpath="perl -MCwd -le 'print Cwd::abs_path(shift)'"
- fi
-fi
-
-## Find a canonical path to project root
-base_dir="$(dirname "$(tgui-realpath "${0}")")/.."
-base_dir="$(tgui-realpath "${base_dir}")"
-
-## Make use of nvm if it exists
-if [[ -e "${HOME}/.nvm/nvm.sh" ]]; then
- source "${HOME}/.nvm/nvm.sh"
-fi
-
-## Fall back to running Yarn from the repo
-if ! hash yarn 2>/dev/null; then
- yarn_releases=("${base_dir}"/.yarn/releases/yarn-*.cjs)
- yarn_release="${yarn_releases[0]}"
- yarn() {
- node "${yarn_release}" "${@}"
- }
-fi
-
-
-## Functions
-## --------------------------------------------------------
-
-## Installs node modules
-task-install() {
- cd "${base_dir}"
- yarn install
-}
-
-## Runs webpack
-task-webpack() {
- cd "${base_dir}"
- yarn run webpack-cli "${@}"
-}
-
-## Runs a development server
-task-dev-server() {
- cd "${base_dir}"
- yarn node --experimental-modules packages/tgui-dev-server/index.js "${@}"
-}
-
-## Run a linter through all packages
-task-lint() {
- cd "${base_dir}"
- yarn run tsc
- echo "tgui: type check passed"
- yarn run eslint packages --ext .js,.cjs,.ts,.tsx "${@}"
- echo "tgui: eslint check passed"
-}
-
-task-test() {
- cd "${base_dir}"
- yarn run jest
-}
-
-## Mr. Proper
-task-clean() {
- cd "${base_dir}"
- ## Build artifacts
- rm -rf public/.tmp
- rm -f public/*.map
- rm -f public/*.chunk.*
- rm -f public/*.bundle.*
- rm -f public/*.hot-update.*
- ## Yarn artifacts
- rm -rf .yarn/cache
- rm -rf .yarn/unplugged
- rm -rf .yarn/webpack
- rm -f .yarn/build-state.yml
- rm -f .yarn/install-state.gz
- rm -f .yarn/install-target
- rm -f .pnp.*
- ## NPM artifacts
- rm -rf **/node_modules
- rm -f **/package-lock.json
-}
-
-## Installs merge drivers and git hooks
-task-install-git-hooks() {
- cd "${base_dir}"
- local git_root
- local git_base_dir
- git_root="$(git rev-parse --show-toplevel)"
- git_base_dir="${base_dir/${git_root}/.}"
- git config --replace-all merge.tgui-merge-bundle.driver \
- "${git_base_dir}/bin/tgui --merge=bundle %O %A %B %L"
- echo "tgui: Merge drivers have been successfully installed!"
-}
-
-## Bundle merge driver
-task-merge-bundle() {
- local file_ancestor="${1}"
- local file_current="${2}"
- local file_other="${3}"
- local conflict_marker_size="${4}"
- echo "tgui: Discarding a local tgui build"
- ## Do nothing (file_current will be merged and is what we want to keep).
- exit 0
-}
-
-
-## Main
-## --------------------------------------------------------
-
-if [[ ${1} == "--merge"* ]]; then
- if [[ ${1} == "--merge=bundle" ]]; then
- shift 1
- task-merge-bundle "${@}"
- fi
- echo "Unknown merge strategy: ${1}"
- exit 1
-fi
-
-if [[ ${1} == "--install-git-hooks" ]]; then
- shift 1
- task-install-git-hooks
- exit 0
-fi
-
-if [[ ${1} == "--clean" ]]; then
- task-clean
- exit 0
-fi
-
-if [[ ${1} == "--dev" ]]; then
- shift
- task-install
- task-dev-server "${@}"
- exit 0
-fi
-
-if [[ ${1} == '--lint' ]]; then
- shift 1
- task-install
- task-lint "${@}"
- exit 0
-fi
-
-if [[ ${1} == '--lint-harder' ]]; then
- shift 1
- task-install
- task-lint -c .eslintrc-harder.yml "${@}"
- exit 0
-fi
-
-if [[ ${1} == '--fix' ]]; then
- shift 1
- task-install
- task-lint --fix "${@}"
- exit 0
-fi
-
-if [[ ${1} == '--test' ]]; then
- shift 1
- task-install
- task-test "${@}"
- exit 0
-fi
-
-## Analyze the bundle
-if [[ ${1} == '--analyze' ]]; then
- task-install
- task-webpack --mode=production --analyze
- exit 0
-fi
-
-## Make a production webpack build
-if [[ ${1} == '--build' ]]; then
- task-install
- task-webpack --mode=production
- exit 0
-fi
-
-## Make a production webpack build + Run eslint
-if [[ -z ${1} ]]; then
- task-install
- task-lint --fix
- task-webpack --mode=production
- exit 0
-fi
-
-## Run webpack with custom flags
-task-install
-task-webpack "${@}"
diff --git a/tgui/bin/tgui-dev-server.bat b/tgui/bin/tgui-dev-server.bat
deleted file mode 100644
index 21b2ea4e962b..000000000000
--- a/tgui/bin/tgui-dev-server.bat
+++ /dev/null
@@ -1,9 +0,0 @@
-@echo off
-rem Copyright (c) 2020 Aleksej Komarov
-rem SPDX-License-Identifier: MIT
-call powershell.exe -NoLogo -ExecutionPolicy Bypass -File "%~dp0\tgui_.ps1" --dev %*
-rem Pause if launched in a separate shell unless initiated from powershell
-echo %PSModulePath% | findstr %USERPROFILE% >NUL
-if %errorlevel% equ 0 exit 0
-echo %cmdcmdline% | find /i "/c"
-if %errorlevel% equ 0 pause
diff --git a/tgui/bin/tgui.bat b/tgui/bin/tgui.bat
deleted file mode 100644
index 39aa279dcaa2..000000000000
--- a/tgui/bin/tgui.bat
+++ /dev/null
@@ -1,9 +0,0 @@
-@echo off
-rem Copyright (c) 2020 Aleksej Komarov
-rem SPDX-License-Identifier: MIT
-call powershell.exe -NoLogo -ExecutionPolicy Bypass -File "%~dp0\tgui_.ps1" %*
-rem Pause if launched in a separate shell unless initiated from powershell
-echo %PSModulePath% | findstr %USERPROFILE% >NUL
-if %errorlevel% equ 0 exit 0
-echo %cmdcmdline% | find /i "/c"
-if %errorlevel% equ 0 pause
diff --git a/tgui/bin/tgui_.ps1 b/tgui/bin/tgui_.ps1
deleted file mode 100644
index 82b8c3517cc2..000000000000
--- a/tgui/bin/tgui_.ps1
+++ /dev/null
@@ -1,147 +0,0 @@
-## Copyright (c) 2020 Aleksej Komarov
-## SPDX-License-Identifier: MIT
-
-## Initial set-up
-## --------------------------------------------------------
-
-## Enable strict mode and stop of first cmdlet error
-Set-StrictMode -Version Latest
-$ErrorActionPreference = "Stop"
-$PSDefaultParameterValues['*:ErrorAction'] = 'Stop'
-
-## Validates exit code of external commands
-function Throw-On-Native-Failure {
- if (-not $?) {
- exit 1
- }
-}
-
-## Normalize current directory
-$basedir = Split-Path $MyInvocation.MyCommand.Path
-$basedir = Resolve-Path "$($basedir)\.."
-Set-Location $basedir
-[Environment]::CurrentDirectory = $basedir
-
-
-## Functions
-## --------------------------------------------------------
-
-function yarn {
- $YarnRelease = Get-ChildItem -Filter ".yarn\releases\yarn-*.cjs" | Select-Object -First 1
- node ".yarn\releases\$YarnRelease" @Args
- Throw-On-Native-Failure
-}
-
-function Remove-Quiet {
- Remove-Item -ErrorAction SilentlyContinue @Args
-}
-
-function task-install {
- yarn install
-}
-
-## Runs webpack
-function task-webpack {
- yarn run webpack-cli @Args
-}
-
-## Runs a development server
-function task-dev-server {
- yarn node --experimental-modules "packages/tgui-dev-server/index.js" @Args
-}
-
-## Run a linter through all packages
-function task-lint {
- yarn run tsc
- Write-Output "tgui: type check passed"
- yarn run eslint packages --ext ".js,.cjs,.ts,.tsx" @Args
- Write-Output "tgui: eslint check passed"
-}
-
-function task-test {
- yarn run jest
-}
-
-## Mr. Proper
-function task-clean {
- ## Build artifacts
- Remove-Quiet -Recurse -Force "public\.tmp"
- Remove-Quiet -Force "public\*.map"
- Remove-Quiet -Force "public\*.hot-update.*"
- ## Yarn artifacts
- Remove-Quiet -Recurse -Force ".yarn\cache"
- Remove-Quiet -Recurse -Force ".yarn\unplugged"
- Remove-Quiet -Recurse -Force ".yarn\webpack"
- Remove-Quiet -Force ".yarn\build-state.yml"
- Remove-Quiet -Force ".yarn\install-state.gz"
- Remove-Quiet -Force ".yarn\install-target"
- Remove-Quiet -Force ".pnp.*"
- ## NPM artifacts
- Get-ChildItem -Path "." -Include "node_modules" -Recurse -File:$false | Remove-Item -Recurse -Force
- Remove-Quiet -Force "package-lock.json"
-}
-
-
-## Main
-## --------------------------------------------------------
-
-if ($Args.Length -gt 0) {
- if ($Args[0] -eq "--clean") {
- task-clean
- exit 0
- }
-
- if ($Args[0] -eq "--dev") {
- $Rest = $Args | Select-Object -Skip 1
- task-install
- task-dev-server @Rest
- exit 0
- }
-
- if ($Args[0] -eq "--lint") {
- $Rest = $Args | Select-Object -Skip 1
- task-install
- task-lint @Rest
- exit 0
- }
-
- if ($Args[0] -eq "--lint-harder") {
- $Rest = $Args | Select-Object -Skip 1
- task-install
- task-lint -c ".eslintrc-harder.yml" @Rest
- exit 0
- }
-
- if ($Args[0] -eq "--fix") {
- $Rest = $Args | Select-Object -Skip 1
- task-install
- task-lint --fix @Rest
- exit 0
- }
-
- if ($Args[0] -eq "--test") {
- $Rest = $Args | Select-Object -Skip 1
- task-install
- task-test @Rest
- exit 0
- }
-
- ## Analyze the bundle
- if ($Args[0] -eq "--analyze") {
- task-install
- task-webpack --mode=production --analyze
- exit 0
- }
-}
-
-## Make a production webpack build
-if ($Args.Length -eq 0) {
- task-install
- task-lint
- task-webpack --mode=production
- exit 0
-}
-
-## Run webpack with custom flags
-task-install
-task-webpack @Args
diff --git a/tgui/package.json b/tgui/package.json
index c6d47687c4bf..2aa15cb2a98e 100644
--- a/tgui/package.json
+++ b/tgui/package.json
@@ -5,6 +5,17 @@
"workspaces": [
"packages/*"
],
+ "scripts": {
+ "tgui:build": "webpack",
+ "tgui:analyze": "webpack --analyze",
+ "tgui:dev": "node --experimental-modules packages/tgui-dev-server/index.js",
+ "tgui:lint": "eslint packages --ext .js,.cjs,.ts,.tsx",
+ "tgui:sonar": "eslint packages --ext .js,.cjs,.ts,.tsx -c .eslintrc-sonar.yml",
+ "tgui:tsc": "tsc",
+ "tgui:test": "jest --watch",
+ "tgui:test-simple": "CI=true jest --color",
+ "tgui:test-ci": "CI=true jest --color --collect-coverage"
+ },
"dependencies": {
"@babel/core": "^7.15.0",
"@babel/eslint-parser": "^7.15.0",
diff --git a/tgui/packages/tgfont/package.json b/tgui/packages/tgfont/package.json
index 920ea8681d80..9459aa129696 100644
--- a/tgui/packages/tgfont/package.json
+++ b/tgui/packages/tgfont/package.json
@@ -2,10 +2,10 @@
"private": true,
"name": "tgfont",
"version": "1.0.0",
+ "scripts": {
+ "tgfont:build": "node mkdist.cjs && fantasticon --config config.cjs"
+ },
"dependencies": {
"fantasticon": "^1.2.2"
- },
- "scripts": {
- "build": "node mkdist.cjs && fantasticon --config config.cjs"
}
}
diff --git a/tgui/webpack.config.js b/tgui/webpack.config.js
index 44926dc0f4da..8698fa13440d 100644
--- a/tgui/webpack.config.js
+++ b/tgui/webpack.config.js
@@ -25,9 +25,9 @@ const createStats = verbose => ({
});
module.exports = (env = {}, argv) => {
- const mode = argv.mode === 'production' ? 'production' : 'development';
+ const mode = argv.mode || 'production';
const config = {
- mode,
+ mode: mode === 'production' ? 'production' : 'development',
context: path.resolve(__dirname),
target: ['web', 'es3', 'browserslist:ie 8'],
entry: {
@@ -113,7 +113,7 @@ module.exports = (env = {}, argv) => {
stats: createStats(true),
plugins: [
new webpack.EnvironmentPlugin({
- NODE_ENV: env.NODE_ENV || argv.mode || 'development',
+ NODE_ENV: env.NODE_ENV || mode,
WEBPACK_HMR_ENABLED: env.WEBPACK_HMR_ENABLED || argv.hot || false,
DEV_SERVER_IP: env.DEV_SERVER_IP || null,
}),
@@ -134,7 +134,7 @@ module.exports = (env = {}, argv) => {
}
// Production build specific options
- if (argv.mode === 'production') {
+ if (mode === 'production') {
const TerserPlugin = require('terser-webpack-plugin');
config.optimization.minimizer = [
new TerserPlugin({
@@ -151,7 +151,7 @@ module.exports = (env = {}, argv) => {
}
// Development build specific options
- if (argv.mode !== 'production') {
+ if (mode !== 'production') {
config.devtool = 'cheap-module-source-map';
}
diff --git a/tools/bootstrap/node.bat b/tools/bootstrap/node.bat
index ba3e52cb084f..fc1441b156cc 100644
--- a/tools/bootstrap/node.bat
+++ b/tools/bootstrap/node.bat
@@ -19,7 +19,7 @@ if %errorlevel% == 0 (
call node.exe %*
goto exit_with_last_error_level
)
-echo "build.bat: Failed to bootstrap Node!"
+echo "node.bat: Failed to bootstrap Node!"
%COMSPEC% /c exit 1
:exit_with_last_error_level
diff --git a/tools/build/.editorconfig b/tools/build/.editorconfig
index 33092d4928a4..d1d8a4176a41 100644
--- a/tools/build/.editorconfig
+++ b/tools/build/.editorconfig
@@ -8,6 +8,3 @@ end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
-
-[*.md]
-max_line_length = 80
diff --git a/tools/build/README.md b/tools/build/README.md
index 51121dbde658..c3dd2f29fb2c 100644
--- a/tools/build/README.md
+++ b/tools/build/README.md
@@ -23,12 +23,12 @@ tools/build/build --help
## Dependencies
-- On Windows, `BUILD.bat` will automatically install a private (vendored) copy of Node.
+- On Windows, `build.bat` will automatically install a private (vendored) copy of Node.
- On Linux, install Node using your package manager or from .
-- On Linux , unless using tgs4 or later you will need to compile rust-g on the server and obtain a .so file, for instructions see https://github.com/tgstation/rust-g
+- On Linux, unless using tgs4 or later you will need to compile rust-g on the server and obtain a .so file, for instructions see https://github.com/tgstation/rust-g
## Why?
We used to include compiled versions of the tgui JavaScript code in the Git repository so that the project could be compiled using BYOND only. These pre-compiled files tended to have merge conflicts for no good reason. Using a build script lets us avoid this problem, while keeping builds convenient for people who are not modifying tgui.
-This build script is based on [Juke Build](https://github.com/stylemistake/juke-build) - please follow the link and read the documentation for the project to understand how it works and how to contribute to this build script.
+This build script is based on [Juke Build](https://github.com/stylemistake/juke-build) - follow the link to read the documentation for the project and understand how it works and how to contribute.
diff --git a/tools/build/build.js b/tools/build/build.js
index f8d3a9a7dd7e..92c8c372d681 100755
--- a/tools/build/build.js
+++ b/tools/build/build.js
@@ -4,19 +4,23 @@
*
* This script uses Juke Build, read the docs here:
* https://github.com/stylemistake/juke-build
- *
- * @file
- * @copyright 2021 Aleksej Komarov
- * @license MIT
*/
import fs from 'fs';
+import Juke from './juke/index.js';
import { DreamDaemon, DreamMaker } from './lib/byond.js';
import { yarn } from './lib/yarn.js';
-import Juke from './juke/index.js';
Juke.chdir('../..', import.meta.url);
-Juke.setup({ file: import.meta.url }).then((code) => process.exit(code));
+Juke.setup({ file: import.meta.url }).then((code) => {
+ // We're using the currently available quirk in Juke Build, which
+ // prevents it from exiting on Windows, to wait on errors.
+ if (code !== 0 && process.argv.includes('--wait-on-error')) {
+ Juke.logger.error('Please inspect the error and close the window.');
+ return;
+ }
+ process.exit(code);
+});
const DME_NAME = 'tgstation';
@@ -30,9 +34,7 @@ export const PortParameter = new Juke.Parameter({
alias: 'p',
});
-export const CiParameter = new Juke.Parameter({
- type: 'boolean',
-});
+export const CiParameter = new Juke.Parameter({ type: 'boolean' });
export const DmMapsIncludeTarget = new Juke.Target({
executes: async () => {
@@ -51,6 +53,7 @@ export const DmMapsIncludeTarget = new Juke.Target({
});
export const DmTarget = new Juke.Target({
+ parameters: [DefineParameter],
dependsOn: ({ get }) => [
get(DefineParameter).includes('ALL_MAPS') && DmMapsIncludeTarget,
],
@@ -67,30 +70,22 @@ export const DmTarget = new Juke.Target({
`${DME_NAME}.dmb`,
`${DME_NAME}.rsc`,
],
- parameters: [DefineParameter],
executes: async ({ get }) => {
- const defines = get(DefineParameter);
- if (defines.length > 0) {
- Juke.logger.info('Using defines:', defines.join(', '));
- }
await DreamMaker(`${DME_NAME}.dme`, {
- defines: ['CBT', ...defines],
+ defines: ['CBT', ...get(DefineParameter)],
});
},
});
export const DmTestTarget = new Juke.Target({
+ parameters: [DefineParameter],
dependsOn: ({ get }) => [
get(DefineParameter).includes('ALL_MAPS') && DmMapsIncludeTarget,
],
executes: async ({ get }) => {
- const defines = get(DefineParameter);
- if (defines.length > 0) {
- Juke.logger.info('Using defines:', defines.join(', '));
- }
fs.copyFileSync(`${DME_NAME}.dme`, `${DME_NAME}.test.dme`);
await DreamMaker(`${DME_NAME}.test.dme`, {
- defines: ['CBT', 'CIBUILDING', ...defines],
+ defines: ['CBT', 'CIBUILDING', ...get(DefineParameter)],
});
Juke.rm('data/logs/ci', { recursive: true });
await DreamDaemon(
@@ -111,6 +106,7 @@ export const DmTestTarget = new Juke.Target({
});
export const YarnTarget = new Juke.Target({
+ parameters: [CiParameter],
inputs: [
'tgui/.yarn/+(cache|releases|plugins|sdks)/**/*',
'tgui/**/package.json',
@@ -119,9 +115,7 @@ export const YarnTarget = new Juke.Target({
outputs: [
'tgui/.yarn/install-target',
],
- executes: async () => {
- await yarn('install');
- },
+ executes: ({ get }) => yarn('install', get(CiParameter) && '--immutable'),
});
export const TgFontTarget = new Juke.Target({
@@ -136,9 +130,7 @@ export const TgFontTarget = new Juke.Target({
'tgui/packages/tgfont/dist/tgfont.eot',
'tgui/packages/tgfont/dist/tgfont.woff2',
],
- executes: async () => {
- await yarn('workspace', 'tgfont', 'build');
- },
+ executes: () => yarn('tgfont:build'),
});
export const TguiTarget = new Juke.Target({
@@ -155,52 +147,43 @@ export const TguiTarget = new Juke.Target({
'tgui/public/tgui-panel.bundle.css',
'tgui/public/tgui-panel.bundle.js',
],
- executes: async () => {
- await yarn('webpack-cli', '--mode=production');
- },
+ executes: () => yarn('tgui:build'),
});
export const TguiEslintTarget = new Juke.Target({
+ parameters: [CiParameter],
dependsOn: [YarnTarget],
- executes: async ({ args }) => {
- await yarn(
- 'eslint', 'packages',
- '--fix', '--ext', '.js,.cjs,.ts,.tsx',
- ...args
- );
- },
+ executes: ({ get }) => yarn('tgui:lint', !get(CiParameter) && '--fix'),
+});
+
+export const TguiSonarTarget = new Juke.Target({
+ dependsOn: [YarnTarget],
+ executes: () => yarn('tgui:sonar'),
});
export const TguiTscTarget = new Juke.Target({
dependsOn: [YarnTarget],
- executes: async () => {
- await yarn('tsc');
- },
+ executes: () => yarn('tgui:tsc'),
});
export const TguiTestTarget = new Juke.Target({
+ parameters: [CiParameter],
dependsOn: [YarnTarget],
- executes: async ({ args }) => {
- await yarn('jest', ...args);
- },
+ executes: ({ get }) => yarn(`tgui:test-${get(CiParameter) ? 'ci' : 'simple'}`),
});
export const TguiLintTarget = new Juke.Target({
- dependsOn: [YarnTarget, TguiEslintTarget, TguiTscTarget, TguiTestTarget],
+ dependsOn: [YarnTarget, TguiEslintTarget, TguiTscTarget],
});
export const TguiDevTarget = new Juke.Target({
dependsOn: [YarnTarget],
- executes: async ({ args }) => {
- await yarn('node', 'packages/tgui-dev-server/index.js', ...args);
- },
+ executes: ({ args }) => yarn('tgui:dev', ...args),
});
export const TguiAnalyzeTarget = new Juke.Target({
dependsOn: [YarnTarget],
- executes: async () => {
- await yarn('webpack-cli', '--mode=production', '--analyze');
- },
+ executes: () => yarn('tgui:analyze'),
});
export const TestTarget = new Juke.Target({
@@ -227,26 +210,13 @@ export const AllTarget = new Juke.Target({
dependsOn: [TestTarget, LintTarget, BuildTarget],
});
-/**
- * Removes the immediate build junk to produce clean builds.
- */
-export const CleanTarget = new Juke.Target({
+export const TguiCleanTarget = new Juke.Target({
executes: async () => {
- Juke.rm('*.dmb');
- Juke.rm('*.rsc');
- Juke.rm('*.mdme');
- Juke.rm('*.mdme*');
- Juke.rm('*.m.*');
- Juke.rm('_maps/templates.dm');
Juke.rm('tgui/public/.tmp', { recursive: true });
Juke.rm('tgui/public/*.map');
- Juke.rm('tgui/public/*.chunk.*');
- Juke.rm('tgui/public/*.bundle.*');
- Juke.rm('tgui/public/*.hot-update.*');
+ Juke.rm('tgui/public/*.{chunk,bundle,hot-update}.*');
Juke.rm('tgui/packages/tgfont/dist', { recursive: true });
- Juke.rm('tgui/.yarn/cache', { recursive: true });
- Juke.rm('tgui/.yarn/unplugged', { recursive: true });
- Juke.rm('tgui/.yarn/webpack', { recursive: true });
+ Juke.rm('tgui/.yarn/{cache,unplugged,webpack}', { recursive: true });
Juke.rm('tgui/.yarn/build-state.yml');
Juke.rm('tgui/.yarn/install-state.gz');
Juke.rm('tgui/.yarn/install-target');
@@ -254,16 +224,24 @@ export const CleanTarget = new Juke.Target({
},
});
+export const CleanTarget = new Juke.Target({
+ dependsOn: [TguiCleanTarget],
+ executes: async () => {
+ Juke.rm('*.{dmb,rsc}');
+ Juke.rm('*.mdme*');
+ Juke.rm('*.m.*');
+ Juke.rm('_maps/templates.dm');
+ },
+});
+
/**
- * Removes more junk at expense of much slower initial builds.
+ * Removes more junk at the expense of much slower initial builds.
*/
-export const DistCleanTarget = new Juke.Target({
+export const CleanAllTarget = new Juke.Target({
dependsOn: [CleanTarget],
executes: async () => {
Juke.logger.info('Cleaning up data/logs');
Juke.rm('data/logs', { recursive: true });
- Juke.logger.info('Cleaning up bootstrap cache');
- Juke.rm('tools/bootstrap/.cache', { recursive: true });
Juke.logger.info('Cleaning up global yarn cache');
await yarn('cache', 'clean', '--all');
},
diff --git a/tools/build/juke/index.d.ts b/tools/build/juke/index.d.ts
index cdc30ea57754..3f8ef8ac503d 100644
--- a/tools/build/juke/index.d.ts
+++ b/tools/build/juke/index.d.ts
@@ -3,7 +3,7 @@
///
import _chalk from 'chalk';
-import { SpawnOptionsWithoutStdio } from 'child_process';
+import { SpawnOptions } from 'child_process';
import EventEmitter from 'events';
/**
@@ -166,7 +166,7 @@ export declare class ExitCode extends Error {
signal: string | null;
constructor(code: number | null, signal?: string | null);
}
-export declare type ExecOptions = SpawnOptionsWithoutStdio & {
+export declare type ExecOptions = SpawnOptions & {
/**
* If `true`, this exec call will not pipe its output to stdio.
* @default false
@@ -177,6 +177,11 @@ export declare type ExecOptions = SpawnOptionsWithoutStdio & {
* @default true
*/
throw?: boolean;
+ /**
+ * Captures stdout/stderr to be available in exec return value.
+ * This is experimental functionality.
+ */
+ captureOutput?: boolean;
};
export declare type ExecReturn = {
/** Exit code of the program. */
diff --git a/tools/build/juke/index.js b/tools/build/juke/index.js
index 4ee8fbf0bfd9..b54b76e587f6 100644
--- a/tools/build/juke/index.js
+++ b/tools/build/juke/index.js
@@ -4302,7 +4302,7 @@ var require_glob = __commonJS({
}
});
-// pnp:/Users/style/Documents/Projects/juke-build/src/index.ts
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/src/index.ts
__export(exports, {
ExitCode: () => ExitCode,
Parameter: () => Parameter,
@@ -4322,10 +4322,10 @@ __export(exports, {
var import_chalk4 = __toModule(require_source());
var import_module = __toModule(require("module"));
-// pnp:/Users/style/Documents/Projects/juke-build/package.json
-var version = "0.8.1";
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/package.json
+var version = "0.9.0";
-// pnp:/Users/style/Documents/Projects/juke-build/src/chdir.ts
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/src/chdir.ts
var import_fs = __toModule(require("fs"));
var import_path = __toModule(require("path"));
var import_url = __toModule(require("url"));
@@ -4347,7 +4347,7 @@ var chdir = (directory, relativeTo) => {
process.chdir(directory);
};
-// pnp:/Users/style/Documents/Projects/juke-build/src/exec.ts
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/src/exec.ts
var import_chalk = __toModule(require_source());
var import_child_process = __toModule(require("child_process"));
var import_fs2 = __toModule(require("fs"));
@@ -4404,25 +4404,31 @@ var exec = (executable, args = [], options = {}) => {
if (process.env.JUKE_DEBUG) {
console.log(import_chalk.default.grey("$", executable, ...args));
}
- const child = (0, import_child_process.spawn)(executable, args, spawnOptions);
+ const child = (0, import_child_process.spawn)(executable, args, __spreadValues({
+ stdio: "inherit"
+ }, spawnOptions));
children.add(child);
let stdout = "";
let stderr = "";
let combined = "";
- child.stdout.on("data", (data) => {
- if (!silent) {
- process.stdout.write(data);
- }
- stdout += data;
- combined += data;
- });
- child.stderr.on("data", (data) => {
- if (!silent) {
- process.stderr.write(data);
- }
- stderr += data;
- combined += data;
- });
+ if (child.stdout) {
+ child.stdout.on("data", (data) => {
+ if (!silent) {
+ process.stdout.write(data);
+ }
+ stdout += data;
+ combined += data;
+ });
+ }
+ if (child.stderr) {
+ child.stderr.on("data", (data) => {
+ if (!silent) {
+ process.stderr.write(data);
+ }
+ stderr += data;
+ combined += data;
+ });
+ }
child.on("error", (err) => reject(err));
child.on("exit", (code, signal) => {
children.delete(child);
@@ -4444,7 +4450,7 @@ var exec = (executable, args = [], options = {}) => {
});
};
-// pnp:/Users/style/Documents/Projects/juke-build/src/logger.ts
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/src/logger.ts
var import_chalk2 = __toModule(require_source());
var logger = {
log: (...args) => {
@@ -4469,13 +4475,13 @@ var logger = {
}
};
-// pnp:/Users/style/Documents/Projects/juke-build/src/string.ts
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/src/string.ts
var import_stringcase = __toModule(require_lib());
var toKebabCase = (str) => (0, import_stringcase.spinalcase)(str);
var toCamelCase = (str) => (0, import_stringcase.camelcase)(str);
var toConstCase = (str) => (0, import_stringcase.constcase)(str);
-// pnp:/Users/style/Documents/Projects/juke-build/src/parameter.ts
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/src/parameter.ts
var Parameter = class {
constructor(config) {
this.type = config.type;
@@ -4512,11 +4518,11 @@ var Parameter = class {
};
var createParameter = (config) => new Parameter(config);
-// pnp:/Users/style/Documents/Projects/juke-build/src/runner.ts
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/src/runner.ts
var import_chalk3 = __toModule(require_source());
var import_events = __toModule(require("events"));
-// pnp:/Users/style/Documents/Projects/juke-build/src/argparse.ts
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/src/argparse.ts
var stringToBoolean = (str) => str !== void 0 && str !== null && str !== "false" && str !== "0" && str !== "null";
var prepareArgs = (args, singleTarget = false) => {
let inGlobalContext = true;
@@ -4674,7 +4680,7 @@ var parseArgs = (args, parameters) => {
return parameterMap;
};
-// pnp:/Users/style/Documents/Projects/juke-build/src/fs.ts
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/src/fs.ts
var import_fs3 = __toModule(require("fs"));
var import_glob = __toModule(require_glob());
var File = class {
@@ -4782,7 +4788,7 @@ var rm = (path2, options = {}) => {
}
};
-// pnp:/Users/style/Documents/Projects/juke-build/src/runner.ts
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/src/runner.ts
var runner = new class Runner {
constructor() {
this.config = {};
@@ -5024,7 +5030,7 @@ var Worker = class {
}
};
-// pnp:/Users/style/Documents/Projects/juke-build/src/target.ts
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/src/target.ts
var Target = class {
constructor(target) {
this.name = target.name;
@@ -5038,7 +5044,7 @@ var Target = class {
};
var createTarget = (config) => new Target(config);
-// pnp:/Users/style/Documents/Projects/juke-build/src/index.ts
+// pnp:/home/style/Documents/Projects/stylemistake/juke-build/src/index.ts
var chalk4 = import_chalk4.default;
var lastExitCode = null;
var setup = async (config) => {
diff --git a/tools/build/lib/byond.js b/tools/build/lib/byond.js
index 952b60c4e95d..eb69e7001ad6 100644
--- a/tools/build/lib/byond.js
+++ b/tools/build/lib/byond.js
@@ -88,18 +88,21 @@ export const DreamMaker = async (dmeFile, options = {}) => {
// Compile
const { defines } = options;
if (defines && defines.length > 0) {
- const injectedContent = defines
- .map(x => `#define ${x}\n`)
- .join('');
- fs.writeFileSync(`${dmeBaseName}.m.dme`, injectedContent);
- const dmeContent = fs.readFileSync(`${dmeBaseName}.dme`);
- fs.appendFileSync(`${dmeBaseName}.m.dme`, dmeContent);
- await Juke.exec(dmPath, [`${dmeBaseName}.m.dme`]);
- fs.writeFileSync(`${dmeBaseName}.dmb`, fs.readFileSync(`${dmeBaseName}.m.dmb`));
- fs.writeFileSync(`${dmeBaseName}.rsc`, fs.readFileSync(`${dmeBaseName}.m.rsc`));
- fs.unlinkSync(`${dmeBaseName}.m.dmb`);
- fs.unlinkSync(`${dmeBaseName}.m.rsc`);
- fs.unlinkSync(`${dmeBaseName}.m.dme`);
+ Juke.logger.info('Using defines:', defines.join(', '));
+ try {
+ const injectedContent = defines
+ .map(x => `#define ${x}\n`)
+ .join('');
+ fs.writeFileSync(`${dmeBaseName}.m.dme`, injectedContent);
+ const dmeContent = fs.readFileSync(`${dmeBaseName}.dme`);
+ fs.appendFileSync(`${dmeBaseName}.m.dme`, dmeContent);
+ await Juke.exec(dmPath, [`${dmeBaseName}.m.dme`]);
+ fs.writeFileSync(`${dmeBaseName}.dmb`, fs.readFileSync(`${dmeBaseName}.m.dmb`));
+ fs.writeFileSync(`${dmeBaseName}.rsc`, fs.readFileSync(`${dmeBaseName}.m.rsc`));
+ }
+ finally {
+ Juke.rm(`${dmeBaseName}.m.*`);
+ }
}
else {
await Juke.exec(dmPath, [dmeFile]);
@@ -109,7 +112,7 @@ export const DreamMaker = async (dmeFile, options = {}) => {
export const DreamDaemon = async (dmbFile, ...args) => {
const dmPath = await getDmPath();
const baseDir = path.dirname(dmPath);
- const ddExeName = process.platform === 'win32' ? 'dd.exe' : 'DreamDaemon';
+ const ddExeName = process.platform === 'win32' ? 'dreamdaemon.exe' : 'DreamDaemon';
const ddExePath = baseDir === '.' ? ddExeName : path.join(baseDir, ddExeName);
return Juke.exec(ddExePath, [dmbFile, ...args]);
};
diff --git a/tools/build/lib/yarn.js b/tools/build/lib/yarn.js
index 8b93f4cfc98b..84b717001f8a 100644
--- a/tools/build/lib/yarn.js
+++ b/tools/build/lib/yarn.js
@@ -7,7 +7,10 @@ export const yarn = (...args) => {
yarnPath = Juke.glob('./tgui/.yarn/releases/*.cjs')[0]
.replace('/tgui/', '/');
}
- return Juke.exec('node', [yarnPath, ...args], {
+ return Juke.exec('node', [
+ yarnPath,
+ ...args.filter((arg) => typeof arg === 'string'),
+ ], {
cwd: './tgui',
});
};