Configure a TypeScript project with common dependencies to build multiple plain JavaScript output files

You could actually use project references. Follow these steps to get the same results you were getting for your original files, with all functions at the top level in one file. However, I could not find a solution to import only needed functions in bots. That is, without using imports and exports.

In your tsconfig.json at the root

{
    "files": [],
    "references": [
        { "path": "./lib" }
        { "path": "./AggroMiner" }
        { "path": "./ArtilleryMicro" }
        { "path": "./MissileKite" }
        { "path": "./SmartMelee" }
        { "path": "./ZapKite" }
    ]
}

Next, in your lib folder, add a tsconfig.json like so

{
  "compilerOptions": {
    "declaration": true,
    "declarationMap": true,
    "composite": true,
    "rootDir": ".",
    "outFile": "../build/lib.js",
    "target": "es3",
    "removeComments": true,
    "sourceMap": false,
  },
  "files": [
    "data.ts",
    "movement.ts",
    "utils.ts"
  ]
}

We need to make a few adjustments in data.ts, movement.ts and utils.ts so that ts doesn't bother us with compilation errors.

data.ts

/// <reference path="./bot.land.d.ts"/>

(...)

movement.ts


/// <reference path="./data.ts"/>
/// <reference path="./utils.ts"/>
(...)

utils.ts

/// <reference path="./bot.land.d.ts"/>
(...)

Next, we add base.json at the root (the tsconfig.json of the bots will extend it).

base.json

{
  "compilerOptions": {
    "declaration": true,
    "composite": true,
    "rootDir": ".",
    "target": "es3",
    "removeComments": true,
    "sourceMap": false,
  }
}

and the bots' tsconfig.json (adapt according to bots)

{
  "extends": "../base",
  "compilerOptions": {
    "outFile": "../build/AggroMiner.js",
  },
  "files": [
    "AggroMiner.ts"
  ],
  "references": [
      { "path": "../lib", "prepend": true } //note the prepend: true
  ]
}

That's it. Now just run

tsc -b

Here is my attempt to answer your requirements.

Notable files:

  • src/tsconfig-botland.json holds settings for any bot.land script (including your custom declarations which I moved to types/bot-land/index.d.ts). You may which to change the strict settings I used.
  • src/tsconfig.json holds references to all your bots. This is the file to edit whenever you want to add another bot script

A bot script is at least two files: a minimalist tsconfig.json and one or more .ts script files.

For example src/AggroMiner/tsconfig.json:

{
    "extends": "../tsconfig-botland",
    "compilerOptions": {
        "outFile": "../../build/AggroMiner.js"
    },
    "files": ["index.ts"],
    "include": ["**/*.ts", "../lib/**/*.ts"]
}

In most cases, to start a new bot script you should:

  1. copy any bot folder (i.e. src/AggroMiner) to a new folder under src
  2. edit the src/<newBotFolder>/tsconfig.json to edit the outFile with the name of your bot
  3. edit src/tsconfig.json and add a reference to src/<newBotFolder>

The following npm/yarn script have been set:

  • build to build all bots
  • build-clean which clear the build folder before running a build
  • format to run Prettier on all .ts files under src
  • lint to run a tslint check on all bot scripts

Now running down your requirements:

  • No new boilerplate required to add a new bot (e.g. no tsconfig.json per bot)

To achieve this would require creating some script which would enumerate your bots folder/scripts... and setup the relevant per bot tsconfig.json and run tsc. Unless it is strictly necessary, a minimal setup (describe above) might be sufficient.

  • Use import for common functions to avoid outputting unused code, but then...

First, be aware that if you start using any module export/import statements, you will need additional 3rd party to pack / treeshake in order to achieve a single file output. From what I could gather of Bot.land, your scripts are running on the server. Unless deadcode has an impact on your bot performance, I would not really bother.

  • Still output all functions as one single file in Bot Land's specific format

Done.

  • A single build step that produces multiple output files, one for each bot

Done.

  • Bonus: integrating the build process with VS Code. There is a currently correspondingly boilerplate tasks.json for building each sub-project.

The npm scripts should appear in vsc's tasks list (at least they do in mine) thus making the tasks.json unnecessary.