Skip to content

chore: support up to Deno LTS and refine supported Deno versions logic #6670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ jobs:
fail-fast: false
matrix:
deno:
- v1.x
- v2.x
- lts
- vx.x.x
- canary
os:
- ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
[![ci](https://github.com/denoland/std/actions/workflows/ci.yml/badge.svg)](https://github.com/denoland/std/actions/workflows/ci.yml)

High-quality APIs for [Deno](https://deno.com/) and the web. Use fearlessly.
Supports up to the
[current Deno LTS version](https://docs.deno.com/runtime/fundamentals/stability_and_releases/#long-term-support-(lts)).

> [!IMPORTANT]
> Newer versions of the Standard Library are now hosted on
Expand Down
13 changes: 7 additions & 6 deletions _tools/lint_plugin_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// @ts-nocheck Deno.lint namespace does not pass type checking in Deno 1.x

import { assertEquals } from "@std/assert/equals";
import { IS_LINT_PLUGIN_SUPPORTED } from "../internal/support.ts";
import lintPlugin from "./lint_plugin.ts";

function assertLintPluginDiagnostics(
Expand All @@ -18,7 +19,7 @@ function assertLintPluginDiagnostics(
}

Deno.test("deno-style-guide/prefer-private-field", {
ignore: !Deno.version.deno.startsWith("2"),
ignore: !IS_LINT_PLUGIN_SUPPORTED,
}, () => {
// Good
assertLintPluginDiagnostics(
Expand Down Expand Up @@ -57,7 +58,7 @@ class MyClass {
});

Deno.test("deno-style-guide/no-top-level-arrow-syntax", {
ignore: !Deno.version.deno.startsWith("2"),
ignore: !IS_LINT_PLUGIN_SUPPORTED,
}, () => {
// Bad
assertLintPluginDiagnostics(
Expand Down Expand Up @@ -98,7 +99,7 @@ function foo() {
});

Deno.test("deno-style-guide/no-external-code", {
ignore: !Deno.version.deno.startsWith("2"),
ignore: !IS_LINT_PLUGIN_SUPPORTED,
}, () => {
// Good
assertLintPluginDiagnostics('import { walk } from "@std/fs/walk";', []);
Expand Down Expand Up @@ -128,7 +129,7 @@ import { bad } from "jsr:@malicious-muffin/bad";
});

Deno.test("deno-style-guide/naming-convention", {
ignore: !Deno.version.deno.startsWith("2"),
ignore: !IS_LINT_PLUGIN_SUPPORTED,
}, () => {
// Good
assertLintPluginDiagnostics(
Expand Down Expand Up @@ -243,7 +244,7 @@ enum enumName {
});

Deno.test("deno-style-guide/error-message", {
ignore: !Deno.version.deno.startsWith("2"),
ignore: !IS_LINT_PLUGIN_SUPPORTED,
}, () => {
// Good
assertLintPluginDiagnostics(
Expand Down Expand Up @@ -312,7 +313,7 @@ new CustomError("Can't parse input");
});

Deno.test("deno-style-guide/exported-function-args-maximum", {
ignore: !Deno.version.deno.startsWith("2"),
ignore: !IS_LINT_PLUGIN_SUPPORTED,
}, () => {
// Good
assertLintPluginDiagnostics(
Expand Down
2 changes: 1 addition & 1 deletion dotenv/mod_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from "@std/assert";
import { load, type LoadOptions, loadSync } from "./mod.ts";
import * as path from "@std/path";
import { IS_DENO_2 } from "../internal/_is_deno_2.ts";
import { IS_DENO_2 } from "../internal/support.ts";

const moduleDir = path.dirname(path.fromFileUrl(import.meta.url));
const testdataDir = path.resolve(moduleDir, "testdata");
Expand Down
2 changes: 1 addition & 1 deletion fs/ensure_dir_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { assertEquals, assertRejects, assertThrows } from "@std/assert";
import * as path from "@std/path";
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import { ensureFile, ensureFileSync } from "./ensure_file.ts";
import { IS_DENO_2 } from "../internal/_is_deno_2.ts";
import { IS_DENO_2 } from "../internal/support.ts";

const moduleDir = path.dirname(path.fromFileUrl(import.meta.url));
const testdataDir = path.resolve(moduleDir, "testdata", "ensure_dir");
Expand Down
2 changes: 1 addition & 1 deletion fs/ensure_file_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { assertRejects, assertThrows } from "@std/assert";
import * as path from "@std/path";
import { ensureFile, ensureFileSync } from "./ensure_file.ts";
import { IS_DENO_2 } from "../internal/_is_deno_2.ts";
import { IS_DENO_2 } from "../internal/support.ts";

const moduleDir = path.dirname(path.fromFileUrl(import.meta.url));
const testdataDir = path.resolve(moduleDir, "testdata");
Expand Down
2 changes: 1 addition & 1 deletion fs/ensure_symlink_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from "@std/assert";
import * as path from "@std/path";
import { ensureSymlink, ensureSymlinkSync } from "./ensure_symlink.ts";
import { IS_DENO_2 } from "../internal/_is_deno_2.ts";
import { IS_DENO_2 } from "../internal/support.ts";

const moduleDir = path.dirname(path.fromFileUrl(import.meta.url));
const testdataDir = path.resolve(moduleDir, "testdata");
Expand Down
2 changes: 1 addition & 1 deletion fs/expand_glob_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
type ExpandGlobOptions,
expandGlobSync,
} from "./expand_glob.ts";
import { IS_DENO_2 } from "../internal/_is_deno_2.ts";
import { IS_DENO_2 } from "../internal/support.ts";

async function expandGlobArray(
globString: string,
Expand Down
5 changes: 2 additions & 3 deletions fs/unstable_rename_test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright 2018-2025 the Deno authors. MIT license.

import { assert, assertRejects, assertThrows } from "@std/assert";
import { lessOrEqual, parse as parseSemver } from "@std/semver";
import { rename, renameSync } from "./unstable_rename.ts";
import { NotFound } from "./unstable_errors.js";
import { mkdir, mkdtemp, open, rm, stat, symlink } from "node:fs/promises";
Expand All @@ -17,11 +16,11 @@ import {
statSync,
symlinkSync,
} from "node:fs";
import { isDenoVersionGreaterOrEqual } from "../internal/support.ts";

// In Deno 2.2.2 or earlier, the `rename` function has an issue on Windows.
const RENAME_HAS_ISSUE = Deno.version &&
parseSemver(Deno.version.deno).build?.length === 0 && // not canary
lessOrEqual(parseSemver(Deno.version.deno), parseSemver("2.2.2")) &&
!isDenoVersionGreaterOrEqual("2.2.3") &&
platform() === "win32";

/** Tests if the original file/directory is missing since the file is renamed.
Expand Down
6 changes: 2 additions & 4 deletions http/file_server_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import denoConfig from "./deno.json" with { type: "json" };
import { MINUTE } from "@std/datetime/constants";
import { getAvailablePort } from "@std/net/get-available-port";
import { concat } from "@std/bytes/concat";
import { lessThan, parse as parseSemver } from "@std/semver";
import { isDenoVersionGreaterOrEqual } from "../internal/support.ts";

const moduleDir = dirname(fromFileUrl(import.meta.url));
const testdataDir = resolve(moduleDir, "testdata");
Expand All @@ -33,11 +33,9 @@ const serveDirOptions: ServeDirOptions = {
showDotfiles: true,
enableCors: true,
};
const denoVersion = parseSemver(Deno.version.deno);
const isCanary = denoVersion.build ? denoVersion.build.length > 0 : false;
// FileInfo.mode is not available on Windows before Deno 2.1.0
const fsModeUnavailable = Deno.build.os === "windows" &&
lessThan(denoVersion, parseSemver("2.1.0")) && !isCanary;
!isDenoVersionGreaterOrEqual("2.1.0");

const TEST_FILE_PATH = join(testdataDir, "test_file.txt");
const TEST_FILE_STAT = await Deno.stat(TEST_FILE_PATH);
Expand Down
3 changes: 0 additions & 3 deletions internal/_is_deno_2.ts

This file was deleted.

3 changes: 2 additions & 1 deletion internal/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"./diff": "./diff.ts",
"./format": "./format.ts",
"./styles": "./styles.ts",
"./types": "./types.ts"
"./types": "./types.ts",
"./support": "./support.ts"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

While mostly used internally, the public endpoint here is created for use by other public APIs.

Copy link
Member

Choose a reason for hiding this comment

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

Sounds like recommending other libs to use this endpoint? I'm not in favor of that policy

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It isn't. Like the other endpoints in this package, it's for internal use only. Do you suggest another name?

}
}
2 changes: 1 addition & 1 deletion internal/mod.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright 2018-2025 the Deno authors. MIT license.
// This module is browser compatible.
/**
* Internal utilities for the public API of the Deno Standard Library.
*
Expand Down Expand Up @@ -43,3 +42,4 @@ export * from "./diff_str.ts";
export * from "./format.ts";
export * from "./styles.ts";
export * from "./types.ts";
export * from "./support.ts";
41 changes: 41 additions & 0 deletions internal/support.ts
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The idea here is that when code or tests will automatically fail once the Deno LTS version is upgraded in CI. Then, we can go in and update the relevant code, dropping support for functionality that's outside of LTS.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2018-2025 the Deno authors. MIT license.
import { greaterOrEqual } from "../semver/greater_or_equal.ts";
import { parse } from "../semver/parse.ts";

/**
* Checks if the current Deno version is greater than or equal to the specified
* minimum version.
*
* @param minVersion Minimum version to check against.
* @returns `true` if the current Deno version is greater than or equal to the
* specified minimum version, `false` otherwise.
*
* @example Basic usage
* ```ts no-assert
* import { isDenoVersionGreaterOrEqual } from "@std/internal/support";
*
* if (isDenoVersionGreaterOrEqual("1.0.0")) {
* console.log("Deno version is greater than or equal to 1.0.0");
* } else {
* console.log("Deno version is less than 1.0.0");
* }
* ```
*/
export function isDenoVersionGreaterOrEqual(minVersion: string): boolean {
// deno-lint-ignore no-explicit-any
return (Deno.version as any) &&
greaterOrEqual(parse(Deno.version.deno), parse(minVersion));
}

/**
* Whether the current Deno version supports the
* {@link https://docs.deno.com/runtime/reference/lint_plugins/ | lint plugin API}.
*/
export const IS_LINT_PLUGIN_SUPPORTED: boolean = isDenoVersionGreaterOrEqual(
"2.2.0",
);

/**
* Whether the current Deno version is 2.0.0 or greater.
*/
export const IS_DENO_2: boolean = isDenoVersionGreaterOrEqual("2.0.0");
3 changes: 0 additions & 3 deletions testing/_snapshot_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,3 @@ export function getSnapshotNotMatchMessage(
`Snapshot does not match:\n${diffMsg}\nTo update snapshots, run\n deno test --allow-read --allow-write [files]... -- --update\n`;
return getErrorMessage(message, options);
}

// TODO (WWRS): Remove this when we drop support for Deno 1.x
export const LINT_SUPPORTED = !Deno.version.deno.startsWith("1.");
4 changes: 2 additions & 2 deletions testing/unstable_snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {
getIsUpdate,
getOptions,
getSnapshotNotMatchMessage,
LINT_SUPPORTED,
serialize,
} from "./_snapshot_utils.ts";
import { IS_LINT_PLUGIN_SUPPORTED } from "@std/internal/support";

/**
* The options for {@linkcode assertInlineSnapshot}.
Expand Down Expand Up @@ -95,7 +95,7 @@ const updateRequests: SnapshotUpdateRequest[] = [];
function updateSnapshots() {
if (updateRequests.length === 0) return;

if (!LINT_SUPPORTED) {
if (!IS_LINT_PLUGIN_SUPPORTED) {
throw new Error(
"Deno versions before 2.2.0 do not support Deno.lint, which is required to update inline snapshots",
);
Expand Down
6 changes: 3 additions & 3 deletions testing/unstable_snapshot_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
assertInlineSnapshot,
createAssertInlineSnapshot,
} from "./unstable_snapshot.ts";
import { LINT_SUPPORTED } from "./_snapshot_utils.ts";
import { IS_LINT_PLUGIN_SUPPORTED } from "../internal/support.ts";

const SNAPSHOT_MODULE_URL = toFileUrl(join(
dirname(fromFileUrl(import.meta.url)),
Expand Down Expand Up @@ -80,7 +80,7 @@ Deno.test("assertInlineSnapshot()", () => {
});

Deno.test("assertInlineSnapshot() formats", async () => {
if (!LINT_SUPPORTED) return;
if (!IS_LINT_PLUGIN_SUPPORTED) return;

const fileContents =
`import { assertInlineSnapshot } from "${SNAPSHOT_MODULE_URL}";
Expand Down Expand Up @@ -143,7 +143,7 @@ Deno.test("format test", async () => {
});

Deno.test("assertInlineSnapshot() counts lines and columns like V8", async () => {
if (!LINT_SUPPORTED) return;
if (!IS_LINT_PLUGIN_SUPPORTED) return;

const tempDir = await Deno.makeTempDir();
const countTestFile = join(tempDir, "count_test.ts");
Expand Down
Loading