@tscircuit/ti 1.0.1
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/README.md +54 -0
- package/cli/import.mjs +104 -0
- package/cli/main.mjs +111 -0
- package/cli/ti.mjs +4 -0
- package/index.cjs +14712 -0
- package/index.d.ts +6675 -0
- package/index.js +14412 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# @tscircuit/ti
|
|
2
|
+
|
|
3
|
+
Texas Instruments chip components and reusable reference subcircuits for
|
|
4
|
+
[tscircuit](https://github.com/tscircuit/ti).
|
|
5
|
+
|
|
6
|
+
## Install in a circuit project
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npm install @tscircuit/ti tscircuit react
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
import { BQ24074, PowerMonitor_INA237 } from "@tscircuit/ti";
|
|
14
|
+
|
|
15
|
+
export default () => (
|
|
16
|
+
<board width="30mm" height="20mm">
|
|
17
|
+
<BQ24074 name="U1" />
|
|
18
|
+
<PowerMonitor_INA237 name="Monitor" />
|
|
19
|
+
</board>
|
|
20
|
+
);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The package includes ESM, CommonJS, and TypeScript declarations. Node.js 22.14
|
|
24
|
+
or newer is required. React, tscircuit, and `@tscircuit/props` are peer dependencies so the library
|
|
25
|
+
uses the same runtime as your circuit project.
|
|
26
|
+
|
|
27
|
+
## Global installation
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
npm install -g @tscircuit/ti
|
|
31
|
+
ti search "buck converter"
|
|
32
|
+
ti search --json "buck converter"
|
|
33
|
+
ti import TPS62160DSGR
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The `ti search` command searches the same Texas Instruments catalog as
|
|
37
|
+
`tsci search --ti`, returning up to 10 components. Queries can be quoted or
|
|
38
|
+
passed as separate words. Use `--json` for `{ query, results }` output, including
|
|
39
|
+
TI metadata and `source: "ti"` on every result, or `ti --help` for usage.
|
|
40
|
+
|
|
41
|
+
`ti import TPS62160DSGR` finds the exact manufacturer part in LCSC/JLCPCB,
|
|
42
|
+
converts its EasyEDA symbol and footprint, and writes `imports/TPS62160DSGR.tsx`.
|
|
43
|
+
You can also use an LCSC ID directly: `ti import C324077`.
|
|
44
|
+
Use the result with `import { TPS62160DSGR } from "./imports/TPS62160DSGR"`.
|
|
45
|
+
Existing files are never overwritten. Imports require an internet connection
|
|
46
|
+
and an available EasyEDA part. They contain individual chips, not complete
|
|
47
|
+
reference subcircuits; available 3D models remain remote links.
|
|
48
|
+
|
|
49
|
+
Global installation does not make imports resolve in local projects; install
|
|
50
|
+
the package in each project where you use its components.
|
|
51
|
+
|
|
52
|
+
See the [library documentation](https://github.com/tscircuit/ti#readme) for the
|
|
53
|
+
available chips, reference subcircuits, and connection examples. Examples using
|
|
54
|
+
`@tsci/tscircuit.ti` have the same exports; use `@tscircuit/ti` for npm imports.
|
package/cli/import.mjs
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { parseArgs } from "node:util";
|
|
4
|
+
import {
|
|
5
|
+
convertRawEasyEdaToTs,
|
|
6
|
+
EasyEdaJsonSchema,
|
|
7
|
+
fetchEasyEDAComponent,
|
|
8
|
+
normalizeManufacturerPartNumber,
|
|
9
|
+
} from "easyeda";
|
|
10
|
+
|
|
11
|
+
const help = `Usage: ti import <part-number>
|
|
12
|
+
|
|
13
|
+
Import an EasyEDA chip as editable TSX into ./imports/.
|
|
14
|
+
Use an exact manufacturer part number or an LCSC ID (C-number).
|
|
15
|
+
Existing files are not overwritten.
|
|
16
|
+
|
|
17
|
+
Examples:
|
|
18
|
+
ti import TPS62160DSGR
|
|
19
|
+
ti import C324077`;
|
|
20
|
+
|
|
21
|
+
export async function runImport(args, { fetch, stdout, stderr, cwd }) {
|
|
22
|
+
try {
|
|
23
|
+
const { values, positionals } = parseArgs({
|
|
24
|
+
args,
|
|
25
|
+
allowPositionals: true,
|
|
26
|
+
options: { help: { type: "boolean", short: "h" } },
|
|
27
|
+
});
|
|
28
|
+
if (values.help) {
|
|
29
|
+
stdout(help);
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
if (positionals.length !== 1 || !positionals[0].trim()) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
"An exact part number is required. Usage: ti import <part-number>",
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const query = positionals[0].trim();
|
|
39
|
+
const directLcsc = /^C[1-9]\d*$/i.test(query);
|
|
40
|
+
let lcscPartNumber = query.toUpperCase();
|
|
41
|
+
if (!directLcsc) {
|
|
42
|
+
const response = await fetch(
|
|
43
|
+
"https://jlcsearch.tscircuit.com/api/search?limit=10&q=" +
|
|
44
|
+
encodeURIComponent(query),
|
|
45
|
+
);
|
|
46
|
+
if (!response.ok)
|
|
47
|
+
throw new Error(`LCSC search failed (HTTP ${response.status})`);
|
|
48
|
+
const data = await response.json();
|
|
49
|
+
if (!Array.isArray(data?.components))
|
|
50
|
+
throw new Error("LCSC search returned an invalid response");
|
|
51
|
+
const match = data.components.find(
|
|
52
|
+
(part) =>
|
|
53
|
+
part?.mfr?.trim().toUpperCase() === query.toUpperCase() &&
|
|
54
|
+
Number.isSafeInteger(part.lcsc) &&
|
|
55
|
+
part.lcsc > 0,
|
|
56
|
+
);
|
|
57
|
+
if (!match) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
`No exact LCSC match for "${query}". Use the full manufacturer part number or an LCSC ID (C-number).`,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
lcscPartNumber = `C${match.lcsc}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const rawEasy = await fetchEasyEDAComponent(lcscPartNumber, { fetch });
|
|
66
|
+
const component = EasyEdaJsonSchema.parse(rawEasy);
|
|
67
|
+
const manufacturerPart = component.dataStr.head.c_para["Manufacturer Part"];
|
|
68
|
+
if (
|
|
69
|
+
!manufacturerPart?.trim() ||
|
|
70
|
+
component.lcsc.number.toUpperCase() !== lcscPartNumber ||
|
|
71
|
+
(!directLcsc &&
|
|
72
|
+
manufacturerPart.trim().toUpperCase() !== query.toUpperCase())
|
|
73
|
+
) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`EasyEDA returned a different or missing part identity for "${query}"`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const componentName = normalizeManufacturerPartNumber(manufacturerPart);
|
|
80
|
+
const tsx = await convertRawEasyEdaToTs({ rawEasy });
|
|
81
|
+
const directory = join(cwd, "imports");
|
|
82
|
+
const filename = `${componentName}.tsx`;
|
|
83
|
+
await mkdir(directory, { recursive: true });
|
|
84
|
+
try {
|
|
85
|
+
await writeFile(join(directory, filename), `${tsx}\n`, { flag: "wx" });
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (error?.code === "EEXIST")
|
|
88
|
+
throw new Error(
|
|
89
|
+
`imports/${filename} already exists; no files were overwritten.`,
|
|
90
|
+
);
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
stdout(`Imported imports/${filename} from EasyEDA (${lcscPartNumber}).`);
|
|
94
|
+
stdout(
|
|
95
|
+
`Use: import { ${componentName} } from "./imports/${componentName}"`,
|
|
96
|
+
);
|
|
97
|
+
return 0;
|
|
98
|
+
} catch (error) {
|
|
99
|
+
stderr(
|
|
100
|
+
`Failed to import: ${error instanceof Error ? error.message : String(error)}`,
|
|
101
|
+
);
|
|
102
|
+
return 1;
|
|
103
|
+
}
|
|
104
|
+
}
|
package/cli/main.mjs
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
|
|
3
|
+
const help = `Usage: ti search [options] <query...>
|
|
4
|
+
ti import <part-number>
|
|
5
|
+
|
|
6
|
+
Search Texas Instruments components or import a chip from EasyEDA.
|
|
7
|
+
|
|
8
|
+
Options:
|
|
9
|
+
--json Output search results as JSON
|
|
10
|
+
-h, --help Show help
|
|
11
|
+
|
|
12
|
+
Examples:
|
|
13
|
+
ti search "buck converter"
|
|
14
|
+
ti search --json TPS62160
|
|
15
|
+
ti import TPS62160DSGR
|
|
16
|
+
ti import C324077`;
|
|
17
|
+
|
|
18
|
+
export async function runCli(
|
|
19
|
+
argv,
|
|
20
|
+
{
|
|
21
|
+
fetch = globalThis.fetch,
|
|
22
|
+
stdout = console.log,
|
|
23
|
+
stderr = console.error,
|
|
24
|
+
cwd = process.cwd(),
|
|
25
|
+
} = {},
|
|
26
|
+
) {
|
|
27
|
+
const [command, ...args] = argv;
|
|
28
|
+
if (!command || command === "--help" || command === "-h") {
|
|
29
|
+
stdout(help);
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
if (command === "import") {
|
|
33
|
+
const { runImport } = await import("./import.mjs");
|
|
34
|
+
return runImport(args, { fetch, stdout, stderr, cwd });
|
|
35
|
+
}
|
|
36
|
+
if (command !== "search") {
|
|
37
|
+
stderr(`Unknown command "${command}". Run ti --help for usage.`);
|
|
38
|
+
return 1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let parsed;
|
|
42
|
+
try {
|
|
43
|
+
parsed = parseArgs({
|
|
44
|
+
args,
|
|
45
|
+
allowPositionals: true,
|
|
46
|
+
options: {
|
|
47
|
+
json: { type: "boolean" },
|
|
48
|
+
help: { type: "boolean", short: "h" },
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
} catch (error) {
|
|
52
|
+
stderr(error instanceof Error ? error.message : String(error));
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
if (parsed.values.help) {
|
|
56
|
+
stdout(help);
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const query = parsed.positionals.join(" ").trim();
|
|
61
|
+
if (!query) {
|
|
62
|
+
stderr("A search query is required. Usage: ti search [options] <query...>");
|
|
63
|
+
return 1;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const response = await fetch(
|
|
68
|
+
"https://tisearch.tscircuit.com/api/search?limit=10&q=" +
|
|
69
|
+
encodeURIComponent(query),
|
|
70
|
+
);
|
|
71
|
+
if (!response.ok)
|
|
72
|
+
throw new Error(`TI search failed (HTTP ${response.status})`);
|
|
73
|
+
const data = await response.json();
|
|
74
|
+
if (!Array.isArray(data?.components))
|
|
75
|
+
throw new Error("TI search returned an invalid response");
|
|
76
|
+
|
|
77
|
+
if (parsed.values.json) {
|
|
78
|
+
stdout(
|
|
79
|
+
JSON.stringify(
|
|
80
|
+
{
|
|
81
|
+
query,
|
|
82
|
+
results: data.components.map((component) => ({
|
|
83
|
+
...component,
|
|
84
|
+
source: "ti",
|
|
85
|
+
})),
|
|
86
|
+
},
|
|
87
|
+
null,
|
|
88
|
+
2,
|
|
89
|
+
),
|
|
90
|
+
);
|
|
91
|
+
} else if (!data.components.length) {
|
|
92
|
+
stdout(`No results found for "${query}" in Texas Instruments.`);
|
|
93
|
+
} else {
|
|
94
|
+
stdout(
|
|
95
|
+
[
|
|
96
|
+
`Found ${data.components.length} component(s) in TI search:`,
|
|
97
|
+
...data.components.map(
|
|
98
|
+
(component, index) =>
|
|
99
|
+
`${index + 1}. ${component.mfr} - ${component.description} (stock: ${component.stock.toLocaleString("en-US")})`,
|
|
100
|
+
),
|
|
101
|
+
].join("\n"),
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
return 0;
|
|
105
|
+
} catch (error) {
|
|
106
|
+
stderr(
|
|
107
|
+
`Failed to search: ${error instanceof Error ? error.message : String(error)}`,
|
|
108
|
+
);
|
|
109
|
+
return 1;
|
|
110
|
+
}
|
|
111
|
+
}
|
package/cli/ti.mjs
ADDED