@ferret/compiler
The compiler core: a .fprj project's files in, a .fex game and a report out. It touches no disk and no network: the
bundler (esbuild, native or wasm), the release's release.json and the engi…
The compiler core: a .fprj project's files in, a .fex game and a report out. It touches no disk and no network: the
bundler (esbuild, native or wasm), the release's release.json and the engine files are handed in, so the same code runs in ferret build and in
the browser editor, and the same project gives the same bytes in both.
Classes
BuildError class
class BuildError extends Errorconstructor(message: string, readonly issues: { path: string; message: string }[] = []) |
packages/compiler/src/index.ts:103
Functions
babylonPartsFor function
function babylonPartsFor(names: Iterable<string>, parts: BabylonParts): string[]The parts of Babylon that cover these names, with the parts they imply, core first.
packages/compiler/src/index.ts:24
buildGame function
async function buildGame(files: Map<string, Uint8Array>, env: BuildEnv, o: BuildOptions = {}): Promise<{ bytes: Uint8Array; manifest: PackageManifest; report: BuildReport }>Build a game from a project. files are the project's files by path (including ferret.json). Returns the .fex bytes and the report; throws a
BuildError, with the issues and without any output, when the project or the result does not check out.
packages/compiler/src/index.ts:160
buildLevelPackage function
async function buildLevelPackage(files: Map<string, Uint8Array>, env: Pick<BuildEnv, 'release'>, o: LevelPackageOptions): Promise<{ bytes: Uint8Array; manifest: PackageManifest; report: LevelPackageReport }>A package of kind levels for a finished game: the chosen levels and the assets they name, no code, for the game.
Assets the game's .fex already holds (alreadyIn) stay out. Throws a BuildError, without output, when the result does not check out.
packages/compiler/src/index.ts:329
checkProject function
async function checkProject(files: Map<string, Uint8Array>, engine: { ferret: string; babylon: string }): Promise<CheckResult>Open a project from its bytes (or files) and check everything that needs no build: the manifest, the levels, every reference.
packages/compiler/src/index.ts:291
ferretSourceIssues function
function ferretSourceIssues(files: Map<string, Uint8Array>): { path: string; message: string }[]the plan requirement 9: a project holds the user's own code and assets, never a copy of Ferret or Babylon. They are met at run time only.
Returns what in the project looks like engine material: an engine/ folder, node_modules, an engine or Babylon bundle by name or by content.
packages/compiler/src/index.ts:141
globMatch function
function globMatch(pattern: string, path: string): booleanDoes a keep / .ferretignore pattern (*, **, ?) match this path?
packages/compiler/src/index.ts:111
projectBundle function
function projectBundle(esbuild: EsbuildLike)packages/compiler/src/bundle.ts:21
selectEngine function
function selectEngine(release: ReleaseJson, names: string[], wanted: Record<string, string> = {}): EngineSelectionThe part of a release the given modules need: their files, the chunks those import (statically or dynamically), and the run-time files.
packages/compiler/src/index.ts:47
Interfaces
BabylonParts interface
interface BabylonPartsparts.json of a Babylon-in-parts folder (tools/babylon/build.mjs): the name -> part map and what a part implies
babylon: string | |
names: Record<string, string> | |
implies: Record<string, string[]> | |
parts: Record<string, { file: string; bytes: number; graphBytes: number; chunks: string[]; /** files it may fetch later by `import()` */ dynamic?: string[] }> |
packages/compiler/src/index.ts:21
BuildEnv interface
interface BuildEnvbundle(entry: string, files: Map<string, Uint8Array>): Promise<BundleResult> | bundle entry (a path in files) as one ES module: relative imports resolved in files, @ferret/* and nothing else left external |
release: ReleaseJson | |
readRelease?(path: string): Promise<Uint8Array> | standalone only: the bytes of a file of the release folder (modules/<v>/<path>), and Babylon's files by their names |
babylonFiles?(): Promise<{ name: string; data: Uint8Array }[]> | |
babylonParts?: BabylonParts | Babylon in parts (stage P6): its parts.json and the bytes of a file of that folder. Without it the game names no parts and the player loads the full build |
readBabylonPart?(file: string): Promise<Uint8Array> |
packages/compiler/src/index.ts:77
BuildOptions interface
interface BuildOptionsstandalone?: boolean |
packages/compiler/src/index.ts:89
BuildReport interface
interface BuildReportgame: { id: string; version: string; bytes: number; standalone: boolean } | |
engine: { ferret: string; babylon: string; modules: { name: string; why: string; bytes: number }[]; files: { path: string; bytes: number }[]; bytes: number; where: 'host' | 'inside' } | |
included: ReportFile[] | what the game reaches and carries, by folder |
left: { path: string; bytes: number }[] | project files nothing reaches |
levels: Record<string, { files: number; bytes: number }> | per level: its files |
packages/compiler/src/index.ts:92
BundleResult interface
interface BundleResultcode: string | |
imports: { name: string; from: string }[] |
packages/compiler/src/index.ts:75
CheckResult interface
interface CheckResultissues: { path: string; message: string }[] | |
warnings: { path: string; message: string }[] |
packages/compiler/src/index.ts:288
EngineSelection interface
interface EngineSelectionmodules: string[] | every module of the closure, with the file sizes it adds |
files: string[] | every file of the release folder this needs, sorted: module files, chunks, runtime files |
babylon: string[] | the Babylon names the modules need at load, and the ones they ask for later |
babylonLazy: string[] | |
release: ReleaseJson | a release.json cut to exactly these files |
why: Record<string, string> | why each module is in: the import that wants it, or always |
packages/compiler/src/index.ts:33
EsbuildLike interface
interface EsbuildLikeThe part of esbuild's API this uses; esbuild and esbuild-wasm both fit.
build(options: Record<string, unknown>): Promise<{ outputFiles?: { text: string }[]; metafile?: { inputs: Record<string, { imports: { path: string }[] }> } }> |
packages/compiler/src/bundle.ts:9
LevelPackageOptions interface
interface LevelPackageOptionslevels: string[] | the level ids to ship |
id?: string | package id, name and version; defaults <game>-levels, <game name> levels, the project's version |
name?: string | |
version?: string | |
forVersion?: string | which versions of the game it fits; default ^<project version> |
alreadyIn?: Iterable<string> | paths the game's .fex already holds (its report.json, or the list of its files): not copied again |
packages/compiler/src/index.ts:313
LevelPackageReport interface
interface LevelPackageReportid: string | |
version: string | |
bytes: number | |
levels: Record<string, { files: number; bytes: number }> | |
included: ReportFile[] | |
skipped: { path: string; why: string }[] |
packages/compiler/src/index.ts:323
ReleaseChunk interface
interface ReleaseChunkbytes: number | |
sha256: string | |
imports: string[] | |
dynamic?: string[] |
packages/compiler/src/index.ts:12
ReleaseJson interface
interface ReleaseJsonformat: number | |
ferret: string | |
build: string | |
babylon: string | |
modules: Record<string, ReleaseModule> | |
chunks: Record<string, ReleaseChunk> | |
runtime: Record<string, { bytes: number; sha256: string; module: string }> |
packages/compiler/src/index.ts:13
ReleaseModule interface
interface ReleaseModulefile: string | |
bytes: number | |
sha256: string | |
chunks: string[] | |
imports: string[] | |
graphBytes: number | |
runtime: string[] | |
babylon?: string[] | |
babylonLazy?: string[] |
packages/compiler/src/index.ts:11
ReportFile interface
interface ReportFilepath: string | |
bytes: number | |
why: string |
packages/compiler/src/index.ts:91
Constants
ALWAYS_LOADED const
const ALWAYS_LOADED: string[]What the player always loads, whatever the game imports: the boot module and the player itself.
packages/compiler/src/index.ts:31