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 +2 -1
- package/dist/commands/RepublishCommand.js +2 -1
- package/dist/commands/StartCommand.js +2 -1
- package/dist/commands/WaitForRegistryCommand.js +1 -1
- package/dist/commands/WatchCommand.js +2 -1
- package/dist/lib/server.js +41 -8
- package/dist/lib/watch.js +2 -2
- package/package.json +23 -24
- package/templates/init/docker-compose.yml.mustache +3 -3
package/README.md
CHANGED
|
@@ -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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
6
|
+
static usage = Command.Usage({
|
|
6
7
|
description: 'Watches directories and republishes on changes',
|
|
7
8
|
});
|
|
8
9
|
async execute() {
|
package/dist/lib/server.js
CHANGED
|
@@ -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(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
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": "
|
|
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/
|
|
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/
|
|
30
|
+
"url": "https://github.com/jg-wright/esm.dev/issues"
|
|
31
31
|
},
|
|
32
|
-
"homepage": "https://github.com/
|
|
32
|
+
"homepage": "https://github.com/jg-wright/esm.dev#readme",
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@commitlint/cli": "
|
|
35
|
-
"@commitlint/config-conventional": "
|
|
36
|
-
"@commitlint/types": "
|
|
37
|
-
"@types/http-proxy": "^1.17.
|
|
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": "^
|
|
40
|
-
"@types/ramda": "^0.31.0",
|
|
39
|
+
"@types/node": "^24.11.0",
|
|
41
40
|
"husky": "9.1.7",
|
|
42
|
-
"lint-staged": "
|
|
43
|
-
"prettier": "3.
|
|
44
|
-
"rimraf": "6.
|
|
45
|
-
"semantic-release": "
|
|
46
|
-
"typescript": "
|
|
47
|
-
"vitest": "
|
|
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.
|
|
56
|
+
"es-toolkit": "^1.49.0",
|
|
58
57
|
"escape-string-regexp": "^5.0.0",
|
|
59
|
-
"glob": "^
|
|
58
|
+
"glob": "^13.0.6",
|
|
60
59
|
"http-proxy": "^1.18.1",
|
|
61
|
-
"ignore": "^7.0.
|
|
62
|
-
"minimatch": "^10.
|
|
63
|
-
"minipass": "^7.1.
|
|
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
|
-
"
|
|
67
|
+
"update": "^0.7.4",
|
|
68
|
+
"zx": "^8.8.5"
|
|
70
69
|
},
|
|
71
70
|
"optionalDependencies": {
|
|
72
|
-
"@rollup/rollup-linux-x64-musl": "^4.
|
|
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/
|
|
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:/
|
|
38
|
-
- {{esmStoragePath}}/storage:/
|
|
37
|
+
- {{esmStoragePath}}/npm:/esm/npm
|
|
38
|
+
- {{esmStoragePath}}/storage:/esm/storage
|
|
39
39
|
|
|
40
40
|
npm:
|
|
41
41
|
image: verdaccio/verdaccio:latest
|