diff --git a/src/cli/lib/components/definition/bundle.test.ts b/src/cli/lib/components/definition/bundle.test.ts new file mode 100644 index 0000000..29ad434 --- /dev/null +++ b/src/cli/lib/components/definition/bundle.test.ts @@ -0,0 +1,11 @@ +import { test, expect, describe } from "vitest"; +import { encodeDefinitionPath } from "./bundle.js"; +import { ComponentDefinitionPath } from "./directoryStructure.js"; + +describe("encodeDefinitionPath", async () => { + test("Escaped definition paths are distinguishable from unescaped ones", () => { + const a = encodeDefinitionPath("foo/bar-baz" as ComponentDefinitionPath); + const b = encodeDefinitionPath("foo/bar_baz" as ComponentDefinitionPath); + expect(a).not.toEqual(b); + }); +}); diff --git a/src/cli/lib/components/definition/bundle.ts b/src/cli/lib/components/definition/bundle.ts index 370aebc..35ae9d5 100644 --- a/src/cli/lib/components/definition/bundle.ts +++ b/src/cli/lib/components/definition/bundle.ts @@ -311,7 +311,7 @@ async function findComponentDependencies( return { components, dependencyGraph }; } -// Each path component is less than 64 bytes and escape all a-zA-Z0-9 +// Each path component is less than 64 bytes and is limited to a-zA-Z0-9 // This is the only version of the path the server will receive. export function encodeDefinitionPath( s: ComponentDefinitionPath, @@ -319,8 +319,13 @@ export function encodeDefinitionPath( const components = s.split(path.sep); return components .map((s) => { - const escaped = s.replaceAll("-", "_").replaceAll("+", "_"); - if (escaped.length <= 64) { + const escaped = s + .replaceAll("-", "_") + .replaceAll("+", "_") + .replaceAll(" ", "_") + .replaceAll(".", "_"); + if (escaped.length <= 64 && escaped === s) { + // If escaping lost any information then return escaped; } const hash = crypto.createHash("md5").update(s).digest("hex");