Skip to content

@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 ​
ParameterTypeDescription
asset{ fileName: string; source: string | Uint8Array<ArrayBufferLike>; type: "asset"; }The asset descriptor.
asset.fileNamestringPath relative to the output directory.
asset.sourcestring | Uint8Array<ArrayBufferLike>Asset contents.
asset.type"asset"Asset output kind.
Returns ​

void

warn() ​
ts
warn(message): void;

Report a build-time warning.

Parameters ​
ParameterTypeDescription
messagestringWhat 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 ​
ParameterType
idstring
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 ​
ParameterType
idstring
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 ​
ParameterTypeDescription
this{ error: never; warn: void; }Build diagnostics.
this.errorFail the build with a structured error.
this.warnReport a structured build warning.
Returns ​

void

config()? ​
ts
optional config(config, env): unknown;

Contribute configuration.

Parameters ​
ParameterTypeDescription
configRecord<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?stringVite 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 ​
ParameterTypeDescription
config{ base?: string; publicDir?: string | false; root?: string; }The resolved configuration.
config.base?stringResolved public base.
config.publicDir?string | falseResolved public directory, or false.
config.root?stringAbsolute project root.
Returns ​

void

configurePreviewServer()? ​
ts
optional configurePreviewServer(server): void;

Install the preview server's middlewares (the talk relay).

Parameters ​
ParameterTypeDescription
serverunknownThe preview server.
Returns ​

void

configureServer()? ​
ts
optional configureServer(server): void;

Install the dev middlewares.

Parameters ​
ParameterTypeDescription
server{ middlewares: { use: (fn) => void; }; }The dev server.
server.middlewares{ use: (fn) => void; }Connect middleware stack.
server.middlewares.use(fn) => voidRegister a middleware.
Returns ​

void

generateBundle()? ​
ts
optional generateBundle(this): void;

Emit the transpiled guest into the build.

Parameters ​
ParameterTypeDescription
thisEmitContextThe Rollup plugin context, for emitFile.
Returns ​

void

handleHotUpdate()? ​
ts
optional handleHotUpdate(ctx): Promise<ModuleNode[] | undefined>;

Intercept only registered direct game sources during development.

Parameters ​
ParameterType
ctxHmrContext
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 ​
ParameterTypeDescription
this{ error: never; warn: void; }The Rollup diagnostic context.
this.errorFail the build with a structured error.
this.warnReport a structured build warning.
optionsunknownOutput options.
bundleSiteBundleFinal 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 ​

ParameterType
req{ url?: string; }
req.url?string
res{ statusCode: number; end: void; setHeader: void; }
res.statusCodenumber
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 ​

ParameterTypeDescription
optionsGameableOptionsMode override, guest directory and the opt-outs.

Returns ​

GameableVitePlugin

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 ​

ParameterTypeDescription
paths{ guestEntry: string; sources: readonly string[]; }The guest's entry and the sources.
paths.guestEntrystringThe transpiled guest's game.js (build/guest/game.js).
paths.sourcesreadonly string[]Files and directories it is built from.

Returns ​

GuestStatus

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 ​

ParameterTypeDescription
rootstringThe 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 ​

ParameterTypeDescription
optionsGameableOptionsThe plugin options.
envGameableEnvThe Vite command, process environment and app base.

Returns ​

GameableConfig

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 ​

ParameterTypeDescription
optionsGameableOptionsThe plugin options.
envGameableEnvThe Vite command and process environment.

Returns ​

GameableMode

The mode.

Example ​

ts
import { resolveGameableMode } from 'gameable/vite';

console.log(resolveGameableMode({}, { command: 'serve' })); // 'direct'
console.log(resolveGameableMode({}, { command: 'build' })); // 'wasm'