@moku-labs/game 0.7.1 → 0.9.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 +12 -8
- package/dist/assets.d.mts +97 -33
- package/dist/assets.mjs +350 -110
- package/dist/{commands-mzE9PX0H.d.mts → commands-DuwCxK5t.d.mts} +5 -4
- package/dist/control.d.mts +4 -3
- package/dist/control.mjs +2 -2
- package/dist/{define-BbgXv4cy.d.mts → define-B6pHpdBi.d.mts} +4 -3
- package/dist/headless-BsNdJs9W.mjs +186 -0
- package/dist/headless-SCQXJxQf.d.mts +181 -0
- package/dist/hot.d.mts +4 -2
- package/dist/hot.mjs +8 -6
- package/dist/index-BO9kZzY3.d.mts +1611 -0
- package/dist/index.d.mts +6 -1596
- package/dist/index.mjs +4 -34334
- package/dist/{input-CK4nxBO1.mjs → input-z_35Jwfn.mjs} +2 -2
- package/dist/inspect.d.mts +7 -6
- package/dist/inspect.mjs +2 -2
- package/dist/jsx-dev-runtime.d.mts +1 -1
- package/dist/jsx-runtime.d.mts +1 -1
- package/dist/lint.d.mts +55 -4
- package/dist/lint.mjs +993 -40
- package/dist/project.d.mts +57 -41
- package/dist/project.mjs +994 -505
- package/dist/{run-Bcyg32M5.mjs → run-CofJEdYx.mjs} +4 -187
- package/dist/{runtime-HTlmRb81.d.mts → runtime-CdNJ0UBm.d.mts} +1 -1
- package/dist/{sources-DVWJ8nfr.mjs → sources-DNnzyCYf.mjs} +2 -2
- package/dist/src-536arXjV.mjs +34644 -0
- package/dist/testing.d.mts +85 -283
- package/dist/testing.mjs +158 -2109
- package/dist/{types-BMEn0tSC.d.mts → types-B0v5VVa3.d.mts} +10 -9
- package/dist/{types-ClF8say0.d.mts → types-CQueODzo.d.mts} +2 -2
- package/dist/{types-CYYKjvLn.d.mts → types-DUMoYPYe.d.mts} +5 -182
- package/dist/{types-CXyipKhE.d.mts → types-VZVWwqCg.d.mts} +42 -4
- package/dist/{types-BaUUcIaN.d.mts → types-xXfyk56Q.d.mts} +1 -1
- package/dist/{visual-DUvvPPCt.mjs → visual-dMW8iqAE.mjs} +8 -4
- package/dist/visual.d.mts +330 -0
- package/dist/visual.mjs +2142 -0
- package/llms.txt +59 -21
- package/package.json +7 -8
- package/dist/memory-CvgdnsQO.mjs +0 -259
package/README.md
CHANGED
|
@@ -115,7 +115,7 @@ await game.walk([{ at: "home", intent: "roll" }, { at: "home", intent: "roll" }]
|
|
|
115
115
|
app.model.store.snapshot().session; // { rolls: 2 }
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
-
The full version, with a reset node and a vitest file, is in [docs/quick-start.md](./docs/quick-start.md). A bigger game lives in [
|
|
118
|
+
The full version, with a reset node and a vitest file, is in [docs/quick-start.md](./docs/quick-start.md). A bigger game, the merge game, lives in [moku-labs/demos](https://github.com/moku-labs/demos) with its tests.
|
|
119
119
|
|
|
120
120
|
A game with a screen gets two more things from the package. The body font `fonts/font-body.*` (Pangolin, SIL OFL 1.1) is the default of the built-in text style `body` once copied into `src/features/ui/assets/`. The bin `moku-game-assets` writes the typed asset keys, the manifest and the strings. It runs under bun; with node only, run `bun node_modules/@moku-labs/game/dist/assets.mjs`. Both are in [docs/quick-start.md](./docs/quick-start.md#a-screen-the-body-font-and-the-asset-keys).
|
|
121
121
|
|
|
@@ -188,7 +188,8 @@ createApp({ plugins: [...screen, effectsPlugin, audioPlugin, platformPlugin] });
|
|
|
188
188
|
| Import | Runs in | For |
|
|
189
189
|
|---|---|---|
|
|
190
190
|
| `@moku-labs/game` | anywhere | The engine: plugins, helpers, components |
|
|
191
|
-
| `@moku-labs/game/testing` |
|
|
191
|
+
| `@moku-labs/game/testing` | anywhere | Headless and isolated games, the fake clock, the in-memory save |
|
|
192
|
+
| `@moku-labs/game/visual` | Node and Bun | Visual tests: baselines of state, describe and pixels |
|
|
192
193
|
| `@moku-labs/game/assets` | Node and Bun | Asset keys, the manifest, strings, the pack |
|
|
193
194
|
| `@moku-labs/game/inspect` | anywhere | Read a running game |
|
|
194
195
|
| `@moku-labs/game/control` | dev builds | Drive a running game |
|
|
@@ -199,7 +200,7 @@ createApp({ plugins: [...screen, effectsPlugin, audioPlugin, platformPlugin] });
|
|
|
199
200
|
|
|
200
201
|
### Lint for games
|
|
201
202
|
|
|
202
|
-
`@moku-labs/game/lint` is an oxlint JS plugin, `moku-game`. It checks the engine rules in a game: lazy Pixi and Yoga, no native package in the logic, the editor only in dev files, no module-scope state, determinism, pure rules and JSX keys the project index can follow.
|
|
203
|
+
`@moku-labs/game/lint` is an oxlint JS plugin, `moku-game`. It checks the engine rules in a game: lazy Pixi and Yoga, no native package in the logic, the editor only in dev files, no module-scope state, determinism, pure rules and JSX keys the project index can follow. Three layout rules check a game on the layered layout: the order of the layers, the doors of the features and the suffix of each test file.
|
|
203
204
|
|
|
204
205
|
```json
|
|
205
206
|
// .oxlintrc.json
|
|
@@ -212,12 +213,15 @@ createApp({ plugins: [...screen, effectsPlugin, audioPlugin, platformPlugin] });
|
|
|
212
213
|
"moku-game/no-module-state": "error",
|
|
213
214
|
"moku-game/determinism": "error",
|
|
214
215
|
"moku-game/rules-siblings": "error",
|
|
215
|
-
"moku-game/static-keys": "error"
|
|
216
|
+
"moku-game/static-keys": "error",
|
|
217
|
+
"moku-game/layer-imports": "error",
|
|
218
|
+
"moku-game/feature-door": "error",
|
|
219
|
+
"moku-game/test-suffix": "error"
|
|
216
220
|
}
|
|
217
221
|
}
|
|
218
222
|
```
|
|
219
223
|
|
|
220
|
-
Each rule takes `{ "files": [...], "ignores": [...] }`. The defaults follow the
|
|
224
|
+
Each rule takes `{ "files": [...], "ignores": [...] }`. `layer-imports`, `feature-door` and `rules-siblings` also take `root` and `tsconfig`; `test-suffix` takes `root` and `suffixes`. The defaults follow the layout of a game. See [Lint for games](./docs/lint.md).
|
|
221
225
|
|
|
222
226
|
## Docs
|
|
223
227
|
|
|
@@ -232,7 +236,7 @@ Each rule takes `{ "files": [...], "ignores": [...] }`. The defaults follow the
|
|
|
232
236
|
| [Configuration](./docs/configuration.md) | Every config field and its default |
|
|
233
237
|
| [Lint for games](./docs/lint.md) | The `moku-game` oxlint rules, their options and defaults |
|
|
234
238
|
| [Project index](./docs/project-index.md) | `openProject`, the key scheme, `find` and `watch`, the `moku-game-index` bin |
|
|
235
|
-
| [Testing](./docs/testing.md) | Headless and visual tests, all scripts, test layout, lint rules |
|
|
239
|
+
| [Testing](./docs/testing.md) | Headless, isolated and visual tests, all scripts, test layout, lint rules |
|
|
236
240
|
| [`llms.txt`](./llms.txt) | The engine in one page, for an AI that writes a game |
|
|
237
241
|
|
|
238
242
|
Each plugin has its own README, linked in the table above. The kernel is specified in the [Moku Core specification](https://github.com/moku-labs/core/tree/main/specification).
|
|
@@ -246,8 +250,8 @@ bun run lint # biome check . && eslint .
|
|
|
246
250
|
bun run test # vitest, unit and integration
|
|
247
251
|
bun run test:coverage # with the 90% threshold
|
|
248
252
|
bun run validate # publint and attw
|
|
249
|
-
bun run
|
|
250
|
-
bun run
|
|
253
|
+
bun run mini:pack # pack the mini game of tests/fixtures
|
|
254
|
+
bun run mini:visual # visual tests of the mini game
|
|
251
255
|
bun run release # moku-release
|
|
252
256
|
```
|
|
253
257
|
|
package/dist/assets.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { l as Manifest } from "./types-
|
|
1
|
+
import { l as Manifest } from "./types-B0v5VVa3.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/plugins/assets/scan/cli.d.ts
|
|
4
4
|
/**
|
|
@@ -19,18 +19,20 @@ type StringsReport = {
|
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
21
21
|
* Compiles the feature strings of a root into a folder, or checks them in a check run; with
|
|
22
|
-
* `pseudo` it writes the pseudo-locale `en-XA` too
|
|
23
|
-
* passes a stub instead.
|
|
22
|
+
* `pseudo` it writes the pseudo-locale `en-XA` too, and with `layers` it walks the `strings/` of
|
|
23
|
+
* every layer as well. `compileStrings` of i18n fits it, and a test passes a stub instead.
|
|
24
24
|
*
|
|
25
25
|
* @example
|
|
26
26
|
* ```ts
|
|
27
27
|
* // A test of a wrapper script: a game with one English key.
|
|
28
28
|
* const compile: StringsCompiler = async () => ({ changed: false, locales: ["en"], keys: ["hud.title"], notes: [] });
|
|
29
|
+
* // runCli passes { check: false, pseudo: true, layers: { shared: "ui" } } for "--pseudo --layer shared=ui"
|
|
29
30
|
* ```
|
|
30
31
|
*/
|
|
31
32
|
type StringsCompiler = (root: string, out: string, options: {
|
|
32
33
|
check: boolean;
|
|
33
34
|
pseudo: boolean;
|
|
35
|
+
layers?: Readonly<Record<string, string>>;
|
|
34
36
|
}) => Promise<StringsReport>;
|
|
35
37
|
/**
|
|
36
38
|
* Writes one exchange file per locale for the translators into a folder, and reports how many
|
|
@@ -44,6 +46,7 @@ type StringsCompiler = (root: string, out: string, options: {
|
|
|
44
46
|
*/
|
|
45
47
|
type StringsExporter = (root: string, dir: string, options: {
|
|
46
48
|
source: string;
|
|
49
|
+
layers?: Readonly<Record<string, string>>;
|
|
47
50
|
}) => Promise<{
|
|
48
51
|
locales: readonly string[];
|
|
49
52
|
missing: Readonly<Record<string, number>>;
|
|
@@ -63,6 +66,7 @@ type StringsImporter = (root: string, dir: string, options: {
|
|
|
63
66
|
source: string;
|
|
64
67
|
pseudo: boolean;
|
|
65
68
|
out: string;
|
|
69
|
+
layers?: Readonly<Record<string, string>>;
|
|
66
70
|
}) => Promise<{
|
|
67
71
|
locales: readonly string[];
|
|
68
72
|
keys: number;
|
|
@@ -90,8 +94,10 @@ type StringsTools = {
|
|
|
90
94
|
* compile the feature strings next to the key module, or check that all of it is current. With
|
|
91
95
|
* `--pack <dir>` it packs the art for production on the same scan (`--no-cache` for a cold run);
|
|
92
96
|
* `--pseudo` adds the pseudo-locale to a dev run. `--export <dir>` and `--import <dir>` exchange
|
|
93
|
-
* the strings with translators and run alone, from the locale of `--source`.
|
|
94
|
-
* `
|
|
97
|
+
* the strings with translators and run alone, from the locale of `--source`.
|
|
98
|
+
* `--layer <folder>[=<name>]` (repeatable) scans a folder under the root like one more feature,
|
|
99
|
+
* its keys and bundles under `<name>` (`<folder>` by default); it goes with every mode. Nothing
|
|
100
|
+
* here calls `process.exit`; the caller does.
|
|
95
101
|
*
|
|
96
102
|
* @param argv - The arguments after the script name.
|
|
97
103
|
* @param strings - The string tools of i18n: compile, export and import.
|
|
@@ -105,6 +111,8 @@ type StringsTools = {
|
|
|
105
111
|
* // 0, and dist/assets holds the pages, the loose files and the packed manifest.json
|
|
106
112
|
* await runCli(["--root", "src", "--export", "translations"], strings);
|
|
107
113
|
* // 0, and translations/ holds one <locale>.json per locale for the translators
|
|
114
|
+
* await runCli(["--root", "src", "--layer", "shared=ui"], strings);
|
|
115
|
+
* // 0, shared/assets/* keyed ui.*, shared/strings/* compiled
|
|
108
116
|
* ```
|
|
109
117
|
*/
|
|
110
118
|
declare function runCli(argv: string[], strings: StringsTools, ui?: ScanUi): Promise<number>;
|
|
@@ -121,36 +129,56 @@ type CompileReport = {
|
|
|
121
129
|
};
|
|
122
130
|
/**
|
|
123
131
|
* What one compile is told beyond its two paths.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```ts
|
|
135
|
+
* // A v15 game: the dev build writes en-XA, and shared/strings/ compiles next to the features.
|
|
136
|
+
* const options: CompileOptions = { pseudo: true, layers: { shared: "ui" } };
|
|
137
|
+
* ```
|
|
124
138
|
*/
|
|
125
139
|
type CompileOptions = {
|
|
126
140
|
/** True for a check run: nothing is written. */check?: boolean; /** Name of the folder that holds the features. Default `"features"`. */
|
|
127
141
|
features?: string; /** True to also write `strings.en-XA.ts`, the pseudo-locale, from the `"en"` messages. */
|
|
128
142
|
pseudo?: boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Layers walked next to the features: folder under `root` to the name its keys take.
|
|
145
|
+
* `{ shared: "ui" }` reads `<root>/shared/strings/<locale>.json` exactly as a feature's
|
|
146
|
+
* `strings/` is read. A folder is one name, without "/", "\" or ".". Default `{}`: features
|
|
147
|
+
* only.
|
|
148
|
+
*/
|
|
149
|
+
layers?: Readonly<Record<string, string>>;
|
|
129
150
|
};
|
|
130
151
|
/**
|
|
131
|
-
* Walks `features/*/strings/<locale>.json` of a game
|
|
132
|
-
* generated modules: the types module `strings.ts` and one
|
|
133
|
-
* `strings.en-XA.ts` with `pseudo`. A check run writes
|
|
134
|
-
* would change; it checks `strings.en-XA.ts` only with
|
|
152
|
+
* Walks `features/*/strings/<locale>.json` of a game and the `strings/` of every layer, compiles
|
|
153
|
+
* every message and writes the generated modules: the types module `strings.ts` and one
|
|
154
|
+
* `strings.<locale>.ts` per locale, plus `strings.en-XA.ts` with `pseudo`. A check run writes
|
|
155
|
+
* nothing and only reports whether something would change; it checks `strings.en-XA.ts` only with
|
|
156
|
+
* `pseudo`.
|
|
135
157
|
*
|
|
136
158
|
* @param root - Game source root, the folder that holds the features.
|
|
137
159
|
* @param out - The generated directory the modules are written into.
|
|
138
|
-
* @param options - Whether this is a check run, what the features folder is called,
|
|
139
|
-
*
|
|
160
|
+
* @param options - Whether this is a check run, what the features folder is called, whether the
|
|
161
|
+
* pseudo-locale is written, and the layers.
|
|
140
162
|
* @returns Whether an output differed, the locales, the keys and the notes.
|
|
141
|
-
* @throws {Error} One error that lists every problem the compile found,
|
|
142
|
-
* no feature brings an `en` string file
|
|
163
|
+
* @throws {Error} One error that lists every problem the compile found, the pseudo error when
|
|
164
|
+
* no feature or layer brings an `en` string file, or the layer error when a layer folder is not
|
|
165
|
+
* one folder name: nothing is read then.
|
|
143
166
|
* @example
|
|
144
167
|
* ```ts
|
|
145
168
|
* // A dev build also writes the pseudo-locale, derived from the English messages.
|
|
146
169
|
* const report = await compileStrings("src", "src/generated", { pseudo: true });
|
|
147
170
|
* // report.locales: ["en", "en-XA", "ru"], report.changed: true on the first run
|
|
171
|
+
* // A v15 game: features/board/strings/en.json { "board.full": "Full" } and the layer file
|
|
172
|
+
* // shared/strings/en.json { "ui.ok": "OK" } compile together.
|
|
173
|
+
* const layered = await compileStrings("src", "src/generated", { layers: { shared: "ui" } });
|
|
174
|
+
* // layered.keys: ["board.full", "ui.ok"]
|
|
148
175
|
* ```
|
|
149
176
|
*/
|
|
150
177
|
declare function compileStrings(root: string, out: string, options?: CompileOptions): Promise<CompileReport>;
|
|
151
178
|
/**
|
|
152
179
|
* Tells whether the generated modules of a game are current, without writing anything. The
|
|
153
|
-
* `--check` run of `bun run assets:keys` covers the strings with it.
|
|
180
|
+
* `--check` run of `bun run assets:keys` covers the strings with it. It walks the features only: a
|
|
181
|
+
* game with layers checks through `runCli` with `--check --layer …`.
|
|
154
182
|
*
|
|
155
183
|
* @param root - Game source root, the folder that holds the features.
|
|
156
184
|
* @param out - The generated directory the modules live in.
|
|
@@ -164,17 +192,27 @@ declare function compileStrings(root: string, out: string, options?: CompileOpti
|
|
|
164
192
|
declare function checkStrings(root: string, out: string): Promise<boolean>;
|
|
165
193
|
//#endregion
|
|
166
194
|
//#region src/plugins/i18n/compile/exchange.d.ts
|
|
195
|
+
/** A layer map: folder under the root to the name its keys take. */
|
|
196
|
+
type Layers = Readonly<Record<string, string>>;
|
|
167
197
|
/**
|
|
168
198
|
* What an export and an import are told beyond their two paths.
|
|
169
199
|
*
|
|
170
200
|
* @example
|
|
171
201
|
* ```ts
|
|
172
202
|
* const options: ExchangeOptions = { source: "ru" }; // the translators read the Russian text
|
|
203
|
+
* // A v15 game: the keys of shared/strings/ go out and come back with the rest.
|
|
204
|
+
* const layered: ExchangeOptions = { source: "ru", layers: { shared: "ui" } };
|
|
173
205
|
* ```
|
|
174
206
|
*/
|
|
175
207
|
type ExchangeOptions = {
|
|
176
208
|
/** The locale translators read from, written as `source` beside each text. Default `"en"`. */source?: string; /** Name of the folder that holds the features. Default `"features"`. */
|
|
177
209
|
features?: string;
|
|
210
|
+
/**
|
|
211
|
+
* Layers read next to the features: folder under `root` to the name its keys take.
|
|
212
|
+
* `{ shared: "ui" }` exports the keys of `<root>/shared/strings/` and imports their texts back
|
|
213
|
+
* into that folder. A folder is one name, without "/", "\" or ".". Default `{}`: features only.
|
|
214
|
+
*/
|
|
215
|
+
layers?: Layers;
|
|
178
216
|
};
|
|
179
217
|
/**
|
|
180
218
|
* What an import is told: the exchange options and the compile that runs after the files are
|
|
@@ -211,20 +249,21 @@ type ExportReport = {
|
|
|
211
249
|
*/
|
|
212
250
|
type ImportReport = {
|
|
213
251
|
/** Every locale an exchange file was read for, sorted. */locales: readonly string[]; /** How many keys were written. */
|
|
214
|
-
keys: number; /** The string files of the features
|
|
252
|
+
keys: number; /** The string files of the features and layers rewritten, relative to the root, sorted. */
|
|
215
253
|
files: readonly string[];
|
|
216
254
|
};
|
|
217
255
|
/**
|
|
218
|
-
* Writes the files translators work in: one `<dir>/<locale>.json` per locale the features
|
|
219
|
-
* the source locale included, so a new language starts as a copy of `en.json`. Every
|
|
220
|
-
* game is in every file, sorted: `{ text, source, note? }`, with `text: ""` where the
|
|
221
|
-
* message yet. The game tree is not touched, and a second run writes the same bytes.
|
|
256
|
+
* Writes the files translators work in: one `<dir>/<locale>.json` per locale the features and
|
|
257
|
+
* layers bring, the source locale included, so a new language starts as a copy of `en.json`. Every
|
|
258
|
+
* key of the game is in every file, sorted: `{ text, source, note? }`, with `text: ""` where the
|
|
259
|
+
* locale has no message yet. The game tree is not touched, and a second run writes the same bytes.
|
|
222
260
|
*
|
|
223
261
|
* @param root - Game source root, the folder that holds the features.
|
|
224
262
|
* @param dir - The folder the exchange files are written into; created when missing.
|
|
225
|
-
* @param options - The source locale
|
|
263
|
+
* @param options - The source locale, the name of the features folder and the layers.
|
|
226
264
|
* @returns The exported locales and how many keys each one lacks.
|
|
227
|
-
* @throws {Error} When the game's strings do not compile,
|
|
265
|
+
* @throws {Error} When the game's strings do not compile, a layer folder is not one folder name,
|
|
266
|
+
* or no feature brings the source locale.
|
|
228
267
|
* @example
|
|
229
268
|
* ```ts
|
|
230
269
|
* // Before a release, the game hands its strings to the translators.
|
|
@@ -235,21 +274,26 @@ type ImportReport = {
|
|
|
235
274
|
declare function exportStrings(root: string, dir: string, options?: ExchangeOptions): Promise<ExportReport>;
|
|
236
275
|
/**
|
|
237
276
|
* Takes translated exchange files back into the game: every `<dir>/<locale>.json` is checked
|
|
238
|
-
* against the game first, then each new text is written into the string file of the feature
|
|
239
|
-
* owns its key, and the strings are compiled into `out` as a dev run does. An empty text
|
|
240
|
-
* text equal to the current message are skipped. With any problem nothing is written.
|
|
277
|
+
* against the game first, then each new text is written into the string file of the feature or
|
|
278
|
+
* layer that owns its key, and the strings are compiled into `out` as a dev run does. An empty text
|
|
279
|
+
* and a text equal to the current message are skipped. With any problem nothing is written.
|
|
241
280
|
*
|
|
242
281
|
* @param root - Game source root, the folder that holds the features.
|
|
243
282
|
* @param dir - The folder the translators handed back.
|
|
244
|
-
* @param options - The features folder, where the compile writes, and whether it
|
|
283
|
+
* @param options - The features folder, the layers, where the compile writes, and whether it
|
|
284
|
+
* writes `en-XA`.
|
|
245
285
|
* @returns The locales read, how many keys were written and the files rewritten.
|
|
246
|
-
* @throws {Error} One error that lists every problem of the exchange files,
|
|
247
|
-
*
|
|
286
|
+
* @throws {Error} One error that lists every problem of the exchange files, the layer error
|
|
287
|
+
* before anything is read when a layer folder is not one folder name, or the compile's own error
|
|
288
|
+
* after the files are written (a parameter kind that differs across locales).
|
|
248
289
|
* @example
|
|
249
290
|
* ```ts
|
|
250
291
|
* // The translators handed back translations/ru.json with two hud texts filled in.
|
|
251
292
|
* await importStrings("src", "translations", { out: "src/generated" });
|
|
252
293
|
* // { locales: ["ru"], keys: 2, files: ["features/hud/strings/ru.json"] }
|
|
294
|
+
* // A v15 game: the translated ui.ok lands in the layer's own file.
|
|
295
|
+
* await importStrings("src", "translations", { out: "src/generated", layers: { shared: "ui" } });
|
|
296
|
+
* // { locales: ["ru"], keys: 1, files: ["shared/strings/ru.json"] }
|
|
253
297
|
* ```
|
|
254
298
|
*/
|
|
255
299
|
declare function importStrings(root: string, dir: string, options?: ImportOptions): Promise<ImportReport>;
|
|
@@ -331,7 +375,19 @@ declare function packAssets(options: PackOptions): Promise<PackResult>;
|
|
|
331
375
|
//#endregion
|
|
332
376
|
//#region src/plugins/assets/scan/scan.d.ts
|
|
333
377
|
/**
|
|
334
|
-
* What one scan is told: where the features are and where the two generated files
|
|
378
|
+
* What one scan is told: where the features and the layers are and where the two generated files
|
|
379
|
+
* go.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```ts
|
|
383
|
+
* // A v15 game: shared/ is a layer whose assets keep the ui.* keys.
|
|
384
|
+
* const options: ScanOptions = {
|
|
385
|
+
* root: "src",
|
|
386
|
+
* manifest: "public/assets/manifest.json",
|
|
387
|
+
* keys: "src/generated/assets.ts",
|
|
388
|
+
* layers: { shared: "ui" }
|
|
389
|
+
* };
|
|
390
|
+
* ```
|
|
335
391
|
*/
|
|
336
392
|
type ScanOptions = {
|
|
337
393
|
/** Path of the game source root, the folder that holds the features. */root: string; /** Name of the folder that holds the features. Default `"features"`. */
|
|
@@ -339,6 +395,12 @@ type ScanOptions = {
|
|
|
339
395
|
manifest: string; /** Path of the generated key module to write. */
|
|
340
396
|
keys: string; /** False for a check run: nothing is written. Default true. */
|
|
341
397
|
write?: boolean;
|
|
398
|
+
/**
|
|
399
|
+
* Layers scanned next to the features: folder under `root` to the name its keys and its default
|
|
400
|
+
* bundle take. `{ shared: "ui" }` reads `<root>/shared/assets.ts` and `<root>/shared/assets/`
|
|
401
|
+
* exactly as `features/ui/` is read, so every key stays `ui.*`. Default `{}`: features only.
|
|
402
|
+
*/
|
|
403
|
+
layers?: Readonly<Record<string, string>>;
|
|
342
404
|
};
|
|
343
405
|
/**
|
|
344
406
|
* What a scan produced.
|
|
@@ -350,19 +412,21 @@ type ScanResult = {
|
|
|
350
412
|
notes: readonly string[];
|
|
351
413
|
};
|
|
352
414
|
/**
|
|
353
|
-
* Walks the features of a game and writes its two generated files: one bundle per
|
|
354
|
-
* by
|
|
415
|
+
* Walks the features and the layers of a game and writes its two generated files: one bundle per
|
|
416
|
+
* feature or layer, split by its optional `assets.ts`, every file keyed by the key rule. A layer is
|
|
417
|
+
* read like one more feature under its mapped name, after the features. A check run
|
|
355
418
|
* (`write: false`) writes nothing and only reports whether something would change.
|
|
356
419
|
*
|
|
357
|
-
* @param options - The game source root, the two output paths and whether to write.
|
|
420
|
+
* @param options - The game source root, the layers, the two output paths and whether to write.
|
|
358
421
|
* @returns The manifest, the text of the key module and whether an output differed.
|
|
359
|
-
* @throws {Error} One error that lists every problem the scan found.
|
|
422
|
+
* @throws {Error} One error that lists every problem the scan found, the layer problems first.
|
|
360
423
|
* @example
|
|
361
424
|
* ```ts
|
|
362
425
|
* const { manifest, changed } = await scanAssets({
|
|
363
426
|
* root: "src",
|
|
364
427
|
* manifest: "public/assets/manifest.json",
|
|
365
|
-
* keys: "src/generated/assets.ts"
|
|
428
|
+
* keys: "src/generated/assets.ts",
|
|
429
|
+
* layers: { shared: "ui" } // shared/assets/button/primary.png keeps the key "ui.button.primary"
|
|
366
430
|
* });
|
|
367
431
|
* // manifest.bundles.ui.files[0].key: "ui.button.primary", changed: true on the first run
|
|
368
432
|
* ```
|