From 1fadf6fcadfc7cd68ca6c67ad9a3cc3d5c4bdecd Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Fri, 3 Apr 2026 16:57:38 -0700 Subject: [PATCH] use --reload flag to make sure latest runtime is used when not using deno.json --- commands/dev.ts | 48 ++++++++++++++++++++++++++------- lib/runtimeVersionCheck.test.ts | 2 ++ lib/runtimeVersionCheck.ts | 11 ++++---- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/commands/dev.ts b/commands/dev.ts index 8243b1e..c126d06 100644 --- a/commands/dev.ts +++ b/commands/dev.ts @@ -29,7 +29,7 @@ import { TriggerEvent, type TriggerRegistration, } from "@streak-glue/runtime/backendTypes"; -import { type Awaitable, GLUE_API_SERVER } from "../common.ts"; +import { type Awaitable, GLUE_API_SERVER, GLUE_RUNTIME_PACKAGE } from "../common.ts"; import { equal } from "@std/assert/equal"; import { delay } from "@std/async/delay"; import { keypress, type KeyPressEvent } from "@cliffy/keypress"; @@ -41,6 +41,7 @@ import { getGlueName } from "../lib/glueNaming.ts"; import { getOutdatedStreakRuntimeVersion } from "../lib/runtimeVersionCheck.ts"; import { once } from "node:events"; import type { CommonCommandOptions } from "./common.ts"; +import { findDenoConfigPaths } from "../lib/denoConfig.ts"; const GLUE_DEV_PORT = getAvailablePort({ preferredPort: 8001 }); const DEFAULT_DEBUG_PORT = 9229; @@ -75,7 +76,7 @@ export async function dev(options: DevOptions, filename: string) { const lifelineReconnectionEvents = pushableV({ objectMode: true }); const glueName = await getGlueName(filename, options.name); - await warnIfStreakRuntimeIsOutdated(filename, options.verbose); + const reloadStreakRuntime = await streakRuntimeUpdateChecks(filename, options.verbose); const glueCliWebsocketAddr = await wsListen(() => { if (!lifelineHasConnected) { @@ -112,7 +113,13 @@ export async function dev(options: DevOptions, filename: string) { } await runUIStep("bootingCode", async () => { - const c = spawnLocalGlueProcess(filename, env, debugMode, abortController); + const c = spawnLocalGlueProcess( + filename, + env, + debugMode, + abortController, + reloadStreakRuntime, + ); const unsub = new AbortController(); try { @@ -511,19 +518,38 @@ function analyzeCode(_filename: string): AnalysisResult { return { errors: [] }; } -async function warnIfStreakRuntimeIsOutdated(filename: string, verbose: boolean): Promise { +/** + * @returns true if the glue process should be started with the `--reload` flag + * to ensure the latest version of the streak runtime is used, false otherwise. + */ +async function streakRuntimeUpdateChecks(filename: string, verbose: boolean): Promise { try { - const outdatedRuntime = await getOutdatedStreakRuntimeVersion(filename); - if (!outdatedRuntime) { - return; + const denoConfigPaths = await findDenoConfigPaths(path.dirname(filename)); + if (!denoConfigPaths.denoJsonPath) { + // When not using deno.json/deno.lock, we want to make sure unversioned + // imports for "jsr:@streak-glue/runtime" get the latest version. We could + // issue some Deno command to update the cache with the latest version + // before we run the user's glue, but instead we'll just pass "--reload" + // to the user's glue Deno process. + return true; + } else { + // When using deno.json+deno.lock, check if the @streak-glue/runtime + // version is outdated and warn the user if so. + const outdatedRuntime = await getOutdatedStreakRuntimeVersion(filename, denoConfigPaths); + if (!outdatedRuntime) { + return false; + } + devProgressProps.outdatedRuntimeWarningInfo = outdatedRuntime; + renderUI(); + return false; } - devProgressProps.outdatedRuntimeWarningInfo = outdatedRuntime; - renderUI(); } catch (e) { if (verbose) { console.error("Caught error:", e); } } + + return false; } async function discoverRegistrations(signal?: AbortSignal): Promise { @@ -546,6 +572,7 @@ function spawnLocalGlueProcess( env: Record, debugMode: DebugMode, abortController: AbortController, + reloadStreakRuntime: boolean, ) { abortController.signal.throwIfAborted(); @@ -562,6 +589,9 @@ function spawnLocalGlueProcess( if (debugMode !== "no-debug") { flags.push("--" + debugMode); } + if (reloadStreakRuntime) { + flags.push(`--reload=jsr:${GLUE_RUNTIME_PACKAGE}`); + } const command = new Deno.Command(Deno.execPath(), { args: [ diff --git a/lib/runtimeVersionCheck.test.ts b/lib/runtimeVersionCheck.test.ts index 14c7315..33869e8 100644 --- a/lib/runtimeVersionCheck.test.ts +++ b/lib/runtimeVersionCheck.test.ts @@ -66,8 +66,10 @@ Deno.test("getOutdatedStreakRuntimeVersion returns latest mismatch and formats w }, }), ); + const denoConfigPaths = await findDenoConfigPaths(sourceDir); const outdatedInfo = await getOutdatedStreakRuntimeVersion( filename, + denoConfigPaths, () => Promise.resolve( new Response(JSON.stringify({ scope: "@streak-glue", name: "runtime", latest: "0.2.33" }), { diff --git a/lib/runtimeVersionCheck.ts b/lib/runtimeVersionCheck.ts index a7c8f32..93652b8 100644 --- a/lib/runtimeVersionCheck.ts +++ b/lib/runtimeVersionCheck.ts @@ -1,6 +1,5 @@ -import * as path from "@std/path"; import z from "zod"; -import { findDenoConfigPaths } from "./denoConfig.ts"; +import type { DenoConfigPaths } from "./denoConfig.ts"; import { GLUE_RUNTIME_PACKAGE } from "../common.ts"; const GLUE_RUNTIME_JSR_SPECIFIER = `jsr:${GLUE_RUNTIME_PACKAGE}`; @@ -12,15 +11,15 @@ export interface OutdatedRuntimeInfo { } export async function getOutdatedStreakRuntimeVersion( - filename: string, + _filename: string, + denoConfigPaths: DenoConfigPaths, fetchImpl: typeof fetch = fetch, ): Promise { - const { denoLockPath } = await findDenoConfigPaths(path.dirname(filename)); - if (!denoLockPath) { + if (!denoConfigPaths.denoLockPath) { return undefined; } const currentVersion = extractStreakRuntimeVersionFromDenoLockText( - await Deno.readTextFile(denoLockPath), + await Deno.readTextFile(denoConfigPaths.denoLockPath), ); if (!currentVersion) { return undefined;