TypeScript setup
The TypeScript plugin API is the npm package @vespura/vmenu-plugin, with its types included. The rest of the API is on Making a plugin. The TypeScript example is a complete project to copy.
Installing the package
Section titled “Installing the package”npm install @vespura/vmenu-plugin@<your vMenu version> --save-exactThe package version always matches the vMenu Enhanced release it belongs to. Pin it to the vMenu your server runs, and raise it when you update vMenu.
| Import from | Used by |
|---|---|
@vespura/vmenu-plugin/client |
your client script |
@vespura/vmenu-plugin/server |
your server script |
Bundling
Section titled “Bundling”The package ships ES modules, and FiveM loads plain scripts. Bundle each half into one file with esbuild, or any bundler you like:
import { build } from 'esbuild';
const shared = { bundle: true, format: 'iife', target: 'es2020' };
await build({ ...shared, entryPoints: ['src/client.ts'], platform: 'browser', outfile: 'dist/client.js' });await build({ ...shared, entryPoints: ['src/server.ts'], platform: 'node', outfile: 'dist/server.js' });The plugin API ends up inside both files, so the resource needs nothing else at runtime, and start order does not matter. Since the output is a plain script, use .then() at the top level rather than a top level await.
Manifest
Section titled “Manifest”fx_version 'cerulean'games { 'gta5' }
client_script 'dist/client.js'server_script 'dist/server.js'Things specific to TypeScript
Section titled “Things specific to TypeScript”Everything on the JavaScript setup page applies, with imports in place of the global vMenu object:
import { Gate, Text, VMenuPlugin } from '@vespura/vmenu-plugin/client';import { ServerPluginDeclaration, VMenuServer } from '@vespura/vmenu-plugin/server';Every row type has its own class, such as PluginCheckbox or PluginList, so instanceof narrows a row you got back from a key press or a filter. The options for each add method are typed too, so your editor tells you which ones a row takes.
