jspm / generator

JSPM Import Map Generator
Apache License 2.0
166 stars 21 forks source link

Pre-release version ranges downgrading #158

Closed zachsa closed 2 years ago

zachsa commented 2 years ago

Bug

JSPM Generator is producing an import map with the wrong maplibre-gl version when non-semantically version is specified, despite that the specified version (2.2.0-pre.3) does exist via the JSPM CDN

The package.json of the version I would like can be found here: https://ga.jspm.io/npm:maplibre-gl@2.2.0-pre.3/package.json

To Reproduce

In a new directory:

npm init
npm install maplibre-gl@2.2.0-pre.3
npm install @jspm/generator@1.0.0-beta.34

Create the following files

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset='utf-8'>
  <script src="index.js" type="module"></script>
</head>
</html>

index.js

import maplibre from 'maplibre-gl'
const x = new maplibre.Map()

jspm.js

import { Generator } from '@jspm/generator'
import { readFile, writeFile } from 'fs/promises'
import { pathToFileURL } from 'url'
import mkdirp from 'mkdirp'
import { dirname } from 'path'

const DEP = './index.html'
const TARGET = './output.html'

const generator = new Generator({
  mapUrl: pathToFileURL(TARGET),
  env: ['browser', 'production', 'module'],
  defaultProvider: 'jspm',
})

const htmlSource = await readFile(DEP, 'utf-8')
const pins = await generator.addMappings(htmlSource)
const html = await generator.htmlInject(htmlSource, {
  trace: true,
  pins,
  preload: false,
  integrity: false,
  esModuleShims: true,
})

mkdirp.sync(dirname(TARGET))
await writeFile(TARGET, html)

Generate the import map

node jspm.js

The output.html file shows the incorrectly resolved package version

<!DOCTYPE html>
<html>
<head>
  <meta charset='utf-8'>
  <!-- Generated by @jspm/generator - https://github.com/jspm/generator -->
  <script async src="https://ga.jspm.io/npm:es-module-shims@1.5.13/dist/es-module-shims.js" crossorigin="anonymous"></script>
  <script type="importmap">
  {
    "scopes": {
      "./": {
        "maplibre-gl": "https://ga.jspm.io/npm:maplibre-gl@2.1.9/dist/maplibre-gl.js"
      }
    }
  }
  </script>
  <script src="index.js" type="module"></script>
</head>
</html>
guybedford commented 2 years ago

I cannot reproduce this.

Here's my test case:

package.json

{
  "dependencies": {
    "maplibre-gl": "2.0.0-pre.3"
  }
}

test.js

import { Generator } from '@jspm/generator';

const generator = new Generator({
  mapUrl: import.meta.url
});

await generator.pin('maplibre-gl');

console.log(generator.getMap());

The resultant import map shows the correct prerelease version of maplibre-gl for me.

zachsa commented 2 years ago

Strange. Just tried deleting the JSPM cache and I still get the old version in the newly generated import map

guybedford commented 2 years ago

Please share your exact package.json contents.

zachsa commented 2 years ago

I'm using an unreleased version of JSPM - the files are here: https://github.com/SAEON/somisana/tree/stable/web/%40jspm/generator

And here is the JSPM code (called via a chomp task):

import { Generator } from '@jspm/generator'
import { readFile, writeFile } from 'fs/promises'
import { pathToFileURL } from 'url'
import mkdirp from 'mkdirp'
import { dirname } from 'path'

const NODE_ENV = process.env.NODE_ENV || 'development'
const DEP = process.env.DEP
const TARGET = process.env.TARGET

const generator = new Generator({
  mapUrl: pathToFileURL(TARGET),
  env: ['browser', NODE_ENV, 'module'],
  defaultProvider: 'jspm',
})

const htmlSource = await readFile(DEP, 'utf-8')
const pins = await generator.addMappings(htmlSource)
const html = await generator.htmlInject(htmlSource, {
  trace: true,
  pins,
  preload: false,
  integrity: false,
  esModuleShims: true,
})

mkdirp.sync(dirname(TARGET))
await writeFile(TARGET, html)
{
  "name": "somisana-web",
  "version": "1.0.0",
  "type": "module",
  "description": "SOMISANA web stack",
  "author": "zd.smith@saeon.nrf.ac.za",
  "dependencies": {
    "@apollo/client": "^3.6.9",
    "@arcgis/core": "^4.24.7",
    "@emotion/cache": "^11.10.1",
    "@emotion/react": "^11.10.0",
    "@emotion/server": "^11.10.0",
    "@emotion/styled": "^11.10.0",
    "@graphql-tools/schema": "^9.0.0",
    "@jspm/generator": "file:@jspm/generator",
    "@koa/router": "^12.0.0",
    "@mdi/js": "^7.0.96",
    "@mui/material": "^5.10.0",
    "@mui/system": "^5.10.0",
    "@node-loader/core": "^2.0.0",
    "@node-loader/import-maps": "^1.1.0",
    "@rollup/plugin-replace": "^4.0.0",
    "@swc/cli": "^0.1.57",
    "@swc/core": "^1.2.224",
    "apollo-server-core": "^3.10.0",
    "apollo-server-koa": "^3.10.0",
    "browserslist": "^4.21.3",
    "cookie": "^0.5.0",
    "dataloader": "^2.1.0",
    "dotenv": "^16.0.1",
    "es-module-shims": "^1.5.13",
    "graphql": "^16.5.0",
    "graphql-type-json": "^0.3.2",
    "install": "^0.13.0",
    "koa": "^2.13.4",
    "koa-bodyparser": "^4.3.0",
    "koa-compress": "^5.1.0",
    "koa-mount": "^4.0.0",
    "koa-static": "^5.0.0",
    "make-fetch-happen": "^10.2.0",
    "maplibre-gl": "^2.2.0-pre.3",
    "mkdirp": "^1.0.4",
    "mongodb": "^4.8.1",
    "prettier": "^2.7.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-markdown": "^8.0.3",
    "react-router-dom": "^6.3.0",
    "rimraf": "^3.0.2",
    "rollup": "^2.77.2",
    "rollup-plugin-import-css": "^3.0.3",
    "rollup-plugin-swc": "^0.2.1",
    "sift": "^16.0.0",
    "swc-loader": "^0.2.3",
    "wkt": "^0.1.1"
  }
}
zachsa commented 2 years ago

Actually - v2.2 was released a few hours ago, but that is not available via JSPM yet. What is the average build time to get a new version of a library when published to NPM?

I think the new version should be here - https://ga.jspm.io/npm:maplibre-gl@2.2.0/dist/maplibre-gl.js

guybedford commented 2 years ago

@zachsa I don't see "maplibre-gl": "2.0.0-pre.3" in your package.json dependencies. Therefore you don't have any version range constraint for JSPM to pick up. You need to use --save or --save-dev or --save-optional when installing with npm to reflect that for JSPM generator.

As for the generator CDN update, that should be available now.

zachsa commented 2 years ago

It is there - see the image. I realize that the version isn't pegged to be the exact version, but the version I specify is more recent than the one that gets used. I would not expect this to happen

image

guybedford commented 2 years ago

Right but ^2.0.0-pre.3 will match the latest 2.x version. Pre-release semver ranges don't bind the prerelease if there is a later stable version.

guybedford commented 2 years ago

Basically if you make the version exact it should work.

But actually yeah the fact that it's "downgrading" is very much a bug.... I will leave this open to track.

zachsa commented 2 years ago

Right. I see, though this morning it should have picked up 2.2.0 regardless of whether that release existed via the CDN.

In this case my workflow is:

I would also be happy to move off package.json by the way. And I don't mind installing packages manually as I use them. So I wouldn't mind for example:

jspm install @mui/material/Typography
jspm install @mui/material/Container
... etc.

And then the idea is that this would replace the dependencies in package.json and package-lock.json with deps specified via an import map. Then instead of generating the import map on every save, I would just refer to the import map.

... Actually... I would much prefer this to optimizing import map generation.

The reason I CAN'T do this at the moment (and the reason that I have to recreate import maps for every HTML file on every save) is that I can't install individual packages: npm install @mui/material/Typography fails, since I ACTUALLY have to install the whole library - npm install @mui/material. And then the generator won't know what packages to include in the import map until I run it. So I run it on every save in case I add a new package import just as I work.

zachsa commented 2 years ago

... Actually. this is already possible isn't it?

await generator.install('lit@2/decorators.js');

So I could theoretically have a file that lists my dependencies (including subpaths) that my jspm generator code then reads and installs to an import map. This then only has to run when jspmfile (TOML format) changes?

... except that I would much rather be able to just go jspm install @mui/material/Typography to update an import map directly.

Is there a JSPM CLI in the works?

guybedford commented 2 years ago

Fixed in https://github.com/jspm/generator/pull/163. Thanks for reporting!