| … | … | @@ -66,6 +66,20 @@ export function defaultRuntimePath (store, name, { execPath } = {}) { |
| 66 | 66 | return resolveBundledRuntime(installPath, 'bare', detectHost(), execPath ? { execPath } : {}) |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | /** |
| 70 | * The materializer for a runtime kind, as the RELEASE declares it. |
| 71 | * |
| 72 | * Exported because it is the whole of the selection logic and the only part of |
| 73 | * createRuntime worth testing without a network: given a kind, which layout. |
| 74 | * |
| 75 | * Throwing on an unknown kind is deliberate. The alternative — defaulting to the |
| 76 | * npm layout — would materialize a godot app as if it were a node one and produce |
| 77 | * an install that exists, passes every "did it install" check, and does not run. |
| 78 | */ |
| 79 | export function selectMaterializer (runtimeKind) { |
| 80 | return loadMaterializer(runtimeKind || 'node').materialize |
| 81 | } |
| 82 | |
| 69 | 83 | // Select the materializer for a runtime — node/bare share the npm layout; |
| 70 | 84 | // godot uses its own. Parity with app.js loadMaterializer (the live path). |
| 71 | 85 | function loadMaterializer (runtime) { |
| … | … | @@ -235,6 +249,8 @@ export async function installComplete ({ store, release, fetcher, name, host, bi |
| 235 | 249 | * |
| 236 | 250 | * @param {object} opts |
| 237 | 251 | * @param {string} opts.name app name |
| 252 | * @param {string} [opts.runtime] override the materializer kind; default |
| 253 | * is the RELEASE's own `runtime` field |
| 238 | 254 | * @param {string} [opts.registryKeyHex] publisher registry key (the hex in |
| 239 | 255 | * pgh.upgrade). WITH it, resolution works |
| 240 | 256 | * without a sidecar — see resolve-release.js. |
| … | … | @@ -296,7 +312,19 @@ export async function createRuntime (opts = {}) { |
| 296 | 312 | host, |
| 297 | 313 | interval: opts.interval, |
| 298 | 314 | currentTreeHash: opts.currentTreeHash, |
| 299 | | materialize: atomicMaterializer({ materialize: nodeMaterialize }) |
| 315 | // FOLLOWS THE RELEASE, not the caller and not a constant. This was |
| 316 | // hardcoded to nodeMaterialize, which is correct for every node/bare app — |
| 317 | // hyper-tps declares runtime 'bare' — and silently wrong for a godot one, |
| 318 | // where it would produce an install that looks complete and does not run. |
| 319 | // The live entries carry `runtime` (verified against the registry: hyper-tps |
| 320 | // resolves with runtime:"bare"), even though release-registry.js's schema |
| 321 | // comment predates the field and does not list it. |
| 322 | // |
| 323 | // Resolved ONCE, from the release we started against. An app that changes |
| 324 | // runtime kind mid-life is a re-install, not an update. |
| 325 | materialize: atomicMaterializer({ |
| 326 | materialize: selectMaterializer(opts.runtime || latest.runtime) |
| 327 | }) |
| 300 | 328 | }) |
| 301 | 329 | |
| 302 | 330 | // Finalize (launcher + manifest) after every install/update, then hand off |