Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 39 additions & 9 deletions commands/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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;
Expand Down Expand Up @@ -75,7 +76,7 @@ export async function dev(options: DevOptions, filename: string) {
const lifelineReconnectionEvents = pushableV<void>({ 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) {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -511,19 +518,38 @@ function analyzeCode(_filename: string): AnalysisResult {
return { errors: [] };
}

async function warnIfStreakRuntimeIsOutdated(filename: string, verbose: boolean): Promise<void> {
/**
* @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<boolean> {
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<Registrations> {
Expand All @@ -546,6 +572,7 @@ function spawnLocalGlueProcess(
env: Record<string, string>,
debugMode: DebugMode,
abortController: AbortController,
reloadStreakRuntime: boolean,
) {
abortController.signal.throwIfAborted();

Expand All @@ -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: [
Expand Down
2 changes: 2 additions & 0 deletions lib/runtimeVersionCheck.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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" }), {
Expand Down
11 changes: 5 additions & 6 deletions lib/runtimeVersionCheck.ts
Original file line number Diff line number Diff line change
@@ -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}`;
Expand All @@ -12,15 +11,15 @@ export interface OutdatedRuntimeInfo {
}

export async function getOutdatedStreakRuntimeVersion(
filename: string,
_filename: string,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The _filename parameter is no longer used within getOutdatedStreakRuntimeVersion because the configuration paths are now passed directly via the denoConfigPaths argument. Removing this unused parameter would simplify the function's signature. Note that call sites in commands/dev.ts and lib/runtimeVersionCheck.test.ts would also need to be updated to reflect this change.

denoConfigPaths: DenoConfigPaths,
fetchImpl: typeof fetch = fetch,
): Promise<OutdatedRuntimeInfo | undefined> {
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;
Expand Down