From 40a72f35550ad2fd995b1d176540cc4fa0858370 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 16 Nov 2022 13:44:31 -0500 Subject: fix(npm): support non-all lowercase package names (#16669) Supports package names that aren't all lowercase. This stores the package with a leading underscore (since that's not allowed in npm's registry and no package exists with a leading underscore) then base32 encoded (A-Z0-9) so it can be lowercased and avoid collisions. Global cache dir: ``` $DENO_DIR/npm/registry.npmjs.org/_{base32_encode(package_name).to_lowercase()}/{version} ``` node_modules dir `.deno` folder: ``` node_modules/.deno/_{base32_encode(package_name).to_lowercase()}@{version}/node_modules/ ``` Within node_modules folder: ``` node_modules/ ``` So, direct childs of the node_modules folder can have collisions between packages like `JSON` vs `json`, but this is already something npm itself doesn't handle well. Plus, Deno doesn't actually ever resolve to the `node_modules/` folder, but just has that for compatibility. Additionally, packages in the `.deno` dir could have collissions if they have multiple dependencies that only differ in casing or a dependency that has different casing, but if someone is doing that then they're already going to have trouble with npm and they are asking for trouble in general. --- cli/tests/integration/npm_tests.rs | 18 ++++++++++++++++++ .../testdata/npm/mixed_case_package_name/global.out | 5 +++++ .../testdata/npm/mixed_case_package_name/global.ts | 2 ++ .../testdata/npm/mixed_case_package_name/local.out | 7 +++++++ .../testdata/npm/mixed_case_package_name/local.ts | 18 ++++++++++++++++++ .../npm/registry/@denotest/CAPITALS/1.0.0/index.js | 1 + .../npm/registry/@denotest/CAPITALS/1.0.0/package.json | 4 ++++ .../npm/registry/@denotest/MixedCase/1.0.0/index.js | 2 ++ .../registry/@denotest/MixedCase/1.0.0/package.json | 7 +++++++ 9 files changed, 64 insertions(+) create mode 100644 cli/tests/testdata/npm/mixed_case_package_name/global.out create mode 100644 cli/tests/testdata/npm/mixed_case_package_name/global.ts create mode 100644 cli/tests/testdata/npm/mixed_case_package_name/local.out create mode 100644 cli/tests/testdata/npm/mixed_case_package_name/local.ts create mode 100644 cli/tests/testdata/npm/registry/@denotest/CAPITALS/1.0.0/index.js create mode 100644 cli/tests/testdata/npm/registry/@denotest/CAPITALS/1.0.0/package.json create mode 100644 cli/tests/testdata/npm/registry/@denotest/MixedCase/1.0.0/index.js create mode 100644 cli/tests/testdata/npm/registry/@denotest/MixedCase/1.0.0/package.json (limited to 'cli/tests') diff --git a/cli/tests/integration/npm_tests.rs b/cli/tests/integration/npm_tests.rs index 787dab815..a530d7545 100644 --- a/cli/tests/integration/npm_tests.rs +++ b/cli/tests/integration/npm_tests.rs @@ -123,6 +123,24 @@ itest!(cjs_module_export_assignment_number { http_server: true, }); +itest!(mixed_case_package_name_global_dir { + args: "run npm/mixed_case_package_name/global.ts", + output: "npm/mixed_case_package_name/global.out", + exit_code: 0, + envs: env_vars(), + http_server: true, +}); + +itest!(mixed_case_package_name_local_dir { + args: + "run --node-modules-dir -A $TESTDATA/npm/mixed_case_package_name/local.ts", + output: "npm/mixed_case_package_name/local.out", + exit_code: 0, + envs: env_vars(), + http_server: true, + temp_cwd: true, +}); + // FIXME(bartlomieju): npm: specifiers are not handled in dynamic imports // at the moment // itest!(dynamic_import { diff --git a/cli/tests/testdata/npm/mixed_case_package_name/global.out b/cli/tests/testdata/npm/mixed_case_package_name/global.out new file mode 100644 index 000000000..72417dd71 --- /dev/null +++ b/cli/tests/testdata/npm/mixed_case_package_name/global.out @@ -0,0 +1,5 @@ +Download http://localhost:4545/npm/registry/@denotest/MixedCase +Download http://localhost:4545/npm/registry/@denotest/CAPITALS +Download http://localhost:4545/npm/registry/@denotest/CAPITALS/1.0.0.tgz +Download http://localhost:4545/npm/registry/@denotest/MixedCase/1.0.0.tgz +5 diff --git a/cli/tests/testdata/npm/mixed_case_package_name/global.ts b/cli/tests/testdata/npm/mixed_case_package_name/global.ts new file mode 100644 index 000000000..a721b3d78 --- /dev/null +++ b/cli/tests/testdata/npm/mixed_case_package_name/global.ts @@ -0,0 +1,2 @@ +import value from "npm:@denotest/MixedCase"; +console.log(value); diff --git a/cli/tests/testdata/npm/mixed_case_package_name/local.out b/cli/tests/testdata/npm/mixed_case_package_name/local.out new file mode 100644 index 000000000..b61be3d35 --- /dev/null +++ b/cli/tests/testdata/npm/mixed_case_package_name/local.out @@ -0,0 +1,7 @@ +Download http://localhost:4545/npm/registry/@denotest/MixedCase +Download http://localhost:4545/npm/registry/@denotest/CAPITALS +Download http://localhost:4545/npm/registry/@denotest/CAPITALS/1.0.0.tgz +Download http://localhost:4545/npm/registry/@denotest/MixedCase/1.0.0.tgz +5 +true +true diff --git a/cli/tests/testdata/npm/mixed_case_package_name/local.ts b/cli/tests/testdata/npm/mixed_case_package_name/local.ts new file mode 100644 index 000000000..6ca6cb581 --- /dev/null +++ b/cli/tests/testdata/npm/mixed_case_package_name/local.ts @@ -0,0 +1,18 @@ +import value from "npm:@denotest/MixedCase"; +console.log(value); +console.log(pathExists("./node_modules/.deno")); +console.log( + pathExists("./node_modules/.deno/_ibsgk3tporsxg5bpinavaskuifgfg@1.0.0"), +); + +function pathExists(filePath: string) { + try { + Deno.lstatSync(filePath); + return true; + } catch (error) { + if (error instanceof Deno.errors.NotFound) { + return false; + } + throw error; + } +} diff --git a/cli/tests/testdata/npm/registry/@denotest/CAPITALS/1.0.0/index.js b/cli/tests/testdata/npm/registry/@denotest/CAPITALS/1.0.0/index.js new file mode 100644 index 000000000..f4e8d9d29 --- /dev/null +++ b/cli/tests/testdata/npm/registry/@denotest/CAPITALS/1.0.0/index.js @@ -0,0 +1 @@ +module.exports = 5; diff --git a/cli/tests/testdata/npm/registry/@denotest/CAPITALS/1.0.0/package.json b/cli/tests/testdata/npm/registry/@denotest/CAPITALS/1.0.0/package.json new file mode 100644 index 000000000..e897d0023 --- /dev/null +++ b/cli/tests/testdata/npm/registry/@denotest/CAPITALS/1.0.0/package.json @@ -0,0 +1,4 @@ +{ + "name": "@denotest/CAPITALS", + "version": "1.0.0" +} diff --git a/cli/tests/testdata/npm/registry/@denotest/MixedCase/1.0.0/index.js b/cli/tests/testdata/npm/registry/@denotest/MixedCase/1.0.0/index.js new file mode 100644 index 000000000..fe1cfe547 --- /dev/null +++ b/cli/tests/testdata/npm/registry/@denotest/MixedCase/1.0.0/index.js @@ -0,0 +1,2 @@ +const value = require("@denotest/CAPITALS"); +module.exports = value; diff --git a/cli/tests/testdata/npm/registry/@denotest/MixedCase/1.0.0/package.json b/cli/tests/testdata/npm/registry/@denotest/MixedCase/1.0.0/package.json new file mode 100644 index 000000000..2a36cb357 --- /dev/null +++ b/cli/tests/testdata/npm/registry/@denotest/MixedCase/1.0.0/package.json @@ -0,0 +1,7 @@ +{ + "name": "@denotest/MixedCase", + "version": "1.0.0", + "dependencies": { + "@denotest/CAPITALS": "^1" + } +} -- cgit v1.2.3