@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 | Path relative to the output directory. |
asset.source | string | Uint8Array<ArrayBufferLike> | Asset contents. |
asset.type | "asset" | Asset output kind. |
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: "build" | "serve";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
check?
ts
optional check?: "error" | "off" | "warn";Static content checking during production builds. Defaults to 'error'.
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.
rootPaths?
ts
optional rootPaths?: "error" | "off" | "warn";How to report root-absolute published file addresses during builds. Defaults to 'error' for a relative base (--base ./, how sites are published) and 'warn' for an absolute one.
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.
talk?
ts
optional talk?: boolean | GameableTalkOptions;Talking characters: the conversation relay inside the dev and preview servers. true finds every src/<id>.story.yaml and uploads it to the conversation service (again when it is saved); an object names more. Needs GAMEABLE_API_KEY in .env.local or the environment. The page connects with talkingCharacters() from gameable/conversation.
three?
ts
optional three?: boolean;Alias bare three onto three/webgpu. Defaults to true.
GameableTalkOptions
The talk option of the Vite plugin.
Properties
characters?
ts
optional characters?: Readonly<Record<string, string | TalkCharacter>>;Characters named here, by the id the game uses: { elora: 'src/elora.story.yaml' }. Besides these, every src/<id>.story.yaml is found by itself, as it is added and saved: its id is the file's name.
faces?
ts
optional faces?: object;The lip-sync models for characters without one of their own (no a2f), by the story's story.character.gender. Default: Myra's (myra) for women, Isaac's (isaac) for men.
female?
ts
optional female?: string;male?
ts
optional male?: string;origins?
ts
optional origins?: readonly string[];Page origins allowed besides loopback ones (http://localhost:*, http://127.0.0.1:*).
path?
ts
optional path?: string;Where the relay is, under the app's base. Default talk.
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.
load?
ts
optional load?: (id) => string | undefined;Serve the internal development client.
Parameters
| Parameter | Type |
|---|---|
id | string |
Returns
string | undefined
name
ts
name: string;Plugin name, as it appears in Vite's logs.
resolveId?
ts
optional resolveId?: (id) => string | undefined;Resolve the internal development client.
Parameters
| Parameter | Type |
|---|---|
id | string |
Returns
string | undefined
transform?
ts
optional transform?: ObjectHook<(this, code, id, options?) => TransformResult | Promise<TransformResult>, {
}>;Inject the development boundary into modules that declare a game.
Methods
buildStart()?
ts
optional buildStart(this): void;Check authored content before production compilation.
Parameters
| Parameter | Type | Description |
|---|---|---|
this | { error: never; warn: void; } | Build diagnostics. |
this.error | Fail the build with a structured error. | |
this.warn | Report a structured build warning. |
Returns
void
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: "build" | "serve"; mode?: string; } | Vite's command and mode. |
env.command | "build" | "serve" | Dev or production build. |
env.mode? | string | Vite mode override. |
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; publicDir?: string | false; root?: string; } | The resolved configuration. |
config.base? | string | Resolved public base. |
config.publicDir? | string | false | Resolved public directory, or false. |
config.root? | string | Absolute project root. |
Returns
void
configurePreviewServer()?
ts
optional configurePreviewServer(server): void;Install the preview server's middlewares (the talk relay).
Parameters
| Parameter | Type | Description |
|---|---|---|
server | unknown | The preview server. |
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; } | Connect middleware stack. |
server.middlewares.use | (fn) => void | Register a middleware. |
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
handleHotUpdate()?
ts
optional handleHotUpdate(ctx): Promise<ModuleNode[] | undefined>;Intercept only registered direct game sources during development.
Parameters
| Parameter | Type |
|---|---|
ctx | HmrContext |
Returns
Promise<ModuleNode[] | undefined>
writeBundle()?
ts
optional writeBundle(
this,
options,
bundle
): void;Check final site addresses. Build hooks are never invoked by the dev server.
Parameters
| Parameter | Type | Description |
|---|---|---|
this | { error: never; warn: void; } | The Rollup diagnostic context. |
this.error | Fail the build with a structured error. | |
this.warn | Report a structured build warning. | |
options | unknown | Output options. |
bundle | SiteBundle | Final emitted chunks and assets. |
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.
TalkCharacter
One talking character: its story file, and optionally the lip-sync model the service animates its face with.
Properties
a2f?
ts
optional a2f?: string;The lip-sync model (isaac-gnm for a studio head's native frames); ARKit-52 weights without it.
story
ts
story: string;The story file (Convorcher story YAML), relative to the Vite root, e.g. stories/elora.yaml.
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'