League-of-Foundry-Developers / foundryvtt-devMode

A module with some tools to help enable Foundry VTT package developers.
MIT License
12 stars 15 forks source link

🧙 Developer Mode

Developer Mode Latest Release Download Count Forge Installs Foundry Hub Endorsements Foundry Hub Comments Supported Foundry Versions

A swiss army knife for development tooling in Foundry VTT.

Features

Demo of the Core Config overrides.

Goal

Enable developers to stop putting debug code in their module code which accidentally gets shipped. Empower developers with commonly sought-after QOL features.

TODO

  1. Leverage the potential future CONFIG.debug.moduleDebug flag.
  2. Implement other developer tooling. Have an idea? Leave a suggestion!

Installation

Module JSON:

https://github.com/League-of-Foundry-Developers/foundryvtt-devMode/releases/latest/download/module.json

Configuration

Name Description
Override CONFIG.debug? Whether or not to use the dev-mode override settings for CONFIG.debug flags.
Suppress Window Size Warning Suppresses the window size warning on startup.
Always Unpause The game will always unpause when starting.
Show Chat Message Ids? Places a clickable chip on chat messages to copy the id or print the document to the console.
Show Sidebar Directory Ids? Places a clickable chip on sidebar directory entries to copy the id or print the document to the console.
Show Compendium Document Ids? Places a clickable chip on compendium directory entries to copy the id.
Show App Header Button? Places a Header Button on document sheets and compendium displays to print the document to the console.
Disable Template Cache? Disables the Foundry Core template cache, allowing any template changes to be picked up when getTemplate is rerun.
System JSON Changes (#21) Notify about system.json and template.json changes.
Module JSON changes (#21) Notify about module.json changes on any and all active modules.
Inspect template.json (#25) Does basic checks on template.json for potential issues on load.

API

While active, after the hook devModeReady is fired, the following api methods are expected to be on game.modules.get('_dev-mode')?.api:

registerPackageDebugFlag

async registerPackageDebugFlag(
  packageName: string,
  kind?: 'boolean' | 'level',
  options?: {
    default?: boolean | LogLevel;
    choiceLabelOverrides?: Record<number, string>;
  }
): Promise<boolean>

choiceLabelOverrides Example

registerPackageDebugFlag('my-module-id', 'level', {
  choiceLabelOverrides: {
    0: 'Foo',
    1: 'Bar',
    2: 'Bat',
    3: 'Biz',
    4: 'Bin',
    5: 'Bam',
  },
});

getPackageDebugValue

getPackageDebugValue(
  packageName: string,
  kind?: 'boolean' | 'level',
): boolean | LogLevel

How do I actually use this?

Step 1: Register your debug flag

If all you want is a simple boolean, this is as simple as doing this in your module's js:

Hooks.once('devModeReady', ({ registerPackageDebugFlag }) => {
  registerPackageDebugFlag('my-module-id');
});

Step 2: Read that value

Here's a log function I use which allows me to toggle on all of the stupid little logs I leave all over the place while I'm debugging.

const MODULE_ID = 'my-module-id';

function log(force: boolean, ...args) {
  try {
    const isDebugging = game.modules.get('_dev-mode')?.api?.getPackageDebugValue(MODULE_ID);

    if (force || isDebugging) {
      console.log(MODULE_ID, '|', ...args);
    }
  } catch (e) {}
}

// ...

log(false, someVarToLog); // won't log unless my debug value is true

Known Issues Features

Typescript Definitions

This is an example typescript definition which would be accurate for the DevMode API available on game.modules.get('_dev-mode')?.api and provided as the argument to devModeReady's callbacks.

enum LogLevel {
  NONE = 0,
  INFO = 1,
  ERROR = 2,
  DEBUG = 3,
  WARN = 4,
  ALL = 5,
}

interface DevModeApi {
  registerPackageDebugFlag(packageName: string, kind?: "boolean" | "level", options?: {
      default?: boolean | LogLevel;
      choiceLabelOverrides?: Record<string, string>; // actually keyed by LogLevel number
  }): Promise<boolean>;

  getPackageDebugValue(packageName: string, kind?: "boolean" | "level"): boolean | LogLevel;
}

Acknowledgements

Mad props to the League of Extraordinary FoundryVTT Developers community which helped me figure out a lot.

Bootstrapped with Ghost's Foundry Factory then heavily trimmed.