@moku-labs/game 0.0.1 → 0.0.3

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.
@@ -0,0 +1,77 @@
1
+ import { a as JsxChild, m as UiIntrinsicElements, t as DescriptionNode } from "./types-C0SLQsx0.mjs";
2
+
3
+ //#region src/plugins/ui/jsx/runtime.d.ts
4
+ /** What the compiler passes as props: the children plus whatever the tag declared. */
5
+ type JsxProperties = Record<string, unknown> & {
6
+ children?: JsxChild;
7
+ };
8
+ /**
9
+ * Builds one description node. A string tag becomes an intrinsic, a component definition becomes
10
+ * one node the reconcile expands, and a plain function runs now.
11
+ *
12
+ * @param type - The tag: a string, `Fragment`, a component definition or a plain function.
13
+ * @param props - What the compiler collected, `children` included.
14
+ * @param key - The `key` attribute, passed as the third argument, never inside `props`.
15
+ * @returns The node.
16
+ * @example
17
+ * ```ts
18
+ * jsx("row", { style: { gap: 8 } }, "tabs"); // { type: "row", key: "tabs", props: { style: { gap: 8 } }, children: [] }
19
+ * ```
20
+ */
21
+ declare function jsx(type: unknown, props: JsxProperties, key?: string): DescriptionNode;
22
+ /**
23
+ * The factory for a tag with several static children. The same function as `jsx`.
24
+ */
25
+ declare const jsxs: typeof jsx;
26
+ /**
27
+ * The development factory. The last three arguments are debug information the runtime drops.
28
+ *
29
+ * @param type - The tag.
30
+ * @param props - What the compiler collected.
31
+ * @param key - The `key` attribute.
32
+ * @param _isStatic - Whether the children list is static. Ignored.
33
+ * @param _source - The file and line of the tag. Ignored.
34
+ * @param _self - The `this` of the enclosing scope. Ignored.
35
+ * @returns The node `jsx` builds.
36
+ * @example
37
+ * ```ts
38
+ * jsxDEV("row", {}, "tabs", false, { fileName: "hud.tsx" }, undefined).key; // "tabs"
39
+ * ```
40
+ */
41
+ declare function jsxDEV(type: unknown, props: JsxProperties, key?: string, _isStatic?: boolean, _source?: unknown, _self?: unknown): DescriptionNode;
42
+ /**
43
+ * Groups children without a tag of its own. Its children are lifted into the parent.
44
+ *
45
+ * @param props - The children between the two ends of the fragment.
46
+ * @returns The fragment node, which `flatten` lifts.
47
+ * @example
48
+ * ```ts
49
+ * Fragment({ children: ["a"] }).children.length; // 1
50
+ * ```
51
+ */
52
+ declare function Fragment(props: JsxProperties): DescriptionNode;
53
+ /**
54
+ * The namespace TypeScript reads a `.tsx` file against. A game sets `"jsx": "react-jsx"` and
55
+ * `"jsxImportSource": "@moku-labs/game"`, and both entry files export this namespace.
56
+ */
57
+ declare namespace JSX {
58
+ /** What a tag evaluates to. */
59
+ interface Element extends DescriptionNode {}
60
+ /** The thirteen tags a screen is written with. */
61
+ interface IntrinsicElements extends UiIntrinsicElements {}
62
+ /** The prop children are collected into. */
63
+ interface ElementChildrenAttribute {
64
+ children: unknown;
65
+ }
66
+ /** The attribute every tag takes next to its own props. */
67
+ interface IntrinsicAttributes {
68
+ key?: string;
69
+ }
70
+ /** The same attribute on a component tag. */
71
+ interface IntrinsicClassAttributes<Component> {
72
+ key?: string;
73
+ ref?: Component;
74
+ }
75
+ }
76
+ //#endregion
77
+ export { jsxs as a, jsxDEV as i, JSX as n, jsx as r, Fragment as t };
@@ -0,0 +1,182 @@
1
+ import { n as isComponentDefinition } from "./component-DGg5DqKK.mjs";
2
+ //#region src/plugins/ui/jsx/flatten.ts
3
+ /** The type of the node `Fragment` builds. It never reaches a reconcile: `flatten` lifts it. */
4
+ const FRAGMENT = "#fragment";
5
+ /**
6
+ * Builds the node a bare string or number child becomes.
7
+ *
8
+ * @param content - What stood between the tags.
9
+ * @returns A text node carrying it.
10
+ * @example
11
+ * ```ts
12
+ * textNode(5); // { type: "text", props: { content: "5" }, children: [] }
13
+ * ```
14
+ */
15
+ function textNode(content) {
16
+ return {
17
+ type: "text",
18
+ props: { content: String(content) },
19
+ children: []
20
+ };
21
+ }
22
+ /**
23
+ * Tells a description node from the other things a child may be.
24
+ *
25
+ * @param child - One child of a tag.
26
+ * @returns True when it is a node.
27
+ * @example
28
+ * ```ts
29
+ * isNode({ type: "row", props: {}, children: [] }); // true
30
+ * ```
31
+ */
32
+ function isNode(child) {
33
+ return typeof child === "object" && child !== null && !Array.isArray(child) && "type" in child;
34
+ }
35
+ /**
36
+ * Turns whatever stood between two tags into the children of that tag.
37
+ *
38
+ * @param child - One child, an array of children, or nothing.
39
+ * @returns The children as nodes, fragments lifted and empty values dropped.
40
+ * @example
41
+ * ```ts
42
+ * flatten(["a", undefined, 2]).map(node => node.props.content); // ["a", "2"]
43
+ * ```
44
+ */
45
+ function flatten(child) {
46
+ if (child === null || child === void 0 || typeof child === "boolean") return [];
47
+ if (typeof child === "string" || typeof child === "number") return [textNode(child)];
48
+ if (Array.isArray(child)) {
49
+ const nodes = [];
50
+ for (const item of child) nodes.push(...flatten(item));
51
+ return nodes;
52
+ }
53
+ if (!isNode(child)) return [];
54
+ if (child.type === "#fragment") return [...child.children];
55
+ return [child];
56
+ }
57
+ //#endregion
58
+ //#region src/plugins/ui/jsx/runtime.ts
59
+ /**
60
+ * @file ui/jsx — the JSX runtime itself: the three factories a TypeScript build calls, the
61
+ * fragment, and the `JSX` namespace `"jsxImportSource": "@moku-labs/game"` resolves to. Pure and
62
+ * reachable only through `src/jsx-runtime.ts` and `src/jsx-dev-runtime.ts` (lint L9).
63
+ */
64
+ /**
65
+ * Splits the children out of the props the compiler built, so a node never carries them twice.
66
+ *
67
+ * @param props - What the compiler passed.
68
+ * @returns The props without `children`.
69
+ * @example
70
+ * ```ts
71
+ * withoutChildren({ style: {}, children: "a" }); // { style: {} }
72
+ * ```
73
+ */
74
+ function withoutChildren(props) {
75
+ const rest = { ...props };
76
+ delete rest.children;
77
+ return rest;
78
+ }
79
+ /**
80
+ * Wraps what a plain function component returned so it can stand where one node is expected.
81
+ *
82
+ * @param produced - What the function returned.
83
+ * @param key - The key the tag carried, if any.
84
+ * @returns One node; several results are lifted by the parent's `flatten`.
85
+ */
86
+ function asSingleNode(produced, key) {
87
+ const nodes = flatten(produced);
88
+ const single = nodes.length === 1 ? nodes[0] : void 0;
89
+ if (single === void 0) return {
90
+ type: FRAGMENT,
91
+ props: {},
92
+ children: nodes
93
+ };
94
+ if (key === void 0) return single;
95
+ return {
96
+ ...single,
97
+ key
98
+ };
99
+ }
100
+ /**
101
+ * Builds one description node. A string tag becomes an intrinsic, a component definition becomes
102
+ * one node the reconcile expands, and a plain function runs now.
103
+ *
104
+ * @param type - The tag: a string, `Fragment`, a component definition or a plain function.
105
+ * @param props - What the compiler collected, `children` included.
106
+ * @param key - The `key` attribute, passed as the third argument, never inside `props`.
107
+ * @returns The node.
108
+ * @example
109
+ * ```ts
110
+ * jsx("row", { style: { gap: 8 } }, "tabs"); // { type: "row", key: "tabs", props: { style: { gap: 8 } }, children: [] }
111
+ * ```
112
+ */
113
+ function jsx(type, props, key) {
114
+ const rest = withoutChildren(props);
115
+ if (type === Fragment) return {
116
+ type: FRAGMENT,
117
+ props: rest,
118
+ children: flatten(props.children)
119
+ };
120
+ if (isComponentDefinition(type)) {
121
+ const node = {
122
+ type: type.name,
123
+ props,
124
+ children: []
125
+ };
126
+ return key === void 0 ? node : {
127
+ ...node,
128
+ key
129
+ };
130
+ }
131
+ if (typeof type === "function") return asSingleNode(type(props), key);
132
+ const node = {
133
+ type: String(type),
134
+ props: rest,
135
+ children: flatten(props.children)
136
+ };
137
+ return key === void 0 ? node : {
138
+ ...node,
139
+ key
140
+ };
141
+ }
142
+ /**
143
+ * The factory for a tag with several static children. The same function as `jsx`.
144
+ */
145
+ const jsxs = jsx;
146
+ /**
147
+ * The development factory. The last three arguments are debug information the runtime drops.
148
+ *
149
+ * @param type - The tag.
150
+ * @param props - What the compiler collected.
151
+ * @param key - The `key` attribute.
152
+ * @param _isStatic - Whether the children list is static. Ignored.
153
+ * @param _source - The file and line of the tag. Ignored.
154
+ * @param _self - The `this` of the enclosing scope. Ignored.
155
+ * @returns The node `jsx` builds.
156
+ * @example
157
+ * ```ts
158
+ * jsxDEV("row", {}, "tabs", false, { fileName: "hud.tsx" }, undefined).key; // "tabs"
159
+ * ```
160
+ */
161
+ function jsxDEV(type, props, key, _isStatic, _source, _self) {
162
+ return jsx(type, props, key);
163
+ }
164
+ /**
165
+ * Groups children without a tag of its own. Its children are lifted into the parent.
166
+ *
167
+ * @param props - The children between the two ends of the fragment.
168
+ * @returns The fragment node, which `flatten` lifts.
169
+ * @example
170
+ * ```ts
171
+ * Fragment({ children: ["a"] }).children.length; // 1
172
+ * ```
173
+ */
174
+ function Fragment(props) {
175
+ return {
176
+ type: FRAGMENT,
177
+ props: {},
178
+ children: flatten(props.children)
179
+ };
180
+ }
181
+ //#endregion
182
+ export { jsxs as i, jsx as n, jsxDEV as r, Fragment as t };
@@ -0,0 +1,145 @@
1
+ //#region src/plugins/flow/doors/define.ts
2
+ /** Lowercase-first camelCase words joined by dots, at least two: `game.position`. */
3
+ const idPattern = /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)+$/;
4
+ /**
5
+ * Refuses an id that is not a dotted name.
6
+ *
7
+ * @param kind - `"source"` or `"command"`, for the message.
8
+ * @param id - The id to check.
9
+ * @throws {Error} When the id is not camelCase words joined by dots.
10
+ */
11
+ function checkId(kind, id) {
12
+ if (idPattern.test(id)) return;
13
+ throw new Error(`[game] The ${kind} id "${id}" is not a dotted name.\n Name it like "game.position": camelCase words joined by dots.`);
14
+ }
15
+ /**
16
+ * Declares a source: a read-only view the editor lists, reads and watches. The types flow from
17
+ * the object: the input from `input`, the app from the `read` parameter, the output from its
18
+ * result.
19
+ *
20
+ * @param source - The descriptor.
21
+ * @returns The same descriptor, frozen.
22
+ * @throws {Error} When the id is not a dotted name such as `"game.position"`.
23
+ * @example
24
+ * ```ts
25
+ * // A game's .dev module: the orders on the board, re-read after every edge.
26
+ * export const orders = defineSource({
27
+ * id: "timber.orders",
28
+ * title: "Orders",
29
+ * input: {},
30
+ * changes: "edge",
31
+ * read: app => app.flow.state().path
32
+ * });
33
+ * read(app, orders); // "board/awaitIntent"
34
+ * ```
35
+ */
36
+ function defineSource(source) {
37
+ checkId("source", source.id);
38
+ Object.freeze(source.input);
39
+ return Object.freeze(source);
40
+ }
41
+ /**
42
+ * Declares a command: a dev-only action the editor lists and runs. Its body starts with the
43
+ * inline dev guard, so a production build drops it.
44
+ *
45
+ * @param command - The descriptor.
46
+ * @returns The same descriptor, frozen.
47
+ * @throws {Error} When the id is not a dotted name such as `"game.answer"`.
48
+ * @example
49
+ * ```ts
50
+ * // A game's .dev module: open the shop from anywhere, through the graph.
51
+ * export const openShop = defineCommand({
52
+ * id: "timber.openShop",
53
+ * title: "Open the shop",
54
+ * input: {},
55
+ * effect: "route",
56
+ * run: app => {
57
+ * if (typeof __MOKU_GAME_DEV__ === "undefined" || !__MOKU_GAME_DEV__) throw controlRefused();
58
+ * return app.flow.walk([{ at: "home", intent: "shop" }]);
59
+ * }
60
+ * });
61
+ * (await run(app, openShop)).state.path; // "shop"
62
+ * ```
63
+ */
64
+ function defineCommand(command) {
65
+ checkId("command", command.id);
66
+ Object.freeze(command.input);
67
+ return Object.freeze(command);
68
+ }
69
+ //#endregion
70
+ //#region src/plugins/flow/doors/input.ts
71
+ /** The input of a call that passed none. */
72
+ const noInput = Object.freeze({});
73
+ /**
74
+ * Hands the given input on, or an empty one. `InputArguments` and `WatchInput` let a call leave
75
+ * the input out only when every field of the schema is optional, so `{}` is an input of that
76
+ * schema.
77
+ *
78
+ * @param input - The input of the call, if any.
79
+ * @returns The input to pass to the descriptor.
80
+ * @example
81
+ * ```ts
82
+ * inputOrEmpty<{ last: "number?" }>(undefined); // {}
83
+ * ```
84
+ */
85
+ function inputOrEmpty(input) {
86
+ return input ?? noInput;
87
+ }
88
+ //#endregion
89
+ //#region src/plugins/flow/doors/session.ts
90
+ /** The journal of an app that ran no cheat. */
91
+ const noCheats = Object.freeze([]);
92
+ const sessions = /*#__PURE__*/ new WeakMap();
93
+ /**
94
+ * Tells whether a cheat or a raw command ran on this app.
95
+ *
96
+ * @param app - The app.
97
+ * @returns True once a `cheat` or `raw` command ran.
98
+ * @example
99
+ * ```ts
100
+ * // After run(app, commands.restore, { repro }): a restore is raw.
101
+ * isTainted(app); // true
102
+ * ```
103
+ */
104
+ function isTainted(app) {
105
+ return sessions.get(app)?.tainted ?? false;
106
+ }
107
+ /**
108
+ * Reads the journal of cheat and raw commands of this app, oldest first.
109
+ *
110
+ * @param app - The app.
111
+ * @returns The frozen journal, the same list until the next cheat.
112
+ * @example
113
+ * ```ts
114
+ * // After run(app, commands.restore, { bookmark }) on frame 96.
115
+ * cheatsOf(app); // [{ id: "game.restore", input: { bookmark: { path: "home", ... } }, frame: 96 }]
116
+ * ```
117
+ */
118
+ function cheatsOf(app) {
119
+ return sessions.get(app)?.cheats ?? noCheats;
120
+ }
121
+ /**
122
+ * Taints the session of this app and journals the command. The input is copied, so the caller
123
+ * cannot rewrite the journal afterwards.
124
+ *
125
+ * @param app - The app.
126
+ * @param id - The command id.
127
+ * @param input - The input the command got.
128
+ * @param frame - The frame it runs on.
129
+ */
130
+ function recordCheat(app, id, input, frame) {
131
+ const session = sessions.get(app) ?? {
132
+ tainted: true,
133
+ cheats: noCheats
134
+ };
135
+ const entry = Object.freeze({
136
+ id,
137
+ input: structuredClone(input),
138
+ frame
139
+ });
140
+ session.tainted = true;
141
+ session.cheats = Object.freeze([...session.cheats.slice(-499), entry]);
142
+ sessions.set(app, session);
143
+ }
144
+ //#endregion
145
+ export { defineCommand as a, inputOrEmpty as i, isTainted as n, defineSource as o, recordCheat as r, cheatsOf as t };