@gameable/vite-plugin-gameable
Interfaces
EmitContext
The slice of the Rollup plugin context the plugin uses.
Methods
emitFile()
ts
emitFile(asset): void;Emit one asset into the build.
Parameters
| Parameter | Type | Description |
|---|---|---|
asset | { fileName: string; source: string | Uint8Array<ArrayBufferLike>; type: "asset"; } | The asset descriptor. |
asset.fileName | string | - |
asset.source | string | Uint8Array<ArrayBufferLike> | - |
asset.type | "asset" | - |
Returns
void
warn()
ts
warn(message): void;Report a build-time warning.
Parameters
| Parameter | Type | Description |
|---|---|---|
message | string | What to say. |
Returns
void
GameableConfig
The configuration gameable() contributes, as a plain object.
Properties
alias
ts
alias: object[];Alias entries to add, in Vite's array form.
find
ts
find: RegExp;replacement
ts
replacement: string;conditions
ts
conditions: string[];Resolve conditions to add.
define
ts
define: Record<string, string>;define entries, including import.meta.env.GAMEABLE_MODE.
exclude
ts
exclude: string[];Packages to keep out of the dependency pre-bundle.
guestBase
ts
guestBase: string;Path the guest is served from, with a leading and trailing slash.
guestOutDir
ts
guestOutDir: string;Where the guest lands inside the build output, relative to outDir, with a trailing slash and no leading one. This is guestBase minus the app base: an emitted file is named relative to outDir, and the base is what the server puts in front of outDir, so baking it into the file name would serve the guest from <base><base>guest/.
guestUrl
ts
guestUrl: string;URL of the transpiled guest entry, as the app should fetch it.
mode
ts
mode: GameableMode;The sandbox mode the app was built for.
GameableEnv
The environment resolveGameableConfig reads.
Properties
base?
ts
optional base?: string;The app's public base path, as Vite resolved it. Defaults to /.
command
ts
command: "serve" | "build";Vite's command: serve for dev and preview, build for a production build.
env?
ts
optional env?: Record<string, string | undefined>;Process environment, for GAMEABLE_MODE and GAMEABLE_WASM.
viteMode?
ts
optional viteMode?: string;Vite's own --mode. direct and wasm select the sandbox, which is how vite build --mode direct produces a build that needs no guest component.
GameableOptions
Options accepted by gameable.
Properties
development?
ts
optional development?: boolean;The old name of source, from when the condition was development.
exclude?
ts
optional exclude?: readonly string[];Extra package names kept out of the dependency pre-bundle. The wasm runtimes jolt-physics and onnxruntime-web are always excluded.
guestBase?
ts
optional guestBase?: string;Path the guest is served from, relative to the app base. Defaults to guest/; the transpiled entry is then guest/game.js.
guestDir?
ts
optional guestDir?: string;Directory holding the jco transpile output, relative to the Vite root. Defaults to build/guest, which is where scripts/build-guest.mjs writes.
guestSources?
ts
optional guestSources?: readonly string[];What the guest is built from, relative to the Vite root, for the dev server's stale-guest answer. Defaults to src/, scripts/build-guest.mjs and the SDK's sources (guestSources).
mode?
ts
optional mode?: GameableMode;Force a sandbox mode instead of deriving one.
The derivation, in order: this option, then Vite's own --mode when it is direct or wasm, then GAMEABLE_MODE in the environment, then GAMEABLE_WASM=1, then wasm for vite build and direct for vite dev.
source?
ts
optional source?: boolean;Add the gameable-source resolve condition, so the engine's packages resolve to their sources in this repository. Defaults to true.
three?
ts
optional three?: boolean;Alias bare three onto three/webgpu. Defaults to true.
GameableVitePlugin
The shape of the Vite plugin object this package produces.
Typed structurally rather than as Vite's Plugin so the package carries no runtime or type dependency on a particular Vite major; a real Vite accepts it because every member matches.
Properties
enforce?
ts
optional enforce?: "pre" | "post";Run before Vite's own resolution, so the alias and conditions win.
name
ts
name: string;Plugin name, as it appears in Vite's logs.
Methods
config()?
ts
optional config(config, env): unknown;Contribute configuration.
Parameters
| Parameter | Type | Description |
|---|---|---|
config | Record<string, unknown> | The user's configuration so far. |
env | { command: "serve" | "build"; mode?: string; } | Vite's command and mode. |
env.command | "serve" | "build" | - |
env.mode? | string | - |
Returns
unknown
A partial configuration Vite deep-merges.
configResolved()?
ts
optional configResolved(config): void;Record the base Vite resolved, so the guest URL is right under a sub-path.
Parameters
| Parameter | Type | Description |
|---|---|---|
config | { base?: string; root?: string; } | The resolved configuration. |
config.base? | string | - |
config.root? | string | - |
Returns
void
configureServer()?
ts
optional configureServer(server): void;Install the dev middlewares.
Parameters
| Parameter | Type | Description |
|---|---|---|
server | { middlewares: { use: (fn) => void; }; } | The dev server. |
server.middlewares | { use: (fn) => void; } | - |
server.middlewares.use | (fn) => void | - |
Returns
void
generateBundle()?
ts
optional generateBundle(this): void;Emit the transpiled guest into the build.
Parameters
| Parameter | Type | Description |
|---|---|---|
this | EmitContext | The Rollup plugin context, for emitFile. |
Returns
void
GuestStatus
The answer at GUEST_STATUS_PATH.
Example
ts
import type { GuestStatus } from 'gameable/vite';
const status: GuestStatus = { builtAt: 0, sourceAt: 1, stale: true };Properties
builtAt
ts
builtAt: number;The built guest's mtime in ms, or 0 when there is none.
sourceAt
ts
sourceAt: number;The newest mtime among the sources it is built from.
stale
ts
stale: boolean;No guest, or a source newer than it.
Type Aliases
DevMiddleware
ts
type DevMiddleware = (req, res, next) => void;The slice of a connect middleware the plugin uses.
Parameters
| Parameter | Type |
|---|---|
req | { url?: string; } |
req.url? | string |
res | { statusCode: number; end: void; setHeader: void; } |
res.statusCode | number |
res.end | |
res.setHeader | |
next | () => void |
Returns
void
GameableMode
ts
type GameableMode = "direct" | "wasm";Which sandbox the app should build.
Variables
ALWAYS_EXCLUDED
ts
const ALWAYS_EXCLUDED: readonly string[];Packages whose emscripten glue must not be pre-bundled by esbuild.
GUEST_STATUS_PATH
ts
const GUEST_STATUS_PATH: "/__aos/guest-status.json" = '/__aos/guest-status.json';Where the dev server answers whether the built guest is stale. The same path is GUEST_STATUS_PATH in gameable/net/solo, which asks it.
Example
ts
import { GUEST_STATUS_PATH } from 'gameable/vite';
console.log(GUEST_STATUS_PATH); // '/__aos/guest-status.json'NEVER_INLINED
ts
const NEVER_INLINED: readonly string[];Extensions never inlined as a data: URI.
A wasm module inlined as base64 cannot be streamed, and an engine asset inlined into the entry chunk is downloaded before the first frame instead of alongside it.
PACKAGE
ts
const PACKAGE: "gameable/vite";Package identity marker for gameable/vite.
Example
ts
import { PACKAGE } from 'gameable/vite';
console.log(PACKAGE); // 'gameable/vite'Functions
gameable()
ts
function gameable(options?): GameableVitePlugin;The gameable Vite plugin.
Add it to plugins and the app resolves workspace packages from source, gets exactly one three, keeps the wasm runtimes out of the pre-bundle, serves .wasm correctly, and learns which sandbox to build through import.meta.env.GAMEABLE_MODE.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | GameableOptions | Mode override, guest directory and the opt-outs. |
Returns
A Vite plugin.
Example
ts
import { gameable } from 'gameable/vite';
import { defineConfig } from 'vite';
export default defineConfig({ plugins: [gameable()] });guestFreshness()
ts
function guestFreshness(paths): GuestStatus;Whether the built guest is older than what it is built from.
Parameters
| Parameter | Type | Description |
|---|---|---|
paths | { guestEntry: string; sources: readonly string[]; } | The guest's entry and the sources. |
paths.guestEntry | string | The transpiled guest's game.js (build/guest/game.js). |
paths.sources | readonly string[] | Files and directories it is built from. |
Returns
The newest mtimes, and stale when there is no guest or a source is newer.
Example
ts
import { guestFreshness, guestSources } from 'gameable/vite';
const status = guestFreshness({ guestEntry: 'build/guest/game.js', sources: guestSources('.') });
if (status.stale) console.warn('run npm run build:guest');guestSources()
ts
function guestSources(root): string[];What a game's guest is built from: its src/, its scripts/build-guest.mjs, and the SDK's sources when they are installed beside it (in this repository's workspace).
Parameters
| Parameter | Type | Description |
|---|---|---|
root | string | The app root (Vite's root). |
Returns
string[]
Absolute paths; missing ones count as never changed.
Example
ts
import { guestSources } from 'gameable/vite';
console.log(guestSources('/app')); // ['/app/src', '/app/scripts/build-guest.mjs', ...]resolveGameableConfig()
ts
function resolveGameableConfig(options, env): GameableConfig;Compute everything the plugin contributes, with no Vite involved.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | GameableOptions | The plugin options. |
env | GameableEnv | The Vite command, process environment and app base. |
Returns
The configuration contribution.
Example
ts
import { resolveGameableConfig } from 'gameable/vite';
const config = resolveGameableConfig({}, { command: 'serve' });
console.log(config.conditions); // ['gameable-source']
console.log(config.define['import.meta.env.GAMEABLE_MODE']); // '"direct"'resolveGameableMode()
ts
function resolveGameableMode(options, env): GameableMode;Decide which sandbox the app is being built for.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | GameableOptions | The plugin options. |
env | GameableEnv | The Vite command and process environment. |
Returns
The mode.
Example
ts
import { resolveGameableMode } from 'gameable/vite';
console.log(resolveGameableMode({}, { command: 'serve' })); // 'direct'
console.log(resolveGameableMode({}, { command: 'build' })); // 'wasm'