From 50509a7eebf0625af3cbeef55e94d00b80e89d80 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 21 Nov 2025 13:38:37 +0000 Subject: [PATCH 1/8] Update CLI usage in README --- README.md | 37 +------------------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/README.md b/README.md index 641c1abd..bb42993e 100644 --- a/README.md +++ b/README.md @@ -31,42 +31,7 @@ npm install -g @tscircuit/cli ``` -Usage: tsci [options] [command] - -CLI for developing tscircuit packages - -Options: - -h, --help display help for command - -Commands: - init [options] [directory] Initialize a new TSCircuit project in the - specified directory (or current directory if none - is provided) - dev [options] [file] Start development server for a package - clone [options] Clone a package from the registry - push [options] [file] Save snippet code to Registry API - auth Login/logout - login Login to tscircuit registry - logout Logout from tscircuit registry - config Manage tscircuit CLI configuration - export [options] Export tscircuit code to various formats - build [options] [file] Run tscircuit eval and output circuit json - add Add a tscircuit component package to your project - remove Remove a tscircuit component package from your - project - snapshot [options] [path] Generate schematic and PCB snapshots (add --3d for - 3d preview) - setup Setup utilities like GitHub Actions - upgrade Upgrade CLI to the latest version - search [options] Search for footprints, CAD models or packages in - the tscircuit ecosystem - import Search JLCPCB or the tscircuit registry and import - a component - convert [options] Convert a .kicad_mod footprint to a tscircuit - component - simulate Run a simulation - version Print CLI version - help [command] display help for command + ``` From 492474d794780781e7ee14d416022937695ea891 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 22 Nov 2025 08:33:37 +0000 Subject: [PATCH 2/8] Update CLI usage in README --- README.md | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bb42993e..beab35cf 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,46 @@ npm install -g @tscircuit/cli ``` - +Usage: tsci [options] [command] + +CLI for developing tscircuit packages + +Options: + -h, --help display help for command + +Commands: + init [options] [directory] Initialize a new TSCircuit project in the + specified directory (or current directory if none + is provided) + dev [options] [file] Start development server for a package + clone [options] [package] Clone a package from the registry + push [options] [file] Save package code to Registry API + auth Login/logout + login Login to tscircuit registry + logout Logout from tscircuit registry + config Manage tscircuit CLI configuration + export [options] Export tscircuit code to various formats + build [options] [file] Run tscircuit eval and output circuit json + transpile [file] Transpile TypeScript/TSX to JavaScript (ESM, + CommonJS, and type declarations) + add Add a tscircuit component package to your project + remove Remove a tscircuit component package from your + project + snapshot [options] [path] Generate schematic and PCB snapshots (add --3d for + 3d preview) + setup Setup utilities like GitHub Actions + install Install project dependencies and generate + package.json if needed + upgrade Upgrade CLI to the latest version + search [options] Search for footprints, CAD models or packages in + the tscircuit ecosystem + import Search JLCPCB or the tscircuit registry and import + a component + convert [options] Convert a .kicad_mod footprint to a tscircuit + component + simulate Run a simulation + version Print CLI version + help [command] display help for command ``` From 41b1684c5d227f311b38bc0a5b1d741e16759781 Mon Sep 17 00:00:00 2001 From: Mustafa Mulla <97171641+MustafaMulla29@users.noreply.github.com> Date: Wed, 26 Nov 2025 17:28:13 +0000 Subject: [PATCH 3/8] Support installing packages through tsci add just like bun add --- cli/add/register.ts | 11 +- lib/shared/add-package.ts | 90 ++++++++++------ tests/cli/add/add-package-or-url.test.ts | 124 +++++++++++++++++++++++ 3 files changed, 192 insertions(+), 33 deletions(-) create mode 100644 tests/cli/add/add-package-or-url.test.ts diff --git a/cli/add/register.ts b/cli/add/register.ts index a93da756..54fcfcd0 100644 --- a/cli/add/register.ts +++ b/cli/add/register.ts @@ -4,11 +4,14 @@ import { addPackage } from "lib/shared/add-package" export const registerAdd = (program: Command) => { program .command("add") - .description("Add a tscircuit component package to your project") - .argument("", "Component to add (e.g. author/component-name)") - .action(async (componentPath: string) => { + .description("Add a package to your project (works like bun add)") + .argument( + "", + "Package to add (e.g. package-name, author/component, https://github.com/user/repo, package@version)", + ) + .action(async (packageSpec: string) => { try { - await addPackage(componentPath) + await addPackage(packageSpec) } catch (error) { process.exit(1) } diff --git a/lib/shared/add-package.ts b/lib/shared/add-package.ts index 1d523b97..c9929c7c 100644 --- a/lib/shared/add-package.ts +++ b/lib/shared/add-package.ts @@ -5,46 +5,78 @@ import { getPackageManager } from "./get-package-manager" import { resolveTarballUrlFromRegistry } from "./resolve-tarball-url-from-registry" /** - * Normalizes a tscircuit component path to an npm package name. - * @param componentPath - The component identifier (e.g., author/name, @tsci/author.name) - * @returns The normalized npm package name. + * Checks if a package spec is a tscircuit component format and normalizes it. + * Returns null if it's not a tscircuit component format (e.g., regular npm package, URL, etc.) + * @param packageSpec - The package specifier + * @returns The normalized npm package name or null if not a tscircuit component */ -export function normalizePackageNameToNpm(componentPath: string): string { - if (componentPath.startsWith("@tscircuit/")) { - return componentPath - } else if (componentPath.startsWith("@tsci/")) { - return componentPath - } else { - const match = componentPath.match(/^([^/.]+)[/.](.+)$/) - if (!match) { - throw new Error( - "Invalid component path. Use format: author/component-name, author.component-name, @tscircuit/package-name, or @tsci/author.component-name", - ) - } +export function normalizePackageNameToNpm(packageSpec: string): string | null { + // Already a tscircuit scoped package + if ( + packageSpec.startsWith("@tscircuit/") || + packageSpec.startsWith("@tsci/") + ) { + return packageSpec + } + + // Check for URLs or git repos - these are not tscircuit components + if ( + packageSpec.startsWith("http://") || + packageSpec.startsWith("https://") || + packageSpec.startsWith("git+") || + packageSpec.startsWith("git://") + ) { + return null + } + + // Check for npm package with version (e.g., lodash@4.17.21) - not a tscircuit component + if (packageSpec.includes("@") && !packageSpec.startsWith("@")) { + return null + } + + // Check for scoped packages that aren't tscircuit + if ( + packageSpec.startsWith("@") && + !packageSpec.startsWith("@tsci/") && + !packageSpec.startsWith("@tscircuit/") + ) { + return null + } + + // Try to match author/component or author.component format + const match = packageSpec.match(/^([^/.@]+)[/.]([^/.@]+)$/) + if (match) { const [, author, componentName] = match return `@tsci/${author}.${componentName}` } + + // Anything else is treated as a regular package name + return null } /** - * Installs a tscircuit component package. - * Handles different package name formats, ensures .npmrc is configured, - * and uses the appropriate package manager. + * Adds a package to the project (works like bun add). + * Detects tscircuit component formats and handles @tsci registry setup. + * All other package specs are passed directly to the package manager. * - * @param componentPath - The component identifier (e.g., author/name, @tsci/author.name) + * @param packageSpec - Any package specifier (e.g., package-name, author/component, https://github.com/user/repo, package@version) * @param projectDir - The root directory of the project (defaults to process.cwd()) */ export async function addPackage( - componentPath: string, + packageSpec: string, projectDir: string = process.cwd(), ) { - const packageName = normalizePackageNameToNpm(componentPath) + // Check if this is a tscircuit component format + const normalizedName = normalizePackageNameToNpm(packageSpec) - console.log(`Adding ${packageName}...`) + // Determine what to display and what to install + const displayName = normalizedName || packageSpec + let installTarget = normalizedName || packageSpec - let installTarget = packageName + console.log(`Adding ${displayName}...`) - if (packageName.startsWith("@tsci/")) { + // Only handle @tsci registry setup if it's a tscircuit component + if (normalizedName && normalizedName.startsWith("@tsci/")) { const npmrcPath = path.join(projectDir, ".npmrc") const npmrcContent = fs.existsSync(npmrcPath) ? fs.readFileSync(npmrcPath, "utf-8") @@ -77,19 +109,19 @@ export async function addPackage( } if (!hasTsciRegistry) { - installTarget = await resolveTarballUrlFromRegistry(packageName) + installTarget = await resolveTarballUrlFromRegistry(normalizedName) } } + // For all other cases (URLs, scoped packages, regular npm packages), use packageSpec as-is // Install the package using the detected package manager const packageManager = getPackageManager() try { packageManager.install({ name: installTarget, cwd: projectDir }) - console.log(`Added ${packageName} successfully.`) + console.log(`Added ${displayName} successfully.`) } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error) - console.error(`Failed to add ${packageName}:`, errorMessage) - // Re-throw the error so the caller can handle it - throw new Error(`Failed to add ${packageName}: ${errorMessage}`) + console.error(`Failed to add ${displayName}:`, errorMessage) + throw new Error(`Failed to add ${displayName}: ${errorMessage}`) } } diff --git a/tests/cli/add/add-package-or-url.test.ts b/tests/cli/add/add-package-or-url.test.ts new file mode 100644 index 00000000..f169ae87 --- /dev/null +++ b/tests/cli/add/add-package-or-url.test.ts @@ -0,0 +1,124 @@ +import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture" +import { test, expect } from "bun:test" +import { join } from "node:path" +import * as fs from "node:fs" + +test("tsci add - adds regular npm package", async () => { + const { tmpDir, runCommand } = await getCliTestFixture() + + // Create initial package.json + await Bun.write( + join(tmpDir, "package.json"), + JSON.stringify({ + name: "test-project", + dependencies: {}, + }), + ) + + // Test adding a regular npm package + const { stdout } = await runCommand("tsci add zod") + expect(stdout).toContain("Adding zod") + expect(stdout).toContain("successfully") + + // Verify package.json was updated + const pkgJson = JSON.parse( + await Bun.file(join(tmpDir, "package.json")).text(), + ) + expect(pkgJson.dependencies["zod"]).toBeDefined() +}) + +test("tsci add - adds package from GitHub URL", async () => { + const { tmpDir, runCommand } = await getCliTestFixture() + + // Create initial package.json + await Bun.write( + join(tmpDir, "package.json"), + JSON.stringify({ + name: "test-project", + dependencies: {}, + }), + ) + + // Test adding from GitHub URL + const { stdout } = await runCommand( + "tsci add https://github.com/lodash/lodash", + ) + expect(stdout).toContain("Adding https://github.com/lodash/lodash") + expect(stdout).toContain("successfully") + + // Verify package.json was updated + const pkgJson = JSON.parse( + await Bun.file(join(tmpDir, "package.json")).text(), + ) + expect(pkgJson.dependencies["lodash"]).toBeDefined() +}) + +test("tsci add - adds package with version", async () => { + const { tmpDir, runCommand } = await getCliTestFixture() + + // Create initial package.json + await Bun.write( + join(tmpDir, "package.json"), + JSON.stringify({ + name: "test-project", + dependencies: {}, + }), + ) + + // Test adding with version + const { stdout } = await runCommand("tsci add zod@3.22.0") + expect(stdout).toContain("Adding zod@3.22.0") + expect(stdout).toContain("successfully") + + // Verify package.json was updated with specific version + const pkgJson = JSON.parse( + await Bun.file(join(tmpDir, "package.json")).text(), + ) + expect(pkgJson.dependencies["zod"]).toBe("3.22.0") +}) + +test("tsci add - handles author/component format as tscircuit package", async () => { + const { tmpDir, runCommand } = await getCliTestFixture() + + // Create initial package.json + await Bun.write( + join(tmpDir, "package.json"), + JSON.stringify({ + name: "test-project", + dependencies: {}, + }), + ) + + // Test author/component format (should convert to @tsci/author.component) + const result = await runCommand("tsci add seveibar/soup") + + // Should show it's trying to add @tsci/seveibar.soup + expect( + result.stdout.includes("@tsci/seveibar.soup") || + result.stderr.includes("@tsci/seveibar.soup"), + ).toBe(true) +}) + +test("tsci add - handles scoped packages", async () => { + const { tmpDir, runCommand } = await getCliTestFixture() + + // Create initial package.json + await Bun.write( + join(tmpDir, "package.json"), + JSON.stringify({ + name: "test-project", + dependencies: {}, + }), + ) + + // Test adding a scoped package + const { stdout } = await runCommand("tsci add @types/node") + expect(stdout).toContain("Adding @types/node") + expect(stdout).toContain("successfully") + + // Verify package.json was updated + const pkgJson = JSON.parse( + await Bun.file(join(tmpDir, "package.json")).text(), + ) + expect(pkgJson.dependencies["@types/node"]).toBeDefined() +}) From 516b6c010e598fbf49c4d634d42826743797b1f8 Mon Sep 17 00:00:00 2001 From: Mustafa Mulla <97171641+MustafaMulla29@users.noreply.github.com> Date: Wed, 26 Nov 2025 17:34:54 +0000 Subject: [PATCH 4/8] fix type issue --- lib/shared/remove-package.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/shared/remove-package.ts b/lib/shared/remove-package.ts index b32dabf9..8607e61f 100644 --- a/lib/shared/remove-package.ts +++ b/lib/shared/remove-package.ts @@ -13,7 +13,8 @@ export async function removePackage( componentPath: string, projectDir: string = process.cwd(), ) { - const packageName = normalizePackageNameToNpm(componentPath) + const normalizedName = normalizePackageNameToNpm(componentPath) + const packageName = normalizedName || componentPath console.log(`Removing ${packageName}...`) From fff410aa92fd126b4f1822f5df2b4b467b94e32a Mon Sep 17 00:00:00 2001 From: Mustafa Mulla <97171641+MustafaMulla29@users.noreply.github.com> Date: Wed, 26 Nov 2025 17:36:28 +0000 Subject: [PATCH 5/8] revert readme --- README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index beab35cf..03cd81ca 100644 --- a/README.md +++ b/README.md @@ -43,24 +43,20 @@ Commands: specified directory (or current directory if none is provided) dev [options] [file] Start development server for a package - clone [options] [package] Clone a package from the registry - push [options] [file] Save package code to Registry API + clone [options] Clone a package from the registry + push [options] [file] Save snippet code to Registry API auth Login/logout login Login to tscircuit registry logout Logout from tscircuit registry config Manage tscircuit CLI configuration export [options] Export tscircuit code to various formats build [options] [file] Run tscircuit eval and output circuit json - transpile [file] Transpile TypeScript/TSX to JavaScript (ESM, - CommonJS, and type declarations) add Add a tscircuit component package to your project remove Remove a tscircuit component package from your project snapshot [options] [path] Generate schematic and PCB snapshots (add --3d for 3d preview) setup Setup utilities like GitHub Actions - install Install project dependencies and generate - package.json if needed upgrade Upgrade CLI to the latest version search [options] Search for footprints, CAD models or packages in the tscircuit ecosystem @@ -108,4 +104,4 @@ runframe each time you'd like to load a new version of runframe. export RUNFRAME_STANDALONE_FILE_PATH=../runframe/dist/standalone.min.js cd ../runframe && bun run build cd ../cli && bun run dev -``` +``` \ No newline at end of file From 33c1d4b9d16b47db424cc63e156a1b9bf57238e6 Mon Sep 17 00:00:00 2001 From: Mustafa Mulla <97171641+MustafaMulla29@users.noreply.github.com> Date: Thu, 27 Nov 2025 06:01:39 +0000 Subject: [PATCH 6/8] update function name --- cli/add/register.ts | 2 +- lib/shared/add-package.ts | 8 +++++--- lib/shared/remove-package.ts | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/cli/add/register.ts b/cli/add/register.ts index 54fcfcd0..3dd7f2b2 100644 --- a/cli/add/register.ts +++ b/cli/add/register.ts @@ -4,7 +4,7 @@ import { addPackage } from "lib/shared/add-package" export const registerAdd = (program: Command) => { program .command("add") - .description("Add a package to your project (works like bun add)") + .description("Add a tscircuit component package to your project") .argument( "", "Package to add (e.g. package-name, author/component, https://github.com/user/repo, package@version)", diff --git a/lib/shared/add-package.ts b/lib/shared/add-package.ts index c9929c7c..2f8afbaf 100644 --- a/lib/shared/add-package.ts +++ b/lib/shared/add-package.ts @@ -8,9 +8,11 @@ import { resolveTarballUrlFromRegistry } from "./resolve-tarball-url-from-regist * Checks if a package spec is a tscircuit component format and normalizes it. * Returns null if it's not a tscircuit component format (e.g., regular npm package, URL, etc.) * @param packageSpec - The package specifier - * @returns The normalized npm package name or null if not a tscircuit component + * @returns The normalized @tsci scoped package name or null if not a tscircuit component */ -export function normalizePackageNameToNpm(packageSpec: string): string | null { +export function normalizeTscircuitPackageName( + packageSpec: string, +): string | null { // Already a tscircuit scoped package if ( packageSpec.startsWith("@tscircuit/") || @@ -67,7 +69,7 @@ export async function addPackage( projectDir: string = process.cwd(), ) { // Check if this is a tscircuit component format - const normalizedName = normalizePackageNameToNpm(packageSpec) + const normalizedName = normalizeTscircuitPackageName(packageSpec) // Determine what to display and what to install const displayName = normalizedName || packageSpec diff --git a/lib/shared/remove-package.ts b/lib/shared/remove-package.ts index 8607e61f..bb79bedb 100644 --- a/lib/shared/remove-package.ts +++ b/lib/shared/remove-package.ts @@ -1,5 +1,5 @@ import { getPackageManager } from "./get-package-manager" -import { normalizePackageNameToNpm } from "./add-package" +import { normalizeTscircuitPackageName } from "./add-package" import path from "node:path" import fs from "node:fs" /** @@ -13,7 +13,7 @@ export async function removePackage( componentPath: string, projectDir: string = process.cwd(), ) { - const normalizedName = normalizePackageNameToNpm(componentPath) + const normalizedName = normalizeTscircuitPackageName(componentPath) const packageName = normalizedName || componentPath console.log(`Removing ${packageName}...`) From 031f929776fb6367b8b9c72e5dd9490ecf41fe91 Mon Sep 17 00:00:00 2001 From: Mustafa Mulla <97171641+MustafaMulla29@users.noreply.github.com> Date: Thu, 27 Nov 2025 06:18:35 +0000 Subject: [PATCH 7/8] add tests --- tests/cli/add/add-package-or-url.test.ts | 124 ----------------------- tests/cli/add/add-package01.test.ts | 27 +++++ tests/cli/add/add-package02.test.ts | 29 ++++++ tests/cli/add/add-package03.test.ts | 27 +++++ tests/cli/add/add-package04.test.ts | 25 +++++ tests/cli/add/add-package05.test.ts | 27 +++++ tests/cli/add/add-package06.test.ts | 25 +++++ 7 files changed, 160 insertions(+), 124 deletions(-) delete mode 100644 tests/cli/add/add-package-or-url.test.ts create mode 100644 tests/cli/add/add-package01.test.ts create mode 100644 tests/cli/add/add-package02.test.ts create mode 100644 tests/cli/add/add-package03.test.ts create mode 100644 tests/cli/add/add-package04.test.ts create mode 100644 tests/cli/add/add-package05.test.ts create mode 100644 tests/cli/add/add-package06.test.ts diff --git a/tests/cli/add/add-package-or-url.test.ts b/tests/cli/add/add-package-or-url.test.ts deleted file mode 100644 index f169ae87..00000000 --- a/tests/cli/add/add-package-or-url.test.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture" -import { test, expect } from "bun:test" -import { join } from "node:path" -import * as fs from "node:fs" - -test("tsci add - adds regular npm package", async () => { - const { tmpDir, runCommand } = await getCliTestFixture() - - // Create initial package.json - await Bun.write( - join(tmpDir, "package.json"), - JSON.stringify({ - name: "test-project", - dependencies: {}, - }), - ) - - // Test adding a regular npm package - const { stdout } = await runCommand("tsci add zod") - expect(stdout).toContain("Adding zod") - expect(stdout).toContain("successfully") - - // Verify package.json was updated - const pkgJson = JSON.parse( - await Bun.file(join(tmpDir, "package.json")).text(), - ) - expect(pkgJson.dependencies["zod"]).toBeDefined() -}) - -test("tsci add - adds package from GitHub URL", async () => { - const { tmpDir, runCommand } = await getCliTestFixture() - - // Create initial package.json - await Bun.write( - join(tmpDir, "package.json"), - JSON.stringify({ - name: "test-project", - dependencies: {}, - }), - ) - - // Test adding from GitHub URL - const { stdout } = await runCommand( - "tsci add https://github.com/lodash/lodash", - ) - expect(stdout).toContain("Adding https://github.com/lodash/lodash") - expect(stdout).toContain("successfully") - - // Verify package.json was updated - const pkgJson = JSON.parse( - await Bun.file(join(tmpDir, "package.json")).text(), - ) - expect(pkgJson.dependencies["lodash"]).toBeDefined() -}) - -test("tsci add - adds package with version", async () => { - const { tmpDir, runCommand } = await getCliTestFixture() - - // Create initial package.json - await Bun.write( - join(tmpDir, "package.json"), - JSON.stringify({ - name: "test-project", - dependencies: {}, - }), - ) - - // Test adding with version - const { stdout } = await runCommand("tsci add zod@3.22.0") - expect(stdout).toContain("Adding zod@3.22.0") - expect(stdout).toContain("successfully") - - // Verify package.json was updated with specific version - const pkgJson = JSON.parse( - await Bun.file(join(tmpDir, "package.json")).text(), - ) - expect(pkgJson.dependencies["zod"]).toBe("3.22.0") -}) - -test("tsci add - handles author/component format as tscircuit package", async () => { - const { tmpDir, runCommand } = await getCliTestFixture() - - // Create initial package.json - await Bun.write( - join(tmpDir, "package.json"), - JSON.stringify({ - name: "test-project", - dependencies: {}, - }), - ) - - // Test author/component format (should convert to @tsci/author.component) - const result = await runCommand("tsci add seveibar/soup") - - // Should show it's trying to add @tsci/seveibar.soup - expect( - result.stdout.includes("@tsci/seveibar.soup") || - result.stderr.includes("@tsci/seveibar.soup"), - ).toBe(true) -}) - -test("tsci add - handles scoped packages", async () => { - const { tmpDir, runCommand } = await getCliTestFixture() - - // Create initial package.json - await Bun.write( - join(tmpDir, "package.json"), - JSON.stringify({ - name: "test-project", - dependencies: {}, - }), - ) - - // Test adding a scoped package - const { stdout } = await runCommand("tsci add @types/node") - expect(stdout).toContain("Adding @types/node") - expect(stdout).toContain("successfully") - - // Verify package.json was updated - const pkgJson = JSON.parse( - await Bun.file(join(tmpDir, "package.json")).text(), - ) - expect(pkgJson.dependencies["@types/node"]).toBeDefined() -}) diff --git a/tests/cli/add/add-package01.test.ts b/tests/cli/add/add-package01.test.ts new file mode 100644 index 00000000..098d65ab --- /dev/null +++ b/tests/cli/add/add-package01.test.ts @@ -0,0 +1,27 @@ +import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture" +import { test, expect } from "bun:test" +import { join } from "node:path" + +test("tsci add - adds regular npm package", async () => { + const { tmpDir, runCommand } = await getCliTestFixture() + + // Create initial package.json + await Bun.write( + join(tmpDir, "package.json"), + JSON.stringify({ + name: "test-project", + dependencies: {}, + }), + ) + + // Test adding a regular npm package + const { stdout } = await runCommand("tsci add zod") + expect(stdout).toContain("Adding zod") + expect(stdout).toContain("successfully") + + // Verify package.json was updated + const pkgJson = JSON.parse( + await Bun.file(join(tmpDir, "package.json")).text(), + ) + expect(pkgJson.dependencies["zod"]).toBeDefined() +}) diff --git a/tests/cli/add/add-package02.test.ts b/tests/cli/add/add-package02.test.ts new file mode 100644 index 00000000..d96c1cf7 --- /dev/null +++ b/tests/cli/add/add-package02.test.ts @@ -0,0 +1,29 @@ +import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture" +import { test, expect } from "bun:test" +import { join } from "node:path" + +test("tsci add - adds package from GitHub URL", async () => { + const { tmpDir, runCommand } = await getCliTestFixture() + + // Create initial package.json + await Bun.write( + join(tmpDir, "package.json"), + JSON.stringify({ + name: "test-project", + dependencies: {}, + }), + ) + + // Test adding from GitHub URL + const { stdout } = await runCommand( + "tsci add https://github.com/lodash/lodash", + ) + expect(stdout).toContain("Adding https://github.com/lodash/lodash") + expect(stdout).toContain("successfully") + + // Verify package.json was updated + const pkgJson = JSON.parse( + await Bun.file(join(tmpDir, "package.json")).text(), + ) + expect(pkgJson.dependencies["lodash"]).toBeDefined() +}) diff --git a/tests/cli/add/add-package03.test.ts b/tests/cli/add/add-package03.test.ts new file mode 100644 index 00000000..10f2261b --- /dev/null +++ b/tests/cli/add/add-package03.test.ts @@ -0,0 +1,27 @@ +import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture" +import { test, expect } from "bun:test" +import { join } from "node:path" + +test("tsci add - adds package with version", async () => { + const { tmpDir, runCommand } = await getCliTestFixture() + + // Create initial package.json + await Bun.write( + join(tmpDir, "package.json"), + JSON.stringify({ + name: "test-project", + dependencies: {}, + }), + ) + + // Test adding with version + const { stdout } = await runCommand("tsci add zod@3.22.0") + expect(stdout).toContain("Adding zod@3.22.0") + expect(stdout).toContain("successfully") + + // Verify package.json was updated with specific version + const pkgJson = JSON.parse( + await Bun.file(join(tmpDir, "package.json")).text(), + ) + expect(pkgJson.dependencies["zod"]).toBe("3.22.0") +}) diff --git a/tests/cli/add/add-package04.test.ts b/tests/cli/add/add-package04.test.ts new file mode 100644 index 00000000..c7d36676 --- /dev/null +++ b/tests/cli/add/add-package04.test.ts @@ -0,0 +1,25 @@ +import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture" +import { test, expect } from "bun:test" +import { join } from "node:path" + +test("tsci add - handles author/component format as tscircuit package", async () => { + const { tmpDir, runCommand } = await getCliTestFixture() + + // Create initial package.json + await Bun.write( + join(tmpDir, "package.json"), + JSON.stringify({ + name: "test-project", + dependencies: {}, + }), + ) + + // Test author/component format (should convert to @tsci/author.component) + const result = await runCommand("tsci add seveibar/soup") + + // Should show it's trying to add @tsci/seveibar.soup + expect( + result.stdout.includes("@tsci/seveibar.soup") || + result.stderr.includes("@tsci/seveibar.soup"), + ).toBe(true) +}) diff --git a/tests/cli/add/add-package05.test.ts b/tests/cli/add/add-package05.test.ts new file mode 100644 index 00000000..ae478def --- /dev/null +++ b/tests/cli/add/add-package05.test.ts @@ -0,0 +1,27 @@ +import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture" +import { test, expect } from "bun:test" +import { join } from "node:path" + +test("tsci add - handles scoped packages", async () => { + const { tmpDir, runCommand } = await getCliTestFixture() + + // Create initial package.json + await Bun.write( + join(tmpDir, "package.json"), + JSON.stringify({ + name: "test-project", + dependencies: {}, + }), + ) + + // Test adding a scoped package + const { stdout } = await runCommand("tsci add @types/node") + expect(stdout).toContain("Adding @types/node") + expect(stdout).toContain("successfully") + + // Verify package.json was updated + const pkgJson = JSON.parse( + await Bun.file(join(tmpDir, "package.json")).text(), + ) + expect(pkgJson.dependencies["@types/node"]).toBeDefined() +}) diff --git a/tests/cli/add/add-package06.test.ts b/tests/cli/add/add-package06.test.ts new file mode 100644 index 00000000..60f2699c --- /dev/null +++ b/tests/cli/add/add-package06.test.ts @@ -0,0 +1,25 @@ +import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture" +import { test, expect } from "bun:test" +import { join } from "node:path" + +test("tsci add - handles author.component format as tscircuit package", async () => { + const { tmpDir, runCommand } = await getCliTestFixture() + + // Create initial package.json + await Bun.write( + join(tmpDir, "package.json"), + JSON.stringify({ + name: "test-project", + dependencies: {}, + }), + ) + + // Test author.component format (should convert to @tsci/author.component) + const result = await runCommand("tsci add seveibar.soup") + + // Should show it's trying to add @tsci/seveibar.soup + expect( + result.stdout.includes("@tsci/seveibar.soup") || + result.stderr.includes("@tsci/seveibar.soup"), + ).toBe(true) +}) From bb0004ab5cde61d7a2882e5de5939f8553c86472 Mon Sep 17 00:00:00 2001 From: Mustafa Mulla <97171641+MustafaMulla29@users.noreply.github.com> Date: Thu, 27 Nov 2025 17:29:39 +0000 Subject: [PATCH 8/8] check node_modules dir in tests --- tests/cli/add/add-package01.test.ts | 5 +++++ tests/cli/add/add-package02.test.ts | 5 +++++ tests/cli/add/add-package03.test.ts | 5 +++++ tests/cli/add/add-package05.test.ts | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/tests/cli/add/add-package01.test.ts b/tests/cli/add/add-package01.test.ts index 098d65ab..2530eac9 100644 --- a/tests/cli/add/add-package01.test.ts +++ b/tests/cli/add/add-package01.test.ts @@ -1,6 +1,7 @@ import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture" import { test, expect } from "bun:test" import { join } from "node:path" +import { existsSync } from "node:fs" test("tsci add - adds regular npm package", async () => { const { tmpDir, runCommand } = await getCliTestFixture() @@ -24,4 +25,8 @@ test("tsci add - adds regular npm package", async () => { await Bun.file(join(tmpDir, "package.json")).text(), ) expect(pkgJson.dependencies["zod"]).toBeDefined() + + // Verify package was actually installed in node_modules + const nodeModulesPath = join(tmpDir, "node_modules", "zod") + expect(existsSync(nodeModulesPath)).toBe(true) }) diff --git a/tests/cli/add/add-package02.test.ts b/tests/cli/add/add-package02.test.ts index d96c1cf7..b2a28ec9 100644 --- a/tests/cli/add/add-package02.test.ts +++ b/tests/cli/add/add-package02.test.ts @@ -1,6 +1,7 @@ import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture" import { test, expect } from "bun:test" import { join } from "node:path" +import { existsSync } from "node:fs" test("tsci add - adds package from GitHub URL", async () => { const { tmpDir, runCommand } = await getCliTestFixture() @@ -26,4 +27,8 @@ test("tsci add - adds package from GitHub URL", async () => { await Bun.file(join(tmpDir, "package.json")).text(), ) expect(pkgJson.dependencies["lodash"]).toBeDefined() + + // Verify package was actually installed in node_modules + const nodeModulesPath = join(tmpDir, "node_modules", "lodash") + expect(existsSync(nodeModulesPath)).toBe(true) }) diff --git a/tests/cli/add/add-package03.test.ts b/tests/cli/add/add-package03.test.ts index 10f2261b..4a7868f2 100644 --- a/tests/cli/add/add-package03.test.ts +++ b/tests/cli/add/add-package03.test.ts @@ -1,6 +1,7 @@ import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture" import { test, expect } from "bun:test" import { join } from "node:path" +import { existsSync } from "node:fs" test("tsci add - adds package with version", async () => { const { tmpDir, runCommand } = await getCliTestFixture() @@ -24,4 +25,8 @@ test("tsci add - adds package with version", async () => { await Bun.file(join(tmpDir, "package.json")).text(), ) expect(pkgJson.dependencies["zod"]).toBe("3.22.0") + + // Verify package was actually installed in node_modules + const nodeModulesPath = join(tmpDir, "node_modules", "zod") + expect(existsSync(nodeModulesPath)).toBe(true) }) diff --git a/tests/cli/add/add-package05.test.ts b/tests/cli/add/add-package05.test.ts index ae478def..f7a3842c 100644 --- a/tests/cli/add/add-package05.test.ts +++ b/tests/cli/add/add-package05.test.ts @@ -1,6 +1,7 @@ import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture" import { test, expect } from "bun:test" import { join } from "node:path" +import { existsSync } from "node:fs" test("tsci add - handles scoped packages", async () => { const { tmpDir, runCommand } = await getCliTestFixture() @@ -24,4 +25,8 @@ test("tsci add - handles scoped packages", async () => { await Bun.file(join(tmpDir, "package.json")).text(), ) expect(pkgJson.dependencies["@types/node"]).toBeDefined() + + // Verify package was actually installed in node_modules + const nodeModulesPath = join(tmpDir, "node_modules", "@types", "node") + expect(existsSync(nodeModulesPath)).toBe(true) })