esm.dev 2.0.6 → 3.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.
package/README.md CHANGED
@@ -37,7 +37,8 @@ Once the above is running point your ESM modules to `localhost:3000`:
37
37
  }
38
38
  </script>
39
39
  <script type="module">
40
- import Package1 from 'package1'
40
+ import Package1 from 'package-1'
41
+ import React from 'react
41
42
  // ...
42
43
  </script>
43
44
  ```
@@ -1,7 +1,8 @@
1
+ import { Command } from 'clipanion';
1
2
  import { ESMDevCommand } from './ESMDevCommand.js';
2
3
  export class RepublishCommand extends ESMDevCommand {
3
4
  static paths = [['republish']];
4
- static usage = this.Usage({
5
+ static usage = Command.Usage({
5
6
  description: 'Removes the references, of given packages, from the ESM server and registry and republishes.',
6
7
  });
7
8
  async execute() {
@@ -2,9 +2,10 @@ import { ESMDevCommand } from './ESMDevCommand.js';
2
2
  import { Servable } from './mixins/Servable.js';
3
3
  import { Watchable } from './mixins/Watchable.js';
4
4
  import { ESMServed } from './mixins/ESMServed.js';
5
+ import { Command } from 'clipanion';
5
6
  export class StartCommand extends Servable(Watchable(ESMServed(ESMDevCommand))) {
6
7
  static paths = [['start']];
7
- static usage = this.Usage({
8
+ static usage = Command.Usage({
8
9
  description: 'Runs a server and concurrently watches a file system',
9
10
  });
10
11
  async execute() {
@@ -3,7 +3,7 @@ import { RegistrySpecific } from './mixins/RegistrySpecific.js';
3
3
  import { Retryable } from './mixins/Retryable.js';
4
4
  export class WaitForRegistryCommand extends Retryable(RegistrySpecific(Command)) {
5
5
  static paths = [['wait-for-registry'], ['wfr']];
6
- static usage = this.Usage({
6
+ static usage = Command.Usage({
7
7
  description: 'wait for the registry to be online',
8
8
  });
9
9
  async execute() {
@@ -1,8 +1,9 @@
1
+ import { Command } from 'clipanion';
1
2
  import { ESMDevCommand } from './ESMDevCommand.js';
2
3
  import { Watchable } from './mixins/Watchable.js';
3
4
  export class WatchCommand extends Watchable(ESMDevCommand) {
4
5
  static paths = [['watch']];
5
- static usage = this.Usage({
6
+ static usage = Command.Usage({
6
7
  description: 'Watches directories and republishes on changes',
7
8
  });
8
9
  async execute() {
@@ -1,17 +1,31 @@
1
1
  import { queue } from './queue.js';
2
2
  import { createServer } from 'node:http';
3
3
  import httpProxy from 'http-proxy';
4
+ import { until } from './until.js';
5
+ /**
6
+ * esm.sh (v137+) can respond with a transient 500 "Storage error, please try
7
+ * again" on the first request after a package is republished: its in-memory
8
+ * build-meta cache still points at a build output that was just invalidated.
9
+ * The following request rebuilds the module and succeeds.
10
+ */
11
+ const TRANSIENT_ESM_ERROR = 'Storage error, please try again';
4
12
  export async function serve(port, esmOrigin) {
5
- const proxy = httpProxy.createProxyServer();
13
+ const proxy = httpProxy.createProxyServer({
14
+ followRedirects: true,
15
+ target: esmOrigin,
16
+ });
6
17
  const { promise, resolve } = Promise.withResolvers();
7
18
  const server = createServer((req, res) => {
8
- queue(() => new Promise((resolve, reject) => {
9
- console.info('Proxying', req.url);
10
- req.on('error', reject);
11
- res.on('error', reject);
12
- res.on('close', resolve);
13
- proxy.web(req, res, { followRedirects: true, target: esmOrigin });
14
- })).catch((error) => {
19
+ queue(async () => {
20
+ await waitForESMBuild(esmOrigin, req);
21
+ await new Promise((resolve, reject) => {
22
+ console.info('Proxying', req.url);
23
+ req.on('error', reject);
24
+ res.on('error', reject);
25
+ res.on('close', resolve);
26
+ proxy.web(req, res);
27
+ });
28
+ }).catch((error) => {
15
29
  res.statusCode = 500;
16
30
  res.setHeader('Content-Type', 'application/json; charset=utf-8');
17
31
  res.write(JSON.stringify(error));
@@ -32,3 +46,22 @@ export async function serve(port, esmOrigin) {
32
46
  });
33
47
  });
34
48
  }
49
+ /**
50
+ * Wait for esm.sh to serve a freshly (re)built module before proxying, so a
51
+ * client never observes the transient {@link TRANSIENT_ESM_ERROR} that esm.sh
52
+ * emits while healing its build cache after a republish.
53
+ */
54
+ async function waitForESMBuild(esmOrigin, req) {
55
+ if (req.method && req.method !== 'GET' && req.method !== 'HEAD')
56
+ return;
57
+ const url = new URL(req.url ?? '/', esmOrigin);
58
+ await until({
59
+ interval: 100,
60
+ timeout: 10_000,
61
+ async try(signal) {
62
+ const response = await fetch(url, { method: 'GET', signal });
63
+ const body = await response.text();
64
+ return !(response.status === 500 && body.trim() === TRANSIENT_ESM_ERROR);
65
+ },
66
+ });
67
+ }
package/dist/lib/watch.js CHANGED
@@ -16,9 +16,9 @@ export async function watch(packagePath, opts) {
16
16
  console.info('Watching', packageRoot);
17
17
  const abortController = new AbortController();
18
18
  const { signal } = abortController;
19
- const republishPackage = (filename = '') => {
19
+ const republishPackage = async (filename = '') => {
20
20
  console.info(`Change detected at ${packageRoot}/${filename}`);
21
- return republish(packageRoot, opts).catch(console.error);
21
+ await republish(packageRoot, opts).catch(console.error);
22
22
  };
23
23
  try {
24
24
  await queue(republishPackage, signal);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esm.dev",
3
- "version": "2.0.6",
3
+ "version": "3.0.0",
4
4
  "description": "TypeScript library template",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -21,30 +21,29 @@
21
21
  },
22
22
  "repository": {
23
23
  "type": "git",
24
- "url": "git+https://github.com/johngeorgewright/esm.dev.git"
24
+ "url": "git+https://github.com/jg-wright/esm.dev.git"
25
25
  },
26
26
  "keywords": [],
27
27
  "author": "John Wright <johngeorge.wright@gmail.com>",
28
28
  "license": "MIT",
29
29
  "bugs": {
30
- "url": "https://github.com/johngeorgewright/esm.dev/issues"
30
+ "url": "https://github.com/jg-wright/esm.dev/issues"
31
31
  },
32
- "homepage": "https://github.com/johngeorgewright/esm.dev#readme",
32
+ "homepage": "https://github.com/jg-wright/esm.dev#readme",
33
33
  "devDependencies": {
34
- "@commitlint/cli": "19.8.1",
35
- "@commitlint/config-conventional": "19.8.1",
36
- "@commitlint/types": "19.8.1",
37
- "@types/http-proxy": "^1.17.16",
34
+ "@commitlint/cli": "21.2.1",
35
+ "@commitlint/config-conventional": "21.2.0",
36
+ "@commitlint/types": "21.2.0",
37
+ "@types/http-proxy": "^1.17.17",
38
38
  "@types/mustache": "^4.2.6",
39
- "@types/node": "^22.15.27",
40
- "@types/ramda": "^0.31.0",
39
+ "@types/node": "^24.11.0",
41
40
  "husky": "9.1.7",
42
- "lint-staged": "16.1.6",
43
- "prettier": "3.6.2",
44
- "rimraf": "6.0.1",
45
- "semantic-release": "^24.2.4",
46
- "typescript": "~5.8.3",
47
- "vitest": "^3.1.4"
41
+ "lint-staged": "17.0.8",
42
+ "prettier": "3.9.5",
43
+ "rimraf": "6.1.3",
44
+ "semantic-release": "25.0.5",
45
+ "typescript": "7.0.2",
46
+ "vitest": "4.1.10"
48
47
  },
49
48
  "lint-staged": {
50
49
  "*.{md,json,js,jsx,ts,tsx,yml,yaml}": [
@@ -54,21 +53,21 @@
54
53
  "dependencies": {
55
54
  "clipanion": "^4.0.0-rc.4",
56
55
  "clipanion-generator-command": "^1.3.1",
57
- "es-toolkit": "^1.39.10",
56
+ "es-toolkit": "^1.49.0",
58
57
  "escape-string-regexp": "^5.0.0",
59
- "glob": "^11.0.2",
58
+ "glob": "^13.0.6",
60
59
  "http-proxy": "^1.18.1",
61
- "ignore": "^7.0.4",
62
- "minimatch": "^10.0.1",
63
- "minipass": "^7.1.2",
60
+ "ignore": "^7.0.5",
61
+ "minimatch": "^10.2.5",
62
+ "minipass": "^7.1.3",
64
63
  "mustache": "^4.2.0",
65
64
  "npm": "^11.4.1",
66
- "ramda": "^0.31.0",
67
65
  "tslib": "^2.8.1",
68
66
  "typanion": "^3.14.0",
69
- "zx": "^8.5.4"
67
+ "update": "^0.7.4",
68
+ "zx": "^8.8.5"
70
69
  },
71
70
  "optionalDependencies": {
72
- "@rollup/rollup-linux-x64-musl": "^4.41.1"
71
+ "@rollup/rollup-linux-x64-musl": "^4.62.2"
73
72
  }
74
73
  }
@@ -1,6 +1,6 @@
1
1
  services:
2
2
  esm.dev:
3
- image: ghcr.io/johngeorgewright/esm.dev:latest
3
+ image: ghcr.io/jg-wright/esm.dev:latest
4
4
  depends_on:
5
5
  - esm
6
6
  - npm
@@ -34,8 +34,8 @@ services:
34
34
  ports:
35
35
  - '{{esmPort}}:8080'
36
36
  volumes:
37
- - {{esmStoragePath}}/npm:/esmd/npm
38
- - {{esmStoragePath}}/storage:/esmd/storage
37
+ - {{esmStoragePath}}/npm:/esm/npm
38
+ - {{esmStoragePath}}/storage:/esm/storage
39
39
 
40
40
  npm:
41
41
  image: verdaccio/verdaccio:latest