Docs for Release: 2.0.1
    Preparing search index...

    @shadowmoose/config

    NPM Version Static Badge

    Config Panel

    This is my personal configuration GUI, used primarily for rapid development of desktop Node/Bun apps.

    This library provides a visual configuration panel, working cross-platform via browsers, in order to expose real-time configuration options to users in a friendly way.

    Because it is web-based, the config panel also supports remote access.

    All configuration values are strongly typed, and validated before being accepted. The panel can load/save from JSON files and environment variables, and can be extended to support other formats.

    screenshot

    Note:
    This is an early release, and the API may change in future versions.

    npm i @shadowmoose/config

    Check out the Documentation for more details.

    import { ConfigPanel, InputType } from "@shadowmoose/config";

    // Define a new configuration panel with strong types.
    const config = new ConfigPanel({
    // Define categories.
    first_category: { displayName: 'Test Category', description: 'This is a test category' },
    cat_2: { displayName: 'Category Two' },
    }, {
    // Define all config inputs, within each category.
    first_category: {
    text_string: {
    type: InputType.string().max(20).default('test-default'),
    displayName: 'Text String',
    description: 'A simple text string input',
    },
    test_number: {
    type: InputType.number().min(0).max(100).default(50),
    displayName: 'Test Number',
    customParser: (input: any) => {
    if (parseInt(input) % 2 !== 0) throw Error('Number must be even');
    return input;
    }
    },
    test_boolean: {
    type: InputType.boolean().default(false),
    displayName: 'Test Boolean',
    description: 'Check me out.'
    },
    },
    cat_2: {
    test_enum: {
    type: InputType.enum(["Salmon", "Tuna", "Trout"]).default('Tuna'),
    envName: 'FISH_TYPE', // Custom environment variable name.
    },
    complex_string_array: {
    type: z.string().transform(value => value.split(',')).pipe(z.string().trim().min(1).array()),
    default: 'one,two,three', // Example transform from CSV into Array.
    useZodTypeName: 'string', // Render as a string input to the user.
    }
    }
    });

    // Example: Load existing config from a JSON file and environment variables, then start the interface.
    // All values are optional.
    await config
    .fromJSON({
    filePath: '.env.json', // Load existing config from a JSON file, if it exists.
    }).fromEnvironment({
    prefix: 'TEST_', // Load existing config from environment variables, with optional prefix.
    envFile: '.env',
    }).startInterface({
    windowOptions: {
    title: 'Test Config Panel',
    width: 350,
    height: 320,
    },
    displayMethod: 'browser', // 'browser' | 'none'
    port: 0, // Use random available port.
    host: '0.0.0.0', // Bind to all interfaces to allow remote access.
    // Optional custom CSS/HTML to apply to the panel. Everything has simple class names to make this easy.
    style: '.category_title { color: blue; } .wrapper_first_category { background: #f0f0f0 !important; }',
    htmlHeader: '<h1 style="text-align: center">Configuration Panel</h1>',
    htmlFooter: '<p style="font-size: small;text-align: center">Generated Panel Demo</p>',
    });

    // Example: save updated config to a JSON file.
    config.toJSON('.env.json');
    // Example: accessing current valid config values live, without waiting.
    console.log(config.values);
    /* Output: {
    first_category: {
    text_string: string
    test_number: number
    test_boolean: boolean
    }
    cat_2: {
    test_enum: "Salmon" | "Tuna" | "Trout",
    complex_string_array: string[]
    }
    } */

    // Wait for the panel to be closed, and save the results to a variable.
    const results = await config.waitForClose();
    console.log('Configured enum value:', results.cat_2.test_enum);
    // Output: 'Configured enum value: Tuna'

    All data updates are emitted as events, enabling real-time feedback and dynamic behavior if desired. Using the above example config, you can listen for events like so:

    config.on('values', console.dir); // Listen for any changes to values.
    config.on('change.first_category', console.dir); // Listen for changes to values within a specific category. Strongly typed.
    config.on(config.key('test_cat', 'test_number'), console.log); // Listen for changes to a specific value. Strongly typed.
    config.on('error', console.error); // Listen for any errors that occur.
    config.on('exit', console.error); // Listen for when the panel is closed.