@dreamboard-games/cli 0.1.30-alpha.7 → 0.1.30-alpha.9

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 (35) hide show
  1. package/dist/agent-verifier/agent-workspace-verifier.mjs +11 -10
  2. package/dist/agent-verifier/agent-workspace-verifier.mjs.map +1 -1
  3. package/dist/agent-verifier/{chunk-RHGGFAMQ.mjs → chunk-3IJBOLGT.mjs} +1 -10
  4. package/dist/agent-verifier/chunk-3IJBOLGT.mjs.map +1 -0
  5. package/dist/agent-verifier/{chunk-DN2JHUGM.mjs → chunk-7ODN2WLL.mjs} +2 -2
  6. package/dist/agent-verifier/{chunk-ZETW43TX.mjs → chunk-EFZMD3WM.mjs} +2 -2
  7. package/dist/agent-verifier/chunk-KK47X7RV.mjs +14 -0
  8. package/dist/agent-verifier/chunk-KK47X7RV.mjs.map +1 -0
  9. package/dist/agent-verifier/{chunk-7CNBKWWE.mjs → chunk-MGXX4WFR.mjs} +7 -5
  10. package/dist/agent-verifier/{chunk-7CNBKWWE.mjs.map → chunk-MGXX4WFR.mjs.map} +1 -1
  11. package/dist/agent-verifier/{chunk-M2MHRWSP.mjs → chunk-RG4PPQC2.mjs} +4 -4
  12. package/dist/agent-verifier/{chunk-NCHH5I7R.mjs → chunk-V6R55ROH.mjs} +5 -23
  13. package/dist/agent-verifier/chunk-V6R55ROH.mjs.map +1 -0
  14. package/dist/agent-verifier/{compile-OTRAPCY6.mjs → compile-G2HBBA4A.mjs} +10 -9
  15. package/dist/agent-verifier/{compile-OTRAPCY6.mjs.map → compile-G2HBBA4A.mjs.map} +1 -1
  16. package/dist/agent-verifier/{local-files-45DUJUEH.mjs → local-files-2VBRFEZM.mjs} +3 -3
  17. package/dist/agent-verifier/{materialize-workspace-R2QJ7HQ6.mjs → materialize-workspace-K5LHD23M.mjs} +8 -7
  18. package/dist/agent-verifier/{materialize-workspace-R2QJ7HQ6.mjs.map → materialize-workspace-K5LHD23M.mjs.map} +1 -1
  19. package/dist/agent-verifier/{reducer-native-test-harness-LNZI3G73.mjs → reducer-native-test-harness-FBMLKX5V.mjs} +4 -4
  20. package/dist/agent-verifier/{static-scaffold-RO2IS34O.mjs → static-scaffold-DHJKZRYD.mjs} +3 -4
  21. package/dist/agent-verifier/{sync-PZXHAEFQ.mjs → sync-KIOG53KM.mjs} +11 -9
  22. package/dist/agent-verifier/{sync-PZXHAEFQ.mjs.map → sync-KIOG53KM.mjs.map} +1 -1
  23. package/dist/agent-verifier/{test-RCFDQBEQ.mjs → test-VKDPAIPF.mjs} +7 -6
  24. package/dist/agent-verifier/{test-RCFDQBEQ.mjs.map → test-VKDPAIPF.mjs.map} +1 -1
  25. package/dist/index.js +1 -17
  26. package/dist/index.js.map +1 -1
  27. package/package.json +1 -1
  28. package/dist/agent-verifier/chunk-NCHH5I7R.mjs.map +0 -1
  29. package/dist/agent-verifier/chunk-RHGGFAMQ.mjs.map +0 -1
  30. /package/dist/agent-verifier/{chunk-DN2JHUGM.mjs.map → chunk-7ODN2WLL.mjs.map} +0 -0
  31. /package/dist/agent-verifier/{chunk-ZETW43TX.mjs.map → chunk-EFZMD3WM.mjs.map} +0 -0
  32. /package/dist/agent-verifier/{chunk-M2MHRWSP.mjs.map → chunk-RG4PPQC2.mjs.map} +0 -0
  33. /package/dist/agent-verifier/{local-files-45DUJUEH.mjs.map → local-files-2VBRFEZM.mjs.map} +0 -0
  34. /package/dist/agent-verifier/{reducer-native-test-harness-LNZI3G73.mjs.map → reducer-native-test-harness-FBMLKX5V.mjs.map} +0 -0
  35. /package/dist/agent-verifier/{static-scaffold-RO2IS34O.mjs.map → static-scaffold-DHJKZRYD.mjs.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/project/source-revision-paths.ts","../../src/services/project/local-maintainer-registry.ts","../../src/services/project/local-maintainer-registry-shared.ts","../../src/commands/sync.ts"],"sourcesContent":["import { RULE_FILE } from \"../../constants.js\";\nimport {\n isAllowedGamePath,\n isDynamicGeneratedPath,\n} from \"./scaffold-ownership.js\";\n\n/**\n * Single definition of what belongs in an uploaded source revision, shared by\n * `dev` and `sync`. The compiler consumes the uploaded workspace as-is and\n * does not regenerate codegen outputs, so dynamic generated files (manifest\n * contract, ui-contract, framework tsconfigs) must always be included.\n */\nexport function isSourceRevisionPath(filePath: string): boolean {\n return filePath !== RULE_FILE && isAllowedGamePath(filePath);\n}\n\n/**\n * Files that must be upserted on every sync even when the local diff reports\n * them unchanged: registry configuration and regenerated codegen outputs.\n */\nexport function shouldAlwaysUpsertSourcePath(filePath: string): boolean {\n return filePath === \".npmrc\" || isDynamicGeneratedPath(filePath);\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { LocalMaintainerRegistryConfig } from \"../../types.js\";\nimport { resolveCliRepoRoot } from \"../../utils/repo-root.js\";\nimport {\n LOCAL_REGISTRY_URL,\n didLocalMaintainerSnapshotChange,\n getLocalMaintainerNpmrcContent,\n isLocalMaintainerRegistryEnabled,\n isLocalMaintainerRegistryUrl,\n shortHash,\n} from \"./local-maintainer-registry-shared.js\";\n\nexport {\n didLocalMaintainerSnapshotChange,\n getLocalMaintainerNpmrcContent,\n isLocalMaintainerRegistryEnabled,\n isLocalMaintainerRegistryUrl,\n};\n\nconst MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));\n\nfunction getCliPackageRoot(): string {\n try {\n return path.join(\n resolveCliRepoRoot(import.meta.url),\n \"apps\",\n \"dreamboard-cli\",\n );\n } catch {\n return resolveInstalledCliPackageRoot(MODULE_DIR);\n }\n}\n\nfunction resolveInstalledCliPackageRoot(moduleDir: string): string {\n let current = moduleDir;\n while (true) {\n const packageJsonPath = path.join(current, \"package.json\");\n if (existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(\n readFileSync(packageJsonPath, \"utf8\"),\n ) as { name?: unknown };\n if (\n packageJson.name === \"@dreamboard-games/cli\" ||\n packageJson.name === \"dreamboard\" ||\n packageJson.name === \"dreamboard-cli\"\n ) {\n return current;\n }\n } catch {\n // Keep walking upward; a malformed parent package should not hide the\n // installed CLI package root.\n }\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return moduleDir;\n }\n current = parent;\n }\n}\n\nfunction getScriptInvocation(): {\n command: string;\n args: string[];\n attemptedCommand: string;\n cwd: string;\n} {\n const cliPackageRoot = getCliPackageRoot();\n const scriptPath = getLocalMaintainerScriptPath(cliPackageRoot);\n if (!existsSync(scriptPath)) {\n throw new Error(\n [\n \"Dreamboard local maintainer registry support is only available from a source checkout.\",\n `Expected helper script at ${scriptPath}.`,\n ].join(\" \"),\n );\n }\n\n const command = process.platform === \"win32\" ? \"pnpm.cmd\" : \"pnpm\";\n const args = [\"exec\", \"tsx\", scriptPath];\n return {\n command,\n args,\n attemptedCommand: `${command} ${args.join(\" \")}`,\n cwd: cliPackageRoot,\n };\n}\n\nfunction getLocalMaintainerScriptPath(cliPackageRoot: string): string {\n return path.join(cliPackageRoot, \"scripts\", \"local-maintainer-registry.ts\");\n}\n\nfunction isInstalledCliPackageRoot(cliPackageRoot: string): boolean {\n return cliPackageRoot.split(path.sep).includes(\"node_modules\");\n}\n\nfunction shouldSkipLocalMaintainerHelper(): boolean {\n const cliPackageRoot = getCliPackageRoot();\n const scriptPath = getLocalMaintainerScriptPath(cliPackageRoot);\n return !existsSync(scriptPath) && isInstalledCliPackageRoot(cliPackageRoot);\n}\n\nexport function buildInstalledCliLocalMaintainerSnapshot(\n packageJson: { dependencies?: Record<string, unknown> },\n registryUrl: string = LOCAL_REGISTRY_URL,\n): LocalMaintainerRegistryConfig | null {\n const sdkVersion = packageJson.dependencies?.[\"@dreamboard-games/sdk\"];\n if (typeof sdkVersion !== \"string\" || !sdkVersion.includes(\"-local.\")) {\n return null;\n }\n\n return {\n registryUrl,\n snapshotId: shortHash(sdkVersion),\n fingerprint: shortHash(sdkVersion),\n publishedAt: \"\",\n packages: {\n \"@dreamboard-games/sdk\": sdkVersion,\n },\n };\n}\n\nexport function readInstalledCliLocalMaintainerSnapshot(): LocalMaintainerRegistryConfig | null {\n const cliPackageRoot = getCliPackageRoot();\n if (!isInstalledCliPackageRoot(cliPackageRoot)) {\n return null;\n }\n\n const packageJsonPath = path.join(cliPackageRoot, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n return null;\n }\n\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as {\n dependencies?: Record<string, unknown>;\n };\n return buildInstalledCliLocalMaintainerSnapshot(packageJson);\n}\n\nfunction buildScriptSetupError(options: {\n attemptedCommand: string;\n message: string;\n stderr?: string;\n}): Error {\n return new Error(\n [\n \"Dreamboard local maintainer registry support requires the source-checkout CLI tooling.\",\n options.message,\n `Attempted command: ${options.attemptedCommand}`,\n options.stderr?.trim() ? `stderr:\\n${options.stderr.trim()}` : null,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n );\n}\n\nfunction parseJsonPayload<T>(output: string): T {\n const payload = output\n .trim()\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .reverse()\n .find(\n (line) => line === \"null\" || line.startsWith(\"{\") || line.startsWith(\"[\"),\n );\n\n if (!payload) {\n throw new Error(\"completed without returning a JSON payload\");\n }\n\n return JSON.parse(payload) as T;\n}\n\nasync function runLocalMaintainerScript<T>(args: string[]): Promise<T> {\n const invocation = getScriptInvocation();\n\n return new Promise<T>((resolve, reject) => {\n const child = spawn(invocation.command, [...invocation.args, ...args], {\n cwd: invocation.cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: process.env,\n });\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout.on(\"data\", (chunk) => {\n stdout += chunk.toString();\n });\n child.stderr.on(\"data\", (chunk) => {\n stderr += chunk.toString();\n });\n child.on(\"error\", (error) => {\n const errnoError = error as NodeJS.ErrnoException;\n if (errnoError.code === \"ENOENT\") {\n reject(\n buildScriptSetupError({\n attemptedCommand: invocation.attemptedCommand,\n message:\n \"`pnpm` was not found on PATH, so the source-checkout local maintainer helper could not run.\",\n }),\n );\n return;\n }\n reject(error);\n });\n child.on(\"close\", (code) => {\n if (code !== 0) {\n const missingTsx =\n stderr.includes('Command \"tsx\" not found') ||\n stderr.includes(\"tsx: command not found\") ||\n stderr.includes(\"tsx: not found\");\n reject(\n buildScriptSetupError({\n attemptedCommand: invocation.attemptedCommand,\n message: missingTsx\n ? \"`tsx` is not available for the source-checkout CLI package.\"\n : \"The source-checkout local maintainer helper failed.\",\n stderr,\n }),\n );\n return;\n }\n\n const trimmedStdout = stdout.trim();\n if (!trimmedStdout) {\n reject(\n buildScriptSetupError({\n attemptedCommand: invocation.attemptedCommand,\n message:\n \"The source-checkout local maintainer helper completed without returning JSON.\",\n stderr,\n }),\n );\n return;\n }\n\n try {\n resolve(parseJsonPayload<T>(trimmedStdout));\n } catch (error) {\n reject(\n buildScriptSetupError({\n attemptedCommand: invocation.attemptedCommand,\n message: `Failed to parse JSON from the source-checkout local maintainer helper: ${\n error instanceof Error ? error.message : String(error)\n }`,\n stderr: [stderr.trim(), trimmedStdout].filter(Boolean).join(\"\\n\"),\n }),\n );\n }\n });\n });\n}\n\nexport async function ensureLocalMaintainerSnapshot(\n apiBaseUrl: string,\n): Promise<LocalMaintainerRegistryConfig | null> {\n if (!isLocalMaintainerRegistryEnabled(apiBaseUrl)) {\n return null;\n }\n if (shouldSkipLocalMaintainerHelper()) {\n return readInstalledCliLocalMaintainerSnapshot();\n }\n\n return runLocalMaintainerScript<LocalMaintainerRegistryConfig | null>([\n \"ensure-snapshot\",\n \"--api-base-url\",\n apiBaseUrl,\n ]);\n}\n\nexport async function readWorkspaceLocalMaintainerRegistry(\n projectRoot: string,\n fallbackRegistryUrl: string = LOCAL_REGISTRY_URL,\n): Promise<LocalMaintainerRegistryConfig | null> {\n if (shouldSkipLocalMaintainerHelper()) {\n return null;\n }\n return runLocalMaintainerScript<LocalMaintainerRegistryConfig | null>([\n \"read-workspace\",\n \"--project-root\",\n projectRoot,\n \"--fallback-registry-url\",\n fallbackRegistryUrl,\n ]);\n}\n","import crypto from \"node:crypto\";\nimport path from \"node:path\";\nimport { BUILD_CHANNEL, IS_PUBLISHED_BUILD } from \"../../build-target.js\";\nimport { ENVIRONMENT_CONFIGS } from \"../../constants.js\";\nimport type {\n LocalMaintainerRegistryConfig,\n LocalMaintainerRegistryPackages,\n LocalMaintainerSdkPackageName,\n} from \"../../types.js\";\nimport { exists, readJsonFile } from \"../../utils/fs.js\";\n\nconst localRegistryAddress = readLocalRegistryAddress();\nexport const LOCAL_REGISTRY_HOST = localRegistryAddress.host;\nexport const LOCAL_REGISTRY_PORT = localRegistryAddress.port;\nexport const LOCAL_REGISTRY_URL = `http://${LOCAL_REGISTRY_HOST}:${LOCAL_REGISTRY_PORT}`;\nexport const LOCAL_SCOPE_NPMRC_CONTENT = `@dreamboard-games:registry=${LOCAL_REGISTRY_URL}\\n`;\nexport const SDK_PUBLISH_ORDER: readonly LocalMaintainerSdkPackageName[] = [\n \"@dreamboard-games/sdk\",\n];\n\nexport type PackageJsonShape = {\n name?: string;\n version?: string;\n description?: string;\n type?: string;\n main?: string;\n types?: string;\n exports?: unknown;\n typesVersions?: Record<string, unknown>;\n files?: string[];\n bin?: Record<string, string>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n};\n\nfunction readLocalRegistryAddress(): { host: string; port: number } {\n const urlOverride = process.env.DREAMBOARD_LOCAL_REGISTRY_URL?.trim();\n const hostOverride = process.env.DREAMBOARD_LOCAL_REGISTRY_HOST?.trim();\n const portOverride = process.env.DREAMBOARD_LOCAL_REGISTRY_PORT?.trim();\n if (urlOverride) {\n let parsed: URL;\n try {\n parsed = new URL(urlOverride);\n } catch {\n throw new Error(\n `Invalid DREAMBOARD_LOCAL_REGISTRY_URL '${urlOverride}'. Expected an http://host:port URL.`,\n );\n }\n if (parsed.protocol !== \"http:\" || !parsed.hostname || !parsed.port) {\n throw new Error(\n `Invalid DREAMBOARD_LOCAL_REGISTRY_URL '${urlOverride}'. Expected an http://host:port URL.`,\n );\n }\n return {\n host: hostOverride || parsed.hostname,\n port: parseLocalRegistryPort(portOverride || parsed.port),\n };\n }\n return {\n host: hostOverride || \"127.0.0.1\",\n port: portOverride ? parseLocalRegistryPort(portOverride) : 4873,\n };\n}\n\nfunction parseLocalRegistryPort(raw: string): number {\n const port = Number.parseInt(raw, 10);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(\n `Invalid DREAMBOARD_LOCAL_REGISTRY_PORT '${raw}'. Expected a TCP port from 1 to 65535.`,\n );\n }\n return port;\n}\n\nexport function shortHash(value: string): string {\n return crypto.createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 12);\n}\n\nexport function isLocalMaintainerRegistryEnabled(apiBaseUrl: string): boolean {\n let isLocalLoopbackUrl = false;\n try {\n const parsed = new URL(apiBaseUrl);\n isLocalLoopbackUrl =\n parsed.protocol === \"http:\" &&\n (parsed.hostname === \"localhost\" || parsed.hostname === \"127.0.0.1\");\n } catch {\n isLocalLoopbackUrl = false;\n }\n\n return (\n !IS_PUBLISHED_BUILD &&\n (apiBaseUrl === ENVIRONMENT_CONFIGS.local?.apiBaseUrl ||\n isLocalLoopbackUrl) &&\n BUILD_CHANNEL === \"development\"\n );\n}\n\nexport function packageShortName(\n packageName: LocalMaintainerSdkPackageName,\n): string {\n return packageName.replace(/^@dreamboard(?:-games)?\\//, \"\");\n}\n\nexport async function readWorkspaceLocalMaintainerRegistryFromPackageJson(\n projectRoot: string,\n fallbackRegistryUrl: string = LOCAL_REGISTRY_URL,\n): Promise<LocalMaintainerRegistryConfig | null> {\n const packageJsonPath = path.join(projectRoot, \"package.json\");\n if (!(await exists(packageJsonPath))) {\n return null;\n }\n\n const packageJson = await readJsonFile<PackageJsonShape>(packageJsonPath);\n const sdkVersion =\n packageJson.dependencies?.[\"@dreamboard-games/sdk\"] ??\n packageJson.devDependencies?.[\"@dreamboard-games/sdk\"];\n const apiClientVersion =\n packageJson.dependencies?.[\"@dreamboard-games/api-client\"] ??\n packageJson.devDependencies?.[\"@dreamboard-games/api-client\"];\n const sdkDependencyVersion =\n packageJson.dependencies?.[\"@dreamboard-games/sdk\"];\n if (!sdkVersion?.includes(\"-local.\") || !sdkDependencyVersion) {\n return null;\n }\n const localSdkVersion = sdkVersion;\n\n const fingerprintSource = [\n apiClientVersion ?? \"\",\n localSdkVersion,\n fallbackRegistryUrl,\n ].join(\":\");\n return {\n registryUrl: fallbackRegistryUrl,\n snapshotId: shortHash(fingerprintSource),\n fingerprint: shortHash(fingerprintSource),\n publishedAt: \"\",\n packages: {\n \"@dreamboard-games/api-client\": apiClientVersion,\n \"@dreamboard-games/sdk\": localSdkVersion,\n } satisfies LocalMaintainerRegistryPackages,\n };\n}\n\nexport function getLocalMaintainerNpmrcContent(\n localMaintainerRegistry: LocalMaintainerRegistryConfig | null | undefined,\n): string | null {\n if (!localMaintainerRegistry) {\n return null;\n }\n return LOCAL_SCOPE_NPMRC_CONTENT.replace(\n LOCAL_REGISTRY_URL,\n localMaintainerRegistry.registryUrl,\n );\n}\n\nexport function didLocalMaintainerSnapshotChange(\n previous: LocalMaintainerRegistryConfig | undefined,\n next: LocalMaintainerRegistryConfig | null,\n): boolean {\n if (!next) {\n return false;\n }\n return previous?.snapshotId !== next.snapshotId;\n}\n\nexport function isLocalMaintainerRegistryUrl(\n fileContent: string | null,\n): boolean {\n if (!fileContent) {\n return false;\n }\n return /@dreamboard-games:registry=http:\\/\\/127\\.0\\.0\\.1:\\d+/.test(\n fileContent,\n );\n}\n","import { defineCommand } from \"citty\";\nimport consola from \"consola\";\nimport {\n mapUpsertBlobContentsByContentHash,\n materializeSourceChangeOperations,\n type SourceContentChangeOperation,\n} from \"@dreamboard-games/api-client/source-revisions\";\nimport { CONFIG_FLAG_ARGS } from \"../command-args.js\";\nimport { resolveProjectContext } from \"../config/resolve.js\";\nimport { updateProjectState } from \"../config/project-config.js\";\nimport { parseSyncCommandArgs } from \"../flags.js\";\nimport {\n collectLocalFiles,\n computeManifestHash,\n getLocalDiff,\n loadManifest,\n loadRule,\n writeSnapshot,\n} from \"../services/project/local-files.js\";\nimport {\n isSourceRevisionPath,\n shouldAlwaysUpsertSourcePath,\n} from \"../services/project/source-revision-paths.js\";\nimport {\n assertCliStaticScaffoldComplete,\n scaffoldStaticWorkspace,\n} from \"../services/project/static-scaffold.js\";\nimport {\n createGameRevisionSdk,\n uploadProjectSourceBlobsSdk,\n} from \"../services/api/index.js\";\nimport {\n getProjectAuthoringState,\n getProjectLocalMaintainerRegistry,\n getProjectPendingAuthoringSync,\n updateProjectAuthoringState,\n updateProjectLocalMaintainerRegistry,\n} from \"../services/project/project-state.js\";\nimport type { ProjectConfig } from \"../types.js\";\nimport { applyWorkspaceCodegen } from \"../services/project/workspace-codegen.js\";\nimport {\n didLocalMaintainerSnapshotChange,\n ensureLocalMaintainerSnapshot,\n isLocalMaintainerRegistryEnabled,\n} from \"../services/project/local-maintainer-registry.js\";\nimport { reconcileWorkspaceDependencies } from \"../services/project/workspace-dependencies.js\";\nimport { assertReducerContractPreflight } from \"../services/project/reducer-contract-preflight.js\";\nimport { assertReducerBundleSmoke } from \"../services/project/reducer-bundle-preflight.js\";\nimport { runLocalTypecheck } from \"../services/project/local-typecheck.js\";\nimport { resolveRemoteProject } from \"../services/project/remote-project.js\";\nimport { assertReleaseEnvironmentPortableDependencies } from \"../services/project/dependency-portability.js\";\n\nasync function runLoggedStep<T>(\n message: string,\n task: () => Promise<T>,\n): Promise<T> {\n consola.start(message);\n return task();\n}\n\nasync function persistProjectConfig(options: {\n projectRoot: string;\n projectConfig: ProjectConfig;\n}): Promise<ProjectConfig> {\n await updateProjectState(options.projectRoot, options.projectConfig);\n return options.projectConfig;\n}\n\nasync function finalizeLocalSync(options: {\n projectRoot: string;\n projectConfig: ProjectConfig;\n}): Promise<ProjectConfig> {\n const { projectRoot, projectConfig } = options;\n await scaffoldStaticWorkspace(projectRoot, \"update\", {\n localMaintainerRegistry: getProjectLocalMaintainerRegistry(projectConfig),\n });\n await applyWorkspaceCodegen({\n projectRoot,\n manifest: await loadManifest(projectRoot),\n });\n\n const finalizedProjectConfig = await persistProjectConfig({\n projectRoot,\n projectConfig,\n });\n await writeSnapshot(projectRoot);\n return finalizedProjectConfig;\n}\n\nfunction buildSourceSnapshotChanges(\n localFiles: Record<string, string>,\n): SourceContentChangeOperation[] {\n return Object.entries(localFiles)\n .filter(\n ([filePath]) =>\n isSourceRevisionPath(filePath) ||\n shouldAlwaysUpsertSourcePath(filePath),\n )\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([path, content]) => ({\n kind: \"upsert\",\n path,\n content,\n }));\n}\n\nexport default defineCommand({\n meta: {\n name: \"sync\",\n description:\n \"Upload authored changes and advance the remote authoring head\",\n },\n args: {\n force: {\n type: \"boolean\",\n description:\n \"Replace the full authored source tree, manifest, and rules, overwriting the remote head with the local copy even when the remote has moved\",\n default: false,\n },\n yes: {\n type: \"boolean\",\n alias: \"y\",\n description: \"Reserved for non-interactive scaffold flows\",\n default: false,\n },\n ...CONFIG_FLAG_ARGS,\n },\n async run({ args }) {\n const parsedArgs = parseSyncCommandArgs(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 const localMaintainerEnabled = isLocalMaintainerRegistryEnabled(\n config.apiBaseUrl,\n );\n const existingLocalMaintainerRegistry =\n getProjectLocalMaintainerRegistry(projectConfig);\n const refreshedLocalMaintainerRegistry = localMaintainerEnabled\n ? await runLoggedStep(\"Checking local SDK snapshot...\", () =>\n ensureLocalMaintainerSnapshot(config.apiBaseUrl),\n )\n : await ensureLocalMaintainerSnapshot(config.apiBaseUrl);\n const localMaintainerRegistry =\n refreshedLocalMaintainerRegistry ??\n (localMaintainerEnabled\n ? (existingLocalMaintainerRegistry ?? null)\n : null);\n const localMaintainerSnapshotChanged = didLocalMaintainerSnapshotChange(\n existingLocalMaintainerRegistry,\n refreshedLocalMaintainerRegistry,\n );\n if (refreshedLocalMaintainerRegistry) {\n nextProjectConfig = updateProjectLocalMaintainerRegistry(\n nextProjectConfig,\n refreshedLocalMaintainerRegistry,\n );\n consola.info(\n localMaintainerSnapshotChanged\n ? \"Local SDK snapshot refreshed.\"\n : \"Using existing local SDK snapshot.\",\n );\n } else if (localMaintainerRegistry) {\n consola.info(\"Using workspace-pinned local SDK snapshot.\");\n }\n\n await runLoggedStep(\"Refreshing static scaffold...\", () =>\n scaffoldStaticWorkspace(projectRoot, \"update\", {\n localMaintainerRegistry,\n }),\n );\n const localManifest = await loadManifest(projectRoot);\n await runLoggedStep(\"Applying workspace codegen...\", async () =>\n applyWorkspaceCodegen({\n projectRoot,\n manifest: localManifest,\n }),\n );\n const dependencyState = await runLoggedStep(\n \"Reconciling workspace dependencies...\",\n () => reconcileWorkspaceDependencies(projectRoot),\n );\n if (\n dependencyState.packageManagerNormalized ||\n dependencyState.lockfileGenerated ||\n dependencyState.installed ||\n localMaintainerSnapshotChanged\n ) {\n consola.info(\"Workspace dependencies reconciled.\");\n } else {\n consola.info(\"Workspace dependencies already up to date.\");\n }\n await runLoggedStep(\"Validating reducer contract...\", () =>\n assertReducerContractPreflight(projectRoot),\n );\n const typecheckResult = await runLoggedStep(\n \"Running local typecheck...\",\n () => runLocalTypecheck(projectRoot),\n );\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 before syncing.\",\n );\n }\n await runLoggedStep(\"Smoke-testing reducer bundle...\", async () =>\n assertReducerBundleSmoke({\n projectRoot,\n manifest: localManifest,\n }),\n );\n consola.success(\"Reducer bundle smoke test passed.\");\n\n const remoteProject = await runLoggedStep(\"Ensuring remote project...\", () =>\n resolveRemoteProject({\n projectRoot,\n projectConfig: nextProjectConfig,\n config,\n }),\n );\n nextProjectConfig = remoteProject.projectConfig;\n\n const localDiff = await getLocalDiff(projectRoot);\n await assertCliStaticScaffoldComplete(projectRoot, localDiff.deleted);\n\n const localAuthoring = getProjectAuthoringState(nextProjectConfig);\n const pendingSync = getProjectPendingAuthoringSync(nextProjectConfig);\n const remoteHeadDigest = remoteProject.project.head?.revisionDigest;\n const localHeadDigest =\n localAuthoring.revisionDigest ?? nextProjectConfig.remoteHeadDigest;\n\n if (pendingSync && !parsedArgs.force) {\n throw new Error(\n \"This workspace has an unfinished legacy sync checkpoint. Run 'dreamboard sync --force' to replace it with an atomic project revision.\",\n );\n }\n\n if (\n remoteHeadDigest &&\n localHeadDigest &&\n remoteHeadDigest !== localHeadDigest\n ) {\n if (parsedArgs.force) {\n consola.warn(\n `Remote project head has moved to ${remoteHeadDigest}. --force will overwrite it with this workspace's local copy.`,\n );\n } else {\n throw new Error(\n `Remote project head has moved to ${remoteHeadDigest}. Run 'dreamboard pull' before syncing local changes, or pass --force to overwrite the remote with the local copy.`,\n );\n }\n }\n\n if (remoteHeadDigest && !localHeadDigest) {\n if (parsedArgs.force) {\n consola.warn(\n `This workspace has no authored base but the remote project head is ${remoteHeadDigest}. --force will overwrite it with this workspace's local copy.`,\n );\n } else {\n throw new Error(\n `This workspace has no authored base but the remote project head is ${remoteHeadDigest}. Re-clone, run 'dreamboard pull --force' into a clean workspace, or pass --force to overwrite the remote with the local copy.`,\n );\n }\n }\n\n const hasChanges =\n localDiff.modified.length > 0 ||\n localDiff.added.length > 0 ||\n localDiff.deleted.length > 0;\n const localManifestContentHash = computeManifestHash(localManifest);\n const manifestOutOfSync =\n localAuthoring.localManifestContentHash !== localManifestContentHash;\n if (\n !hasChanges &&\n !parsedArgs.force &&\n localHeadDigest != null &&\n remoteHeadDigest === localHeadDigest &&\n !pendingSync &&\n !manifestOutOfSync\n ) {\n consola.info(\"No local authored changes to sync.\");\n return;\n }\n\n const localFiles = await collectLocalFiles(projectRoot);\n const sourceChanges = buildSourceSnapshotChanges(localFiles);\n const { changes } = await materializeSourceChangeOperations(sourceChanges);\n const uploadBlobs = mapUpsertBlobContentsByContentHash(\n sourceChanges,\n changes,\n );\n await uploadProjectSourceBlobsSdk(\n nextProjectConfig.projectId,\n Array.from(uploadBlobs.values()),\n );\n\n const sourceFiles = changes\n .filter((change) => change.kind === \"upsert\")\n .map(({ path, contentHash, byteSize }) => ({\n path,\n contentHash,\n byteSize,\n }));\n const revision = await createGameRevisionSdk({\n projectId: nextProjectConfig.projectId,\n request: {\n ...(remoteHeadDigest ? { baseRevisionDigest: remoteHeadDigest } : {}),\n source: { files: sourceFiles },\n ruleText: await loadRule(projectRoot),\n manifest: localManifest,\n },\n });\n nextProjectConfig = await persistProjectConfig({\n projectRoot,\n projectConfig: {\n ...updateProjectAuthoringState(nextProjectConfig, {\n revisionDigest: revision.revisionDigest,\n sourceTreeHash: revision.sourceTreeHash,\n manifestContentHash: revision.manifestContentHash,\n localManifestContentHash,\n }),\n remoteHeadDigest: revision.revisionDigest,\n },\n });\n nextProjectConfig = await finalizeLocalSync({\n projectRoot,\n projectConfig: nextProjectConfig,\n });\n\n consola.success(\n `Synced revision ${revision.revisionDigest}. Run 'dreamboard compile' when you're ready.`,\n );\n },\n});\n"],"mappings":"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","names":["path","path","path"]}
1
+ {"version":3,"sources":["../../src/services/project/source-revision-paths.ts","../../src/services/project/local-maintainer-registry.ts","../../src/services/project/local-maintainer-registry-shared.ts","../../src/commands/sync.ts"],"sourcesContent":["import { RULE_FILE } from \"../../constants.js\";\nimport {\n isAllowedGamePath,\n isDynamicGeneratedPath,\n} from \"./scaffold-ownership.js\";\n\n/**\n * Single definition of what belongs in an uploaded source revision, shared by\n * `dev` and `sync`. The compiler consumes the uploaded workspace as-is and\n * does not regenerate codegen outputs, so dynamic generated files (manifest\n * contract, ui-contract, framework tsconfigs) must always be included.\n */\nexport function isSourceRevisionPath(filePath: string): boolean {\n return filePath !== RULE_FILE && isAllowedGamePath(filePath);\n}\n\n/**\n * Files that must be upserted on every sync even when the local diff reports\n * them unchanged: registry configuration and regenerated codegen outputs.\n */\nexport function shouldAlwaysUpsertSourcePath(filePath: string): boolean {\n return filePath === \".npmrc\" || isDynamicGeneratedPath(filePath);\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { LocalMaintainerRegistryConfig } from \"../../types.js\";\nimport { resolveCliRepoRoot } from \"../../utils/repo-root.js\";\nimport {\n LOCAL_REGISTRY_URL,\n didLocalMaintainerSnapshotChange,\n getLocalMaintainerNpmrcContent,\n isLocalMaintainerRegistryEnabled,\n isLocalMaintainerRegistryUrl,\n shortHash,\n} from \"./local-maintainer-registry-shared.js\";\n\nexport {\n didLocalMaintainerSnapshotChange,\n getLocalMaintainerNpmrcContent,\n isLocalMaintainerRegistryEnabled,\n isLocalMaintainerRegistryUrl,\n};\n\nconst MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));\n\nfunction getCliPackageRoot(): string {\n try {\n return path.join(\n resolveCliRepoRoot(import.meta.url),\n \"apps\",\n \"dreamboard-cli\",\n );\n } catch {\n return resolveInstalledCliPackageRoot(MODULE_DIR);\n }\n}\n\nfunction resolveInstalledCliPackageRoot(moduleDir: string): string {\n let current = moduleDir;\n while (true) {\n const packageJsonPath = path.join(current, \"package.json\");\n if (existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(\n readFileSync(packageJsonPath, \"utf8\"),\n ) as { name?: unknown };\n if (\n packageJson.name === \"@dreamboard-games/cli\" ||\n packageJson.name === \"dreamboard\" ||\n packageJson.name === \"dreamboard-cli\"\n ) {\n return current;\n }\n } catch {\n // Keep walking upward; a malformed parent package should not hide the\n // installed CLI package root.\n }\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return moduleDir;\n }\n current = parent;\n }\n}\n\nfunction getScriptInvocation(): {\n command: string;\n args: string[];\n attemptedCommand: string;\n cwd: string;\n} {\n const cliPackageRoot = getCliPackageRoot();\n const scriptPath = getLocalMaintainerScriptPath(cliPackageRoot);\n if (!existsSync(scriptPath)) {\n throw new Error(\n [\n \"Dreamboard local maintainer registry support is only available from a source checkout.\",\n `Expected helper script at ${scriptPath}.`,\n ].join(\" \"),\n );\n }\n\n const command = process.platform === \"win32\" ? \"pnpm.cmd\" : \"pnpm\";\n const args = [\"exec\", \"tsx\", scriptPath];\n return {\n command,\n args,\n attemptedCommand: `${command} ${args.join(\" \")}`,\n cwd: cliPackageRoot,\n };\n}\n\nfunction getLocalMaintainerScriptPath(cliPackageRoot: string): string {\n return path.join(cliPackageRoot, \"scripts\", \"local-maintainer-registry.ts\");\n}\n\nfunction isInstalledCliPackageRoot(cliPackageRoot: string): boolean {\n return cliPackageRoot.split(path.sep).includes(\"node_modules\");\n}\n\nfunction shouldSkipLocalMaintainerHelper(): boolean {\n const cliPackageRoot = getCliPackageRoot();\n const scriptPath = getLocalMaintainerScriptPath(cliPackageRoot);\n return !existsSync(scriptPath) && isInstalledCliPackageRoot(cliPackageRoot);\n}\n\nexport function buildInstalledCliLocalMaintainerSnapshot(\n packageJson: { dependencies?: Record<string, unknown> },\n registryUrl: string = LOCAL_REGISTRY_URL,\n): LocalMaintainerRegistryConfig | null {\n const sdkVersion = packageJson.dependencies?.[\"@dreamboard-games/sdk\"];\n if (typeof sdkVersion !== \"string\" || !sdkVersion.includes(\"-local.\")) {\n return null;\n }\n\n return {\n registryUrl,\n snapshotId: shortHash(sdkVersion),\n fingerprint: shortHash(sdkVersion),\n publishedAt: \"\",\n packages: {\n \"@dreamboard-games/sdk\": sdkVersion,\n },\n };\n}\n\nexport function readInstalledCliLocalMaintainerSnapshot(): LocalMaintainerRegistryConfig | null {\n const cliPackageRoot = getCliPackageRoot();\n if (!isInstalledCliPackageRoot(cliPackageRoot)) {\n return null;\n }\n\n const packageJsonPath = path.join(cliPackageRoot, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n return null;\n }\n\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as {\n dependencies?: Record<string, unknown>;\n };\n return buildInstalledCliLocalMaintainerSnapshot(packageJson);\n}\n\nfunction buildScriptSetupError(options: {\n attemptedCommand: string;\n message: string;\n stderr?: string;\n}): Error {\n return new Error(\n [\n \"Dreamboard local maintainer registry support requires the source-checkout CLI tooling.\",\n options.message,\n `Attempted command: ${options.attemptedCommand}`,\n options.stderr?.trim() ? `stderr:\\n${options.stderr.trim()}` : null,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n );\n}\n\nfunction parseJsonPayload<T>(output: string): T {\n const payload = output\n .trim()\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .reverse()\n .find(\n (line) => line === \"null\" || line.startsWith(\"{\") || line.startsWith(\"[\"),\n );\n\n if (!payload) {\n throw new Error(\"completed without returning a JSON payload\");\n }\n\n return JSON.parse(payload) as T;\n}\n\nasync function runLocalMaintainerScript<T>(args: string[]): Promise<T> {\n const invocation = getScriptInvocation();\n\n return new Promise<T>((resolve, reject) => {\n const child = spawn(invocation.command, [...invocation.args, ...args], {\n cwd: invocation.cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: process.env,\n });\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout.on(\"data\", (chunk) => {\n stdout += chunk.toString();\n });\n child.stderr.on(\"data\", (chunk) => {\n stderr += chunk.toString();\n });\n child.on(\"error\", (error) => {\n const errnoError = error as NodeJS.ErrnoException;\n if (errnoError.code === \"ENOENT\") {\n reject(\n buildScriptSetupError({\n attemptedCommand: invocation.attemptedCommand,\n message:\n \"`pnpm` was not found on PATH, so the source-checkout local maintainer helper could not run.\",\n }),\n );\n return;\n }\n reject(error);\n });\n child.on(\"close\", (code) => {\n if (code !== 0) {\n const missingTsx =\n stderr.includes('Command \"tsx\" not found') ||\n stderr.includes(\"tsx: command not found\") ||\n stderr.includes(\"tsx: not found\");\n reject(\n buildScriptSetupError({\n attemptedCommand: invocation.attemptedCommand,\n message: missingTsx\n ? \"`tsx` is not available for the source-checkout CLI package.\"\n : \"The source-checkout local maintainer helper failed.\",\n stderr,\n }),\n );\n return;\n }\n\n const trimmedStdout = stdout.trim();\n if (!trimmedStdout) {\n reject(\n buildScriptSetupError({\n attemptedCommand: invocation.attemptedCommand,\n message:\n \"The source-checkout local maintainer helper completed without returning JSON.\",\n stderr,\n }),\n );\n return;\n }\n\n try {\n resolve(parseJsonPayload<T>(trimmedStdout));\n } catch (error) {\n reject(\n buildScriptSetupError({\n attemptedCommand: invocation.attemptedCommand,\n message: `Failed to parse JSON from the source-checkout local maintainer helper: ${\n error instanceof Error ? error.message : String(error)\n }`,\n stderr: [stderr.trim(), trimmedStdout].filter(Boolean).join(\"\\n\"),\n }),\n );\n }\n });\n });\n}\n\nexport async function ensureLocalMaintainerSnapshot(\n apiBaseUrl: string,\n): Promise<LocalMaintainerRegistryConfig | null> {\n if (!isLocalMaintainerRegistryEnabled(apiBaseUrl)) {\n return null;\n }\n if (shouldSkipLocalMaintainerHelper()) {\n return readInstalledCliLocalMaintainerSnapshot();\n }\n\n return runLocalMaintainerScript<LocalMaintainerRegistryConfig | null>([\n \"ensure-snapshot\",\n \"--api-base-url\",\n apiBaseUrl,\n ]);\n}\n\nexport async function readWorkspaceLocalMaintainerRegistry(\n projectRoot: string,\n fallbackRegistryUrl: string = LOCAL_REGISTRY_URL,\n): Promise<LocalMaintainerRegistryConfig | null> {\n if (shouldSkipLocalMaintainerHelper()) {\n return null;\n }\n return runLocalMaintainerScript<LocalMaintainerRegistryConfig | null>([\n \"read-workspace\",\n \"--project-root\",\n projectRoot,\n \"--fallback-registry-url\",\n fallbackRegistryUrl,\n ]);\n}\n","import crypto from \"node:crypto\";\nimport path from \"node:path\";\nimport { BUILD_CHANNEL, IS_PUBLISHED_BUILD } from \"../../build-target.js\";\nimport { ENVIRONMENT_CONFIGS } from \"../../constants.js\";\nimport type {\n LocalMaintainerRegistryConfig,\n LocalMaintainerRegistryPackages,\n LocalMaintainerSdkPackageName,\n} from \"../../types.js\";\nimport { exists, readJsonFile } from \"../../utils/fs.js\";\n\nconst localRegistryAddress = readLocalRegistryAddress();\nexport const LOCAL_REGISTRY_HOST = localRegistryAddress.host;\nexport const LOCAL_REGISTRY_PORT = localRegistryAddress.port;\nexport const LOCAL_REGISTRY_URL = `http://${LOCAL_REGISTRY_HOST}:${LOCAL_REGISTRY_PORT}`;\nexport const LOCAL_SCOPE_NPMRC_CONTENT = `@dreamboard-games:registry=${LOCAL_REGISTRY_URL}\\n`;\nexport const SDK_PUBLISH_ORDER: readonly LocalMaintainerSdkPackageName[] = [\n \"@dreamboard-games/sdk\",\n];\n\nexport type PackageJsonShape = {\n name?: string;\n version?: string;\n description?: string;\n type?: string;\n main?: string;\n types?: string;\n exports?: unknown;\n typesVersions?: Record<string, unknown>;\n files?: string[];\n bin?: Record<string, string>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n};\n\nfunction readLocalRegistryAddress(): { host: string; port: number } {\n const urlOverride = process.env.DREAMBOARD_LOCAL_REGISTRY_URL?.trim();\n const hostOverride = process.env.DREAMBOARD_LOCAL_REGISTRY_HOST?.trim();\n const portOverride = process.env.DREAMBOARD_LOCAL_REGISTRY_PORT?.trim();\n if (urlOverride) {\n let parsed: URL;\n try {\n parsed = new URL(urlOverride);\n } catch {\n throw new Error(\n `Invalid DREAMBOARD_LOCAL_REGISTRY_URL '${urlOverride}'. Expected an http://host:port URL.`,\n );\n }\n if (parsed.protocol !== \"http:\" || !parsed.hostname || !parsed.port) {\n throw new Error(\n `Invalid DREAMBOARD_LOCAL_REGISTRY_URL '${urlOverride}'. Expected an http://host:port URL.`,\n );\n }\n return {\n host: hostOverride || parsed.hostname,\n port: parseLocalRegistryPort(portOverride || parsed.port),\n };\n }\n return {\n host: hostOverride || \"127.0.0.1\",\n port: portOverride ? parseLocalRegistryPort(portOverride) : 4873,\n };\n}\n\nfunction parseLocalRegistryPort(raw: string): number {\n const port = Number.parseInt(raw, 10);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(\n `Invalid DREAMBOARD_LOCAL_REGISTRY_PORT '${raw}'. Expected a TCP port from 1 to 65535.`,\n );\n }\n return port;\n}\n\nexport function shortHash(value: string): string {\n return crypto.createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 12);\n}\n\nexport function isLocalMaintainerRegistryEnabled(apiBaseUrl: string): boolean {\n let isLocalLoopbackUrl = false;\n try {\n const parsed = new URL(apiBaseUrl);\n isLocalLoopbackUrl =\n parsed.protocol === \"http:\" &&\n (parsed.hostname === \"localhost\" || parsed.hostname === \"127.0.0.1\");\n } catch {\n isLocalLoopbackUrl = false;\n }\n\n return (\n !IS_PUBLISHED_BUILD &&\n (apiBaseUrl === ENVIRONMENT_CONFIGS.local?.apiBaseUrl ||\n isLocalLoopbackUrl) &&\n BUILD_CHANNEL === \"development\"\n );\n}\n\nexport function packageShortName(\n packageName: LocalMaintainerSdkPackageName,\n): string {\n return packageName.replace(/^@dreamboard(?:-games)?\\//, \"\");\n}\n\nexport async function readWorkspaceLocalMaintainerRegistryFromPackageJson(\n projectRoot: string,\n fallbackRegistryUrl: string = LOCAL_REGISTRY_URL,\n): Promise<LocalMaintainerRegistryConfig | null> {\n const packageJsonPath = path.join(projectRoot, \"package.json\");\n if (!(await exists(packageJsonPath))) {\n return null;\n }\n\n const packageJson = await readJsonFile<PackageJsonShape>(packageJsonPath);\n const sdkVersion =\n packageJson.dependencies?.[\"@dreamboard-games/sdk\"] ??\n packageJson.devDependencies?.[\"@dreamboard-games/sdk\"];\n const apiClientVersion =\n packageJson.dependencies?.[\"@dreamboard-games/api-client\"] ??\n packageJson.devDependencies?.[\"@dreamboard-games/api-client\"];\n const sdkDependencyVersion =\n packageJson.dependencies?.[\"@dreamboard-games/sdk\"];\n if (!sdkVersion?.includes(\"-local.\") || !sdkDependencyVersion) {\n return null;\n }\n const localSdkVersion = sdkVersion;\n\n const fingerprintSource = [\n apiClientVersion ?? \"\",\n localSdkVersion,\n fallbackRegistryUrl,\n ].join(\":\");\n return {\n registryUrl: fallbackRegistryUrl,\n snapshotId: shortHash(fingerprintSource),\n fingerprint: shortHash(fingerprintSource),\n publishedAt: \"\",\n packages: {\n \"@dreamboard-games/api-client\": apiClientVersion,\n \"@dreamboard-games/sdk\": localSdkVersion,\n } satisfies LocalMaintainerRegistryPackages,\n };\n}\n\nexport function getLocalMaintainerNpmrcContent(\n localMaintainerRegistry: LocalMaintainerRegistryConfig | null | undefined,\n): string | null {\n if (!localMaintainerRegistry) {\n return null;\n }\n return LOCAL_SCOPE_NPMRC_CONTENT.replace(\n LOCAL_REGISTRY_URL,\n localMaintainerRegistry.registryUrl,\n );\n}\n\nexport function didLocalMaintainerSnapshotChange(\n previous: LocalMaintainerRegistryConfig | undefined,\n next: LocalMaintainerRegistryConfig | null,\n): boolean {\n if (!next) {\n return false;\n }\n return previous?.snapshotId !== next.snapshotId;\n}\n\nexport function isLocalMaintainerRegistryUrl(\n fileContent: string | null,\n): boolean {\n if (!fileContent) {\n return false;\n }\n return /@dreamboard-games:registry=http:\\/\\/127\\.0\\.0\\.1:\\d+/.test(\n fileContent,\n );\n}\n","import { defineCommand } from \"citty\";\nimport consola from \"consola\";\nimport {\n mapUpsertBlobContentsByContentHash,\n materializeSourceChangeOperations,\n type SourceContentChangeOperation,\n} from \"@dreamboard-games/api-client/source-revisions\";\nimport { CONFIG_FLAG_ARGS } from \"../command-args.js\";\nimport { resolveProjectContext } from \"../config/resolve.js\";\nimport { updateProjectState } from \"../config/project-config.js\";\nimport { parseSyncCommandArgs } from \"../flags.js\";\nimport {\n collectLocalFiles,\n computeManifestHash,\n getLocalDiff,\n loadManifest,\n loadRule,\n writeSnapshot,\n} from \"../services/project/local-files.js\";\nimport {\n isSourceRevisionPath,\n shouldAlwaysUpsertSourcePath,\n} from \"../services/project/source-revision-paths.js\";\nimport {\n assertCliStaticScaffoldComplete,\n scaffoldStaticWorkspace,\n} from \"../services/project/static-scaffold.js\";\nimport {\n createGameRevisionSdk,\n uploadProjectSourceBlobsSdk,\n} from \"../services/api/index.js\";\nimport {\n getProjectAuthoringState,\n getProjectLocalMaintainerRegistry,\n getProjectPendingAuthoringSync,\n updateProjectAuthoringState,\n updateProjectLocalMaintainerRegistry,\n} from \"../services/project/project-state.js\";\nimport type { ProjectConfig } from \"../types.js\";\nimport { applyWorkspaceCodegen } from \"../services/project/workspace-codegen.js\";\nimport {\n didLocalMaintainerSnapshotChange,\n ensureLocalMaintainerSnapshot,\n isLocalMaintainerRegistryEnabled,\n} from \"../services/project/local-maintainer-registry.js\";\nimport { reconcileWorkspaceDependencies } from \"../services/project/workspace-dependencies.js\";\nimport { assertReducerContractPreflight } from \"../services/project/reducer-contract-preflight.js\";\nimport { assertReducerBundleSmoke } from \"../services/project/reducer-bundle-preflight.js\";\nimport { runLocalTypecheck } from \"../services/project/local-typecheck.js\";\nimport { resolveRemoteProject } from \"../services/project/remote-project.js\";\nimport { assertReleaseEnvironmentPortableDependencies } from \"../services/project/dependency-portability.js\";\n\nasync function runLoggedStep<T>(\n message: string,\n task: () => Promise<T>,\n): Promise<T> {\n consola.start(message);\n return task();\n}\n\nasync function persistProjectConfig(options: {\n projectRoot: string;\n projectConfig: ProjectConfig;\n}): Promise<ProjectConfig> {\n await updateProjectState(options.projectRoot, options.projectConfig);\n return options.projectConfig;\n}\n\nasync function finalizeLocalSync(options: {\n projectRoot: string;\n projectConfig: ProjectConfig;\n}): Promise<ProjectConfig> {\n const { projectRoot, projectConfig } = options;\n await scaffoldStaticWorkspace(projectRoot, \"update\", {\n localMaintainerRegistry: getProjectLocalMaintainerRegistry(projectConfig),\n });\n await applyWorkspaceCodegen({\n projectRoot,\n manifest: await loadManifest(projectRoot),\n });\n\n const finalizedProjectConfig = await persistProjectConfig({\n projectRoot,\n projectConfig,\n });\n await writeSnapshot(projectRoot);\n return finalizedProjectConfig;\n}\n\nfunction buildSourceSnapshotChanges(\n localFiles: Record<string, string>,\n): SourceContentChangeOperation[] {\n return Object.entries(localFiles)\n .filter(\n ([filePath]) =>\n isSourceRevisionPath(filePath) ||\n shouldAlwaysUpsertSourcePath(filePath),\n )\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([path, content]) => ({\n kind: \"upsert\",\n path,\n content,\n }));\n}\n\nexport default defineCommand({\n meta: {\n name: \"sync\",\n description:\n \"Upload authored changes and advance the remote authoring head\",\n },\n args: {\n force: {\n type: \"boolean\",\n description:\n \"Replace the full authored source tree, manifest, and rules, overwriting the remote head with the local copy even when the remote has moved\",\n default: false,\n },\n yes: {\n type: \"boolean\",\n alias: \"y\",\n description: \"Reserved for non-interactive scaffold flows\",\n default: false,\n },\n ...CONFIG_FLAG_ARGS,\n },\n async run({ args }) {\n const parsedArgs = parseSyncCommandArgs(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 const localMaintainerEnabled = isLocalMaintainerRegistryEnabled(\n config.apiBaseUrl,\n );\n const existingLocalMaintainerRegistry =\n getProjectLocalMaintainerRegistry(projectConfig);\n const refreshedLocalMaintainerRegistry = localMaintainerEnabled\n ? await runLoggedStep(\"Checking local SDK snapshot...\", () =>\n ensureLocalMaintainerSnapshot(config.apiBaseUrl),\n )\n : await ensureLocalMaintainerSnapshot(config.apiBaseUrl);\n const localMaintainerRegistry =\n refreshedLocalMaintainerRegistry ??\n (localMaintainerEnabled\n ? (existingLocalMaintainerRegistry ?? null)\n : null);\n const localMaintainerSnapshotChanged = didLocalMaintainerSnapshotChange(\n existingLocalMaintainerRegistry,\n refreshedLocalMaintainerRegistry,\n );\n if (refreshedLocalMaintainerRegistry) {\n nextProjectConfig = updateProjectLocalMaintainerRegistry(\n nextProjectConfig,\n refreshedLocalMaintainerRegistry,\n );\n consola.info(\n localMaintainerSnapshotChanged\n ? \"Local SDK snapshot refreshed.\"\n : \"Using existing local SDK snapshot.\",\n );\n } else if (localMaintainerRegistry) {\n consola.info(\"Using workspace-pinned local SDK snapshot.\");\n }\n\n await runLoggedStep(\"Refreshing static scaffold...\", () =>\n scaffoldStaticWorkspace(projectRoot, \"update\", {\n localMaintainerRegistry,\n }),\n );\n const localManifest = await loadManifest(projectRoot);\n await runLoggedStep(\"Applying workspace codegen...\", async () =>\n applyWorkspaceCodegen({\n projectRoot,\n manifest: localManifest,\n }),\n );\n const dependencyState = await runLoggedStep(\n \"Reconciling workspace dependencies...\",\n () => reconcileWorkspaceDependencies(projectRoot),\n );\n if (\n dependencyState.packageManagerNormalized ||\n dependencyState.lockfileGenerated ||\n dependencyState.installed ||\n localMaintainerSnapshotChanged\n ) {\n consola.info(\"Workspace dependencies reconciled.\");\n } else {\n consola.info(\"Workspace dependencies already up to date.\");\n }\n await runLoggedStep(\"Validating reducer contract...\", () =>\n assertReducerContractPreflight(projectRoot),\n );\n const typecheckResult = await runLoggedStep(\n \"Running local typecheck...\",\n () => runLocalTypecheck(projectRoot),\n );\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 before syncing.\",\n );\n }\n await runLoggedStep(\"Smoke-testing reducer bundle...\", async () =>\n assertReducerBundleSmoke({\n projectRoot,\n manifest: localManifest,\n }),\n );\n consola.success(\"Reducer bundle smoke test passed.\");\n\n const remoteProject = await runLoggedStep(\"Ensuring remote project...\", () =>\n resolveRemoteProject({\n projectRoot,\n projectConfig: nextProjectConfig,\n config,\n }),\n );\n nextProjectConfig = remoteProject.projectConfig;\n\n const localDiff = await getLocalDiff(projectRoot);\n await assertCliStaticScaffoldComplete(projectRoot, localDiff.deleted);\n\n const localAuthoring = getProjectAuthoringState(nextProjectConfig);\n const pendingSync = getProjectPendingAuthoringSync(nextProjectConfig);\n const remoteHeadDigest = remoteProject.project.head?.revisionDigest;\n const localHeadDigest =\n localAuthoring.revisionDigest ?? nextProjectConfig.remoteHeadDigest;\n\n if (pendingSync && !parsedArgs.force) {\n throw new Error(\n \"This workspace has an unfinished legacy sync checkpoint. Run 'dreamboard sync --force' to replace it with an atomic project revision.\",\n );\n }\n\n if (\n remoteHeadDigest &&\n localHeadDigest &&\n remoteHeadDigest !== localHeadDigest\n ) {\n if (parsedArgs.force) {\n consola.warn(\n `Remote project head has moved to ${remoteHeadDigest}. --force will overwrite it with this workspace's local copy.`,\n );\n } else {\n throw new Error(\n `Remote project head has moved to ${remoteHeadDigest}. Run 'dreamboard pull' before syncing local changes, or pass --force to overwrite the remote with the local copy.`,\n );\n }\n }\n\n if (remoteHeadDigest && !localHeadDigest) {\n if (parsedArgs.force) {\n consola.warn(\n `This workspace has no authored base but the remote project head is ${remoteHeadDigest}. --force will overwrite it with this workspace's local copy.`,\n );\n } else {\n throw new Error(\n `This workspace has no authored base but the remote project head is ${remoteHeadDigest}. Re-clone, run 'dreamboard pull --force' into a clean workspace, or pass --force to overwrite the remote with the local copy.`,\n );\n }\n }\n\n const hasChanges =\n localDiff.modified.length > 0 ||\n localDiff.added.length > 0 ||\n localDiff.deleted.length > 0;\n const localManifestContentHash = computeManifestHash(localManifest);\n const manifestOutOfSync =\n localAuthoring.localManifestContentHash !== localManifestContentHash;\n if (\n !hasChanges &&\n !parsedArgs.force &&\n localHeadDigest != null &&\n remoteHeadDigest === localHeadDigest &&\n !pendingSync &&\n !manifestOutOfSync\n ) {\n consola.info(\"No local authored changes to sync.\");\n return;\n }\n\n const localFiles = await collectLocalFiles(projectRoot);\n const sourceChanges = buildSourceSnapshotChanges(localFiles);\n const { changes } = await materializeSourceChangeOperations(sourceChanges);\n const uploadBlobs = mapUpsertBlobContentsByContentHash(\n sourceChanges,\n changes,\n );\n await uploadProjectSourceBlobsSdk(\n nextProjectConfig.projectId,\n Array.from(uploadBlobs.values()),\n );\n\n const sourceFiles = changes\n .filter((change) => change.kind === \"upsert\")\n .map(({ path, contentHash, byteSize }) => ({\n path,\n contentHash,\n byteSize,\n }));\n const revision = await createGameRevisionSdk({\n projectId: nextProjectConfig.projectId,\n request: {\n ...(remoteHeadDigest ? { baseRevisionDigest: remoteHeadDigest } : {}),\n source: { files: sourceFiles },\n ruleText: await loadRule(projectRoot),\n manifest: localManifest,\n },\n });\n nextProjectConfig = await persistProjectConfig({\n projectRoot,\n projectConfig: {\n ...updateProjectAuthoringState(nextProjectConfig, {\n revisionDigest: revision.revisionDigest,\n sourceTreeHash: revision.sourceTreeHash,\n manifestContentHash: revision.manifestContentHash,\n localManifestContentHash,\n }),\n remoteHeadDigest: revision.revisionDigest,\n },\n });\n nextProjectConfig = await finalizeLocalSync({\n projectRoot,\n projectConfig: nextProjectConfig,\n });\n\n consola.success(\n `Synced revision ${revision.revisionDigest}. Run 'dreamboard compile' when you're ready.`,\n );\n },\n});\n"],"mappings":"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","names":["path","path","path"]}
@@ -16,7 +16,7 @@ import {
16
16
  generateReducerNativeArtifacts,
17
17
  isReducerNativeTestingWorkspace,
18
18
  runReducerNativeScenarios
19
- } from "./chunk-DN2JHUGM.mjs";
19
+ } from "./chunk-7ODN2WLL.mjs";
20
20
  import "./chunk-XKCJBIRY.mjs";
21
21
  import {
22
22
  STALE_CONTRACT_ARTIFACT_CODE,
@@ -29,18 +29,19 @@ import {
29
29
  configureClient,
30
30
  consola,
31
31
  resolveProjectContext
32
- } from "./chunk-7CNBKWWE.mjs";
32
+ } from "./chunk-MGXX4WFR.mjs";
33
+ import "./chunk-3IJBOLGT.mjs";
33
34
  import "./chunk-W2MDP5ZN.mjs";
34
- import "./chunk-M2MHRWSP.mjs";
35
+ import "./chunk-RG4PPQC2.mjs";
36
+ import "./chunk-TAEQKBJB.mjs";
35
37
  import "./chunk-F2DIOJJZ.mjs";
36
38
  import {
37
39
  IS_PUBLISHED_BUILD
38
- } from "./chunk-RHGGFAMQ.mjs";
40
+ } from "./chunk-KK47X7RV.mjs";
39
41
  import "./chunk-XIFLZGDQ.mjs";
40
42
  import "./chunk-JZTH3EMV.mjs";
41
43
  import "./chunk-QBAF7EYR.mjs";
42
44
  import "./chunk-NAK77WXW.mjs";
43
- import "./chunk-TAEQKBJB.mjs";
44
45
  import "./chunk-IAYRNVUC.mjs";
45
46
  import "./chunk-M7UVBANQ.mjs";
46
47
  import "./chunk-H6XDQJ3N.mjs";
@@ -350,4 +351,4 @@ export {
350
351
  resolveRequestedRunner,
351
352
  resolveTestRunExitCode
352
353
  };
353
- //# sourceMappingURL=test-RCFDQBEQ.mjs.map
354
+ //# sourceMappingURL=test-VKDPAIPF.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/test.ts","../../src/services/testing/runtime-mode.ts","../../src/services/workflows/resolve-latest-compiled-result.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport consola from \"consola\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { CONFIG_FLAG_ARGS } from \"../command-args.js\";\nimport { configureClient, resolveProjectContext } from \"../config/resolve.js\";\nimport { parseConfigFlags } from \"../flags.js\";\nimport { uploadInitialProjectionSdk } from \"../services/api/index.js\";\nimport { assertReleaseEnvironmentPortableDependencies } from \"../services/project/dependency-portability.js\";\nimport {\n generateReducerNativeArtifacts,\n isReducerNativeTestingWorkspace,\n runReducerNativeScenarios,\n type ReducerNativeScenarioSummary,\n} from \"../services/testing/reducer-native-test-harness.js\";\nimport { shouldUseRemoteTestRuntime } from \"../services/testing/runtime-mode.js\";\nimport { resolveLatestCompiledResult } from \"../services/workflows/resolve-latest-compiled-result.js\";\nimport type { ProjectConfig } from \"../types.js\";\nimport {\n isDreamboardApiError,\n isStaleContractArtifactMessage,\n STALE_CONTRACT_ARTIFACT_CODE,\n STALE_CONTRACT_ARTIFACT_EXIT_CODE,\n} from \"../utils/errors.js\";\n\ntype RequestedTestRunner = \"reducer\" | \"remote\" | \"browser\";\n\nexport const REDUCER_NATIVE_TEST_WORKSPACE_ERROR =\n \"dreamboard test now requires a reducer-native workspace with app/game.ts, shared/generated/ui-contract.ts, test/bases/*.base.ts, and test/scenarios/*.scenario.ts. Legacy test/base-scenarios.json workspaces are no longer supported.\";\n\nexport const NO_REDUCER_NATIVE_BASES_FOUND_ERROR =\n \"No bases found under test/bases/*.base.ts\";\n\nexport const NO_REDUCER_NATIVE_SCENARIOS_FOUND_ERROR =\n \"No scenarios found under test/scenarios/*.scenario.ts\";\n\nexport function isPreviewProjectionEndpointUnavailable(\n error: unknown,\n): boolean {\n if (!isDreamboardApiError(error) || error.status !== 404) {\n return false;\n }\n\n const endpoint = error.problem.instance ?? error.problem.context?.endpoint;\n const message = error.problem.detail ?? error.problem.title;\n return (\n endpoint?.includes(\"/preview/initial-projection\") === true &&\n message?.toLowerCase() === \"not found\"\n );\n}\n\nasync function uploadGeneratedPreviewProjection(options: {\n projectRoot: string;\n gameId: string;\n bases: Array<{ definition: { id: string } }>;\n}): Promise<void> {\n const previewBase =\n options.bases.find((base) => base.definition.id === \"initial-turn\") ??\n options.bases[0];\n if (!previewBase) {\n return;\n }\n const projectionPath = path.join(\n options.projectRoot,\n \"test\",\n \"generated\",\n \"bases\",\n previewBase.definition.id,\n \"player-1.projection.json\",\n );\n const projectionJson = await readFile(projectionPath, \"utf8\");\n try {\n await uploadInitialProjectionSdk(options.gameId, projectionJson);\n } catch (error) {\n if (isPreviewProjectionEndpointUnavailable(error)) {\n consola.warn(\n \"Skipping preview projection upload because the selected backend does not expose the preview projection endpoint.\",\n );\n return;\n }\n throw error;\n }\n}\n\nexport function resolveRequestedRunner(\n value: unknown,\n): RequestedTestRunner | undefined {\n if (value == null || value === \"\") {\n return undefined;\n }\n if (value === \"reducer\" || value === \"remote\" || value === \"browser\") {\n return value;\n }\n throw new Error(\n `Unsupported test runner '${String(value)}'. Expected one of reducer, remote, browser.`,\n );\n}\n\nfunction isStaleContractArtifactResult(\n result: ReducerNativeScenarioSummary[\"results\"][number],\n): boolean {\n return (\n result.errorCode === STALE_CONTRACT_ARTIFACT_CODE ||\n (result.error ? isStaleContractArtifactMessage(result.error) : false)\n );\n}\n\nexport function resolveTestRunExitCode(\n summary: ReducerNativeScenarioSummary,\n): number {\n if (summary.failed === 0) {\n return 0;\n }\n return summary.results.some(\n (result) => !result.success && isStaleContractArtifactResult(result),\n )\n ? STALE_CONTRACT_ARTIFACT_EXIT_CODE\n : 1;\n}\n\nasync function assertReducerNativeTestingWorkspace(\n projectRoot: string,\n): Promise<void> {\n if (await isReducerNativeTestingWorkspace(projectRoot)) {\n return;\n }\n\n throw new Error(REDUCER_NATIVE_TEST_WORKSPACE_ERROR);\n}\n\nasync function resolveReducerNativeRuntimeIdentity(options: {\n projectRoot: string;\n projectConfig: ProjectConfig;\n useRemoteRuntime: boolean;\n runner?: RequestedTestRunner;\n}): Promise<{\n gameId: string;\n compiledResultId?: string;\n}> {\n if (\n options.useRemoteRuntime ||\n options.runner === \"remote\" ||\n options.runner === \"browser\"\n ) {\n const latestCompiledResult = await resolveLatestCompiledResult(\n options.projectRoot,\n options.projectConfig,\n );\n return {\n gameId: options.projectConfig.gameId,\n compiledResultId: latestCompiledResult.id,\n };\n }\n\n return {\n gameId: options.projectConfig.gameId,\n compiledResultId: options.projectConfig.compile?.latestSuccessful?.resultId,\n };\n}\n\nconst generateCommand = defineCommand({\n meta: {\n name: \"generate\",\n description: \"Generate reducer-native base artifacts for typed scenarios\",\n },\n args: {\n scenario: {\n type: \"string\",\n description: \"Optional scenario file path under test/scenarios\",\n },\n debug: {\n type: \"boolean\",\n description: \"Print full reducer-native validation details\",\n default: false,\n },\n \"update-snapshots\": {\n type: \"boolean\",\n description: \"Refresh generated projection and scenario snapshots\",\n default: false,\n },\n ...CONFIG_FLAG_ARGS,\n },\n async run({ args }) {\n const parsedFlags = parseConfigFlags(args);\n const useRemoteRuntime = shouldUseRemoteTestRuntime(parsedFlags.env);\n const { projectRoot, projectConfig, config } = await resolveProjectContext(\n parsedFlags,\n { requireAuth: useRemoteRuntime },\n );\n await assertReleaseEnvironmentPortableDependencies({\n projectRoot,\n projectConfig,\n environment: config.environment,\n });\n\n await assertReducerNativeTestingWorkspace(projectRoot);\n\n const runtimeIdentity = await resolveReducerNativeRuntimeIdentity({\n projectRoot,\n projectConfig,\n useRemoteRuntime,\n });\n const { bases, scenarios } = await generateReducerNativeArtifacts({\n projectRoot,\n scenarioPath: args.scenario,\n compiledResultId: runtimeIdentity.compiledResultId,\n gameId: runtimeIdentity.gameId,\n debug: Boolean(args.debug),\n });\n\n if (bases.length === 0) {\n throw new Error(NO_REDUCER_NATIVE_BASES_FOUND_ERROR);\n }\n if (scenarios.length === 0) {\n throw new Error(NO_REDUCER_NATIVE_SCENARIOS_FOUND_ERROR);\n }\n\n if (useRemoteRuntime && config.authToken) {\n await configureClient(config);\n await uploadGeneratedPreviewProjection({\n projectRoot,\n gameId: runtimeIdentity.gameId,\n bases,\n });\n } else {\n consola.info(\n \"Skipping preview projection upload because this test generation is local-only.\",\n );\n }\n\n consola.success(\n `Generated ${bases.length} base state(s) for ${scenarios.length} scenario(s).`,\n );\n },\n});\n\nconst runCommand = defineCommand({\n meta: {\n name: \"run\",\n description: \"Run reducer-native scenarios from test/scenarios\",\n },\n args: {\n scenario: {\n type: \"string\",\n description: \"Optional scenario file path under test/scenarios\",\n },\n debug: {\n type: \"boolean\",\n description: \"Print full reducer-native validation details\",\n default: false,\n },\n \"update-snapshots\": {\n type: \"boolean\",\n description: \"Refresh generated projection and scenario snapshots\",\n default: false,\n },\n runner: {\n type: \"string\",\n valueHint: \"reducer|remote|browser\",\n description:\n \"Scenario runner: reducer (in-process, default), remote (live sessions against the configured backend), or browser (local web stack).\",\n },\n ...CONFIG_FLAG_ARGS,\n },\n async run({ args }) {\n const parsedFlags = parseConfigFlags(args);\n const useRemoteRuntime = shouldUseRemoteTestRuntime(parsedFlags.env);\n const runner = resolveRequestedRunner(args.runner) ?? \"reducer\";\n const { projectRoot, projectConfig, config } = await resolveProjectContext(\n parsedFlags,\n {\n requireAuth:\n useRemoteRuntime || runner === \"remote\" || runner === \"browser\",\n },\n );\n await assertReleaseEnvironmentPortableDependencies({\n projectRoot,\n projectConfig,\n environment: config.environment,\n });\n\n await assertReducerNativeTestingWorkspace(projectRoot);\n\n const runtimeIdentity = await resolveReducerNativeRuntimeIdentity({\n projectRoot,\n projectConfig,\n useRemoteRuntime,\n runner,\n });\n const summary = await runReducerNativeScenarios({\n projectRoot,\n projectConfig,\n resolvedConfig: config,\n runner,\n scenarioPath: args.scenario,\n compiledResultId: runtimeIdentity.compiledResultId,\n gameId: runtimeIdentity.gameId,\n debug: Boolean(args.debug),\n updateSnapshots: Boolean(args[\"update-snapshots\"]),\n });\n\n for (const result of summary.results) {\n if (result.success) {\n consola.success(`PASS ${result.id}`);\n } else if (\n result.errorCode === STALE_CONTRACT_ARTIFACT_CODE &&\n result.error\n ) {\n consola.error(result.error);\n } else {\n consola.error(\n `FAIL ${result.id}: ${result.error ?? \"Scenario failed\"}`,\n );\n }\n }\n\n consola.info(\n `Test summary: ${summary.passed} passed, ${summary.failed} failed.`,\n );\n if (summary.failed > 0) {\n process.exitCode = resolveTestRunExitCode(summary);\n }\n },\n});\n\nexport default defineCommand({\n meta: {\n name: \"test\",\n description: \"Reducer-native test runner with typed bases and scenarios\",\n },\n subCommands: {\n generate: generateCommand,\n run: runCommand,\n },\n});\n","import { IS_PUBLISHED_BUILD } from \"../../build-target.js\";\n\nexport function isRemoteTestEnvironment(\n environment: string | undefined,\n): environment is \"staging\" | \"prod\" {\n return environment === \"staging\" || environment === \"prod\";\n}\n\nexport function shouldUseRemoteTestRuntime(\n environment: string | undefined,\n): boolean {\n return IS_PUBLISHED_BUILD || isRemoteTestEnvironment(environment);\n}\n","import consola from \"consola\";\nimport type { CompiledResult } from \"@dreamboard-games/api-client\";\nimport type { ProjectConfig } from \"../../types.js\";\nimport {\n findProjectCompiledResultsForRevision,\n getProjectCompiledResultSdk,\n} from \"../api/compiled-results-api.js\";\nimport {\n getProjectCompileState,\n getProjectAuthoringState,\n getProjectPendingAuthoringSync,\n} from \"../project/project-state.js\";\n\nexport async function resolveLatestCompiledResult(\n projectRoot: string,\n projectConfig: ProjectConfig,\n): Promise<CompiledResult> {\n void projectRoot;\n const authoring = getProjectAuthoringState(projectConfig);\n if (getProjectPendingAuthoringSync(projectConfig)) {\n throw new Error(\n \"Previous sync did not finish updating local scaffold files. Run 'dreamboard sync' again first.\",\n );\n }\n if (authoring.revisionDigest) {\n const compile = getProjectCompileState(projectConfig);\n const latestSuccess = (\n await findProjectCompiledResultsForRevision({\n projectId: projectConfig.projectId,\n revisionDigest: authoring.revisionDigest,\n })\n ).find((result) => result.success);\n const matchingLocalSuccess =\n compile.latestSuccessful?.revisionDigest === authoring.revisionDigest\n ? compile.latestSuccessful\n : undefined;\n const resolvedSuccess =\n latestSuccess ??\n (matchingLocalSuccess?.resultId\n ? await getProjectCompiledResultSdk(\n projectConfig.projectId,\n matchingLocalSuccess.resultId,\n )\n : undefined);\n\n if (!resolvedSuccess?.success) {\n throw new Error(\n \"No successful compile exists for the current authored revision. Run 'dreamboard compile' first.\",\n );\n }\n\n const resultRevisionDigest = (resolvedSuccess as { revisionDigest?: string })\n .revisionDigest;\n if (\n resultRevisionDigest &&\n resultRevisionDigest !== authoring.revisionDigest\n ) {\n consola.warn(\n `Latest successful compile ${resolvedSuccess.id} belongs to ${resultRevisionDigest}, not ${authoring.revisionDigest}.`,\n );\n }\n\n consola.info(\n `Project summary:\\n compiledResultId: ${resolvedSuccess.id}\\n revisionDigest: ${authoring.revisionDigest}`,\n );\n\n return resolvedSuccess;\n }\n\n throw new Error(\n \"This workspace does not know its project revision yet. Run 'dreamboard sync' first.\",\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/commands/test.ts","../../src/services/testing/runtime-mode.ts","../../src/services/workflows/resolve-latest-compiled-result.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport consola from \"consola\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { CONFIG_FLAG_ARGS } from \"../command-args.js\";\nimport { configureClient, resolveProjectContext } from \"../config/resolve.js\";\nimport { parseConfigFlags } from \"../flags.js\";\nimport { uploadInitialProjectionSdk } from \"../services/api/index.js\";\nimport { assertReleaseEnvironmentPortableDependencies } from \"../services/project/dependency-portability.js\";\nimport {\n generateReducerNativeArtifacts,\n isReducerNativeTestingWorkspace,\n runReducerNativeScenarios,\n type ReducerNativeScenarioSummary,\n} from \"../services/testing/reducer-native-test-harness.js\";\nimport { shouldUseRemoteTestRuntime } from \"../services/testing/runtime-mode.js\";\nimport { resolveLatestCompiledResult } from \"../services/workflows/resolve-latest-compiled-result.js\";\nimport type { ProjectConfig } from \"../types.js\";\nimport {\n isDreamboardApiError,\n isStaleContractArtifactMessage,\n STALE_CONTRACT_ARTIFACT_CODE,\n STALE_CONTRACT_ARTIFACT_EXIT_CODE,\n} from \"../utils/errors.js\";\n\ntype RequestedTestRunner = \"reducer\" | \"remote\" | \"browser\";\n\nexport const REDUCER_NATIVE_TEST_WORKSPACE_ERROR =\n \"dreamboard test now requires a reducer-native workspace with app/game.ts, shared/generated/ui-contract.ts, test/bases/*.base.ts, and test/scenarios/*.scenario.ts. Legacy test/base-scenarios.json workspaces are no longer supported.\";\n\nexport const NO_REDUCER_NATIVE_BASES_FOUND_ERROR =\n \"No bases found under test/bases/*.base.ts\";\n\nexport const NO_REDUCER_NATIVE_SCENARIOS_FOUND_ERROR =\n \"No scenarios found under test/scenarios/*.scenario.ts\";\n\nexport function isPreviewProjectionEndpointUnavailable(\n error: unknown,\n): boolean {\n if (!isDreamboardApiError(error) || error.status !== 404) {\n return false;\n }\n\n const endpoint = error.problem.instance ?? error.problem.context?.endpoint;\n const message = error.problem.detail ?? error.problem.title;\n return (\n endpoint?.includes(\"/preview/initial-projection\") === true &&\n message?.toLowerCase() === \"not found\"\n );\n}\n\nasync function uploadGeneratedPreviewProjection(options: {\n projectRoot: string;\n gameId: string;\n bases: Array<{ definition: { id: string } }>;\n}): Promise<void> {\n const previewBase =\n options.bases.find((base) => base.definition.id === \"initial-turn\") ??\n options.bases[0];\n if (!previewBase) {\n return;\n }\n const projectionPath = path.join(\n options.projectRoot,\n \"test\",\n \"generated\",\n \"bases\",\n previewBase.definition.id,\n \"player-1.projection.json\",\n );\n const projectionJson = await readFile(projectionPath, \"utf8\");\n try {\n await uploadInitialProjectionSdk(options.gameId, projectionJson);\n } catch (error) {\n if (isPreviewProjectionEndpointUnavailable(error)) {\n consola.warn(\n \"Skipping preview projection upload because the selected backend does not expose the preview projection endpoint.\",\n );\n return;\n }\n throw error;\n }\n}\n\nexport function resolveRequestedRunner(\n value: unknown,\n): RequestedTestRunner | undefined {\n if (value == null || value === \"\") {\n return undefined;\n }\n if (value === \"reducer\" || value === \"remote\" || value === \"browser\") {\n return value;\n }\n throw new Error(\n `Unsupported test runner '${String(value)}'. Expected one of reducer, remote, browser.`,\n );\n}\n\nfunction isStaleContractArtifactResult(\n result: ReducerNativeScenarioSummary[\"results\"][number],\n): boolean {\n return (\n result.errorCode === STALE_CONTRACT_ARTIFACT_CODE ||\n (result.error ? isStaleContractArtifactMessage(result.error) : false)\n );\n}\n\nexport function resolveTestRunExitCode(\n summary: ReducerNativeScenarioSummary,\n): number {\n if (summary.failed === 0) {\n return 0;\n }\n return summary.results.some(\n (result) => !result.success && isStaleContractArtifactResult(result),\n )\n ? STALE_CONTRACT_ARTIFACT_EXIT_CODE\n : 1;\n}\n\nasync function assertReducerNativeTestingWorkspace(\n projectRoot: string,\n): Promise<void> {\n if (await isReducerNativeTestingWorkspace(projectRoot)) {\n return;\n }\n\n throw new Error(REDUCER_NATIVE_TEST_WORKSPACE_ERROR);\n}\n\nasync function resolveReducerNativeRuntimeIdentity(options: {\n projectRoot: string;\n projectConfig: ProjectConfig;\n useRemoteRuntime: boolean;\n runner?: RequestedTestRunner;\n}): Promise<{\n gameId: string;\n compiledResultId?: string;\n}> {\n if (\n options.useRemoteRuntime ||\n options.runner === \"remote\" ||\n options.runner === \"browser\"\n ) {\n const latestCompiledResult = await resolveLatestCompiledResult(\n options.projectRoot,\n options.projectConfig,\n );\n return {\n gameId: options.projectConfig.gameId,\n compiledResultId: latestCompiledResult.id,\n };\n }\n\n return {\n gameId: options.projectConfig.gameId,\n compiledResultId: options.projectConfig.compile?.latestSuccessful?.resultId,\n };\n}\n\nconst generateCommand = defineCommand({\n meta: {\n name: \"generate\",\n description: \"Generate reducer-native base artifacts for typed scenarios\",\n },\n args: {\n scenario: {\n type: \"string\",\n description: \"Optional scenario file path under test/scenarios\",\n },\n debug: {\n type: \"boolean\",\n description: \"Print full reducer-native validation details\",\n default: false,\n },\n \"update-snapshots\": {\n type: \"boolean\",\n description: \"Refresh generated projection and scenario snapshots\",\n default: false,\n },\n ...CONFIG_FLAG_ARGS,\n },\n async run({ args }) {\n const parsedFlags = parseConfigFlags(args);\n const useRemoteRuntime = shouldUseRemoteTestRuntime(parsedFlags.env);\n const { projectRoot, projectConfig, config } = await resolveProjectContext(\n parsedFlags,\n { requireAuth: useRemoteRuntime },\n );\n await assertReleaseEnvironmentPortableDependencies({\n projectRoot,\n projectConfig,\n environment: config.environment,\n });\n\n await assertReducerNativeTestingWorkspace(projectRoot);\n\n const runtimeIdentity = await resolveReducerNativeRuntimeIdentity({\n projectRoot,\n projectConfig,\n useRemoteRuntime,\n });\n const { bases, scenarios } = await generateReducerNativeArtifacts({\n projectRoot,\n scenarioPath: args.scenario,\n compiledResultId: runtimeIdentity.compiledResultId,\n gameId: runtimeIdentity.gameId,\n debug: Boolean(args.debug),\n });\n\n if (bases.length === 0) {\n throw new Error(NO_REDUCER_NATIVE_BASES_FOUND_ERROR);\n }\n if (scenarios.length === 0) {\n throw new Error(NO_REDUCER_NATIVE_SCENARIOS_FOUND_ERROR);\n }\n\n if (useRemoteRuntime && config.authToken) {\n await configureClient(config);\n await uploadGeneratedPreviewProjection({\n projectRoot,\n gameId: runtimeIdentity.gameId,\n bases,\n });\n } else {\n consola.info(\n \"Skipping preview projection upload because this test generation is local-only.\",\n );\n }\n\n consola.success(\n `Generated ${bases.length} base state(s) for ${scenarios.length} scenario(s).`,\n );\n },\n});\n\nconst runCommand = defineCommand({\n meta: {\n name: \"run\",\n description: \"Run reducer-native scenarios from test/scenarios\",\n },\n args: {\n scenario: {\n type: \"string\",\n description: \"Optional scenario file path under test/scenarios\",\n },\n debug: {\n type: \"boolean\",\n description: \"Print full reducer-native validation details\",\n default: false,\n },\n \"update-snapshots\": {\n type: \"boolean\",\n description: \"Refresh generated projection and scenario snapshots\",\n default: false,\n },\n runner: {\n type: \"string\",\n valueHint: \"reducer|remote|browser\",\n description:\n \"Scenario runner: reducer (in-process, default), remote (live sessions against the configured backend), or browser (local web stack).\",\n },\n ...CONFIG_FLAG_ARGS,\n },\n async run({ args }) {\n const parsedFlags = parseConfigFlags(args);\n const useRemoteRuntime = shouldUseRemoteTestRuntime(parsedFlags.env);\n const runner = resolveRequestedRunner(args.runner) ?? \"reducer\";\n const { projectRoot, projectConfig, config } = await resolveProjectContext(\n parsedFlags,\n {\n requireAuth:\n useRemoteRuntime || runner === \"remote\" || runner === \"browser\",\n },\n );\n await assertReleaseEnvironmentPortableDependencies({\n projectRoot,\n projectConfig,\n environment: config.environment,\n });\n\n await assertReducerNativeTestingWorkspace(projectRoot);\n\n const runtimeIdentity = await resolveReducerNativeRuntimeIdentity({\n projectRoot,\n projectConfig,\n useRemoteRuntime,\n runner,\n });\n const summary = await runReducerNativeScenarios({\n projectRoot,\n projectConfig,\n resolvedConfig: config,\n runner,\n scenarioPath: args.scenario,\n compiledResultId: runtimeIdentity.compiledResultId,\n gameId: runtimeIdentity.gameId,\n debug: Boolean(args.debug),\n updateSnapshots: Boolean(args[\"update-snapshots\"]),\n });\n\n for (const result of summary.results) {\n if (result.success) {\n consola.success(`PASS ${result.id}`);\n } else if (\n result.errorCode === STALE_CONTRACT_ARTIFACT_CODE &&\n result.error\n ) {\n consola.error(result.error);\n } else {\n consola.error(\n `FAIL ${result.id}: ${result.error ?? \"Scenario failed\"}`,\n );\n }\n }\n\n consola.info(\n `Test summary: ${summary.passed} passed, ${summary.failed} failed.`,\n );\n if (summary.failed > 0) {\n process.exitCode = resolveTestRunExitCode(summary);\n }\n },\n});\n\nexport default defineCommand({\n meta: {\n name: \"test\",\n description: \"Reducer-native test runner with typed bases and scenarios\",\n },\n subCommands: {\n generate: generateCommand,\n run: runCommand,\n },\n});\n","import { IS_PUBLISHED_BUILD } from \"../../build-target.js\";\n\nexport function isRemoteTestEnvironment(\n environment: string | undefined,\n): environment is \"staging\" | \"prod\" {\n return environment === \"staging\" || environment === \"prod\";\n}\n\nexport function shouldUseRemoteTestRuntime(\n environment: string | undefined,\n): boolean {\n return IS_PUBLISHED_BUILD || isRemoteTestEnvironment(environment);\n}\n","import consola from \"consola\";\nimport type { CompiledResult } from \"@dreamboard-games/api-client\";\nimport type { ProjectConfig } from \"../../types.js\";\nimport {\n findProjectCompiledResultsForRevision,\n getProjectCompiledResultSdk,\n} from \"../api/compiled-results-api.js\";\nimport {\n getProjectCompileState,\n getProjectAuthoringState,\n getProjectPendingAuthoringSync,\n} from \"../project/project-state.js\";\n\nexport async function resolveLatestCompiledResult(\n projectRoot: string,\n projectConfig: ProjectConfig,\n): Promise<CompiledResult> {\n void projectRoot;\n const authoring = getProjectAuthoringState(projectConfig);\n if (getProjectPendingAuthoringSync(projectConfig)) {\n throw new Error(\n \"Previous sync did not finish updating local scaffold files. Run 'dreamboard sync' again first.\",\n );\n }\n if (authoring.revisionDigest) {\n const compile = getProjectCompileState(projectConfig);\n const latestSuccess = (\n await findProjectCompiledResultsForRevision({\n projectId: projectConfig.projectId,\n revisionDigest: authoring.revisionDigest,\n })\n ).find((result) => result.success);\n const matchingLocalSuccess =\n compile.latestSuccessful?.revisionDigest === authoring.revisionDigest\n ? compile.latestSuccessful\n : undefined;\n const resolvedSuccess =\n latestSuccess ??\n (matchingLocalSuccess?.resultId\n ? await getProjectCompiledResultSdk(\n projectConfig.projectId,\n matchingLocalSuccess.resultId,\n )\n : undefined);\n\n if (!resolvedSuccess?.success) {\n throw new Error(\n \"No successful compile exists for the current authored revision. Run 'dreamboard compile' first.\",\n );\n }\n\n const resultRevisionDigest = (resolvedSuccess as { revisionDigest?: string })\n .revisionDigest;\n if (\n resultRevisionDigest &&\n resultRevisionDigest !== authoring.revisionDigest\n ) {\n consola.warn(\n `Latest successful compile ${resolvedSuccess.id} belongs to ${resultRevisionDigest}, not ${authoring.revisionDigest}.`,\n );\n }\n\n consola.info(\n `Project summary:\\n compiledResultId: ${resolvedSuccess.id}\\n revisionDigest: ${authoring.revisionDigest}`,\n );\n\n return resolvedSuccess;\n }\n\n throw new Error(\n \"This workspace does not know its project revision yet. Run 'dreamboard sync' first.\",\n );\n}\n"],"mappings":"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","names":[]}
package/dist/index.js CHANGED
@@ -107,7 +107,6 @@ import {
107
107
  DEFAULT_WEB_BASE_URL,
108
108
  MANIFEST_FILE,
109
109
  MANIFEST_TYPECHECK_CONFIG_FILE,
110
- PROJECT_CONFIG_FILE,
111
110
  PROJECT_DIR_NAME,
112
111
  RULE_FILE,
113
112
  clearCredentials,
@@ -3044,27 +3043,12 @@ async function getDynamicStaticEntries(projectRoot, mode, options = {}) {
3044
3043
  }
3045
3044
  return entries;
3046
3045
  }
3047
- async function readProjectLocalMaintainerRegistry(projectRoot) {
3048
- const projectConfigPath = path.join(
3049
- projectRoot,
3050
- PROJECT_DIR_NAME,
3051
- PROJECT_CONFIG_FILE
3052
- );
3053
- if (!await exists(projectConfigPath)) {
3054
- return null;
3055
- }
3056
- const projectConfig = await loadProjectConfig(projectRoot);
3057
- return projectConfig.localMaintainerRegistry ?? null;
3058
- }
3059
3046
  async function getExpectedStaticEntries(projectRoot) {
3060
- const localMaintainerRegistry = await readProjectLocalMaintainerRegistry(projectRoot);
3061
3047
  const entries = [
3062
3048
  ...(await getStaticAssetEntries()).filter(
3063
3049
  (entry) => entry.targetPath !== ".npmrc"
3064
3050
  ),
3065
- ...await getDynamicStaticEntries(projectRoot, "update", {
3066
- localMaintainerRegistry
3067
- })
3051
+ ...await getDynamicStaticEntries(projectRoot, "update")
3068
3052
  ];
3069
3053
  entries.sort(
3070
3054
  (left, right) => left.targetPath.localeCompare(right.targetPath)