@dreamboard-games/cli 0.1.30-alpha.3 → 0.1.30-alpha.31

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.
Files changed (173) hide show
  1. package/README.md +27 -108
  2. package/dist/agent-verifier/agent-workspace-verifier.mjs +1988 -57
  3. package/dist/agent-verifier/agent-workspace-verifier.mjs.map +1 -1
  4. package/dist/agent-verifier/{chunk-XQXDOBYB.mjs → chunk-4I2WWAPK.mjs} +27 -10
  5. package/dist/agent-verifier/chunk-4I2WWAPK.mjs.map +1 -0
  6. package/dist/agent-verifier/{chunk-O4YCPU7C.mjs → chunk-BWBN2TDJ.mjs} +539 -641
  7. package/dist/agent-verifier/chunk-BWBN2TDJ.mjs.map +1 -0
  8. package/dist/agent-verifier/{chunk-TAEQKBJB.mjs → chunk-GWRZRWCF.mjs} +1 -1
  9. package/dist/agent-verifier/chunk-GWRZRWCF.mjs.map +1 -0
  10. package/dist/agent-verifier/chunk-H6XDQJ3N.mjs +11 -0
  11. package/dist/agent-verifier/chunk-HUBV22JQ.mjs +89 -0
  12. package/dist/agent-verifier/chunk-HUBV22JQ.mjs.map +1 -0
  13. package/dist/agent-verifier/{chunk-VS573ERH.mjs → chunk-JZTH3EMV.mjs} +2 -2
  14. package/dist/agent-verifier/{chunk-XGWCY624.mjs → chunk-KDAQ4CZY.mjs} +34 -27
  15. package/dist/agent-verifier/chunk-KDAQ4CZY.mjs.map +1 -0
  16. package/dist/agent-verifier/{chunk-IAYRNVUC.mjs → chunk-LMW66VBH.mjs} +2 -13
  17. package/dist/agent-verifier/{chunk-IAYRNVUC.mjs.map → chunk-LMW66VBH.mjs.map} +1 -1
  18. package/dist/agent-verifier/{chunk-776W3UGV.mjs → chunk-M6YNQZCC.mjs} +4 -13
  19. package/dist/agent-verifier/chunk-M6YNQZCC.mjs.map +1 -0
  20. package/dist/agent-verifier/{chunk-H76MT5UR.mjs → chunk-M7UVBANQ.mjs} +2 -1
  21. package/dist/agent-verifier/chunk-M7UVBANQ.mjs.map +1 -0
  22. package/dist/agent-verifier/{chunk-SH5JKYOB.mjs → chunk-MIRGCMUC.mjs} +112 -26
  23. package/dist/agent-verifier/chunk-MIRGCMUC.mjs.map +1 -0
  24. package/dist/agent-verifier/{chunk-NAK77WXW.mjs → chunk-MYMVXTZT.mjs} +4 -5
  25. package/dist/agent-verifier/chunk-MYMVXTZT.mjs.map +1 -0
  26. package/dist/agent-verifier/{chunk-7WWGFAAU.mjs → chunk-NBRUEJUK.mjs} +215 -223
  27. package/dist/agent-verifier/chunk-NBRUEJUK.mjs.map +1 -0
  28. package/dist/agent-verifier/chunk-OJFZVGEL.mjs +492 -0
  29. package/dist/agent-verifier/chunk-OJFZVGEL.mjs.map +1 -0
  30. package/dist/agent-verifier/{chunk-LUZ7KE6H.mjs → chunk-QD4SQNUP.mjs} +4 -8
  31. package/dist/agent-verifier/{chunk-LUZ7KE6H.mjs.map → chunk-QD4SQNUP.mjs.map} +1 -1
  32. package/dist/agent-verifier/chunk-TTB7AIHZ.mjs +214 -0
  33. package/dist/agent-verifier/chunk-TTB7AIHZ.mjs.map +1 -0
  34. package/dist/agent-verifier/{chunk-F2DIOJJZ.mjs → chunk-XCQQIPCO.mjs} +5 -46
  35. package/dist/agent-verifier/chunk-XCQQIPCO.mjs.map +1 -0
  36. package/dist/agent-verifier/{global-config-Y2NTSK4R.mjs → global-config-2NUESNEQ.mjs} +6 -6
  37. package/dist/agent-verifier/{keychain-backend-SPQWGKZN.mjs → keychain-backend-FF4I6ODB.mjs} +12 -7
  38. package/dist/agent-verifier/keychain-backend-FF4I6ODB.mjs.map +1 -0
  39. package/dist/agent-verifier/{local-files-JFOQQZDL.mjs → local-files-OF4QFISU.mjs} +10 -10
  40. package/dist/agent-verifier/{chunk-UIOLGH4A.mjs → local-typecheck-DHVLM37Z.mjs} +4 -4
  41. package/dist/agent-verifier/local-typecheck-DHVLM37Z.mjs.map +1 -0
  42. package/dist/agent-verifier/{materialize-workspace-ZAVGQQSF.mjs → materialize-workspace-MAGKDMK5.mjs} +23 -22
  43. package/dist/agent-verifier/materialize-workspace-MAGKDMK5.mjs.map +1 -0
  44. package/dist/agent-verifier/{project-state-K576C2TE.mjs → project-state-XKUSCFSV.mjs} +2 -2
  45. package/dist/agent-verifier/{prompt-MJRJMOGQ.mjs → prompt-VKHMCQT6.mjs} +2 -2
  46. package/dist/agent-verifier/{chunk-A64ZZUZV.mjs → reducer-bundle-preflight-GLUJKTWU.mjs} +76 -25
  47. package/dist/agent-verifier/reducer-bundle-preflight-GLUJKTWU.mjs.map +1 -0
  48. package/dist/agent-verifier/{chunk-JGT4P4UD.mjs → reducer-contract-preflight-WVQQPW5F.mjs} +7 -6
  49. package/dist/agent-verifier/reducer-contract-preflight-WVQQPW5F.mjs.map +1 -0
  50. package/dist/agent-verifier/{chunk-E7SSWJXJ.mjs → reducer-native-test-harness-UFMSNNDY.mjs} +463 -686
  51. package/dist/agent-verifier/reducer-native-test-harness-UFMSNNDY.mjs.map +1 -0
  52. package/dist/agent-verifier/static-scaffold-CLRRWXON.mjs +24 -0
  53. package/dist/agent-verifier/workspace-codegen-SPPVHURX.mjs +10 -0
  54. package/dist/agent-verifier/{workspace-dependencies-NOOQBK6I.mjs → workspace-dependencies-5HEEKZFP.mjs} +6 -4
  55. package/dist/authoring-compatibility-internal.js +12 -0
  56. package/dist/chunk-2H7UOFLK.js +11 -0
  57. package/dist/chunk-6NYVJYN4.js +313 -0
  58. package/dist/chunk-6NYVJYN4.js.map +1 -0
  59. package/dist/chunk-EQNBQVIW.js +204 -0
  60. package/dist/chunk-EQNBQVIW.js.map +1 -0
  61. package/dist/chunk-X244CUU4.js +3815 -0
  62. package/dist/chunk-X244CUU4.js.map +1 -0
  63. package/dist/{chunk-TAQKH67O.js → chunk-YNJVKC2T.js} +2587 -7278
  64. package/dist/chunk-YNJVKC2T.js.map +1 -0
  65. package/dist/{global-config-S4ZIPECE.js → global-config-RBMW7IVA.js} +4 -3
  66. package/dist/index.js +3099 -6187
  67. package/dist/index.js.map +1 -1
  68. package/dist/internal.js +36 -10
  69. package/dist/internal.js.map +1 -1
  70. package/dist/{keychain-backend-HDF4TZDL.js → keychain-backend-FSNTNTZE.js} +12 -7
  71. package/dist/keychain-backend-FSNTNTZE.js.map +1 -0
  72. package/dist/{prompt-NDV3AE5L.js → prompt-GMZABCJC.js} +2 -2
  73. package/package.json +9 -19
  74. package/release/authoring-release-set.json +38 -0
  75. package/skills/dreamboard/SKILL.md +30 -28
  76. package/skills/dreamboard/references/building-your-first-game.md +15 -15
  77. package/skills/dreamboard/references/cli.md +46 -47
  78. package/skills/dreamboard/references/manifest-authoring.md +11 -3
  79. package/skills/dreamboard/references/quickstart.md +16 -13
  80. package/skills/dreamboard/references/testing.md +6 -13
  81. package/dist/agent-verifier/chunk-3UKQVWLV.mjs +0 -1744
  82. package/dist/agent-verifier/chunk-3UKQVWLV.mjs.map +0 -1
  83. package/dist/agent-verifier/chunk-776W3UGV.mjs.map +0 -1
  84. package/dist/agent-verifier/chunk-7WWGFAAU.mjs.map +0 -1
  85. package/dist/agent-verifier/chunk-A64ZZUZV.mjs.map +0 -1
  86. package/dist/agent-verifier/chunk-E7SSWJXJ.mjs.map +0 -1
  87. package/dist/agent-verifier/chunk-F2DIOJJZ.mjs.map +0 -1
  88. package/dist/agent-verifier/chunk-G42BGGG2.mjs +0 -70
  89. package/dist/agent-verifier/chunk-G42BGGG2.mjs.map +0 -1
  90. package/dist/agent-verifier/chunk-H76MT5UR.mjs.map +0 -1
  91. package/dist/agent-verifier/chunk-HGMUAL33.mjs +0 -39
  92. package/dist/agent-verifier/chunk-HGMUAL33.mjs.map +0 -1
  93. package/dist/agent-verifier/chunk-JGT4P4UD.mjs.map +0 -1
  94. package/dist/agent-verifier/chunk-NAK77WXW.mjs.map +0 -1
  95. package/dist/agent-verifier/chunk-O4YCPU7C.mjs.map +0 -1
  96. package/dist/agent-verifier/chunk-S34FRJHS.mjs +0 -222
  97. package/dist/agent-verifier/chunk-S34FRJHS.mjs.map +0 -1
  98. package/dist/agent-verifier/chunk-SH5JKYOB.mjs.map +0 -1
  99. package/dist/agent-verifier/chunk-SKI2ESE5.mjs +0 -44
  100. package/dist/agent-verifier/chunk-TAEQKBJB.mjs.map +0 -1
  101. package/dist/agent-verifier/chunk-UIOLGH4A.mjs.map +0 -1
  102. package/dist/agent-verifier/chunk-UIZNWRM6.mjs +0 -2432
  103. package/dist/agent-verifier/chunk-UIZNWRM6.mjs.map +0 -1
  104. package/dist/agent-verifier/chunk-W3N3QJ4V.mjs +0 -624
  105. package/dist/agent-verifier/chunk-W3N3QJ4V.mjs.map +0 -1
  106. package/dist/agent-verifier/chunk-XGWCY624.mjs.map +0 -1
  107. package/dist/agent-verifier/chunk-XQXDOBYB.mjs.map +0 -1
  108. package/dist/agent-verifier/compile-TEQVA46V.mjs +0 -312
  109. package/dist/agent-verifier/compile-TEQVA46V.mjs.map +0 -1
  110. package/dist/agent-verifier/keychain-backend-SPQWGKZN.mjs.map +0 -1
  111. package/dist/agent-verifier/local-typecheck-XVGWI75X.mjs +0 -10
  112. package/dist/agent-verifier/materialize-workspace-ZAVGQQSF.mjs.map +0 -1
  113. package/dist/agent-verifier/reducer-bundle-preflight-LXNJUBKL.mjs +0 -20
  114. package/dist/agent-verifier/reducer-contract-preflight-TUMQ43JV.mjs +0 -11
  115. package/dist/agent-verifier/reducer-native-test-harness-CHX5MBL5.mjs +0 -50
  116. package/dist/agent-verifier/static-scaffold-R7SVDRQI.mjs +0 -27
  117. package/dist/agent-verifier/sync-THAI546U.mjs +0 -588
  118. package/dist/agent-verifier/sync-THAI546U.mjs.map +0 -1
  119. package/dist/agent-verifier/test-AFAQFKOB.mjs +0 -353
  120. package/dist/agent-verifier/test-AFAQFKOB.mjs.map +0 -1
  121. package/dist/agent-verifier/workspace-codegen-2ZMQRIKJ.mjs +0 -10
  122. package/dist/agent-verifier/workspace-dependencies-NOOQBK6I.mjs.map +0 -1
  123. package/dist/chunk-N7XPNNUI.js +0 -432
  124. package/dist/chunk-N7XPNNUI.js.map +0 -1
  125. package/dist/chunk-SEGVTWSK.js +0 -44
  126. package/dist/chunk-SEGVTWSK.js.map +0 -1
  127. package/dist/chunk-TAQKH67O.js.map +0 -1
  128. package/dist/dev-host/components/drawer.tsx +0 -132
  129. package/dist/dev-host/components/input.tsx +0 -21
  130. package/dist/dev-host/dev-api-proxy-plugin.ts +0 -328
  131. package/dist/dev-host/dev-author-dom-warnings.ts +0 -100
  132. package/dist/dev-host/dev-diagnostics.ts +0 -62
  133. package/dist/dev-host/dev-fallback-stylesheet.ts +0 -53
  134. package/dist/dev-host/dev-hmr-guard-plugin.ts +0 -47
  135. package/dist/dev-host/dev-host-controller.ts +0 -674
  136. package/dist/dev-host/dev-host-player-query.ts +0 -17
  137. package/dist/dev-host/dev-host-session-transport.ts +0 -52
  138. package/dist/dev-host/dev-host-storage.ts +0 -56
  139. package/dist/dev-host/dev-log-relay-plugin.ts +0 -510
  140. package/dist/dev-host/dev-runtime-config.ts +0 -14
  141. package/dist/dev-host/dev-runtime-platform.ts +0 -335
  142. package/dist/dev-host/dev-virtual-modules-plugin.ts +0 -64
  143. package/dist/dev-host/host-main.css +0 -224
  144. package/dist/dev-host/host-main.tsx +0 -948
  145. package/dist/dev-host/index.html +0 -56
  146. package/dist/dev-host/lib/utils.ts +0 -6
  147. package/dist/dev-host/plugin-main.ts +0 -61
  148. package/dist/dev-host/plugin.html +0 -24
  149. package/dist/dev-host/shared-styles.css +0 -144
  150. package/dist/dev-host/start-dev-server.ts +0 -140
  151. package/dist/dev-host/virtual-modules.d.ts +0 -27
  152. package/dist/global-config-S4ZIPECE.js.map +0 -1
  153. package/dist/keychain-backend-HDF4TZDL.js.map +0 -1
  154. package/skills/dreamboard/scripts/events-extract.mjs +0 -218
  155. /package/dist/agent-verifier/{chunk-SKI2ESE5.mjs.map → chunk-H6XDQJ3N.mjs.map} +0 -0
  156. /package/dist/agent-verifier/{chunk-VS573ERH.mjs.map → chunk-JZTH3EMV.mjs.map} +0 -0
  157. /package/dist/agent-verifier/{global-config-Y2NTSK4R.mjs.map → global-config-2NUESNEQ.mjs.map} +0 -0
  158. /package/dist/agent-verifier/{local-files-JFOQQZDL.mjs.map → local-files-OF4QFISU.mjs.map} +0 -0
  159. /package/dist/agent-verifier/{local-typecheck-XVGWI75X.mjs.map → project-state-XKUSCFSV.mjs.map} +0 -0
  160. /package/dist/agent-verifier/{prompt-MJRJMOGQ.mjs.map → prompt-VKHMCQT6.mjs.map} +0 -0
  161. /package/dist/agent-verifier/{project-state-K576C2TE.mjs.map → static-scaffold-CLRRWXON.mjs.map} +0 -0
  162. /package/dist/agent-verifier/{reducer-bundle-preflight-LXNJUBKL.mjs.map → workspace-codegen-SPPVHURX.mjs.map} +0 -0
  163. /package/dist/agent-verifier/{reducer-contract-preflight-TUMQ43JV.mjs.map → workspace-dependencies-5HEEKZFP.mjs.map} +0 -0
  164. /package/dist/{agent-verifier/reducer-native-test-harness-CHX5MBL5.mjs.map → authoring-compatibility-internal.js.map} +0 -0
  165. /package/dist/{agent-verifier/static-scaffold-R7SVDRQI.mjs.map → chunk-2H7UOFLK.js.map} +0 -0
  166. /package/dist/{agent-verifier/workspace-codegen-2ZMQRIKJ.mjs.map → global-config-RBMW7IVA.js.map} +0 -0
  167. /package/dist/{prompt-NDV3AE5L.js.map → prompt-GMZABCJC.js.map} +0 -0
  168. /package/{dist/scaffold → scaffold}/assets/static/app/tsconfig.framework.json +0 -0
  169. /package/{dist/scaffold → scaffold}/assets/static/app/tsconfig.json +0 -0
  170. /package/{dist/scaffold → scaffold}/assets/static/ui/index.tsx +0 -0
  171. /package/{dist/scaffold → scaffold}/assets/static/ui/style.css +0 -0
  172. /package/{dist/scaffold → scaffold}/assets/static/ui/tsconfig.framework.json +0 -0
  173. /package/{dist/scaffold → scaffold}/assets/static/ui/tsconfig.json +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../node_modules/.pnpm/citty@0.2.2/node_modules/citty/dist/index.mjs","../../../../packages/api-client/dist/source-revisions.js","../../src/command-args.ts","../../src/flags.ts","../../src/utils/strings.ts","../../src/services/api/compiled-results-api.ts","../../src/services/api/project-api.ts","../../src/services/api/preview-api.ts","../../src/services/api/source-revisions-api.ts"],"sourcesContent":["import { n as kebabCase, r as snakeCase, t as camelCase } from \"./_chunks/libs/scule.mjs\";\nimport { parseArgs as parseArgs$1 } from \"node:util\";\n//#region src/_utils.ts\nfunction toArray(val) {\n\tif (Array.isArray(val)) return val;\n\treturn val === void 0 ? [] : [val];\n}\nfunction formatLineColumns(lines, linePrefix = \"\") {\n\tconst maxLength = [];\n\tfor (const line of lines) for (const [i, element] of line.entries()) maxLength[i] = Math.max(maxLength[i] || 0, element.length);\n\treturn lines.map((l) => l.map((c, i) => linePrefix + c[i === 0 ? \"padStart\" : \"padEnd\"](maxLength[i])).join(\" \")).join(\"\\n\");\n}\nfunction resolveValue(input) {\n\treturn typeof input === \"function\" ? input() : input;\n}\nvar CLIError = class extends Error {\n\tcode;\n\tconstructor(message, code) {\n\t\tsuper(message);\n\t\tthis.name = \"CLIError\";\n\t\tthis.code = code;\n\t}\n};\n//#endregion\n//#region src/_parser.ts\nfunction parseRawArgs(args = [], opts = {}) {\n\tconst booleans = new Set(opts.boolean || []);\n\tconst strings = new Set(opts.string || []);\n\tconst aliasMap = opts.alias || {};\n\tconst defaults = opts.default || {};\n\tconst aliasToMain = /* @__PURE__ */ new Map();\n\tconst mainToAliases = /* @__PURE__ */ new Map();\n\tfor (const [key, value] of Object.entries(aliasMap)) {\n\t\tconst targets = value;\n\t\tfor (const target of targets) {\n\t\t\taliasToMain.set(key, target);\n\t\t\tif (!mainToAliases.has(target)) mainToAliases.set(target, []);\n\t\t\tmainToAliases.get(target).push(key);\n\t\t\taliasToMain.set(target, key);\n\t\t\tif (!mainToAliases.has(key)) mainToAliases.set(key, []);\n\t\t\tmainToAliases.get(key).push(target);\n\t\t}\n\t}\n\tconst options = {};\n\tfunction getType(name) {\n\t\tif (booleans.has(name)) return \"boolean\";\n\t\tconst aliases = mainToAliases.get(name) || [];\n\t\tfor (const alias of aliases) if (booleans.has(alias)) return \"boolean\";\n\t\treturn \"string\";\n\t}\n\tfunction isStringType(name) {\n\t\tif (strings.has(name)) return true;\n\t\tconst aliases = mainToAliases.get(name) || [];\n\t\tfor (const alias of aliases) if (strings.has(alias)) return true;\n\t\treturn false;\n\t}\n\tconst allOptions = new Set([\n\t\t...booleans,\n\t\t...strings,\n\t\t...Object.keys(aliasMap),\n\t\t...Object.values(aliasMap).flat(),\n\t\t...Object.keys(defaults)\n\t]);\n\tfor (const name of allOptions) if (!options[name]) options[name] = {\n\t\ttype: getType(name),\n\t\tdefault: defaults[name]\n\t};\n\tfor (const [alias, main] of aliasToMain.entries()) if (alias.length === 1 && options[main] && !options[main].short) options[main].short = alias;\n\tconst processedArgs = [];\n\tconst negatedFlags = {};\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\t\tif (arg === \"--\") {\n\t\t\tprocessedArgs.push(...args.slice(i));\n\t\t\tbreak;\n\t\t}\n\t\tif (arg.startsWith(\"--no-\")) {\n\t\t\tconst flagName = arg.slice(5);\n\t\t\tnegatedFlags[flagName] = true;\n\t\t\tcontinue;\n\t\t}\n\t\tprocessedArgs.push(arg);\n\t}\n\tlet parsed;\n\ttry {\n\t\tparsed = parseArgs$1({\n\t\t\targs: processedArgs,\n\t\t\toptions: Object.keys(options).length > 0 ? options : void 0,\n\t\t\tallowPositionals: true,\n\t\t\tstrict: false\n\t\t});\n\t} catch {\n\t\tparsed = {\n\t\t\tvalues: {},\n\t\t\tpositionals: processedArgs\n\t\t};\n\t}\n\tconst out = { _: [] };\n\tout._ = parsed.positionals;\n\tfor (const [key, value] of Object.entries(parsed.values)) {\n\t\tlet coerced = value;\n\t\tif (getType(key) === \"boolean\" && typeof value === \"string\") coerced = value !== \"false\";\n\t\telse if (isStringType(key) && typeof value === \"boolean\") coerced = \"\";\n\t\tout[key] = coerced;\n\t}\n\tfor (const [name] of Object.entries(negatedFlags)) {\n\t\tout[name] = false;\n\t\tconst mainName = aliasToMain.get(name);\n\t\tif (mainName) out[mainName] = false;\n\t\tconst aliases = mainToAliases.get(name);\n\t\tif (aliases) for (const alias of aliases) out[alias] = false;\n\t}\n\tfor (const [alias, main] of aliasToMain.entries()) {\n\t\tif (out[alias] !== void 0 && out[main] === void 0) out[main] = out[alias];\n\t\tif (out[main] !== void 0 && out[alias] === void 0) out[alias] = out[main];\n\t\tif (out[alias] !== out[main] && defaults[main] === out[main]) out[main] = out[alias];\n\t}\n\treturn out;\n}\n//#endregion\n//#region src/_color.ts\nconst noColor = /* @__PURE__ */ (() => {\n\tconst env = globalThis.process?.env ?? {};\n\treturn env.NO_COLOR === \"1\" || env.TERM === \"dumb\" || env.TEST || env.CI;\n})();\nconst _c = (c, r = 39) => (t) => noColor ? t : `\\u001B[${c}m${t}\\u001B[${r}m`;\nconst bold = /* @__PURE__ */ _c(1, 22);\nconst cyan = /* @__PURE__ */ _c(36);\nconst gray = /* @__PURE__ */ _c(90);\nconst underline = /* @__PURE__ */ _c(4, 24);\n//#endregion\n//#region src/args.ts\nfunction parseArgs(rawArgs, argsDef) {\n\tconst parseOptions = {\n\t\tboolean: [],\n\t\tstring: [],\n\t\talias: {},\n\t\tdefault: {}\n\t};\n\tconst args = resolveArgs(argsDef);\n\tfor (const arg of args) {\n\t\tif (arg.type === \"positional\") continue;\n\t\tif (arg.type === \"string\" || arg.type === \"enum\") parseOptions.string.push(arg.name);\n\t\telse if (arg.type === \"boolean\") parseOptions.boolean.push(arg.name);\n\t\tif (arg.default !== void 0) parseOptions.default[arg.name] = arg.default;\n\t\tif (arg.alias) parseOptions.alias[arg.name] = arg.alias;\n\t\tconst camelName = camelCase(arg.name);\n\t\tconst kebabName = kebabCase(arg.name);\n\t\tif (camelName !== arg.name || kebabName !== arg.name) {\n\t\t\tconst existingAliases = toArray(parseOptions.alias[arg.name] || []);\n\t\t\tif (camelName !== arg.name && !existingAliases.includes(camelName)) existingAliases.push(camelName);\n\t\t\tif (kebabName !== arg.name && !existingAliases.includes(kebabName)) existingAliases.push(kebabName);\n\t\t\tif (existingAliases.length > 0) parseOptions.alias[arg.name] = existingAliases;\n\t\t}\n\t}\n\tconst parsed = parseRawArgs(rawArgs, parseOptions);\n\tconst [ ...positionalArguments] = parsed._;\n\tconst parsedArgsProxy = new Proxy(parsed, { get(target, prop) {\n\t\treturn target[prop] ?? target[camelCase(prop)] ?? target[kebabCase(prop)];\n\t} });\n\tfor (const [, arg] of args.entries()) if (arg.type === \"positional\") {\n\t\tconst nextPositionalArgument = positionalArguments.shift();\n\t\tif (nextPositionalArgument !== void 0) parsedArgsProxy[arg.name] = nextPositionalArgument;\n\t\telse if (arg.default === void 0 && arg.required !== false) throw new CLIError(`Missing required positional argument: ${arg.name.toUpperCase()}`, \"EARG\");\n\t\telse parsedArgsProxy[arg.name] = arg.default;\n\t} else if (arg.type === \"enum\") {\n\t\tconst argument = parsedArgsProxy[arg.name];\n\t\tconst options = arg.options || [];\n\t\tif (argument !== void 0 && options.length > 0 && !options.includes(argument)) throw new CLIError(`Invalid value for argument: ${cyan(`--${arg.name}`)} (${cyan(argument)}). Expected one of: ${options.map((o) => cyan(o)).join(\", \")}.`, \"EARG\");\n\t} else if (arg.required && parsedArgsProxy[arg.name] === void 0) throw new CLIError(`Missing required argument: --${arg.name}`, \"EARG\");\n\treturn parsedArgsProxy;\n}\nfunction resolveArgs(argsDef) {\n\tconst args = [];\n\tfor (const [name, argDef] of Object.entries(argsDef || {})) args.push({\n\t\t...argDef,\n\t\tname,\n\t\talias: toArray(argDef.alias)\n\t});\n\treturn args;\n}\n//#endregion\n//#region src/plugin.ts\nfunction defineCittyPlugin(plugin) {\n\treturn plugin;\n}\nasync function resolvePlugins(plugins) {\n\treturn Promise.all(plugins.map((p) => resolveValue(p)));\n}\n//#endregion\n//#region src/command.ts\nfunction defineCommand(def) {\n\treturn def;\n}\nasync function runCommand(cmd, opts) {\n\tconst cmdArgs = await resolveValue(cmd.args || {});\n\tconst parsedArgs = parseArgs(opts.rawArgs, cmdArgs);\n\tconst context = {\n\t\trawArgs: opts.rawArgs,\n\t\targs: parsedArgs,\n\t\tdata: opts.data,\n\t\tcmd\n\t};\n\tconst plugins = await resolvePlugins(cmd.plugins ?? []);\n\tlet result;\n\tlet runError;\n\ttry {\n\t\tfor (const plugin of plugins) await plugin.setup?.(context);\n\t\tif (typeof cmd.setup === \"function\") await cmd.setup(context);\n\t\tconst subCommands = await resolveValue(cmd.subCommands);\n\t\tif (subCommands && Object.keys(subCommands).length > 0) {\n\t\t\tconst subCommandArgIndex = findSubCommandIndex(opts.rawArgs, cmdArgs);\n\t\t\tconst explicitName = opts.rawArgs[subCommandArgIndex];\n\t\t\tif (explicitName) {\n\t\t\t\tconst subCommand = await _findSubCommand(subCommands, explicitName);\n\t\t\t\tif (!subCommand) throw new CLIError(`Unknown command ${cyan(explicitName)}`, \"E_UNKNOWN_COMMAND\");\n\t\t\t\tawait runCommand(subCommand, { rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1) });\n\t\t\t} else {\n\t\t\t\tconst defaultSubCommand = await resolveValue(cmd.default);\n\t\t\t\tif (defaultSubCommand) {\n\t\t\t\t\tif (cmd.run) throw new CLIError(`Cannot specify both 'run' and 'default' on the same command.`, \"E_DEFAULT_CONFLICT\");\n\t\t\t\t\tconst subCommand = await _findSubCommand(subCommands, defaultSubCommand);\n\t\t\t\t\tif (!subCommand) throw new CLIError(`Default sub command ${cyan(defaultSubCommand)} not found in subCommands.`, \"E_UNKNOWN_COMMAND\");\n\t\t\t\t\tawait runCommand(subCommand, { rawArgs: opts.rawArgs });\n\t\t\t\t} else if (!cmd.run) throw new CLIError(`No command specified.`, \"E_NO_COMMAND\");\n\t\t\t}\n\t\t}\n\t\tif (typeof cmd.run === \"function\") result = await cmd.run(context);\n\t} catch (error) {\n\t\trunError = error;\n\t}\n\tconst cleanupErrors = [];\n\tif (typeof cmd.cleanup === \"function\") try {\n\t\tawait cmd.cleanup(context);\n\t} catch (error) {\n\t\tcleanupErrors.push(error);\n\t}\n\tfor (const plugin of [...plugins].reverse()) try {\n\t\tawait plugin.cleanup?.(context);\n\t} catch (error) {\n\t\tcleanupErrors.push(error);\n\t}\n\tif (runError) throw runError;\n\tif (cleanupErrors.length === 1) throw cleanupErrors[0];\n\tif (cleanupErrors.length > 1) throw new Error(\"Multiple cleanup errors\", { cause: cleanupErrors });\n\treturn { result };\n}\nasync function resolveSubCommand(cmd, rawArgs, parent) {\n\tconst subCommands = await resolveValue(cmd.subCommands);\n\tif (subCommands && Object.keys(subCommands).length > 0) {\n\t\tconst subCommandArgIndex = findSubCommandIndex(rawArgs, await resolveValue(cmd.args || {}));\n\t\tconst subCommandName = rawArgs[subCommandArgIndex];\n\t\tconst subCommand = await _findSubCommand(subCommands, subCommandName);\n\t\tif (subCommand) return resolveSubCommand(subCommand, rawArgs.slice(subCommandArgIndex + 1), cmd);\n\t}\n\treturn [cmd, parent];\n}\nasync function _findSubCommand(subCommands, name) {\n\tif (name in subCommands) return resolveValue(subCommands[name]);\n\tfor (const sub of Object.values(subCommands)) {\n\t\tconst resolved = await resolveValue(sub);\n\t\tconst meta = await resolveValue(resolved?.meta);\n\t\tif (meta?.alias) {\n\t\t\tif (toArray(meta.alias).includes(name)) return resolved;\n\t\t}\n\t}\n}\nfunction findSubCommandIndex(rawArgs, argsDef) {\n\tfor (let i = 0; i < rawArgs.length; i++) {\n\t\tconst arg = rawArgs[i];\n\t\tif (arg === \"--\") return -1;\n\t\tif (arg.startsWith(\"-\")) {\n\t\t\tif (!arg.includes(\"=\") && _isValueFlag(arg, argsDef)) i++;\n\t\t\tcontinue;\n\t\t}\n\t\treturn i;\n\t}\n\treturn -1;\n}\nfunction _isValueFlag(flag, argsDef) {\n\tconst name = flag.replace(/^-{1,2}/, \"\");\n\tconst normalized = camelCase(name);\n\tfor (const [key, def] of Object.entries(argsDef)) {\n\t\tif (def.type !== \"string\" && def.type !== \"enum\") continue;\n\t\tif (normalized === camelCase(key)) return true;\n\t\tif ((Array.isArray(def.alias) ? def.alias : def.alias ? [def.alias] : []).includes(name)) return true;\n\t}\n\treturn false;\n}\n//#endregion\n//#region src/usage.ts\nasync function showUsage(cmd, parent) {\n\ttry {\n\t\tconsole.log(await renderUsage(cmd, parent) + \"\\n\");\n\t} catch (error) {\n\t\tconsole.error(error);\n\t}\n}\nconst negativePrefixRe = /^no[-A-Z]/;\nasync function renderUsage(cmd, parent) {\n\tconst cmdMeta = await resolveValue(cmd.meta || {});\n\tconst cmdArgs = resolveArgs(await resolveValue(cmd.args || {}));\n\tconst parentMeta = await resolveValue(parent?.meta || {});\n\tconst commandName = `${parentMeta.name ? `${parentMeta.name} ` : \"\"}` + (cmdMeta.name || process.argv[1]);\n\tconst argLines = [];\n\tconst posLines = [];\n\tconst commandsLines = [];\n\tconst usageLine = [];\n\tfor (const arg of cmdArgs) if (arg.type === \"positional\") {\n\t\tconst name = arg.name.toUpperCase();\n\t\tconst isRequired = arg.required !== false && arg.default === void 0;\n\t\tposLines.push([cyan(name + renderValueHint(arg)), renderDescription(arg, isRequired)]);\n\t\tusageLine.push(isRequired ? `<${name}>` : `[${name}]`);\n\t} else {\n\t\tconst isRequired = arg.required === true && arg.default === void 0;\n\t\tconst argStr = [...(arg.alias || []).map((a) => `-${a}`), `--${arg.name}`].join(\", \") + renderValueHint(arg);\n\t\targLines.push([cyan(argStr), renderDescription(arg, isRequired)]);\n\t\t/**\n\t\t* print negative boolean arg variant usage when\n\t\t* - enabled by default or has `negativeDescription`\n\t\t* - not prefixed with `no-` or `no[A-Z]`\n\t\t*/\n\t\tif (arg.type === \"boolean\" && (arg.default === true || arg.negativeDescription) && !negativePrefixRe.test(arg.name)) {\n\t\t\tconst negativeArgStr = [...(arg.alias || []).map((a) => `--no-${a}`), `--no-${arg.name}`].join(\", \");\n\t\t\targLines.push([cyan(negativeArgStr), [arg.negativeDescription, isRequired ? gray(\"(Required)\") : \"\"].filter(Boolean).join(\" \")]);\n\t\t}\n\t\tif (isRequired) usageLine.push(`--${arg.name}` + renderValueHint(arg));\n\t}\n\tif (cmd.subCommands) {\n\t\tconst commandNames = [];\n\t\tconst subCommands = await resolveValue(cmd.subCommands);\n\t\tfor (const [name, sub] of Object.entries(subCommands)) {\n\t\t\tconst meta = await resolveValue((await resolveValue(sub))?.meta);\n\t\t\tif (meta?.hidden) continue;\n\t\t\tconst aliases = toArray(meta?.alias);\n\t\t\tconst label = [name, ...aliases].join(\", \");\n\t\t\tcommandsLines.push([cyan(label), meta?.description || \"\"]);\n\t\t\tcommandNames.push(name, ...aliases);\n\t\t}\n\t\tusageLine.push(commandNames.join(\"|\"));\n\t}\n\tconst usageLines = [];\n\tconst version = cmdMeta.version || parentMeta.version;\n\tusageLines.push(gray(`${cmdMeta.description} (${commandName + (version ? ` v${version}` : \"\")})`), \"\");\n\tconst hasOptions = argLines.length > 0 || posLines.length > 0;\n\tusageLines.push(`${underline(bold(\"USAGE\"))} ${cyan(`${commandName}${hasOptions ? \" [OPTIONS]\" : \"\"} ${usageLine.join(\" \")}`)}`, \"\");\n\tif (posLines.length > 0) {\n\t\tusageLines.push(underline(bold(\"ARGUMENTS\")), \"\");\n\t\tusageLines.push(formatLineColumns(posLines, \" \"));\n\t\tusageLines.push(\"\");\n\t}\n\tif (argLines.length > 0) {\n\t\tusageLines.push(underline(bold(\"OPTIONS\")), \"\");\n\t\tusageLines.push(formatLineColumns(argLines, \" \"));\n\t\tusageLines.push(\"\");\n\t}\n\tif (commandsLines.length > 0) {\n\t\tusageLines.push(underline(bold(\"COMMANDS\")), \"\");\n\t\tusageLines.push(formatLineColumns(commandsLines, \" \"));\n\t\tusageLines.push(\"\", `Use ${cyan(`${commandName} <command> --help`)} for more information about a command.`);\n\t}\n\treturn usageLines.filter((l) => typeof l === \"string\").join(\"\\n\");\n}\nfunction renderValueHint(arg) {\n\tconst valueHint = arg.valueHint ? `=<${arg.valueHint}>` : \"\";\n\tconst fallbackValueHint = valueHint || `=<${snakeCase(arg.name)}>`;\n\tif (!arg.type || arg.type === \"positional\" || arg.type === \"boolean\") return valueHint;\n\tif (arg.type === \"enum\" && arg.options?.length) return `=<${arg.options.join(\"|\")}>`;\n\treturn fallbackValueHint;\n}\nfunction renderDescription(arg, required) {\n\tconst requiredHint = required ? gray(\"(Required)\") : \"\";\n\tconst defaultHint = arg.default === void 0 ? \"\" : gray(`(Default: ${arg.default})`);\n\treturn [\n\t\targ.description,\n\t\trequiredHint,\n\t\tdefaultHint\n\t].filter(Boolean).join(\" \");\n}\n//#endregion\n//#region src/main.ts\nasync function runMain(cmd, opts = {}) {\n\tconst rawArgs = opts.rawArgs || process.argv.slice(2);\n\tconst showUsage$1 = opts.showUsage || showUsage;\n\ttry {\n\t\tconst builtinFlags = await _resolveBuiltinFlags(cmd);\n\t\tif (builtinFlags.help.length > 0 && rawArgs.some((arg) => builtinFlags.help.includes(arg))) {\n\t\t\tawait showUsage$1(...await resolveSubCommand(cmd, rawArgs));\n\t\t\tprocess.exit(0);\n\t\t} else if (rawArgs.length === 1 && builtinFlags.version.includes(rawArgs[0])) {\n\t\t\tconst meta = typeof cmd.meta === \"function\" ? await cmd.meta() : await cmd.meta;\n\t\t\tif (!meta?.version) throw new CLIError(\"No version specified\", \"E_NO_VERSION\");\n\t\t\tconsole.log(meta.version);\n\t\t} else await runCommand(cmd, { rawArgs });\n\t} catch (error) {\n\t\tif (error instanceof CLIError) {\n\t\t\tawait showUsage$1(...await resolveSubCommand(cmd, rawArgs));\n\t\t\tconsole.error(error.message);\n\t\t} else console.error(error, \"\\n\");\n\t\tprocess.exit(1);\n\t}\n}\nfunction createMain(cmd) {\n\treturn (opts = {}) => runMain(cmd, opts);\n}\nasync function _resolveBuiltinFlags(cmd) {\n\tconst argsDef = await resolveValue(cmd.args || {});\n\tconst userNames = /* @__PURE__ */ new Set();\n\tconst userAliases = /* @__PURE__ */ new Set();\n\tfor (const [name, def] of Object.entries(argsDef)) {\n\t\tuserNames.add(name);\n\t\tfor (const alias of toArray(def.alias)) userAliases.add(alias);\n\t}\n\treturn {\n\t\thelp: _getBuiltinFlags(\"help\", \"h\", userNames, userAliases),\n\t\tversion: _getBuiltinFlags(\"version\", \"v\", userNames, userAliases)\n\t};\n}\nfunction _getBuiltinFlags(long, short, userNames, userAliases) {\n\tif (userNames.has(long) || userAliases.has(long)) return [];\n\tif (userNames.has(short) || userAliases.has(short)) return [`--${long}`];\n\treturn [`--${long}`, `-${short}`];\n}\n//#endregion\nexport { createMain, defineCittyPlugin, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage };\n","import { createProjectSourceBlobUploadSession, createSourceBlobUploadSession, } from \"./sdk.gen.js\";\nconst textEncoder = new TextEncoder();\nfunction bytesToHex(bytes) {\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\nasync function sha256Hex(bytes) {\n const normalizedBytes = new Uint8Array(bytes.byteLength);\n normalizedBytes.set(bytes);\n const digest = await crypto.subtle.digest(\"SHA-256\", normalizedBytes.buffer);\n return bytesToHex(new Uint8Array(digest));\n}\nfunction getUtf8ByteSize(content) {\n return textEncoder.encode(content).byteLength;\n}\nasync function computeSourceContentHash(content) {\n return sha256Hex(textEncoder.encode(content));\n}\nasync function describeSourceBlob(content) {\n return {\n contentHash: await computeSourceContentHash(content),\n byteSize: getUtf8ByteSize(content),\n };\n}\nexport async function materializeSourceChangeOperations(changes) {\n const blobsByHash = new Map();\n const materialized = await Promise.all(Array.from(changes, async (change) => {\n if (change.kind === \"delete\") {\n return change;\n }\n const blob = await describeSourceBlob(change.content);\n const existing = blobsByHash.get(blob.contentHash);\n if (!existing) {\n blobsByHash.set(blob.contentHash, blob);\n }\n return {\n kind: \"upsert\",\n path: change.path,\n contentHash: blob.contentHash,\n byteSize: blob.byteSize,\n };\n }));\n return {\n blobs: Array.from(blobsByHash.values()).sort((left, right) => left.contentHash.localeCompare(right.contentHash)),\n changes: materialized,\n };\n}\nexport function mapUpsertBlobContentsByContentHash(localChanges, materializedChanges) {\n const uploadBlobs = new Map();\n const length = Math.min(localChanges.length, materializedChanges.length);\n for (let index = 0; index < length; index += 1) {\n const localChange = localChanges[index];\n const materializedChange = materializedChanges[index];\n if (localChange?.kind !== \"upsert\" ||\n materializedChange?.kind !== \"upsert\") {\n continue;\n }\n uploadBlobs.set(materializedChange.contentHash, {\n contentHash: materializedChange.contentHash,\n byteSize: materializedChange.byteSize,\n content: localChange.content,\n });\n }\n return uploadBlobs;\n}\nclass SourceBlobUploadError extends Error {\n constructor(status, details) {\n const suffix = details.trim().length > 0 ? `: ${details.trim()}` : \"\";\n super(`Failed to upload source blob (HTTP ${status}${suffix})`);\n this.name = \"SourceBlobUploadError\";\n this.status = status;\n this.details = details;\n }\n}\nfunction isDuplicateDirectUploadError(error) {\n if (!(error instanceof SourceBlobUploadError)) {\n return false;\n }\n if (error.status === 409) {\n return true;\n }\n const normalizedDetails = error.details.toLowerCase();\n return (normalizedDetails.includes(\"duplicate\") ||\n normalizedDetails.includes(\"already exists\") ||\n normalizedDetails.includes(\"resource already exists\"));\n}\nasync function uploadSourceBlob(uploadTarget, content) {\n const response = await fetch(uploadTarget.url, {\n method: uploadTarget.method,\n headers: uploadTarget.headers,\n body: textEncoder.encode(content),\n });\n if (response.ok) {\n return;\n }\n const details = await response.text().catch(() => \"\");\n throw new SourceBlobUploadError(response.status, details);\n}\nexport class SourceBlobSessionRequestError extends Error {\n constructor(message, apiError, response) {\n super(message);\n this.name = \"SourceBlobSessionRequestError\";\n this.apiError = apiError;\n this.response = response;\n }\n}\nfunction assertSourceBlobUploadSession(data, response) {\n if (!data ||\n typeof data !== \"object\" ||\n !Array.isArray(data.uploads)) {\n throw new SourceBlobSessionRequestError(\"Source blob upload session response did not include an uploads array\", data, response);\n }\n}\nasync function confirmSourceBlobAlreadyExists(options) {\n const { requestUploadSession, blob } = options;\n const { data, error, response } = await requestUploadSession([\n {\n contentHash: blob.contentHash,\n byteSize: blob.byteSize,\n },\n ]);\n if (error || !data) {\n throw new SourceBlobSessionRequestError(\"Failed to create source blob upload session\", error, response);\n }\n assertSourceBlobUploadSession(data, response);\n return data.uploads[0]?.status === \"exists\";\n}\nasync function uploadSourceBlobs(options) {\n const { blobs, requestUploadSession } = options;\n const uniqueBlobs = new Map();\n for (const blob of blobs) {\n const existing = uniqueBlobs.get(blob.contentHash);\n if (!existing) {\n uniqueBlobs.set(blob.contentHash, blob);\n continue;\n }\n if (existing.byteSize !== blob.byteSize) {\n throw new Error(`Source blob ${blob.contentHash} has conflicting byte sizes.`);\n }\n }\n if (uniqueBlobs.size === 0) {\n return;\n }\n const { data, error, response } = await requestUploadSession(Array.from(uniqueBlobs.values(), ({ contentHash, byteSize }) => ({\n contentHash,\n byteSize,\n })));\n if (error || !data) {\n throw new SourceBlobSessionRequestError(\"Failed to create source blob upload session\", error, response);\n }\n assertSourceBlobUploadSession(data, response);\n for (const upload of data.uploads) {\n if (upload.status !== \"upload_required\") {\n continue;\n }\n const blob = uniqueBlobs.get(upload.contentHash);\n if (!blob) {\n throw new Error(`Upload session referenced unknown source blob ${upload.contentHash}.`);\n }\n if (!upload.uploadTarget) {\n throw new Error(`Upload target missing for source blob ${upload.contentHash}.`);\n }\n try {\n await uploadSourceBlob(upload.uploadTarget, blob.content);\n if (!(await confirmSourceBlobAlreadyExists({ requestUploadSession, blob }))) {\n throw new Error(`Source blob ${blob.contentHash} was uploaded but not registered.`);\n }\n }\n catch (error) {\n if (isDuplicateDirectUploadError(error) &&\n (await confirmSourceBlobAlreadyExists({ requestUploadSession, blob }))) {\n continue;\n }\n throw error;\n }\n }\n}\nexport async function uploadGameSourceBlobs(options) {\n const { gameId, blobs } = options;\n return uploadSourceBlobs({\n blobs,\n requestUploadSession: (uploadBlobs) => createSourceBlobUploadSession({\n path: { gameId },\n body: { blobs: uploadBlobs },\n }),\n });\n}\nexport async function uploadProjectSourceBlobs(options) {\n const { projectId, blobs } = options;\n return uploadSourceBlobs({\n blobs,\n requestUploadSession: (uploadBlobs) => createProjectSourceBlobUploadSession({\n path: { projectId },\n body: { blobs: uploadBlobs },\n }),\n });\n}\n","export const CONFIG_FLAG_ARGS = {\n env: {\n type: \"string\" as const,\n description: \"Environment: local | staging | prod\",\n },\n token: {\n type: \"string\" as const,\n description: \"Auth token (Dreamboard bearer JWT)\",\n },\n};\n","import { z } from \"zod\";\n\nconst configFlagsSchema = z.object({\n env: z.enum([\"local\", \"staging\", \"prod\"]).optional(),\n token: z.string().optional(),\n});\n\nconst ruleInputFlagsSchema = z.object({\n \"rule-file\": z.string().optional(),\n rule: z.string().optional(),\n});\n\nconst playerCountFlagsSchema = z.object({\n players: z.string().optional(),\n \"player-count\": z.string().optional(),\n});\n\nconst newCommandArgsSchema = configFlagsSchema.extend({\n slug: z.string().min(1),\n description: z.string().min(1),\n force: z.boolean().default(false),\n});\n\nconst cloneCommandArgsSchema = configFlagsSchema.extend({\n slug: z.string().min(1),\n});\n\nconst queryCommandArgsSchema = configFlagsSchema.extend({\n title: z.string().min(1),\n});\n\nconst pullCommandArgsSchema = configFlagsSchema.extend({\n force: z.boolean().default(false),\n});\n\nconst syncCommandArgsSchema = configFlagsSchema.extend({\n force: z.boolean().default(false),\n yes: z.boolean().default(false),\n});\n\nconst compileCommandArgsSchema = configFlagsSchema.extend({\n debug: z.boolean().default(false),\n \"skip-local-check\": z.boolean().default(false),\n});\n\nconst statusCommandArgsSchema = configFlagsSchema.extend({\n json: z.boolean().default(false),\n});\n\nconst devCommandArgsSchema = configFlagsSchema.extend({\n seed: z.string().optional(),\n \"setup-profile\": z.string().optional(),\n players: z.string().optional(),\n \"player-count\": z.string().optional(),\n debug: z.boolean().default(false),\n resume: z.string().optional(),\n \"from-scenario\": z.string().optional(),\n \"new-session\": z.boolean().default(false),\n open: z.boolean().default(false),\n port: z.string().optional(),\n host: z.union([z.string(), z.boolean()]).optional(),\n \"allowed-host\": z.string().optional(),\n});\n\nconst joinCommandArgsSchema = configFlagsSchema.extend({\n session: z.string().min(1).optional(),\n player: z.string().min(1),\n \"raw-events\": z.boolean().default(false),\n});\n\nconst loginCommandArgsSchema = configFlagsSchema;\n\nconst configCommandArgsSchema = configFlagsSchema.extend({\n action: z.string().optional().default(\"show\"),\n scope: z.enum([\"global\", \"workspace\"]).optional().default(\"global\"),\n});\n\nconst authCommandArgsSchema = z.object({\n action: z.enum([\"set\", \"clear\", \"login\", \"env\", \"status\"]),\n tokenValue: z.string().optional(),\n token: z.string().optional(),\n jwt: z.boolean().optional(),\n env: z.enum([\"local\", \"staging\", \"prod\"]).optional(),\n});\n\nexport type ConfigFlags = z.infer<typeof configFlagsSchema>;\nexport type RuleInputFlags = z.infer<typeof ruleInputFlagsSchema>;\nexport type PlayerCountFlags = z.infer<typeof playerCountFlagsSchema>;\n\nexport type NewCommandArgs = z.infer<typeof newCommandArgsSchema>;\nexport type CloneCommandArgs = z.infer<typeof cloneCommandArgsSchema>;\nexport type QueryCommandArgs = z.infer<typeof queryCommandArgsSchema>;\nexport type PullCommandArgs = z.infer<typeof pullCommandArgsSchema>;\nexport type SyncCommandArgs = z.infer<typeof syncCommandArgsSchema>;\nexport type CompileCommandArgs = z.infer<typeof compileCommandArgsSchema>;\nexport type StatusCommandArgs = z.infer<typeof statusCommandArgsSchema>;\nexport type DevCommandArgs = z.infer<typeof devCommandArgsSchema>;\nexport type JoinCommandArgs = z.infer<typeof joinCommandArgsSchema>;\nexport type LoginCommandArgs = z.infer<typeof loginCommandArgsSchema>;\nexport type ConfigCommandArgs = z.infer<typeof configCommandArgsSchema>;\nexport type AuthCommandArgs = z.infer<typeof authCommandArgsSchema>;\n\nfunction parseArgs<TOutput>(\n commandName: string,\n schema: z.ZodType<TOutput>,\n args: unknown,\n): TOutput {\n const parsed = schema.safeParse(args);\n if (parsed.success) {\n return parsed.data;\n }\n\n const details = parsed.error.issues\n .map((issue) => {\n const field = issue.path.length > 0 ? issue.path.join(\".\") : \"args\";\n return `${field}: ${issue.message}`;\n })\n .join(\"; \");\n throw new Error(`Invalid arguments for '${commandName}': ${details}`);\n}\n\nexport function parseConfigFlags(args: unknown): ConfigFlags {\n return parseArgs(\"config-flags\", configFlagsSchema, args);\n}\n\nexport function parseRuleInputFlags(args: unknown): RuleInputFlags {\n return parseArgs(\"rule-flags\", ruleInputFlagsSchema, args);\n}\n\nexport function parsePlayerCountFlags(args: unknown): PlayerCountFlags {\n return parseArgs(\"player-count\", playerCountFlagsSchema, args);\n}\n\nexport function parseNewCommandArgs(args: unknown): NewCommandArgs {\n return parseArgs(\"new\", newCommandArgsSchema, args);\n}\n\nexport function parseCloneCommandArgs(args: unknown): CloneCommandArgs {\n return parseArgs(\"clone\", cloneCommandArgsSchema, args);\n}\n\nexport function parseQueryCommandArgs(args: unknown): QueryCommandArgs {\n return parseArgs(\"query\", queryCommandArgsSchema, args);\n}\n\nexport function parsePullCommandArgs(args: unknown): PullCommandArgs {\n return parseArgs(\"pull\", pullCommandArgsSchema, args);\n}\n\nexport function parseSyncCommandArgs(args: unknown): SyncCommandArgs {\n return parseArgs(\"sync\", syncCommandArgsSchema, args);\n}\n\nexport function parseCompileCommandArgs(args: unknown): CompileCommandArgs {\n return parseArgs(\"compile\", compileCommandArgsSchema, args);\n}\n\nexport function parseStatusCommandArgs(args: unknown): StatusCommandArgs {\n return parseArgs(\"status\", statusCommandArgsSchema, args);\n}\n\nexport function parseDevCommandArgs(args: unknown): DevCommandArgs {\n return parseArgs(\"dev\", devCommandArgsSchema, args);\n}\n\nexport function parseJoinCommandArgs(args: unknown): JoinCommandArgs {\n return parseArgs(\"join\", joinCommandArgsSchema, args);\n}\n\nexport function parseLoginCommandArgs(args: unknown): LoginCommandArgs {\n return parseArgs(\"login\", loginCommandArgsSchema, args);\n}\n\nexport function parseConfigCommandArgs(args: unknown): ConfigCommandArgs {\n return parseArgs(\"config\", configCommandArgsSchema, args);\n}\n\nexport function parseAuthCommandArgs(args: unknown): AuthCommandArgs {\n return parseArgs(\"auth\", authCommandArgsSchema, args);\n}\n","import path from \"node:path\";\nimport type { RuleInputFlags } from \"../flags.js\";\nimport { readTextFile } from \"./fs.js\";\n\nexport function normalizeSlug(input: string): string {\n const lowered = input.trim().toLowerCase();\n const replaced = lowered.replace(/[^a-z0-9]+/g, \"-\");\n return replaced.replace(/^-+/, \"\").replace(/-+$/, \"\");\n}\n\nexport function titleFromSlug(slug: string): string {\n return slug\n .split(\"-\")\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n}\n\nexport async function readRuleInput(flags: RuleInputFlags): Promise<string> {\n if (flags[\"rule-file\"] && typeof flags[\"rule-file\"] === \"string\") {\n const filePath = path.resolve(process.cwd(), flags[\"rule-file\"]);\n return readTextFile(filePath);\n }\n if (flags.rule && typeof flags.rule === \"string\") {\n return flags.rule;\n }\n throw new Error('Provide rule input via --rule-file or --rule \"...\".');\n}\n\nexport function parsePositiveInt(value: string, label: string): number {\n const parsed = Number.parseInt(value, 10);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(`${label} must be a positive integer.`);\n }\n return parsed;\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import {\n getCompiledResult,\n getJob,\n getLatestCompiledResult,\n getProjectCompiledResult,\n listProjectCompiledResults,\n listCompiledResults,\n queueProjectRevisionCompile,\n type CompiledResult,\n type JobDetailResponse,\n type QueueCompiledResultJobResponse,\n} from \"@dreamboard-games/api-client\";\nimport { toDreamboardApiError } from \"../../utils/errors.js\";\n\nconst COMPILE_JOB_POLL_INTERVAL_MS = 1000;\nconst DEFAULT_COMPILE_JOB_WAIT_TIMEOUT_MS = 10 * 60 * 1000;\nimport { sleep } from \"../../utils/strings.js\";\n\nfunction firstNonEmpty(\n ...values: Array<string | null | undefined>\n): string | null {\n for (const value of values) {\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n }\n return null;\n}\n\nfunction formatTerminalCompileJobMessage(\n job: Pick<\n JobDetailResponse,\n \"createdAt\" | \"errorMessage\" | \"jobId\" | \"message\" | \"phase\" | \"status\"\n >,\n): string {\n const detail = firstNonEmpty(job.errorMessage, job.message);\n const phase = firstNonEmpty(job.phase);\n const prefix = `Compile ${job.status.toLowerCase()}${phase ? ` [${phase}]` : \"\"}`;\n return detail\n ? `${prefix}: ${detail}`\n : `${prefix}: job ${job.jobId} ended before a compiled result was created.`;\n}\n\nfunction compareCreatedAtDesc(\n left: Pick<CompiledResult, \"createdAt\">,\n right: Pick<CompiledResult, \"createdAt\">,\n): number {\n const leftTime = Date.parse(left.createdAt);\n const rightTime = Date.parse(right.createdAt);\n if (Number.isFinite(leftTime) && Number.isFinite(rightTime)) {\n return rightTime - leftTime;\n }\n if (Number.isFinite(rightTime)) {\n return 1;\n }\n if (Number.isFinite(leftTime)) {\n return -1;\n }\n return 0;\n}\n\nasync function findFallbackCompiledResultForJob(options: {\n gameId?: string;\n projectId?: string;\n job: Pick<JobDetailResponse, \"createdAt\">;\n}): Promise<CompiledResult | null> {\n const { gameId, projectId, job } = options;\n const results = projectId\n ? await listProjectCompiledResults({\n path: { projectId },\n query: { limit: 100 },\n })\n : await listCompiledResults({\n path: { gameId: gameId! },\n query: { limit: 100 },\n });\n if (results.error || !results.data) {\n return null;\n }\n if (results.data.results.length === 0) {\n return null;\n }\n\n const jobCreatedAtMs = Date.parse(job.createdAt);\n const resultsCreatedAfterJob = Number.isFinite(jobCreatedAtMs)\n ? results.data.results.filter((result) => {\n const resultCreatedAtMs = Date.parse(result.createdAt);\n return (\n !Number.isFinite(resultCreatedAtMs) ||\n resultCreatedAtMs >= jobCreatedAtMs\n );\n })\n : results.data.results;\n const candidateResults =\n resultsCreatedAfterJob.length > 0\n ? resultsCreatedAfterJob\n : results.data.results;\n\n return [...candidateResults].sort(compareCreatedAtDesc)[0] ?? null;\n}\n\nexport async function findLatestSuccessfulCompiledResult(\n gameId: string,\n): Promise<CompiledResult | null> {\n const { data } = await getLatestCompiledResult({\n path: { gameId },\n query: { successOnly: true },\n });\n return data ?? null;\n}\n\nexport async function findCompiledResultsForAuthoringState(options: {\n gameId: string;\n authoringStateId: string;\n}): Promise<CompiledResult[]> {\n const { gameId, authoringStateId } = options;\n const { data, error, response } = await listCompiledResults({\n path: { gameId },\n query: {\n limit: 100,\n authoringStateId,\n },\n });\n if (error || !data) {\n throw toDreamboardApiError(\n error,\n response,\n \"Failed to list compiled results\",\n );\n }\n return data.results;\n}\n\nexport async function getCompiledResultSdk(\n gameId: string,\n compiledResultId: string,\n): Promise<CompiledResult> {\n const { data, error, response } = await getCompiledResult({\n path: {\n gameId,\n compiledResultId,\n },\n });\n if (error || !data) {\n throw toDreamboardApiError(\n error,\n response,\n \"Failed to fetch compiled result\",\n );\n }\n return data;\n}\n\nexport async function findProjectCompiledResultsForRevision(options: {\n projectId: string;\n revisionDigest: string;\n}): Promise<CompiledResult[]> {\n const { projectId, revisionDigest } = options;\n const { data, error, response } = await listProjectCompiledResults({\n path: { projectId },\n query: { limit: 100 },\n });\n if (error || !data) {\n throw toDreamboardApiError(\n error,\n response,\n \"Failed to list compiled results\",\n );\n }\n return data.results.filter(\n (result) => {\n const maybeRevisionDigest = (result as { revisionDigest?: string })\n .revisionDigest;\n return (\n maybeRevisionDigest === revisionDigest ||\n result.authoringStateId === revisionDigest\n );\n },\n );\n}\n\nexport async function getProjectCompiledResultSdk(\n projectId: string,\n compiledResultId: string,\n): Promise<CompiledResult> {\n const { data, error, response } = await getProjectCompiledResult({\n path: { projectId, compiledResultId },\n });\n if (error || !data) {\n throw toDreamboardApiError(\n error,\n response,\n \"Failed to fetch compiled result\",\n );\n }\n return data;\n}\n\nexport async function queueProjectRevisionCompileSdk(options: {\n projectId: string;\n revisionDigest: string;\n}): Promise<QueueCompiledResultJobResponse> {\n const { data, error, response } = await queueProjectRevisionCompile({\n path: {\n projectId: options.projectId,\n revisionDigest: options.revisionDigest,\n },\n });\n\n if (error || !data) {\n throw toDreamboardApiError(error, response, \"Failed to create compile job\");\n }\n\n return data;\n}\n\nexport async function waitForCompiledResultJobSdk(options: {\n gameId?: string;\n projectId?: string;\n jobId: string;\n onProgress?: (job: JobDetailResponse) => void;\n}): Promise<{\n job: JobDetailResponse;\n compiledResult: CompiledResult;\n}> {\n const { gameId, projectId, jobId, onProgress } = options;\n let previousTransitionKey: string | null = null;\n const startedAt = Date.now();\n const timeoutMs = readCompileJobWaitTimeoutMs();\n\n while (Date.now() - startedAt < timeoutMs) {\n const {\n data: job,\n error,\n response,\n } = await getJob({\n path: { jobId },\n });\n if (error || !job) {\n if (isTransientJobPollError(error, response)) {\n await sleep(COMPILE_JOB_POLL_INTERVAL_MS);\n continue;\n }\n throw toDreamboardApiError(error, response, \"Failed to get job\");\n }\n\n const transitionKey = `${job.status}:${job.phase ?? \"\"}`;\n if (transitionKey !== previousTransitionKey) {\n previousTransitionKey = transitionKey;\n onProgress?.(job);\n }\n\n if (job.status === \"COMPLETED\" || job.status === \"FAILED\") {\n const compiledResultId =\n job.createdCompiledResultId ?? job.createdAppScriptId;\n if (compiledResultId) {\n if (projectId) {\n const compiledResult = await getProjectCompiledResultSdk(\n projectId,\n compiledResultId,\n );\n return { job, compiledResult };\n }\n const compiledResult = await getCompiledResultSdk(\n gameId!,\n compiledResultId,\n );\n return { job, compiledResult };\n }\n\n const fallbackCompiledResult = await findFallbackCompiledResultForJob({\n gameId,\n projectId,\n job,\n });\n if (fallbackCompiledResult) {\n return { job, compiledResult: fallbackCompiledResult };\n }\n\n throw new Error(formatTerminalCompileJobMessage(job));\n }\n\n if (job.status === \"CANCELLED\" || job.status === \"INTERRUPTED\") {\n throw new Error(formatTerminalCompileJobMessage(job));\n }\n\n await sleep(COMPILE_JOB_POLL_INTERVAL_MS);\n }\n\n throw new Error(`Compile job ${jobId} did not complete in time.`);\n}\n\nfunction readCompileJobWaitTimeoutMs(): number {\n const raw = process.env.DREAMBOARD_COMPILE_WAIT_TIMEOUT_MS;\n if (!raw) return DEFAULT_COMPILE_JOB_WAIT_TIMEOUT_MS;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n return DEFAULT_COMPILE_JOB_WAIT_TIMEOUT_MS;\n }\n return parsed;\n}\n\nfunction isTransientJobPollError(error: unknown, response: unknown): boolean {\n if (response) return false;\n if (!error) return false;\n if (error instanceof Error) {\n return isTransientJobPollMessage(error.message);\n }\n if (typeof error === \"object\" && error !== null && \"message\" in error) {\n return isTransientJobPollMessage(String(error.message));\n }\n return isTransientJobPollMessage(String(error));\n}\n\nfunction isTransientJobPollMessage(message: string): boolean {\n const normalized = message.toLowerCase();\n return (\n normalized.includes(\"fetch failed\") ||\n normalized.includes(\"network\") ||\n normalized.includes(\"timeout\") ||\n normalized.includes(\"econnreset\") ||\n normalized.includes(\"econnrefused\") ||\n normalized.includes(\"socket\")\n );\n}\n","import {\n createGameRevision,\n createProjectSession,\n createProjectSessionFromReducerSnapshot,\n ensureProject,\n ensureProjectDevCompile,\n getApiVersion,\n getCurrentAuthUser,\n getProjectBySlug,\n getProjectRevisionSources,\n getProjectSources,\n type CreateSessionFromReducerSnapshotRequest,\n type CreateSessionRequest,\n type CreateSessionResponse,\n type CreateGameRevisionRequest,\n type EnsureDevCompileRequest,\n type EnsureDevCompileResponse,\n type GameRevision,\n type GameSourcesResponse,\n type HostSessionSnapshot,\n type Project,\n type ProjectRevisionSourcesResponse,\n} from \"@dreamboard-games/api-client\";\nimport { toDreamboardApiError } from \"../../utils/errors.js\";\nimport { titleFromSlug } from \"../../utils/strings.js\";\n\nexport type RemoteProjectIdentity = {\n deploymentId: string;\n ownerScopeId: string;\n bindingKey: string;\n};\n\nexport async function loadRemoteProjectIdentity(): Promise<RemoteProjectIdentity> {\n const [versionResponse, userResponse] = await Promise.all([\n getApiVersion(),\n getCurrentAuthUser(),\n ]);\n\n if (versionResponse.error || !versionResponse.data) {\n throw toDreamboardApiError(\n versionResponse.error as Parameters<typeof toDreamboardApiError>[0],\n versionResponse.response,\n \"Failed to resolve backend deployment identity\",\n );\n }\n if (userResponse.error || !userResponse.data) {\n throw toDreamboardApiError(\n userResponse.error,\n userResponse.response,\n \"Failed to resolve authenticated owner scope\",\n );\n }\n\n const deploymentId = versionResponse.data.deploymentId;\n const ownerScopeId = userResponse.data.ownerScopeId;\n return {\n deploymentId,\n ownerScopeId,\n bindingKey: `${deploymentId}:${ownerScopeId}`,\n };\n}\n\nexport async function ensureProjectSdk(options: {\n projectId: string;\n slug: string;\n description?: string;\n updateAlias?: boolean;\n}): Promise<Project> {\n const { data, error, response } = await ensureProject({\n path: { projectId: options.projectId },\n body: {\n slug: options.slug,\n name: titleFromSlug(options.slug),\n description:\n options.description ?? `Dreamboard workspace for ${options.slug}.`,\n ...(options.updateAlias ? { updateAlias: true } : {}),\n },\n });\n\n if (error || !data) {\n throw toDreamboardApiError(error, response, \"Failed to ensure project\");\n }\n\n return data;\n}\n\nexport async function getProjectBySlugSdk(slug: string): Promise<Project> {\n const { data, error, response } = await getProjectBySlug({\n path: { slug },\n });\n\n if (error || !data) {\n throw toDreamboardApiError(\n error,\n response,\n `Project '${slug}' not found`,\n );\n }\n\n return data;\n}\n\nexport async function createGameRevisionSdk(options: {\n projectId: string;\n request: CreateGameRevisionRequest;\n}): Promise<GameRevision> {\n const { data, error, response } = await createGameRevision({\n path: { projectId: options.projectId },\n body: options.request,\n });\n\n if (error || !data) {\n throw toDreamboardApiError(\n error,\n response,\n \"Failed to create game revision\",\n );\n }\n\n return data;\n}\n\nexport async function getProjectSourcesSdk(\n projectId: string,\n): Promise<GameSourcesResponse | null> {\n const { data, error, response } = await getProjectSources({\n path: { projectId },\n });\n\n if (response?.status === 404) {\n return null;\n }\n if (error || !data) {\n throw toDreamboardApiError(\n error,\n response,\n \"Failed to fetch project sources\",\n );\n }\n\n return data;\n}\n\nexport async function getProjectRevisionSourcesSdk(options: {\n projectId: string;\n revisionDigest: string;\n}): Promise<ProjectRevisionSourcesResponse> {\n const { data, error, response } = await getProjectRevisionSources({\n path: {\n projectId: options.projectId,\n revisionDigest: options.revisionDigest,\n },\n });\n\n if (error || !data) {\n throw toDreamboardApiError(\n error,\n response,\n \"Failed to fetch project revision sources\",\n );\n }\n\n return data;\n}\n\nexport async function ensureProjectDevCompileSdk(options: {\n projectId: string;\n request: EnsureDevCompileRequest;\n}): Promise<EnsureDevCompileResponse> {\n const { data, error, response } = await ensureProjectDevCompile({\n path: { projectId: options.projectId },\n body: options.request,\n });\n\n if (error || !data) {\n throw toDreamboardApiError(error, response, \"Failed to ensure dev compile\");\n }\n\n return data;\n}\n\nexport async function createProjectSessionSdk(options: {\n projectId: string;\n request: CreateSessionRequest;\n}): Promise<CreateSessionResponse> {\n const { data, error, response } = await createProjectSession({\n path: { projectId: options.projectId },\n body: options.request,\n });\n\n if (error || !data) {\n throw toDreamboardApiError(error, response, \"Failed to create session\");\n }\n\n return data;\n}\n\nexport async function createProjectSessionFromReducerSnapshotSdk(options: {\n projectId: string;\n request: CreateSessionFromReducerSnapshotRequest;\n}): Promise<HostSessionSnapshot> {\n const { data, error, response } =\n await createProjectSessionFromReducerSnapshot({\n path: { projectId: options.projectId },\n body: options.request,\n });\n\n if (error || !data) {\n throw toDreamboardApiError(\n error,\n response,\n \"Failed to create session from reducer snapshot\",\n );\n }\n\n return data;\n}\n","import { uploadInitialProjection } from \"@dreamboard-games/api-client\";\nimport { toDreamboardApiError } from \"../../utils/errors.js\";\n\nexport async function uploadInitialProjectionSdk(\n gameId: string,\n projectionJson: string,\n): Promise<void> {\n const { error, response } = await uploadInitialProjection({\n path: { gameId },\n body: { projectionJson },\n });\n if (error) {\n throw toDreamboardApiError(\n error,\n response,\n \"Failed to upload initial preview projection\",\n );\n }\n}\n","import {\n createSourceRevision,\n type CreateSourceRevisionRequest,\n queueCompiledResultJob,\n type QueueCompiledResultJobResponse,\n type SourceRevision,\n} from \"@dreamboard-games/api-client\";\nimport {\n SourceBlobSessionRequestError,\n uploadGameSourceBlobs,\n uploadProjectSourceBlobs,\n type SourceBlobUploadInput,\n} from \"@dreamboard-games/api-client/source-revisions\";\nimport { toDreamboardApiError } from \"../../utils/errors.js\";\n\nexport async function createSourceRevisionSdk(\n gameId: string,\n request: CreateSourceRevisionRequest,\n): Promise<SourceRevision> {\n const response = await createSourceRevision({\n path: { gameId },\n body: request,\n });\n\n if (response.error || !response.data) {\n throw toDreamboardApiError(\n response.error,\n response.response,\n \"Failed to create source revision\",\n );\n }\n\n return response.data;\n}\n\nexport async function uploadSourceBlobsSdk(\n gameId: string,\n blobs: SourceBlobUploadInput[],\n): Promise<void> {\n try {\n await uploadGameSourceBlobs({ gameId, blobs });\n } catch (error) {\n if (error instanceof SourceBlobSessionRequestError) {\n throw toDreamboardApiError(\n error.apiError as Parameters<typeof toDreamboardApiError>[0],\n error.response,\n error.message,\n );\n }\n throw error;\n }\n}\n\nexport async function uploadProjectSourceBlobsSdk(\n projectId: string,\n blobs: SourceBlobUploadInput[],\n): Promise<void> {\n try {\n await uploadProjectSourceBlobs({ projectId, blobs });\n } catch (error) {\n if (error instanceof SourceBlobSessionRequestError) {\n throw toDreamboardApiError(\n error.apiError as Parameters<typeof toDreamboardApiError>[0],\n error.response,\n error.message,\n );\n }\n throw error;\n }\n}\n\nexport async function queueCompiledResultJobSdk(options: {\n gameId: string;\n authoringStateId: string;\n}): Promise<QueueCompiledResultJobResponse> {\n const { gameId, authoringStateId } = options;\n const { data, error, response } = await queueCompiledResultJob({\n path: { gameId },\n body: {\n authoringStateId,\n },\n });\n\n if (error || !data) {\n throw toDreamboardApiError(error, response, \"Failed to create compile job\");\n }\n\n return data;\n}\n"],"mappings":"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","names":["error","compiledResult"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/services/project/local-files.ts"],"sourcesContent":["import { readdir, unlink } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { GameTopologyManifest } from \"@dreamboard-games/sdk/types\";\nimport {\n PROJECT_DIR_NAME,\n MANIFEST_FILE,\n RULE_FILE,\n SNAPSHOT_FILE,\n LOCAL_IGNORE_DIRS,\n} from \"../../constants.js\";\nimport type { Snapshot } from \"../../types.js\";\nimport {\n readJsonFile,\n readTextFile,\n readTextFileIfExists,\n writeTextFile,\n} from \"../../utils/fs.js\";\nimport { atomicWriteFile } from \"../../utils/atomic-file.js\";\nimport { hashContent } from \"../../utils/crypto.js\";\nimport {\n computeManifestHash,\n materializeManifest,\n writeManifestSource,\n} from \"./manifest-authoring.js\";\nimport {\n isAllowedGamePath as isAllowedPathFromOwnership,\n isDynamicGeneratedPath,\n isLibraryPath as isLibraryPathFromOwnership,\n} from \"./scaffold-ownership.js\";\n\n/**\n * Returns true when a path is inside the canonical game project structure.\n * Anything outside app/, ui/, shared/, or the known root files is rejected.\n */\nexport function isAllowedGamePath(filePath: string): boolean {\n return isAllowedPathFromOwnership(filePath);\n}\n\nexport function isLibraryPath(filePath: string): boolean {\n return isLibraryPathFromOwnership(filePath);\n}\n\ntype WriteDecision = \"write\" | \"skip\";\n\n/**\n * Decide whether a file from the scaffold response should be written to disk.\n *\n * - Library files → always overwrite (they are fully generated).\n * - Everything else → only write if the file does not yet exist or is empty\n * locally (first-time seeding; preserves user edits).\n */\nfunction shouldWriteScaffoldFile(\n filePath: string,\n existingContent: string | null,\n): WriteDecision {\n if (isLibraryPath(filePath)) return \"write\";\n const hasContent =\n existingContent !== null && existingContent.trim().length > 0;\n return hasContent ? \"skip\" : \"write\";\n}\n\nexport async function writeSourceFiles(\n rootDir: string,\n files: Record<string, string | null>,\n): Promise<void> {\n for (const [relativePath, content] of Object.entries(files)) {\n if (content === null || content === undefined) continue;\n const filePath = path.join(rootDir, relativePath);\n await writeTextFile(filePath, content);\n }\n}\n\nexport interface ScaffoldWriteResult {\n written: string[];\n skipped: string[];\n}\n\n/**\n * Write scaffold files using local-merge logic.\n *\n * - Library files are always overwritten.\n * - User-owned files (phases, components, etc.) are only written when the\n * local file does not exist or is empty. Files with content are skipped\n * so user edits are never lost.\n *\n * Returns lists of files that were written (and actually changed) and files\n * that were skipped because a non-empty local copy already exists.\n */\nexport async function writeScaffoldFiles(\n rootDir: string,\n files: Record<string, string | null>,\n): Promise<ScaffoldWriteResult> {\n const written: string[] = [];\n const skipped: string[] = [];\n\n for (const [relativePath, content] of Object.entries(files)) {\n if (content === null || content === undefined) continue;\n\n const fullPath = path.join(rootDir, relativePath);\n const existingContent = await readTextFileIfExists(fullPath);\n\n const decision = shouldWriteScaffoldFile(relativePath, existingContent);\n\n if (decision === \"skip\") {\n skipped.push(relativePath);\n continue;\n }\n\n await writeTextFile(fullPath, content);\n\n if (existingContent !== content) {\n written.push(relativePath);\n }\n }\n\n written.sort();\n skipped.sort();\n return { written, skipped };\n}\n\nexport async function removeExtraneousFiles(\n rootDir: string,\n keep: Set<string>,\n): Promise<void> {\n const localFiles = await collectLocalFiles(rootDir);\n for (const filePath of Object.keys(localFiles)) {\n if (filePath === MANIFEST_FILE || filePath === RULE_FILE) continue;\n if (!keep.has(filePath)) {\n await unlink(path.join(rootDir, filePath));\n }\n }\n}\n\nexport async function collectLocalFiles(\n rootDir: string,\n): Promise<Record<string, string>> {\n const result: Record<string, string> = {};\n await walkDir(rootDir, rootDir, result);\n return result;\n}\n\nexport async function walkDir(\n rootDir: string,\n currentDir: string,\n result: Record<string, string>,\n): Promise<void> {\n const entries = await readdir(currentDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) {\n if (LOCAL_IGNORE_DIRS.has(entry.name)) continue;\n await walkDir(rootDir, path.join(currentDir, entry.name), result);\n } else if (entry.isFile()) {\n const filePath = path.join(currentDir, entry.name);\n const relativePath = path.relative(rootDir, filePath);\n result[relativePath] = await readTextFile(filePath);\n }\n }\n}\n\nexport async function writeManifest(\n rootDir: string,\n manifest: GameTopologyManifest,\n): Promise<void> {\n await writeManifestSource(rootDir, manifest);\n}\n\nexport async function writeRule(\n rootDir: string,\n ruleText: string,\n): Promise<void> {\n const filePath = path.join(rootDir, RULE_FILE);\n await writeTextFile(filePath, ruleText);\n}\n\nexport async function loadManifest(\n rootDir: string,\n): Promise<GameTopologyManifest> {\n return materializeManifest(rootDir);\n}\n\nexport { computeManifestHash };\n\nexport async function loadRule(rootDir: string): Promise<string> {\n const filePath = path.join(rootDir, RULE_FILE);\n return readTextFile(filePath);\n}\n\nexport async function writeSnapshot(rootDir: string): Promise<void> {\n const files = await collectLocalFiles(rootDir);\n await writeSnapshotFromFiles(rootDir, files);\n}\n\nexport async function writeSnapshotFromFiles(\n rootDir: string,\n files: Record<string, string>,\n): Promise<void> {\n const snapshot: Snapshot = {\n files: {},\n };\n\n for (const [filePath, content] of Object.entries(files)) {\n if (filePath.startsWith(`${PROJECT_DIR_NAME}/`)) continue;\n if (isDynamicGeneratedPath(filePath)) continue;\n snapshot.files[filePath] = hashContent(content);\n }\n\n const snapshotPath = path.join(rootDir, PROJECT_DIR_NAME, SNAPSHOT_FILE);\n // Atomic write: a crash mid-snapshot (e.g. user kills a long `dreamboard\n // sync`) must not leave `.dreamboard/snapshot.json` truncated, or\n // `getLocalDiff` will silently report everything as \"added\" on the\n // next run and force a full re-sync.\n await atomicWriteFile(\n snapshotPath,\n `${JSON.stringify(snapshot, null, 2)}\\n`,\n { mode: 0o644 },\n );\n}\n\nfunction isIgnorableLocalDiffPath(filePath: string): boolean {\n return (\n filePath.startsWith(\"test/generated/\") ||\n filePath.startsWith(\".playwright-cli/\")\n );\n}\n\nexport async function getLocalDiff(rootDir: string): Promise<{\n modified: string[];\n added: string[];\n deleted: string[];\n}> {\n const snapshotPath = path.join(rootDir, PROJECT_DIR_NAME, SNAPSHOT_FILE);\n const snapshot = await readJsonFile<Snapshot>(snapshotPath).catch(() => null);\n if (!snapshot) {\n return { modified: [], added: [], deleted: [] };\n }\n\n const files = await collectLocalFiles(rootDir);\n const currentHashes: Record<string, string> = {};\n\n for (const [filePath, content] of Object.entries(files)) {\n if (filePath.startsWith(`${PROJECT_DIR_NAME}/`)) continue;\n if (isIgnorableLocalDiffPath(filePath)) continue;\n if (isDynamicGeneratedPath(filePath)) continue;\n currentHashes[filePath] = hashContent(content);\n }\n\n const modified: string[] = [];\n const added: string[] = [];\n const deleted: string[] = [];\n\n for (const [filePath, hash] of Object.entries(currentHashes)) {\n const prevHash = snapshot.files[filePath];\n if (!prevHash) {\n added.push(filePath);\n } else if (prevHash !== hash) {\n modified.push(filePath);\n }\n }\n\n for (const filePath of Object.keys(snapshot.files)) {\n if (isIgnorableLocalDiffPath(filePath)) continue;\n if (isDynamicGeneratedPath(filePath)) continue;\n if (!currentHashes[filePath]) {\n deleted.push(filePath);\n }\n }\n\n return { modified, added, deleted };\n}\n"],"mappings":"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","names":["isAllowedGamePath","isLibraryPath"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/services/project/workspace-dependencies.ts","../../src/services/project/dependency-tooling-messages.ts"],"sourcesContent":["import crypto from \"node:crypto\";\nimport { spawn } from \"node:child_process\";\nimport { EventEmitter } from \"node:events\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, lstat, readFile, rm, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Readable } from \"node:stream\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n buildDependencyPreparationFailureMessage,\n buildMissingDependencyToolingMessage,\n buildMissingGeneratedLockfileMessage,\n buildPackageLockConflictMessage,\n} from \"./dependency-tooling-messages.js\";\nimport { FRAMEWORK_PNPM_OVERRIDES } from \"./framework-dependencies.js\";\n\ntype LockfileGenerationOptions = Record<string, never>;\n\ntype PackageJsonShape = {\n packageManager?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n pnpm?: Record<string, unknown>;\n};\n\ntype DependencyInstallMetadata = {\n dependencyFingerprint: string;\n installedAt: string;\n packageManager: string;\n};\n\ntype LockfileCommand = {\n binary: string;\n args: string[];\n};\n\nexport type WorkspaceDependencyReconciliationResult = {\n required: boolean;\n installed: boolean;\n lockfileGenerated: boolean;\n packageManagerNormalized: boolean;\n fingerprint: string | null;\n};\n\nconst MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));\nconst CLI_ROOT = path.resolve(MODULE_DIR, \"../../..\");\nconst REPO_ROOT = path.resolve(CLI_ROOT, \"../..\");\nconst REPO_PACKAGE_JSON_PATH = path.join(REPO_ROOT, \"package.json\");\nconst DEFAULT_PACKAGE_MANAGER = \"pnpm@10.4.1\";\nconst SDK_PACKAGE_NAME = \"@dreamboard-games/sdk\";\nconst SDK_REQUIRED_DIST_FILES = [\n \"dist/index.d.ts\",\n \"dist/index.js\",\n \"dist/types.d.ts\",\n \"dist/types.js\",\n \"dist/ui.d.ts\",\n \"dist/ui.js\",\n \"dist/runtime.d.ts\",\n \"dist/runtime.js\",\n] as const;\nconst DEPENDENCY_INSTALL_METADATA_PATH_SEGMENTS = [\n \".dreamboard\",\n \"dependency-install.json\",\n] as const;\n\nclass LockfileGenerationError extends Error {\n constructor(\n readonly binary: string,\n readonly details: {\n code?: number | null;\n stdout: string;\n stderr: string;\n cause?: Error;\n },\n ) {\n super(buildLockfileGenerationErrorMessage(binary, details), {\n cause: details.cause,\n });\n this.name = \"LockfileGenerationError\";\n }\n}\n\nexport async function generatePnpmLockfile(\n projectRoot: string,\n _options: LockfileGenerationOptions = {},\n): Promise<boolean> {\n await ensurePackageManagerNormalized(projectRoot);\n await assertNoNpmLockfileConflict(projectRoot);\n await runPackageManagerCommand(projectRoot, {\n args: [\n \"install\",\n \"--ignore-workspace\",\n \"--lockfile-only\",\n \"--config.shared-workspace-lockfile=false\",\n ],\n });\n await assertPnpmLockfilePresent(projectRoot);\n return true;\n}\n\nexport async function installWorkspaceDependencies(\n projectRoot: string,\n _options: LockfileGenerationOptions = {},\n): Promise<boolean> {\n const result = await reconcileWorkspaceDependencies(projectRoot);\n return result.required;\n}\n\nexport async function reconcileWorkspaceDependencies(\n projectRoot: string,\n): Promise<WorkspaceDependencyReconciliationResult> {\n const packageJsonPath = path.join(projectRoot, \"package.json\");\n if (!(await pathExists(packageJsonPath))) {\n return {\n required: false,\n installed: false,\n lockfileGenerated: false,\n packageManagerNormalized: false,\n fingerprint: null,\n };\n }\n\n await assertNoNpmLockfileConflict(projectRoot);\n const packageManagerNormalized =\n await ensurePackageManagerNormalized(projectRoot);\n const pnpmLockfilePath = path.join(projectRoot, \"pnpm-lock.yaml\");\n const nodeModulesPath = path.join(projectRoot, \"node_modules\");\n const metadataPath = path.join(\n projectRoot,\n ...DEPENDENCY_INSTALL_METADATA_PATH_SEGMENTS,\n );\n\n let lockfileGenerated = false;\n let installed = false;\n const metadata = await readJsonFile<DependencyInstallMetadata>(metadataPath);\n const lockfileExists = await pathExists(pnpmLockfilePath);\n\n if (!lockfileExists) {\n await runPackageManagerCommand(projectRoot, {\n args: [\n \"install\",\n \"--ignore-workspace\",\n \"--config.shared-workspace-lockfile=false\",\n ],\n });\n lockfileGenerated = true;\n installed = true;\n }\n\n await assertPnpmLockfilePresent(projectRoot);\n let fingerprint = await fingerprintInstallManifest({\n packageJsonPath,\n lockfilePath: pnpmLockfilePath,\n });\n const hasValidInstalledDeps =\n (await pathExists(nodeModulesPath)) &&\n (await hasValidInstalledDependencies({\n packageJsonPath,\n nodeModulesPath,\n }));\n const shouldInstall =\n !installed &&\n (metadata?.dependencyFingerprint !== fingerprint || !hasValidInstalledDeps);\n\n if (shouldInstall) {\n await rm(nodeModulesPath, { recursive: true, force: true });\n await runPackageManagerCommand(projectRoot, {\n args: [\n \"install\",\n \"--ignore-workspace\",\n \"--config.shared-workspace-lockfile=false\",\n ],\n });\n installed = true;\n fingerprint = await fingerprintInstallManifest({\n packageJsonPath,\n lockfilePath: pnpmLockfilePath,\n });\n }\n\n if (installed || packageManagerNormalized || !metadata) {\n await mkdir(path.dirname(metadataPath), { recursive: true });\n await writeJsonFile(metadataPath, {\n dependencyFingerprint: fingerprint,\n installedAt: new Date().toISOString(),\n packageManager: await readRepoPackageManager(),\n } satisfies DependencyInstallMetadata);\n }\n\n return {\n required: true,\n installed,\n lockfileGenerated,\n packageManagerNormalized,\n fingerprint,\n };\n}\n\nasync function assertNoNpmLockfileConflict(projectRoot: string): Promise<void> {\n const packageLockPath = path.join(projectRoot, \"package-lock.json\");\n const pnpmLockPath = path.join(projectRoot, \"pnpm-lock.yaml\");\n if (\n (await pathExists(packageLockPath)) &&\n !(await pathExists(pnpmLockPath))\n ) {\n throw new Error(buildPackageLockConflictMessage());\n }\n}\n\nasync function assertPnpmLockfilePresent(projectRoot: string): Promise<void> {\n const pnpmLockfilePath = path.join(projectRoot, \"pnpm-lock.yaml\");\n if (!(await pathExists(pnpmLockfilePath))) {\n throw new Error(buildMissingGeneratedLockfileMessage());\n }\n}\n\nasync function ensurePackageManagerNormalized(\n projectRoot: string,\n): Promise<boolean> {\n const packageJsonPath = path.join(projectRoot, \"package.json\");\n const packageJsonContent = await readFile(packageJsonPath, \"utf8\");\n const packageJson = JSON.parse(packageJsonContent) as PackageJsonShape;\n const packageManager = await readRepoPackageManager();\n const nextPackageJson: PackageJsonShape = {\n ...packageJson,\n packageManager,\n pnpm: mergePnpmConfig(packageJson.pnpm),\n };\n const normalizedPackageJson = `${JSON.stringify(nextPackageJson, null, 2)}\\n`;\n if (normalizedPackageJson === packageJsonContent) {\n return false;\n }\n await writeFile(packageJsonPath, normalizedPackageJson, \"utf8\");\n return true;\n}\n\nfunction mergePnpmConfig(\n existingPnpm: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n const existingOverrides =\n existingPnpm?.overrides &&\n typeof existingPnpm.overrides === \"object\" &&\n !Array.isArray(existingPnpm.overrides)\n ? (existingPnpm.overrides as Record<string, unknown>)\n : {};\n return {\n ...(existingPnpm ?? {}),\n overrides: {\n ...existingOverrides,\n ...FRAMEWORK_PNPM_OVERRIDES,\n },\n };\n}\n\nasync function fingerprintInstallManifest(options: {\n packageJsonPath: string;\n lockfilePath: string;\n}): Promise<string> {\n const packageJson = await readFile(options.packageJsonPath, \"utf8\");\n const lockfile = await readFile(options.lockfilePath, \"utf8\");\n const packageManager = await readRepoPackageManager();\n return fingerprintContent([\n packageJson,\n lockfile,\n `packageManager:${packageManager}`,\n ]);\n}\n\nasync function hasValidInstalledDependencies(options: {\n packageJsonPath: string;\n nodeModulesPath: string;\n}): Promise<boolean> {\n const packageJson = await readJsonFile<PackageJsonShape>(\n options.packageJsonPath,\n );\n if (!packageJson) {\n return false;\n }\n\n const directDependencyNames = new Set<string>();\n for (const field of [\n \"dependencies\",\n \"devDependencies\",\n \"optionalDependencies\",\n ] as const) {\n for (const packageName of Object.keys(packageJson[field] ?? {})) {\n directDependencyNames.add(packageName);\n }\n }\n\n if (directDependencyNames.size === 0) {\n return true;\n }\n\n for (const packageName of directDependencyNames) {\n const packageRoot = path.join(\n options.nodeModulesPath,\n ...packageName.split(\"/\"),\n );\n if (!(await pathExists(path.join(packageRoot, \"package.json\")))) {\n return false;\n }\n if (\n packageName === SDK_PACKAGE_NAME &&\n !(await hasInstalledSdkDistFiles(packageRoot))\n ) {\n return false;\n }\n }\n\n return true;\n}\n\nasync function hasInstalledSdkDistFiles(packageRoot: string): Promise<boolean> {\n for (const relativePath of SDK_REQUIRED_DIST_FILES) {\n if (!(await pathExists(path.join(packageRoot, relativePath)))) {\n return false;\n }\n }\n return true;\n}\n\nfunction hasExactPnpmVersion(value?: string): boolean {\n return /^pnpm@\\d+\\.\\d+\\.\\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(value ?? \"\");\n}\n\nasync function readRepoPackageManager(): Promise<string> {\n const packageJson = await readJsonFile<PackageJsonShape>(\n REPO_PACKAGE_JSON_PATH,\n );\n const packageManager = packageJson?.packageManager?.trim();\n return hasExactPnpmVersion(packageManager)\n ? packageManager!\n : DEFAULT_PACKAGE_MANAGER;\n}\n\nfunction fingerprintContent(parts: string[]): string {\n return crypto\n .createHash(\"sha256\")\n .update(parts.join(\"\\n---\\n\"))\n .digest(\"hex\");\n}\n\nfunction resolvePnpmInstallInvocation(installArgs: readonly string[]): {\n command: string;\n args: string[];\n} {\n const corepackPath = path.join(path.dirname(process.execPath), \"corepack\");\n if (existsSync(corepackPath)) {\n return { command: corepackPath, args: [\"pnpm\", ...installArgs] };\n }\n return { command: \"pnpm\", args: [...installArgs] };\n}\n\nasync function runPackageManagerCommand(\n projectRoot: string,\n command: { args: string[] },\n): Promise<void> {\n const invocation = resolvePnpmInstallInvocation(command.args);\n await runLockfileCommand(projectRoot, {\n binary: invocation.command,\n args: invocation.args,\n });\n}\n\nasync function runLockfileCommand(\n projectRoot: string,\n command: LockfileCommand,\n): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(command.binary, command.args, {\n cwd: projectRoot,\n env: process.env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n bindStream(child.stdout, (chunk) => {\n stdout += chunk.toString();\n });\n bindStream(child.stderr, (chunk) => {\n stderr += chunk.toString();\n });\n\n child.on(\"error\", (cause) => {\n reject(\n new LockfileGenerationError(command.binary, {\n stdout,\n stderr,\n cause,\n }),\n );\n });\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n return;\n }\n reject(\n new LockfileGenerationError(command.binary, {\n code,\n stdout,\n stderr,\n }),\n );\n });\n });\n}\n\nfunction buildLockfileGenerationErrorMessage(\n binary: string,\n details: {\n code?: number | null;\n stdout: string;\n stderr: string;\n cause?: Error;\n },\n): string {\n if (details.cause) {\n const errnoError = details.cause as NodeJS.ErrnoException;\n const binaryName = path.basename(binary).toLowerCase();\n if (\n errnoError.code === \"ENOENT\" &&\n (binaryName === \"pnpm\" ||\n binaryName === \"pnpm.cmd\" ||\n binaryName === \"corepack\" ||\n binaryName === \"corepack.exe\")\n ) {\n return buildMissingDependencyToolingMessage();\n }\n return `Failed to start ${binary} for Dreamboard dependency reconciliation. ${details.cause.message}`;\n }\n\n const output = [details.stdout.trim(), details.stderr.trim()]\n .filter((chunk) => chunk.length > 0)\n .join(\"\\n\");\n\n return buildDependencyPreparationFailureMessage({\n exitCode: details.code,\n output,\n });\n}\n\nasync function pathExists(targetPath: string): Promise<boolean> {\n try {\n await lstat(targetPath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readJsonFile<T>(filePath: string): Promise<T | null> {\n try {\n return JSON.parse(await readFile(filePath, \"utf8\")) as T;\n } catch {\n return null;\n }\n}\n\nasync function writeJsonFile(filePath: string, value: unknown): Promise<void> {\n await writeFile(filePath, `${JSON.stringify(value, null, 2)}\\n`, \"utf8\");\n}\n\nfunction bindStream(\n stream: Readable | EventEmitter | null | undefined,\n onData: (chunk: Buffer | string) => void,\n): void {\n stream?.on(\"data\", onData);\n}\n","import { DEFAULT_WEB_BASE_URL } from \"../../constants.js\";\n\nexport const DEPENDENCY_SETUP_DOCS_PATH = \"/docs/reference/dependency-setup\";\nexport const DEPENDENCY_SETUP_DOCS_URL = `${DEFAULT_WEB_BASE_URL}${DEPENDENCY_SETUP_DOCS_PATH}`;\n\nexport function buildMissingDependencyToolingMessage(): string {\n return [\n \"Dreamboard needs dependency tooling to finish `dreamboard sync`.\",\n \"Use Node 24+ with Corepack enabled, then run `dreamboard sync` again.\",\n \"If Corepack is unavailable on this machine, install pnpm globally with `npm install -g pnpm`.\",\n `Help: ${DEPENDENCY_SETUP_DOCS_URL}`,\n ].join(\"\\n\");\n}\n\nexport function buildPackageLockConflictMessage(): string {\n return [\n \"Dreamboard manages workspace dependencies during `dreamboard sync`.\",\n \"This workspace has an npm lockfile that conflicts with Dreamboard-managed dependencies.\",\n \"Remove `package-lock.json` and run `dreamboard sync` again.\",\n `Help: ${DEPENDENCY_SETUP_DOCS_URL}`,\n ].join(\"\\n\");\n}\n\nexport function buildMissingGeneratedLockfileMessage(): string {\n return [\n \"Dreamboard could not finish preparing workspace dependencies during `dreamboard sync`.\",\n \"Diagnostic: `pnpm-lock.yaml` was not created.\",\n `Help: ${DEPENDENCY_SETUP_DOCS_URL}`,\n ].join(\"\\n\");\n}\n\nexport function buildDependencyPreparationFailureMessage(options: {\n output?: string;\n exitCode?: number | null;\n}): string {\n const details = options.output?.trim();\n return [\n `Dreamboard could not finish preparing workspace dependencies during \\`dreamboard sync\\`${options.exitCode != null ? ` (exit code ${options.exitCode})` : \"\"}.`,\n details ? `Diagnostic output:\\n${details}` : null,\n `Help: ${DEPENDENCY_SETUP_DOCS_URL}`,\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
@@ -1,312 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- resolveRemoteProject
4
- } from "./chunk-HGMUAL33.mjs";
5
- import {
6
- CONFIG_FLAG_ARGS,
7
- defineCommand,
8
- findProjectCompiledResultsForRevision,
9
- parseCompileCommandArgs,
10
- queueProjectRevisionCompileSdk,
11
- waitForCompiledResultJobSdk
12
- } from "./chunk-W3N3QJ4V.mjs";
13
- import {
14
- getProjectAuthoringState,
15
- getProjectPendingAuthoringSync,
16
- setLatestCompileAttempt
17
- } from "./chunk-YE7UAO3T.mjs";
18
- import {
19
- runLocalTypecheck
20
- } from "./chunk-UIOLGH4A.mjs";
21
- import {
22
- formatCliError
23
- } from "./chunk-S34FRJHS.mjs";
24
- import {
25
- assertCompilerPortableDependencies,
26
- assertReleaseEnvironmentPortableDependencies,
27
- consola,
28
- resolveProjectContext
29
- } from "./chunk-3UKQVWLV.mjs";
30
- import "./chunk-SH5JKYOB.mjs";
31
- import {
32
- getLocalDiff
33
- } from "./chunk-XGWCY624.mjs";
34
- import {
35
- assertCliStaticScaffoldComplete
36
- } from "./chunk-7WWGFAAU.mjs";
37
- import "./chunk-F2DIOJJZ.mjs";
38
- import {
39
- updateProjectState
40
- } from "./chunk-776W3UGV.mjs";
41
- import "./chunk-O4YCPU7C.mjs";
42
- import "./chunk-VS573ERH.mjs";
43
- import "./chunk-UIZNWRM6.mjs";
44
- import "./chunk-NAK77WXW.mjs";
45
- import "./chunk-TAEQKBJB.mjs";
46
- import "./chunk-IAYRNVUC.mjs";
47
- import "./chunk-ZEELHSY3.mjs";
48
- import "./chunk-H76MT5UR.mjs";
49
- import "./chunk-SKI2ESE5.mjs";
50
-
51
- // src/commands/compile.ts
52
- function formatDiagnosticsSummary(diagnostics) {
53
- const firstMessage = diagnostics?.find(
54
- (diagnostic) => diagnostic.message
55
- )?.message;
56
- return firstMessage?.trim() || void 0;
57
- }
58
- function formatCompileJobProgressMessage(job) {
59
- const phase = job.phase ? ` [${job.phase}]` : "";
60
- const detail = job.message ? ` ${job.message}` : "";
61
- if (job.status === "PENDING") {
62
- const queue = typeof job.queuePosition === "number" ? ` (queue ${job.queuePosition + 1})` : "";
63
- return `Compile queued${queue}${phase}${detail}`.trim();
64
- }
65
- if (job.status === "RUNNING") {
66
- return `Compile running${phase}${detail}`.trim();
67
- }
68
- if (job.status === "FAILED") {
69
- return `Compile failed${phase}${detail}`.trim();
70
- }
71
- return `Compile ${job.status.toLowerCase()}${phase}${detail}`.trim();
72
- }
73
- function formatFailedCompileJobSummary(job) {
74
- return formatCompileJobProgressMessage({
75
- status: "FAILED",
76
- phase: job.phase,
77
- message: job.errorMessage ?? job.message ?? void 0
78
- });
79
- }
80
- function formatFailedCompileJobWithCompiledResultMessage(options) {
81
- return `${formatFailedCompileJobSummary(options.job)}. The backend created compiled result ${options.compiledResultId}, but the compile job did not complete cleanly. Run 'dreamboard compile' again after fixing the backend/compiler issue.`;
82
- }
83
- function formatRemoteCompileCommandError(options) {
84
- const detail = options.message.trim();
85
- const hasActionableTerminalContext = /^Compile\s+(failed|completed|cancelled|interrupted)\b/i.test(detail);
86
- if (options.jobId) {
87
- if (hasActionableTerminalContext) {
88
- return `Remote compile job ${options.jobId} could not be completed. ${detail}`;
89
- }
90
- return `Remote compile job ${options.jobId} could not be completed. ${detail} Check backend health and try 'dreamboard compile' again.`;
91
- }
92
- return `Remote compile could not be started. ${detail} Check backend health and try 'dreamboard compile' again.`;
93
- }
94
- async function persistFailedCompileAttempt(options) {
95
- const nextProjectConfig = setLatestCompileAttempt(options.projectConfig, {
96
- resultId: void 0,
97
- jobId: options.jobId,
98
- revisionDigest: options.revisionDigest,
99
- authoringStateId: options.authoringStateId ?? options.revisionDigest,
100
- status: "failed",
101
- diagnosticsSummary: options.diagnosticsSummary
102
- });
103
- await updateProjectState(options.projectRoot, nextProjectConfig);
104
- }
105
- var compile_default = defineCommand({
106
- meta: {
107
- name: "compile",
108
- description: "Compile the current remote authoring head"
109
- },
110
- args: {
111
- debug: {
112
- type: "boolean",
113
- description: "Print additional compile progress context",
114
- default: false
115
- },
116
- "skip-local-check": {
117
- type: "boolean",
118
- description: "Skip the best-effort local typecheck before compiling",
119
- default: false
120
- },
121
- ...CONFIG_FLAG_ARGS
122
- },
123
- async run({ args }) {
124
- const parsedArgs = parseCompileCommandArgs(args);
125
- const { projectRoot, projectConfig, config } = await resolveProjectContext(parsedArgs);
126
- let nextProjectConfig = projectConfig;
127
- await assertReleaseEnvironmentPortableDependencies({
128
- projectRoot,
129
- projectConfig: nextProjectConfig,
130
- environment: config.environment
131
- });
132
- await assertCompilerPortableDependencies({
133
- projectRoot,
134
- projectConfig: nextProjectConfig
135
- });
136
- const diff = await getLocalDiff(projectRoot);
137
- await assertCliStaticScaffoldComplete(projectRoot, diff.deleted);
138
- if (diff.modified.length > 0 || diff.added.length > 0 || diff.deleted.length > 0) {
139
- throw new Error(
140
- "Local authored changes are not synced yet. Run 'dreamboard sync' before compiling."
141
- );
142
- }
143
- const remoteProject = await resolveRemoteProject({
144
- projectRoot,
145
- projectConfig: nextProjectConfig,
146
- config
147
- });
148
- nextProjectConfig = remoteProject.projectConfig;
149
- const localAuthoring = getProjectAuthoringState(nextProjectConfig);
150
- const pendingSync = getProjectPendingAuthoringSync(nextProjectConfig);
151
- if (pendingSync) {
152
- if (pendingSync.phase === "authoring_state_created") {
153
- throw new Error(
154
- "Previous sync reached the remote authored head, but local scaffold finalization did not complete. Run 'dreamboard sync' again before compiling."
155
- );
156
- }
157
- throw new Error(
158
- "Previous sync uploaded source changes but did not finish creating the authored head. Run 'dreamboard sync' again before compiling."
159
- );
160
- }
161
- const localRevisionDigest = localAuthoring.revisionDigest ?? nextProjectConfig.remoteHeadDigest;
162
- if (!localRevisionDigest) {
163
- throw new Error(
164
- "This workspace does not know its authored revision yet. Run 'dreamboard sync' first."
165
- );
166
- }
167
- const remoteRevisionDigest = remoteProject.project.head?.revisionDigest;
168
- if (!remoteRevisionDigest) {
169
- throw new Error("Remote has no authored project revision to compile yet.");
170
- }
171
- if (remoteRevisionDigest !== localRevisionDigest) {
172
- throw new Error(
173
- `Remote project head is ${remoteRevisionDigest} but this workspace is based on ${localRevisionDigest}. Run 'dreamboard pull' before compiling.`
174
- );
175
- }
176
- if (!parsedArgs["skip-local-check"]) {
177
- consola.start("Running local typecheck...");
178
- const typecheckResult = await runLocalTypecheck(projectRoot);
179
- if (typecheckResult.skipped) {
180
- if (typecheckResult.output) {
181
- consola.warn(typecheckResult.output);
182
- }
183
- } else if (!typecheckResult.success) {
184
- if (typecheckResult.output) {
185
- consola.error(typecheckResult.output);
186
- }
187
- throw new Error(
188
- "Local typecheck failed. Fix the diagnostics or re-run with --skip-local-check."
189
- );
190
- } else {
191
- consola.success("Local typecheck passed.");
192
- }
193
- }
194
- const existingCompiledResult = (await findProjectCompiledResultsForRevision({
195
- projectId: nextProjectConfig.projectId,
196
- revisionDigest: localRevisionDigest
197
- })).find((result) => result.success);
198
- if (existingCompiledResult) {
199
- nextProjectConfig = setLatestCompileAttempt(nextProjectConfig, {
200
- resultId: existingCompiledResult.id,
201
- jobId: void 0,
202
- revisionDigest: localRevisionDigest,
203
- authoringStateId: existingCompiledResult.authoringStateId ?? localRevisionDigest,
204
- status: "successful",
205
- diagnosticsSummary: void 0
206
- });
207
- await updateProjectState(projectRoot, nextProjectConfig);
208
- consola.success(
209
- `Reusing compiled ${existingCompiledResult.id} for authored state ${existingCompiledResult.authoringStateId}.`
210
- );
211
- return;
212
- }
213
- let compileJobId;
214
- let compileJobStatus;
215
- let compileJobPhase;
216
- let compileJobMessage;
217
- let compileJobErrorMessage;
218
- let compiledResult;
219
- try {
220
- const compileJob = await queueProjectRevisionCompileSdk({
221
- projectId: nextProjectConfig.projectId,
222
- revisionDigest: localRevisionDigest
223
- });
224
- compileJobId = compileJob.jobId;
225
- if (!compileJobId) {
226
- throw new Error("Failed to create compile job: missing jobId.");
227
- }
228
- ({
229
- job: {
230
- status: compileJobStatus,
231
- phase: compileJobPhase,
232
- message: compileJobMessage,
233
- errorMessage: compileJobErrorMessage
234
- },
235
- compiledResult
236
- } = await waitForCompiledResultJobSdk({
237
- projectId: nextProjectConfig.projectId,
238
- jobId: compileJobId,
239
- onProgress: (job) => {
240
- const message = formatCompileJobProgressMessage(job);
241
- if (parsedArgs.debug) {
242
- consola.info(message);
243
- } else {
244
- consola.start(message);
245
- }
246
- }
247
- }));
248
- } catch (error) {
249
- const message = formatCliError(error);
250
- if (compileJobId) {
251
- await persistFailedCompileAttempt({
252
- projectRoot,
253
- projectConfig: nextProjectConfig,
254
- revisionDigest: localRevisionDigest,
255
- authoringStateId: localAuthoring.authoringStateId,
256
- diagnosticsSummary: message,
257
- jobId: compileJobId
258
- });
259
- }
260
- throw new Error(
261
- formatRemoteCompileCommandError({
262
- message,
263
- jobId: compileJobId
264
- })
265
- );
266
- }
267
- const failedJobProducedCompiledResult = compileJobStatus === "FAILED" && compiledResult.success;
268
- const failedJobWithCompiledResultSummary = failedJobProducedCompiledResult ? formatFailedCompileJobSummary({
269
- phase: compileJobPhase,
270
- message: compileJobMessage,
271
- errorMessage: compileJobErrorMessage
272
- }) : void 0;
273
- nextProjectConfig = setLatestCompileAttempt(nextProjectConfig, {
274
- resultId: compiledResult.id,
275
- jobId: compileJobId,
276
- revisionDigest: localRevisionDigest,
277
- authoringStateId: compiledResult.authoringStateId ?? localRevisionDigest,
278
- status: compiledResult.success && !failedJobProducedCompiledResult ? "successful" : "failed",
279
- diagnosticsSummary: failedJobWithCompiledResultSummary ?? formatDiagnosticsSummary(compiledResult.diagnostics)
280
- });
281
- await updateProjectState(projectRoot, nextProjectConfig);
282
- if (failedJobProducedCompiledResult) {
283
- throw new Error(
284
- formatFailedCompileJobWithCompiledResultMessage({
285
- compiledResultId: compiledResult.id,
286
- job: {
287
- phase: compileJobPhase,
288
- message: compileJobMessage,
289
- errorMessage: compileJobErrorMessage
290
- }
291
- })
292
- );
293
- }
294
- if (!compiledResult.success) {
295
- for (const diagnostic of compiledResult.diagnostics ?? []) {
296
- if (diagnostic.message) {
297
- consola.error(diagnostic.message);
298
- }
299
- }
300
- throw new Error(
301
- "Remote compile failed, but your authored state is synced. Fix the diagnostics and run 'dreamboard compile' again."
302
- );
303
- }
304
- consola.success(
305
- `Compiled ${compiledResult.id} for revision ${localRevisionDigest}.`
306
- );
307
- }
308
- });
309
- export {
310
- compile_default as default
311
- };
312
- //# sourceMappingURL=compile-TEQVA46V.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/compile.ts"],"sourcesContent":["import type { CompiledResult } from \"@dreamboard-games/api-client\";\nimport type { ProjectConfig } from \"../types.js\";\nimport { defineCommand } from \"citty\";\nimport consola from \"consola\";\nimport { CONFIG_FLAG_ARGS } from \"../command-args.js\";\nimport { resolveProjectContext } from \"../config/resolve.js\";\nimport { updateProjectState } from \"../config/project-config.js\";\nimport { parseCompileCommandArgs } from \"../flags.js\";\nimport { getLocalDiff } from \"../services/project/local-files.js\";\nimport { assertCliStaticScaffoldComplete } from \"../services/project/static-scaffold.js\";\nimport {\n assertCompilerPortableDependencies,\n assertReleaseEnvironmentPortableDependencies,\n} from \"../services/project/dependency-portability.js\";\nimport { runLocalTypecheck } from \"../services/project/local-typecheck.js\";\nimport {\n findProjectCompiledResultsForRevision,\n queueProjectRevisionCompileSdk,\n waitForCompiledResultJobSdk,\n} from \"../services/api/index.js\";\nimport {\n getProjectAuthoringState,\n getProjectPendingAuthoringSync,\n setLatestCompileAttempt,\n} from \"../services/project/project-state.js\";\nimport { formatCliError } from \"../utils/errors.js\";\nimport { resolveRemoteProject } from \"../services/project/remote-project.js\";\n\nfunction formatDiagnosticsSummary(\n diagnostics: Array<{ message?: string }> | null | undefined,\n): string | undefined {\n const firstMessage = diagnostics?.find(\n (diagnostic) => diagnostic.message,\n )?.message;\n return firstMessage?.trim() || undefined;\n}\n\nfunction formatCompileJobProgressMessage(job: {\n status: string;\n phase?: string;\n queuePosition?: number;\n message?: string;\n}): string {\n const phase = job.phase ? ` [${job.phase}]` : \"\";\n const detail = job.message ? ` ${job.message}` : \"\";\n if (job.status === \"PENDING\") {\n const queue =\n typeof job.queuePosition === \"number\"\n ? ` (queue ${job.queuePosition + 1})`\n : \"\";\n return `Compile queued${queue}${phase}${detail}`.trim();\n }\n if (job.status === \"RUNNING\") {\n return `Compile running${phase}${detail}`.trim();\n }\n if (job.status === \"FAILED\") {\n return `Compile failed${phase}${detail}`.trim();\n }\n return `Compile ${job.status.toLowerCase()}${phase}${detail}`.trim();\n}\n\nfunction formatFailedCompileJobSummary(job: {\n phase?: string;\n message?: string | null;\n errorMessage?: string | null;\n}): string {\n return formatCompileJobProgressMessage({\n status: \"FAILED\",\n phase: job.phase,\n message: job.errorMessage ?? job.message ?? undefined,\n });\n}\n\nfunction formatFailedCompileJobWithCompiledResultMessage(options: {\n compiledResultId: string;\n job: {\n phase?: string;\n message?: string | null;\n errorMessage?: string | null;\n };\n}): string {\n return `${formatFailedCompileJobSummary(options.job)}. The backend created compiled result ${options.compiledResultId}, but the compile job did not complete cleanly. Run 'dreamboard compile' again after fixing the backend/compiler issue.`;\n}\n\nfunction formatRemoteCompileCommandError(options: {\n message: string;\n jobId?: string;\n}): string {\n const detail = options.message.trim();\n const hasActionableTerminalContext =\n /^Compile\\s+(failed|completed|cancelled|interrupted)\\b/i.test(detail);\n if (options.jobId) {\n if (hasActionableTerminalContext) {\n return `Remote compile job ${options.jobId} could not be completed. ${detail}`;\n }\n return `Remote compile job ${options.jobId} could not be completed. ${detail} Check backend health and try 'dreamboard compile' again.`;\n }\n return `Remote compile could not be started. ${detail} Check backend health and try 'dreamboard compile' again.`;\n}\n\nasync function persistFailedCompileAttempt(options: {\n projectRoot: string;\n projectConfig: ProjectConfig;\n revisionDigest: string;\n authoringStateId?: string;\n diagnosticsSummary: string;\n jobId?: string;\n}): Promise<void> {\n const nextProjectConfig = setLatestCompileAttempt(options.projectConfig, {\n resultId: undefined,\n jobId: options.jobId,\n revisionDigest: options.revisionDigest,\n authoringStateId: options.authoringStateId ?? options.revisionDigest,\n status: \"failed\",\n diagnosticsSummary: options.diagnosticsSummary,\n });\n await updateProjectState(options.projectRoot, nextProjectConfig);\n}\n\nexport default defineCommand({\n meta: {\n name: \"compile\",\n description: \"Compile the current remote authoring head\",\n },\n args: {\n debug: {\n type: \"boolean\",\n description: \"Print additional compile progress context\",\n default: false,\n },\n \"skip-local-check\": {\n type: \"boolean\",\n description: \"Skip the best-effort local typecheck before compiling\",\n default: false,\n },\n ...CONFIG_FLAG_ARGS,\n },\n async run({ args }) {\n const parsedArgs = parseCompileCommandArgs(args);\n const { projectRoot, projectConfig, config } =\n await resolveProjectContext(parsedArgs);\n let nextProjectConfig = projectConfig;\n await assertReleaseEnvironmentPortableDependencies({\n projectRoot,\n projectConfig: nextProjectConfig,\n environment: config.environment,\n });\n await assertCompilerPortableDependencies({\n projectRoot,\n projectConfig: nextProjectConfig,\n });\n\n const diff = await getLocalDiff(projectRoot);\n await assertCliStaticScaffoldComplete(projectRoot, diff.deleted);\n if (\n diff.modified.length > 0 ||\n diff.added.length > 0 ||\n diff.deleted.length > 0\n ) {\n throw new Error(\n \"Local authored changes are not synced yet. Run 'dreamboard sync' before compiling.\",\n );\n }\n\n const remoteProject = await resolveRemoteProject({\n projectRoot,\n projectConfig: nextProjectConfig,\n config,\n });\n nextProjectConfig = remoteProject.projectConfig;\n\n const localAuthoring = getProjectAuthoringState(nextProjectConfig);\n const pendingSync = getProjectPendingAuthoringSync(nextProjectConfig);\n if (pendingSync) {\n if (pendingSync.phase === \"authoring_state_created\") {\n throw new Error(\n \"Previous sync reached the remote authored head, but local scaffold finalization did not complete. Run 'dreamboard sync' again before compiling.\",\n );\n }\n throw new Error(\n \"Previous sync uploaded source changes but did not finish creating the authored head. Run 'dreamboard sync' again before compiling.\",\n );\n }\n const localRevisionDigest =\n localAuthoring.revisionDigest ?? nextProjectConfig.remoteHeadDigest;\n if (!localRevisionDigest) {\n throw new Error(\n \"This workspace does not know its authored revision yet. Run 'dreamboard sync' first.\",\n );\n }\n\n const remoteRevisionDigest = remoteProject.project.head?.revisionDigest;\n if (!remoteRevisionDigest) {\n throw new Error(\"Remote has no authored project revision to compile yet.\");\n }\n if (remoteRevisionDigest !== localRevisionDigest) {\n throw new Error(\n `Remote project head is ${remoteRevisionDigest} but this workspace is based on ${localRevisionDigest}. Run 'dreamboard pull' before compiling.`,\n );\n }\n\n if (!parsedArgs[\"skip-local-check\"]) {\n consola.start(\"Running local typecheck...\");\n const typecheckResult = await runLocalTypecheck(projectRoot);\n if (typecheckResult.skipped) {\n if (typecheckResult.output) {\n consola.warn(typecheckResult.output);\n }\n } else if (!typecheckResult.success) {\n if (typecheckResult.output) {\n consola.error(typecheckResult.output);\n }\n throw new Error(\n \"Local typecheck failed. Fix the diagnostics or re-run with --skip-local-check.\",\n );\n } else {\n consola.success(\"Local typecheck passed.\");\n }\n }\n\n const existingCompiledResult = (\n await findProjectCompiledResultsForRevision({\n projectId: nextProjectConfig.projectId,\n revisionDigest: localRevisionDigest,\n })\n ).find((result) => result.success);\n if (existingCompiledResult) {\n nextProjectConfig = setLatestCompileAttempt(nextProjectConfig, {\n resultId: existingCompiledResult.id,\n jobId: undefined,\n revisionDigest: localRevisionDigest,\n authoringStateId:\n existingCompiledResult.authoringStateId ?? localRevisionDigest,\n status: \"successful\",\n diagnosticsSummary: undefined,\n });\n await updateProjectState(projectRoot, nextProjectConfig);\n consola.success(\n `Reusing compiled ${existingCompiledResult.id} for authored state ${existingCompiledResult.authoringStateId}.`,\n );\n return;\n }\n\n let compileJobId: string | undefined;\n let compileJobStatus: string | undefined;\n let compileJobPhase: string | undefined;\n let compileJobMessage: string | null | undefined;\n let compileJobErrorMessage: string | null | undefined;\n let compiledResult: CompiledResult;\n try {\n const compileJob = await queueProjectRevisionCompileSdk({\n projectId: nextProjectConfig.projectId,\n revisionDigest: localRevisionDigest,\n });\n compileJobId = compileJob.jobId;\n if (!compileJobId) {\n throw new Error(\"Failed to create compile job: missing jobId.\");\n }\n\n ({\n job: {\n status: compileJobStatus,\n phase: compileJobPhase,\n message: compileJobMessage,\n errorMessage: compileJobErrorMessage,\n },\n compiledResult,\n } = await waitForCompiledResultJobSdk({\n projectId: nextProjectConfig.projectId,\n jobId: compileJobId,\n onProgress: (job) => {\n const message = formatCompileJobProgressMessage(job);\n if (parsedArgs.debug) {\n consola.info(message);\n } else {\n consola.start(message);\n }\n },\n }));\n } catch (error) {\n const message = formatCliError(error);\n if (compileJobId) {\n await persistFailedCompileAttempt({\n projectRoot,\n projectConfig: nextProjectConfig,\n revisionDigest: localRevisionDigest,\n authoringStateId: localAuthoring.authoringStateId,\n diagnosticsSummary: message,\n jobId: compileJobId,\n });\n }\n throw new Error(\n formatRemoteCompileCommandError({\n message,\n jobId: compileJobId,\n }),\n );\n }\n\n const failedJobProducedCompiledResult =\n compileJobStatus === \"FAILED\" && compiledResult.success;\n const failedJobWithCompiledResultSummary = failedJobProducedCompiledResult\n ? formatFailedCompileJobSummary({\n phase: compileJobPhase,\n message: compileJobMessage,\n errorMessage: compileJobErrorMessage,\n })\n : undefined;\n\n nextProjectConfig = setLatestCompileAttempt(nextProjectConfig, {\n resultId: compiledResult.id,\n jobId: compileJobId,\n revisionDigest: localRevisionDigest,\n authoringStateId: compiledResult.authoringStateId ?? localRevisionDigest,\n status:\n compiledResult.success && !failedJobProducedCompiledResult\n ? \"successful\"\n : \"failed\",\n diagnosticsSummary:\n failedJobWithCompiledResultSummary ??\n formatDiagnosticsSummary(compiledResult.diagnostics),\n });\n await updateProjectState(projectRoot, nextProjectConfig);\n\n if (failedJobProducedCompiledResult) {\n throw new Error(\n formatFailedCompileJobWithCompiledResultMessage({\n compiledResultId: compiledResult.id,\n job: {\n phase: compileJobPhase,\n message: compileJobMessage,\n errorMessage: compileJobErrorMessage,\n },\n }),\n );\n }\n\n if (!compiledResult.success) {\n for (const diagnostic of compiledResult.diagnostics ?? []) {\n if (diagnostic.message) {\n consola.error(diagnostic.message);\n }\n }\n throw new Error(\n \"Remote compile failed, but your authored state is synced. Fix the diagnostics and run 'dreamboard compile' again.\",\n );\n }\n\n consola.success(\n `Compiled ${compiledResult.id} for revision ${localRevisionDigest}.`,\n );\n },\n});\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/config/keychain-backend.ts"],"sourcesContent":["/**\n * OS keychain-backed `CredentialBackend` built on top of `@napi-rs/keyring`.\n *\n * Keychain is an *opt-in* storage backend, enabled by setting\n * `credentialBackend: \"keychain\"` in `~/.dreamboard/config.json` (see\n * `credential-store.ts` for the resolver). When enabled, it gives us:\n * - A refresh token encrypted at rest by the OS (Keychain on macOS,\n * Credential Vault on Windows, Secret Service on Linux).\n * - Protection against other processes running as the same user tailing\n * `~/.dreamboard/auth.json` to scrape the token.\n *\n * It is not the default because on macOS the first keychain write\n * triggers a login-password prompt, and macOS re-prompts whenever the\n * executing Node binary's code signature changes (e.g. after an\n * `nvm`/`volta` upgrade). The zero-prompt file backend is a better\n * out-of-the-box experience for CLI users.\n *\n * This module is loaded optionally: `@napi-rs/keyring` is declared as an\n * `optionalDependencies` entry so environments where the native binary is\n * unavailable (e.g. Alpine containers, Linux without libsecret, some CI\n * images) still get a working CLI via the file backend fallback.\n *\n * One-time migration: when a user opts into the keychain and `auth.json`\n * still has tokens, `credential-store.ts` copies them into the keychain\n * and deletes the file. This is the only path that intentionally mutates\n * both backends.\n */\n\nimport type {\n CredentialBackend,\n Credentials,\n StoredSessionSnapshot,\n} from \"./credential-store.js\";\n\n/** Keychain service id. Shared across all Dreamboard CLI builds. */\nconst KEYCHAIN_SERVICE = \"dreamboard-cli\";\n/**\n * Keychain account id. The `user@host` shape is conventional but we keep\n * it fixed for now because the CLI only cares about \"the session for this\n * OS user\", not per-process sessions.\n */\nconst KEYCHAIN_ACCOUNT = \"session\";\n\ntype EntryInstance = {\n setPassword(value: string): void;\n getPassword(): string | null | undefined;\n deletePassword(): boolean;\n};\n\ntype KeyringModule = {\n Entry: new (service: string, account: string) => EntryInstance;\n};\n\nlet cachedModule: KeyringModule | null | undefined;\n\nasync function loadKeyringModule(): Promise<KeyringModule | null> {\n if (cachedModule !== undefined) return cachedModule;\n try {\n // `@napi-rs/keyring` is an optional dependency. If the native binary is\n // missing on this platform the dynamic import throws; we swallow that\n // and fall back to the file backend.\n const mod = (await import(\"@napi-rs/keyring\")) as unknown as KeyringModule;\n cachedModule = mod;\n } catch {\n cachedModule = null;\n }\n return cachedModule;\n}\n\nfunction keychainProbe(entry: EntryInstance): boolean {\n // Some platforms have the module installed but no accessible keyring\n // (e.g. headless Linux without DBus). Touch getPassword to verify we\n // can talk to the service without side effects.\n try {\n entry.getPassword();\n return true;\n } catch {\n return false;\n }\n}\n\ntype KeychainPayload = {\n accessToken?: string;\n refreshToken?: string;\n tokenExpiresAt?: string;\n clerkOAuthIssuer?: string;\n clerkOAuthClientId?: string;\n clerkOAuthTokenUrl?: string;\n environment?: string;\n};\n\nfunction parsePayload(\n raw: string | null | undefined,\n): StoredSessionSnapshot | null {\n if (raw === null || raw === undefined) return null;\n const trimmed = raw.trim();\n if (trimmed.length === 0) return null;\n try {\n const parsed = JSON.parse(trimmed) as KeychainPayload;\n if (!parsed.accessToken && !parsed.refreshToken) return null;\n return {\n accessToken: parsed.accessToken || undefined,\n refreshToken: parsed.refreshToken || undefined,\n tokenExpiresAt: parsed.tokenExpiresAt || undefined,\n clerkOAuthIssuer: parsed.clerkOAuthIssuer || undefined,\n clerkOAuthClientId: parsed.clerkOAuthClientId || undefined,\n clerkOAuthTokenUrl: parsed.clerkOAuthTokenUrl || undefined,\n environment: parsed.environment || undefined,\n };\n } catch {\n return null;\n }\n}\n\nfunction writeFull(entry: EntryInstance, creds: Credentials): void {\n if (!creds.accessToken || !creds.refreshToken) {\n throw new Error(\n \"Refusing to persist credentials with an empty accessToken or refreshToken.\",\n );\n }\n const payload: KeychainPayload = {\n accessToken: creds.accessToken,\n refreshToken: creds.refreshToken,\n tokenExpiresAt: creds.tokenExpiresAt,\n clerkOAuthIssuer: creds.clerkOAuthIssuer,\n clerkOAuthClientId: creds.clerkOAuthClientId,\n clerkOAuthTokenUrl: creds.clerkOAuthTokenUrl,\n environment: creds.environment,\n };\n entry.setPassword(JSON.stringify(payload));\n}\n\nfunction writeAccessOnly(entry: EntryInstance, accessToken: string): void {\n if (!accessToken) {\n throw new Error(\"Refusing to persist an empty access token.\");\n }\n const payload: KeychainPayload = { accessToken };\n entry.setPassword(JSON.stringify(payload));\n}\n\nfunction clear(entry: EntryInstance): void {\n try {\n entry.deletePassword();\n } catch {\n // keyring-rs throws when the entry does not exist. That is fine -\n // `clearCredentials` contracts as idempotent.\n }\n}\n\nexport type KeychainAvailability =\n | { available: true; backend: CredentialBackend }\n | { available: false; reason: string };\n\n/**\n * Attempt to construct a keychain-backed `CredentialBackend`. Returns an\n * `available: false` result (with a reason) if the native module, the\n * OS keyring, or the probe fails.\n */\nexport async function tryKeychainBackend(): Promise<KeychainAvailability> {\n const mod = await loadKeyringModule();\n if (!mod) {\n return {\n available: false,\n reason: \"@napi-rs/keyring is not installed for this platform\",\n };\n }\n\n let entry: EntryInstance;\n try {\n entry = new mod.Entry(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT);\n } catch (err) {\n return {\n available: false,\n reason: `Failed to construct keyring entry: ${String((err as Error).message ?? err)}`,\n };\n }\n\n if (!keychainProbe(entry)) {\n return {\n available: false,\n reason: \"OS keyring is not accessible from this process\",\n };\n }\n\n const backend: CredentialBackend = {\n name: \"keychain\",\n async read() {\n try {\n return parsePayload(entry.getPassword());\n } catch (err) {\n const message = String((err as Error).message ?? err);\n // Transient keychain access errors (e.g. Touch ID prompt\n // cancelled) should not surface as \"session wiped\". Treat the\n // unreadable state as \"no session\" so the caller can fall back\n // to prompting for login.\n if (/no matching entry|not found/i.test(message)) {\n return null;\n }\n throw err;\n }\n },\n async writeFull(creds) {\n writeFull(entry, creds);\n },\n async writeAccessOnly(accessToken) {\n writeAccessOnly(entry, accessToken);\n },\n async clear() {\n clear(entry);\n },\n };\n return { available: true, backend };\n}\n\n/**\n * Test-only escape hatch so unit tests can install a fake keyring module\n * without going through the dynamic import cache.\n */\nexport function _setKeyringModuleForTests(mod: KeyringModule | null): void {\n cachedModule = mod;\n}\n\nexport function _resetKeyringModuleForTests(): void {\n cachedModule = undefined;\n}\n"],"mappings":"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","names":[]}