@tscircuit/cli 0.0.82 → 0.0.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.lockb +0 -0
- package/dev-server-api/bun.lockb +0 -0
- package/dev-server-api/routes/api/dev_package_examples/get.ts +4 -0
- package/dev-server-api/routes/api/dev_package_examples/list.ts +1 -0
- package/dev-server-api/routes/api/dev_package_examples/update.ts +16 -2
- package/dev-server-api/src/db/create-schema.ts +3 -0
- package/dev-server-api/src/db/get-db.ts +2 -0
- package/dev-server-frontend/bun.lockb +0 -0
- package/dev-server-frontend/package-lock.json +273 -54
- package/dev-server-frontend/package.json +3 -3
- package/dev-server-frontend/src/ExampleContentView.tsx +34 -4
- package/dev-server-frontend/src/HeaderMenu.tsx +4 -4
- package/dist/cli.js +214 -58
- package/lib/cmd-fns/dev/derive-selector-from-pcb-component-id.ts +23 -0
- package/lib/cmd-fns/dev/index.ts +4 -1
- package/lib/cmd-fns/dev/start-edit-event-watcher.ts +219 -0
- package/lib/cmd-fns/dev/start-export-request-watcher.ts +7 -1
- package/lib/cmd-fns/init/index.ts +39 -6
- package/package.json +9 -5
- package/tests/assets/example-project/examples/basic-bug.tsx +26 -14
- package/tests/assets/example-project/package-lock.json +96 -19
- package/tests/assets/example-project/package.json +2 -2
- package/tests/assets/example-project/src/MyCircuit.tsx +9 -1
- package/tests/assets/example-project/src/manual-edits.ts +37 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AnySoupElement } from "@tscircuit/builder"
|
|
2
|
+
import { su } from "@tscircuit/soup-util"
|
|
3
|
+
|
|
4
|
+
export const deriveSelectorFromPcbComponentId = ({
|
|
5
|
+
soup,
|
|
6
|
+
pcb_component_id,
|
|
7
|
+
}: {
|
|
8
|
+
soup: AnySoupElement[]
|
|
9
|
+
pcb_component_id: string
|
|
10
|
+
}) => {
|
|
11
|
+
const source_component = su(soup).source_component.getUsing({
|
|
12
|
+
pcb_component_id,
|
|
13
|
+
})
|
|
14
|
+
if (!source_component) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
`Could not find source component for pcb_component_id="${pcb_component_id}"`
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// TODO travel up the tree to make the selector more specific
|
|
21
|
+
|
|
22
|
+
return `.${source_component.name}`
|
|
23
|
+
}
|
package/lib/cmd-fns/dev/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { checkIfInitialized } from "./check-if-initialized"
|
|
|
14
14
|
import { initCmd } from "../init"
|
|
15
15
|
import { startExportRequestWatcher } from "./start-export-request-watcher"
|
|
16
16
|
import $ from "dax-sh"
|
|
17
|
+
import { startEditEventWatcher } from "./start-edit-event-watcher"
|
|
17
18
|
|
|
18
19
|
export const devCmd = async (ctx: AppContext, args: any) => {
|
|
19
20
|
const params = z
|
|
@@ -75,9 +76,10 @@ export const devCmd = async (ctx: AppContext, args: any) => {
|
|
|
75
76
|
console.log(`Loading examples...`)
|
|
76
77
|
await uploadExamplesFromDirectory({ devServerAxios, cwd }, ctx)
|
|
77
78
|
|
|
78
|
-
// Start
|
|
79
|
+
// Start watchers
|
|
79
80
|
const fs_watcher = await startFsWatcher({ cwd, devServerAxios }, ctx)
|
|
80
81
|
const er_watcher = await startExportRequestWatcher({ devServerAxios }, ctx)
|
|
82
|
+
const ee_watcher = await startEditEventWatcher({ devServerAxios }, ctx)
|
|
81
83
|
|
|
82
84
|
while (true) {
|
|
83
85
|
const { action } = await prompts({
|
|
@@ -108,6 +110,7 @@ export const devCmd = async (ctx: AppContext, args: any) => {
|
|
|
108
110
|
if (server.close) server.close()
|
|
109
111
|
fs_watcher.stop()
|
|
110
112
|
er_watcher.stop()
|
|
113
|
+
ee_watcher.stop()
|
|
111
114
|
break
|
|
112
115
|
}
|
|
113
116
|
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { DevPackageExample } from "@server/db/get-db"
|
|
2
|
+
import { AxiosInstance } from "axios"
|
|
3
|
+
import kleur from "kleur"
|
|
4
|
+
import { AppContext } from "lib/util/app-context"
|
|
5
|
+
import fg from "fast-glob"
|
|
6
|
+
import fs from "fs"
|
|
7
|
+
import { Project, ts } from "ts-morph"
|
|
8
|
+
import * as Path from "path"
|
|
9
|
+
import { ManualPcbPosition } from "@tscircuit/builder"
|
|
10
|
+
import { deriveSelectorFromPcbComponentId } from "./derive-selector-from-pcb-component-id"
|
|
11
|
+
|
|
12
|
+
// TODO import from builder when builder exports it
|
|
13
|
+
type EditEvent = {
|
|
14
|
+
edit_event_id: string
|
|
15
|
+
pcb_edit_event_type: "edit_component_location"
|
|
16
|
+
pcb_component_id: string
|
|
17
|
+
original_center: { x: number; y: number }
|
|
18
|
+
new_center: { x: number; y: number }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const startEditEventWatcher = async (
|
|
22
|
+
{
|
|
23
|
+
devServerAxios,
|
|
24
|
+
}: {
|
|
25
|
+
devServerAxios: AxiosInstance
|
|
26
|
+
},
|
|
27
|
+
ctx: AppContext
|
|
28
|
+
) => {
|
|
29
|
+
let running = true
|
|
30
|
+
|
|
31
|
+
;(async () => {
|
|
32
|
+
let last_edit_event_update_time: Record<string, string> = {}
|
|
33
|
+
|
|
34
|
+
while (running) {
|
|
35
|
+
try {
|
|
36
|
+
const dev_package_examples: DevPackageExample[] = await devServerAxios
|
|
37
|
+
.post("/api/dev_package_examples/list", {})
|
|
38
|
+
.then((r) => r.data.dev_package_examples)
|
|
39
|
+
|
|
40
|
+
for (const dev_package_example of dev_package_examples) {
|
|
41
|
+
const dev_package_example_id: number =
|
|
42
|
+
dev_package_example.dev_package_example_id as any
|
|
43
|
+
|
|
44
|
+
const last_recorded_update_time =
|
|
45
|
+
last_edit_event_update_time[dev_package_example_id]
|
|
46
|
+
|
|
47
|
+
// TODO use last_edit_event_updated_at
|
|
48
|
+
if (
|
|
49
|
+
last_recorded_update_time !== dev_package_example.last_updated_at
|
|
50
|
+
) {
|
|
51
|
+
console.log(
|
|
52
|
+
kleur.gray(
|
|
53
|
+
`Edit event detected for dev_package_example ${dev_package_example.dev_package_example_id}`
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
console.log(
|
|
57
|
+
kleur.gray(` file_path: ${dev_package_example.file_path}`)
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
last_edit_event_update_time[dev_package_example_id] =
|
|
61
|
+
dev_package_example.last_updated_at // TODO last_edit_event_updated_at
|
|
62
|
+
|
|
63
|
+
console.log(kleur.gray(` getting new edit events...`))
|
|
64
|
+
|
|
65
|
+
const dev_package_example_full = await devServerAxios
|
|
66
|
+
.post("/api/dev_package_examples/get", {
|
|
67
|
+
dev_package_example_id,
|
|
68
|
+
})
|
|
69
|
+
.then((r) => r.data.dev_package_example)
|
|
70
|
+
|
|
71
|
+
// 1. Find the *.manual-edits.ts, if there are multiple error
|
|
72
|
+
const manual_edit_files = fg.sync(
|
|
73
|
+
["**/*.manual-edits.ts", "**/manual-edits.ts"],
|
|
74
|
+
{
|
|
75
|
+
cwd: ctx.cwd,
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
if (manual_edit_files.length === 0) {
|
|
80
|
+
console.log(
|
|
81
|
+
kleur.red(
|
|
82
|
+
`No manual edit files found in "${ctx.cwd}", please create a file "manual-edits.ts" or "*.manual-edits.ts" to persist manual edits`
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
continue
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (manual_edit_files.length > 1) {
|
|
89
|
+
console.log(
|
|
90
|
+
kleur.red(
|
|
91
|
+
`Multiple manual edit files found, tsci currently doesn't know how to handle this, you should go upvote an issue`
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
continue
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const manual_edit_file = manual_edit_files[0]
|
|
98
|
+
const manual_edit_file_content = fs.readFileSync(
|
|
99
|
+
Path.join(ctx.cwd, manual_edit_file),
|
|
100
|
+
"utf-8"
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
console.log(
|
|
104
|
+
kleur.gray(` found manual edit file: ${manual_edit_file}`)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
// 2. Convert the edit events into ManualPcbPosition[] and append,
|
|
108
|
+
// removing any old placements/positions for the same selector.
|
|
109
|
+
// We can completely rewrite the file here for now (we'll need
|
|
110
|
+
// to preserve comments etc. later)
|
|
111
|
+
|
|
112
|
+
const edit_events: EditEvent[] =
|
|
113
|
+
dev_package_example_full.completed_edit_events ?? []
|
|
114
|
+
|
|
115
|
+
if (edit_events.length === 0) continue
|
|
116
|
+
|
|
117
|
+
const project = new Project()
|
|
118
|
+
|
|
119
|
+
const ts_manual_edits_file = project.createSourceFile(
|
|
120
|
+
"manual-edits.ts",
|
|
121
|
+
manual_edit_file_content
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
// Access the default export declaration
|
|
125
|
+
const default_export_dec = ts_manual_edits_file
|
|
126
|
+
.getDefaultExportSymbol()!
|
|
127
|
+
.getDeclarations()[0]
|
|
128
|
+
|
|
129
|
+
// Get the object literal expression from the export default statement
|
|
130
|
+
const object_literal =
|
|
131
|
+
default_export_dec.getFirstChildByKindOrThrow(
|
|
132
|
+
ts.SyntaxKind.ObjectLiteralExpression
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
// Get the `pcb_placements` property
|
|
136
|
+
const pcb_placements_ts =
|
|
137
|
+
object_literal.getPropertyOrThrow("pcb_placements")
|
|
138
|
+
|
|
139
|
+
let pcb_placements: (ManualPcbPosition & {
|
|
140
|
+
_edit_event_id?: string
|
|
141
|
+
})[]
|
|
142
|
+
try {
|
|
143
|
+
pcb_placements = JSON.parse(
|
|
144
|
+
pcb_placements_ts.getText().replace(/pcb_placements:\s/, "")
|
|
145
|
+
)
|
|
146
|
+
} catch (e: any) {
|
|
147
|
+
console.log(
|
|
148
|
+
kleur.red(
|
|
149
|
+
`Error parsing pcb_placements from manual edits file: ${pcb_placements_ts.getText()} ${e.toString()}`
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
continue
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const handled_edit_events = new Set<string>(
|
|
156
|
+
pcb_placements
|
|
157
|
+
.map((p) => (p as any)._edit_event_id)
|
|
158
|
+
.filter(Boolean)
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
// Add PCB placements from edit events
|
|
162
|
+
for (const edit_event of edit_events) {
|
|
163
|
+
if (handled_edit_events.has(edit_event.edit_event_id)) continue
|
|
164
|
+
|
|
165
|
+
// TODO Figure out a good selector for this pcb_component
|
|
166
|
+
const selector = deriveSelectorFromPcbComponentId({
|
|
167
|
+
soup: dev_package_example_full.tscircuit_soup,
|
|
168
|
+
pcb_component_id: edit_event.pcb_component_id,
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
const existing_placement_for_selector = pcb_placements.find(
|
|
172
|
+
(pp) => pp.selector === selector
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
if (!existing_placement_for_selector) {
|
|
176
|
+
console.log(
|
|
177
|
+
kleur.gray(
|
|
178
|
+
` adding PCB placement from edit event for "${selector}"`
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
pcb_placements.push({
|
|
183
|
+
_edit_event_id: edit_event.edit_event_id,
|
|
184
|
+
selector,
|
|
185
|
+
center: edit_event.new_center,
|
|
186
|
+
relative_to: "group_center",
|
|
187
|
+
})
|
|
188
|
+
} else {
|
|
189
|
+
existing_placement_for_selector.center = edit_event.new_center
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Edit the pcb placements object
|
|
193
|
+
pcb_placements_ts.replaceWithText(
|
|
194
|
+
`pcb_placements: ${JSON.stringify(pcb_placements, null, " ")}`
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
// Save the file
|
|
198
|
+
|
|
199
|
+
fs.writeFileSync(
|
|
200
|
+
Path.join(ctx.cwd, manual_edit_file),
|
|
201
|
+
ts_manual_edits_file.getFullText()
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
} catch (err: any) {
|
|
207
|
+
console.log(kleur.red(`Error in edit event watcher: ${err.toString()}`))
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
211
|
+
}
|
|
212
|
+
})()
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
stop: () => {
|
|
216
|
+
running = false
|
|
217
|
+
},
|
|
218
|
+
}
|
|
219
|
+
}
|
|
@@ -15,7 +15,13 @@ export const startExportRequestWatcher = async (
|
|
|
15
15
|
|
|
16
16
|
;(async () => {
|
|
17
17
|
while (running) {
|
|
18
|
-
|
|
18
|
+
try {
|
|
19
|
+
await fulfillExportRequests({ dev_server_axios: devServerAxios }, ctx)
|
|
20
|
+
} catch (err: any) {
|
|
21
|
+
console.log(
|
|
22
|
+
kleur.red(`Error in export request watcher: ${err.toString()}`)
|
|
23
|
+
)
|
|
24
|
+
}
|
|
19
25
|
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
20
26
|
}
|
|
21
27
|
})()
|
|
@@ -45,7 +45,7 @@ export const initCmd = async (ctx: AppContext, args: any) => {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
let runtime = params.runtime
|
|
48
|
+
let runtime = params.runtime ?? ctx.runtime
|
|
49
49
|
if (!runtime) {
|
|
50
50
|
const bunExists = $.commandExistsSync("bun")
|
|
51
51
|
|
|
@@ -94,6 +94,10 @@ export const initCmd = async (ctx: AppContext, args: any) => {
|
|
|
94
94
|
packageJson.scripts.build = "tsup ./index.ts --sourcemap --dts"
|
|
95
95
|
writeFileSync("package.json", JSON.stringify(packageJson, null, 2))
|
|
96
96
|
|
|
97
|
+
console.log('Making package type: "module"...')
|
|
98
|
+
packageJson.type = "module"
|
|
99
|
+
writeFileSync("package.json", JSON.stringify(packageJson, null, 2))
|
|
100
|
+
|
|
97
101
|
console.log(`Adding ".tscircuit" to .gitignore`)
|
|
98
102
|
appendFileSync(".gitignore", "\n.tscircuit\n*.__tmp_entrypoint.tsx\ndist", {
|
|
99
103
|
encoding: "utf-8",
|
|
@@ -107,15 +111,44 @@ export const initCmd = async (ctx: AppContext, args: any) => {
|
|
|
107
111
|
mkdirSync("examples", { recursive: true })
|
|
108
112
|
mkdirSync("lib", { recursive: true })
|
|
109
113
|
|
|
114
|
+
writeFileSync(
|
|
115
|
+
Path.join("lib", "MyCircuit.manual-edits.ts"),
|
|
116
|
+
`
|
|
117
|
+
/**
|
|
118
|
+
* DO NOT EDIT THIS FILE DIRECTLY!
|
|
119
|
+
*
|
|
120
|
+
* This file is automatically edited when running \`tsci dev\` and dragging things
|
|
121
|
+
* around. \`tsci dev\` searches for a file named "*.manual-edits.ts" and edits
|
|
122
|
+
* it when you e.g. move a footprint. If there are multiple files, it'll try
|
|
123
|
+
* to pick one based on context or ask.
|
|
124
|
+
*
|
|
125
|
+
* If you're not running \`tsci dev\`, you can safely edit this file.
|
|
126
|
+
*/
|
|
127
|
+
export default {
|
|
128
|
+
// Generated when this file is created, this unique identifier is used to help
|
|
129
|
+
// determine which file to edit when there are many *.manual-edits.ts files
|
|
130
|
+
manual_edit_id: "abcdef",
|
|
131
|
+
|
|
132
|
+
// Manual pcb placements, added when you drag a footprint
|
|
133
|
+
pcb_placements: [],
|
|
134
|
+
}
|
|
135
|
+
`.trim()
|
|
136
|
+
)
|
|
137
|
+
|
|
110
138
|
writeFileSync(
|
|
111
139
|
Path.join("lib", "MyCircuit.tsx"),
|
|
112
140
|
`
|
|
141
|
+
import { layout } from "tscircuit"
|
|
142
|
+
import manual_edits from "./MyCircuit.manual-edits"
|
|
143
|
+
|
|
113
144
|
export const MyCircuit = () => (
|
|
114
|
-
<
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
145
|
+
<group layout={layout().manualPcbPositions(manual_edits.pcb_placements)}>
|
|
146
|
+
<resistor
|
|
147
|
+
resistance="10kohm"
|
|
148
|
+
name="R1"
|
|
149
|
+
footprint="0805"
|
|
150
|
+
/>
|
|
151
|
+
</group>
|
|
119
152
|
)
|
|
120
153
|
`.trim()
|
|
121
154
|
)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.84",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Command line tool for developing, publishing and installing tscircuit circuits",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"bootstrap": "bun i && cd dev-server-api && bun i && cd ../dev-server-frontend && bun i",
|
|
10
10
|
"bootstrap:ci": "bun i --frozen-lockfile && cd dev-server-api && bun i --frozen-lockfile && cd ../dev-server-frontend && bun i --frozen-lockfile",
|
|
11
11
|
"start": "bun cli.ts",
|
|
12
|
-
"
|
|
12
|
+
"dev": "TSCI_DEV_SERVER_DB=$(pwd)/.tscircuit/dev-server.sqlite concurrently 'cd dev-server-api && bun run build && bun start' 'cd dev-server-frontend && bun start' 'bun run dev-with-test-project'",
|
|
13
|
+
"clear": "rm -rf .tscircuit",
|
|
13
14
|
"start:dev-server": "bun build:dev-server && bun cli.ts dev -y --cwd ./tests/assets/example-project",
|
|
14
15
|
"build:dev-server": "cd dev-server-api && bun run build && cd ../dev-server-frontend && bun run build",
|
|
15
16
|
"build:dev-server:api": "cd dev-server-api && bun run build",
|
|
@@ -17,7 +18,7 @@
|
|
|
17
18
|
"build": "bun build:dev-server && npm run build:cli",
|
|
18
19
|
"dev-with-test-project": "bun cli.ts dev --cwd ./tests/assets/example-project",
|
|
19
20
|
"test:init": "bun cli.ts init --dir ./tmp/test --name test",
|
|
20
|
-
"update-deps": "
|
|
21
|
+
"update-deps": "npm add @tscircuit/builder@latest @tscircuit/react-fiber@latest && cd dev-server-frontend && npm run update-deps && cd ../tests/assets/example-project && npm add @tscircuit/builder@latest @tscircuit/react-fiber@latest"
|
|
21
22
|
},
|
|
22
23
|
"bin": {
|
|
23
24
|
"tscircuit": "./dist/cli.js",
|
|
@@ -35,8 +36,9 @@
|
|
|
35
36
|
"dependencies": {
|
|
36
37
|
"@edge-runtime/primitives": "^4.1.0",
|
|
37
38
|
"@hono/node-server": "^1.8.2",
|
|
38
|
-
"@tscircuit/builder": "1.5.
|
|
39
|
-
"@tscircuit/react-fiber": "^1.0.
|
|
39
|
+
"@tscircuit/builder": "^1.5.86",
|
|
40
|
+
"@tscircuit/react-fiber": "^1.0.39",
|
|
41
|
+
"@tscircuit/soup-util": "^0.0.1",
|
|
40
42
|
"archiver": "^7.0.1",
|
|
41
43
|
"axios": "^1.6.7",
|
|
42
44
|
"better-sqlite3": "^9.4.3",
|
|
@@ -49,6 +51,7 @@
|
|
|
49
51
|
"delay": "^6.0.0",
|
|
50
52
|
"edgespec": "^0.0.69",
|
|
51
53
|
"esbuild": "^0.20.2",
|
|
54
|
+
"fast-glob": "^3.3.2",
|
|
52
55
|
"glob": "^10.3.10",
|
|
53
56
|
"hono": "^4.1.0",
|
|
54
57
|
"ignore": "^5.3.1",
|
|
@@ -63,6 +66,7 @@
|
|
|
63
66
|
"prompts": "^2.4.2",
|
|
64
67
|
"react": "^18.2.0",
|
|
65
68
|
"semver": "^7.6.0",
|
|
69
|
+
"ts-morph": "^22.0.0",
|
|
66
70
|
"tsup": "^8.0.2",
|
|
67
71
|
"zod": "latest"
|
|
68
72
|
},
|
|
@@ -1,16 +1,28 @@
|
|
|
1
|
+
import { layout } from "@tscircuit/layout"
|
|
2
|
+
import manual_edits from "../src/manual-edits"
|
|
3
|
+
|
|
1
4
|
export const BasicBug = () => (
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
<group
|
|
6
|
+
layout={layout()
|
|
7
|
+
.autoLayoutSchematic()
|
|
8
|
+
.manualPcbPlacement(manual_edits.pcb_placements)}
|
|
9
|
+
>
|
|
10
|
+
<bug
|
|
11
|
+
name="U2"
|
|
12
|
+
port_arrangement={{
|
|
13
|
+
left_size: 4,
|
|
14
|
+
right_size: 4,
|
|
15
|
+
}}
|
|
16
|
+
footprint="sparkfun:ssop16"
|
|
17
|
+
center={[-10, 0]}
|
|
18
|
+
port_labels={{
|
|
19
|
+
"1": "GND",
|
|
20
|
+
"2": "VBUS",
|
|
21
|
+
"3": "D-",
|
|
22
|
+
"4": "D+",
|
|
23
|
+
}}
|
|
24
|
+
/>
|
|
25
|
+
<resistor name="R1" resistance="10kohm" footprint="0805" />
|
|
26
|
+
<trace from=".U2 > .1" to=".R1 > .left" />
|
|
27
|
+
</group>
|
|
16
28
|
)
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
"name": "example-project",
|
|
9
9
|
"version": "1.2.26",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@tscircuit/builder": "^1.5.
|
|
12
|
-
"@tscircuit/react-fiber": "^1.0.
|
|
11
|
+
"@tscircuit/builder": "^1.5.86",
|
|
12
|
+
"@tscircuit/react-fiber": "^1.0.39"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"node_modules/@babel/runtime": {
|
|
@@ -29,14 +29,17 @@
|
|
|
29
29
|
"integrity": "sha512-iB+oaYyaVK1hQ0cODubnoSDg4gGYL9cp/4ad7G1b9Z0/IqehPztp5qE3KP2mV9Ns0UYmzwvtkEhTCmKUuhorbg=="
|
|
30
30
|
},
|
|
31
31
|
"node_modules/@tscircuit/builder": {
|
|
32
|
-
"version": "1.5.
|
|
33
|
-
"resolved": "https://registry.npmjs.org/@tscircuit/builder/-/builder-1.5.
|
|
34
|
-
"integrity": "sha512-
|
|
32
|
+
"version": "1.5.86",
|
|
33
|
+
"resolved": "https://registry.npmjs.org/@tscircuit/builder/-/builder-1.5.86.tgz",
|
|
34
|
+
"integrity": "sha512-hZZvpo6t84kd66BfLE120eTLgoEUv42iEjxtQS6IeOUXk7y+pSMYwS16L+HHjmivKKRx0BOO+KmYFRsqi18mdw==",
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@lume/kiwi": "^0.1.0",
|
|
37
37
|
"@tscircuit/footprints": "^0.0.14",
|
|
38
|
+
"@tscircuit/layout": "^0.0.7",
|
|
38
39
|
"@tscircuit/routing": "^1.3.1",
|
|
39
|
-
"@tscircuit/
|
|
40
|
+
"@tscircuit/schematic-autolayout": "^0.0.5",
|
|
41
|
+
"@tscircuit/soup-util": "^0.0.1",
|
|
42
|
+
"@tscircuit/sparkfun-packages": "^1.2.1",
|
|
40
43
|
"convert-units": "^2.3.4",
|
|
41
44
|
"fast-json-stable-stringify": "^2.1.0",
|
|
42
45
|
"format-si-prefix": "^0.3.2",
|
|
@@ -57,6 +60,18 @@
|
|
|
57
60
|
"typescript": "^5.0.0"
|
|
58
61
|
}
|
|
59
62
|
},
|
|
63
|
+
"node_modules/@tscircuit/layout": {
|
|
64
|
+
"version": "0.0.7",
|
|
65
|
+
"resolved": "https://registry.npmjs.org/@tscircuit/layout/-/layout-0.0.7.tgz",
|
|
66
|
+
"integrity": "sha512-Jdd6j0+p4yK8zAqFX7dgmb5PT8A9KJduDBhEgAm+OgwDrw3Mp0hQ80pbR2Mvm02UF2Gu9H7TWpMytACCoNqPdA==",
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"transformation-matrix": "^2.16.1"
|
|
69
|
+
},
|
|
70
|
+
"peerDependencies": {
|
|
71
|
+
"@tscircuit/builder": "*",
|
|
72
|
+
"zod": "*"
|
|
73
|
+
}
|
|
74
|
+
},
|
|
60
75
|
"node_modules/@tscircuit/mm": {
|
|
61
76
|
"version": "0.0.4",
|
|
62
77
|
"resolved": "https://registry.npmjs.org/@tscircuit/mm/-/mm-0.0.4.tgz",
|
|
@@ -69,9 +84,9 @@
|
|
|
69
84
|
}
|
|
70
85
|
},
|
|
71
86
|
"node_modules/@tscircuit/react-fiber": {
|
|
72
|
-
"version": "1.0.
|
|
73
|
-
"resolved": "https://registry.npmjs.org/@tscircuit/react-fiber/-/react-fiber-1.0.
|
|
74
|
-
"integrity": "sha512-
|
|
87
|
+
"version": "1.0.39",
|
|
88
|
+
"resolved": "https://registry.npmjs.org/@tscircuit/react-fiber/-/react-fiber-1.0.39.tgz",
|
|
89
|
+
"integrity": "sha512-xdEghvKDm9xr5j+zvEH8VVLj6haYCsQ5V8vNOyuXLoc63o7B/Maibsp5Yf6DdoC+SsxYYdZIt8cc0lAj7REfFg==",
|
|
75
90
|
"dependencies": {
|
|
76
91
|
"react-reconciler": "^0.29.0"
|
|
77
92
|
},
|
|
@@ -89,10 +104,31 @@
|
|
|
89
104
|
"react-error-boundary": "^4.0.11"
|
|
90
105
|
}
|
|
91
106
|
},
|
|
107
|
+
"node_modules/@tscircuit/schematic-autolayout": {
|
|
108
|
+
"version": "0.0.5",
|
|
109
|
+
"resolved": "https://registry.npmjs.org/@tscircuit/schematic-autolayout/-/schematic-autolayout-0.0.5.tgz",
|
|
110
|
+
"integrity": "sha512-I4CtLQfqTPTxDSumnquaJtkJkc16VjLC4bwU3jQdBXwwh9ODzBf88clUznUtDDzwV+BPM5P0W0VCfFhvPL3/Cw==",
|
|
111
|
+
"dependencies": {
|
|
112
|
+
"react": "^18.2.0",
|
|
113
|
+
"react-dom": "^18.2.0",
|
|
114
|
+
"react-supergrid": "^1.0.10",
|
|
115
|
+
"transformation-matrix": "^2.16.1",
|
|
116
|
+
"use-mouse-matrix-transform": "^1.1.12"
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"node_modules/@tscircuit/soup-util": {
|
|
120
|
+
"version": "0.0.1",
|
|
121
|
+
"resolved": "https://registry.npmjs.org/@tscircuit/soup-util/-/soup-util-0.0.1.tgz",
|
|
122
|
+
"integrity": "sha512-hNJayJ/Z+Clms1uAv8j6TCkK2aVNrm/C0PnAUcbSMY3gZfA+os7ovTxS/hCJfC22K4wHoBwsbZ+mE8R3KxaFfQ==",
|
|
123
|
+
"peerDependencies": {
|
|
124
|
+
"@tscircuit/builder": "*",
|
|
125
|
+
"zod": "*"
|
|
126
|
+
}
|
|
127
|
+
},
|
|
92
128
|
"node_modules/@tscircuit/sparkfun-packages": {
|
|
93
|
-
"version": "1.2.
|
|
94
|
-
"resolved": "https://registry.npmjs.org/@tscircuit/sparkfun-packages/-/sparkfun-packages-1.2.
|
|
95
|
-
"integrity": "sha512-
|
|
129
|
+
"version": "1.2.1",
|
|
130
|
+
"resolved": "https://registry.npmjs.org/@tscircuit/sparkfun-packages/-/sparkfun-packages-1.2.1.tgz",
|
|
131
|
+
"integrity": "sha512-2HzmmHydo5vgoKmNBAHd6RD93LaIMXRSt6t//1zx19/ZwrOA43qVOvb7cCTA82GHib1bSxoL7bqgii9sYudCHw==",
|
|
96
132
|
"dependencies": {
|
|
97
133
|
"change-case": "^5.4.3"
|
|
98
134
|
}
|
|
@@ -359,10 +395,9 @@
|
|
|
359
395
|
}
|
|
360
396
|
},
|
|
361
397
|
"node_modules/react": {
|
|
362
|
-
"version": "18.
|
|
363
|
-
"resolved": "https://registry.npmjs.org/react/-/react-18.
|
|
364
|
-
"integrity": "sha512
|
|
365
|
-
"peer": true,
|
|
398
|
+
"version": "18.3.1",
|
|
399
|
+
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
|
400
|
+
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
|
366
401
|
"dependencies": {
|
|
367
402
|
"loose-envify": "^1.1.0"
|
|
368
403
|
},
|
|
@@ -370,6 +405,18 @@
|
|
|
370
405
|
"node": ">=0.10.0"
|
|
371
406
|
}
|
|
372
407
|
},
|
|
408
|
+
"node_modules/react-dom": {
|
|
409
|
+
"version": "18.3.1",
|
|
410
|
+
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
|
411
|
+
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
|
412
|
+
"dependencies": {
|
|
413
|
+
"loose-envify": "^1.1.0",
|
|
414
|
+
"scheduler": "^0.23.2"
|
|
415
|
+
},
|
|
416
|
+
"peerDependencies": {
|
|
417
|
+
"react": "^18.3.1"
|
|
418
|
+
}
|
|
419
|
+
},
|
|
373
420
|
"node_modules/react-error-boundary": {
|
|
374
421
|
"version": "4.0.13",
|
|
375
422
|
"resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz",
|
|
@@ -396,6 +443,16 @@
|
|
|
396
443
|
"react": "^18.2.0"
|
|
397
444
|
}
|
|
398
445
|
},
|
|
446
|
+
"node_modules/react-supergrid": {
|
|
447
|
+
"version": "1.0.10",
|
|
448
|
+
"resolved": "https://registry.npmjs.org/react-supergrid/-/react-supergrid-1.0.10.tgz",
|
|
449
|
+
"integrity": "sha512-dJd9wkH6BJkdfkv62EcRAIBn59e2wj58bJFVXiW/ZHQzxz20qIql63fTU2qFMOujXnBIDaMG0uTod67/mjEGeA==",
|
|
450
|
+
"peerDependencies": {
|
|
451
|
+
"react": "*",
|
|
452
|
+
"react-dom": "*",
|
|
453
|
+
"transformation-matrix": "*"
|
|
454
|
+
}
|
|
455
|
+
},
|
|
399
456
|
"node_modules/rectilinear-router": {
|
|
400
457
|
"version": "1.0.1",
|
|
401
458
|
"resolved": "https://registry.npmjs.org/rectilinear-router/-/rectilinear-router-1.0.1.tgz",
|
|
@@ -419,9 +476,9 @@
|
|
|
419
476
|
}
|
|
420
477
|
},
|
|
421
478
|
"node_modules/scheduler": {
|
|
422
|
-
"version": "0.23.
|
|
423
|
-
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.
|
|
424
|
-
"integrity": "sha512-
|
|
479
|
+
"version": "0.23.2",
|
|
480
|
+
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
|
481
|
+
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
|
|
425
482
|
"dependencies": {
|
|
426
483
|
"loose-envify": "^1.1.0"
|
|
427
484
|
}
|
|
@@ -462,6 +519,26 @@
|
|
|
462
519
|
"engines": {
|
|
463
520
|
"node": ">=14.17"
|
|
464
521
|
}
|
|
522
|
+
},
|
|
523
|
+
"node_modules/use-mouse-matrix-transform": {
|
|
524
|
+
"version": "1.1.13",
|
|
525
|
+
"resolved": "https://registry.npmjs.org/use-mouse-matrix-transform/-/use-mouse-matrix-transform-1.1.13.tgz",
|
|
526
|
+
"integrity": "sha512-NsP0j0Ifv9TywhqrNGfIhjpGzuyEzPK553ahn+LBVvZHZ6Gv+2T3tn41pJV6Syos1W7crWKolbP+XLfqa5BpCQ==",
|
|
527
|
+
"dependencies": {
|
|
528
|
+
"transformation-matrix": "^2.14.0"
|
|
529
|
+
},
|
|
530
|
+
"peerDependencies": {
|
|
531
|
+
"react": "^18.2.0"
|
|
532
|
+
}
|
|
533
|
+
},
|
|
534
|
+
"node_modules/zod": {
|
|
535
|
+
"version": "3.23.6",
|
|
536
|
+
"resolved": "https://registry.npmjs.org/zod/-/zod-3.23.6.tgz",
|
|
537
|
+
"integrity": "sha512-RTHJlZhsRbuA8Hmp/iNL7jnfc4nZishjsanDAfEY1QpDQZCahUp3xDzl+zfweE9BklxMUcgBgS1b7Lvie/ZVwA==",
|
|
538
|
+
"peer": true,
|
|
539
|
+
"funding": {
|
|
540
|
+
"url": "https://github.com/sponsors/colinhacks"
|
|
541
|
+
}
|
|
465
542
|
}
|
|
466
543
|
}
|
|
467
544
|
}
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import "@tscircuit/react-fiber"
|
|
2
|
+
import { layout } from "@tscircuit/layout"
|
|
3
|
+
import manual_edits from "./manual-edits"
|
|
2
4
|
|
|
3
5
|
export const MyCircuit = () => (
|
|
4
|
-
<board
|
|
6
|
+
<board
|
|
7
|
+
width="40mm"
|
|
8
|
+
height="40mm"
|
|
9
|
+
center_x={0}
|
|
10
|
+
center_y={0}
|
|
11
|
+
layout={layout().manualPcbPlacement(manual_edits.pcb_placements)}
|
|
12
|
+
>
|
|
5
13
|
<resistor
|
|
6
14
|
name="R1"
|
|
7
15
|
resistance="20kohm"
|