Skip to content

Commit

Permalink
Revert "Move the CLI script endpoint to /cli"
Browse files Browse the repository at this point in the history
  • Loading branch information
ije committed Aug 1, 2023
1 parent c7378d0 commit 69cdde7
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 122 deletions.
8 changes: 4 additions & 4 deletions CLI.deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export type Package = {
};

const importUrl = new URL(import.meta.url);
const VERSION = /^\/v\d+\//.test(importUrl.pathname)
const VERSION = /^\/v\d+\/?/.test(importUrl.pathname)
? importUrl.pathname.split("/")[1]
: "v{VERSION}";

Expand Down Expand Up @@ -173,9 +173,9 @@ async function init(_args: string[], _options: Record<string, string>) {
const tasks = config.tasks as Record<string, string> | undefined;
config.tasks = {
...tasks,
"esm:add": `deno run -A ${importUrl.origin}/${VERSION}/cli add`,
"esm:update": `deno run -A ${importUrl.origin}/${VERSION}/cli update`,
"esm:remove": `deno run -A ${importUrl.origin}/${VERSION}/cli remove`,
"esm:add": `deno run -A ${importUrl.origin}/${VERSION} add`,
"esm:update": `deno run -A ${importUrl.origin}/${VERSION} update`,
"esm:remove": `deno run -A ${importUrl.origin}/${VERSION} remove`,
};
await Deno.writeTextFile(
"deno.json",
Expand Down
8 changes: 4 additions & 4 deletions CLI.node.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const importUrl = new URL(globalThis?.process?.env?.ESMSH_SERVER || "https://esm.sh");
const VERSION = /^\/v\d+\//.test(importUrl.pathname)
const VERSION = /^\/v\d+\/?/.test(importUrl.pathname)
? importUrl.pathname.split("/")[1]
: "v{VERSION}";

Expand Down Expand Up @@ -157,9 +157,9 @@ async function init(args, options) {
const tasks = config.tasks;
config.tasks = {
...tasks,
"esm:add": `reejs x ${importUrl.origin}/${VERSION}/cli add`,
"esm:update": `reejs x ${importUrl.origin}/${VERSION}/cli update`,
"esm:remove": `reejs x ${importUrl.origin}/${VERSION}/cli remove`,
"esm:add": `reejs x ${importUrl.origin}/${VERSION} add`,
"esm:update": `reejs x ${importUrl.origin}/${VERSION} update`,
"esm:remove": `reejs x ${importUrl.origin}/${VERSION} remove`,
};
await Deno.writeTextFile(
"reecfg.json",
Expand Down
40 changes: 20 additions & 20 deletions packages/esm-worker/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,23 +119,25 @@ class ESMWorker {
let pathname = decodeURIComponent(url.pathname);
let buildVersion = "v" + VERSION;

switch (pathname) {
case "/":
// redirect to the CLI script if the request is from Node.js/Deno/Bun
if (
ua === "undici" ||
ua?.startsWith("Node/") ||
ua?.startsWith("Deno/") ||
ua?.startsWith("Bun/")
) {
return redirect(
new URL(`/${buildVersion}/cli${url.search}`, url),
302,
86400,
);
}
break;
if (
ua === "undici" ||
ua?.startsWith("Node/") ||
ua?.startsWith("Deno/") ||
ua?.startsWith("Bun/")
) {
if (pathname === "/" || /^\/v\d+\/?$/.test(pathname)) {
return ctx.withCache(() =>
fetchServerOrigin(
req,
env,
ctx,
pathname,
corsHeaders(),
), { varyUA: true });
}
}

switch (pathname) {
case "/build":
if (req.method === "POST" || req.method === "PUT") {
return fetchServerOrigin(
Expand Down Expand Up @@ -209,9 +211,7 @@ class ESMWorker {
buildVersion = url.searchParams.get("pin")!;
}

if (
pathname === "/cli" || pathname === "/build" || pathname === "/server"
) {
if (pathname === "/build" || pathname === "/server") {
if (!hasBuildVerPrefix && !hasBuildVerQuery) {
return redirect(
new URL(`/${buildVersion}${pathname}`, url),
Expand All @@ -224,7 +224,7 @@ class ESMWorker {
req,
env,
ctx,
`/${buildVersion}${pathname}` + url.search,
`/${buildVersion}${pathname}`,
corsHeaders(),
), { varyUA: true });
}
Expand Down
55 changes: 25 additions & 30 deletions server/server_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,13 +236,31 @@ func esmHandler() rex.Handle {
}
}

if userAgent == "undici" || strings.HasPrefix(userAgent, "Node/") || strings.HasPrefix(userAgent, "Deno/") || strings.HasPrefix(userAgent, "Bun/") {
if pathname == "/" || regexpCliPath.MatchString(pathname) {
if strings.HasPrefix(userAgent, "Deno/") {
cliTs, err := embedFS.ReadFile("CLI.deno.ts")
if err != nil {
return err
}
ctx.SetHeader("Content-Type", "application/typescript; charset=utf-8")
return bytes.ReplaceAll(cliTs, []byte("v{VERSION}"), []byte(fmt.Sprintf("v%d", CTX_BUILD_VERSION)))
}
if userAgent == "undici" || strings.HasPrefix(userAgent, "Node/") || strings.HasPrefix(userAgent, "Bun/") {
cliJs, err := embedFS.ReadFile("CLI.node.js")
if err != nil {
return err
}
ctx.SetHeader("Content-Type", "application/javascript; charset=utf-8")
cliJs = bytes.ReplaceAll(cliJs, []byte("v{VERSION}"), []byte(fmt.Sprintf("v%d", CTX_BUILD_VERSION)))
return bytes.ReplaceAll(cliJs, []byte("https://esm.sh"), []byte(cdnOrigin+cfg.CdnBasePath))
}
}
}

// static routes
switch pathname {
case "/":
if userAgent == "undici" || strings.HasPrefix(userAgent, "Node/") || strings.HasPrefix(userAgent, "Deno/") || strings.HasPrefix(userAgent, "Bun/") {
url := fmt.Sprintf("%s%s/v%d/cli", cdnOrigin, cfg.CdnBasePath, CTX_BUILD_VERSION)
return rex.Redirect(url, 302)
}
indexHTML, err := embedFS.ReadFile("server/embed/index.html")
if err != nil {
return err
Expand Down Expand Up @@ -400,31 +418,7 @@ func esmHandler() rex.Handle {
outdatedBuildVer = a[1]
}

switch pathname {
case "/cli":
if !hasBuildVerPrefix && !ctx.Form.Has("pin") {
url := fmt.Sprintf("%s%s/v%d/cli", cdnOrigin, cfg.CdnBasePath, CTX_BUILD_VERSION)
return rex.Redirect(url, 302)
}
if strings.HasPrefix(userAgent, "Deno/") {
cliTs, err := embedFS.ReadFile("CLI.deno.ts")
if err != nil {
return err
}
ctx.SetHeader("Content-Type", "application/typescript; charset=utf-8")
return bytes.ReplaceAll(cliTs, []byte("v{VERSION}"), []byte(fmt.Sprintf("v%d", CTX_BUILD_VERSION)))
}
if userAgent == "undici" || strings.HasPrefix(userAgent, "Node/") || strings.HasPrefix(userAgent, "Bun/") {
cliJs, err := embedFS.ReadFile("CLI.node.js")
if err != nil {
return err
}
ctx.SetHeader("Content-Type", "application/javascript; charset=utf-8")
cliJs = bytes.ReplaceAll(cliJs, []byte("v{VERSION}"), []byte(fmt.Sprintf("v%d", CTX_BUILD_VERSION)))
return bytes.ReplaceAll(cliJs, []byte("https://esm.sh"), []byte(cdnOrigin+cfg.CdnBasePath))
}

case "/build":
if pathname == "/build" {
if !hasBuildVerPrefix && !ctx.Form.Has("pin") {
url := fmt.Sprintf("%s%s/v%d/build", cdnOrigin, cfg.CdnBasePath, CTX_BUILD_VERSION)
return rex.Redirect(url, 302)
Expand Down Expand Up @@ -461,8 +455,9 @@ func esmHandler() rex.Handle {
ctx.AddHeader("Vary", "User-Agent")
}
return bytes.ReplaceAll(data, []byte("$ORIGIN"), []byte(cdnOrigin))
}

case "/server":
if pathname == "/server" {
if !hasBuildVerPrefix && !ctx.Form.Has("pin") {
url := fmt.Sprintf("%s%s/v%d/server", cdnOrigin, cfg.CdnBasePath, CTX_BUILD_VERSION)
return rex.Redirect(url, 302)
Expand Down
1 change: 1 addition & 0 deletions server/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ var (
regexpFullVersion = regexp.MustCompile(`^\d+\.\d+\.\d+[\w\.\+\-]*$`)
regexpFullVersionPath = regexp.MustCompile(`(\w)@(v?\d+\.\d+\.\d+[\w\.\+\-]*|[0-9a-f]{10})(/|$)`)
regexpBuildVersionPath = regexp.MustCompile(`^/v\d+(/|$)`)
regexpCliPath = regexp.MustCompile(`^/v\d+\/?$`)
regexpLocPath = regexp.MustCompile(`(\.js):\d+:\d+$`)
regexpJSIdent = regexp.MustCompile(`^[a-zA-Z_$][\w$]*$`)
regexpGlobalIdent = regexp.MustCompile(`__[a-zA-Z]+\$`)
Expand Down
65 changes: 1 addition & 64 deletions test/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ async function startServer(onStart: () => Promise<void>, single: boolean) {
const status = await res.json();
if (status.ns === "READY") {
console.log("esm.sh server started.");
await onStart();
onStart();
break;
}
} catch (_) {
Expand Down Expand Up @@ -62,68 +62,6 @@ async function runTest(name: string, retry?: boolean): Promise<number> {
return Date.now() - execBegin;
}

async function runCliTest() {
console.log(`\n[test CLI]`);

const cwd = await Deno.makeTempDir();
await Deno.writeTextFile(
cwd + "/deno.json",
`{"importMap": "import-map.json"}`,
);

const res = await fetch("http://localhost:8080/");
if (!res.headers.get("content-type")?.startsWith("application/typescript")) {
throw new Error(`Invalid content type: ${res.headers.get("content-type")}`);
}

const p = new Deno.Command(Deno.execPath(), {
args: [
"run",
"-A",
"-r",
"--no-lock",
"http://localhost:8080/v100/cli",
"add",
"[email protected]",
"[email protected]",
"react:[email protected]/compat",
"[email protected]",
],
cwd,
stdout: "inherit",
stderr: "inherit",
}).spawn();
const { code, success } = await p.status;
if (!success) {
Deno.exit(code);
}

const imRaw = await Deno.readTextFile(cwd + "/import-map.json");
const im = JSON.parse(imRaw);
if (
JSON.stringify(im) !== JSON.stringify({
imports: {
"preact-render-to-string":
"http://localhost:8080/v100/*[email protected]",
"preact-render-to-string/":
"http://localhost:8080/v100/*[email protected]/",
preact: "http://localhost:8080/v100/[email protected]",
"preact/": "http://localhost:8080/v100/[email protected]/",
react: "http://localhost:8080/v100/[email protected]/compat",
swr: "http://localhost:8080/v100/*[email protected]",
"swr/": "http://localhost:8080/v100/*[email protected]/",
},
scopes: {
"http://localhost:8080/v100/": {
"pretty-format": "http://localhost:8080/v100/[email protected]",
},
},
})
) {
console.log(im);
throw new Error("Invalid import maps generated");
}
}

function run(name: string, ...args: string[]) {
const p = new Deno.Command(name, {
Expand Down Expand Up @@ -168,7 +106,6 @@ if (import.meta.main) {
if (testDir) {
timeUsed += await runTest(testDir, true);
} else {
await runCliTest();
for await (const entry of Deno.readDir("./test")) {
if (entry.isDirectory && !entry.name.startsWith("_")) {
timeUsed += await runTest(entry.name);
Expand Down
58 changes: 58 additions & 0 deletions test/cli/cli.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {
assert,
assertEquals,
} from "https://deno.land/[email protected]/testing/asserts.ts";

Deno.test("CLI script", async () => {
const cwd = await Deno.makeTempDir();
await Deno.writeTextFile(
cwd + "/deno.json",
`{"importMap": "import-map.json"}`,
);

const res = await fetch("http://localhost:8080/");
await res.body?.cancel();
assertEquals(res.status, 200);
assertEquals(res.headers.get("content-type"), "application/typescript; charset=utf-8");

const p = new Deno.Command(Deno.execPath(), {
args: [
"run",
"-A",
"-r",
"--no-lock",
"http://localhost:8080/v100",
"add",
"[email protected]",
"[email protected]",
"react:[email protected]/compat",
"[email protected]",
],
cwd,
stdout: "inherit",
stderr: "inherit",
}).spawn();
const { success } = await p.status;
assert(success);

const imRaw = await Deno.readTextFile(cwd + "/import-map.json");
const im = JSON.parse(imRaw);
assertEquals(im, {
imports: {
"preact-render-to-string":
"http://localhost:8080/v100/*[email protected]",
"preact-render-to-string/":
"http://localhost:8080/v100/*[email protected]/",
preact: "http://localhost:8080/v100/[email protected]",
"preact/": "http://localhost:8080/v100/[email protected]/",
react: "http://localhost:8080/v100/[email protected]/compat",
swr: "http://localhost:8080/v100/*[email protected]",
"swr/": "http://localhost:8080/v100/*[email protected]/",
},
scopes: {
"http://localhost:8080/v100/": {
"pretty-format": "http://localhost:8080/v100/[email protected]",
},
},
});
});

0 comments on commit 69cdde7

Please sign in to comment.