importmap-plus 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +420 -0
- data/README.md +44 -430
- data/app/helpers/importmap/importmap_tags_helper.rb +3 -0
- data/lib/importmap/batch_resolver.rb +133 -0
- data/lib/importmap/commands.rb +546 -43
- data/lib/importmap/doctor.rb +331 -0
- data/lib/importmap/early_hints.rb +50 -0
- data/lib/importmap/engine.rb +3 -0
- data/lib/importmap/esm_run.rb +118 -0
- data/lib/importmap/graph.rb +126 -0
- data/lib/importmap/import_scanner.rb +53 -0
- data/lib/importmap/integrity.rb +25 -0
- data/lib/importmap/map.rb +38 -1
- data/lib/importmap/module_inspector.rb +200 -0
- data/lib/importmap/npm.rb +37 -14
- data/lib/importmap/package_graph.rb +299 -0
- data/lib/importmap/packager.rb +432 -117
- data/lib/importmap/provider_chain.rb +89 -0
- data/lib/importmap/vendored_graph.rb +214 -0
- data/lib/importmap/version.rb +1 -1
- metadata +18 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a89ba9297f9e04e1f3a892ea319d509ce9300789f648327c3b4b1cf72c0951d7
|
|
4
|
+
data.tar.gz: c088e5ab5732c9f132bfa63a60d2a7d9243ac85690670e1a040e3658fc1fb091
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 81f2d28ee6c2d724917e338451d4a0f2baef86feb1bcc5477feca8114f13213787d9164b6befc8e7e02cf24e5ec0f810e13d05195be4e27c689bc70db5fd9311
|
|
7
|
+
data.tar.gz: 3cbd693b24887409203b8f75294798c3ee4b08dec82a90eb404de2a24e7ba7f273d4babd48a72c3a1608f8f263b4804b27dcfbf624edbb69252ea8ea6b346d63
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,425 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`pin` resolves the version on the npm registry, then falls back from jspm
|
|
8
|
+
to esm.run to jsDelivr.** jspm is the default CDN and was the only one `pin`
|
|
9
|
+
asked, so a package its generator can't build — `mermaid@10.6.0` fails on a
|
|
10
|
+
cytoscape subpath, `@mui/material@5.15.0` on a module it can't find — ended
|
|
11
|
+
in `Couldn't find any packages`, and a bare `pin foo` took whatever version
|
|
12
|
+
jspm had indexed, which lags npm. A package that names no CDN of its own is
|
|
13
|
+
now asked of each in turn, and its version is settled against the registry
|
|
14
|
+
before any of them is asked:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
$ bin/importmap pin mermaid
|
|
18
|
+
Resolved "mermaid" to 10.6.0 from the npm registry
|
|
19
|
+
jspm couldn't resolve "mermaid@10.6.0" (No './dist/cytoscape.umd.js' exports subpath defined in cytoscape@3.34.3); trying esm.run
|
|
20
|
+
Pinning "mermaid" to vendor/javascript/mermaid.js via download from https://cdn.jsdelivr.net/npm/mermaid@10.6.0/+esm
|
|
21
|
+
```
|
|
22
|
+
```ruby
|
|
23
|
+
pin "mermaid" # @10.6.0 (esm.run)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The pin comment already records a CDN that isn't jspm, so `update` and
|
|
27
|
+
`pristine` stay on esm.run from then on with no new state anywhere. An
|
|
28
|
+
explicit `--from`, and a provider a pin already names, are choices somebody
|
|
29
|
+
made: those are asked once and never fall back. When no CDN has the package,
|
|
30
|
+
each one's reason is printed and the summary names all three.
|
|
31
|
+
- **A download that isn't an ES module is kept remote instead of vendored.**
|
|
32
|
+
The CDNs that serve a package's own `dist` file hand back the UMD bundle
|
|
33
|
+
plenty of packages still publish; vendored into an import map it runs and
|
|
34
|
+
exports nothing, so `import x from "pkg"` fails to link in the browser and
|
|
35
|
+
nowhere else. `pin google-libphonenumber --from jsdelivr` now keeps the pin
|
|
36
|
+
remote and records `(remote: not an ES module)`. `--vendor` downloads it
|
|
37
|
+
anyway, and the default `pin` never sees it, since jspm converts the package.
|
|
38
|
+
- **The CDN's own reason reaches the terminal.** jspm answers 401 with its
|
|
39
|
+
generator's message in the body, which `pin` discarded: `Couldn't find any
|
|
40
|
+
packages in ["mermaid@10.6.0"] on jspm` said nothing about what went wrong.
|
|
41
|
+
That message is now printed with the sentence, whichever CDN was asked.
|
|
42
|
+
|
|
43
|
+
- **`pin` keeps a package remote when its file can't stand alone, and says
|
|
44
|
+
why.** A vendored package is one file served under a digested asset path,
|
|
45
|
+
but plenty of packages ship a file that imports a sibling by relative path,
|
|
46
|
+
spawns a `Worker`, reads `import.meta.url` or fetches a `.wasm` binary —
|
|
47
|
+
every one of those 404s in the browser, and importmap-rails vendors it
|
|
48
|
+
anyway. `pin` now reads the download before writing anything to
|
|
49
|
+
`vendor/javascript`; a file that needs more than itself is pinned to its CDN
|
|
50
|
+
URL and the reason goes on the pin:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
$ bin/importmap pin fflate@0.8.2
|
|
54
|
+
Pinning "fflate" to https://ga.jspm.io/npm:fflate@0.8.2/esm/browser.js (kept remote: workers)
|
|
55
|
+
```
|
|
56
|
+
```ruby
|
|
57
|
+
pin "fflate", to: "https://ga.jspm.io/npm:fflate@0.8.2/esm/browser.js" # @0.8.2 (remote: workers)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The pin then behaves like any other remote pin — `pin` and `update`
|
|
61
|
+
re-resolve it from the same CDN and keep the reason, `pristine` skips it.
|
|
62
|
+
`pin --vendor` downloads the package anyway and records `(vendored)` on the
|
|
63
|
+
pin, so a later `update` doesn't undo the override; it also converts a pin
|
|
64
|
+
that was kept remote back to a download. Nothing an app already vendored is
|
|
65
|
+
rewritten on its own — `pristine` redownloads those pins as it always has —
|
|
66
|
+
but the next `pin` or `update` that touches one re-resolves it, and a package
|
|
67
|
+
whose file can't stand alone converts to a remote pin then. That is the fix
|
|
68
|
+
arriving, not a surprise: the vendored file it replaces was already 404ing
|
|
69
|
+
for its siblings. pdf.js is the package most apps will see this on — see
|
|
70
|
+
the upgrading page for what to expect and how `--vendor` puts it back.
|
|
71
|
+
|
|
72
|
+
- **A pin that stays remote carries a subresource-integrity hash.** A vendored
|
|
73
|
+
file is served by the app; a remote pin is fetched from a CDN on every page
|
|
74
|
+
load with nothing checking the bytes, and importmap-rails never wrote an
|
|
75
|
+
`integrity:` value for one — the hash had to be computed by hand and redone
|
|
76
|
+
on every update. `pin --remote`, and a package [kept remote] because its file
|
|
77
|
+
can't stand alone, now fetch the URL they just resolved, hash it and write it
|
|
78
|
+
with the pin:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
$ bin/importmap pin md5@2.2.0 --remote
|
|
82
|
+
Pinning "md5" to https://ga.jspm.io/npm:md5@2.2.0/md5.js (integrity sha384-+wqk6m3DPZ6mVMgVZlXnGgDjDY2skGEZ3U9tBnRHiPJXLRLKBmYkKlX2urz9T61b)
|
|
83
|
+
```
|
|
84
|
+
```ruby
|
|
85
|
+
pin "md5", to: "https://ga.jspm.io/npm:md5@2.2.0/md5.js", integrity: "sha384-+wqk6m3DPZ6mVMgVZlXnGgDjDY2skGEZ3U9tBnRHiPJXLRLKBmYkKlX2urz9T61b"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The hash is `sha384` of the bytes the CDN served, computed here rather than
|
|
89
|
+
asked of any one CDN, so jspm, esm.run, jsDelivr, unpkg, esm.sh and skypack
|
|
90
|
+
are all covered by one code path. `update` and a later `pin` fetch the new
|
|
91
|
+
URL and rewrite the hash, so a pin never carries the hash of a file it no
|
|
92
|
+
longer points at — where before an explicit hash was simply dropped.
|
|
93
|
+
`enable_integrity!` in `config/importmap.rb` is still what puts the value in
|
|
94
|
+
the import map and on the preload link; `--no-integrity` skips the fetch for
|
|
95
|
+
a run, and `integrity: false` on a pin stays off for good. Vendored downloads
|
|
96
|
+
are unaffected: `integrity: true`, the default, already computes theirs
|
|
97
|
+
through the asset pipeline.
|
|
98
|
+
|
|
99
|
+
[kept remote]: https://importmap-plus.zoolutions.llc/docs/pinning
|
|
100
|
+
|
|
101
|
+
- **`pin` vendors a package's whole file graph, so a chunked package no longer
|
|
102
|
+
needs a CDN at runtime.** A package whose entry imports a sibling by relative
|
|
103
|
+
path — `@popperjs/core`, `date-fns`, `lodash-es`, and every package built by
|
|
104
|
+
a bundler that splits chunks — could not be vendored: the browser resolves
|
|
105
|
+
`./enums.js` against a digested asset path, and neither Propshaft nor
|
|
106
|
+
Sprockets rewrites `import` statements. Those packages were [kept remote].
|
|
107
|
+
`pin` now downloads the closed set of files the entry reaches, rewrites every
|
|
108
|
+
relative specifier to a bare key, and maps the directory with one
|
|
109
|
+
`pin_all_from` line:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
$ bin/importmap pin @popperjs/core@2.11.8
|
|
113
|
+
Pinning "@popperjs/core" to vendor/javascript/@popperjs/core.js via download from https://ga.jspm.io/npm:@popperjs/core@2.11.8/lib/index.js (with 47 sibling files)
|
|
114
|
+
```
|
|
115
|
+
```ruby
|
|
116
|
+
pin "@popperjs/core", to: "@popperjs--core.js" # @2.11.8
|
|
117
|
+
pin_all_from "vendor/javascript/@popperjs--core", under: "@popperjs/core", to: "@popperjs--core" # @2.11.8 (graph of @popperjs/core)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The entry keeps the flat file and the plain comment it always had, so
|
|
121
|
+
`update`, `outdated`, `lock` and `pristine` read it exactly as before, and a
|
|
122
|
+
`config/importmap.rb` written this way still parses under importmap-rails.
|
|
123
|
+
Bare specifiers are untouched, and a file that is another pin's own entry is
|
|
124
|
+
rewritten to that pin's key rather than copied, so the browser evaluates each
|
|
125
|
+
module once. (Two pins of one package do each carry their own copy of a chunk
|
|
126
|
+
they share; both write it under the same key, so one of the copies is what
|
|
127
|
+
every importer gets and the other is dead weight.) `unpin` takes the directory and the line with the pin,
|
|
128
|
+
`pristine` rebuilds the directory, `pin --minify` minifies every file in it,
|
|
129
|
+
and `pin --vendor` downloads the entry on its own and drops the directory and
|
|
130
|
+
line it had. A directory the import map doesn't map as one of ours is the
|
|
131
|
+
app's: `pin` says so, writes nothing rather than renaming it away, and exits
|
|
132
|
+
non-zero — as it does when a CDN fails partway through a crawl, where the pin
|
|
133
|
+
and the files it had are left exactly as they were.
|
|
134
|
+
|
|
135
|
+
Only jspm, jsDelivr and unpkg are crawled — their URLs say where a package's
|
|
136
|
+
directory ends. A graph that can't be taken over whole (a relative path that
|
|
137
|
+
climbs out of the package, a sibling the CDN hasn't got, a sibling that isn't
|
|
138
|
+
JavaScript, two files that would collapse to one key) keeps the whole package
|
|
139
|
+
remote, as does a download that also spawns a worker, reads
|
|
140
|
+
`import.meta.url`, computes an `import()` or names a `.wasm` file. A pin
|
|
141
|
+
importmap-plus had kept remote for its relative imports is converted back to
|
|
142
|
+
a download by the next `pin` or `update`, on the CDN its URL names.
|
|
143
|
+
|
|
144
|
+
Two things `pin` says out loud rather than doing quietly: a key some other
|
|
145
|
+
package's graph already maps (a directory wins over a pin, so the pin would
|
|
146
|
+
do nothing), and a second directory mapping a package one already maps at
|
|
147
|
+
another version (a file they share resolves to one of them).
|
|
148
|
+
|
|
149
|
+
- **`bin/importmap doctor` checks an app's import map and vendored files,
|
|
150
|
+
offline.** `audit` and `outdated` ask the npm registry about your packages;
|
|
151
|
+
nothing asked whether the map still matched the files in the repo. A pin
|
|
152
|
+
whose file had gone missing, a vendored file importing a bare specifier
|
|
153
|
+
nobody pinned, a vendored file still importing the siblings it was downloaded
|
|
154
|
+
beside, a CommonJS bundle a CDN handed back — each of those said so in the
|
|
155
|
+
browser and nowhere else. `doctor` boots the app and reports them:
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
$ bin/importmap doctor
|
|
159
|
+
error pin "not_there" → nowhere.js: no such asset
|
|
160
|
+
error vendor/javascript/shoelace.js imports "lit/decorators.js", which isn't pinned
|
|
161
|
+
error vendor/javascript/popper.js imports "./enums.js" by relative path — run bin/importmap pin @popperjs/core to vendor its files
|
|
162
|
+
warning vendor/javascript/old-lib.js isn't pinned by anything
|
|
163
|
+
warning "@hotwired/turbo" and "@hotwired/turbo-rails" both resolve to turbo.min.js
|
|
164
|
+
3 errors, 2 warnings
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Errors exit 1, so it belongs in CI beside `audit` and `outdated`; warnings —
|
|
168
|
+
a file nothing serves, including a `.mjs` that `pin_all_from` never picks up,
|
|
169
|
+
and two keys on one file or one package vendored at two versions — leave the
|
|
170
|
+
exit status alone. It reports and never edits: `pin`, `unpin` and `pristine`
|
|
171
|
+
are what fix what it finds.
|
|
172
|
+
|
|
173
|
+
`--online` adds the one check that needs the network, fetching every remote
|
|
174
|
+
pin to report one the CDN no longer serves and an `integrity:` hash that
|
|
175
|
+
doesn't match the bytes it does serve. Every other check reads only the map,
|
|
176
|
+
the asset paths and the files on disk, so the default is fast and can't fail
|
|
177
|
+
because a CDN is having a bad afternoon.
|
|
178
|
+
|
|
179
|
+
- **`config.importmap.preload_strategy = :reachable` preloads what the entry
|
|
180
|
+
point actually reaches.** Every pin with `preload: true` gets a modulepreload
|
|
181
|
+
link on every page, so a package the app only loads with `import()` is
|
|
182
|
+
fetched up front anyway unless someone writes `preload: false` on it — and on
|
|
183
|
+
everything it depends on, and keeps that list right as the package changes.
|
|
184
|
+
An app on this gem carried the comment "imported only by apexcharts.js, which
|
|
185
|
+
is itself lazy. Without it, 1.1 MB was preloaded on every page."
|
|
186
|
+
|
|
187
|
+
The import graph already knows. `app/javascript`, `vendor/javascript` and
|
|
188
|
+
every `pin_all_from` directory are files on disk, and their `import`
|
|
189
|
+
statements name pin keys:
|
|
190
|
+
|
|
191
|
+
```ruby
|
|
192
|
+
# config/application.rb
|
|
193
|
+
config.importmap.preload_strategy = :reachable
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
`javascript_importmap_tags "application"` now emits a link only for the pins
|
|
197
|
+
`application` reaches through **static** imports, however deep. A dynamic
|
|
198
|
+
`import()` is the lazy boundary and contributes nothing — preloading its
|
|
199
|
+
target is the deferral the app asked for, undone. A pin naming an entry point
|
|
200
|
+
(`preload: "admin"`) is preloaded whether or not the graph reaches it, which
|
|
201
|
+
is the escape hatch for a specifier no regex can see; `preload: false` stays
|
|
202
|
+
off either way.
|
|
203
|
+
|
|
204
|
+
Nothing new happens on the request path: the files are the ones the asset
|
|
205
|
+
pipeline already serves, read once per import map cache generation and
|
|
206
|
+
dropped by the same sweeper that drops the rendered map when a `.js` file
|
|
207
|
+
changes. The default `:all` — upstream's behaviour, one link per
|
|
208
|
+
`preload: true` pin — is unchanged and never opens a file.
|
|
209
|
+
|
|
210
|
+
- **`javascript_importmap_tags` sends its modulepreload links as 103 Early
|
|
211
|
+
Hints.** A modulepreload link is markup, so the browser can only act on it
|
|
212
|
+
once the HTML has streamed far enough to be parsed — the whole module graph
|
|
213
|
+
waits on the response. The same list now goes out ahead of it as a `Link`
|
|
214
|
+
header, and the fetches start while the app is still rendering:
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
HTTP/1.1 103 Early Hints
|
|
218
|
+
Link: </assets/application-abc.js>; rel=modulepreload, </assets/@hotwired--stimulus-def.js>; rel=modulepreload
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Exactly the modules the tags preload, so `preload: false`, an entry point's
|
|
222
|
+
own list and `preload_strategy = :reachable` all narrow the hinted set with
|
|
223
|
+
the tags. No `integrity` parameter: browsers don't honour one on a `Link`
|
|
224
|
+
header, and the tag in the body still carries it.
|
|
225
|
+
|
|
226
|
+
This is what Rails' own `javascript_include_tag` and `stylesheet_link_tag`
|
|
227
|
+
already do, and it needs what they need — a server that puts
|
|
228
|
+
`rack.early_hints` in the env, which Puma does with `early_hints true`. On a
|
|
229
|
+
server without it, `send_early_hints` is a no-op and nothing changes. Off
|
|
230
|
+
with `config.importmap.early_hints = false`.
|
|
231
|
+
|
|
232
|
+
### Changed
|
|
233
|
+
|
|
234
|
+
- **Everything this gem knows about esm.run lives in `Importmap::EsmRun`.**
|
|
235
|
+
The provider name, the bundle URL shapes, the rewrite that turns a bundle's
|
|
236
|
+
`/npm/dep@ver/+esm` imports into bare specifiers and the jsDelivr version
|
|
237
|
+
lookup were nine things in `Importmap::Packager`, which had grown to the
|
|
238
|
+
800-line ceiling with nowhere to put the next addition. Behaviour is
|
|
239
|
+
unchanged and no documented setting moved: `Importmap::Packager.esm_run_resolver`
|
|
240
|
+
still reads and writes the resolver, now on the new class. Only the `:nodoc:`
|
|
241
|
+
constants `Packager::ESM_RUN_*` are gone, as `Importmap::EsmRun::PROVIDER`,
|
|
242
|
+
`::CDN`, `::URL_REGEXP` and `::IMPORT_REGEXP`.
|
|
243
|
+
|
|
244
|
+
### Fixed
|
|
245
|
+
|
|
246
|
+
- **One package a CDN can't resolve no longer blocks — or silently moves — the
|
|
247
|
+
rest of the batch.** ([#32](https://github.com/zoolutions/importmap-plus/issues/32))
|
|
248
|
+
A CDN answers a batch of packages as a whole, so `bin/importmap update` with
|
|
249
|
+
three outdated packages reported `Couldn't find any packages in
|
|
250
|
+
["cheap-ruler", "mapbox-gl", "mermaid"] on jspm`, updated nothing and exited
|
|
251
|
+
0, because jspm's generator can't build `mermaid`. Commenting out the one
|
|
252
|
+
package let the other two through. A refused batch of more than one package
|
|
253
|
+
is now asked for one package at a time, along the path each would have taken
|
|
254
|
+
alone:
|
|
255
|
+
|
|
256
|
+
```
|
|
257
|
+
$ bin/importmap pin md5@2.2.0 mermaid@10.6.0
|
|
258
|
+
jspm couldn't resolve "md5@2.2.0", "mermaid@10.6.0" (No './dist/cytoscape.umd.js' exports subpath defined in cytoscape@3.34.3); asking for each on its own
|
|
259
|
+
Pinning "md5" to vendor/javascript/md5.js via download from https://ga.jspm.io/npm:md5@2.2.0/md5.js
|
|
260
|
+
jspm couldn't resolve "mermaid@10.6.0" (No './dist/cytoscape.umd.js' exports subpath defined in cytoscape@3.34.3); trying esm.run
|
|
261
|
+
Pinning "mermaid" to vendor/javascript/mermaid.js via download from https://cdn.jsdelivr.net/npm/mermaid@10.6.0/+esm
|
|
262
|
+
```
|
|
263
|
+
```ruby
|
|
264
|
+
pin "md5" # @2.2.0
|
|
265
|
+
pin "mermaid" # @10.6.0 (esm.run)
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Only the package the CDN refused travels the rest of the chain, so a healthy
|
|
269
|
+
package is never re-pinned from another CDN — and never has its provenance
|
|
270
|
+
comment rewritten — because a sibling failed. An explicit `--from`, or a
|
|
271
|
+
provider a pin records, still asks that one CDN and only that one, now once
|
|
272
|
+
per package. The batch stays the fast path: it is split only when it is
|
|
273
|
+
refused and holds more than one package.
|
|
274
|
+
|
|
275
|
+
`pin`, `update` and `pristine` now **exit 1** when a package was left
|
|
276
|
+
unresolved, so `bin/importmap update && git commit` can no longer commit an
|
|
277
|
+
import map that quietly missed a package. The packages that did resolve are
|
|
278
|
+
still written.
|
|
279
|
+
- **A CDN that fails mid-crawl leaves the pin alone.** Vendoring a graph makes
|
|
280
|
+
one request per file — 250 of them for `date-fns` — so a 503 that outlives
|
|
281
|
+
the retries is far likelier than it was for a single download. `pin` and
|
|
282
|
+
`pristine` report it (`Skipping "date-fns": Unexpected response code (503)`)
|
|
283
|
+
and change nothing, rather than taking it for "this package can't be
|
|
284
|
+
vendored" and converting a working pin to a remote one, which would delete
|
|
285
|
+
the very files that make it work.
|
|
286
|
+
- **`pristine` reports a package it can't restore and carries on.** It is the
|
|
287
|
+
repair command, and a pin whose graph the CDN no longer serves the way the
|
|
288
|
+
pin describes now raises where nothing used to — unrescued, that ended the
|
|
289
|
+
whole run with a backtrace and left every package after it unrestored. Each
|
|
290
|
+
one that fails is reported (`Couldn't restore "pdfjs-dist": it can't be
|
|
291
|
+
vendored as a single file (workers)`), the rest are restored, and the command
|
|
292
|
+
exits non-zero to say it didn't do all of it — as it does when a dependency
|
|
293
|
+
of an esm.run bundle, pinned on the way, had to be skipped.
|
|
294
|
+
- **A download the CDN encoded in a way Net::HTTP can't undo is fetched
|
|
295
|
+
again.** jspm answers some files with `content-encoding: br` whatever the
|
|
296
|
+
request advertises, and Net::HTTP decompresses gzip and deflate only:
|
|
297
|
+
`@popperjs/core@2.11.8/lib/utils/computeAutoPlacement.js` arrived as brotli
|
|
298
|
+
bytes, which read as invalid UTF-8 and took the source inspection down with
|
|
299
|
+
`ArgumentError: invalid byte sequence in UTF-8`. `pin` now repeats that one
|
|
300
|
+
request asking for an unencoded body. It doesn't ask up front: supplying an
|
|
301
|
+
`Accept-Encoding` at all stops Net::HTTP decoding the gzip it does
|
|
302
|
+
understand. Inherited from importmap-rails, which downloads the same way.
|
|
303
|
+
|
|
304
|
+
- **`Importmap::Packager::ServiceError` is a class again.** It was assigned
|
|
305
|
+
`Error.new(Error)` — an *instance* — so `rescue Packager::ServiceError`
|
|
306
|
+
raised `TypeError: class or module required for rescue clause`, and every
|
|
307
|
+
jspm service error arrived as a plain `Packager::Error`. Inherited from
|
|
308
|
+
importmap-rails, where it is still the case.
|
|
309
|
+
- **A failed download no longer deletes the file an app already has.**
|
|
310
|
+
`pin` and `pristine` removed `vendor/javascript/<package>.js` before
|
|
311
|
+
fetching, so a CDN that answered 500 — or, now, a file that can't be
|
|
312
|
+
vendored — left the app with no file at all. The existing file is replaced
|
|
313
|
+
only once the new one has arrived and been found fit to serve.
|
|
314
|
+
- **`update <package>` moves every pin of that package, not just the bare
|
|
315
|
+
one.** An app with `pin "pdfjs-dist"` and
|
|
316
|
+
`pin "pdfjs-dist/build/pdf.worker.min.mjs"` ran `update pdfjs-dist` and got
|
|
317
|
+
a new main file next to a worker still at the old version — the two are
|
|
318
|
+
built together and don't tolerate that. A package name now means every
|
|
319
|
+
key that carries it, the same set `outdated` reports and a bare `update`
|
|
320
|
+
moves; `update pdfjs-dist/build/pdf.worker.min.mjs` still means that one
|
|
321
|
+
key.
|
|
322
|
+
- **A subpath pin without a CDN in its comment resolves from the CDN its
|
|
323
|
+
package's pin names.** The worker pin above, written before provenance
|
|
324
|
+
existed, was sent to jspm — which can't resolve pdf.js at all — and
|
|
325
|
+
reported "Couldn't find any packages" on every update while the main pin
|
|
326
|
+
moved on from jsdelivr. Siblings pinned together come from the same place;
|
|
327
|
+
the next update records it on the pin. A pin answers for itself first — its
|
|
328
|
+
own comment, then its own `to:` URL — and only then does its package answer
|
|
329
|
+
for it, whether that pin is vendored, recording the CDN in its comment, or
|
|
330
|
+
remote, carrying it in the URL with no comment at all.
|
|
331
|
+
|
|
332
|
+
- **An array `preload:` survives a rewrite however it is quoted, and
|
|
333
|
+
`preload: []` stays `preload: []`.** The option was read back through
|
|
334
|
+
`JSON.parse`, so `pin 'md5', preload: ['admin']` — single quotes being a
|
|
335
|
+
supported pin shape everywhere else in this gem — took down every command
|
|
336
|
+
that reads a pin with `JSON::ParserError: unexpected character`. And
|
|
337
|
+
`preload: []` matched nothing at all, so `pin`, `update` and `pristine`
|
|
338
|
+
dropped it and quietly restored the `preload: true` default on a package the
|
|
339
|
+
app had asked to preload for no entry point. `config/importmap.rb` is Ruby,
|
|
340
|
+
not JSON: the entry points are scanned out of the literal now, and an empty
|
|
341
|
+
array is written back as one.
|
|
342
|
+
|
|
343
|
+
- **`pin --vendor` leaves a pin to a custom URL alone.** `--vendor` is meant to
|
|
344
|
+
override the check that refuses a download, not the URL an app chose to pin,
|
|
345
|
+
but it reached the vendoring path before the branch that skips custom URLs
|
|
346
|
+
could run: `bin/importmap pin md5 --vendor` against
|
|
347
|
+
`pin "md5", to: "https://cdn.example.com/md5.js"` downloaded md5 from
|
|
348
|
+
whichever CDN the spec resolved to and replaced the line with
|
|
349
|
+
`pin "md5" # @2.3.0 (vendored)`, without a word about the URL it had just
|
|
350
|
+
dropped. It now reports the skip the way a plain `pin` does and names the
|
|
351
|
+
flag in it. Moving such a pin on purpose is still `--from`, which re-resolves
|
|
352
|
+
it from the CDN you name.
|
|
353
|
+
|
|
354
|
+
## 1.1.0
|
|
355
|
+
|
|
356
|
+
### Added
|
|
357
|
+
|
|
358
|
+
- **Version locks.** `bin/importmap pin luxon@3.7.2 --lock`, or
|
|
359
|
+
`bin/importmap lock luxon` for a package already pinned, records the lock
|
|
360
|
+
in the version comment — `pin "luxon" # @3.7.2 (locked)` — and `update`
|
|
361
|
+
and a plain `pin` skip the package from then on, saying so. A remote pin
|
|
362
|
+
gains the comment too, carrying the version from its URL. `pin --force`
|
|
363
|
+
moves a locked package and keeps the lock at the new version; `--no-lock`
|
|
364
|
+
drops it; `bin/importmap unlock luxon` removes it without touching the
|
|
365
|
+
file. `pristine` still redownloads a locked vendored package, at the
|
|
366
|
+
locked version; remote pins are skipped as always. Only the packages
|
|
367
|
+
named on the command line are locked, never the dependencies a CDN
|
|
368
|
+
resolves with them, and a locked dependency stays where it is when the
|
|
369
|
+
package that needs it is pinned or updated.
|
|
370
|
+
- **`update` takes package names, `--all` and `--force`.**
|
|
371
|
+
`bin/importmap update luxon stimulus-use` re-pins just those, asking the
|
|
372
|
+
registry about them alone; `update --all` says explicitly what a bare
|
|
373
|
+
`update` has always done. A named package that is up to date, or has no
|
|
374
|
+
version to compare, is reported; a name with no pin stops the command
|
|
375
|
+
before anything is touched. `--force` updates locked packages too and
|
|
376
|
+
keeps each lock at the new version.
|
|
377
|
+
- **`outdated` shows locks.** A new Locked column marks packages held at
|
|
378
|
+
their version, and the command exits 1 only when an unlocked package is
|
|
379
|
+
outdated, so CI stays green for the versions the app chose.
|
|
380
|
+
- **`integrity: true` and `integrity: false` survive a rewrite.** An
|
|
381
|
+
`update`, `pristine` or `pin` used to drop the option; only an integrity
|
|
382
|
+
hash, which belongs to the old file, is still removed when the URL changes.
|
|
383
|
+
|
|
384
|
+
### Fixed
|
|
385
|
+
|
|
386
|
+
- **`update` no longer re-pins a package the registry couldn't be checked
|
|
387
|
+
for.** A package whose registry lookup came back unusable has no latest
|
|
388
|
+
version, so nothing established that it moved — but `update` re-pinned it
|
|
389
|
+
anyway, letting a bad answer re-resolve the pin against the CDN and carry
|
|
390
|
+
it to a version nobody asked for. Those packages are now reported —
|
|
391
|
+
`Couldn't check "md5": Unexpected error response 500: …` — and left where
|
|
392
|
+
they are; every other package still updates, and the command exits 1.
|
|
393
|
+
Inherited from importmap-rails, where a bare `update` has always behaved
|
|
394
|
+
this way.
|
|
395
|
+
- **`update` re-pins a subpath pin instead of appending a bare one.** The
|
|
396
|
+
registry answers about `photoswipe`, the import map pins
|
|
397
|
+
`photoswipe/lightbox`, and a bare `update` or `update --all` used to re-pin
|
|
398
|
+
the name it was answered with: the subpath pin stayed at its old version and
|
|
399
|
+
a `pin "photoswipe"` was appended beside it — vendored, since a fresh pin
|
|
400
|
+
has no provenance to say otherwise. Every key carrying an outdated package
|
|
401
|
+
is now re-pinned, and a package pinned under several keys moves all of them.
|
|
402
|
+
Only pins that declare a version take part, the same ones `outdated`
|
|
403
|
+
reports on, so an app file pinned under a package's namespace —
|
|
404
|
+
`pin "md5/helpers", to: "md5/helpers.js"` — is left alone. Inherited from
|
|
405
|
+
importmap-rails; `update photoswipe/lightbox` was fixed for the named form
|
|
406
|
+
in 1.1.0.
|
|
407
|
+
- **A remote subpath pin is re-resolved from the CDN it is on.** Moving
|
|
408
|
+
`pin "photoswipe/lightbox", to: "https://cdn.jsdelivr.net/npm/photoswipe@5.3.0/…"`
|
|
409
|
+
back onto jsDelivr asked for `photoswipe/lightbox@5.4.4`, a path no CDN
|
|
410
|
+
has, so `update` gave up with `Keeping "photoswipe/lightbox" pinned to …
|
|
411
|
+
(couldn't resolve it from jsdelivr)` and the pin never moved. The version
|
|
412
|
+
now goes where a CDN expects it, ahead of the subpath —
|
|
413
|
+
`photoswipe@5.4.4/lightbox`.
|
|
414
|
+
- **A registry that won't answer for one package no longer ends the run.**
|
|
415
|
+
A 404, a 5xx or a connection that kept resetting used to escape
|
|
416
|
+
`outdated_packages` once the retries were spent, so `outdated` and
|
|
417
|
+
`update` died with a backtrace and checked nothing else. The failure is
|
|
418
|
+
now recorded against that package alone — `outdated` prints the reason in
|
|
419
|
+
its Latest column, which is what the column was always for — and every
|
|
420
|
+
other package is still checked. `audit` is unchanged: a registry it can't
|
|
421
|
+
reach still fails the command outright.
|
|
422
|
+
|
|
3
423
|
## 1.0.0
|
|
4
424
|
|
|
5
425
|
First release of importmap-plus, a drop-in replacement for
|