denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
93.9k stars 5.22k forks source link

JSR import maps #23504

Open oscarotero opened 4 months ago

oscarotero commented 4 months ago

Version: Deno 1.42.4

I have the following script:

import * as types from "jsr:@std/media-types@0.223.0";
import * as mod from "jsr:@oak/commons@0.10.1/media_types";

deno info outputs the following dependencies tree:

➜  oak deno info main.ts
local: /Users/oscarotero/oak/main.ts
type: TypeScript
dependencies: 16 unique
size: 393.66KB

file:///Users/oscarotero/oak/main.ts (114B)
├─┬ https://jsr.io/@std/media-types/0.223.0/mod.ts (1.14KB)
│ ├─┬ https://jsr.io/@std/media-types/0.223.0/content_type.ts (3.04KB)
│ │ ├─┬ https://jsr.io/@std/media-types/0.223.0/parse_media_type.ts (3.23KB)
│ │ │ └── https://jsr.io/@std/media-types/0.223.0/_util.ts (3.29KB)
│ │ ├─┬ https://jsr.io/@std/media-types/0.223.0/get_charset.ts (1.18KB)
│ │ │ ├── https://jsr.io/@std/media-types/0.223.0/parse_media_type.ts *
│ │ │ ├── https://jsr.io/@std/media-types/0.223.0/_util.ts *
│ │ │ └─┬ https://jsr.io/@std/media-types/0.223.0/_db.ts (1.26KB)
│ │ │   ├── https://jsr.io/@std/media-types/0.223.0/vendor/mime-db.v1.52.0.ts (182.13KB)
│ │ │   └── https://jsr.io/@std/media-types/0.223.0/_util.ts *
│ │ ├─┬ https://jsr.io/@std/media-types/0.223.0/format_media_type.ts (1.73KB)
│ │ │ └── https://jsr.io/@std/media-types/0.223.0/_util.ts *
│ │ ├── https://jsr.io/@std/media-types/0.223.0/_db.ts *
│ │ └─┬ https://jsr.io/@std/media-types/0.223.0/type_by_extension.ts (912B)
│ │   └── https://jsr.io/@std/media-types/0.223.0/_db.ts *
│ ├─┬ https://jsr.io/@std/media-types/0.223.0/extension.ts (780B)
│ │ └─┬ https://jsr.io/@std/media-types/0.223.0/extensions_by_type.ts (979B)
│ │   ├── https://jsr.io/@std/media-types/0.223.0/parse_media_type.ts *
│ │   └── https://jsr.io/@std/media-types/0.223.0/_db.ts *
│ ├── https://jsr.io/@std/media-types/0.223.0/extensions_by_type.ts *
│ ├── https://jsr.io/@std/media-types/0.223.0/format_media_type.ts *
│ ├── https://jsr.io/@std/media-types/0.223.0/get_charset.ts *
│ ├── https://jsr.io/@std/media-types/0.223.0/parse_media_type.ts *
│ └── https://jsr.io/@std/media-types/0.223.0/type_by_extension.ts *
└─┬ https://jsr.io/@oak/commons/0.10.1/media_types.ts (6.36KB)
  └─┬ https://jsr.io/@std/media-types/0.222.1/type_by_extension.ts (912B)
    └─┬ https://jsr.io/@std/media-types/0.222.1/_db.ts (1.26KB)
      ├── https://jsr.io/@std/media-types/0.222.1/vendor/mime-db.v1.52.0.ts (182.13KB)
      └── https://jsr.io/@std/media-types/0.222.1/_util.ts (3.29KB)

As you can see, there are two different versions of the same package: @std/media/0.223.0 and std/media/0.222.1. I want to use import maps to fix this:

{
  "imports": {
    "jsr:@std/media-types@0.222.1": "jsr:@std/media-types@0.223.0"
  }
}

But it doesn't work. I've tried different strategies:

{
  "imports": {
    "jsr:@std/media-types@0.222.1": "jsr:@std/media-types@0.223.0",
    "https://jsr.io/@std/media-types/0.222.1/": "https://jsr.io/@std/media-types/0.223.0/"
  },
  "scopes": {
    "https://jsr.io/@oak/commons/0.10.1/": {
      "https://jsr.io/@std/media-types/0.222.1/": "https://jsr.io/@std/media-types/0.223.0/"
    }
  }
}

But seems that none of them fixes this issue, deno info outputs the same tree, ignoring the import maps. Are import maps supported in JSR dependencies?

FYI I found the same issue with NPM #23459

jollytoad commented 4 months ago

The problem is that import maps don't understand the semantics of the version in the URL, it must literally match the URL of the import.

If you look at the module https://jsr.io/@oak/commons/0.10.1/media_types.ts you'll see that it imports: jsr:@std/media-types@0.222/type-by-extension (ie. without the patch .1 part of the version)

So the import map will only match that whole value, or maybe one with a trailing /, so the following mapping may work:

"jsr:@std/media-types@0.222/type-by-extension": "jsr:@std/media-types@0.223.0/type-by-extension" or "jsr:/@std/media-types@0.222/": "jsr:/@std/media-types@0.223.0/" (not 100% sure on this, try it with and without the / after the jsr: scheme)

I have a similar case where a package is using older versions of @std/path, I can dedupe with the following:

"jsr:@std/path@0.213": "jsr:@std/path@^0.223.0"

oscarotero commented 4 months ago

Thanks @jollytoad I can confirm that the following import map does the job:

{
  "imports": {
    "jsr:@std/media-types@0.222/type-by-extension": "jsr:@std/media-types@0.223.0/type-by-extension"
  }
}

But I think it's a very unfortunate behavior. If JSR dependencies can have different specifiers for the same file, it's really painful to work with import maps.

dsherret commented 4 months ago

What seems like a bug here is that this doesn't seem to work:

"jsr:@std/media-types@0.222": "jsr:@std/media-types@0.223.0"

But I think it's a very unfortunate behavior. If JSR dependencies can have different specifiers for the same file, it's really painful to work with import maps.

Yeah, there needs to be a better way here.

oscarotero commented 4 months ago

An annoying thing (the main reason I hate exports feature of JSR packages) is the file is imported as /type-by-extension (with dashes) but deno info shows /type_by_extension.ts (with extension and underscores) which makes even more complicated to figure out what's the file that need to be mapped.

And another inconsitency: it seems that the scope must be defined in http format and the imports in jsr format.

// This works
{
  "scopes": {
    "https://jsr.io/@oak/commons/0.10.1/media_types.ts": {
      "jsr:@std/media-types@0.222/type-by-extension": "jsr:@std/media-types@0.223.0/type-by-extension"
    }
  },
}

// This doesn't work
{
  "scopes": {
    "jsr:@oak/commons@0.10.1/media-types": {
      "jsr:@std/media-types@0.222/type-by-extension": "jsr:@std/media-types@0.223.0/type-by-extension"
    }
  },
}

// This neither
{
  "scopes": {
    "https://jsr.io/@oak/commons@0.10.1/media_types.ts": {
      "https://jsr.io/@std/media-types@0.222/type_by_extension.ts": "https://jsr.io/@std/media-types@0.223.0/type_by_extension.ts"
    }
  },
}