@moku-labs/game 0.14.12 → 0.14.13
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 +13 -12
- package/dist/app/page.d.mts +8 -3
- package/dist/app/page.mjs +57 -12
- package/dist/app/system.d.mts +5 -3
- package/dist/app/system.mjs +2 -0
- package/dist/app.d.mts +15 -7
- package/dist/app.mjs +131 -27
- package/dist/{assets-BrKSg1O6.mjs → assets-CEMfBogh.mjs} +471 -120
- package/dist/assets.d.mts +30 -13
- package/dist/assets.mjs +1 -1
- package/dist/cli.d.mts +105 -8
- package/dist/cli.mjs +1036 -128
- package/dist/{commands-BaCx2B9j.d.mts → commands-DAETmK86.d.mts} +43 -7
- package/dist/{config-CdARrrhU.mjs → config-B87aFTW-.mjs} +25 -4
- package/dist/control.d.mts +130 -17
- package/dist/control.mjs +4 -4
- package/dist/{define-Ce8SVEN-.d.mts → define-BASd9ZUh.d.mts} +32 -4
- package/dist/dev-DbHgx-R-.mjs +89 -0
- package/dist/{fake-MpzwZhIZ.mjs → fake-6mazmHK3.mjs} +20 -2
- package/dist/features-DowEilZm.mjs +266 -0
- package/dist/{headless-CMHNsKjW.d.mts → headless-cFveciuY.d.mts} +1 -1
- package/dist/hot.d.mts +4 -2
- package/dist/hot.mjs +7 -4
- package/dist/{index-CLQ8NOTw.d.mts → index-DedbED3T.d.mts} +317 -69
- package/dist/index.d.mts +5 -6
- package/dist/index.mjs +3 -3
- package/dist/inspect.d.mts +12 -7
- 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 +8 -3
- package/dist/lint.mjs +432 -20
- package/dist/project.d.mts +15 -1
- package/dist/project.mjs +1 -1
- package/dist/{run-Bf2hKyjZ.mjs → run-BbipFRc6.mjs} +250 -51
- package/dist/{runtime-BCnKn0xf.d.mts → runtime-DoSlRx8X.d.mts} +1 -1
- package/dist/{session-DgukhR_7.mjs → session-CeKgO2hy.mjs} +30 -2
- package/dist/{sources-Duzj6lhV.mjs → sources-Cdvb0rOS.mjs} +33 -6
- package/dist/{src-CtC8w3_z.mjs → src-BEbJ_sSx.mjs} +35536 -17789
- package/dist/testing.d.mts +23 -13
- package/dist/testing.mjs +10 -6
- package/dist/{types-DOlpeuGx.d.mts → types-7GXcXxxv.d.mts} +174 -242
- package/dist/{types-BjTtGSFb.d.mts → types-BGcda5Le.d.mts} +4459 -732
- package/dist/{types-gisvSHoC.d.mts → types-C73hbmxi.d.mts} +129 -17
- package/dist/{types-CAPv9l29.d.mts → types-DngFQJro.d.mts} +43 -5
- package/dist/{types-Y_rCuXtj.d.mts → types-GHE4J5Uf.d.mts} +1025 -191
- package/dist/{visual-dMW8iqAE.mjs → visual-2m4wJL_z.mjs} +111 -7
- package/dist/visual-_XhoGeIC.d.mts +345 -0
- package/dist/visual.d.mts +1 -332
- package/dist/visual.mjs +130 -20
- package/dist/{watch-CWI_on4T.mjs → watch-BEdrp80i.mjs} +149 -30
- package/llms.txt +99 -48
- package/package.json +8 -6
- package/dist/dev-Cc50Dk7H.mjs +0 -47
- package/dist/memory-pUQ7YZWC.d.mts +0 -50
- package/dist/types-BX4Ge_j5.d.mts +0 -656
package/dist/testing.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as createApp } from "./index-
|
|
3
|
-
import {
|
|
4
|
-
import { a as createHeadless, i as ReproResult, n as HeadlessGame, o as runRepro, r as Repro, s as stepFrames, t as HeadlessApp } from "./headless-
|
|
1
|
+
import { $n as NodeFx, In as FeaturePlugin, Jn as Descriptor, Qn as Hint, Rn as AnyFlow, Wn as NodeTable, ir as FakeClock, nr as ClockSource, ur as Json } from "./types-BGcda5Le.mjs";
|
|
2
|
+
import { t as createApp } from "./index-DedbED3T.mjs";
|
|
3
|
+
import { b as saveOf, v as WithGameState, y as memory } from "./types-C73hbmxi.mjs";
|
|
4
|
+
import { a as createHeadless, i as ReproResult, n as HeadlessGame, o as runRepro, r as Repro, s as stepFrames, t as HeadlessApp } from "./headless-cFveciuY.mjs";
|
|
5
5
|
import { AnyPluginInstance } from "@moku-labs/core";
|
|
6
6
|
|
|
7
7
|
//#region src/plugins/clock/fake.d.ts
|
|
@@ -160,12 +160,12 @@ type StubsOf<Nodes extends NodeTable> = { readonly [Name in keyof Nodes & string
|
|
|
160
160
|
*
|
|
161
161
|
* @example
|
|
162
162
|
* ```ts
|
|
163
|
-
* const options: IsolateOptions<typeof boardFlow.nodes> = {
|
|
163
|
+
* const options: IsolateOptions<typeof boardFlow.nodes, Player> = {
|
|
164
164
|
* flow: boardFlow, shared: sharedLayer, stubs: { settings: stub("closed") }, player: fresh
|
|
165
165
|
* };
|
|
166
166
|
* ```
|
|
167
167
|
*/
|
|
168
|
-
type IsolateOptions<Nodes extends NodeTable> = {
|
|
168
|
+
type IsolateOptions<Nodes extends NodeTable, Player extends Json = Json, Session extends Json = Json> = {
|
|
169
169
|
/** The feature's flow. It becomes the one node of the harness main flow, named by `as`. */flow: AnyFlow & {
|
|
170
170
|
readonly nodes: Nodes;
|
|
171
171
|
};
|
|
@@ -182,9 +182,9 @@ type IsolateOptions<Nodes extends NodeTable> = {
|
|
|
182
182
|
as?: string; /** The shared layer, composed as `logicOnly` before the feature. */
|
|
183
183
|
shared?: FeaturePlugin; /** Node name of `flow` to the stub that replaces it. A node not listed runs for real. */
|
|
184
184
|
stubs?: StubsOf<Nodes>; /** More plugins the feature needs headless, for example a feature-own plugin. */
|
|
185
|
-
plugins?: readonly AnyPluginInstance[]; /** The player a new save starts from. */
|
|
186
|
-
player:
|
|
187
|
-
session?:
|
|
185
|
+
plugins?: readonly AnyPluginInstance[]; /** The player a new save starts from. Its type types `model.store.snapshot().player`. */
|
|
186
|
+
player: Player; /** The session at start. `{}` by default. Its type types `model.store.snapshot().session`. */
|
|
187
|
+
session?: Session; /** The rng seed. `1` by default. */
|
|
188
188
|
seed?: number;
|
|
189
189
|
};
|
|
190
190
|
/**
|
|
@@ -206,6 +206,12 @@ type IsolateSeams = {
|
|
|
206
206
|
* plugins on it.
|
|
207
207
|
*/
|
|
208
208
|
type IsolatedApp = ReturnType<typeof createApp>;
|
|
209
|
+
/**
|
|
210
|
+
* The app of an isolated feature with `model.store.snapshot()` typed by the player and session
|
|
211
|
+
* of the `isolate` call, as `WithGameState` types `game.headless()`. A call whose player and
|
|
212
|
+
* session are `Model.Json` reads a `Model.Json` snapshot, as before. Only the type.
|
|
213
|
+
*/
|
|
214
|
+
type IsolatedAppOf<Player, Session> = WithGameState<IsolatedApp, Player, Session>;
|
|
209
215
|
/**
|
|
210
216
|
* A stub: the replaced node or sub-flow ends at once with this outcome. Written as a sub-flow of
|
|
211
217
|
* one transit node, so a route can still substitute it for one visit:
|
|
@@ -223,14 +229,16 @@ type IsolatedApp = ReturnType<typeof createApp>;
|
|
|
223
229
|
declare function stub<const Name extends string>(outcome: Name, payload?: Json): Stub<Name>;
|
|
224
230
|
/**
|
|
225
231
|
* Composes one feature without the rest of the game: the shared layer and the feature as
|
|
226
|
-
* `logicOnly
|
|
232
|
+
* `logicOnly` (a parent feature is composed with its sub-features), the feature's flow inside a
|
|
233
|
+
* harness main flow `isolated`, and every stubbed node
|
|
227
234
|
* replaced by a sub-flow that ends with the stub's outcome. Every exit of the flow lands on the
|
|
228
235
|
* rest node `exited`, whose intent `again` enters the flow once more. Paths read as in the game:
|
|
229
236
|
* the harness holds the flow under `options.as`, its id by default. A node that is not stubbed
|
|
230
237
|
* runs for real, even when it belongs to a feature that is not composed.
|
|
231
238
|
*
|
|
232
239
|
* @param feature - The feature under test.
|
|
233
|
-
* @param options - Its flow, the shared layer, the stubs, the starting state.
|
|
240
|
+
* @param options - Its flow, the shared layer, the stubs, the starting state. The types of
|
|
241
|
+
* `player` and `session` type the app's `model.store.snapshot()`.
|
|
234
242
|
* @returns A factory of apps, not started; pass one to `createHeadless`.
|
|
235
243
|
* @throws {Error} For a stub key that is not a node of the flow, or an outcome the node does not declare.
|
|
236
244
|
* @example
|
|
@@ -239,11 +247,13 @@ declare function stub<const Name extends string>(outcome: Name, payload?: Json):
|
|
|
239
247
|
* const homeOnly = isolate(homeFeature, {
|
|
240
248
|
* flow: mainFlow, stubs: { info: stub("ok") }, player: startingPlayer, session: startingSession
|
|
241
249
|
* });
|
|
242
|
-
* const
|
|
250
|
+
* const app = homeOnly();
|
|
251
|
+
* const game = await createHeadless(app);
|
|
243
252
|
* const state = await game.walk([{ at: "main/home", intent: "info" }]);
|
|
244
253
|
* state.path; // "main/home"
|
|
254
|
+
* app.model.store.snapshot().player.count; // 0, typed number: startingPlayer types the snapshot
|
|
245
255
|
* ```
|
|
246
256
|
*/
|
|
247
|
-
declare function isolate<Nodes extends NodeTable>(feature: FeaturePlugin, options: IsolateOptions<Nodes>): (seams?: IsolateSeams) =>
|
|
257
|
+
declare function isolate<Nodes extends NodeTable, Player extends Json = Json, Session extends Json = Json>(feature: FeaturePlugin, options: IsolateOptions<Nodes, Player, Session>): (seams?: IsolateSeams) => IsolatedAppOf<Player, Session>;
|
|
248
258
|
//#endregion
|
|
249
259
|
export { type FakeFx, type FakeFxOptions, type HeadlessApp, type HeadlessGame, type IsolateOptions, type IsolateSeams, type Repro, type ReproResult, type Stub, type StubsOf, createHeadless, fakeClock, fakeFx, isolate, memory, runRepro, saveOf, stepFrames, stub };
|
package/dist/testing.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $t as refuseStart, en as exit, p as flattenFeatures, rn as type, t as createApp } from "./src-BEbJ_sSx.mjs";
|
|
2
2
|
import { n as saveOf, t as memory } from "./memory-CWlqhS7l.mjs";
|
|
3
|
-
import { t as fakeClock } from "./fake-
|
|
3
|
+
import { t as fakeClock } from "./fake-6mazmHK3.mjs";
|
|
4
4
|
import { i as stepFrames, r as runRepro, t as createHeadless } from "./headless-BA6ffzqD.mjs";
|
|
5
5
|
//#region src/testing/fake-fx.ts
|
|
6
6
|
/** The node path a refused `fx.start` names when the test gives none. */
|
|
@@ -235,14 +235,16 @@ function harnessOf(flow, name = flow.id) {
|
|
|
235
235
|
}
|
|
236
236
|
/**
|
|
237
237
|
* Composes one feature without the rest of the game: the shared layer and the feature as
|
|
238
|
-
* `logicOnly
|
|
238
|
+
* `logicOnly` (a parent feature is composed with its sub-features), the feature's flow inside a
|
|
239
|
+
* harness main flow `isolated`, and every stubbed node
|
|
239
240
|
* replaced by a sub-flow that ends with the stub's outcome. Every exit of the flow lands on the
|
|
240
241
|
* rest node `exited`, whose intent `again` enters the flow once more. Paths read as in the game:
|
|
241
242
|
* the harness holds the flow under `options.as`, its id by default. A node that is not stubbed
|
|
242
243
|
* runs for real, even when it belongs to a feature that is not composed.
|
|
243
244
|
*
|
|
244
245
|
* @param feature - The feature under test.
|
|
245
|
-
* @param options - Its flow, the shared layer, the stubs, the starting state.
|
|
246
|
+
* @param options - Its flow, the shared layer, the stubs, the starting state. The types of
|
|
247
|
+
* `player` and `session` type the app's `model.store.snapshot()`.
|
|
246
248
|
* @returns A factory of apps, not started; pass one to `createHeadless`.
|
|
247
249
|
* @throws {Error} For a stub key that is not a node of the flow, or an outcome the node does not declare.
|
|
248
250
|
* @example
|
|
@@ -251,16 +253,18 @@ function harnessOf(flow, name = flow.id) {
|
|
|
251
253
|
* const homeOnly = isolate(homeFeature, {
|
|
252
254
|
* flow: mainFlow, stubs: { info: stub("ok") }, player: startingPlayer, session: startingSession
|
|
253
255
|
* });
|
|
254
|
-
* const
|
|
256
|
+
* const app = homeOnly();
|
|
257
|
+
* const game = await createHeadless(app);
|
|
255
258
|
* const state = await game.walk([{ at: "main/home", intent: "info" }]);
|
|
256
259
|
* state.path; // "main/home"
|
|
260
|
+
* app.model.store.snapshot().player.count; // 0, typed number: startingPlayer types the snapshot
|
|
257
261
|
* ```
|
|
258
262
|
*/
|
|
259
263
|
function isolate(feature, options) {
|
|
260
264
|
const mainFlow = harnessOf(withStubs(options.flow, options.stubs ?? {}), options.as);
|
|
261
265
|
const plugins = [
|
|
262
266
|
...options.shared === void 0 ? [] : [options.shared.logicOnly],
|
|
263
|
-
feature.logicOnly,
|
|
267
|
+
...flattenFeatures([feature.logicOnly]),
|
|
264
268
|
...options.plugins ?? []
|
|
265
269
|
];
|
|
266
270
|
return (seams = {}) => createApp({
|