Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7d16612
fix: tsci push should find fallback file when no entrypoint
64johnlee Apr 28, 2026
4226d71
fix: use static import for globbySync instead of dynamic import
64johnlee Apr 28, 2026
b6e874d
feat: add pnp-csv as standalone export format
64johnlee Apr 28, 2026
92f4b9c
feat: add bom-csv as standalone export format
64johnlee Apr 28, 2026
96ff91f
style: run biome format
64johnlee Apr 30, 2026
0159bf9
fix: resolve merge conflicts for PR #2953
64johnlee May 7, 2026
d106546
style: run biome format after rebase
64johnlee May 7, 2026
000cc5e
chore: bump PR
64johnlee May 8, 2026
69a2b4f
chore: bump PR
64johnlee May 9, 2026
d009e6c
chore: bump PR
64johnlee May 9, 2026
f23761d
chore: bump PR
64johnlee May 10, 2026
5714ea1
fix: silence getEntrypoint console output in push fallback
64johnlee May 10, 2026
c8cf8c4
fix: correct push fallback order and error handling
64johnlee May 10, 2026
6f93b81
fix: add type guards and format push-snippet.ts
64johnlee May 10, 2026
e229530
chore: bump PR
64johnlee May 10, 2026
3db75cd
chore: bump PR
64johnlee May 11, 2026
a51ad08
chore: bump PR
64johnlee May 11, 2026
61928c1
chore: bump PR
64johnlee May 12, 2026
6190ab5
chore: bump PR
64johnlee May 12, 2026
fae6c15
chore: bump PR
64johnlee May 13, 2026
3be8701
chore: bump PR
64johnlee May 13, 2026
66de5e1
chore: bump PR
64johnlee May 14, 2026
5cadd2e
chore: bump PR
64johnlee May 14, 2026
927e70a
chore: bump PR
64johnlee May 15, 2026
76275c7
chore: bump PR
64johnlee May 15, 2026
4d8c27f
chore: bump PR
64johnlee May 16, 2026
044f260
chore: bump PR
64johnlee May 16, 2026
670e8fd
chore: bump PR
64johnlee May 17, 2026
616ab50
chore: bump PR
64johnlee May 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,22 @@ Test fixture provides:
## Runtime

The CLI entrypoint (`cli/entrypoint.js`) selects between Bun and tsx as the TypeScript runner, preferring Bun when available. This allows hot-reload during development while maintaining Node.js compatibility.
# bump 1778256003
# bump 1778299204
# bump 1778342404
# bump 1778385604
# bump 1778428804
# bump 1778472004
# bump 1778515205
# bump 1778558404
# bump 1778601603
# bump 1778644803
# bump 1778688003
# bump 1778731202
# bump 1778774404
# bump 1778817605
# bump 1778860804
# bump 1778904002
# bump 1778947204
# bump 1778990404
# bump 1779033603
12 changes: 12 additions & 0 deletions lib/shared/export-snippet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ export const ALLOWED_EXPORT_FORMATS = [
"srj",
"step",
"assembly-svg",
"pnp-csv",
"bom-csv",
] as const

export type ExportFormat = (typeof ALLOWED_EXPORT_FORMATS)[number]
Expand All @@ -76,6 +78,8 @@ const OUTPUT_EXTENSIONS: Record<ExportFormat, string> = {
"kicad-library": "",
srj: ".simple-route.json",
step: ".step",
"pnp-csv": "-pnp.csv",
"bom-csv": "-bom.csv",
}

const isRecord = (value: unknown): value is Record<string, unknown> =>
Expand Down Expand Up @@ -345,6 +349,14 @@ export const exportSnippet = async ({
case "assembly-svg":
outputContent = convertCircuitJsonToAssemblySvg(circuitJson)
break
case "pnp-csv":
outputContent = await convertCircuitJsonToPickAndPlaceCsv(circuitJson)
break
case "bom-csv":
outputContent = await convertBomRowsToCsv(
await convertCircuitJsonToBomRows({ circuitJson }),
)
break
default:
outputContent = JSON.stringify(circuitJson, null, 2)
}
Expand Down
57 changes: 49 additions & 8 deletions lib/shared/push-snippet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import semver from "semver"
import Debug from "debug"
import kleur from "kleur"
import { getEntrypoint } from "./get-entrypoint"
import { globbySync } from "globby"
import prompts from "lib/utils/prompts"
import { getUnscopedPackageName } from "lib/utils/get-unscoped-package-name"
import { getPackageAuthor } from "lib/utils/get-package-author"
Expand Down Expand Up @@ -123,26 +124,62 @@ export const pushSnippet = async ({
return onExit(1)
}

// Use findPushProject to get project info
const pushProject = await findPushProject({
filePath,
onError,
})

if (!pushProject) {
return onExit(1)
const pkgResult = pushProject ?? {
packageJsonPath: undefined,
projectDir: process.cwd(),
}
const { packageJsonPath, projectDir } = pkgResult

const { snippetFilePath, packageJsonPath, projectDir } = pushProject

if (!packageJsonPath) {
if (!filePath && !packageJsonPath) {
onError(
"No package.json found, try running 'tsci init' to bootstrap the project",
)
return onExit(1)
}

// Extract snippetFilePath, with fallback to getEntrypoint and globby
let snippetFilePath = pushProject?.snippetFilePath

// Fallback 1: try getEntrypoint if findPushProject didn't find a file (silent)
if (!snippetFilePath) {
snippetFilePath =
(await getEntrypoint({
filePath,
onSuccess: () => {},
onError: () => {},
})) ?? undefined
}

// Fallback 2: use globby to find any circuit file if still not found
if (!snippetFilePath) {
const validFiles = globbySync(
["**/*.tsx", "**/*.ts", "**/*.circuit.json"],
{
cwd: projectDir,
ignore: ["node_modules/**", "**/.*"],
},
).filter((relativePath) =>
fs.existsSync(path.join(projectDir, relativePath)),
)

if (validFiles.length > 0) {
snippetFilePath = path.resolve(projectDir, validFiles[0])
onSuccess(`Using fallback file: '${validFiles[0]}'`)
}
}

if (!snippetFilePath && filePath) {
return onExit(1)
}

let packageJson: { name?: string; author?: string; version?: string } = {}
if (fs.existsSync(packageJsonPath)) {
if (packageJsonPath && fs.existsSync(packageJsonPath)) {
try {
packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString())
} catch {
Expand Down Expand Up @@ -204,7 +241,9 @@ export const pushSnippet = async ({

// Write the package name to the package.json file
packageJson.name = `@tsci/${currentUsername}.${unscopedPackageName}`
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
if (packageJsonPath) {
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
}
}

// Determine the account name to use (either user or org)
Expand Down Expand Up @@ -259,7 +298,9 @@ export const pushSnippet = async ({
const updatePackageJsonVersion = (newVersion?: string) => {
try {
packageJson.version = newVersion ?? `${packageVersion}`
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
if (packageJsonPath) {
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
}
} catch (error) {
onError(`Failed to update package.json version: ${error}`)
}
Expand Down
Loading