@dreamboard-games/cli 0.1.30-alpha.4 → 0.1.30-alpha.40
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 +32 -113
- package/dist/agent-verifier/agent-workspace-verifier.mjs +2084 -57
- package/dist/agent-verifier/agent-workspace-verifier.mjs.map +1 -1
- package/dist/agent-verifier/{chunk-XQXDOBYB.mjs → chunk-4I2WWAPK.mjs} +27 -10
- package/dist/agent-verifier/chunk-4I2WWAPK.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-C3VW3DTA.mjs → chunk-BWBN2TDJ.mjs} +535 -633
- package/dist/agent-verifier/chunk-BWBN2TDJ.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-TAEQKBJB.mjs → chunk-GWRZRWCF.mjs} +1 -1
- package/dist/agent-verifier/chunk-GWRZRWCF.mjs.map +1 -0
- package/dist/agent-verifier/chunk-HUBV22JQ.mjs +89 -0
- package/dist/agent-verifier/chunk-HUBV22JQ.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-MW2QIWWA.mjs → chunk-KAA3B4DI.mjs} +215 -223
- package/dist/agent-verifier/chunk-KAA3B4DI.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-27EEIZCI.mjs → chunk-KDAQ4CZY.mjs} +34 -27
- package/dist/agent-verifier/chunk-KDAQ4CZY.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-IAYRNVUC.mjs → chunk-LMW66VBH.mjs} +2 -13
- package/dist/agent-verifier/{chunk-IAYRNVUC.mjs.map → chunk-LMW66VBH.mjs.map} +1 -1
- package/dist/agent-verifier/{chunk-776W3UGV.mjs → chunk-LROY5SN2.mjs} +7 -45
- package/dist/agent-verifier/chunk-LROY5SN2.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-H76MT5UR.mjs → chunk-M7UVBANQ.mjs} +2 -1
- package/dist/agent-verifier/chunk-M7UVBANQ.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-5NYBTZB4.mjs → chunk-MIRGCMUC.mjs} +112 -26
- package/dist/agent-verifier/chunk-MIRGCMUC.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-NAK77WXW.mjs → chunk-MYMVXTZT.mjs} +4 -5
- package/dist/agent-verifier/chunk-MYMVXTZT.mjs.map +1 -0
- package/dist/agent-verifier/chunk-OJFZVGEL.mjs +492 -0
- package/dist/agent-verifier/chunk-OJFZVGEL.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-XKCJBIRY.mjs → chunk-QD4SQNUP.mjs} +2 -2
- package/dist/agent-verifier/{chunk-QBAF7EYR.mjs → chunk-TTB7AIHZ.mjs} +4 -4
- package/dist/agent-verifier/{chunk-QBAF7EYR.mjs.map → chunk-TTB7AIHZ.mjs.map} +1 -1
- package/dist/agent-verifier/{chunk-F2DIOJJZ.mjs → chunk-XCQQIPCO.mjs} +5 -46
- package/dist/agent-verifier/chunk-XCQQIPCO.mjs.map +1 -0
- package/dist/agent-verifier/{global-config-NYCSCAUI.mjs → global-config-2NUESNEQ.mjs} +5 -5
- package/dist/agent-verifier/{keychain-backend-A3MRWLPF.mjs → keychain-backend-FF4I6ODB.mjs} +11 -6
- package/dist/agent-verifier/keychain-backend-FF4I6ODB.mjs.map +1 -0
- package/dist/agent-verifier/{local-files-QVJ2H3MH.mjs → local-files-OF4QFISU.mjs} +8 -8
- package/dist/agent-verifier/{chunk-UIOLGH4A.mjs → local-typecheck-DHVLM37Z.mjs} +4 -4
- package/dist/agent-verifier/local-typecheck-DHVLM37Z.mjs.map +1 -0
- package/dist/agent-verifier/{materialize-workspace-OZKOQCSQ.mjs → materialize-workspace-JBDL6LF4.mjs} +22 -22
- package/dist/agent-verifier/materialize-workspace-JBDL6LF4.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-Z6OZWUIZ.mjs → reducer-bundle-preflight-GLUJKTWU.mjs} +75 -24
- package/dist/agent-verifier/reducer-bundle-preflight-GLUJKTWU.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-YDIOW2BO.mjs → reducer-contract-preflight-WVQQPW5F.mjs} +7 -6
- package/dist/agent-verifier/reducer-contract-preflight-WVQQPW5F.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-ON62IGWK.mjs → reducer-native-test-harness-XQUPIT5D.mjs} +480 -703
- package/dist/agent-verifier/reducer-native-test-harness-XQUPIT5D.mjs.map +1 -0
- package/dist/agent-verifier/static-scaffold-U5DXE23S.mjs +24 -0
- package/dist/agent-verifier/{workspace-codegen-WPZHMATU.mjs → workspace-codegen-SPPVHURX.mjs} +3 -3
- package/dist/agent-verifier/{workspace-dependencies-B6A2ZX55.mjs → workspace-dependencies-5HEEKZFP.mjs} +5 -3
- package/dist/authoring-compatibility-internal.js +12 -0
- package/dist/chunk-5IYJOVUA.js +3902 -0
- package/dist/chunk-5IYJOVUA.js.map +1 -0
- package/dist/chunk-6NYVJYN4.js +313 -0
- package/dist/chunk-6NYVJYN4.js.map +1 -0
- package/dist/chunk-EQNBQVIW.js +204 -0
- package/dist/chunk-EQNBQVIW.js.map +1 -0
- package/dist/{chunk-M4SCKH5M.js → chunk-USZAPMQ4.js} +2488 -4993
- package/dist/chunk-USZAPMQ4.js.map +1 -0
- package/dist/{global-config-YBFEGJQG.js → global-config-RBMW7IVA.js} +3 -2
- package/dist/index.js +3099 -6188
- package/dist/index.js.map +1 -1
- package/dist/internal.js +35 -9
- package/dist/internal.js.map +1 -1
- package/dist/{keychain-backend-JHTXAKWC.js → keychain-backend-FSNTNTZE.js} +11 -6
- package/dist/keychain-backend-FSNTNTZE.js.map +1 -0
- package/package.json +9 -19
- package/release/authoring-release-set.json +38 -0
- package/skills/dreamboard/SKILL.md +32 -30
- package/skills/dreamboard/references/building-your-first-game.md +16 -16
- package/skills/dreamboard/references/cli.md +54 -54
- package/skills/dreamboard/references/manifest-authoring.md +11 -3
- package/skills/dreamboard/references/quickstart.md +19 -16
- package/skills/dreamboard/references/testing.md +6 -13
- package/dist/agent-verifier/chunk-27EEIZCI.mjs.map +0 -1
- package/dist/agent-verifier/chunk-5NYBTZB4.mjs.map +0 -1
- package/dist/agent-verifier/chunk-776W3UGV.mjs.map +0 -1
- package/dist/agent-verifier/chunk-C3VW3DTA.mjs.map +0 -1
- package/dist/agent-verifier/chunk-F2DIOJJZ.mjs.map +0 -1
- package/dist/agent-verifier/chunk-G42BGGG2.mjs +0 -70
- package/dist/agent-verifier/chunk-G42BGGG2.mjs.map +0 -1
- package/dist/agent-verifier/chunk-H76MT5UR.mjs.map +0 -1
- package/dist/agent-verifier/chunk-IDVQXGAO.mjs +0 -222
- package/dist/agent-verifier/chunk-IDVQXGAO.mjs.map +0 -1
- package/dist/agent-verifier/chunk-JO5AMVZU.mjs +0 -1744
- package/dist/agent-verifier/chunk-JO5AMVZU.mjs.map +0 -1
- package/dist/agent-verifier/chunk-KDBSVLCF.mjs +0 -624
- package/dist/agent-verifier/chunk-KDBSVLCF.mjs.map +0 -1
- package/dist/agent-verifier/chunk-MW2QIWWA.mjs.map +0 -1
- package/dist/agent-verifier/chunk-NAK77WXW.mjs.map +0 -1
- package/dist/agent-verifier/chunk-ON62IGWK.mjs.map +0 -1
- package/dist/agent-verifier/chunk-QZH6IEZS.mjs +0 -39
- package/dist/agent-verifier/chunk-QZH6IEZS.mjs.map +0 -1
- package/dist/agent-verifier/chunk-TAEQKBJB.mjs.map +0 -1
- package/dist/agent-verifier/chunk-UIOLGH4A.mjs.map +0 -1
- package/dist/agent-verifier/chunk-XQXDOBYB.mjs.map +0 -1
- package/dist/agent-verifier/chunk-YDIOW2BO.mjs.map +0 -1
- package/dist/agent-verifier/chunk-Z6OZWUIZ.mjs.map +0 -1
- package/dist/agent-verifier/compile-576O7TYP.mjs +0 -312
- package/dist/agent-verifier/compile-576O7TYP.mjs.map +0 -1
- package/dist/agent-verifier/keychain-backend-A3MRWLPF.mjs.map +0 -1
- package/dist/agent-verifier/local-typecheck-2JWG5IGL.mjs +0 -10
- package/dist/agent-verifier/materialize-workspace-OZKOQCSQ.mjs.map +0 -1
- package/dist/agent-verifier/reducer-bundle-preflight-7NYZF5ZT.mjs +0 -20
- package/dist/agent-verifier/reducer-contract-preflight-COD2CO22.mjs +0 -11
- package/dist/agent-verifier/reducer-native-test-harness-QC7HZUK4.mjs +0 -50
- package/dist/agent-verifier/static-scaffold-JBUE3ROP.mjs +0 -27
- package/dist/agent-verifier/sync-C6S3OGCD.mjs +0 -588
- package/dist/agent-verifier/sync-C6S3OGCD.mjs.map +0 -1
- package/dist/agent-verifier/test-Y5UGQV7J.mjs +0 -353
- package/dist/agent-verifier/test-Y5UGQV7J.mjs.map +0 -1
- package/dist/agent-verifier/workspace-codegen-WPZHMATU.mjs.map +0 -1
- package/dist/agent-verifier/workspace-dependencies-B6A2ZX55.mjs.map +0 -1
- package/dist/chunk-3NRROR4P.js +0 -432
- package/dist/chunk-3NRROR4P.js.map +0 -1
- package/dist/chunk-M4SCKH5M.js.map +0 -1
- package/dist/dev-host/components/drawer.tsx +0 -132
- package/dist/dev-host/components/input.tsx +0 -21
- package/dist/dev-host/dev-api-proxy-plugin.ts +0 -328
- package/dist/dev-host/dev-author-dom-warnings.ts +0 -100
- package/dist/dev-host/dev-diagnostics.ts +0 -62
- package/dist/dev-host/dev-fallback-stylesheet.ts +0 -53
- package/dist/dev-host/dev-hmr-guard-plugin.ts +0 -47
- package/dist/dev-host/dev-host-controller.ts +0 -674
- package/dist/dev-host/dev-host-player-query.ts +0 -17
- package/dist/dev-host/dev-host-session-transport.ts +0 -52
- package/dist/dev-host/dev-host-storage.ts +0 -56
- package/dist/dev-host/dev-log-relay-plugin.ts +0 -510
- package/dist/dev-host/dev-runtime-config.ts +0 -14
- package/dist/dev-host/dev-runtime-platform.ts +0 -335
- package/dist/dev-host/dev-virtual-modules-plugin.ts +0 -64
- package/dist/dev-host/host-main.css +0 -224
- package/dist/dev-host/host-main.tsx +0 -948
- package/dist/dev-host/index.html +0 -56
- package/dist/dev-host/lib/utils.ts +0 -6
- package/dist/dev-host/plugin-main.ts +0 -61
- package/dist/dev-host/plugin.html +0 -24
- package/dist/dev-host/shared-styles.css +0 -144
- package/dist/dev-host/start-dev-server.ts +0 -140
- package/dist/dev-host/virtual-modules.d.ts +0 -27
- package/dist/global-config-YBFEGJQG.js.map +0 -1
- package/dist/keychain-backend-JHTXAKWC.js.map +0 -1
- package/skills/dreamboard/scripts/events-extract.mjs +0 -218
- /package/dist/agent-verifier/{chunk-XKCJBIRY.mjs.map → chunk-QD4SQNUP.mjs.map} +0 -0
- /package/dist/agent-verifier/{global-config-NYCSCAUI.mjs.map → global-config-2NUESNEQ.mjs.map} +0 -0
- /package/dist/agent-verifier/{local-files-QVJ2H3MH.mjs.map → local-files-OF4QFISU.mjs.map} +0 -0
- /package/dist/agent-verifier/{local-typecheck-2JWG5IGL.mjs.map → static-scaffold-U5DXE23S.mjs.map} +0 -0
- /package/dist/agent-verifier/{reducer-bundle-preflight-7NYZF5ZT.mjs.map → workspace-codegen-SPPVHURX.mjs.map} +0 -0
- /package/dist/agent-verifier/{reducer-contract-preflight-COD2CO22.mjs.map → workspace-dependencies-5HEEKZFP.mjs.map} +0 -0
- /package/dist/{agent-verifier/reducer-native-test-harness-QC7HZUK4.mjs.map → authoring-compatibility-internal.js.map} +0 -0
- /package/dist/{agent-verifier/static-scaffold-JBUE3ROP.mjs.map → global-config-RBMW7IVA.js.map} +0 -0
- /package/{dist/scaffold → scaffold}/assets/static/app/tsconfig.framework.json +0 -0
- /package/{dist/scaffold → scaffold}/assets/static/app/tsconfig.json +0 -0
- /package/{dist/scaffold → scaffold}/assets/static/ui/index.tsx +0 -0
- /package/{dist/scaffold → scaffold}/assets/static/ui/style.css +0 -0
- /package/{dist/scaffold → scaffold}/assets/static/ui/tsconfig.framework.json +0 -0
- /package/{dist/scaffold → scaffold}/assets/static/ui/tsconfig.json +0 -0
|
@@ -1,19 +1,55 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
importTypeScriptModule
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QD4SQNUP.mjs";
|
|
5
5
|
import {
|
|
6
6
|
external_exports
|
|
7
7
|
} from "./chunk-JZTH3EMV.mjs";
|
|
8
|
+
import "./chunk-TTB7AIHZ.mjs";
|
|
9
|
+
import "./chunk-H6XDQJ3N.mjs";
|
|
8
10
|
|
|
9
11
|
// src/services/project/reducer-bundle-preflight.ts
|
|
10
12
|
import path from "path";
|
|
11
|
-
import {
|
|
12
|
-
import "
|
|
13
|
-
import { materializeManifestTable } from "@dreamboard-games/sdk/codegen";
|
|
13
|
+
import { createRequire } from "module";
|
|
14
|
+
import { pathToFileURL } from "url";
|
|
14
15
|
globalThis.__DREAMBOARD_AUTHORING_WARNINGS__ = true;
|
|
15
16
|
var REDUCER_BUNDLE_ENTRY_PATH = path.join("app", "index.ts");
|
|
16
17
|
var PREFLIGHT_RNG_SEED = 1337;
|
|
18
|
+
function isStructuralPerPlayer(value) {
|
|
19
|
+
return typeof value === "object" && value !== null && value.__perPlayer === true && Array.isArray(value.entries);
|
|
20
|
+
}
|
|
21
|
+
function fallbackPerPlayerSchema(valueSchema, options) {
|
|
22
|
+
const playerSchema = options.players.length > 0 ? external_exports.enum(options.players) : external_exports.string();
|
|
23
|
+
return external_exports.object({
|
|
24
|
+
__perPlayer: external_exports.literal(true),
|
|
25
|
+
entries: external_exports.array(external_exports.tuple([playerSchema, valueSchema]))
|
|
26
|
+
}).strict();
|
|
27
|
+
}
|
|
28
|
+
async function loadProjectReducerPreflightModules(projectRoot) {
|
|
29
|
+
const requireFromProject = createRequire(
|
|
30
|
+
path.join(projectRoot, "package.json")
|
|
31
|
+
);
|
|
32
|
+
const reducerPath = requireFromProject.resolve(
|
|
33
|
+
"@dreamboard-games/sdk/reducer"
|
|
34
|
+
);
|
|
35
|
+
const reducerContractPath = requireFromProject.resolve(
|
|
36
|
+
"@dreamboard-games/sdk/reducer-contract"
|
|
37
|
+
);
|
|
38
|
+
const [reducerModule, reducerContractModule] = await Promise.all([
|
|
39
|
+
import(pathToFileURL(reducerPath).href),
|
|
40
|
+
import(pathToFileURL(reducerContractPath).href)
|
|
41
|
+
]);
|
|
42
|
+
if (typeof reducerModule.isPerPlayer !== "function" || typeof reducerModule.perPlayerSchema !== "function" || typeof reducerContractModule.materializeManifestTable !== "function") {
|
|
43
|
+
throw new Error(
|
|
44
|
+
"Installed @dreamboard-games/sdk does not expose the reducer preflight helpers required by this CLI."
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
isPerPlayer: reducerModule.isPerPlayer,
|
|
49
|
+
perPlayerSchema: reducerModule.perPlayerSchema,
|
|
50
|
+
materializeManifestTable: reducerContractModule.materializeManifestTable
|
|
51
|
+
};
|
|
52
|
+
}
|
|
17
53
|
function buildPlayerIds(playerCount) {
|
|
18
54
|
const ids = [];
|
|
19
55
|
for (let index = 1; index <= playerCount; index += 1) {
|
|
@@ -58,12 +94,15 @@ function summarizeError(error) {
|
|
|
58
94
|
}
|
|
59
95
|
return { headline: String(error ?? "Unknown failure") };
|
|
60
96
|
}
|
|
61
|
-
function assertViewPerPlayerSeatsValid(view, expectedPlayerIds,
|
|
97
|
+
function assertViewPerPlayerSeatsValid(view, expectedPlayerIds, helpers = {
|
|
98
|
+
isPerPlayer: isStructuralPerPlayer,
|
|
99
|
+
perPlayerSchema: fallbackPerPlayerSchema
|
|
100
|
+
}, breadcrumb = []) {
|
|
62
101
|
if (view === null || view === void 0) {
|
|
63
102
|
return null;
|
|
64
103
|
}
|
|
65
|
-
if (isPerPlayer(view)) {
|
|
66
|
-
const schema = perPlayerSchema(external_exports.unknown(), {
|
|
104
|
+
if (helpers.isPerPlayer(view)) {
|
|
105
|
+
const schema = helpers.perPlayerSchema(external_exports.unknown(), {
|
|
67
106
|
players: expectedPlayerIds
|
|
68
107
|
});
|
|
69
108
|
const result = schema.safeParse(view);
|
|
@@ -80,6 +119,7 @@ function assertViewPerPlayerSeatsValid(view, expectedPlayerIds, breadcrumb = [])
|
|
|
80
119
|
const result = assertViewPerPlayerSeatsValid(
|
|
81
120
|
view[index],
|
|
82
121
|
expectedPlayerIds,
|
|
122
|
+
helpers,
|
|
83
123
|
[...breadcrumb, `[${index}]`]
|
|
84
124
|
);
|
|
85
125
|
if (result) return result;
|
|
@@ -90,10 +130,12 @@ function assertViewPerPlayerSeatsValid(view, expectedPlayerIds, breadcrumb = [])
|
|
|
90
130
|
for (const [key, value] of Object.entries(
|
|
91
131
|
view
|
|
92
132
|
)) {
|
|
93
|
-
const result = assertViewPerPlayerSeatsValid(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
133
|
+
const result = assertViewPerPlayerSeatsValid(
|
|
134
|
+
value,
|
|
135
|
+
expectedPlayerIds,
|
|
136
|
+
helpers,
|
|
137
|
+
[...breadcrumb, key]
|
|
138
|
+
);
|
|
97
139
|
if (result) return result;
|
|
98
140
|
}
|
|
99
141
|
return null;
|
|
@@ -104,7 +146,7 @@ function identityShuffle(values) {
|
|
|
104
146
|
return [...values];
|
|
105
147
|
}
|
|
106
148
|
async function driveReducerBundleThroughScenarios(options) {
|
|
107
|
-
const { manifest, bundle, scenarios } = options;
|
|
149
|
+
const { manifest, bundle, scenarios, preflightModules } = options;
|
|
108
150
|
const rngSeed = options.rngSeed ?? PREFLIGHT_RNG_SEED;
|
|
109
151
|
const failures = [];
|
|
110
152
|
const tableCache = /* @__PURE__ */ new Map();
|
|
@@ -115,7 +157,7 @@ async function driveReducerBundleThroughScenarios(options) {
|
|
|
115
157
|
const playerIds2 = buildPlayerIds(scenario.playerCount);
|
|
116
158
|
const table2 = JSON.parse(
|
|
117
159
|
JSON.stringify(
|
|
118
|
-
materializeManifestTable({
|
|
160
|
+
preflightModules.materializeManifestTable({
|
|
119
161
|
manifest,
|
|
120
162
|
playerIds: playerIds2,
|
|
121
163
|
shuffleItems: identityShuffle
|
|
@@ -185,7 +227,11 @@ async function driveReducerBundleThroughScenarios(options) {
|
|
|
185
227
|
});
|
|
186
228
|
continue;
|
|
187
229
|
}
|
|
188
|
-
const mismatch = assertViewPerPlayerSeatsValid(
|
|
230
|
+
const mismatch = assertViewPerPlayerSeatsValid(
|
|
231
|
+
seat.view,
|
|
232
|
+
playerIds,
|
|
233
|
+
preflightModules
|
|
234
|
+
);
|
|
189
235
|
if (mismatch) {
|
|
190
236
|
failures.push({
|
|
191
237
|
scenario,
|
|
@@ -214,8 +260,8 @@ async function runReducerBundleSmoke(options) {
|
|
|
214
260
|
const summary = summarizeError(error);
|
|
215
261
|
throw new Error(
|
|
216
262
|
[
|
|
217
|
-
`Dreamboard could not import \`${REDUCER_BUNDLE_ENTRY_PATH}
|
|
218
|
-
"Fix the reducer bundle entry so it can be imported locally, then
|
|
263
|
+
`Dreamboard could not import \`${REDUCER_BUNDLE_ENTRY_PATH}\`.`,
|
|
264
|
+
"Fix the reducer bundle entry so it can be imported locally, then rerun the command.",
|
|
219
265
|
`Original error: ${summary.headline}`
|
|
220
266
|
].join(" ")
|
|
221
267
|
);
|
|
@@ -229,7 +275,13 @@ async function runReducerBundleSmoke(options) {
|
|
|
229
275
|
].join(" ")
|
|
230
276
|
);
|
|
231
277
|
}
|
|
232
|
-
|
|
278
|
+
const preflightModules = await loadProjectReducerPreflightModules(projectRoot);
|
|
279
|
+
return driveReducerBundleThroughScenarios({
|
|
280
|
+
manifest,
|
|
281
|
+
bundle,
|
|
282
|
+
scenarios,
|
|
283
|
+
preflightModules
|
|
284
|
+
});
|
|
233
285
|
}
|
|
234
286
|
function formatFailureLines(failures) {
|
|
235
287
|
return failures.map((failure) => {
|
|
@@ -244,18 +296,17 @@ async function assertReducerBundleSmoke(options) {
|
|
|
244
296
|
}
|
|
245
297
|
throw new Error(
|
|
246
298
|
[
|
|
247
|
-
"Reducer bundle preflight failed
|
|
248
|
-
"Fix the reported scenarios locally before
|
|
299
|
+
"Reducer bundle preflight failed.",
|
|
300
|
+
"Fix the reported scenarios locally before building or starting dev:",
|
|
249
301
|
formatFailureLines(failures)
|
|
250
302
|
].join("\n")
|
|
251
303
|
);
|
|
252
304
|
}
|
|
253
|
-
|
|
254
305
|
export {
|
|
255
|
-
|
|
306
|
+
assertReducerBundleSmoke,
|
|
256
307
|
assertViewPerPlayerSeatsValid,
|
|
308
|
+
buildScenarios,
|
|
257
309
|
driveReducerBundleThroughScenarios,
|
|
258
|
-
runReducerBundleSmoke
|
|
259
|
-
assertReducerBundleSmoke
|
|
310
|
+
runReducerBundleSmoke
|
|
260
311
|
};
|
|
261
|
-
//# sourceMappingURL=
|
|
312
|
+
//# sourceMappingURL=reducer-bundle-preflight-GLUJKTWU.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/project/reducer-bundle-preflight.ts"],"sourcesContent":["import path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { pathToFileURL } from \"node:url\";\nimport type {\n GameTopologyManifest,\n SetupProfileSpec,\n} from \"@dreamboard-games/sdk/types\";\nimport { z } from \"zod\";\nimport { importTypeScriptModule } from \"../../utils/ts-module-loader.js\";\n\nnamespace Wire {\n export type JsonValue =\n | null\n | boolean\n | number\n | string\n | JsonValue[]\n | { [key: string]: JsonValue };\n export type ReducerSessionState = Record<string, unknown>;\n export type SeatProjection = { view: unknown };\n export type SeatProjectionBundle = {\n seats?: Record<string, SeatProjection | undefined>;\n };\n}\n\n// Opt in to SDK authoring warnings (e.g. concrete dependent-choice defaults).\n// Trusted reducer code cannot read process.env, so the SDK gates authoring\n// warnings on this host-set global instead.\n(globalThis as Record<string, unknown>).__DREAMBOARD_AUTHORING_WARNINGS__ =\n true;\n\n/**\n * Path to the reducer bundle entry, relative to the project root. Matches\n * the scaffold produced by `dreamboard new`.\n */\nconst REDUCER_BUNDLE_ENTRY_PATH = path.join(\"app\", \"index.ts\");\n\n/**\n * Deterministic rng seed used to drive the reducer during preflight.\n * Kept stable so local preflight failures reproduce across CLI runs.\n */\nconst PREFLIGHT_RNG_SEED = 1337;\n\n/**\n * Phase of the preflight smoke test that a failure occurred in.\n */\nexport type ReducerBundleSmokePhase =\n | \"BUILD_GAME_STATE\"\n | \"INITIALIZE\"\n | \"PROJECT_SEATS\"\n | \"VALIDATE_VIEW\";\n\nexport interface ReducerBundleSmokeScenario {\n readonly setupProfileId: string | null;\n readonly playerCount: number;\n}\n\nexport interface ReducerBundleSmokeFailure {\n readonly scenario: ReducerBundleSmokeScenario;\n readonly phase: ReducerBundleSmokePhase;\n readonly playerId?: string;\n readonly headline: string;\n readonly detail?: string;\n}\n\n/**\n * Shape of a single seat's slice in `projectSeatsDynamic(...)`. Only `view`\n * is consumed by the preflight, but the full wire DTO keeps local tests\n * aligned with the canonical reducer boundary.\n */\nexport type ReducerBundleSeatProjection = Wire.SeatProjection;\n\n/** Result of calling `bundle.projectSeatsDynamic({ state, playerIds })`. */\nexport type ReducerBundleSeatProjectionBundle = Wire.SeatProjectionBundle;\n\n/**\n * Minimal structural shape the preflight needs from the authored reducer\n * bundle. Matches the subset of `createReducerBundle(game)` used by the\n * reducer runtime.\n */\nexport type ReducerBundleLike = Pick<\n {\n initialize(input: {\n table: Wire.JsonValue;\n playerIds: readonly string[];\n rngSeed?: number | null;\n setup?: unknown;\n }): unknown | Promise<unknown>;\n projectSeatsDynamic(input: {\n state: unknown;\n playerIds: readonly string[];\n }): ReducerBundleSeatProjectionBundle;\n },\n \"initialize\" | \"projectSeatsDynamic\"\n>;\n\ntype PerPlayerValidationHelpers = {\n isPerPlayer(value: unknown): boolean;\n perPlayerSchema(\n valueSchema: z.ZodTypeAny,\n options: { players: readonly string[] },\n ): z.ZodTypeAny;\n};\n\ntype ProjectReducerPreflightModules = PerPlayerValidationHelpers & {\n materializeManifestTable(input: {\n manifest: GameTopologyManifest;\n playerIds: readonly string[];\n shuffleItems<Value>(values: readonly Value[]): Value[];\n }): unknown;\n};\n\nfunction isStructuralPerPlayer(value: unknown): boolean {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as { __perPlayer?: unknown }).__perPlayer === true &&\n Array.isArray((value as { entries?: unknown }).entries)\n );\n}\n\nfunction fallbackPerPlayerSchema(\n valueSchema: z.ZodTypeAny,\n options: { players: readonly string[] },\n): z.ZodTypeAny {\n const playerSchema =\n options.players.length > 0\n ? z.enum(options.players as [string, ...string[]])\n : z.string();\n return z\n .object({\n __perPlayer: z.literal(true),\n entries: z.array(z.tuple([playerSchema, valueSchema])),\n })\n .strict();\n}\n\nasync function loadProjectReducerPreflightModules(\n projectRoot: string,\n): Promise<ProjectReducerPreflightModules> {\n const requireFromProject = createRequire(\n path.join(projectRoot, \"package.json\"),\n );\n const reducerPath = requireFromProject.resolve(\n \"@dreamboard-games/sdk/reducer\",\n );\n const reducerContractPath = requireFromProject.resolve(\n \"@dreamboard-games/sdk/reducer-contract\",\n );\n const [reducerModule, reducerContractModule] = (await Promise.all([\n import(pathToFileURL(reducerPath).href),\n import(pathToFileURL(reducerContractPath).href),\n ])) as [\n Partial<PerPlayerValidationHelpers>,\n { materializeManifestTable?: unknown },\n ];\n\n if (\n typeof reducerModule.isPerPlayer !== \"function\" ||\n typeof reducerModule.perPlayerSchema !== \"function\" ||\n typeof reducerContractModule.materializeManifestTable !== \"function\"\n ) {\n throw new Error(\n \"Installed @dreamboard-games/sdk does not expose the reducer preflight helpers required by this CLI.\",\n );\n }\n\n return {\n isPerPlayer: reducerModule.isPerPlayer,\n perPlayerSchema: reducerModule.perPlayerSchema,\n materializeManifestTable:\n reducerContractModule.materializeManifestTable as ProjectReducerPreflightModules[\"materializeManifestTable\"],\n };\n}\n\nfunction buildPlayerIds(playerCount: number): string[] {\n const ids: string[] = [];\n for (let index = 1; index <= playerCount; index += 1) {\n ids.push(`player-${index}`);\n }\n return ids;\n}\n\n/**\n * Build the matrix of scenarios to drive. Exported for tests so we can\n * assert scenario generation without loading a full reducer bundle.\n */\nexport function buildScenarios(\n manifest: GameTopologyManifest,\n): ReducerBundleSmokeScenario[] {\n const rawCounts = [\n manifest.players?.minPlayers,\n manifest.players?.maxPlayers,\n ].filter(\n (count): count is number =>\n typeof count === \"number\" && Number.isFinite(count) && count > 0,\n );\n const playerCounts = Array.from(new Set(rawCounts));\n if (playerCounts.length === 0) {\n return [];\n }\n const profiles: SetupProfileSpec[] = manifest.setupProfiles ?? [];\n const profileIds: Array<string | null> =\n profiles.length > 0 ? profiles.map((profile) => profile.id) : [null];\n\n const scenarios: ReducerBundleSmokeScenario[] = [];\n const seen = new Set<string>();\n for (const profileId of profileIds) {\n for (const count of playerCounts) {\n const key = `${profileId ?? \"<default>\"}:${count}`;\n if (seen.has(key)) continue;\n seen.add(key);\n scenarios.push({ setupProfileId: profileId, playerCount: count });\n }\n }\n return scenarios;\n}\n\nfunction describeScenario(scenario: ReducerBundleSmokeScenario): string {\n const profileDesc = scenario.setupProfileId\n ? `setup profile '${scenario.setupProfileId}'`\n : \"no setup profile\";\n return `${profileDesc}, ${scenario.playerCount} player${\n scenario.playerCount === 1 ? \"\" : \"s\"\n }`;\n}\n\nfunction summarizeError(error: unknown): { headline: string; detail?: string } {\n if (error instanceof Error) {\n const firstLine =\n error.message\n .split(\"\\n\")\n .map((line) => line.trim())\n .find((line) => line.length > 0) ?? \"Unknown failure\";\n const detail =\n error.stack && error.stack !== error.message ? error.stack : undefined;\n return { headline: firstLine, detail };\n }\n return { headline: String(error ?? \"Unknown failure\") };\n}\n\n/**\n * Walk `view` recursively and, for every embedded `PerPlayer<T>` shape,\n * assert its seat list matches `expectedPlayerIds` using\n * `perPlayerSchema({ players })`. Returns `null` on success, or a headline\n * describing the first mismatch.\n *\n * This catches the class of bug where an author returns a `PerPlayer<T>`\n * that was built from the wrong seat list (e.g. a manifest-derived\n * `maxPlayers` literal union) while the runtime session has a different\n * number of seats. The Zod bound schema produces an identical error shape\n * to the one the backend raises in production so authors see the same\n * diagnostic locally.\n */\nexport function assertViewPerPlayerSeatsValid(\n view: unknown,\n expectedPlayerIds: readonly string[],\n helpers: PerPlayerValidationHelpers = {\n isPerPlayer: isStructuralPerPlayer,\n perPlayerSchema: fallbackPerPlayerSchema,\n },\n breadcrumb: string[] = [],\n): string | null {\n if (view === null || view === undefined) {\n return null;\n }\n\n if (helpers.isPerPlayer(view)) {\n const schema = helpers.perPlayerSchema(z.unknown(), {\n players: expectedPlayerIds as never,\n });\n const result = schema.safeParse(view);\n if (!result.success) {\n const firstIssue = result.error.issues[0];\n const location =\n breadcrumb.length > 0 ? ` at view.${breadcrumb.join(\".\")}` : \"\";\n const message = firstIssue?.message ?? \"PerPlayer seat mismatch\";\n return `PerPlayer seat mismatch${location}: ${message}`;\n }\n return null;\n }\n\n if (Array.isArray(view)) {\n for (let index = 0; index < view.length; index += 1) {\n const result = assertViewPerPlayerSeatsValid(\n view[index],\n expectedPlayerIds,\n helpers,\n [...breadcrumb, `[${index}]`],\n );\n if (result) return result;\n }\n return null;\n }\n\n if (typeof view === \"object\") {\n for (const [key, value] of Object.entries(\n view as Record<string, unknown>,\n )) {\n const result = assertViewPerPlayerSeatsValid(\n value,\n expectedPlayerIds,\n helpers,\n [...breadcrumb, key],\n );\n if (result) return result;\n }\n return null;\n }\n\n return null;\n}\n\nfunction identityShuffle<Value>(values: readonly Value[]): Value[] {\n return [...values];\n}\n\n/**\n * Drive an already-loaded reducer bundle through the provided scenarios.\n * Shared between the full `runReducerBundleSmoke` entrypoint and the\n * unit tests, which feed a fake bundle directly.\n *\n * For each (setup profile × player count) scenario this:\n *\n * 1. materializes an initial table via `materializeManifestTable`,\n * 2. calls `bundle.initialize({ table, playerIds, rngSeed, setup })`,\n * 3. calls `bundle.projectSeatsDynamic({ state, playerIds })` once, and\n * 4. validates any embedded `PerPlayer<T>` views match the runtime seat\n * list using `perPlayerSchema({ players: playerIds })`.\n *\n * Failures are collected instead of thrown so authors get the full list\n * of broken scenarios in one preflight pass.\n */\nexport async function driveReducerBundleThroughScenarios(options: {\n manifest: GameTopologyManifest;\n bundle: ReducerBundleLike;\n scenarios: readonly ReducerBundleSmokeScenario[];\n preflightModules: ProjectReducerPreflightModules;\n rngSeed?: number;\n}): Promise<ReducerBundleSmokeFailure[]> {\n const { manifest, bundle, scenarios, preflightModules } = options;\n const rngSeed = options.rngSeed ?? PREFLIGHT_RNG_SEED;\n\n const failures: ReducerBundleSmokeFailure[] = [];\n const tableCache = new Map<\n number,\n { table: unknown; playerIds: string[] } | { error: unknown }\n >();\n\n for (const scenario of scenarios) {\n let tableEntry = tableCache.get(scenario.playerCount);\n if (!tableEntry) {\n try {\n const playerIds = buildPlayerIds(scenario.playerCount);\n // JSON-roundtrip the materialized table to mirror the backend wire\n // boundary: real flows serialize the table over HTTP, which drops\n // explicit `undefined` property values (e.g. optional card text) that\n // the bundle's strict JSON state schema would otherwise reject.\n const table: unknown = JSON.parse(\n JSON.stringify(\n preflightModules.materializeManifestTable({\n manifest,\n playerIds,\n shuffleItems: identityShuffle,\n }),\n ),\n );\n tableEntry = { table, playerIds };\n } catch (error) {\n tableEntry = { error };\n }\n tableCache.set(scenario.playerCount, tableEntry);\n }\n if (\"error\" in tableEntry) {\n const summary = summarizeError(tableEntry.error);\n failures.push({\n scenario,\n phase: \"BUILD_GAME_STATE\",\n headline: summary.headline,\n detail: summary.detail,\n });\n continue;\n }\n\n const { table, playerIds } = tableEntry;\n\n let sessionState: unknown;\n try {\n sessionState = await bundle.initialize({\n table: table as Wire.JsonValue,\n playerIds: [...playerIds],\n rngSeed,\n setup: scenario.setupProfileId\n ? { profileId: scenario.setupProfileId, optionValues: {} }\n : null,\n });\n } catch (error) {\n const summary = summarizeError(error);\n failures.push({\n scenario,\n phase: \"INITIALIZE\",\n headline: summary.headline,\n detail: summary.detail,\n });\n continue;\n }\n\n let projection: ReducerBundleSeatProjectionBundle | undefined;\n try {\n projection = bundle.projectSeatsDynamic({\n state: sessionState as Wire.ReducerSessionState,\n playerIds: [...playerIds],\n });\n } catch (error) {\n const summary = summarizeError(error);\n failures.push({\n scenario,\n phase: \"PROJECT_SEATS\",\n headline: summary.headline,\n detail: summary.detail,\n });\n continue;\n }\n\n const seats = projection?.seats ?? {};\n for (const playerId of playerIds) {\n const seat = seats[playerId];\n if (!seat) {\n failures.push({\n scenario,\n phase: \"PROJECT_SEATS\",\n playerId,\n headline: `projectSeatsDynamic() did not return an entry for seat '${playerId}'.`,\n });\n continue;\n }\n const mismatch = assertViewPerPlayerSeatsValid(\n seat.view,\n playerIds,\n preflightModules,\n );\n if (mismatch) {\n failures.push({\n scenario,\n phase: \"VALIDATE_VIEW\",\n playerId,\n headline: mismatch,\n });\n }\n }\n }\n\n return failures;\n}\n\n/**\n * Import the authored reducer bundle from `projectRoot/app/index.ts` and\n * drive it through every (setup profile × player count) scenario the\n * manifest declares. Returns the collected failures without throwing so\n * callers can decide whether to surface them.\n */\nexport async function runReducerBundleSmoke(options: {\n projectRoot: string;\n manifest: GameTopologyManifest;\n}): Promise<ReducerBundleSmokeFailure[]> {\n const { projectRoot, manifest } = options;\n const scenarios = buildScenarios(manifest);\n if (scenarios.length === 0) {\n return [];\n }\n\n const entryPath = path.join(projectRoot, REDUCER_BUNDLE_ENTRY_PATH);\n let module: { default?: ReducerBundleLike };\n try {\n module = await importTypeScriptModule<{ default?: ReducerBundleLike }>(\n entryPath,\n );\n } catch (error) {\n const summary = summarizeError(error);\n throw new Error(\n [\n `Dreamboard could not import \\`${REDUCER_BUNDLE_ENTRY_PATH}\\`.`,\n \"Fix the reducer bundle entry so it can be imported locally, then rerun the command.\",\n `Original error: ${summary.headline}`,\n ].join(\" \"),\n );\n }\n const bundle = module.default;\n if (!bundle || typeof bundle.initialize !== \"function\") {\n throw new Error(\n [\n `\\`${REDUCER_BUNDLE_ENTRY_PATH}\\` does not export a reducer bundle as its default export.`,\n \"Export `createReducerBundle(game)` from `app/index.ts` so the compile pipeline can smoke-test it.\",\n ].join(\" \"),\n );\n }\n\n const preflightModules =\n await loadProjectReducerPreflightModules(projectRoot);\n return driveReducerBundleThroughScenarios({\n manifest,\n bundle,\n scenarios,\n preflightModules,\n });\n}\n\nfunction formatFailureLines(\n failures: readonly ReducerBundleSmokeFailure[],\n): string {\n return failures\n .map((failure) => {\n const location = failure.playerId ? ` (seat ${failure.playerId})` : \"\";\n return `• [${failure.phase}] ${describeScenario(failure.scenario)}${location}: ${failure.headline}`;\n })\n .join(\"\\n\");\n}\n\n/**\n * Preflight wrapper used before build, verify, test, and dev workflows. Runs\n * `runReducerBundleSmoke` and throws an aggregated error if any scenario\n * failed so the author sees every broken seat/profile in one shot.\n *\n * The surrounding workflow already guarantees that the authored contract imports cleanly\n * (via `assertReducerContractPreflight`) and that `tsc --noEmit` is\n * green (via `runLocalTypecheck`) before this runs, so failures from\n * this step are always runtime-shaped (`initialize`/`projectSeatsDynamic` rejecting,\n * `perPlayer` seat mismatches, …) rather than static type or import\n * errors.\n */\nexport async function assertReducerBundleSmoke(options: {\n projectRoot: string;\n manifest: GameTopologyManifest;\n}): Promise<void> {\n const failures = await runReducerBundleSmoke(options);\n if (failures.length === 0) {\n return;\n }\n throw new Error(\n [\n \"Reducer bundle preflight failed.\",\n \"Fix the reported scenarios locally before building or starting dev:\",\n formatFailureLines(failures),\n ].join(\"\\n\"),\n );\n}\n"],"mappings":"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","names":["playerIds","table"]}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
importTypeScriptModule
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QD4SQNUP.mjs";
|
|
5
|
+
import "./chunk-TTB7AIHZ.mjs";
|
|
6
|
+
import "./chunk-H6XDQJ3N.mjs";
|
|
5
7
|
|
|
6
8
|
// src/services/project/reducer-contract-preflight.ts
|
|
7
9
|
import path from "path";
|
|
@@ -22,7 +24,7 @@ async function assertReducerContractPreflight(projectRoot) {
|
|
|
22
24
|
if (isManifestScopedIdBrandingError(message)) {
|
|
23
25
|
throw new Error(
|
|
24
26
|
[
|
|
25
|
-
`Dreamboard could not validate \`${GAME_CONTRACT_ENTRY_PATH}
|
|
27
|
+
`Dreamboard could not validate \`${GAME_CONTRACT_ENTRY_PATH}\`.`,
|
|
26
28
|
"This happens because a state field name looks like a manifest-scoped id, but the schema uses a plain string instead of the manifest-backed id schema.",
|
|
27
29
|
"Workaround: use `gameContract.schemas.<id>` (or `manifest.ids.<id>`) for manifest ids. If the field is intentionally free-form text, rename it so it does not look like a manifest id field.",
|
|
28
30
|
`Original error: ${message}`
|
|
@@ -31,15 +33,14 @@ async function assertReducerContractPreflight(projectRoot) {
|
|
|
31
33
|
}
|
|
32
34
|
throw new Error(
|
|
33
35
|
[
|
|
34
|
-
`Dreamboard could not validate \`${GAME_CONTRACT_ENTRY_PATH}
|
|
35
|
-
"Fix the authored reducer contract module so it can be imported locally, then
|
|
36
|
+
`Dreamboard could not validate \`${GAME_CONTRACT_ENTRY_PATH}\`.`,
|
|
37
|
+
"Fix the authored reducer contract module so it can be imported locally, then rerun the command.",
|
|
36
38
|
`Original error: ${message}`
|
|
37
39
|
].join(" ")
|
|
38
40
|
);
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
|
-
|
|
42
43
|
export {
|
|
43
44
|
assertReducerContractPreflight
|
|
44
45
|
};
|
|
45
|
-
//# sourceMappingURL=
|
|
46
|
+
//# sourceMappingURL=reducer-contract-preflight-WVQQPW5F.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/project/reducer-contract-preflight.ts"],"sourcesContent":["import path from \"node:path\";\nimport { importTypeScriptModule } from \"../../utils/ts-module-loader.js\";\n\nconst GAME_CONTRACT_ENTRY_PATH = path.join(\"app\", \"game-contract.ts\");\n\nfunction normalizeErrorMessage(error: unknown): string {\n const rawMessage =\n error instanceof Error ? error.message : String(error ?? \"Unknown error\");\n return (\n rawMessage\n .split(\"\\n\")\n .map((line) => line.trim())\n .find(Boolean)\n ?.replace(/^Error:\\s*/u, \"\") ?? \"Unknown error\"\n );\n}\n\nfunction isManifestScopedIdBrandingError(message: string): boolean {\n return (\n message.includes(\"defineGameContract:\") &&\n message.includes(\"manifest-scoped\") &&\n (message.includes(\"uses a raw z.string()\") ||\n message.includes(\"uses z.array(z.string())\"))\n );\n}\n\nexport async function assertReducerContractPreflight(\n projectRoot: string,\n): Promise<void> {\n const entryPath = path.join(projectRoot, GAME_CONTRACT_ENTRY_PATH);\n\n try {\n await importTypeScriptModule(entryPath);\n } catch (error) {\n const message = normalizeErrorMessage(error);\n if (isManifestScopedIdBrandingError(message)) {\n throw new Error(\n [\n `Dreamboard could not validate \\`${GAME_CONTRACT_ENTRY_PATH}\\`.`,\n \"This happens because a state field name looks like a manifest-scoped id, but the schema uses a plain string instead of the manifest-backed id schema.\",\n \"Workaround: use `gameContract.schemas.<id>` (or `manifest.ids.<id>`) for manifest ids. If the field is intentionally free-form text, rename it so it does not look like a manifest id field.\",\n `Original error: ${message}`,\n ].join(\" \"),\n );\n }\n\n throw new Error(\n [\n `Dreamboard could not validate \\`${GAME_CONTRACT_ENTRY_PATH}\\`.`,\n \"Fix the authored reducer contract module so it can be imported locally, then rerun the command.\",\n `Original error: ${message}`,\n ].join(\" \"),\n );\n }\n}\n"],"mappings":";;;;;;;;AAAA,OAAO,UAAU;AAGjB,IAAM,2BAA2B,KAAK,KAAK,OAAO,kBAAkB;AAEpE,SAAS,sBAAsB,OAAwB;AACrD,QAAM,aACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,SAAS,eAAe;AAC1E,SACE,WACG,MAAM,IAAI,EACV,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,KAAK,OAAO,GACX,QAAQ,eAAe,EAAE,KAAK;AAEtC;AAEA,SAAS,gCAAgC,SAA0B;AACjE,SACE,QAAQ,SAAS,qBAAqB,KACtC,QAAQ,SAAS,iBAAiB,MACjC,QAAQ,SAAS,uBAAuB,KACvC,QAAQ,SAAS,0BAA0B;AAEjD;AAEA,eAAsB,+BACpB,aACe;AACf,QAAM,YAAY,KAAK,KAAK,aAAa,wBAAwB;AAEjE,MAAI;AACF,UAAM,uBAAuB,SAAS;AAAA,EACxC,SAAS,OAAO;AACd,UAAM,UAAU,sBAAsB,KAAK;AAC3C,QAAI,gCAAgC,OAAO,GAAG;AAC5C,YAAM,IAAI;AAAA,QACR;AAAA,UACE,mCAAmC,wBAAwB;AAAA,UAC3D;AAAA,UACA;AAAA,UACA,mBAAmB,OAAO;AAAA,QAC5B,EAAE,KAAK,GAAG;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,IAAI;AAAA,MACR;AAAA,QACE,mCAAmC,wBAAwB;AAAA,QAC3D;AAAA,QACA,mBAAmB,OAAO;AAAA,MAC5B,EAAE,KAAK,GAAG;AAAA,IACZ;AAAA,EACF;AACF;","names":[]}
|