@moku-labs/game 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -165,7 +165,7 @@ The engine bin `moku-game` serves, builds and packs a game folder. A game writes
165
165
  | `moku-game native build <target> [--simulator]` | Builds the native app: `ios`, `macos`, `android` |
166
166
  | `moku-game native dev <target>` | Runs the native shell on the dev server |
167
167
  | `moku-game native doctor`, `native clean` | Checks or removes the native project |
168
- | `moku-game keys [--check]` | Writes `generated/assets.ts`, the strings and `manifest.json` |
168
+ | `moku-game keys [--check]` | Writes `generated/assets.ts`, the strings and `generated/manifest.json` |
169
169
  | `moku-game pack [--no-cache]` | Packs the assets into `dist/assets` |
170
170
  | `moku-game visual [--update] [--only <name>] [--no-pixels]` | Runs the visual tests of `tests/visual/index.ts` against `tests/visual/baselines/`. The pixel leg runs on a Mac, on a page served for the run. Exit 1 when a checkpoint differs |
171
171
 
package/dist/cli.mjs CHANGED
@@ -355,6 +355,11 @@ const FORWARDED = [
355
355
  const STOPPING = ["SIGINT", "SIGTERM"];
356
356
  /** How often the dev child checks that its parent still runs. */
357
357
  const PARENT_CHECK_MS = 1e3;
358
+ /**
359
+ * The dev manifest `moku-game keys` writes, relative to the game folder, next to
360
+ * `generated/assets.ts`. The dev server answers `/manifest.json` with it.
361
+ */
362
+ const DEV_MANIFEST = "generated/manifest.json";
358
363
  /** The folders a `.dev.ts` module is never looked for in. */
359
364
  const NO_DEV_MODULES = /^(?:node_modules|dist|generated|tests|__tests__)$/;
360
365
  /** A `.gitignore` line that keeps `.moku/` of its own folder out. */
@@ -663,9 +668,9 @@ function devChildCommand(run, page, deps) {
663
668
  async function serveParent(run, deps) {
664
669
  const settings = await loadGame(run.root);
665
670
  const hasPack = isFile(path.join(run.root, "dist", "assets", "manifest.json"));
666
- const hasManifest = isFile(path.join(run.root, "manifest.json"));
671
+ const hasManifest = isFile(path.join(run.root, DEV_MANIFEST));
667
672
  if (run.packed && !hasPack) throw new Error(`[game] dev: no packed build in "${path.join(run.root, "dist", "assets")}".\n Run "moku-game pack" first.`);
668
- if (!run.packed && !hasManifest) deps.ui.warn(`[game] dev: no manifest.json in "${run.root}".\n Run "moku-game keys" first.`);
673
+ if (!run.packed && !hasManifest) deps.ui.warn(`[game] dev: no ${DEV_MANIFEST} in "${run.root}".\n Run "moku-game keys" first.`);
669
674
  const page = writePage(run.root, settings, run, deps.resolve);
670
675
  if (!ignoresMoku(run.root)) deps.ui.warn("[game] dev: add \".moku/\" to .gitignore. moku-game writes its dev page there.");
671
676
  return runChild(devChildCommand(run, page, deps), deps, {
@@ -755,8 +760,10 @@ function fileResponse(file) {
755
760
  }
756
761
  /**
757
762
  * Starts the dev server on `127.0.0.1` only, never on every interface: the page on `/`, the
758
- * manifest of the served folder on `/manifest.json`, and its files as static files. The dev child
759
- * and `moku-game visual` serve the page with it.
763
+ * manifest on `/manifest.json`, and the files of the served folder as static files. The manifest
764
+ * is the dev manifest `generated/manifest.json` of the game, or `manifest.json` of `dist/assets`
765
+ * with `--packed`; its paths are relative to the served folder. The dev child and
766
+ * `moku-game visual` serve the page with it.
760
767
  *
761
768
  * @param run - The flags of the run.
762
769
  * @param page - The page bundle the process imported.
@@ -765,6 +772,7 @@ function fileResponse(file) {
765
772
  */
766
773
  function serveOn(run, page) {
767
774
  const base = run.packed ? path.join(run.root, "dist", "assets") : run.root;
775
+ const manifest = path.join(base, run.packed ? "manifest.json" : DEV_MANIFEST);
768
776
  try {
769
777
  return Bun.serve({
770
778
  hostname: "127.0.0.1",
@@ -772,7 +780,7 @@ function serveOn(run, page) {
772
780
  development: true,
773
781
  routes: {
774
782
  "/": page,
775
- "/manifest.json": () => fileResponse(path.join(base, "manifest.json"))
783
+ "/manifest.json": () => fileResponse(manifest)
776
784
  },
777
785
  fetch: (request) => fileResponse(staticPath(base, new URL(request.url).pathname))
778
786
  });
@@ -891,7 +899,7 @@ function hasEnglishStrings(root, settings) {
891
899
  return [...featureFolders, ...layerFolders].some((folder) => statSync(path.join(folder, "strings", "en.json"), { throwIfNoEntry: false })?.isFile() === true);
892
900
  }
893
901
  /**
894
- * The flags of the asset scan for `moku-game keys`: the dev manifest beside the game, the
902
+ * The flags of the asset scan for `moku-game keys`: the dev manifest in `generated/`, the
895
903
  * pseudo-locale when the game has an English string file, and `--check` for a check run.
896
904
  *
897
905
  * @param root - The game folder.
@@ -900,7 +908,7 @@ function hasEnglishStrings(root, settings) {
900
908
  * @returns The flags for the scanner's command line.
901
909
  * @example
902
910
  * ```ts
903
- * keysArguments("/g", resolveConfig({ page: { title: "T" } }), true).slice(4); // ["--manifest", "/g/manifest.json", "--check"]: no strings
911
+ * keysArguments("/g", resolveConfig({ page: { title: "T" } }), true).slice(4); // ["--manifest", "/g/generated/manifest.json", "--check"]: no strings
904
912
  * keysArguments("/g", resolveConfig({ page: { title: "T" } }), false).at(-1); // "--pseudo" once /g/features/home/strings/en.json exists
905
913
  * ```
906
914
  */
@@ -908,7 +916,7 @@ function keysArguments(root, settings, check) {
908
916
  return [
909
917
  ...scanArguments(root, settings),
910
918
  "--manifest",
911
- path.join(root, "manifest.json"),
919
+ path.join(root, DEV_MANIFEST),
912
920
  ...hasEnglishStrings(root, settings) ? ["--pseudo"] : [],
913
921
  ...check ? ["--check"] : []
914
922
  ];
@@ -1183,12 +1191,12 @@ async function loadSuite(file, cwd) {
1183
1191
  * @param resolve - Bun's resolver, to find the hot plugin.
1184
1192
  * @returns The paths of the HTML and the bunfig.
1185
1193
  * @throws {Error} The errors of `moku-game dev` before its server starts, and a game without
1186
- * `manifest.json`.
1194
+ * `generated/manifest.json`.
1187
1195
  */
1188
1196
  async function writeVisualPage(page, resolve) {
1189
1197
  const settings = await loadGame(page.root);
1190
- const manifest = path.join(page.root, "manifest.json");
1191
- if (statSync(manifest, { throwIfNoEntry: false })?.isFile() !== true) throw new Error(`[game] visual: no manifest.json in "${page.root}".\n Run "moku-game keys" first.`);
1198
+ const manifest = path.join(page.root, DEV_MANIFEST);
1199
+ if (statSync(manifest, { throwIfNoEntry: false })?.isFile() !== true) throw new Error(`[game] visual: no ${DEV_MANIFEST} in "${page.root}".\n Run "moku-game keys" first.`);
1192
1200
  return writePage(page.root, settings, {
1193
1201
  preload: page.preload,
1194
1202
  servePlugins: page.servePlugins
@@ -1391,7 +1399,7 @@ const USAGE = [
1391
1399
  " native build <target> [--simulator] build the native app (ios, macos, android)",
1392
1400
  " native dev <target> run the native shell on the dev server",
1393
1401
  " native doctor | native clean check or remove the native project",
1394
- " keys [--check] write generated/assets.ts and manifest.json",
1402
+ " keys [--check] write generated/assets.ts and generated/manifest.json",
1395
1403
  " pack [--no-cache] pack the assets into dist/assets",
1396
1404
  " visual [--update] [--only <name>] run tests/visual/index.ts: headless, pixels on a Mac",
1397
1405
  " [--no-pixels | --pixels] [--webgl] [--dir tests/visual/baselines]",
@@ -21,7 +21,7 @@
21
21
  * ```
22
22
  */
23
23
  type ProjectOptions = {
24
- /** The folder of the game. A path that is not a directory rejects `openProject`. */root: string; /** The asset manifest, root-relative. Default `manifest.json`, the scanner's default. */
24
+ /** The folder of the game. A path that is not a directory rejects `openProject`. */root: string; /** The asset manifest, root-relative. Default `generated/manifest.json`, where `moku-game keys` writes it. */
25
25
  manifest?: string;
26
26
  /**
27
27
  * The tsconfig whose `paths` the index follows, root-relative. Default `tsconfig.json`. A path
package/dist/project.mjs CHANGED
@@ -2888,8 +2888,8 @@ async function walkRoot(root) {
2888
2888
  * ones, reads the aliases again when a config file moved, and rebuilds the index when bytes or
2889
2889
  * aliases changed. `reindexPath` reads one path now for `changed`.
2890
2890
  */
2891
- /** The manifest the asset scanner writes by default. */
2892
- const MANIFEST_FILE = "manifest.json";
2891
+ /** The dev manifest `moku-game keys` writes. */
2892
+ const MANIFEST_FILE = "generated/manifest.json";
2893
2893
  /** The tsconfig whose `paths` are read by default. */
2894
2894
  const TSCONFIG_FILE = "tsconfig.json";
2895
2895
  /**
package/llms.txt CHANGED
@@ -320,7 +320,7 @@ Commands of the bin `moku-game` (bun). Every command takes `--root <dir>` (defau
320
320
  - `moku-game dev [--port 3000] [--packed]`: writes `.moku/index.html`, `dev.ts`, `main.ts`, `bunfig.toml` (the hot plugin first, `__MOKU_GAME_DEV__` defined `true`), runs Bun again under that bunfig in the game folder and serves `/`. It prints `› <folder>: dev server, raw assets. Ctrl+C stops it.` and then the bound URL alone on its own line, `http://localhost:3000/`. `--port 0` takes a free port. `--packed` serves `dist/assets`. A new or removed file in `tests/scenarios/` rewrites `main.ts`. A taken port: `[game] dev: port 3000 is in use.` with `Pass --port 0 for a free port.`
321
321
  - `moku-game build [--out dist/web]`: packs the assets, bundles the page minified with `__MOKU_GAME_DEV__` defined `false` (no scenario, no agent, no `.dev` module, no `/control`), every link `./`, and copies the pack beside it with `manifest.json` next to `index.html`. Runs from any http sub-path and from Tauri, not from `file://`.
322
322
  - `moku-game native build <target> [--simulator]`, `native dev <target>`, `native doctor [<target>]`, `native clean [<target>]`: one verb of `@moku-labs/native` (a dev dependency, `^0.3.2`) over `config.ts`. App name, identifier and icon from `native`, orientation and background colour from `page`; the web build is `moku-game build`, the dev server `moku-game dev --port 5173`; system rows for `back`, `haptics`, `store`; the Tauri project in `.moku/tauri`, the apps in `dist-native`. `[game] config.ts has no native section.` without `native`.
323
- - `moku-game keys [--check]`: `generated/assets.ts`, the compiled strings and `manifest.json`. `moku-game pack [--no-cache]`: `dist/assets`. Both pass the layers of `config.ts`.
323
+ - `moku-game keys [--check]`: `generated/assets.ts`, the compiled strings and the dev manifest `generated/manifest.json`; `dev` serves it on `/manifest.json` and warns without it, `visual` stops without it. `moku-game pack [--no-cache]`: `dist/assets`. Both pass the layers of `config.ts`.
324
324
  - `moku-game visual [--update] [--only <name>] [--no-pixels | --pixels] [--webgl] [--dir <path>] [--tests <file>] [--url <url>]`: runs `runVisualTests` with the default export of `tests/visual/index.ts`, `{ app, tests }` (`app` is a `VisualSetup` `{ app, page? }`: `export default { app: { app: fixtureApp }, tests }`), against `tests/visual/baselines/`. The flags go through `parseVisualArgv`. The pixel leg runs on a Mac only unless `--pixels`/`--no-pixels`; without `--url` the command writes its own page into `.moku/visual/` (the page of `dev` and of the editor in `.moku/` stays), runs Bun again under `.moku/visual/bunfig.toml` as `dev` does (hot plugin, `--serve-plugin`, `--preload`), and the child serves the page on a free port, then stops it. No `manifest.json`: `[game] visual: no manifest.json in "<game>".` Exit 0 when the report is ok, else 1. `[game] visual: <file> must export default { app, tests }.` for a missing module or another shape, a bare app factory too.
325
325
  - `preparePage(root, { agents?, preload?, servePlugins? })` of `@moku-labs/game/cli` writes the dev page of `moku-game dev` and resolves `{ html, bunfig }`, both absolute, for a server the caller starts: `bun --config=<bunfig>`. With agents the page also imports the game's `**/*.dev.ts` and hands them to the agents. The editor calls it: `await preparePage("games/timber", { agents: ["@moku-labs/editor/agent/page"] })`.
326
326
 
@@ -711,7 +711,7 @@ core/ the kit (the defineGame call) and its types
711
711
  shared/ the shared layer
712
712
  features/<f>/ one feature: flow/, rules/, views/, styles/, motion/, world/, assets/, strings/
713
713
  plugins/ the game's own plugins
714
- generated/ what moku-game keys writes
714
+ generated/ what moku-game keys writes: assets.ts, the strings, manifest.json
715
715
  tests/ the tests; tests/scenarios/<name>.ts are the saves of ?player=<name>
716
716
  .moku/ what moku-game writes, ignored by git
717
717
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moku-labs/game",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "2D puzzle game engine on TypeScript and PixiJS, built on @moku-labs/core.",
5
5
  "type": "module",
6
6
  "sideEffects": false,