diff --git a/.github/dependency_graph.svg b/.github/dependency_graph.svg index db3b31678ced..e59f1001de4f 100644 --- a/.github/dependency_graph.svg +++ b/.github/dependency_graph.svg @@ -4,11 +4,11 @@ - + std_deps - + assert @@ -30,50 +30,50 @@ async - -async + +async bytes - -bytes + +bytes cache - -cache + +cache cbor - -cbor + +cbor cbor->bytes - - + + streams - -streams + +streams cbor->streams - - + + - + streams->bytes - - + + @@ -84,45 +84,45 @@ collections - -collections + +collections crypto - -crypto + +crypto csv - -csv + +csv csv->streams - - + + data-\nstructures - -data- -structures + +data- +structures datetime - -datetime + +datetime dotenv - -dotenv + +dotenv @@ -151,238 +151,244 @@ fmt - -fmt + +fmt front-\nmatter - -front- -matter + +front- +matter toml - -toml + +toml front-\nmatter->toml - - + + yaml - -yaml + +yaml front-\nmatter->yaml - - + + - + toml->collections - - + + fs - -fs + +fs path - -path + +path fs->path - - + + html - -html + +html http - -http + +http http->streams - - + + http->cli - - + + http->encoding - - + + http->fmt - - + + http->path - - + + + + + +http->html + + media-\ntypes - -media- -types + +media- +types http->media-\ntypes - - + + net - -net + +net http->net - - + + ini - -ini + +ini io - -io + +io - + io->bytes - - + + json - -json + +json - + json->streams - - + + jsonc - -jsonc + +jsonc - + jsonc->json - - + + log - -log + +log - + log->fmt - - + + - + log->fs - - + + - + log->io - - + + msgpack - -msgpack + +msgpack - + msgpack->bytes - - + + random - -random + +random regexp - -regexp + +regexp semver - -semver + +semver tar - -tar + +tar - + tar->streams - - + + @@ -391,76 +397,76 @@ testing - + testing->assert - - + + - + testing->internal - - + + - + testing->async - - + + - + testing->data-\nstructures - - + + - + testing->fs - - + + - + testing->path - - + + text - -text + +text ulid - -ulid + +ulid uuid - -uuid + +uuid - + uuid->bytes - - + + - + uuid->crypto - - + + webgpu - -webgpu + +webgpu diff --git a/Releases.md b/Releases.md index 816a843a23a5..54e3a1256b98 100644 --- a/Releases.md +++ b/Releases.md @@ -1,3 +1,68 @@ +### 2025.01.31 + +#### @std/bytes 1.0.5 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/cli 1.0.12 (patch) + +- feat(cli/unstable): support stderr on spinner (#6350) + +#### @std/crypto 1.0.4 (patch) + +- docs(crypto): clarify doc comment (#6368) +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/encoding 1.0.7 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/expect 1.0.13 (patch) + +- test(expect): check error message of `.toBeCloseTo()` (#6296) + +#### @std/fmt 1.0.5 (patch) + +- fix(fmt): make printf working with colors. (#6360) + +#### @std/fs 1.0.11 (patch) + +- feat(fs/unstable): add readLink and readLinkSync (#6373) +- feat(fs/unstable): add link and linkSync (#6369) +- feat(fs/unstable): add realPath and realPathSync (#6366) + +#### @std/http 1.0.13 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/io 0.225.2 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/log 0.224.14 (patch) + +- docs(log): mention potential deprecation of @std/log (#6364) + +#### @std/msgpack 1.0.3 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/streams 1.0.9 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/tar 0.1.5 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + ### 2025.01.22 #### @std/assert 1.0.11 (patch) diff --git a/_tools/node_test_runner/run_test.mjs b/_tools/node_test_runner/run_test.mjs index cd1cb999ff43..79b10428d9f1 100644 --- a/_tools/node_test_runner/run_test.mjs +++ b/_tools/node_test_runner/run_test.mjs @@ -49,7 +49,10 @@ import "../../collections/union_test.ts"; import "../../collections/unzip_test.ts"; import "../../collections/without_all_test.ts"; import "../../collections/zip_test.ts"; +import "../../fs/unstable_link_test.ts"; import "../../fs/unstable_read_dir_test.ts"; +import "../../fs/unstable_read_link_test.ts"; +import "../../fs/unstable_real_path_test.ts"; import "../../fs/unstable_stat_test.ts"; import "../../fs/unstable_symlink_test.ts"; import "../../fs/unstable_lstat_test.ts"; diff --git a/bytes/_types.ts b/bytes/_types.ts new file mode 100644 index 000000000000..340b2fcce9d6 --- /dev/null +++ b/bytes/_types.ts @@ -0,0 +1,11 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +/** + * Proxy type of {@code Uint8Array; diff --git a/bytes/concat.ts b/bytes/concat.ts index 5031cfbcdf02..5ee31f2ea002 100644 --- a/bytes/concat.ts +++ b/bytes/concat.ts @@ -1,6 +1,9 @@ // Copyright 2018-2025 the Deno authors. MIT license. // This module is browser compatible. +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; + /** * Concatenate an array of byte slices into a single slice. * @@ -18,7 +21,7 @@ * assertEquals(concat([a, b]), new Uint8Array([0, 1, 2, 3, 4, 5])); * ``` */ -export function concat(buffers: Uint8Array[]): Uint8Array { +export function concat(buffers: Uint8Array[]): Uint8Array_ { let length = 0; for (const buffer of buffers) { length += buffer.length; diff --git a/bytes/deno.json b/bytes/deno.json index 618e91e63b41..2e927e8f9f5b 100644 --- a/bytes/deno.json +++ b/bytes/deno.json @@ -1,6 +1,6 @@ { "name": "@std/bytes", - "version": "1.0.4", + "version": "1.0.5", "exports": { ".": "./mod.ts", "./concat": "./concat.ts", diff --git a/bytes/repeat.ts b/bytes/repeat.ts index 6a13e4c511b2..b15d45af59f7 100644 --- a/bytes/repeat.ts +++ b/bytes/repeat.ts @@ -1,6 +1,8 @@ // Copyright 2018-2025 the Deno authors. MIT license. // This module is browser compatible. import { copy } from "./copy.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Returns a new byte slice composed of `count` repetitions of the `source` @@ -31,7 +33,7 @@ import { copy } from "./copy.ts"; * assertEquals(repeat(source, 0), new Uint8Array()); * ``` */ -export function repeat(source: Uint8Array, count: number): Uint8Array { +export function repeat(source: Uint8Array, count: number): Uint8Array_ { if (count < 0 || !Number.isInteger(count)) { throw new RangeError("Count must be a non-negative integer"); } diff --git a/cli/deno.json b/cli/deno.json index 569a90771550..aaab86bc67f4 100644 --- a/cli/deno.json +++ b/cli/deno.json @@ -1,6 +1,6 @@ { "name": "@std/cli", - "version": "1.0.11", + "version": "1.0.12", "exports": { ".": "./mod.ts", "./parse-args": "./parse_args.ts", diff --git a/crypto/crypto.ts b/crypto/crypto.ts index 626195006a6e..14ff82cd3c4d 100644 --- a/crypto/crypto.ts +++ b/crypto/crypto.ts @@ -188,8 +188,8 @@ export interface StdCrypto extends Crypto { } /** - * An wrapper for WebCrypto adding support for additional non-standard - * algorithms, but delegating to the runtime WebCrypto implementation whenever + * A wrapper for WebCrypto which adds support for additional non-standard + * algorithms, but delegates to the runtime WebCrypto implementation whenever * possible. */ const stdCrypto: StdCrypto = ((x) => x)({ @@ -241,7 +241,7 @@ const stdCrypto: StdCrypto = ((x) => x)({ } context.update(chunkBytes); } - return context.digestAndDrop(length).buffer; + return context.digestAndDrop(length).buffer as ArrayBuffer; } else { throw new TypeError( "data must be a BufferSource or [Async]Iterable", @@ -265,7 +265,7 @@ const stdCrypto: StdCrypto = ((x) => x)({ const wasmCrypto = instantiateWasm(); if (isBufferSource(data)) { const bytes = toUint8Array(data)!; - return wasmCrypto.digest(name, bytes, length).buffer; + return wasmCrypto.digest(name, bytes, length).buffer as ArrayBuffer; } if (isIterable(data)) { const context = new wasmCrypto.DigestContext(name); @@ -278,7 +278,7 @@ const stdCrypto: StdCrypto = ((x) => x)({ } context.update(chunkBytes); } - return context.digestAndDrop(length).buffer; + return context.digestAndDrop(length).buffer as ArrayBuffer; } throw new TypeError( "data must be a BufferSource or Iterable", diff --git a/crypto/deno.json b/crypto/deno.json index b38a0b6eee9a..b43c2d28d638 100644 --- a/crypto/deno.json +++ b/crypto/deno.json @@ -1,6 +1,6 @@ { "name": "@std/crypto", - "version": "1.0.3", + "version": "1.0.4", "exports": { ".": "./mod.ts", "./crypto": "./crypto.ts", diff --git a/encoding/_base32_common.ts b/encoding/_base32_common.ts index f567bedf60a5..8d3cd6cdda97 100644 --- a/encoding/_base32_common.ts +++ b/encoding/_base32_common.ts @@ -7,6 +7,7 @@ */ import { validateBinaryLike } from "./_validate_binary_like.ts"; +import type { Uint8Array_ } from "./_types.ts"; const placeHolderPadLookup = [0, 1, , 2, 3, , 4]; @@ -46,7 +47,10 @@ function getByteLength(validLen: number, placeHoldersLen: number): number { * @param lookup The lookup table * @returns The encoded string. */ -export function decode(b32: string, lookup: ReadonlyArray): Uint8Array { +export function decode( + b32: string, + lookup: ReadonlyArray, +): Uint8Array_ { const revLookup: number[] = []; lookup.forEach((c, i) => (revLookup[c.charCodeAt(0)] = i)); diff --git a/encoding/_types.ts b/encoding/_types.ts new file mode 100644 index 000000000000..340b2fcce9d6 --- /dev/null +++ b/encoding/_types.ts @@ -0,0 +1,11 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +/** + * Proxy type of {@code Uint8Array; diff --git a/encoding/ascii85.ts b/encoding/ascii85.ts index ef8fa702e718..043ac92f670f 100644 --- a/encoding/ascii85.ts +++ b/encoding/ascii85.ts @@ -1,6 +1,9 @@ // Copyright 2018-2025 the Deno authors. MIT license. // This module is browser compatible. +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; + /** * Utilities for working with {@link https://en.wikipedia.org/wiki/Ascii85 | ascii85} encoding. * @@ -156,7 +159,7 @@ export type DecodeAscii85Options = Omit; export function decodeAscii85( ascii85: string, options: DecodeAscii85Options = {}, -): Uint8Array { +): Uint8Array_ { const { standard = "Adobe" } = options; // translate all encodings to most basic adobe/btoa one and decompress some special characters ("z" and "y") diff --git a/encoding/base32.ts b/encoding/base32.ts index dac3c15de8c2..2f3ac4431efc 100644 --- a/encoding/base32.ts +++ b/encoding/base32.ts @@ -2,6 +2,9 @@ // Copyright (c) 2014 Jameson Little. MIT License. // This module is browser compatible. +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; + /** * Utilities for * {@link https://www.rfc-editor.org/rfc/rfc4648.html#section-6 | base32} @@ -48,7 +51,7 @@ lookup.forEach((c, i) => (revLookup[c.charCodeAt(0)] = i)); * ); * ``` */ -export function decodeBase32(b32: string): Uint8Array { +export function decodeBase32(b32: string): Uint8Array_ { return decode(b32, lookup); } diff --git a/encoding/base58.ts b/encoding/base58.ts index 06194e07e585..42c346e79ad9 100644 --- a/encoding/base58.ts +++ b/encoding/base58.ts @@ -21,6 +21,8 @@ */ import { validateBinaryLike } from "./_validate_binary_like.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; // deno-fmt-ignore const mapBase58: Record = { @@ -120,7 +122,7 @@ export function encodeBase58(data: ArrayBuffer | Uint8Array | string): string { * ); * ``` */ -export function decodeBase58(b58: string): Uint8Array { +export function decodeBase58(b58: string): Uint8Array_ { const splitInput = b58.trim().split(""); let length = 0; diff --git a/encoding/base58_test.ts b/encoding/base58_test.ts index 82e3e55c0a6f..a4ecdb92e1d1 100644 --- a/encoding/base58_test.ts +++ b/encoding/base58_test.ts @@ -53,7 +53,7 @@ Deno.test("encodeBase58() encodes binary", () => { Deno.test("encodeBase58() encodes binary buffer", () => { for (const [input, output] of testSetBinary) { - assertEquals(encodeBase58(input.buffer), output); + assertEquals(encodeBase58(input.buffer as ArrayBuffer), output); } }); diff --git a/encoding/base64.ts b/encoding/base64.ts index f791a29c5696..a0fd36f23725 100644 --- a/encoding/base64.ts +++ b/encoding/base64.ts @@ -23,6 +23,8 @@ */ import { validateBinaryLike } from "./_validate_binary_like.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; const base64abc = [ "A", @@ -163,7 +165,7 @@ export function encodeBase64(data: ArrayBuffer | Uint8Array | string): string { * ); * ``` */ -export function decodeBase64(b64: string): Uint8Array { +export function decodeBase64(b64: string): Uint8Array_ { const binString = atob(b64); const size = binString.length; const bytes = new Uint8Array(size); diff --git a/encoding/base64_test.ts b/encoding/base64_test.ts index 09345d34f5ac..26581c508e17 100644 --- a/encoding/base64_test.ts +++ b/encoding/base64_test.ts @@ -33,7 +33,7 @@ Deno.test("encodeBase64() encodes binary", () => { Deno.test("encodeBase64() encodes binary buffer", () => { for (const [input, output] of testsetBinary) { - assertEquals(encodeBase64(input.buffer), output); + assertEquals(encodeBase64(input.buffer as ArrayBuffer), output); } }); diff --git a/encoding/base64url.ts b/encoding/base64url.ts index 3485ab23091c..460c8d405dc9 100644 --- a/encoding/base64url.ts +++ b/encoding/base64url.ts @@ -10,6 +10,8 @@ */ import * as base64 from "./base64.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Some variants allow or require omitting the padding '=' signs: @@ -83,6 +85,6 @@ export function encodeBase64Url( * ); * ``` */ -export function decodeBase64Url(b64url: string): Uint8Array { +export function decodeBase64Url(b64url: string): Uint8Array_ { return base64.decodeBase64(convertBase64urlToBase64(b64url)); } diff --git a/encoding/deno.json b/encoding/deno.json index 016f8a3f47ee..cb1870a3bfae 100644 --- a/encoding/deno.json +++ b/encoding/deno.json @@ -1,6 +1,6 @@ { "name": "@std/encoding", - "version": "1.0.6", + "version": "1.0.7", "exports": { ".": "./mod.ts", "./ascii85": "./ascii85.ts", diff --git a/encoding/hex.ts b/encoding/hex.ts index 442111f58366..7efe6e42935f 100644 --- a/encoding/hex.ts +++ b/encoding/hex.ts @@ -27,6 +27,8 @@ */ import { validateBinaryLike } from "./_validate_binary_like.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; const hexTable = new TextEncoder().encode("0123456789abcdef"); const textEncoder = new TextEncoder(); @@ -100,7 +102,7 @@ export function encodeHex(src: string | Uint8Array | ArrayBuffer): string { * ); * ``` */ -export function decodeHex(src: string): Uint8Array { +export function decodeHex(src: string): Uint8Array_ { const u8 = textEncoder.encode(src); const dst = new Uint8Array(u8.length / 2); for (let i = 0; i < dst.length; i++) { diff --git a/encoding/unstable_base32_stream.ts b/encoding/unstable_base32_stream.ts index 1f14a0dd3a9e..ebe169924fbb 100644 --- a/encoding/unstable_base32_stream.ts +++ b/encoding/unstable_base32_stream.ts @@ -22,6 +22,8 @@ */ import { decodeBase32, encodeBase32 } from "./base32.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Converts a Uint8Array stream into a base32-encoded stream. @@ -88,7 +90,7 @@ export class Base32EncoderStream extends TransformStream { * assertEquals(await toText(stream), "Hello World!"); * ``` */ -export class Base32DecoderStream extends TransformStream { +export class Base32DecoderStream extends TransformStream { constructor() { let push = ""; super({ diff --git a/encoding/unstable_base32crockford.ts b/encoding/unstable_base32crockford.ts index 0f8b69a55b59..07cd17a9614c 100644 --- a/encoding/unstable_base32crockford.ts +++ b/encoding/unstable_base32crockford.ts @@ -24,6 +24,8 @@ * @module */ import { decode, encode } from "./_base32_common.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; const lookup: string[] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ".split(""); const revLookup: number[] = []; @@ -48,7 +50,7 @@ lookup.forEach((c, i) => (revLookup[c.charCodeAt(0)] = i)); * ); * ``` */ -export function decodeBase32Crockford(b32: string): Uint8Array { +export function decodeBase32Crockford(b32: string): Uint8Array_ { return decode(b32, lookup); } diff --git a/encoding/unstable_base32hex.ts b/encoding/unstable_base32hex.ts index 91622f31e7a5..9a4b3c6d2c12 100644 --- a/encoding/unstable_base32hex.ts +++ b/encoding/unstable_base32hex.ts @@ -28,6 +28,8 @@ * @module */ import { decode, encode } from "./_base32_common.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; const lookup: string[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV".split(""); const revLookup: number[] = []; @@ -54,7 +56,7 @@ lookup.forEach((c, i) => revLookup[c.charCodeAt(0)] = i); * ); * ``` */ -export function decodeBase32Hex(b32: string): Uint8Array { +export function decodeBase32Hex(b32: string): Uint8Array_ { return decode(b32, lookup); } diff --git a/encoding/unstable_base32hex_stream.ts b/encoding/unstable_base32hex_stream.ts index 9862d464b504..735281272900 100644 --- a/encoding/unstable_base32hex_stream.ts +++ b/encoding/unstable_base32hex_stream.ts @@ -22,6 +22,8 @@ */ import { decodeBase32Hex, encodeBase32Hex } from "./unstable_base32hex.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Converts a Uint8Array stream into a base32hex-encoded stream. @@ -90,7 +92,7 @@ export class Base32HexEncoderStream * ``` */ export class Base32HexDecoderStream - extends TransformStream { + extends TransformStream { constructor() { let push = ""; super({ diff --git a/encoding/unstable_base64_stream.ts b/encoding/unstable_base64_stream.ts index 2dc5232877e4..a2aa70db8c28 100644 --- a/encoding/unstable_base64_stream.ts +++ b/encoding/unstable_base64_stream.ts @@ -22,6 +22,8 @@ */ import { decodeBase64, encodeBase64 } from "./base64.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Converts a Uint8Array stream into a base64-encoded stream. @@ -88,7 +90,7 @@ export class Base64EncoderStream extends TransformStream { * assertEquals(await toText(stream), "Hello, world!"); * ``` */ -export class Base64DecoderStream extends TransformStream { +export class Base64DecoderStream extends TransformStream { constructor() { let push = ""; super({ diff --git a/encoding/unstable_base64url_stream.ts b/encoding/unstable_base64url_stream.ts index ee940ca15c00..53d67245dd73 100644 --- a/encoding/unstable_base64url_stream.ts +++ b/encoding/unstable_base64url_stream.ts @@ -22,6 +22,8 @@ */ import { decodeBase64Url, encodeBase64Url } from "./base64url.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Converts a Uint8Array stream into a base64url-encoded stream. @@ -91,7 +93,7 @@ export class Base64UrlEncoderStream * ``` */ export class Base64UrlDecoderStream - extends TransformStream { + extends TransformStream { constructor() { let push = ""; super({ diff --git a/encoding/unstable_hex_stream.ts b/encoding/unstable_hex_stream.ts index afb85869d195..7c17b8fd10ec 100644 --- a/encoding/unstable_hex_stream.ts +++ b/encoding/unstable_hex_stream.ts @@ -22,6 +22,8 @@ */ import { decodeHex, encodeHex } from "./hex.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Converts a Uint8Array stream into a hex-encoded stream. @@ -74,7 +76,7 @@ export class HexEncoderStream extends TransformStream { * assertEquals(await toText(stream), "Hello, world!"); * ``` */ -export class HexDecoderStream extends TransformStream { +export class HexDecoderStream extends TransformStream { constructor() { let push = ""; super({ diff --git a/encoding/varint.ts b/encoding/varint.ts index ebf7f00c8dcd..c20f1242c80c 100644 --- a/encoding/varint.ts +++ b/encoding/varint.ts @@ -28,6 +28,9 @@ // This implementation is a port of https://deno.land/x/varint@v2.0.0 by @keithamus // This module is browser compatible. +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; + /** * The maximum value of an unsigned 64-bit integer. * Equivalent to `2n**64n - 1n` @@ -216,7 +219,7 @@ export function encodeVarint( num: bigint | number, buf: Uint8Array = new Uint8Array(MaxVarintLen64), offset = 0, -): [Uint8Array, number] { +): [Uint8Array_, number] { num = BigInt(num); if (num < 0n) { throw new RangeError( diff --git a/expect/deno.json b/expect/deno.json index 91137260ab12..b64670473e2e 100644 --- a/expect/deno.json +++ b/expect/deno.json @@ -1,6 +1,6 @@ { "name": "@std/expect", - "version": "1.0.12", + "version": "1.0.13", "exports": { ".": "./mod.ts", "./expect": "./expect.ts", diff --git a/fmt/deno.json b/fmt/deno.json index 41d40b01f525..4256ebede623 100644 --- a/fmt/deno.json +++ b/fmt/deno.json @@ -1,6 +1,6 @@ { "name": "@std/fmt", - "version": "1.0.4", + "version": "1.0.5", "exports": { "./bytes": "./bytes.ts", "./colors": "./colors.ts", diff --git a/fmt/printf.ts b/fmt/printf.ts index 99c767c5b49b..d07a7384baec 100644 --- a/fmt/printf.ts +++ b/fmt/printf.ts @@ -1,5 +1,7 @@ // Copyright 2018-2025 the Deno authors. MIT license. +import { stripAnsiCode } from "./colors.ts"; + /** * {@linkcode sprintf} and {@linkcode printf} for printing formatted strings to * stdout. @@ -389,6 +391,7 @@ class Printf { this.state = State.PERCENT; return; } + flags.width = flags.width === -1 ? 0 : flags.width; flags.width *= 10; flags.width += val; @@ -862,6 +865,10 @@ class Printf { if (this.flags.precision !== -1) { s = s.slice(0, this.flags.precision); } + const sac = stripAnsiCode(s); + if (sac.length !== s.length) { + this.flags.width += s.length - sac.length; + } return this.pad(s); } diff --git a/fmt/printf_test.ts b/fmt/printf_test.ts index 8d56275d6ef4..74ed85d8b1e3 100644 --- a/fmt/printf_test.ts +++ b/fmt/printf_test.ts @@ -8,6 +8,7 @@ import { printf, sprintf } from "./printf.ts"; import { assertEquals, assertThrows } from "@std/assert"; import { assertSpyCall, spy } from "@std/testing/mock"; +import * as c from "./colors.ts"; Deno.test("sprintf() handles noVerb", function () { assertEquals(sprintf("bla"), "bla"); @@ -169,6 +170,54 @@ Deno.test("sprintf() handles string", function () { assertEquals(sprintf("%s World%s", "Hello", "!"), "Hello World!"); }); +Deno.test("printf() handles string with colors", () => { + assertEquals(sprintf("%4s", c.bold("foo")), " foo"); + assertEquals(sprintf("%4s", c.dim("foo")), " foo"); + assertEquals(sprintf("%4s", c.italic("foo")), " foo"); + assertEquals(sprintf("%4s", c.underline("foo")), " foo"); + assertEquals(sprintf("%4s", c.inverse("foo")), " foo"); + assertEquals(sprintf("%4s", c.hidden("foo")), " foo"); + assertEquals(sprintf("%4s", c.strikethrough("foo")), " foo"); + + assertEquals(sprintf("%4s", c.black("foo")), " foo"); + assertEquals(sprintf("%4s", c.red("foo")), " foo"); + assertEquals(sprintf("%4s", c.green("foo")), " foo"); + assertEquals(sprintf("%4s", c.yellow("foo")), " foo"); + assertEquals(sprintf("%4s", c.blue("foo")), " foo"); + assertEquals(sprintf("%4s", c.magenta("foo")), " foo"); + assertEquals(sprintf("%4s", c.cyan("foo")), " foo"); + assertEquals(sprintf("%4s", c.white("foo")), " foo"); + assertEquals(sprintf("%4s", c.gray("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightBlack("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightRed("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightGreen("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightYellow("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightBlue("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightMagenta("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightCyan("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightWhite("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBlack("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgRed("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgGreen("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgYellow("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBlue("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgMagenta("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgCyan("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgWhite("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightBlack("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightRed("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightGreen("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightYellow("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightBlue("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightMagenta("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightCyan("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightWhite("foo")), " foo"); + assertEquals(sprintf("%4s", c.rgb8("foo", -10)), " foo"); + assertEquals(sprintf("%4s", c.rgb8("foo", 42.5)), " foo"); + assertEquals(sprintf("%4s", c.rgb8("foo", 42)), " foo"); + assertEquals(sprintf("%4s", c.bgRgb8("foo", 42)), " foo"); +}); + Deno.test("sprintf() handles hex", function () { assertEquals(sprintf("%x", "123"), "313233"); assertEquals(sprintf("%x", "n"), "6e"); diff --git a/fs/deno.json b/fs/deno.json index 26fe767ec40f..e9fa16175f4b 100644 --- a/fs/deno.json +++ b/fs/deno.json @@ -1,6 +1,6 @@ { "name": "@std/fs", - "version": "1.0.10", + "version": "1.0.11", "exports": { ".": "./mod.ts", "./copy": "./copy.ts", @@ -14,8 +14,11 @@ "./expand-glob": "./expand_glob.ts", "./move": "./move.ts", "./unstable-chmod": "./unstable_chmod.ts", + "./unstable-link": "./unstable_link.ts", "./unstable-lstat": "./unstable_lstat.ts", "./unstable-read-dir": "./unstable_read_dir.ts", + "./unstable-read-link": "./unstable_read_link.ts", + "./unstable-real-path": "./unstable_real_path.ts", "./unstable-stat": "./unstable_stat.ts", "./unstable-symlink": "./unstable_symlink.ts", "./unstable-types": "./unstable_types.ts", diff --git a/fs/unstable_link.ts b/fs/unstable_link.ts new file mode 100644 index 000000000000..d9e599a2726d --- /dev/null +++ b/fs/unstable_link.ts @@ -0,0 +1,60 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +import { getNodeFs, isDeno } from "./_utils.ts"; +import { mapError } from "./_map_error.ts"; + +/** + * Creates `newpath` as a hard link to `oldpath`. + * + * Requires `allow-read` and `allow-write` permissions. + * + * @example Usage + * ```ts ignore + * import { link } from "@std/fs/unstable-link"; + * await link("old/name", "new/name"); + * ``` + * + * @tags allow-read, allow-write + * + * @param oldpath The path of the resource pointed by the hard link. + * @param newpath The path of the hard link. + */ +export async function link(oldpath: string, newpath: string): Promise { + if (isDeno) { + await Deno.link(oldpath, newpath); + } else { + try { + await getNodeFs().promises.link(oldpath, newpath); + } catch (error) { + throw mapError(error); + } + } +} + +/** + * Synchronously creates `newpath` as a hard link to `oldpath`. + * + * Requires `allow-read` and `allow-write` permissions. + * + * @example Usage + * ```ts ignore + * import { linkSync } from "@std/fs/unstable-link"; + * linkSync("old/name", "new/name"); + * ``` + * + * @tags allow-read, allow-write + * + * @param oldpath The path of the resource pointed by the hard link. + * @param newpath The path of the hard link. + */ +export function linkSync(oldpath: string, newpath: string): void { + if (isDeno) { + Deno.linkSync(oldpath, newpath); + } else { + try { + getNodeFs().linkSync(oldpath, newpath); + } catch (error) { + throw mapError(error); + } + } +} diff --git a/fs/unstable_link_test.ts b/fs/unstable_link_test.ts new file mode 100644 index 000000000000..ffbd9d3b0b17 --- /dev/null +++ b/fs/unstable_link_test.ts @@ -0,0 +1,171 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +import { + assert, + assertEquals, + assertExists, + assertRejects, + assertThrows, +} from "@std/assert"; +import { link, linkSync } from "./unstable_link.ts"; +import { AlreadyExists, NotFound } from "./unstable_errors.js"; +import { mkdtemp, open, readFile, rm, stat, writeFile } from "node:fs/promises"; +import { + closeSync, + mkdtempSync, + openSync, + readFileSync, + rmSync, + statSync, + writeFileSync, +} from "node:fs"; +import { platform, tmpdir } from "node:os"; +import { join, resolve } from "node:path"; + +Deno.test("link() creates a hard link to a file and mutate through hard link", async () => { + const tempDirPath = await mkdtemp(resolve(tmpdir(), "link_")); + const testFile = join(tempDirPath, "testFile.txt"); + const linkFile = join(tempDirPath, "testFile.txt.hardlink"); + + const helloWrite = "Hello"; + await writeFile(testFile, helloWrite); + + // Linux & Mac: A single file implicitly has 1 hard link count to an inode. + if (platform() !== "win32") { + const testFileStat = await stat(testFile); + assertExists(testFileStat.nlink, "Hard link count is null"); + assert(testFileStat.nlink === 1); + } + + // Make another hard link with `link` to the same file. (Linux & Mac - inode). + await link(testFile, linkFile); + + // Linux & Mac: Count hard links. + if (platform() !== "win32") { + const testFileStat = await stat(testFile); + assertExists(testFileStat.nlink, "Hard link count is null"); + assert(testFileStat.nlink === 2); + } + + // Read test file content through the hard link. + const helloRead = await readFile(linkFile, { encoding: "utf8" }); + assertEquals(helloRead, helloWrite); + + // Overwrite file content through hard link and read through testFile. + const stdWrite = "Standard Library"; + await writeFile(linkFile, stdWrite); + const stdRead = await readFile(testFile, { encoding: "utf8" }); + assertEquals(stdRead, stdWrite); + + // Remove testFile, count links, and check hard link properties. + await rm(testFile); + + const linkFileStat = await stat(linkFile); + assert(linkFileStat.isFile()); + assert(!linkFileStat.isSymbolicLink()); + + // Linux & Mac: Count hard links. + if (platform() !== "win32") { + assertExists(linkFileStat.nlink, "Hard link count is null"); + assert(linkFileStat.nlink === 1); + } + + await rm(tempDirPath, { recursive: true, force: true }); +}); + +Deno.test("link() rejects with AlreadyExists when hard linking with an existing path", async () => { + const tempDirPath = await mkdtemp(resolve(tmpdir(), "link_")); + const testFile = join(tempDirPath, "testFile.txt"); + const anotherFile = join(tempDirPath, "anotherFile.txt"); + + const testFh = await open(testFile, "w"); + await testFh.close(); + const anotherFh = await open(anotherFile, "w"); + await anotherFh.close(); + + await assertRejects(async () => { + await link(testFile, anotherFile); + }, AlreadyExists); + + await rm(tempDirPath, { recursive: true, force: true }); +}); + +Deno.test("link() rejects with NotFound with a non-existent file", async () => { + await assertRejects(async () => { + await link("non-existent-file.txt", "non-existent-hard-link"); + }, NotFound); +}); + +Deno.test("linkSync() creates a hard link to a file and mutate through hard link", () => { + const tempDirPath = mkdtempSync(resolve(tmpdir(), "linkSync_")); + const testFile = join(tempDirPath, "testFile.txt"); + const linkFile = join(tempDirPath, "testFile.txt.hardlink"); + + const helloWrite = "Hello"; + writeFileSync(testFile, helloWrite); + + // Linux & Mac: A single file implicitly has 1 hard link to an inode. + if (platform() !== "win32") { + const testFileStat = statSync(testFile); + assertExists(testFileStat.nlink, "Hard link count is null"); + assert(testFileStat.nlink === 1); + } + + // Make another hard link with `link` to the same inode. + linkSync(testFile, linkFile); + + // Linux & Mac: Count hard links. + if (platform() !== "win32") { + const testFileStat = statSync(testFile); + assertExists(testFileStat.nlink, "Hard link count is null"); + assert(testFileStat.nlink === 2); + } + + // Read test file content through the hard link. + const helloRead = readFileSync(linkFile, { encoding: "utf8" }); + assertEquals(helloRead, helloWrite); + + // Overwrite file content through hard link and read through testFile. + const stdWrite = "Standard Library"; + writeFileSync(linkFile, stdWrite); + const stdRead = readFileSync(testFile, { encoding: "utf8" }); + assertEquals(stdRead, stdWrite); + + // Remove testFile, count links, and check hard link properties. + rmSync(testFile); + + const linkFileStat = statSync(linkFile); + assert(linkFileStat.isFile()); + assert(!linkFileStat.isSymbolicLink()); + + // Linux & Mac: Count hard links. + if (platform() !== "win32") { + assertExists(linkFileStat.nlink, "Hard link count is null"); + assert(linkFileStat.nlink === 1); + } + + rmSync(tempDirPath, { recursive: true, force: true }); +}); + +Deno.test("linkSync() throws with AlreadyExists when hard linking with an existing path", () => { + const tempDirPath = mkdtempSync(resolve(tmpdir(), "link_")); + const testFile = join(tempDirPath, "testFile.txt"); + const anotherFile = join(tempDirPath, "anotherFile.txt"); + + const testFd = openSync(testFile, "w"); + closeSync(testFd); + const anotherFd = openSync(anotherFile, "w"); + closeSync(anotherFd); + + assertThrows(() => { + linkSync(testFile, anotherFile); + }, AlreadyExists); + + rmSync(tempDirPath, { recursive: true, force: true }); +}); + +Deno.test("linkSync() throws with NotFound with a non-existent file", () => { + assertThrows(() => { + linkSync("non-existent-file.txt", "non-existent-hard-link"); + }, NotFound); +}); diff --git a/fs/unstable_read_link.ts b/fs/unstable_read_link.ts new file mode 100644 index 000000000000..3b9f75f36371 --- /dev/null +++ b/fs/unstable_read_link.ts @@ -0,0 +1,69 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +import { getNodeFs, isDeno } from "./_utils.ts"; +import { mapError } from "./_map_error.ts"; + +/** + * Resolves to the path destination of the named symbolic link. + * + * Throws Error if called with a hard link. + * + * Requires `allow-read` permission. + * + * @example Usage + * ```ts ignore + * import { readLink } from "@std/fs/unstable-read-link"; + * import { symlink } from "@std/fs/unstable-symlink"; + * await symlink("./test.txt", "./test_link.txt"); + * const target = await readLink("./test_link.txt"); // full path of ./test.txt + * ``` + * + * @tags allow-read + * + * @param path The path of the symbolic link. + * @returns A promise that resolves to the file path pointed by the symbolic + * link. + */ +export async function readLink(path: string | URL): Promise { + if (isDeno) { + return Deno.readLink(path); + } else { + try { + return await getNodeFs().promises.readlink(path); + } catch (error) { + throw mapError(error); + } + } +} + +/** + * Synchronously returns the path destination of the named symbolic link. + * + * Throws Error if called with a hard link. + * + * Requires `allow-read` permission. + * + * @example Usage + * ```ts ignore + * import { readLinkSync } from "@std/fs/unstable-read-link"; + * import { symlinkSync } from "@std/fs/unstable-symlink"; + * symlinkSync("./test.txt", "./test_link.txt"); + * const target = readLinkSync("./test_link.txt"); // full path of ./test.txt + * ``` + * + * @tags allow-read + * + * @param path The path of the symbolic link. + * @returns The file path pointed by the symbolic link. + */ +export function readLinkSync(path: string | URL): string { + if (isDeno) { + return Deno.readLinkSync(path); + } else { + try { + return getNodeFs().readlinkSync(path); + } catch (error) { + throw mapError(error); + } + } +} diff --git a/fs/unstable_read_link_test.ts b/fs/unstable_read_link_test.ts new file mode 100644 index 000000000000..0ef85e6a8753 --- /dev/null +++ b/fs/unstable_read_link_test.ts @@ -0,0 +1,85 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +import { assertEquals, assertRejects, assertThrows } from "@std/assert"; +import { readLink, readLinkSync } from "./unstable_read_link.ts"; +import { NotFound } from "./unstable_errors.js"; +import { + linkSync, + mkdtempSync, + rmSync, + symlinkSync, + writeFileSync, +} from "node:fs"; +import { link, mkdtemp, rm, symlink, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; + +Deno.test("readLink() can read through symlink", async () => { + const tempDirPath = await mkdtemp(resolve(tmpdir(), "readLink_")); + const testFile = join(tempDirPath, "testFile.txt"); + const symlinkFile = join(tempDirPath, "testFile.txt.link"); + + await writeFile(testFile, "Hello, Standard Library"); + await symlink(testFile, symlinkFile); + + const realFile = await readLink(symlinkFile); + assertEquals(testFile, realFile); + + await rm(tempDirPath, { recursive: true, force: true }); +}); + +Deno.test("readLink() rejects with Error when reading from a hard link", async () => { + const tempDirPath = await mkdtemp(resolve(tmpdir(), "readLink_")); + const testFile = join(tempDirPath, "testFile.txt"); + const linkFile = join(tempDirPath, "testFile.txt.hlink"); + + await writeFile(testFile, "Hello, Standard Library"); + await link(testFile, linkFile); + + await assertRejects(async () => { + await readLink(linkFile); + }, Error); + + await rm(tempDirPath, { recursive: true, force: true }); +}); + +Deno.test("readLink() rejects with NotFound when reading through a non-existent file", async () => { + await assertRejects(async () => { + await readLink("non-existent-file.txt.link"); + }, NotFound); +}); + +Deno.test("readLinkSync() can read through symlink", () => { + const tempDirPath = mkdtempSync(resolve(tmpdir(), "readLink_")); + const testFile = join(tempDirPath, "testFile.txt"); + const symlinkFile = join(tempDirPath, "testFile.txt.link"); + + writeFileSync(testFile, "Hello, Standard Library"); + symlinkSync(testFile, symlinkFile); + + const realFile = readLinkSync(symlinkFile); + assertEquals(testFile, realFile); + + rmSync(tempDirPath, { recursive: true, force: true }); +}); + +Deno.test("readLinkSync() throws Error when reading from a hard link", () => { + const tempDirPath = mkdtempSync(resolve(tmpdir(), "readLinkSync_")); + const testFile = join(tempDirPath, "testFile.txt"); + const linkFile = join(tempDirPath, "testFile.txt.hlink"); + + writeFileSync(testFile, "Hello, Standard Library!"); + linkSync(testFile, linkFile); + + assertThrows(() => { + readLinkSync(linkFile); + }, Error); + + rmSync(tempDirPath, { recursive: true, force: true }); +}); + +Deno.test("readLinkSync() throws NotFound when reading through a non-existent file", () => { + assertThrows(() => { + readLinkSync("non-existent-file.txt.hlink"); + }, NotFound); +}); diff --git a/fs/unstable_real_path.ts b/fs/unstable_real_path.ts new file mode 100644 index 000000000000..7f5410d9dedc --- /dev/null +++ b/fs/unstable_real_path.ts @@ -0,0 +1,79 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +import { getNodeFs, isDeno } from "./_utils.ts"; +import { mapError } from "./_map_error.ts"; + +/** + * Resolves to the absolute normalized path, with symbolic links resolved. + * + * Requires `allow-read` permission for the target path. + * + * Also requires `allow-read` permission for the `CWD` if the target path is + * relative. + * + * @example Usage + * ```ts ignore + * import { realPath } from "@std/fs/unstable-real-path"; + * import { symlink } from "@std/fs/unstable-symlink"; + * // e.g. given /home/alice/file.txt and current directory /home/alice + * await symlink("file.txt", "symlink_file.txt"); + * const fileRealPath = await realPath("./file.txt"); + * const realSymLinkPath = await realPath("./symlink_file.txt"); + * console.log(fileRealPath); // outputs "/home/alice/file.txt" + * console.log(realSymLinkPath); // outputs "/home/alice/file.txt" + * ``` + * + * @tags allow-read + * + * @param path The path of the file or directory. + * @returns A promise fulfilling with the absolute `path` of the file. + */ +export async function realPath(path: string | URL): Promise { + if (isDeno) { + return Deno.realPath(path); + } else { + try { + return await getNodeFs().promises.realpath(path); + } catch (error) { + throw mapError(error); + } + } +} + +/** + * Synchronously returns absolute normalized path, with symbolic links + * resolved. + * + * Requires `allow-read` permission for the target path. + * + * Also requires `allow-read` permission for the `CWD` if the target path is + * relative. + * + * @example Usage + * ```ts ignore + * import { realPathSync } from "@std/fs/unstable-real-path"; + * import { symlinkSync } from "@std/fs/unstable-symlink"; + * // e.g. given /home/alice/file.txt and current directory /home/alice + * symlinkSync("file.txt", "symlink_file.txt"); + * const realPath = realPathSync("./file.txt"); + * const realSymLinkPath = realPathSync("./symlink_file.txt"); + * console.log(realPath); // outputs "/home/alice/file.txt" + * console.log(realSymLinkPath); // outputs "/home/alice/file.txt" + * ``` + * + * @tags allow-read + * + * @param path The path of the file or directory. + * @returns The absolute `path` of the file. + */ +export function realPathSync(path: string | URL): string { + if (isDeno) { + return Deno.realPathSync(path); + } else { + try { + return getNodeFs().realpathSync(path); + } catch (error) { + throw mapError(error); + } + } +} diff --git a/fs/unstable_real_path_test.ts b/fs/unstable_real_path_test.ts new file mode 100644 index 000000000000..a729dd1bb441 --- /dev/null +++ b/fs/unstable_real_path_test.ts @@ -0,0 +1,68 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +import { assert, assertMatch, assertRejects, assertThrows } from "@std/assert"; +import { realPath, realPathSync } from "./unstable_real_path.ts"; +import { NotFound } from "./unstable_errors.js"; +import { platform } from "node:os"; + +Deno.test("realPath() returns the absolute path from a relative file path", async () => { + const testFileRelative = "fs/testdata/0.ts"; + const testFileReal = await realPath(testFileRelative); + if (platform() === "win32") { + assertMatch(testFileReal, /^[A-Z]:\\/); + assert(testFileReal.endsWith(testFileRelative.replace(/\//g, "\\"))); + } else { + assert(testFileReal.startsWith("/")); + assert(testFileReal.endsWith(testFileRelative)); + } +}); + +Deno.test("realPath() returns the absolute path of the linked file via symlink", async () => { + // `fs/testdata/0-link` is symlinked to file `fs/testdata/0.ts`. + const testFileSymlink = "fs/testdata/0-link"; + const testFileReal = await realPath(testFileSymlink); + if (platform() === "win32") { + assertMatch(testFileReal, /^[A-Z]:\\/); + assert(testFileReal.endsWith("/testdata/0.ts".replace(/\//g, "\\"))); + } else { + assert(testFileReal.startsWith("/")); + assert(testFileReal.endsWith("fs/testdata/0.ts")); + } +}); + +Deno.test("realPath() rejects with NotFound for a non-existent file", async () => { + await assertRejects(async () => { + await realPath("non-existent-file.txt"); + }, NotFound); +}); + +Deno.test("realPathSync() returns the absolute path of a relative file", () => { + const testFileRelative = "fs/testdata/0.ts"; + const testFileReal = realPathSync(testFileRelative); + if (platform() === "win32") { + assertMatch(testFileReal, /^[A-Z]:\\/); + assert(testFileReal.endsWith(testFileRelative.replace(/\//g, "\\"))); + } else { + assert(testFileReal.startsWith("/")); + assert(testFileReal.endsWith(testFileRelative)); + } +}); + +Deno.test("realPathSync() returns the absolute path of the linked file via symlink", () => { + // `fs/testdata/0-link` is symlinked to file `fs/testdata/0.ts`. + const testFileSymlink = "fs/testdata/0-link"; + const testFileReal = realPathSync(testFileSymlink); + if (platform() === "win32") { + assertMatch(testFileReal, /^[A-Z]:\\/); + assert(testFileReal.endsWith("/testdata/0.ts".replace(/\//g, "\\"))); + } else { + assert(testFileReal.startsWith("/")); + assert(testFileReal.endsWith("/testdata/0.ts")); + } +}); + +Deno.test("realPathSync() throws with NotFound for a non-existent file", () => { + assertThrows(() => { + realPathSync("non-existent-file.txt"); + }, NotFound); +}); diff --git a/http/deno.json b/http/deno.json index 93ba1b572176..dadf0bbc3979 100644 --- a/http/deno.json +++ b/http/deno.json @@ -1,6 +1,6 @@ { "name": "@std/http", - "version": "1.0.12", + "version": "1.0.13", "exports": { ".": "./mod.ts", "./cookie": "./cookie.ts", diff --git a/http/file_server_test.ts b/http/file_server_test.ts index 7b1e6873dc6f..e2d762512e18 100644 --- a/http/file_server_test.ts +++ b/http/file_server_test.ts @@ -1125,7 +1125,7 @@ async function readUntilMatch( match: string, ) { const reader = source.getReader(); - let buf = new Uint8Array(0); + let buf: Uint8Array = new Uint8Array(0); const dec = new TextDecoder(); while (!dec.decode(buf).includes(match)) { const { value } = await reader.read(); diff --git a/import_map.json b/import_map.json index 4e2bc2352727..f9cff79c30e6 100644 --- a/import_map.json +++ b/import_map.json @@ -1,6 +1,6 @@ { "imports": { - "@deno/graph": "jsr:@deno/graph@^0.82", + "@deno/graph": "jsr:@deno/graph@^0.87.2", "@deno/doc": "jsr:@deno/doc@0.148", "npm:/typescript": "npm:typescript@5.6.2", "automation/": "https://raw.githubusercontent.com/denoland/automation/0.10.0/", @@ -8,38 +8,38 @@ "@std/assert": "jsr:@std/assert@^1.0.11", "@std/async": "jsr:@std/async@^1.0.10", - "@std/bytes": "jsr:@std/bytes@^1.0.4", + "@std/bytes": "jsr:@std/bytes@^1.0.5", "@std/cache": "jsr:@std/cache@^0.1.3", "@std/cbor": "jsr:@std/cbor@^0.1.6", - "@std/cli": "jsr:@std/cli@^1.0.11", + "@std/cli": "jsr:@std/cli@^1.0.12", "@std/collections": "jsr:@std/collections@^1.0.10", - "@std/crypto": "jsr:@std/crypto@^1.0.3", + "@std/crypto": "jsr:@std/crypto@^1.0.4", "@std/csv": "jsr:@std/csv@^1.0.5", "@std/data-structures": "jsr:@std/data-structures@^1.0.6", "@std/datetime": "jsr:@std/datetime@^0.225.3", "@std/dotenv": "jsr:@std/dotenv@^0.225.3", - "@std/encoding": "jsr:@std/encoding@^1.0.6", - "@std/expect": "jsr:@std/expect@^1.0.12", - "@std/fmt": "jsr:@std/fmt@^1.0.4", + "@std/encoding": "jsr:@std/encoding@^1.0.7", + "@std/expect": "jsr:@std/expect@^1.0.13", + "@std/fmt": "jsr:@std/fmt@^1.0.5", "@std/front-matter": "jsr:@std/front-matter@^1.0.5", - "@std/fs": "jsr:@std/fs@^1.0.10", + "@std/fs": "jsr:@std/fs@^1.0.11", "@std/html": "jsr:@std/html@^1.0.3", - "@std/http": "jsr:@std/http@^1.0.12", + "@std/http": "jsr:@std/http@^1.0.13", "@std/ini": "jsr:@std/ini@^1.0.0-rc.5", "@std/internal": "jsr:@std/internal@^1.0.5", - "@std/io": "jsr:@std/io@^0.225.1", + "@std/io": "jsr:@std/io@^0.225.2", "@std/json": "jsr:@std/json@^1.0.1", "@std/jsonc": "jsr:@std/jsonc@^1.0.1", - "@std/log": "jsr:@std/log@^0.224.13", + "@std/log": "jsr:@std/log@^0.224.14", "@std/media-types": "jsr:@std/media-types@^1.1.0", - "@std/msgpack": "jsr:@std/msgpack@^1.0.2", + "@std/msgpack": "jsr:@std/msgpack@^1.0.3", "@std/net": "jsr:@std/net@^1.0.4", "@std/path": "jsr:@std/path@^1.0.8", "@std/regexp": "jsr:@std/regexp@^1.0.1", "@std/random": "jsr:@std/random@^0.1.0", "@std/semver": "jsr:@std/semver@^1.0.3", - "@std/streams": "jsr:@std/streams@^1.0.8", - "@std/tar": "jsr:@std/tar@^0.1.4", + "@std/streams": "jsr:@std/streams@^1.0.9", + "@std/tar": "jsr:@std/tar@^0.1.5", "@std/testing": "jsr:@std/testing@^1.0.9", "@std/text": "jsr:@std/text@^1.0.10", "@std/toml": "jsr:@std/toml@^1.0.2", diff --git a/io/buffer.ts b/io/buffer.ts index 7b3630cbcdd2..48f579f6f23a 100644 --- a/io/buffer.ts +++ b/io/buffer.ts @@ -53,7 +53,14 @@ export class Buffer implements Writer, WriterSync, Reader, ReaderSync { * @param ab The ArrayBuffer to use as the initial contents of the buffer. */ constructor(ab?: ArrayBufferLike | ArrayLike) { - this.#buf = ab === undefined ? new Uint8Array(0) : new Uint8Array(ab); + if (ab === undefined) { + this.#buf = new Uint8Array(0); + } else if (ab instanceof SharedArrayBuffer) { + // Note: This is necessary to avoid type error + this.#buf = new Uint8Array(ab); + } else { + this.#buf = new Uint8Array(ab); + } } /** diff --git a/io/deno.json b/io/deno.json index 68042fab6f06..2a6ffa5fd8ba 100644 --- a/io/deno.json +++ b/io/deno.json @@ -1,6 +1,6 @@ { "name": "@std/io", - "version": "0.225.1", + "version": "0.225.2", "exports": { ".": "./mod.ts", "./buffer": "./buffer.ts", diff --git a/log/deno.json b/log/deno.json index 8437c073596e..08b9efe3c376 100644 --- a/log/deno.json +++ b/log/deno.json @@ -1,6 +1,6 @@ { "name": "@std/log", - "version": "0.224.13", + "version": "0.224.14", "exports": { ".": "./mod.ts", "./base-handler": "./base_handler.ts", diff --git a/log/mod.ts b/log/mod.ts index 30ef9524ea57..b6cbdd0a43ab 100644 --- a/log/mod.ts +++ b/log/mod.ts @@ -1,9 +1,13 @@ // Copyright 2018-2025 the Deno authors. MIT license. /** - * Logging library with the support for terminal and file outputs. Also provides + * Logging library with support for terminal and file outputs. Also provides * interfaces for building custom loggers. * + * > [!IMPORTANT] + * > @std/log is [likely to be removed in the future](https://github.com/denoland/std/issues/6124). + * > Consider using [Open Telemetry](https://docs.deno.com/runtime/fundamentals/open_telemetry/). + * * ## Loggers * * Loggers are objects that you interact with. When you use a logger method it diff --git a/msgpack/_types.ts b/msgpack/_types.ts new file mode 100644 index 000000000000..340b2fcce9d6 --- /dev/null +++ b/msgpack/_types.ts @@ -0,0 +1,11 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +/** + * Proxy type of {@code Uint8Array; diff --git a/msgpack/deno.json b/msgpack/deno.json index 4e39c6b0aad0..40180351ea1d 100644 --- a/msgpack/deno.json +++ b/msgpack/deno.json @@ -1,6 +1,6 @@ { "name": "@std/msgpack", - "version": "1.0.2", + "version": "1.0.3", "exports": { ".": "./mod.ts", "./decode": "./decode.ts", diff --git a/msgpack/encode.ts b/msgpack/encode.ts index ce7b73fd78dd..2d3c2f834104 100644 --- a/msgpack/encode.ts +++ b/msgpack/encode.ts @@ -2,6 +2,8 @@ // This module is browser compatible. import { concat } from "@std/bytes/concat"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Value types that can be encoded to MessagePack. @@ -61,7 +63,7 @@ const encoder = new TextEncoder(); * @param object Value to encode to MessagePack binary format. * @returns Encoded MessagePack binary data. */ -export function encode(object: ValueType): Uint8Array { +export function encode(object: ValueType): Uint8Array_ { const byteParts: Uint8Array[] = []; encodeSlice(object, byteParts); return concat(byteParts); diff --git a/streams/buffer.ts b/streams/buffer.ts index b9abc98c08af..52324692f69f 100644 --- a/streams/buffer.ts +++ b/streams/buffer.ts @@ -133,7 +133,14 @@ export class Buffer { * @param ab An optional buffer to use as the initial buffer. */ constructor(ab?: ArrayBufferLike | ArrayLike) { - this.#buf = ab === undefined ? new Uint8Array(0) : new Uint8Array(ab); + if (ab === undefined) { + this.#buf = new Uint8Array(0); + } else if (ab instanceof SharedArrayBuffer) { + // Note: This is necessary to avoid type error + this.#buf = new Uint8Array(ab); + } else { + this.#buf = new Uint8Array(ab); + } } /** diff --git a/streams/deno.json b/streams/deno.json index cd5a18764ddb..81ca3e6f11c8 100644 --- a/streams/deno.json +++ b/streams/deno.json @@ -1,6 +1,6 @@ { "name": "@std/streams", - "version": "1.0.8", + "version": "1.0.9", "exports": { ".": "./mod.ts", "./buffer": "./buffer.ts", diff --git a/streams/to_array_buffer.ts b/streams/to_array_buffer.ts index 0a67b1e2754b..d1fae7178eff 100644 --- a/streams/to_array_buffer.ts +++ b/streams/to_array_buffer.ts @@ -39,5 +39,5 @@ export async function toArrayBuffer( chunks.push(value); } - return concat(chunks).buffer; + return concat(chunks).buffer as ArrayBuffer; } diff --git a/tar/deno.json b/tar/deno.json index 033d4caa621a..4d7d40e927c3 100644 --- a/tar/deno.json +++ b/tar/deno.json @@ -1,6 +1,6 @@ { "name": "@std/tar", - "version": "0.1.4", + "version": "0.1.5", "exports": { ".": "./mod.ts", "./tar-stream": "./tar_stream.ts", diff --git a/tar/untar_stream_test.ts b/tar/untar_stream_test.ts index 0d7023c0b143..fa0ce3f5f952 100644 --- a/tar/untar_stream_test.ts +++ b/tar/untar_stream_test.ts @@ -97,7 +97,7 @@ Deno.test("expandTarArchiveCheckingBodies", async () => { .pipeThrough(new TarStream()) .pipeThrough(new UntarStream()); - let buffer = new Uint8Array(); + let buffer: Uint8Array = new Uint8Array(); for await (const item of readable) { if (item.readable) buffer = await toBytes(item.readable); } @@ -122,7 +122,7 @@ Deno.test("UntarStream() with size equals to multiple of 512", async () => { .pipeThrough(new TarStream()) .pipeThrough(new UntarStream()); - let buffer = new Uint8Array(); + let buffer: Uint8Array = new Uint8Array(); for await (const entry of readable) { if (entry.readable) buffer = await toBytes(entry.readable); }