diff --git a/README.md b/README.md index abceb993..6ee1e3c8 100644 --- a/README.md +++ b/README.md @@ -79,13 +79,13 @@ Alternatively, you may prefer to run the remote script directly through #### Usage -``` +```` > molt --help Usage: molt Description: - Check updates to dependencies in Deno modules + Check updates to dependencies in Deno modules and configuration files Options: @@ -104,56 +104,48 @@ Options: Examples: - Check updates in a module: molt deps.ts + Check import maps in a config: molt deno.json + Check imports in a module: molt deps.ts Include multiple modules: molt mod.ts lib.ts Target all .ts files: molt ./**/*.ts Specify an import map: molt mod.ts --import-map deno.json - Ignore specific dependencies: molt deps.ts --ignore=deno_graph,node_emoji - Only check deno_std: molt deps.ts --only deno.land/std -``` + Ignore specified dependencies: molt deps.ts --ignore=deno_graph,node_emoji + Check deno_std only: molt deps.ts --only deno.land/std > [!Note]\ -> Molt CLI automatically uses import maps defined in `deno.json` or `deno.jsonc` -> if available.\ -> You can't, however, use import maps as entrypoints. +> Molt CLI automatically finds `deno.json` or `deno.jsonc` in the current +> working directory or its parent directories and uses import maps defined in +> the file if available.\ #### Examples ##### Check for updates ```sh -> molt mod.ts +> molt deno.json +📦 @luca/flag 1.0.0 => 123.456.789 📦 deno.land/std 0.200.0 => 123.456.789 - lib.ts 0.200.0 - mod.ts 0.200.0 - 📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 - mod.ts 0.50.0 - -📦 node-emoji 2.0.0 => 123.456.789 - mod.ts 2.0.0 -``` +📦 node-emoji 1.0.0 => 123.456.789 +```` ##### Write changes to files ```sh -> molt mod.ts --write +> molt deno.json --write ... -💾 lib.ts -💾 mod.ts +💾 deno.json ``` ##### Commit changes to git ```sh -> molt mod.ts --commit --pre-commit=test --prefix :package: --summary title.txt --report report.md +> molt deno.json --commit --prefix :package: ... +📝 :package: bump @luca/flag from 1.0.0 to 123.456.789 📝 :package: bump deno.land/std from 0.200.0 to 123.456.789 📝 :package: bump deno.land/x/deno_graph from 0.50.0 to 123.456.789 📝 :package: bump node-emoji from 2.0.0 to 123.456.789 - -📄 title.txt -📄 report.md ``` ## Compatibility with registries diff --git a/cli.ts b/cli.ts index 2a60794c..9f5a3f4f 100644 --- a/cli.ts +++ b/cli.ts @@ -1,6 +1,6 @@ import { distinct, filterKeys, mapEntries } from "./lib/std/collections.ts"; import { parse as parseJsonc } from "./lib/std/jsonc.ts"; -import { extname, relative } from "./lib/std/path.ts"; +import { relative } from "./lib/std/path.ts"; import { colors, Command } from "./lib/x/cliffy.ts"; import { $ } from "./lib/x/dax.ts"; import { ensure, is } from "./lib/x/unknownutil.ts"; @@ -19,9 +19,12 @@ const { gray, yellow, bold, cyan } = colors; const main = new Command() .name("molt") - .description("Check updates to dependencies in Deno modules") + .description( + "Check updates to dependencies in Deno modules and configuration files", + ) .versionOption("-v, --version", "Print version info.", versionCommand) - .example("Check updates in a module", "molt deps.ts") + .example("Check import maps in a config", "molt deno.json") + .example("Check imports in a module", "molt deps.ts") .example("Include multiple modules", "molt mod.ts lib.ts") .example("Target all .ts files", "molt ./**/*.ts") .option("--import-map ", "Specify import map file") @@ -51,16 +54,16 @@ const main = new Command() .option("--summary ", "Write a summary of changes to file") .option("--report ", "Write a report of changes to file") .arguments("") - .action(async function (options, ...entrypoints) { + .action(async function (options, ...files) { if (options.importMap) { if (await $.path(options.importMap).exists() === false) { console.error(`Import map ${options.importMap} does not exist.`); Deno.exit(1); } } - ensureJsFiles(entrypoints); - const updates = await collectUpdates(entrypoints, options); - printUpdates(updates); + ensureFiles(files); + const updates = await collectUpdates(files, options); + printUpdates(files, updates); if (options.write) { return writeUpdates(updates, options); } @@ -102,7 +105,6 @@ async function collectUpdates( const updates = await Promise.all( entrypoints.map(async (entrypoint) => await collect(entrypoint, { - findImportMap: options.importMap === undefined, ignore: options.ignore ? (dep) => options.ignore!.some((it) => dep.name.includes(it)) : undefined, @@ -149,7 +151,10 @@ async function getTasks() { const toRelativePath = (path: string) => relative(Deno.cwd(), path); -function printUpdates(updates: DependencyUpdate[]) { +function printUpdates( + files: string[], + updates: DependencyUpdate[], +) { const dependencies = new Map(); for (const u of updates) { const list = dependencies.get(u.to.name) ?? []; @@ -157,19 +162,22 @@ function printUpdates(updates: DependencyUpdate[]) { dependencies.set(u.to.name, list); } let count = 0; + const nWrites = distinct(updates.map((u) => u.referrer)).length; for (const [name, list] of dependencies.entries()) { const froms = distinct(list.map((u) => u.from.version)).join(", "); console.log( `📦 ${bold(name)} ${yellow(froms)} => ${yellow(list[0].to.version)}`, ); - distinct( - list.map((u) => { - const source = toRelativePath(u.map?.source ?? u.referrer); - return ` ${source} ` + gray(u.from.version ?? ""); - }), - ).forEach((line) => console.log(line)); - if (++count < dependencies.size) { - console.log(); + if (files.length > 1 || nWrites > 1) { + distinct( + list.map((u) => { + const source = toRelativePath(u.map?.source ?? u.referrer); + return ` ${source} ` + gray(u.from.version ?? ""); + }), + ).forEach((line) => console.log(line)); + if (++count < dependencies.size) { + console.log(); + } } } } @@ -271,17 +279,14 @@ async function runTask([name, args]: [string, string[]]) { } } -function ensureJsFiles(paths: string[]) { +function ensureFiles(paths: string[]) { for (const path of paths) { - if (!["", ".js", ".ts", ".jsx", ".tsx"].includes(extname(path))) { - throw new Error(`❌ file must be javascript or typescript: "${path}"`); - } try { if (!Deno.statSync(path).isFile) { - throw new Error(`❌ not a file: "${path}"`); + throw new Error(`Not a valid file: "${path}"`); } } catch { - throw new Error(`❌ path does not exist: "${path}"`); + throw new Error(`Path does not exist: "${path}"`); } } } diff --git a/deno.json b/deno.json index b1b65ef8..5e5059eb 100644 --- a/deno.json +++ b/deno.json @@ -4,7 +4,7 @@ "lock": "deno task -q cache --lock-write && git add deno.lock", "check": "deno check ./*.ts ./lib/*.ts ./test/integration/*.ts", "test": "NO_COLOR=1 deno test -A --no-check ./lib", - "all": "deno fmt && deno lint && deno task -q check && deno task lock && deno task -q test", + "pre-commit": "deno fmt && deno lint && deno task -q check && deno task lock && deno task -q test", "integration": "NO_COLOR=1 deno test --no-lock -A ./test/integration/*.ts", "run": "deno run --allow-env --allow-read --allow-net --allow-write=. --allow-run=git,deno cli.ts", "update": "deno run --allow-env --allow-read --allow-write --allow-net=deno.land,registry.npmjs.org --allow-run=git,deno ./cli.ts ./lib/*/*.ts", diff --git a/lib/file.ts b/lib/file.ts index bf509f61..8f4f5dfc 100644 --- a/lib/file.ts +++ b/lib/file.ts @@ -1,8 +1,7 @@ -import { parse as parseJsonc } from "./std/jsonc.ts"; import { detectEOL } from "./std/fs.ts"; import { toUrl } from "./dependency.ts"; import { type DependencyUpdate } from "./update.ts"; -import { ImportMapJson } from "./import_map.ts"; +import { readImportMapJson } from "./import_map.ts"; /** * Write the given array of DependencyUpdate to files. @@ -27,16 +26,21 @@ export function writeAll( return write(associateByFile(updates), options); } +type FileKind = "module" | "import_map"; + /** * A collection of updates to dependencies associated with a file. */ -export interface FileUpdate { - /** The full path to the file being updated. */ +export interface FileUpdate< + Kind extends FileKind = FileKind, +> { + /** The full path to the file being updated. + * @example "/path/to/mod.ts" */ path: string; /** The type of the file being updated. */ - kind: "module" | "import_map"; + kind: Kind; /** The updates to dependencies associated with the file. */ - dependencies: DependencyUpdate[]; + dependencies: DependencyUpdate[]; } /** @@ -83,16 +87,16 @@ function _write( ) { switch (update.kind) { case "module": - return writeToModule(update); + return writeToModule(update as FileUpdate<"module">); case "import_map": - return writeToImportMap(update); + return writeToImportMap(update as FileUpdate<"import_map">); } } async function writeToModule( - update: FileUpdate, + update: FileUpdate<"module">, ) { - const lineToDependencyMap = new Map( + const lineToDependencyMap = new Map( update.dependencies.map(( dependency, ) => [dependency.code.span.start.line, dependency]), @@ -121,12 +125,11 @@ async function writeToModule( async function writeToImportMap( /** The dependency update to apply. */ - update: FileUpdate, + update: FileUpdate<"import_map">, ) { - const content = await Deno.readTextFile(update.path); - const json = parseJsonc(content) as unknown as ImportMapJson; + const json = await readImportMapJson(update.path); for (const dependency of update.dependencies) { - json.imports[dependency.map!.key!] = toUrl(dependency.to); + json.imports[dependency.map.key] = toUrl(dependency.to); } await Deno.writeTextFile(update.path, JSON.stringify(json, null, 2)); } diff --git a/lib/file_test.ts b/lib/file_test.ts index c8c64edd..9f90f56c 100644 --- a/lib/file_test.ts +++ b/lib/file_test.ts @@ -58,7 +58,7 @@ WriteTextFileStub.create(fs); async function test(path: string, name = toName(path)) { const updates = await DependencyUpdate.collect( new URL(path, import.meta.url), - { findImportMap: true }, + { cwd: new URL(dirname(path), import.meta.url) }, ); const results = associateByFile(updates); diff --git a/lib/import_map.ts b/lib/import_map.ts index e82ec019..12aeb060 100644 --- a/lib/import_map.ts +++ b/lib/import_map.ts @@ -2,18 +2,18 @@ import { assertEquals } from "./std/assert.ts"; import { maxBy } from "./std/collections.ts"; import { parse as parseJsonc } from "./std/jsonc.ts"; import { type ImportMapJson, parseFromJson } from "./x/import_map.ts"; -import { is } from "./x/unknownutil.ts"; +import { ensure, is } from "./x/unknownutil.ts"; import { toPath } from "./path.ts"; export type { ImportMapJson }; -export interface ImportMapResolveResult { +export interface ImportMapResolveResult { /** The fully-resolved URL string of the import specifier. */ resolved: string; /** The key of the import map that matched with the import specifier. */ - key?: string; + key: HasKey extends true ? string : undefined; /** The mapped value by the import map corresponding to the key. */ - value?: string; + value: HasKey extends true ? string : undefined; } export interface ImportMap { @@ -45,6 +45,20 @@ const isImportMapReferrer = is.ObjectOf({ importMap: is.String, }); +/** + * Read and parse a JSON including import maps from the given file path or URL. + */ +export async function readImportMapJson( + url: string | URL, +): Promise { + const data = await Deno.readTextFile(url); + try { + return ensure(parseJsonc(data), isImportMapJson); + } catch { + throw new SyntaxError(`${url} does not have a valid import map`); + } +} + /** * Read an import map from the given file path or URL. * @param url - The URL of the import map. @@ -91,7 +105,8 @@ export async function readFromJson( } return { resolved, - ...replacement, + key: replacement?.key, + value: replacement?.value, }; }, resolveInner: inner.resolve.bind(inner), diff --git a/lib/import_map_test.ts b/lib/import_map_test.ts index a920fe92..757dd36d 100644 --- a/lib/import_map_test.ts +++ b/lib/import_map_test.ts @@ -69,6 +69,8 @@ describe("resolve()", () => { { resolved: new URL("../test/data/import_map/lib.ts", import.meta.url).href, + key: undefined, + value: undefined, }, ); }); diff --git a/lib/update.ts b/lib/update.ts index 4923e48c..65eefb3e 100644 --- a/lib/update.ts +++ b/lib/update.ts @@ -1,5 +1,5 @@ import { distinct } from "./std/collections.ts"; -import { dirname, fromFileUrl } from "./std/path.ts"; +import { fromFileUrl } from "./std/path.ts"; import { createGraph, type CreateGraphOptions, @@ -11,21 +11,25 @@ import { findFileUp, toPath, toUrl } from "./path.ts"; import { ImportMap, ImportMapResolveResult, + readImportMapJson, tryReadFromJson, } from "./import_map.ts"; import { type Dependency, parse, resolveLatestVersion, + toUrl as dependencyToUrl, type UpdatedDependency, } from "./dependency.ts"; type DependencyJson = NonNullable[number]; +type If = T extends true ? A : B; + /** * Representation of an update to a dependency. */ -export interface DependencyUpdate { +export interface DependencyUpdate { /** Properties of the dependency being updated. */ from: Dependency; /** Properties of the updated dependency. */ @@ -37,17 +41,21 @@ export interface DependencyUpdate { code: { /** The original specifier of the dependency appeared in the code. */ specifier: string; - span: NonNullable["span"]; + span: If["span"]>; }; /** The full path to the module that imports the dependency. * @example "/path/to/mod.ts" */ referrer: string; /** Information about the import map used to resolve the dependency. */ - map?: { - /** The full path to the import map used to resolve the dependency. - * @example "/path/to/import_map.json" */ - source: string; - } & ImportMapResolveResult; + map: If< + IsMapped, + { + /** The full path to the import map used to resolve the dependency. + * @example "/path/to/import_map.json" */ + source: string; + } & ImportMapResolveResult, + undefined + >; } class DenoGraph { @@ -63,9 +71,18 @@ class DenoGraph { } export interface CollectOptions { + /** + * The working directory to resolve relative paths. + * If not specified, the current working directory is used. + * At present, this option is only used to find the import map. + * + * @example "/path/to/project" + */ + cwd?: string | URL; /** * The path to the import map used to resolve dependencies. - * If not specified, deno.json or deno.jsonc in the root directory of the module is used. + * If not specified, molt will automatically find deno.json or deno.jsonc + * in the current working directory or parent directories. * * @example * ```ts @@ -76,10 +93,6 @@ export interface CollectOptions { * ``` */ importMap?: string | URL; - /** - * If true, the import map is searched for in the parent directories of the first module specified. - */ - findImportMap?: boolean; /** * A function to filter out dependencies. * @@ -107,10 +120,23 @@ export interface CollectOptions { } /** - * Collect dependencies from the given module(s). - * @param from - The path(s) to the module(s) to collect dependencies from. + * Collect dependencies from the given module(s) or Deno configuration file(s). + * Local submodules are also checked recursively. + * + * @param from - The path(s) to the file(s) to collect dependencies from. * @param options - Options to customize the behavior. * @returns The list of dependencies. + * + * @example + * ```ts + * collect("mod.ts") + * // -> Collect dependencies from mod.ts and its local submodules. + * ``` + * @example + * ```ts + * collect("deno.json") + * // -> Collect dependencies from the import map specified in deno.json + * ``` */ export async function collect( from: string | URL | (string | URL)[], @@ -120,9 +146,7 @@ export async function collect( const urls = froms.map((path) => toUrl(path)); const importMapPath = options.importMap ?? - (options.findImportMap - ? await findFileUp(dirname(urls[0]), "deno.json", "deno.jsonc") - : undefined); + await findFileUp(options.cwd ?? Deno.cwd(), "deno.json", "deno.jsonc"); const importMap = importMapPath ? await tryReadFromJson(toUrl(importMapPath)) @@ -135,18 +159,26 @@ export async function collect( }); const updates: DependencyUpdate[] = []; - await Promise.all( - graph.modules.flatMap((m) => - m.dependencies?.map(async (dependency) => { - const update = await create( - dependency, - m.specifier, - { ...options, importMap }, - ); - return update ? updates.push(update) : undefined; - }) - ), - ); + await Promise.all([ + ...graph.modules + .filter((m) => m.kind === "esm") + .flatMap((m) => + m.dependencies?.map(async (dependency) => { + const update = await _createDependencyUpdate( + dependency, + m.specifier, + { ...options, importMap }, + ); + return update ? updates.push(update) : undefined; + }) + ), + ...graph.modules + .filter((m) => m.kind === "asserted" && m.mediaType === "Json") + .map(async (m) => { + const results = await _collectFromImportMap(m.specifier, options); + updates.push(...results); + }), + ]); return updates.sort((a, b) => a.to.name.localeCompare(b.to.name)); } @@ -157,6 +189,7 @@ const load: NonNullable = async ( switch (url.protocol) { case "node:": case "npm:": + case "jsr:": return { kind: "external", specifier, @@ -181,7 +214,7 @@ const load: NonNullable = async ( * @param options - Options to customize the behavior. * @returns The created DependencyUpdate. */ -async function create( +async function _createDependencyUpdate( dependencyJson: DependencyJson, referrer: string, options?: Pick & { @@ -201,7 +234,7 @@ async function create( const mapped = options?.importMap?.resolve( dependencyJson.specifier, referrer, - ); + ) as ImportMapResolveResult | undefined; const dependency = parse(new URL(mapped?.value ?? specifier)); if (options?.ignore?.(dependency)) { return; @@ -239,6 +272,50 @@ async function create( }; } +async function _collectFromImportMap( + specifier: ModuleJson["specifier"], + options: Pick, +): Promise { + const json = await readImportMapJson(new URL(specifier)); + const updates: DependencyUpdate[] = []; + await Promise.all( + Object.entries(json.imports).map( + async ([key, value]): Promise => { + if (!URL.canParse(value)) { + return; + } + const dependency = parse(new URL(value)); + if (options.ignore?.(dependency)) { + return; + } + if (options.only && !options.only(dependency)) { + return; + } + const latest = await resolveLatestVersion(dependency); + if (!latest || latest.version === dependency.version) { + return; + } + updates.push({ + from: dependency, + to: latest, + code: { + specifier: value, + span: undefined, + }, + referrer: toPath(specifier), + map: { + source: toPath(specifier), + resolved: value, + key, + value: dependencyToUrl(latest), + }, + }); + }, + ), + ); + return updates; +} + export type VersionChange = { from?: string; to: string; diff --git a/lib/update_test.ts b/lib/update_test.ts index 236b1462..d21572fb 100644 --- a/lib/update_test.ts +++ b/lib/update_test.ts @@ -1,19 +1,29 @@ +import { dirname } from "./std/path.ts"; import { assertEquals, assertThrows } from "./std/assert.ts"; import { filterKeys } from "./std/collections.ts"; import { basename } from "./std/path.ts"; import { assertSnapshot } from "./testing.ts"; import { LatestSemVerStub } from "./testing.ts"; +import { readImportMapJson } from "./import_map.ts"; import { collect, DependencyUpdate, getVersionChange } from "./update.ts"; -const test = (path: string, name = basename(path)) => - Deno.test("collect - " + name, async (t) => { - const updates = await collect(new URL(path, import.meta.url), { - findImportMap: true, - }); - for (const update of updates) { - await assertUpdateSnapshot(t, update); - } - }); +function test( + path: string, + name = basename(path), + variation?: string, +) { + Deno.test( + "collect - " + (variation ? `${name} - ${variation}` : name), + async (t) => { + const updates = await collect(new URL(path, import.meta.url), { + cwd: new URL(dirname(path), import.meta.url), + }); + for (const update of updates) { + await assertUpdateSnapshot(t, update); + } + }, + ); +} async function assertUpdateSnapshot( t: Deno.TestContext, @@ -29,6 +39,15 @@ async function assertUpdateSnapshot( ); } +async function hasImportMap(url: URL) { + try { + await readImportMapJson(url); + return true; + } catch { + return false; + } +} + const LATEST = "123.456.789"; LatestSemVerStub.create(LATEST); @@ -45,8 +64,20 @@ for await ( new URL("../test/data/" + testCase.name, import.meta.url), ) ) { - if (entry.isFile && entry.name === "mod.ts") { - test(`../test/data/${testCase.name}/mod.ts`, testCase.name); + if ( + entry.isFile && entry.name === "mod.ts" || + entry.name.endsWith(".json") && await hasImportMap( + new URL( + `../test/data/${testCase.name}/${entry.name}`, + import.meta.url, + ), + ) + ) { + test( + `../test/data/${testCase.name}/${entry.name}`, + testCase.name, + entry.name, + ); } } } diff --git a/test/data/import_map/deno.json b/test/data/import_map/deno.json index 0c8ebcd8..6a32c256 100644 --- a/test/data/import_map/deno.json +++ b/test/data/import_map/deno.json @@ -3,6 +3,7 @@ "std/": "https://deno.land/std@0.200.0/", "deno_graph": "https://deno.land/x/deno_graph@0.50.0/mod.ts", "node-emoji": "npm:node-emoji@1.0.0", + "flag": "jsr:@luca/flag@1.0.0", "/": "./" } } diff --git a/test/data/import_map/mod.ts b/test/data/import_map/mod.ts index 06d1d826..39afe7b3 100644 --- a/test/data/import_map/mod.ts +++ b/test/data/import_map/mod.ts @@ -1,4 +1,5 @@ import { assert } from "std/assert.ts"; import { createGraph } from "deno_graph"; import { emojify } from "node-emoji"; +import { printProgress } from "flag"; import { noop } from "/noop.ts"; diff --git a/test/data/multiple_imports.ts b/test/data/multiple_imports.ts index d46da302..da326cfa 100644 --- a/test/data/multiple_imports.ts +++ b/test/data/multiple_imports.ts @@ -1,3 +1,4 @@ import { assert } from "https://deno.land/std@0.200.0/assert/assert.ts"; import { createGraph } from "https://deno.land/x/deno_graph@0.50.0/mod.ts"; import emoji from "npm:node-emoji@2.0.0"; +import { printProgress } from "jsr:@luca/flag@1.0.0"; diff --git a/test/integration/cli.ts b/test/integration/cli.ts index 307ecca7..9ed5c216 100644 --- a/test/integration/cli.ts +++ b/test/integration/cli.ts @@ -1,29 +1,86 @@ import { assertEquals } from "../../lib/std/assert.ts"; import { stripAnsiCode } from "../../lib/std/fmt.ts"; +import { join } from "../../lib/std/path.ts"; import { assertSnapshot } from "../../lib/testing.ts"; -function stringify(data: Uint8Array) { - const decoder = new TextDecoder(); - let text = decoder.decode(data); - if (Deno.build.os === "windows") { - text = text - .replace(/\r\n/g, "\n") - .replace(/\\/g, "/"); - } - return stripAnsiCode(text); -} +// basic commands +molt("", { code: 2 }); +molt("--help"); +molt("--version"); + +// single file +molt("not_exist.ts", { code: 1 }); +molt("import.ts"); + +// special registries +molt("jsr.ts"); + +// with import maps +molt("mod.ts", { cwd: "import_map" }); +molt("mod.ts --import-map deno.json", { cwd: "import_map" }); + +// --ignore and --only +molt("multiple_imports.ts --ignore node-emoji"); +molt("multiple_imports.ts --ignore=deno_graph,node-emoji"); +molt("multiple_imports.ts --only deno.land/std"); +molt("multiple_imports.ts --only=deno.land/std,deno_graph"); +molt("multiple_imports.ts --only deno.land --ignore deno_graph"); + +// --write +molt("mod.ts --write", { cwd: "multiple_modules" }); +molt( + "mod.ts --write --summary title.txt --report body.md", + { cwd: "multiple_modules" }, +); + +// --commit +molt("mod.ts --commit", { cwd: "multiple_modules" }); +molt("mod.ts --commit --prefix :package:", { cwd: "multiple_modules" }); +molt( + "mod.ts --commit --pre-commit=fmt --post-commit=lint", + { cwd: "multiple_modules" }, +); +molt( + "mod.ts --commit --summary title.txt --report body.md", + { cwd: "multiple_modules" }, +); +molt( + "mod.ts --commit --summary title.txt --pre-commit=fmt", + { cwd: "multiple_modules" }, +); + +// deno.json +molt("deno.json", { cwd: "import_map" }); +molt("deno.json --write", { cwd: "import_map" }); +molt("deno.json --commit --prefix :package:", { cwd: "import_map" }); + +//----------------------- +// Test implementation +//----------------------- + +const BIN = new URL("../../cli.ts", import.meta.url).pathname; +const DATA = new URL("../data", import.meta.url).pathname; + +function molt(line: string, opts?: { + cwd?: string; + code?: number; +}) { + const args = line.length > 0 ? line.split(" ") : []; + + const name = "cli - " + (opts?.cwd ? opts.cwd + " - " : "") + + '"' + ["molt"].concat(args).join(" ") + '"'; -function test(cmd: string, code = 0) { - const [, ...args] = cmd.split(" "); - Deno.test(cmd, async (t) => { + Deno.test(name, async (t) => { const output = await new Deno.Command("deno", { - args: ["run", "-A", "./cli.ts", ...args], + args: ["run", "-A", BIN, ...args], env: { MOLT_TEST: "1" }, + cwd: join(DATA, opts?.cwd ? `/${opts?.cwd}` : ""), }).output(); + const stdout = stringify(output.stdout); const stderr = stringify(output.stderr); try { - assertEquals(output.code, code); + assertEquals(output.code, opts?.code ?? 0); } catch (err) { console.error(stdout); console.error(stderr); @@ -34,46 +91,13 @@ function test(cmd: string, code = 0) { }); } -const dir = "test/data"; - -test("molt", 2); -test("molt --help"); -test("molt --version"); - -test(`molt not_exist.ts`, 1); -test(`molt ${dir}/import.ts`); - -test(`molt ${dir}/jsr.ts`); - -test(`molt ${dir}/import_map/mod.ts`); -test(`molt ${dir}/import_map/mod.ts --import-map ${dir}/import_map/deno.json`); -test(`molt ${dir}/import_map/deno.json`, 1); -test( - `molt ${dir}/import_map/mod.ts --import-map not_exist.json`, - 1, -); - -test(`molt ${dir}/multiple_imports.ts --ignore node-emoji`); -test(`molt ${dir}/multiple_imports.ts --ignore=deno_graph,node-emoji`); - -test(`molt ${dir}/multiple_imports.ts --only deno.land/std`); -test(`molt ${dir}/multiple_imports.ts --only=deno.land/std,deno_graph`); - -test(`molt ${dir}/multiple_imports.ts --only deno.land --ignore deno_graph`); - -test(`molt ${dir}/multiple_modules/mod.ts --write`); -test( - `molt ${dir}/multiple_modules/mod.ts --write --summary title.txt --report body.md`, -); - -test(`molt ${dir}/multiple_modules/mod.ts --commit`); -test(`molt ${dir}/multiple_modules/mod.ts --commit --prefix :package:`); -test( - `molt ${dir}/multiple_modules/mod.ts --commit --pre-commit=fmt --post-commit=lint`, -); -test( - `molt ${dir}/multiple_modules/mod.ts --commit --summary title.txt --report body.md`, -); -test( - `molt ${dir}/multiple_modules/mod.ts --commit --summary title.txt --pre-commit=fmt`, -); +function stringify(data: Uint8Array) { + const decoder = new TextDecoder(); + let text = decoder.decode(data); + if (Deno.build.os === "windows") { + text = text + .replace(/\r\n/g, "\n") + .replace(/\\/g, "/"); + } + return stripAnsiCode(text); +} diff --git a/test/integration/registries.ts b/test/integration/registries.ts index b079f3c3..6478cf94 100644 --- a/test/integration/registries.ts +++ b/test/integration/registries.ts @@ -17,37 +17,35 @@ const SPECS = [ ], [ "npm:", - "npm:preact@10.5.5", + "npm:preact@10.19.0", ], [ "jsr:", - "jsr:@std/semver@0.210.0", + "jsr:@std/jsonc@0.210.0", ], [ "cdn.jsdelivr.net/npm", - "https://cdn.jsdelivr.net/npm/preact@10.5.5", + "https://cdn.jsdelivr.net/npm/preact@10.19.0", ], [ "cdn.jsdelivr.net/gh", - "https://cdn.jsdelivr.net/gh/hasundue/molt@e4509a9/lib/path.ts", + "https://cdn.jsdelivr.net/gh/hasundue/molt@8a4a9a7/lib/path.ts", ], [ "cdn.skypack.dev", - "https://cdn.skypack.dev/preact@10.5.5", + "https://cdn.skypack.dev/preact@10.19.0", ], [ "ga.jspm.io", "https://ga.jspm.io/npm:lit-html@2.7.0/development/is-server.js", ], - /** [ "esm.run", - "https://esm.run/preact@10.5.5", + "https://esm.run/preact@10.19.0", ], - */ [ "esm.sh", - "https://esm.sh/preact@10.5.5", + "https://esm.sh/preact@10.19.0", ], [ "x.nest.land", @@ -55,32 +53,24 @@ const SPECS = [ ], [ "pax.deno.dev", - "https://pax.deno.dev/hasundue/molt@e4509a9/lib/path.ts", + "https://pax.deno.dev/hasundue/molt@8a4a9a7/lib/path.ts", ], [ "raw.githubusercontent.com", - "https://raw.githubusercontent.com/hasundue/molt/e4509a9/lib/path.ts", + "https://raw.githubusercontent.com/hasundue/molt/8a4a9a7/lib/path.ts", ], [ "unpkg.com", - "https://unpkg.com/preact@10.5.5", + "https://unpkg.com/preact@10.19.0", ], ] satisfies RegistryTestSpec[]; for (const spec of SPECS) { - const name = spec[0]; + const name = "registry - " + spec[0]; Deno.test(name, async (t) => { const assert = (it: unknown) => assertSnapshot(t, it !== undefined); - // Make sure the URL is valid. - // Skip this test for npm because it fails. - if (name !== "npm:") { - await assert(await import(spec[1])); - } else { - await assert(true); - } - // Check if the dependency can be parsed. const parsed = parse(spec[1]); await assert(parsed.version); diff --git a/test/snapshots/cli.ts.snap b/test/snapshots/cli.ts.snap index 9914d45c..83730a2a 100644 --- a/test/snapshots/cli.ts.snap +++ b/test/snapshots/cli.ts.snap @@ -1,12 +1,12 @@ export const snapshot = {}; -snapshot[`molt 1`] = ` +snapshot[`cli - "molt" 1`] = ` " Usage: molt Description: - Check updates to dependencies in Deno modules + Check updates to dependencies in Deno modules and configuration files Options: @@ -25,7 +25,8 @@ Options: Examples: - Check updates in a module: molt deps.ts + Check import maps in a config: molt deno.json + Check imports in a module: molt deps.ts Include multiple modules: molt mod.ts lib.ts Target all .ts files: molt ./**/*.ts Specify an import map: molt mod.ts --import-map deno.json @@ -35,19 +36,19 @@ Examples: " `; -snapshot[`molt 2`] = ` +snapshot[`cli - "molt" 2`] = ` " error: Missing argument(s): modules " `; -snapshot[`molt --help 1`] = ` +snapshot[`cli - "molt --help" 1`] = ` " Usage: molt Description: - Check updates to dependencies in Deno modules + Check updates to dependencies in Deno modules and configuration files Options: @@ -66,7 +67,8 @@ Options: Examples: - Check updates in a module: molt deps.ts + Check import maps in a config: molt deno.json + Check imports in a module: molt deps.ts Include multiple modules: molt mod.ts lib.ts Target all .ts files: molt ./**/*.ts Specify an import map: molt mod.ts --import-map deno.json @@ -76,211 +78,180 @@ Examples: " `; -snapshot[`molt --help 2`] = `""`; +snapshot[`cli - "molt --help" 2`] = `""`; -snapshot[`molt --version 1`] = ` +snapshot[`cli - "molt --version" 1`] = ` "123.456.789 " `; -snapshot[`molt --version 2`] = ` +snapshot[`cli - "molt --version" 2`] = ` "Fetching version info " `; -snapshot[`molt not_exist.ts 1`] = `""`; +snapshot[`cli - "molt not_exist.ts" 1`] = `""`; -snapshot[`molt not_exist.ts 2`] = ` -'❌ path does not exist: "not_exist.ts" +snapshot[`cli - "molt not_exist.ts" 2`] = ` +'Path does not exist: "not_exist.ts" ' `; -snapshot[`molt test/data/import.ts 1`] = ` +snapshot[`cli - "molt import.ts" 1`] = ` "📦 deno.land/std 0.200.0 => 123.456.789 - test/data/import.ts 0.200.0 " `; -snapshot[`molt test/data/import.ts 2`] = ` +snapshot[`cli - "molt import.ts" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/jsr.ts 1`] = ` +snapshot[`cli - "molt jsr.ts" 1`] = ` "📦 @std/assert 0.210.0 => 123.456.789 - test/data/jsr.ts 0.210.0 " `; -snapshot[`molt test/data/jsr.ts 2`] = ` +snapshot[`cli - "molt jsr.ts" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/import_map/mod.ts 1`] = ` -"📦 deno.land/std 0.200.0 => 123.456.789 - test/data/import_map/deno.json 0.200.0 - +snapshot[`cli - import_map - "molt mod.ts" 1`] = ` +"📦 @luca/flag 1.0.0 => 123.456.789 +📦 deno.land/std 0.200.0 => 123.456.789 📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 - test/data/import_map/deno.json 0.50.0 - 📦 node-emoji 1.0.0 => 123.456.789 - test/data/import_map/deno.json 1.0.0 " `; -snapshot[`molt test/data/import_map/mod.ts 2`] = ` +snapshot[`cli - import_map - "molt mod.ts" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/import_map/mod.ts --import-map test/data/import_map/deno.json 1`] = ` -"📦 deno.land/std 0.200.0 => 123.456.789 - test/data/import_map/deno.json 0.200.0 - +snapshot[`cli - import_map - "molt mod.ts --import-map deno.json" 1`] = ` +"📦 @luca/flag 1.0.0 => 123.456.789 +📦 deno.land/std 0.200.0 => 123.456.789 📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 - test/data/import_map/deno.json 0.50.0 - 📦 node-emoji 1.0.0 => 123.456.789 - test/data/import_map/deno.json 1.0.0 " `; -snapshot[`molt test/data/import_map/mod.ts --import-map test/data/import_map/deno.json 2`] = ` +snapshot[`cli - import_map - "molt mod.ts --import-map deno.json" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/import_map/deno.json 1`] = `""`; - -snapshot[`molt test/data/import_map/deno.json 2`] = ` -'❌ file must be javascript or typescript: "test/data/import_map/deno.json" -' -`; - -snapshot[`molt test/data/import_map/mod.ts --import-map not_exist.json 1`] = `""`; - -snapshot[`molt test/data/import_map/mod.ts --import-map not_exist.json 2`] = ` -"Import map not_exist.json does not exist. -" -`; - -snapshot[`molt test/data/multiple_imports.ts --ignore node-emoji 1`] = ` -"📦 deno.land/std 0.200.0 => 123.456.789 - test/data/multiple_imports.ts 0.200.0 - +snapshot[`cli - "molt multiple_imports.ts --ignore node-emoji" 1`] = ` +"📦 @luca/flag 1.0.0 => 123.456.789 +📦 deno.land/std 0.200.0 => 123.456.789 📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 - test/data/multiple_imports.ts 0.50.0 " `; -snapshot[`molt test/data/multiple_imports.ts --ignore node-emoji 2`] = ` +snapshot[`cli - "molt multiple_imports.ts --ignore node-emoji" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/multiple_imports.ts --ignore=deno_graph,node-emoji 1`] = ` -"📦 deno.land/std 0.200.0 => 123.456.789 - test/data/multiple_imports.ts 0.200.0 +snapshot[`cli - "molt multiple_imports.ts --ignore=deno_graph,node-emoji" 1`] = ` +"📦 @luca/flag 1.0.0 => 123.456.789 +📦 deno.land/std 0.200.0 => 123.456.789 " `; -snapshot[`molt test/data/multiple_imports.ts --ignore=deno_graph,node-emoji 2`] = ` +snapshot[`cli - "molt multiple_imports.ts --ignore=deno_graph,node-emoji" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/multiple_imports.ts --only deno.land/std 1`] = ` +snapshot[`cli - "molt multiple_imports.ts --only deno.land/std" 1`] = ` "📦 deno.land/std 0.200.0 => 123.456.789 - test/data/multiple_imports.ts 0.200.0 " `; -snapshot[`molt test/data/multiple_imports.ts --only deno.land/std 2`] = ` +snapshot[`cli - "molt multiple_imports.ts --only deno.land/std" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/multiple_imports.ts --only=deno.land/std,deno_graph 1`] = ` +snapshot[`cli - "molt multiple_imports.ts --only=deno.land/std,deno_graph" 1`] = ` "📦 deno.land/std 0.200.0 => 123.456.789 - test/data/multiple_imports.ts 0.200.0 - 📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 - test/data/multiple_imports.ts 0.50.0 " `; -snapshot[`molt test/data/multiple_imports.ts --only=deno.land/std,deno_graph 2`] = ` +snapshot[`cli - "molt multiple_imports.ts --only=deno.land/std,deno_graph" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/multiple_imports.ts --only deno.land --ignore deno_graph 1`] = ` +snapshot[`cli - "molt multiple_imports.ts --only deno.land --ignore deno_graph" 1`] = ` "📦 deno.land/std 0.200.0 => 123.456.789 - test/data/multiple_imports.ts 0.200.0 " `; -snapshot[`molt test/data/multiple_imports.ts --only deno.land --ignore deno_graph 2`] = ` +snapshot[`cli - "molt multiple_imports.ts --only deno.land --ignore deno_graph" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/multiple_modules/mod.ts --write 1`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --write" 1`] = ` "📦 deno.land/std 0.200.0 => 123.456.789 - test/data/multiple_modules/lib.ts 0.200.0 - test/data/multiple_modules/mod.ts 0.200.0 + lib.ts 0.200.0 + mod.ts 0.200.0 📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 - test/data/multiple_modules/mod.ts 0.50.0 + mod.ts 0.50.0 📦 node-emoji 2.0.0 => 123.456.789 - test/data/multiple_modules/mod.ts 2.0.0 + mod.ts 2.0.0 -💾 test/data/multiple_modules/lib.ts -💾 test/data/multiple_modules/mod.ts +💾 lib.ts +💾 mod.ts " `; -snapshot[`molt test/data/multiple_modules/mod.ts --write 2`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --write" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/multiple_modules/mod.ts --write --summary title.txt --report body.md 1`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --write --summary title.txt --report body.md" 1`] = ` "📦 deno.land/std 0.200.0 => 123.456.789 - test/data/multiple_modules/lib.ts 0.200.0 - test/data/multiple_modules/mod.ts 0.200.0 + lib.ts 0.200.0 + mod.ts 0.200.0 📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 - test/data/multiple_modules/mod.ts 0.50.0 + mod.ts 0.50.0 📦 node-emoji 2.0.0 => 123.456.789 - test/data/multiple_modules/mod.ts 2.0.0 + mod.ts 2.0.0 -💾 test/data/multiple_modules/lib.ts -💾 test/data/multiple_modules/mod.ts +💾 lib.ts +💾 mod.ts 📄 title.txt 📄 body.md " `; -snapshot[`molt test/data/multiple_modules/mod.ts --write --summary title.txt --report body.md 2`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --write --summary title.txt --report body.md" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/multiple_modules/mod.ts --commit 1`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --commit" 1`] = ` "📦 deno.land/std 0.200.0 => 123.456.789 - test/data/multiple_modules/lib.ts 0.200.0 - test/data/multiple_modules/mod.ts 0.200.0 + lib.ts 0.200.0 + mod.ts 0.200.0 📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 - test/data/multiple_modules/mod.ts 0.50.0 + mod.ts 0.50.0 📦 node-emoji 2.0.0 => 123.456.789 - test/data/multiple_modules/mod.ts 2.0.0 + mod.ts 2.0.0 📝 bump deno.land/std from 0.200.0 to 123.456.789 📝 bump deno.land/x/deno_graph from 0.50.0 to 123.456.789 @@ -288,21 +259,21 @@ snapshot[`molt test/data/multiple_modules/mod.ts --commit 1`] = ` " `; -snapshot[`molt test/data/multiple_modules/mod.ts --commit 2`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --commit" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/multiple_modules/mod.ts --commit --prefix :package: 1`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --commit --prefix :package:" 1`] = ` "📦 deno.land/std 0.200.0 => 123.456.789 - test/data/multiple_modules/lib.ts 0.200.0 - test/data/multiple_modules/mod.ts 0.200.0 + lib.ts 0.200.0 + mod.ts 0.200.0 📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 - test/data/multiple_modules/mod.ts 0.50.0 + mod.ts 0.50.0 📦 node-emoji 2.0.0 => 123.456.789 - test/data/multiple_modules/mod.ts 2.0.0 + mod.ts 2.0.0 📝 :package: bump deno.land/std from 0.200.0 to 123.456.789 📝 :package: bump deno.land/x/deno_graph from 0.50.0 to 123.456.789 @@ -310,21 +281,21 @@ snapshot[`molt test/data/multiple_modules/mod.ts --commit --prefix :package: 1`] " `; -snapshot[`molt test/data/multiple_modules/mod.ts --commit --prefix :package: 2`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --commit --prefix :package:" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/multiple_modules/mod.ts --commit --pre-commit=fmt --post-commit=lint 1`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --commit --pre-commit=fmt --post-commit=lint" 1`] = ` "📦 deno.land/std 0.200.0 => 123.456.789 - test/data/multiple_modules/lib.ts 0.200.0 - test/data/multiple_modules/mod.ts 0.200.0 + lib.ts 0.200.0 + mod.ts 0.200.0 📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 - test/data/multiple_modules/mod.ts 0.50.0 + mod.ts 0.50.0 📦 node-emoji 2.0.0 => 123.456.789 - test/data/multiple_modules/mod.ts 2.0.0 + mod.ts 2.0.0 💾 bump deno.land/std from 0.200.0 to 123.456.789 🔨 Running task fmt... @@ -343,21 +314,21 @@ snapshot[`molt test/data/multiple_modules/mod.ts --commit --pre-commit=fmt --pos " `; -snapshot[`molt test/data/multiple_modules/mod.ts --commit --pre-commit=fmt --post-commit=lint 2`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --commit --pre-commit=fmt --post-commit=lint" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/multiple_modules/mod.ts --commit --summary title.txt --report body.md 1`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --commit --summary title.txt --report body.md" 1`] = ` "📦 deno.land/std 0.200.0 => 123.456.789 - test/data/multiple_modules/lib.ts 0.200.0 - test/data/multiple_modules/mod.ts 0.200.0 + lib.ts 0.200.0 + mod.ts 0.200.0 📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 - test/data/multiple_modules/mod.ts 0.50.0 + mod.ts 0.50.0 📦 node-emoji 2.0.0 => 123.456.789 - test/data/multiple_modules/mod.ts 2.0.0 + mod.ts 2.0.0 📝 bump deno.land/std from 0.200.0 to 123.456.789 📝 bump deno.land/x/deno_graph from 0.50.0 to 123.456.789 @@ -368,21 +339,21 @@ snapshot[`molt test/data/multiple_modules/mod.ts --commit --summary title.txt -- " `; -snapshot[`molt test/data/multiple_modules/mod.ts --commit --summary title.txt --report body.md 2`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --commit --summary title.txt --report body.md" 2`] = ` "Checking for updates " `; -snapshot[`molt test/data/multiple_modules/mod.ts --commit --summary title.txt --pre-commit=fmt 1`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --commit --summary title.txt --pre-commit=fmt" 1`] = ` "📦 deno.land/std 0.200.0 => 123.456.789 - test/data/multiple_modules/lib.ts 0.200.0 - test/data/multiple_modules/mod.ts 0.200.0 + lib.ts 0.200.0 + mod.ts 0.200.0 📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 - test/data/multiple_modules/mod.ts 0.50.0 + mod.ts 0.50.0 📦 node-emoji 2.0.0 => 123.456.789 - test/data/multiple_modules/mod.ts 2.0.0 + mod.ts 2.0.0 💾 bump deno.land/std from 0.200.0 to 123.456.789 🔨 Running task fmt... @@ -400,7 +371,53 @@ snapshot[`molt test/data/multiple_modules/mod.ts --commit --summary title.txt -- " `; -snapshot[`molt test/data/multiple_modules/mod.ts --commit --summary title.txt --pre-commit=fmt 2`] = ` +snapshot[`cli - multiple_modules - "molt mod.ts --commit --summary title.txt --pre-commit=fmt" 2`] = ` +"Checking for updates +" +`; + +snapshot[`cli - import_map - "molt deno.json" 1`] = ` +"📦 @luca/flag 1.0.0 => 123.456.789 +📦 deno.land/std 0.200.0 => 123.456.789 +📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 +📦 node-emoji 1.0.0 => 123.456.789 +" +`; + +snapshot[`cli - import_map - "molt deno.json" 2`] = ` +"Checking for updates +" +`; + +snapshot[`cli - import_map - "molt deno.json --write" 1`] = ` +"📦 @luca/flag 1.0.0 => 123.456.789 +📦 deno.land/std 0.200.0 => 123.456.789 +📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 +📦 node-emoji 1.0.0 => 123.456.789 + +💾 deno.json +" +`; + +snapshot[`cli - import_map - "molt deno.json --write" 2`] = ` +"Checking for updates +" +`; + +snapshot[`cli - import_map - "molt deno.json --commit --prefix :package:" 1`] = ` +"📦 @luca/flag 1.0.0 => 123.456.789 +📦 deno.land/std 0.200.0 => 123.456.789 +📦 deno.land/x/deno_graph 0.50.0 => 123.456.789 +📦 node-emoji 1.0.0 => 123.456.789 + +📝 :package: bump @luca/flag from 1.0.0 to 123.456.789 +📝 :package: bump deno.land/std from 0.200.0 to 123.456.789 +📝 :package: bump deno.land/x/deno_graph from 0.50.0 to 123.456.789 +📝 :package: bump node-emoji from 1.0.0 to 123.456.789 +" +`; + +snapshot[`cli - import_map - "molt deno.json --commit --prefix :package:" 2`] = ` "Checking for updates " `; diff --git a/test/snapshots/file_test.ts.snap b/test/snapshots/file_test.ts.snap index ff5a1738..aece0c17 100644 --- a/test/snapshots/file_test.ts.snap +++ b/test/snapshots/file_test.ts.snap @@ -49,6 +49,34 @@ snapshot[`associateByFile - multiple_imports.ts 1`] = ` [ { dependencies: [ + { + code: { + span: { + end: { + character: 52, + line: 3, + }, + start: { + character: 30, + line: 3, + }, + }, + specifier: "jsr:@luca/flag@1.0.0", + }, + from: { + name: "@luca/flag", + path: "", + protocol: "jsr:", + version: "1.0.0", + }, + map: undefined, + to: { + name: "@luca/flag", + path: "", + protocol: "jsr:", + version: "123.456.789", + }, + }, { code: { span: { @@ -144,6 +172,7 @@ snapshot[`write - multiple_imports.ts 1`] = ` 'import { assert } from "https://deno.land/std@123.456.789/assert/assert.ts"; import { createGraph } from "https://deno.land/x/deno_graph@123.456.789/mod.ts"; import emoji from "npm:node-emoji@123.456.789"; +import { printProgress } from "jsr:@luca/flag@123.456.789"; ', ] `; @@ -249,6 +278,37 @@ snapshot[`associateByFile - import_map/mod.ts 1`] = ` [ { dependencies: [ + { + code: { + span: { + end: { + character: 36, + line: 3, + }, + start: { + character: 30, + line: 3, + }, + }, + specifier: "flag", + }, + from: { + name: "@luca/flag", + path: "", + protocol: "jsr:", + version: "1.0.0", + }, + map: { + key: "flag", + resolved: "jsr:@luca/flag@1.0.0", + }, + to: { + name: "@luca/flag", + path: "", + protocol: "jsr:", + version: "123.456.789", + }, + }, { code: { span: { @@ -355,6 +415,7 @@ snapshot[`write - import_map/mod.ts 1`] = ` "std/": "https://deno.land/std@123.456.789/", "deno_graph": "https://deno.land/x/deno_graph@123.456.789/mod.ts", "node-emoji": "npm:node-emoji@123.456.789", + "flag": "jsr:@luca/flag@123.456.789", "/": "./" } }', diff --git a/test/snapshots/registries.ts.snap b/test/snapshots/registries.ts.snap index 20fedd5d..bd63db51 100644 --- a/test/snapshots/registries.ts.snap +++ b/test/snapshots/registries.ts.snap @@ -1,79 +1,57 @@ export const snapshot = {}; -snapshot[`deno.land/std 1`] = `true`; +snapshot[`registry - deno.land/std 1`] = `true`; -snapshot[`deno.land/std 2`] = `true`; +snapshot[`registry - deno.land/std 2`] = `true`; -snapshot[`deno.land/std 3`] = `true`; +snapshot[`registry - deno.land/x 1`] = `true`; -snapshot[`deno.land/x 1`] = `true`; +snapshot[`registry - deno.land/x 2`] = `true`; -snapshot[`deno.land/x 2`] = `true`; +snapshot[`registry - npm: 1`] = `true`; -snapshot[`deno.land/x 3`] = `true`; +snapshot[`registry - npm: 2`] = `true`; -snapshot[`npm: 1`] = `true`; +snapshot[`registry - jsr: 1`] = `true`; -snapshot[`npm: 2`] = `true`; +snapshot[`registry - jsr: 2`] = `true`; -snapshot[`npm: 3`] = `true`; +snapshot[`registry - cdn.jsdelivr.net/npm 1`] = `true`; -snapshot[`jsr: 1`] = `true`; +snapshot[`registry - cdn.jsdelivr.net/npm 2`] = `false`; -snapshot[`jsr: 2`] = `true`; +snapshot[`registry - cdn.jsdelivr.net/gh 1`] = `true`; -snapshot[`jsr: 3`] = `true`; +snapshot[`registry - cdn.jsdelivr.net/gh 2`] = `false`; -snapshot[`cdn.jsdelivr.net/npm 1`] = `true`; +snapshot[`registry - cdn.skypack.dev 1`] = `true`; -snapshot[`cdn.jsdelivr.net/npm 2`] = `true`; +snapshot[`registry - cdn.skypack.dev 2`] = `false`; -snapshot[`cdn.jsdelivr.net/npm 3`] = `false`; +snapshot[`registry - ga.jspm.io 1`] = `true`; -snapshot[`cdn.jsdelivr.net/gh 1`] = `true`; +snapshot[`registry - ga.jspm.io 2`] = `false`; -snapshot[`cdn.jsdelivr.net/gh 2`] = `true`; +snapshot[`registry - esm.run 1`] = `true`; -snapshot[`cdn.jsdelivr.net/gh 3`] = `false`; +snapshot[`registry - esm.run 2`] = `false`; -snapshot[`cdn.skypack.dev 1`] = `true`; +snapshot[`registry - esm.sh 1`] = `true`; -snapshot[`cdn.skypack.dev 2`] = `true`; +snapshot[`registry - esm.sh 2`] = `true`; -snapshot[`cdn.skypack.dev 3`] = `false`; +snapshot[`registry - x.nest.land 1`] = `true`; -snapshot[`ga.jspm.io 1`] = `true`; +snapshot[`registry - x.nest.land 2`] = `false`; -snapshot[`ga.jspm.io 2`] = `true`; +snapshot[`registry - pax.deno.dev 1`] = `true`; -snapshot[`ga.jspm.io 3`] = `false`; +snapshot[`registry - pax.deno.dev 2`] = `false`; -snapshot[`esm.sh 1`] = `true`; +snapshot[`registry - raw.githubusercontent.com 1`] = `false`; -snapshot[`esm.sh 2`] = `true`; +snapshot[`registry - raw.githubusercontent.com 2`] = `false`; -snapshot[`esm.sh 3`] = `true`; +snapshot[`registry - unpkg.com 1`] = `true`; -snapshot[`x.nest.land 1`] = `true`; - -snapshot[`x.nest.land 2`] = `true`; - -snapshot[`x.nest.land 3`] = `false`; - -snapshot[`pax.deno.dev 1`] = `true`; - -snapshot[`pax.deno.dev 2`] = `true`; - -snapshot[`pax.deno.dev 3`] = `false`; - -snapshot[`raw.githubusercontent.com 1`] = `true`; - -snapshot[`raw.githubusercontent.com 2`] = `false`; - -snapshot[`raw.githubusercontent.com 3`] = `false`; - -snapshot[`unpkg.com 1`] = `true`; - -snapshot[`unpkg.com 2`] = `true`; - -snapshot[`unpkg.com 3`] = `true`; +snapshot[`registry - unpkg.com 2`] = `true`; diff --git a/test/snapshots/update_test.ts.snap b/test/snapshots/update_test.ts.snap index acdffa03..1ec512d5 100644 --- a/test/snapshots/update_test.ts.snap +++ b/test/snapshots/update_test.ts.snap @@ -31,6 +31,36 @@ snapshot[`collect - export.ts 1`] = ` `; snapshot[`collect - multiple_imports.ts 1`] = ` +{ + code: { + span: { + end: { + character: 52, + line: 3, + }, + start: { + character: 30, + line: 3, + }, + }, + specifier: "jsr:@luca/flag@1.0.0", + }, + from: { + name: "@luca/flag", + path: "", + protocol: "jsr:", + version: "1.0.0", + }, + to: { + name: "@luca/flag", + path: "", + protocol: "jsr:", + version: "123.456.789", + }, +} +`; + +snapshot[`collect - multiple_imports.ts 2`] = ` { code: { span: { @@ -60,7 +90,7 @@ snapshot[`collect - multiple_imports.ts 1`] = ` } `; -snapshot[`collect - multiple_imports.ts 2`] = ` +snapshot[`collect - multiple_imports.ts 3`] = ` { code: { span: { @@ -90,7 +120,7 @@ snapshot[`collect - multiple_imports.ts 2`] = ` } `; -snapshot[`collect - multiple_imports.ts 3`] = ` +snapshot[`collect - multiple_imports.ts 4`] = ` { code: { span: { @@ -120,7 +150,28 @@ snapshot[`collect - multiple_imports.ts 3`] = ` } `; -snapshot[`collect - import_map_referred 1`] = ` +snapshot[`collect - import_map_referred - import_map.json 1`] = ` +{ + code: { + span: undefined, + specifier: "https://deno.land/x/dax@0.17.0/mod.ts", + }, + from: { + name: "deno.land/x/dax", + path: "/mod.ts", + protocol: "https:", + version: "0.17.0", + }, + to: { + name: "deno.land/x/dax", + path: "/mod.ts", + protocol: "https:", + version: "123.456.789", + }, +} +`; + +snapshot[`collect - import_map_referred - mod.ts 1`] = ` { code: { span: { @@ -180,7 +231,121 @@ snapshot[`collect - updated_import_and_outdated_export.ts 1`] = ` } `; -snapshot[`collect - import_map 1`] = ` +snapshot[`collect - import_map - deno.json 1`] = ` +{ + code: { + span: undefined, + specifier: "jsr:@luca/flag@1.0.0", + }, + from: { + name: "@luca/flag", + path: "", + protocol: "jsr:", + version: "1.0.0", + }, + to: { + name: "@luca/flag", + path: "", + protocol: "jsr:", + version: "123.456.789", + }, +} +`; + +snapshot[`collect - import_map - deno.json 2`] = ` +{ + code: { + span: undefined, + specifier: "https://deno.land/std@0.200.0/", + }, + from: { + name: "deno.land/std", + path: "/", + protocol: "https:", + version: "0.200.0", + }, + to: { + name: "deno.land/std", + path: "/", + protocol: "https:", + version: "123.456.789", + }, +} +`; + +snapshot[`collect - import_map - deno.json 3`] = ` +{ + code: { + span: undefined, + specifier: "https://deno.land/x/deno_graph@0.50.0/mod.ts", + }, + from: { + name: "deno.land/x/deno_graph", + path: "/mod.ts", + protocol: "https:", + version: "0.50.0", + }, + to: { + name: "deno.land/x/deno_graph", + path: "/mod.ts", + protocol: "https:", + version: "123.456.789", + }, +} +`; + +snapshot[`collect - import_map - deno.json 4`] = ` +{ + code: { + span: undefined, + specifier: "npm:node-emoji@1.0.0", + }, + from: { + name: "node-emoji", + path: "", + protocol: "npm:", + version: "1.0.0", + }, + to: { + name: "node-emoji", + path: "", + protocol: "npm:", + version: "123.456.789", + }, +} +`; + +snapshot[`collect - import_map - mod.ts 1`] = ` +{ + code: { + span: { + end: { + character: 36, + line: 3, + }, + start: { + character: 30, + line: 3, + }, + }, + specifier: "flag", + }, + from: { + name: "@luca/flag", + path: "", + protocol: "jsr:", + version: "1.0.0", + }, + to: { + name: "@luca/flag", + path: "", + protocol: "jsr:", + version: "123.456.789", + }, +} +`; + +snapshot[`collect - import_map - mod.ts 2`] = ` { code: { span: { @@ -210,7 +375,7 @@ snapshot[`collect - import_map 1`] = ` } `; -snapshot[`collect - import_map 2`] = ` +snapshot[`collect - import_map - mod.ts 3`] = ` { code: { span: { @@ -240,7 +405,7 @@ snapshot[`collect - import_map 2`] = ` } `; -snapshot[`collect - import_map 3`] = ` +snapshot[`collect - import_map - mod.ts 4`] = ` { code: { span: { @@ -360,7 +525,7 @@ snapshot[`collect - import_and_export.ts 2`] = ` } `; -snapshot[`collect - import_map_no_resolve 1`] = ` +snapshot[`collect - import_map_no_resolve - mod.ts 1`] = ` { code: { span: { @@ -390,7 +555,7 @@ snapshot[`collect - import_map_no_resolve 1`] = ` } `; -snapshot[`collect - relative_import 1`] = ` +snapshot[`collect - relative_import - mod.ts 1`] = ` { code: { span: { @@ -450,7 +615,7 @@ snapshot[`collect - updated_and_outdated.ts 1`] = ` } `; -snapshot[`collect - multiple_modules 1`] = ` +snapshot[`collect - multiple_modules - mod.ts 1`] = ` { code: { span: { @@ -480,7 +645,7 @@ snapshot[`collect - multiple_modules 1`] = ` } `; -snapshot[`collect - multiple_modules 2`] = ` +snapshot[`collect - multiple_modules - mod.ts 2`] = ` { code: { span: { @@ -510,7 +675,7 @@ snapshot[`collect - multiple_modules 2`] = ` } `; -snapshot[`collect - multiple_modules 3`] = ` +snapshot[`collect - multiple_modules - mod.ts 3`] = ` { code: { span: { @@ -540,7 +705,7 @@ snapshot[`collect - multiple_modules 3`] = ` } `; -snapshot[`collect - multiple_modules 4`] = ` +snapshot[`collect - multiple_modules - mod.ts 4`] = ` { code: { span: {