Skip to content

Commit

Permalink
fix: react type declarations (#50)
Browse files Browse the repository at this point in the history
* fix(examples): type declarations

* seperate tsconfig for examples as they are react components

* new lock

* update init

* tests: init

* ux

* old lock

* new bun lock 1.2.*

* Update register.ts

* deps -> devDeps
  • Loading branch information
ArnavK-09 authored Feb 5, 2025
1 parent 218eb04 commit 0d8dbea
Show file tree
Hide file tree
Showing 8 changed files with 2,414 additions and 6 deletions.
2,260 changes: 2,260 additions & 0 deletions bun.lock

Large diffs are not rendered by default.

Binary file removed bun.lockb
Binary file not shown.
83 changes: 80 additions & 3 deletions cli/init/register.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,67 @@
import type { Command } from "commander"
import * as fs from "node:fs"
import * as path from "node:path"
import { execSync } from "node:child_process"

// Detect the package manager being used in the project
const detectPackageManager = (): string => {
const userAgent = process.env.npm_config_user_agent || ""
if (userAgent.startsWith("yarn")) return "yarn"
if (userAgent.startsWith("pnpm")) return "pnpm"
if (userAgent.startsWith("bun")) return "bun"

if (fs.existsSync("yarn.lock")) return "yarn"
if (fs.existsSync("pnpm-lock.yaml")) return "pnpm"
if (fs.existsSync("bun.lockb")) return "bun"

return "npm" // Default to npm
}

// Generate a React-compatible tsconfig.json
const generateTsConfig = (dir: string) => {
const tsconfigPath = path.join(dir, "tsconfig.json")
const tsconfigContent = JSON.stringify(
{
compilerOptions: {
target: "ES6",
module: "ESNext",
jsx: "react-jsx",
outDir: "dist",
strict: true,
esModuleInterop: true,
moduleResolution: "node",
skipLibCheck: true,
forceConsistentCasingInFileNames: true,
resolveJsonModule: true,
sourceMap: true,
allowSyntheticDefaultImports: true,
experimentalDecorators: true,
},
},
null,
2,
)
if (!fs.existsSync(tsconfigPath)) {
fs.writeFileSync(tsconfigPath, tsconfigContent.trimStart())
console.log(`Created: ${tsconfigPath}`)
} else {
console.log(`Skipped: ${tsconfigPath} already exists`)
}
}

export const registerInit = (program: Command) => {
program
.command("init")
.description("Initialize a new TSCircuit project in the current directory")
.action(() => {
const currentDir = process.cwd()

const indexFilePath = path.join(currentDir, "index.tsx")
const npmrcFilePath = path.join(currentDir, ".npmrc")

// Content for index.tsx
const indexContent = `
import "@tscircuit/core"
export default () => (
<board width="10mm" height="10mm">
<resistor
Expand All @@ -32,26 +81,54 @@ export default () => (
<trace from=".R1 > .pin1" to=".C1 > .pin1" />
</board>
);
`
`.trim()

// Content for .npmrc
const npmrcContent = `
@tsci:registry=https://npm.tscircuit.com
`
`.trim()

// Create index.tsx if it doesn't exist
if (!fs.existsSync(indexFilePath)) {
fs.writeFileSync(indexFilePath, indexContent.trimStart())
console.log(`Created: ${indexFilePath}`)
} else {
console.log(`Skipped: ${indexFilePath} already exists`)
}

// Create .npmrc if it doesn't exist
if (!fs.existsSync(npmrcFilePath)) {
fs.writeFileSync(npmrcFilePath, npmrcContent.trimStart())
console.log(`Created: ${npmrcFilePath}`)
} else {
console.log(`Skipped: ${npmrcFilePath} already exists`)
}

// Detect the package manager
const packageManager = detectPackageManager()
console.log(`Detected package manager: ${packageManager}`)

// Install deps using the detected package manager
const dependencies = "@types/react @tscircuit/core"
try {
console.log("Installing dependencies...")
const installCommand =
packageManager === "yarn"
? `yarn add -D ${dependencies}`
: packageManager === "pnpm"
? `pnpm add -D ${dependencies}`
: packageManager === "bun"
? `bun add -D ${dependencies}`
: `npm install -D ${dependencies}`
execSync(installCommand, { stdio: "inherit" })
console.log("Dependencies installed successfully.")
} catch (error) {
console.error("Failed to install dependencies:", error)
}

// Generate tsconfig.json
generateTsConfig(currentDir)

console.log(
`Initialization complete. Run "tsci dev" to start developing.`,
)
Expand Down
2 changes: 1 addition & 1 deletion example-dir/snippet2-large-led-matrix.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export default () => {
ySpacing: 5,
offsetX: 3 - 122,
offsetY: -32 / 2 - 7.5,
}).map(({ center, index, row, col }) => {
}).map(({ center, index }) => {
const ledName = `LED${index + 1}`
const prevLedName = index > 0 ? `LED${index}` : null
const capName = `C_${ledName}`
Expand Down
17 changes: 17 additions & 0 deletions example-dir/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "ES6",
"module": "ESNext",
"jsx": "react-jsx",
"outDir": "dist",
"strict": true,
"esModuleInterop": true,
"moduleResolution": "node",
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"sourceMap": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true
}
}
20 changes: 20 additions & 0 deletions example-dir/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,23 @@ declare module "@tsci/seveibar.push-button" {
declare module "@tsci/seveibar.smd-usb-c" {
export function useUsbC(name: string): any
}

declare module "@tsci/seveibar.PICO_W" {
export function usePICO_W(name: string): any
}

declare module "@tsci/seveibar.HS91L02W2C01" {
export function useHS91L02W2C01(name: string): any
}

declare module "@tsci/seveibar.WS2812B_2020" {
interface WS2812B_2020Props {
schX: number
schY: number
name: string
pcbX: number
pcbY: number
}

export const WS2812B_2020: React.FC<WS2812B_2020Props>
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@tscircuit/fake-snippets": "^0.0.5",
"@types/bun": "^1.1.15",
"@types/configstore": "^6.0.2",
"@types/react": "^19.0.1",
"@types/react": "^19.0.8",
"@types/semver": "^7.5.8",
"get-port": "^7.1.0",
"tempy": "^3.1.0",
Expand All @@ -33,7 +33,7 @@
"dependencies": {
"@tscircuit/file-server": "^0.0.13",
"@tscircuit/runframe": "^0.0.47",
"chokidar": "^4.0.1",
"chokidar": "4.0.1",
"commander": "^12.1.0",
"configstore": "^7.0.0",
"cosmiconfig": "^9.0.0",
Expand Down
34 changes: 34 additions & 0 deletions tests/cli/init/init.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { getCliTestFixture } from "../../fixtures/get-cli-test-fixture"
import { test, expect } from "bun:test"
import { join } from "node:path"
import { execSync } from "node:child_process"

test("init command installs @types/react and passes type-checking", async () => {
const { tmpDir, runCommand } = await getCliTestFixture()

const { stdout } = await runCommand("tsci init")
console.log(stdout)

const pkgJsonPath = join(tmpDir, "package.json")
const pkgJson = JSON.parse(await Bun.file(pkgJsonPath).text())
expect(pkgJson.devDependencies["@types/react"]).toBeDefined()
expect(pkgJson.devDependencies["@tscircuit/core"]).toBeDefined()

const npmrcPath = join(tmpDir, ".npmrc")
const npmrcContent = await Bun.file(npmrcPath).text()
expect(npmrcContent).toContain("@tsci:registry=https://npm.tscircuit.com")

const tsconfigPath = join(tmpDir, "tsconfig.json")
const tsconfigExists = await Bun.file(tsconfigPath).exists()
expect(tsconfigExists).toBeTrue()

try {
const typeCheckResult = execSync("npx tsc --noEmit", {
cwd: tmpDir,
stdio: "pipe",
})
console.log(typeCheckResult.toString())
} catch (error) {
throw new Error("Type-checking failed")
}
})

0 comments on commit 0d8dbea

Please sign in to comment.