From 831aef8a7bcf63d00fe335e06012ded2b3ecfa30 Mon Sep 17 00:00:00 2001 From: zuiidea Date: Tue, 14 Apr 2026 22:30:41 +0800 Subject: [PATCH] test(create): vitest and package name normalization Made-with: Cursor --- .../src/utils/normalize-package-name.test.ts | 12 +++++++++ .../src/utils/normalize-package-name.ts | 26 +++++++++++++++++++ packages/create/vitest.config.ts | 8 ++++++ 3 files changed, 46 insertions(+) create mode 100644 packages/create/src/utils/normalize-package-name.test.ts create mode 100644 packages/create/src/utils/normalize-package-name.ts create mode 100644 packages/create/vitest.config.ts diff --git a/packages/create/src/utils/normalize-package-name.test.ts b/packages/create/src/utils/normalize-package-name.test.ts new file mode 100644 index 0000000..0008ea6 --- /dev/null +++ b/packages/create/src/utils/normalize-package-name.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from "vitest"; +import { normalizePackageName } from "./normalize-package-name.js"; + +describe("normalizePackageName", () => { + it("lowercases and replaces spaces", () => { + expect(normalizePackageName("My App")).toBe("my-app"); + }); + + it("rejects leading dot", () => { + expect(() => normalizePackageName(".bad")).toThrow(/cannot start/); + }); +}); diff --git a/packages/create/src/utils/normalize-package-name.ts b/packages/create/src/utils/normalize-package-name.ts new file mode 100644 index 0000000..e99ddc0 --- /dev/null +++ b/packages/create/src/utils/normalize-package-name.ts @@ -0,0 +1,26 @@ +import { CliError } from "../errors.js"; + +/** + * npm package name rules (simplified): lowercase, URL-safe, no leading dot, segments 1-214. + */ +export function normalizePackageName(input: string): string { + const trimmed = input.trim().toLowerCase(); + if (!trimmed) { + throw new CliError("Project name cannot be empty", "INVALID_INPUT"); + } + if (trimmed.startsWith(".") || trimmed.startsWith("_")) { + throw new CliError( + "Project name cannot start with . or _", + "INVALID_INPUT" + ); + } + const safe = trimmed + .replace(/\s+/g, "-") + .replace(/[^a-z0-9-._~]/g, "-") + .replace(/-+/g, "-") + .replace(/^-+|-+$/g, ""); + if (!safe || safe.length > 214) { + throw new CliError("Project name is invalid or too long", "INVALID_INPUT"); + } + return safe; +} diff --git a/packages/create/vitest.config.ts b/packages/create/vitest.config.ts new file mode 100644 index 0000000..c1433e6 --- /dev/null +++ b/packages/create/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "node", + include: ["src/**/*.test.ts"], + }, +});