@bingran/sbti-cli 0.1.0
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/LICENSE +21 -0
- package/NOTICE +13 -0
- package/README.md +322 -0
- package/README.zh-CN.md +319 -0
- package/bin/sbti-cli.cjs +33 -0
- package/lib/platform-package.cjs +117 -0
- package/package.json +45 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bingran You
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
This repository includes original code and documentation authored for `sbti-cli`,
|
|
2
|
+
which are released under the MIT License in `LICENSE`.
|
|
3
|
+
|
|
4
|
+
This repository may also contain third-party content derived from the upstream
|
|
5
|
+
SBTI website at https://sbti.fancc.de5.net/, including but not limited to:
|
|
6
|
+
|
|
7
|
+
- survey prompts
|
|
8
|
+
- result descriptions
|
|
9
|
+
- extracted character artwork / poster images
|
|
10
|
+
|
|
11
|
+
Those upstream materials remain subject to their original ownership and are not
|
|
12
|
+
relicensed by this repository unless the original rights holder states
|
|
13
|
+
otherwise.
|
package/README.md
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
<h1 align="center">SBTI CLI - Test SBTI for your agents.</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<em>SBTI CLI - Test SBTI for your agents.</em><br>
|
|
5
|
+
A Node.js CLI with <strong>offline-only execution</strong>, <strong>bundled survey data</strong>, and <strong>result-image export</strong>.
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a href="https://sbti.fancc.de5.net"><img alt="Original test" src="https://img.shields.io/badge/original-sbti.fancc.de5.net-4CAF50?style=flat-square"></a>
|
|
10
|
+
<img alt="Node.js" src="https://img.shields.io/badge/Node.js-18%2B-339933?style=flat-square">
|
|
11
|
+
<img alt="Runtime mode" src="https://img.shields.io/badge/runtime-offline--only-blue?style=flat-square">
|
|
12
|
+
<img alt="Result images" src="https://img.shields.io/badge/result%20images-27-orange?style=flat-square">
|
|
13
|
+
<img alt="Questions" src="https://img.shields.io/badge/questions-30%20%2B%201%20hidden-purple?style=flat-square">
|
|
14
|
+
<img alt="License" src="https://img.shields.io/badge/license-MIT-red?style=flat-square">
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<a href="./README.md"><img alt="English" src="https://img.shields.io/badge/English-current-111827?style=for-the-badge"></a>
|
|
19
|
+
<a href="./README.zh-CN.md"><img alt="简体中文" src="https://img.shields.io/badge/简体中文-click_to_switch-EF4444?style=for-the-badge"></a>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
<p align="center">
|
|
23
|
+
<img src="assets/type-images/CTRL.png" width="130" alt="CTRL">
|
|
24
|
+
<img src="assets/type-images/BOSS.png" width="130" alt="BOSS">
|
|
25
|
+
<img src="assets/type-images/SEXY.png" width="130" alt="SEXY">
|
|
26
|
+
<img src="assets/type-images/MALO.png" width="130" alt="MALO">
|
|
27
|
+
<img src="assets/type-images/DRUNK.png" width="130" alt="DRUNK">
|
|
28
|
+
<img src="assets/type-images/HHHH.png" width="130" alt="HHHH">
|
|
29
|
+
</p>
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 📖 Table of Contents
|
|
34
|
+
|
|
35
|
+
- [📖 Table of Contents](#-table-of-contents)
|
|
36
|
+
- [🎯 What Is This](#-what-is-this)
|
|
37
|
+
- [🧭 Installation \& Setup](#-installation--setup)
|
|
38
|
+
- [🧪 Using the CLI](#-using-the-cli)
|
|
39
|
+
- [Common Commands](#common-commands)
|
|
40
|
+
- [Interactive Controls](#interactive-controls)
|
|
41
|
+
- [Typical Run](#typical-run)
|
|
42
|
+
- [🧬 Core Capabilities](#-core-capabilities)
|
|
43
|
+
- [🎭 Result Images \& Offline Resources](#-result-images--offline-resources)
|
|
44
|
+
- [Export All Result Images](#export-all-result-images)
|
|
45
|
+
- [🔬 Data Sources \& How It Works](#-data-sources--how-it-works)
|
|
46
|
+
- [Why It Can Match the Website So Closely](#why-it-can-match-the-website-so-closely)
|
|
47
|
+
- [Where the Poster Art Comes From](#where-the-poster-art-comes-from)
|
|
48
|
+
- [Most Important Files in This Repo](#most-important-files-in-this-repo)
|
|
49
|
+
- [🙏 Acknowledgements](#-acknowledgements)
|
|
50
|
+
- [📄 License](#-license)
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 🎯 What Is This
|
|
55
|
+
|
|
56
|
+
This repository turns **SBTI** into a local command-line runner.
|
|
57
|
+
|
|
58
|
+
Key traits:
|
|
59
|
+
|
|
60
|
+
- 🎲 **Website-equivalent question flow**
|
|
61
|
+
- 📊 **Website-equivalent scoring**
|
|
62
|
+
- 📴 **Offline-safe execution**
|
|
63
|
+
- 🖼️ **Exportable result posters**
|
|
64
|
+
- ✅ **Regression coverage**
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 🧭 Installation & Setup
|
|
69
|
+
|
|
70
|
+
### Install From npm
|
|
71
|
+
|
|
72
|
+
For agent runs or normal CLI use, install the published package and run the binary directly:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npm install -g @bingran/sbti-cli
|
|
76
|
+
sbti-cli
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
or:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npx @bingran/sbti-cli
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The npm install surface is intentionally small: the root `@bingran/sbti-cli` package only ships a tiny launcher, and npm pulls the matching platform-native binary package for your machine. The published package does **not** ship the repository source tree, tests, build scripts, or image assets.
|
|
86
|
+
|
|
87
|
+
Current native package targets:
|
|
88
|
+
|
|
89
|
+
- macOS `arm64`
|
|
90
|
+
- macOS `x64`
|
|
91
|
+
- Linux `arm64`
|
|
92
|
+
- Linux `x64`
|
|
93
|
+
- Windows `x64`
|
|
94
|
+
|
|
95
|
+
### Clone The Repo For Development
|
|
96
|
+
|
|
97
|
+
If you want the test suite, image-export tooling, or source code itself, use the repository checkout:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
git clone https://github.com/bingran-you/sbti-cli.git
|
|
101
|
+
cd sbti-cli
|
|
102
|
+
npm install
|
|
103
|
+
npm test
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Then start the development CLI with:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npm run sbti
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
or:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
node src/cli.mjs
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
> 💡 There is no database, browser driver, or `.env` setup required. If Node.js is installed, you can run either the published CLI or the repo-local development entry point.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 🧪 Using the CLI
|
|
123
|
+
|
|
124
|
+
### Common Commands
|
|
125
|
+
|
|
126
|
+
| Command | Purpose |
|
|
127
|
+
|---|---|
|
|
128
|
+
| `sbti-cli` | Start a normal interactive run from the published npm package |
|
|
129
|
+
| `sbti-cli --seed 42` | Use a deterministic shuffle seed |
|
|
130
|
+
| `sbti-cli --json` | Print the final result as JSON |
|
|
131
|
+
| `npm run sbti` | Start the repo-local development entry point |
|
|
132
|
+
| `npm run export-images` | Rebuild the local poster manifest and gallery from bundled assets in a repo checkout |
|
|
133
|
+
|
|
134
|
+
### Interactive Controls
|
|
135
|
+
|
|
136
|
+
Once the CLI starts, you answer one question at a time:
|
|
137
|
+
Each answer is locked in for that run as soon as you submit it.
|
|
138
|
+
|
|
139
|
+
| Input | Action |
|
|
140
|
+
|---|---|
|
|
141
|
+
| `A / B / C / D` | Select the current option |
|
|
142
|
+
| `q` | Quit without submitting |
|
|
143
|
+
|
|
144
|
+
### Typical Run
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
sbti-cli
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
SBTI CLI
|
|
152
|
+
Question source: bundled:sbti-main.js
|
|
153
|
+
|
|
154
|
+
Question 1 / 31 · dimension hidden
|
|
155
|
+
...
|
|
156
|
+
|
|
157
|
+
Enter A/B/C/D, or q to quit.
|
|
158
|
+
> C
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 🧬 Core Capabilities
|
|
164
|
+
|
|
165
|
+
<table>
|
|
166
|
+
<tr>
|
|
167
|
+
<th>Area</th>
|
|
168
|
+
<th>Capability</th>
|
|
169
|
+
<th>Details</th>
|
|
170
|
+
</tr>
|
|
171
|
+
<tr>
|
|
172
|
+
<td><strong>🛟 Offline runtime</strong></td>
|
|
173
|
+
<td>Always runs from the bundled snapshot</td>
|
|
174
|
+
<td>The CLI never fetches the live website at runtime, so every questionnaire run stays fully local</td>
|
|
175
|
+
</tr>
|
|
176
|
+
<tr>
|
|
177
|
+
<td><strong>🖼️ Result-image export</strong></td>
|
|
178
|
+
<td>27 bundled posters can be indexed locally</td>
|
|
179
|
+
<td>The repo can rebuild a JSON manifest and an HTML gallery from the checked-in image files</td>
|
|
180
|
+
</tr>
|
|
181
|
+
<tr>
|
|
182
|
+
<td><strong>🧪 Regression tests</strong></td>
|
|
183
|
+
<td>Bundled-runtime verification</td>
|
|
184
|
+
<td>Includes runtime parity, 50 deterministic result cases, and offline asset coverage</td>
|
|
185
|
+
</tr>
|
|
186
|
+
<tr>
|
|
187
|
+
<td><strong>📦 Native npm release</strong></td>
|
|
188
|
+
<td>Small launcher plus platform-native binary packages</td>
|
|
189
|
+
<td>Installing from npm no longer ships the repo source tree, tests, or build scripts with the runnable CLI</td>
|
|
190
|
+
</tr>
|
|
191
|
+
</table>
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## 🎭 Result Images & Offline Resources
|
|
196
|
+
|
|
197
|
+
This section is repository-only. The published npm CLI does not ship the poster assets or the export script.
|
|
198
|
+
|
|
199
|
+
<table>
|
|
200
|
+
<tr>
|
|
201
|
+
<td align="center" width="33%">
|
|
202
|
+
<a href="assets/type-images/index.html"><img src="assets/type-images/CTRL.png" width="180"><br><strong>Local result gallery</strong></a><br>
|
|
203
|
+
<sub>An HTML gallery generated from the extracted poster files</sub>
|
|
204
|
+
</td>
|
|
205
|
+
<td align="center" width="33%">
|
|
206
|
+
<a href="assets/type-images/manifest.json"><img src="assets/type-images/BOSS.png" width="180"><br><strong>Image manifest</strong></a><br>
|
|
207
|
+
<sub>File names, MIME types, and sizes for all exported posters</sub>
|
|
208
|
+
</td>
|
|
209
|
+
<td align="center" width="33%">
|
|
210
|
+
<a href="src/bundled-data.mjs"><img src="assets/type-images/SEXY.png" width="180"><br><strong>Offline snapshot</strong></a><br>
|
|
211
|
+
<sub>The built-in survey data used for every CLI run</sub>
|
|
212
|
+
</td>
|
|
213
|
+
</tr>
|
|
214
|
+
<tr>
|
|
215
|
+
<td align="center">
|
|
216
|
+
<a href="scripts/export-type-images.mjs"><img src="assets/type-images/MALO.png" width="180"><br><strong>Image export script</strong></a><br>
|
|
217
|
+
<sub>Rebuilds the local poster manifest and gallery from the checked-in image files</sub>
|
|
218
|
+
</td>
|
|
219
|
+
<td align="center">
|
|
220
|
+
<a href="test/runtime.test.mjs"><img src="assets/type-images/HHHH.png" width="180"><br><strong>Parity tests</strong></a><br>
|
|
221
|
+
<sub>Checks that CLI results stay aligned with the bundled scoring logic</sub>
|
|
222
|
+
</td>
|
|
223
|
+
</tr>
|
|
224
|
+
</table>
|
|
225
|
+
|
|
226
|
+
### Export All Result Images
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
npm run export-images
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
This generates:
|
|
233
|
+
|
|
234
|
+
- [`assets/type-images/index.html`](assets/type-images/index.html) — local gallery
|
|
235
|
+
- [`assets/type-images/manifest.json`](assets/type-images/manifest.json) — poster manifest
|
|
236
|
+
- [`assets/type-images/`](assets/type-images/) — all decoded `.png` / `.jpg` files
|
|
237
|
+
|
|
238
|
+
## 🔬 Data Sources & How It Works
|
|
239
|
+
|
|
240
|
+
### Why It Can Match the Website So Closely
|
|
241
|
+
|
|
242
|
+
This repository stores a bundled snapshot of the survey data and scoring logic in [`src/bundled-data.mjs`](src/bundled-data.mjs). [`src/runtime.mjs`](src/runtime.mjs) turns that snapshot into a sandboxed runtime so the CLI can stay local while preserving the original question flow and result math.
|
|
243
|
+
|
|
244
|
+
The CLI therefore uses the same runtime objects throughout every run:
|
|
245
|
+
|
|
246
|
+
| Runtime object | Content |
|
|
247
|
+
|---|---|
|
|
248
|
+
| `dimensionMeta` | Chinese labels and model groups for the 15 dimensions |
|
|
249
|
+
| `questions` | The 30 regular questions |
|
|
250
|
+
| `specialQuestions` | The drink-gate question set |
|
|
251
|
+
| `TYPE_LIBRARY` | Codes, names, intros, and full descriptions for all 27 result types |
|
|
252
|
+
| `NORMAL_TYPES` | The 25 normal H / M / L templates |
|
|
253
|
+
| `DIM_EXPLANATIONS` | Dimension explanations for each L / M / H tier |
|
|
254
|
+
| `computeResult()` | The website's own result-selection branch logic |
|
|
255
|
+
|
|
256
|
+
That is why the CLI can stay aligned with:
|
|
257
|
+
|
|
258
|
+
- question shuffle
|
|
259
|
+
- drink-gate insertion and hidden question reveal
|
|
260
|
+
- 15-dimension scoring and bucketing
|
|
261
|
+
- normal-type ranking
|
|
262
|
+
- `DRUNK` override
|
|
263
|
+
- `HHHH` low-similarity fallback
|
|
264
|
+
|
|
265
|
+
### Where the Poster Art Comes From
|
|
266
|
+
|
|
267
|
+
All 27 result posters are checked into [`assets/type-images/`](assets/type-images/). [`scripts/export-type-images.mjs`](scripts/export-type-images.mjs) rebuilds the manifest and gallery pages from those local files.
|
|
268
|
+
|
|
269
|
+
### Most Important Files in This Repo
|
|
270
|
+
|
|
271
|
+
- [`src/cli.mjs`](src/cli.mjs) — CLI entry point and interactive questionnaire flow
|
|
272
|
+
- [`src/runtime.mjs`](src/runtime.mjs) — bundled runtime loading, sandbox evaluation, and result summarization
|
|
273
|
+
- [`src/bundled-data.mjs`](src/bundled-data.mjs) — bundled offline snapshot
|
|
274
|
+
- [`src/type-images.mjs`](src/type-images.mjs) — image helpers and local gallery generation
|
|
275
|
+
- [`bin/sbti-cli.cjs`](bin/sbti-cli.cjs) — npm launcher that resolves the installed native binary package
|
|
276
|
+
- [`lib/platform-package.cjs`](lib/platform-package.cjs) — supported-platform map and native-package resolution helpers
|
|
277
|
+
- [`dist/sbti-cli.cjs`](dist/sbti-cli.cjs) — CommonJS single-file bundle used as the native-binary build input
|
|
278
|
+
- [`scripts/build-dist.mjs`](scripts/build-dist.mjs) — generates the single-file ESM/CJS CLI bundles
|
|
279
|
+
- [`scripts/build-platform-packages.mjs`](scripts/build-platform-packages.mjs) — builds precompiled native npm subpackages for each platform target
|
|
280
|
+
- [`scripts/publish-packages.mjs`](scripts/publish-packages.mjs) — publishes the native platform packages and then the root `@bingran/sbti-cli` package
|
|
281
|
+
- [`scripts/export-type-images.mjs`](scripts/export-type-images.mjs) — local poster metadata rebuild
|
|
282
|
+
- [`test/runtime.test.mjs`](test/runtime.test.mjs) — bundled runtime parity tests
|
|
283
|
+
- [`test/launcher.test.mjs`](test/launcher.test.mjs) — native-launcher package resolution coverage
|
|
284
|
+
- [`test/package.test.mjs`](test/package.test.mjs) — publish-tarball surface checks
|
|
285
|
+
- [`test/type-images.test.mjs`](test/type-images.test.mjs) — offline asset coverage
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## 🙏 Acknowledgements
|
|
290
|
+
|
|
291
|
+
<table>
|
|
292
|
+
<tr>
|
|
293
|
+
<th>Project</th>
|
|
294
|
+
<th>Author</th>
|
|
295
|
+
<th>Contribution</th>
|
|
296
|
+
</tr>
|
|
297
|
+
<tr>
|
|
298
|
+
<td><a href="https://sbti.fancc.de5.net"><strong>SBTI Personality Test</strong></a></td>
|
|
299
|
+
<td>Bilibili <a href="https://space.bilibili.com/417038183">@蛆肉儿串儿</a></td>
|
|
300
|
+
<td>Original survey author and source of the question text, result copy, and character artwork</td>
|
|
301
|
+
</tr>
|
|
302
|
+
<tr>
|
|
303
|
+
<td><a href="https://github.com/serenakeyitan/sbti-wiki"><strong>sbti-wiki</strong></a></td>
|
|
304
|
+
<td><a href="https://github.com/serenakeyitan">@serenakeyitan</a></td>
|
|
305
|
+
<td>The visual README format here was inspired by that project's centered hero, badges, image strip, and information-card layout</td>
|
|
306
|
+
</tr>
|
|
307
|
+
<tr>
|
|
308
|
+
<td><strong>sbti-cli</strong></td>
|
|
309
|
+
<td><a href="https://github.com/bingran-you">Bingran You (@bingran-you)</a></td>
|
|
310
|
+
<td>Built the sandboxed runtime loader, offline snapshot, image exporter, and regression test suite for a practical terminal workflow</td>
|
|
311
|
+
</tr>
|
|
312
|
+
</table>
|
|
313
|
+
|
|
314
|
+
> ⚠️ **For entertainment only**: the upstream site already warns against treating this as diagnosis, hiring criteria, relationship truth, fortune telling, or any serious judgment. This repo is a tooling and reference project, not a psychological assessment.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## 📄 License
|
|
319
|
+
|
|
320
|
+
The original code and documentation in this repository are released under the [MIT License](LICENSE).
|
|
321
|
+
|
|
322
|
+
Third-party survey prompts, result text, and extracted character artwork originate from the upstream SBTI website and remain subject to their original ownership. See [NOTICE](NOTICE) for attribution and scope.
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
<h1 align="center">SBTI CLI · 官网逻辑等效的命令行版</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<em>把 SBTI 人格测试搬进终端,同时尽量保留官网同一套运行时与结果资源。</em><br>
|
|
5
|
+
一个支持 <strong>纯离线运行</strong>、<strong>内置题库快照</strong>、<strong>结果图导出</strong> 的 Node.js CLI。
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a href="https://sbti.fancc.de5.net"><img alt="原测试" src="https://img.shields.io/badge/原测试-sbti.fancc.de5.net-4CAF50?style=flat-square"></a>
|
|
10
|
+
<img alt="Node.js" src="https://img.shields.io/badge/Node.js-18%2B-339933?style=flat-square">
|
|
11
|
+
<img alt="运行模式" src="https://img.shields.io/badge/运行模式-纯离线-blue?style=flat-square">
|
|
12
|
+
<img alt="结果图" src="https://img.shields.io/badge/结果图-27%20张-orange?style=flat-square">
|
|
13
|
+
<img alt="题目" src="https://img.shields.io/badge/题目-30%20%2B%201%20隐藏-purple?style=flat-square">
|
|
14
|
+
<img alt="许可证" src="https://img.shields.io/badge/许可证-MIT-red?style=flat-square">
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<a href="./README.md"><img alt="English" src="https://img.shields.io/badge/English-click_to_switch-2563EB?style=for-the-badge"></a>
|
|
19
|
+
<a href="./README.zh-CN.md"><img alt="简体中文" src="https://img.shields.io/badge/简体中文-当前-F0522D?style=for-the-badge"></a>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
<p align="center">
|
|
23
|
+
<img src="assets/type-images/CTRL.png" width="130" alt="CTRL">
|
|
24
|
+
<img src="assets/type-images/BOSS.png" width="130" alt="BOSS">
|
|
25
|
+
<img src="assets/type-images/SEXY.png" width="130" alt="SEXY">
|
|
26
|
+
<img src="assets/type-images/MALO.png" width="130" alt="MALO">
|
|
27
|
+
<img src="assets/type-images/DRUNK.png" width="130" alt="DRUNK">
|
|
28
|
+
<img src="assets/type-images/HHHH.png" width="130" alt="HHHH">
|
|
29
|
+
</p>
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 📖 目录
|
|
34
|
+
|
|
35
|
+
- [这是什么](#-这是什么)
|
|
36
|
+
- [如何安装与设置](#-如何安装与设置)
|
|
37
|
+
- [如何使用 CLI](#-如何使用-cli)
|
|
38
|
+
- [核心能力一览](#-核心能力一览)
|
|
39
|
+
- [结果图与离线资源](#-结果图与离线资源)
|
|
40
|
+
- [数据来源与原理](#-数据来源与原理)
|
|
41
|
+
- [鸣谢](#-鸣谢)
|
|
42
|
+
- [License](#-license)
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 🎯 这是什么
|
|
47
|
+
|
|
48
|
+
本仓库把 [**sbti.fancc.de5.net**](https://sbti.fancc.de5.net) 的 SBTI 人格测试做成了一个可在本地终端运行的 CLI。它不是手写一套“像官网”的逻辑,而是把题库和结果逻辑打包成内置快照,在本地 sandbox 中运行,因此保留了这些关键特性:
|
|
49
|
+
|
|
50
|
+
- 🎲 **和官网一致的题目行为**:30 道常规题随机顺序、饮酒分支插入位置、隐藏题触发规则都保持一致
|
|
51
|
+
- 📊 **和官网一致的结果计算**:15 维打分、H / M / L 分档、25 个标准人格匹配、`DRUNK` 覆盖、`HHHH` 兜底都保持一致
|
|
52
|
+
- 📴 **每次都纯离线运行**:CLI 每次都直接使用仓库内置快照,不依赖 live website
|
|
53
|
+
- 🖼️ **结果图可本地整理**:27 张结果海报已随仓库提供,可重建本地 manifest 与画廊
|
|
54
|
+
- ✅ **有对齐测试兜底**:除了基础单测,还包含 50 组结果回归测试与离线资源完整性验证
|
|
55
|
+
|
|
56
|
+
如果你想:
|
|
57
|
+
|
|
58
|
+
- 在终端里完整做一次 SBTI
|
|
59
|
+
- 用脚本研究结果逻辑
|
|
60
|
+
- 在完全离线的环境里继续跑测试
|
|
61
|
+
- 重建 27 张结果图的本地资源清单
|
|
62
|
+
|
|
63
|
+
这个仓库就是干这个的。
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 🧭 如何安装与设置
|
|
68
|
+
|
|
69
|
+
### 直接从 npm 安装
|
|
70
|
+
|
|
71
|
+
如果只是想让 agent 或普通用户直接跑 CLI,用 npm 安装发布包即可:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm install -g @bingran/sbti-cli
|
|
75
|
+
sbti-cli
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
或者:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npx @bingran/sbti-cli
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
npm 安装面现在被刻意收紧了:根包 `@bingran/sbti-cli` 只带一个很小的 launcher,安装时会自动拉取当前平台对应的 native binary 子包。发布到 npm 的内容 **不会** 再带上仓库源码、测试、构建脚本或结果图资源。
|
|
85
|
+
|
|
86
|
+
当前原生包目标平台:
|
|
87
|
+
|
|
88
|
+
- macOS `arm64`
|
|
89
|
+
- macOS `x64`
|
|
90
|
+
- Linux `arm64`
|
|
91
|
+
- Linux `x64`
|
|
92
|
+
- Windows `x64`
|
|
93
|
+
|
|
94
|
+
### 克隆仓库用于开发
|
|
95
|
+
|
|
96
|
+
如果你需要测试集、结果图导出工具或源码本身,再使用仓库 checkout:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
git clone https://github.com/bingran-you/sbti-cli.git
|
|
100
|
+
cd sbti-cli
|
|
101
|
+
npm install
|
|
102
|
+
npm test
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
然后可以用开发入口启动:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
npm run sbti
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
或者:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
node src/cli.mjs
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
> 💡 这个项目不需要数据库、浏览器驱动或 `.env` 配置;只要有 Node.js,就能运行发布版 CLI 或仓库内开发入口。
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## 🧪 如何使用 CLI
|
|
122
|
+
|
|
123
|
+
### 常用命令
|
|
124
|
+
|
|
125
|
+
| 命令 | 作用 |
|
|
126
|
+
|---|---|
|
|
127
|
+
| `sbti-cli` | 从 npm 发布包直接开始一次测试 |
|
|
128
|
+
| `sbti-cli --seed 42` | 固定随机种子,方便复现题目顺序 |
|
|
129
|
+
| `sbti-cli --json` | 直接输出 JSON 结果 |
|
|
130
|
+
| `npm run sbti` | 运行仓库内的开发入口 |
|
|
131
|
+
| `npm run export-images` | 在仓库 checkout 里重建 manifest 和本地画廊 |
|
|
132
|
+
|
|
133
|
+
### 交互方式
|
|
134
|
+
|
|
135
|
+
运行测试后,CLI 会逐题提问。输入方式和导航规则如下:
|
|
136
|
+
每个答案一旦提交,就会在本轮测试中锁定。
|
|
137
|
+
|
|
138
|
+
| 输入 | 作用 |
|
|
139
|
+
|---|---|
|
|
140
|
+
| `A / B / C / D` | 选择当前题的选项 |
|
|
141
|
+
| `q` | 中途退出,不提交结果 |
|
|
142
|
+
|
|
143
|
+
### 一个最常见的流程
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
sbti-cli
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
SBTI 人格测试 CLI
|
|
151
|
+
题库来源: bundled:sbti-main.js
|
|
152
|
+
|
|
153
|
+
第 1 题 / 31 · 维度已隐藏
|
|
154
|
+
...
|
|
155
|
+
|
|
156
|
+
输入 A/B/C/D 选择,或输入 q 退出。
|
|
157
|
+
> C
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## 🧬 核心能力一览
|
|
161
|
+
|
|
162
|
+
<table>
|
|
163
|
+
<tr>
|
|
164
|
+
<th>模块</th>
|
|
165
|
+
<th>能力</th>
|
|
166
|
+
<th>说明</th>
|
|
167
|
+
</tr>
|
|
168
|
+
<tr>
|
|
169
|
+
<td><strong>🛟 离线运行时</strong></td>
|
|
170
|
+
<td>始终直接加载内置快照</td>
|
|
171
|
+
<td>题目顺序、饮酒隐藏题、打分、匹配、特殊分支都走本地内置的同一套逻辑</td>
|
|
172
|
+
</tr>
|
|
173
|
+
<tr>
|
|
174
|
+
<td><strong>🖼️ 结果图资源</strong></td>
|
|
175
|
+
<td>27 张已收录海报可本地整理</td>
|
|
176
|
+
<td>支持生成 <code>manifest.json</code> 与本地 <code>index.html</code> 画廊</td>
|
|
177
|
+
</tr>
|
|
178
|
+
<tr>
|
|
179
|
+
<td><strong>🧪 回归测试</strong></td>
|
|
180
|
+
<td>内置运行时验证</td>
|
|
181
|
+
<td>包含 50 组结果回归、图片完整性测试与离线运行路径验证</td>
|
|
182
|
+
</tr>
|
|
183
|
+
<tr>
|
|
184
|
+
<td><strong>📦 原生 npm 发布</strong></td>
|
|
185
|
+
<td>小型 launcher + 平台 native binary 子包</td>
|
|
186
|
+
<td>通过 npm 安装时,不再把仓库源码、测试或构建脚本连同可运行 CLI 一起发出去</td>
|
|
187
|
+
</tr>
|
|
188
|
+
</table>
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## 🎭 结果图与离线资源
|
|
193
|
+
|
|
194
|
+
这一节是仓库开发资源,不属于发布到 npm 的 CLI 安装面。
|
|
195
|
+
|
|
196
|
+
<table>
|
|
197
|
+
<tr>
|
|
198
|
+
<td align="center" width="33%">
|
|
199
|
+
<a href="assets/type-images/index.html"><img src="assets/type-images/CTRL.png" width="180"><br><strong>本地结果图画廊</strong></a><br>
|
|
200
|
+
<sub>27 张海报导出后的可浏览 HTML 页面</sub>
|
|
201
|
+
</td>
|
|
202
|
+
<td align="center" width="33%">
|
|
203
|
+
<a href="assets/type-images/manifest.json"><img src="assets/type-images/BOSS.png" width="180"><br><strong>结果图清单</strong></a><br>
|
|
204
|
+
<sub>文件名、类型、字节数都收录在 manifest 里</sub>
|
|
205
|
+
</td>
|
|
206
|
+
<td align="center" width="33%">
|
|
207
|
+
<a href="src/bundled-data.mjs"><img src="assets/type-images/SEXY.png" width="180"><br><strong>离线快照</strong></a><br>
|
|
208
|
+
<sub>每次 CLI 运行都会直接使用的内置题库与结果数据</sub>
|
|
209
|
+
</td>
|
|
210
|
+
</tr>
|
|
211
|
+
<tr>
|
|
212
|
+
<td align="center">
|
|
213
|
+
<a href="scripts/export-type-images.mjs"><img src="assets/type-images/MALO.png" width="180"><br><strong>图片导出脚本</strong></a><br>
|
|
214
|
+
<sub>基于仓库内已有图片重建 manifest 和本地画廊</sub>
|
|
215
|
+
</td>
|
|
216
|
+
<td align="center">
|
|
217
|
+
<a href="test/runtime.test.mjs"><img src="assets/type-images/HHHH.png" width="180"><br><strong>对齐测试</strong></a><br>
|
|
218
|
+
<sub>确保 CLI 的结果分支和内置逻辑保持一致</sub>
|
|
219
|
+
</td>
|
|
220
|
+
</tr>
|
|
221
|
+
</table>
|
|
222
|
+
|
|
223
|
+
### 导出结果图
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
npm run export-images
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
执行后会生成:
|
|
230
|
+
|
|
231
|
+
- [`assets/type-images/index.html`](assets/type-images/index.html) — 本地画廊
|
|
232
|
+
- [`assets/type-images/manifest.json`](assets/type-images/manifest.json) — 27 张图片的清单
|
|
233
|
+
- [`assets/type-images/`](assets/type-images/) — 全部解码后的 `.png` / `.jpg` 文件
|
|
234
|
+
|
|
235
|
+
## 🔬 数据来源与原理
|
|
236
|
+
|
|
237
|
+
### 为什么能做到和官网行为一致
|
|
238
|
+
|
|
239
|
+
本仓库把题库和结果逻辑存成 [`src/bundled-data.mjs`](src/bundled-data.mjs) 里的内置快照,再通过 [`src/runtime.mjs`](src/runtime.mjs) 用 Node.js 的 `vm` 模块放进一个很小的 sandbox 里运行。
|
|
240
|
+
|
|
241
|
+
CLI 不是手写“差不多”的逻辑,而是每次都直接跑这份内置快照里的同一套对象:
|
|
242
|
+
|
|
243
|
+
| 运行时对象 | 内容 |
|
|
244
|
+
|---|---|
|
|
245
|
+
| `dimensionMeta` | 15 个维度的中文名与模型分组 |
|
|
246
|
+
| `questions` | 30 道常规题 |
|
|
247
|
+
| `specialQuestions` | 饮酒隐藏题与其前置分支 |
|
|
248
|
+
| `TYPE_LIBRARY` | 27 个人格的代号、中文名、开场白、完整描述 |
|
|
249
|
+
| `NORMAL_TYPES` | 25 个标准人格的 H / M / L 模板 |
|
|
250
|
+
| `DIM_EXPLANATIONS` | 15 维 × 3 档的维度文案 |
|
|
251
|
+
| `computeResult()` | 官网自己的结果分支逻辑 |
|
|
252
|
+
|
|
253
|
+
因此,CLI 可以和官网保持同一套:
|
|
254
|
+
|
|
255
|
+
- 题目 shuffle
|
|
256
|
+
- 饮酒题插入与隐藏题显示
|
|
257
|
+
- 15 维打分与分档
|
|
258
|
+
- 25 个标准人格匹配排序
|
|
259
|
+
- `DRUNK` 特殊覆盖
|
|
260
|
+
- `HHHH` 低匹配度兜底
|
|
261
|
+
|
|
262
|
+
### 结果图从哪里来
|
|
263
|
+
|
|
264
|
+
27 张人物海报已经随仓库一起存放在 [`assets/type-images/`](assets/type-images/) 中。[`scripts/export-type-images.mjs`](scripts/export-type-images.mjs) 负责根据这些本地文件重建 manifest 和本地画廊。
|
|
265
|
+
|
|
266
|
+
### 本仓库里最关键的文件
|
|
267
|
+
|
|
268
|
+
- [`src/cli.mjs`](src/cli.mjs) — 命令行交互入口
|
|
269
|
+
- [`src/runtime.mjs`](src/runtime.mjs) — 内置运行时加载、sandbox 运行、结果汇总
|
|
270
|
+
- [`src/bundled-data.mjs`](src/bundled-data.mjs) — CLI 使用的内置快照
|
|
271
|
+
- [`src/type-images.mjs`](src/type-images.mjs) — 图片工具与本地画廊生成
|
|
272
|
+
- [`bin/sbti-cli.cjs`](bin/sbti-cli.cjs) — npm launcher,会解析当前平台对应的 native binary 子包
|
|
273
|
+
- [`lib/platform-package.cjs`](lib/platform-package.cjs) — 支持的平台映射与 native package 解析逻辑
|
|
274
|
+
- [`dist/sbti-cli.cjs`](dist/sbti-cli.cjs) — 用来生成 native binary 的 CommonJS 单文件入口
|
|
275
|
+
- [`scripts/build-dist.mjs`](scripts/build-dist.mjs) — 生成 ESM/CJS 两份单文件 CLI 构建产物
|
|
276
|
+
- [`scripts/build-platform-packages.mjs`](scripts/build-platform-packages.mjs) — 生成各平台预编译 native npm 子包
|
|
277
|
+
- [`scripts/publish-packages.mjs`](scripts/publish-packages.mjs) — 先发布平台子包,再发布根包 `@bingran/sbti-cli`
|
|
278
|
+
- [`scripts/export-type-images.mjs`](scripts/export-type-images.mjs) — 重建结果图 manifest 与画廊
|
|
279
|
+
- [`test/runtime.test.mjs`](test/runtime.test.mjs) — 内置运行时对齐测试
|
|
280
|
+
- [`test/launcher.test.mjs`](test/launcher.test.mjs) — launcher 与 native package 解析测试
|
|
281
|
+
- [`test/package.test.mjs`](test/package.test.mjs) — npm tarball 发布面检查
|
|
282
|
+
- [`test/type-images.test.mjs`](test/type-images.test.mjs) — 图片资源完整性测试
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## 🙏 鸣谢
|
|
287
|
+
|
|
288
|
+
<table>
|
|
289
|
+
<tr>
|
|
290
|
+
<th>项目</th>
|
|
291
|
+
<th>作者</th>
|
|
292
|
+
<th>贡献</th>
|
|
293
|
+
</tr>
|
|
294
|
+
<tr>
|
|
295
|
+
<td><a href="https://sbti.fancc.de5.net"><strong>SBTI 人格测试</strong></a></td>
|
|
296
|
+
<td>B 站 <a href="https://space.bilibili.com/417038183">@蛆肉儿串儿</a></td>
|
|
297
|
+
<td>原测试作者,提供题目、27 个人格文案与角色插画</td>
|
|
298
|
+
</tr>
|
|
299
|
+
<tr>
|
|
300
|
+
<td><a href="https://github.com/serenakeyitan/sbti-wiki"><strong>sbti-wiki</strong></a></td>
|
|
301
|
+
<td><a href="https://github.com/serenakeyitan">@serenakeyitan</a></td>
|
|
302
|
+
<td>这次 README 改版的版式参考来源:中心 Hero、徽章、图卡与信息分段方式</td>
|
|
303
|
+
</tr>
|
|
304
|
+
<tr>
|
|
305
|
+
<td><strong>sbti-cli</strong></td>
|
|
306
|
+
<td><a href="https://github.com/bingran-you">Bingran You (@bingran-you)</a></td>
|
|
307
|
+
<td>把题库快照 sandbox 化,补上离线运行、结果图整理与测试体系,提供一个可直接使用的 CLI</td>
|
|
308
|
+
</tr>
|
|
309
|
+
</table>
|
|
310
|
+
|
|
311
|
+
> ⚠️ **仅供娱乐**:原测试首页已经写得很明确了,不要把它当成诊断、面试、相亲、分手、招魂、算命或人生判决书。本仓库也只是一个便于运行、研究和导出资源的工具。
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## 📄 License
|
|
316
|
+
|
|
317
|
+
本仓库中由本项目原创的代码与文档采用 [MIT License](LICENSE) 发布。
|
|
318
|
+
|
|
319
|
+
与此同时,来自上游 SBTI 网站的题目文案、结果文案以及角色插画仍然归原作者所有,并不因为放进这个仓库就自动转成 MIT。具体归属说明见 [NOTICE](NOTICE)。
|
package/bin/sbti-cli.cjs
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('node:child_process');
|
|
4
|
+
const process = require('node:process');
|
|
5
|
+
|
|
6
|
+
const { resolveInstalledBinaryPath } = require('../lib/platform-package.cjs');
|
|
7
|
+
|
|
8
|
+
let resolvedBinary;
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
resolvedBinary = resolveInstalledBinaryPath((request) => require.resolve(request));
|
|
12
|
+
} catch (error) {
|
|
13
|
+
console.error(error.message);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const child = spawn(resolvedBinary.binaryPath, process.argv.slice(2), {
|
|
18
|
+
stdio: 'inherit'
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
child.on('error', (error) => {
|
|
22
|
+
console.error(error.message);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
child.on('exit', (code, signal) => {
|
|
27
|
+
if (signal) {
|
|
28
|
+
console.error(`sbti-cli terminated with signal ${signal}.`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
process.exit(code ?? 0);
|
|
33
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
const path = require('node:path');
|
|
2
|
+
|
|
3
|
+
const SUPPORTED_PLATFORMS = [
|
|
4
|
+
{
|
|
5
|
+
id: 'darwin-arm64',
|
|
6
|
+
platform: 'darwin',
|
|
7
|
+
arch: 'arm64',
|
|
8
|
+
packageName: '@bingran/sbti-cli-darwin-arm64',
|
|
9
|
+
pkgTarget: 'node18-macos-arm64',
|
|
10
|
+
binaryName: 'sbti-cli'
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: 'darwin-x64',
|
|
14
|
+
platform: 'darwin',
|
|
15
|
+
arch: 'x64',
|
|
16
|
+
packageName: '@bingran/sbti-cli-darwin-x64',
|
|
17
|
+
pkgTarget: 'node18-macos-x64',
|
|
18
|
+
binaryName: 'sbti-cli'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: 'linux-arm64',
|
|
22
|
+
platform: 'linux',
|
|
23
|
+
arch: 'arm64',
|
|
24
|
+
packageName: '@bingran/sbti-cli-linux-arm64',
|
|
25
|
+
pkgTarget: 'node18-linux-arm64',
|
|
26
|
+
binaryName: 'sbti-cli'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'linux-x64',
|
|
30
|
+
platform: 'linux',
|
|
31
|
+
arch: 'x64',
|
|
32
|
+
packageName: '@bingran/sbti-cli-linux-x64',
|
|
33
|
+
pkgTarget: 'node18-linux-x64',
|
|
34
|
+
binaryName: 'sbti-cli'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'win32-x64',
|
|
38
|
+
platform: 'win32',
|
|
39
|
+
arch: 'x64',
|
|
40
|
+
packageName: '@bingran/sbti-cli-win32-x64',
|
|
41
|
+
pkgTarget: 'node18-win-x64',
|
|
42
|
+
binaryName: 'sbti-cli.exe'
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
function formatSupportedPlatforms() {
|
|
47
|
+
return SUPPORTED_PLATFORMS.map(
|
|
48
|
+
({ platform, arch, packageName }) => `- ${platform}/${arch}: ${packageName}`
|
|
49
|
+
).join('\n');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getPlatformPackageInfo(platform, arch) {
|
|
53
|
+
return (
|
|
54
|
+
SUPPORTED_PLATFORMS.find(
|
|
55
|
+
(entry) => entry.platform === platform && entry.arch === arch
|
|
56
|
+
) ?? null
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function getCurrentPlatformPackageInfo() {
|
|
61
|
+
return getPlatformPackageInfo(process.platform, process.arch);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function getBinaryPath(packageRoot, platformInfo) {
|
|
65
|
+
if (!platformInfo) {
|
|
66
|
+
throw new Error('A supported platform package definition is required.');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return path.join(packageRoot, 'bin', platformInfo.binaryName);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function resolveInstalledBinaryPath(
|
|
73
|
+
resolveRequest,
|
|
74
|
+
platform = process.platform,
|
|
75
|
+
arch = process.arch
|
|
76
|
+
) {
|
|
77
|
+
if (typeof resolveRequest !== 'function') {
|
|
78
|
+
throw new TypeError('resolveRequest must be a function.');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const platformInfo = getPlatformPackageInfo(platform, arch);
|
|
82
|
+
|
|
83
|
+
if (!platformInfo) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`Unsupported platform ${platform}/${arch}.\nSupported native packages:\n${formatSupportedPlatforms()}`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let packageJsonPath;
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
packageJsonPath = resolveRequest(`${platformInfo.packageName}/package.json`);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
if (error?.code === 'MODULE_NOT_FOUND') {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`Missing native binary package ${platformInfo.packageName} for ${platform}/${arch}. ` +
|
|
97
|
+
'Reinstall @bingran/sbti-cli without omitting optional dependencies.'
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
platformInfo,
|
|
106
|
+
binaryPath: getBinaryPath(path.dirname(packageJsonPath), platformInfo)
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
module.exports = {
|
|
111
|
+
SUPPORTED_PLATFORMS,
|
|
112
|
+
formatSupportedPlatforms,
|
|
113
|
+
getBinaryPath,
|
|
114
|
+
getCurrentPlatformPackageInfo,
|
|
115
|
+
getPlatformPackageInfo,
|
|
116
|
+
resolveInstalledBinaryPath
|
|
117
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bingran/sbti-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Native-binary CLI runner for the public SBTI survey.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/bingran-you/sbti-cli",
|
|
8
|
+
"bugs": {
|
|
9
|
+
"url": "https://github.com/bingran-you/sbti-cli/issues"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/bingran-you/sbti-cli.git"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"bin",
|
|
17
|
+
"lib",
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"NOTICE",
|
|
20
|
+
"README.md",
|
|
21
|
+
"README.zh-CN.md"
|
|
22
|
+
],
|
|
23
|
+
"bin": {
|
|
24
|
+
"sbti-cli": "./bin/sbti-cli.cjs"
|
|
25
|
+
},
|
|
26
|
+
"optionalDependencies": {
|
|
27
|
+
"@bingran/sbti-cli-darwin-arm64": "0.1.0",
|
|
28
|
+
"@bingran/sbti-cli-darwin-x64": "0.1.0",
|
|
29
|
+
"@bingran/sbti-cli-linux-arm64": "0.1.0",
|
|
30
|
+
"@bingran/sbti-cli-linux-x64": "0.1.0",
|
|
31
|
+
"@bingran/sbti-cli-win32-x64": "0.1.0"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build:dist": "node scripts/build-dist.mjs",
|
|
35
|
+
"build:platform-packages": "node scripts/build-platform-packages.mjs",
|
|
36
|
+
"publish:packages": "node scripts/publish-packages.mjs",
|
|
37
|
+
"start": "node src/cli.mjs",
|
|
38
|
+
"sbti": "node src/cli.mjs",
|
|
39
|
+
"export-images": "node scripts/export-type-images.mjs",
|
|
40
|
+
"test": "node --test test/*.test.mjs"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18"
|
|
44
|
+
}
|
|
45
|
+
}
|