wrapture 0.0.2 β†’ 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.
@@ -48,6 +48,13 @@ jobs:
48
48
  uses: actions/setup-node@v4
49
49
  with:
50
50
  node-version: '>=22.8.0'
51
+ - uses: actions/setup-python@v4
52
+ with:
53
+ python-version: '3.10'
54
+ - name: Install Python dependencies
55
+ run: |
56
+ python3 -m pip install --upgrade pip
57
+ pip install torch onnx onnxsim onnxruntime
51
58
  - name: Install dependencies
52
59
  run: | # Install and link dependencies
53
60
  npm i
@@ -69,4 +76,4 @@ jobs:
69
76
  - uses: jayqi/failed-build-issue-action@v1.2
70
77
  with:
71
78
  github-token: ${{ secrets.GH_TOKEN }}
72
- label-name: 'problems: build failed'
79
+ label-name: 'problems: πŸ’” build failed'
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.0](https://github.com/phun-ky/wrapture/compare/0.0.3...0.1.0) (2025-05-15)
4
+
5
+ ### Tasks
6
+
7
+ * πŸ€– add `bin/` to `.gitignore` ([a90b288](https://github.com/phun-ky/wrapture/commit/a90b2880a6179010b6133f719eb7696759e6ac06))
8
+ * πŸ€– Delete file from bin ([b707abd](https://github.com/phun-ky/wrapture/commit/b707abddd989c43da70bf91512d75e752c18456c))
9
+ * πŸ€– Remove old dep imports ([819e9e4](https://github.com/phun-ky/wrapture/commit/819e9e439f0bbf50383038db2cded3d3c167e3f3))
10
+ * πŸ€– Use correct label ([3d6acf0](https://github.com/phun-ky/wrapture/commit/3d6acf0311f18e9e2d90b4a129f0dc7cae9b955c))
11
+
12
+ ### Feature
13
+
14
+ * 🎸 Add `--logLevel`-option and clean up messages ([c93f4ef](https://github.com/phun-ky/wrapture/commit/c93f4ef0570d4fe7501776f2fbce1ed362e048a7))
15
+ * 🎸 Check for correct dependencies ([28d1d4d](https://github.com/phun-ky/wrapture/commit/28d1d4def395c700285caf82139e8b0786cc4855))
16
+
17
+ ### Bug
18
+
19
+ * πŸ› Remove outtdated python module ([0b58d3c](https://github.com/phun-ky/wrapture/commit/0b58d3cc5c2758b606333e011766a3ed91fbfa74))
20
+
21
+ ### Refactoring
22
+
23
+ * πŸ’‘ Adjust cli interface ([ddc80b9](https://github.com/phun-ky/wrapture/commit/ddc80b9d96f11133c2aa4e26ffcde40f316f12a8))
24
+
25
+ ## [0.0.3](https://github.com/phun-ky/wrapture/compare/0.0.2...0.0.3) (2025-05-14)
26
+
27
+ ### Bug
28
+
29
+ * πŸ› Python env ([36d0a30](https://github.com/phun-ky/wrapture/commit/36d0a302aebfabf9860f7cc5c70bc8151b221632))
30
+
3
31
  ## [0.0.2](https://github.com/phun-ky/wrapture/compare/0.0.1...0.0.2) (2025-05-14)
4
32
 
5
33
  ### Documentation
package/README.md CHANGED
@@ -62,7 +62,7 @@ Install Python if you don’t have it: πŸ‘‰ <https://www.python.org/downloads/>
62
62
  ### Install required Python packages
63
63
 
64
64
  ```shell-session
65
- python3 -m pip install torch onnx onnxsim onnxruntime onnxruntime-tools
65
+ python3 -m pip install torch onnx onnxsim onnxruntime
66
66
  ```
67
67
 
68
68
  Check your installation:
package/api/README.md CHANGED
@@ -1,11 +1,13 @@
1
1
  # wrapture API documentation
2
2
 
3
- > Last updated 2025-05-14T13:10:23.461Z
3
+ > Last updated 2025-05-15T10:00:06.699Z
4
4
 
5
5
  ## Modules
6
6
 
7
+ - [utils/check-deps](utils/check-deps.md)
7
8
  - [utils/convert](utils/convert.md)
8
9
  - [utils/generate-wrapper](utils/generate-wrapper.md)
10
+ - [utils/log-level](utils/log-level.md)
9
11
  - [wrapture](wrapture.md)
10
12
 
11
13
  ---
@@ -0,0 +1,61 @@
1
+ [wrapture](../README.md) / utils/check-deps
2
+
3
+ # utils/check-deps
4
+
5
+ > Last updated 2025-05-15T10:00:06.852Z
6
+
7
+ ## Functions
8
+
9
+ ### checkPythonAvailable()
10
+
11
+ ```ts
12
+ function checkPythonAvailable(): void;
13
+ ```
14
+
15
+ Defined in:
16
+ [utils/check-deps.ts:11](https://github.com/phun-ky/wrapture/blob/main/src/utils/check-deps.ts#L11)
17
+
18
+ #### Returns
19
+
20
+ `void`
21
+
22
+ ---
23
+
24
+ ### checkPythonDeps()
25
+
26
+ ```ts
27
+ function checkPythonDeps(): void;
28
+ ```
29
+
30
+ Defined in:
31
+ [utils/check-deps.ts:23](https://github.com/phun-ky/wrapture/blob/main/src/utils/check-deps.ts#L23)
32
+
33
+ #### Returns
34
+
35
+ `void`
36
+
37
+ ---
38
+
39
+ **Contributing**
40
+
41
+ Want to contribute? Please read the
42
+ [CONTRIBUTING.md](https://github.com/phun-ky/wrapture/blob/main/CONTRIBUTING.md)
43
+ and
44
+ [CODE_OF_CONDUCT.md](https://github.com/phun-ky/wrapture/blob/main/CODE_OF_CONDUCT.md)
45
+
46
+ **Sponsor me**
47
+
48
+ I'm an Open Source evangelist, creating stuff that does not exist yet to help
49
+ get rid of secondary activities and to enhance systems already in place, be it
50
+ documentation or web sites.
51
+
52
+ The sponsorship is an unique opportunity to alleviate more hours for me to
53
+ maintain my projects, create new ones and contribute to the large community
54
+ we're all part of :)
55
+
56
+ [Support me on GitHub Sponsors](https://github.com/sponsors/phun-ky).
57
+
58
+ ---
59
+
60
+ This project created by [Alexander Vassbotn RΓΈyne-Helgesen](http://phun-ky.net)
61
+ is licensed under a [MIT License](https://choosealicense.com/licenses/mit/).
@@ -2,14 +2,14 @@
2
2
 
3
3
  # utils/convert
4
4
 
5
- > Last updated 2025-05-14T13:10:23.623Z
5
+ > Last updated 2025-05-15T10:00:06.925Z
6
6
 
7
7
  ## Interfaces
8
8
 
9
9
  ### ConvertOptionsInterface
10
10
 
11
11
  Defined in:
12
- [utils/convert.ts:17](https://github.com/phun-ky/wrapture/blob/main/src/utils/convert.ts#L17)
12
+ [utils/convert.ts:12](https://github.com/phun-ky/wrapture/blob/main/src/utils/convert.ts#L12)
13
13
 
14
14
  Options for the [convert](#convert) function.
15
15
 
@@ -17,8 +17,8 @@ Options for the [convert](#convert) function.
17
17
 
18
18
  | Property | Type | Description | Defined in |
19
19
  | --------------------------------- | --------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
20
- | <a id="format"></a> `format?` | `string` | The output format for the converted model (e.g., 'onnx'). Defaults to 'onnx' if not provided. | [utils/convert.ts:22](https://github.com/phun-ky/wrapture/blob/main/src/utils/convert.ts#L22) |
21
- | <a id="quantize"></a> `quantize?` | `boolean` | Whether to apply quantization to the model. | [utils/convert.ts:27](https://github.com/phun-ky/wrapture/blob/main/src/utils/convert.ts#L27) |
20
+ | <a id="format"></a> `format?` | `string` | The output format for the converted model (e.g., 'onnx'). Defaults to 'onnx' if not provided. | [utils/convert.ts:17](https://github.com/phun-ky/wrapture/blob/main/src/utils/convert.ts#L17) |
21
+ | <a id="quantize"></a> `quantize?` | `boolean` | Whether to apply quantization to the model. | [utils/convert.ts:22](https://github.com/phun-ky/wrapture/blob/main/src/utils/convert.ts#L22) |
22
22
 
23
23
  ## Functions
24
24
 
@@ -29,7 +29,7 @@ function convert(inputPath, outputDir, opts): Promise<void>;
29
29
  ```
30
30
 
31
31
  Defined in:
32
- [utils/convert.ts:54](https://github.com/phun-ky/wrapture/blob/main/src/utils/convert.ts#L54)
32
+ [utils/convert.ts:49](https://github.com/phun-ky/wrapture/blob/main/src/utils/convert.ts#L49)
33
33
 
34
34
  Converts a machine learning model to ONNX or another supported format by
35
35
  delegating to a Python script (`convert.py`).
@@ -2,14 +2,14 @@
2
2
 
3
3
  # utils/generate-wrapper
4
4
 
5
- > Last updated 2025-05-14T13:10:23.726Z
5
+ > Last updated 2025-05-15T10:00:06.977Z
6
6
 
7
7
  ## Interfaces
8
8
 
9
9
  ### GenerateWrapperOptionsInterface
10
10
 
11
11
  Defined in:
12
- [utils/generate-wrapper.ts:9](https://github.com/phun-ky/wrapture/blob/main/src/utils/generate-wrapper.ts#L9)
12
+ [utils/generate-wrapper.ts:10](https://github.com/phun-ky/wrapture/blob/main/src/utils/generate-wrapper.ts#L10)
13
13
 
14
14
  Options for generating ONNX wrapper files.
15
15
 
@@ -17,7 +17,7 @@ Options for generating ONNX wrapper files.
17
17
 
18
18
  | Property | Type | Description | Defined in |
19
19
  | ------------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
20
- | <a id="backend"></a> `backend` | `string` | The backend to use for inference. This affects the model file used. If set to `'wasm'`, the generated wrapper will load `model_quant.onnx`, otherwise it will load `model.onnx`. | [utils/generate-wrapper.ts:15](https://github.com/phun-ky/wrapture/blob/main/src/utils/generate-wrapper.ts#L15) |
20
+ | <a id="backend"></a> `backend` | `string` | The backend to use for inference. This affects the model file used. If set to `'wasm'`, the generated wrapper will load `model_quant.onnx`, otherwise it will load `model.onnx`. | [utils/generate-wrapper.ts:16](https://github.com/phun-ky/wrapture/blob/main/src/utils/generate-wrapper.ts#L16) |
21
21
 
22
22
  ## Functions
23
23
 
@@ -28,7 +28,7 @@ function generateWrapper(outputDir, opts): Promise<void>;
28
28
  ```
29
29
 
30
30
  Defined in:
31
- [utils/generate-wrapper.ts:39](https://github.com/phun-ky/wrapture/blob/main/src/utils/generate-wrapper.ts#L39)
31
+ [utils/generate-wrapper.ts:40](https://github.com/phun-ky/wrapture/blob/main/src/utils/generate-wrapper.ts#L40)
32
32
 
33
33
  Generates a TypeScript wrapper and type definition file (`wrapped.ts` and
34
34
  `wrapped.d.ts`) for use with `onnxruntime-web`, including utility functions like
@@ -0,0 +1,161 @@
1
+ [wrapture](../README.md) / utils/log-level
2
+
3
+ # utils/log-level
4
+
5
+ > Last updated 2025-05-15T10:00:07.021Z
6
+
7
+ ## Type Aliases
8
+
9
+ ### LogLevelType
10
+
11
+ ```ts
12
+ type LogLevelType = 'silent' | 'error' | 'warn' | 'info' | 'debug';
13
+ ```
14
+
15
+ Defined in:
16
+ [utils/log-level.ts:2](https://github.com/phun-ky/wrapture/blob/main/src/utils/log-level.ts#L2)
17
+
18
+ ## Variables
19
+
20
+ ### log
21
+
22
+ ```ts
23
+ const log: {
24
+ debug: (...args) => false | void;
25
+ error: (...args) => false | void;
26
+ info: (...args) => false | void;
27
+ warn: (...args) => false | void;
28
+ };
29
+ ```
30
+
31
+ Defined in:
32
+ [utils/log-level.ts:22](https://github.com/phun-ky/wrapture/blob/main/src/utils/log-level.ts#L22)
33
+
34
+ #### Type declaration
35
+
36
+ <table>
37
+ <thead>
38
+ <tr>
39
+ <th>Name</th>
40
+ <th>Type</th>
41
+ <th>Defined in</th>
42
+ </tr>
43
+ </thead>
44
+ <tbody>
45
+ <tr>
46
+ <td>
47
+
48
+ <a id="debug"></a> `debug()`
49
+
50
+ </td>
51
+ <td>
52
+
53
+ (...`args`) => `false` | `void`
54
+
55
+ </td>
56
+ <td>
57
+
58
+ [utils/log-level.ts:23](https://github.com/phun-ky/wrapture/blob/main/src/utils/log-level.ts#L23)
59
+
60
+ </td>
61
+ </tr>
62
+ <tr>
63
+ <td>
64
+
65
+ <a id="error"></a> `error()`
66
+
67
+ </td>
68
+ <td>
69
+
70
+ (...`args`) => `false` | `void`
71
+
72
+ </td>
73
+ <td>
74
+
75
+ [utils/log-level.ts:29](https://github.com/phun-ky/wrapture/blob/main/src/utils/log-level.ts#L29)
76
+
77
+ </td>
78
+ </tr>
79
+ <tr>
80
+ <td>
81
+
82
+ <a id="info"></a> `info()`
83
+
84
+ </td>
85
+ <td>
86
+
87
+ (...`args`) => `false` | `void`
88
+
89
+ </td>
90
+ <td>
91
+
92
+ [utils/log-level.ts:25](https://github.com/phun-ky/wrapture/blob/main/src/utils/log-level.ts#L25)
93
+
94
+ </td>
95
+ </tr>
96
+ <tr>
97
+ <td>
98
+
99
+ <a id="warn"></a> `warn()`
100
+
101
+ </td>
102
+ <td>
103
+
104
+ (...`args`) => `false` | `void`
105
+
106
+ </td>
107
+ <td>
108
+
109
+ [utils/log-level.ts:27](https://github.com/phun-ky/wrapture/blob/main/src/utils/log-level.ts#L27)
110
+
111
+ </td>
112
+ </tr>
113
+ </tbody>
114
+ </table>
115
+
116
+ ## Functions
117
+
118
+ ### setLogLevel()
119
+
120
+ ```ts
121
+ function setLogLevel(level): void;
122
+ ```
123
+
124
+ Defined in:
125
+ [utils/log-level.ts:14](https://github.com/phun-ky/wrapture/blob/main/src/utils/log-level.ts#L14)
126
+
127
+ #### Parameters
128
+
129
+ | Parameter | Type |
130
+ | --------- | ------------------------------- |
131
+ | `level` | [`LogLevelType`](#logleveltype) |
132
+
133
+ #### Returns
134
+
135
+ `void`
136
+
137
+ ---
138
+
139
+ **Contributing**
140
+
141
+ Want to contribute? Please read the
142
+ [CONTRIBUTING.md](https://github.com/phun-ky/wrapture/blob/main/CONTRIBUTING.md)
143
+ and
144
+ [CODE_OF_CONDUCT.md](https://github.com/phun-ky/wrapture/blob/main/CODE_OF_CONDUCT.md)
145
+
146
+ **Sponsor me**
147
+
148
+ I'm an Open Source evangelist, creating stuff that does not exist yet to help
149
+ get rid of secondary activities and to enhance systems already in place, be it
150
+ documentation or web sites.
151
+
152
+ The sponsorship is an unique opportunity to alleviate more hours for me to
153
+ maintain my projects, create new ones and contribute to the large community
154
+ we're all part of :)
155
+
156
+ [Support me on GitHub Sponsors](https://github.com/sponsors/phun-ky).
157
+
158
+ ---
159
+
160
+ This project created by [Alexander Vassbotn RΓΈyne-Helgesen](http://phun-ky.net)
161
+ is licensed under a [MIT License](https://choosealicense.com/licenses/mit/).
package/api/wrapture.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # wrapture
4
4
 
5
- > Last updated 2025-05-14T13:10:23.760Z
5
+ > Last updated 2025-05-15T10:00:07.077Z
6
6
 
7
7
  ---
8
8
 
package/bin/wrapture.js CHANGED
@@ -3,25 +3,197 @@
3
3
  // src/wrapture.ts
4
4
  import chalk2 from "chalk";
5
5
  import { Command } from "commander";
6
+ import ora from "ora";
6
7
  import { existsSync } from "node:fs";
7
8
  import path3 from "node:path";
8
9
 
9
- // src/utils/convert.ts
10
+ // package.json
11
+ var package_default = {
12
+ name: "wrapture",
13
+ version: "0.1.0",
14
+ description: "Wrapture lets you go from a Python-trained model to deployable JavaScript with a single command. It generates TypeScript bindings and a Web/Node-compatible wrapper, using WebGPU/WASM-ready ONNX runtimes.",
15
+ keywords: [
16
+ "onnx",
17
+ "pytorch",
18
+ "torch",
19
+ "model exporter",
20
+ "onnx export",
21
+ "onnx runtime",
22
+ "onnx to javascript",
23
+ "machine learning",
24
+ "ml model conversion",
25
+ "typescript",
26
+ "javascript",
27
+ "cli tool",
28
+ "webgpu",
29
+ "wasm",
30
+ "onnx simplifier",
31
+ "onnx quantization",
32
+ "deep learning",
33
+ "model conversion",
34
+ "wrapture",
35
+ "loadModel",
36
+ "predict"
37
+ ],
38
+ homepage: "https://github.com/phun-ky/wrapture#readme",
39
+ bugs: {
40
+ url: "https://github.com/phun-ky/wrapture/issues"
41
+ },
42
+ repository: {
43
+ type: "git",
44
+ url: "git+https://github.com/phun-ky/wrapture.git"
45
+ },
46
+ funding: "https://github.com/phun-ky/angle?sponsor=1",
47
+ license: "MIT",
48
+ author: "Alexander Vassbotn R\xF8yne-Helgesen <alexander@phun-ky.net>",
49
+ type: "module",
50
+ bin: {
51
+ wrapture: "./bin/wrapture.js"
52
+ },
53
+ scripts: {
54
+ build: "tsup",
55
+ commit: "npx git-cz",
56
+ "docs:gen": "node ./node_modules/.bin/typedoc",
57
+ release: "release-it",
58
+ start: "node ./bin/wrapture.js",
59
+ "style:code": "npx putout src",
60
+ "style:format": "./node_modules/.bin/eslint -c ./eslint.config.mjs src --fix && ./node_modules/.bin/prettier --write ./eslint.config.mjs src",
61
+ "style:lint": "./node_modules/.bin/eslint -c ./eslint.config.mjs src && ./node_modules/.bin/prettier --check src",
62
+ test: 'NODE_ENV=test glob -c "node --import tsx --test --no-warnings" "./src/**/__tests__/**/*.[jt]s"',
63
+ "pretest:ci": "rm -rf coverage && mkdir -p coverage",
64
+ "test:ci": 'NODE_ENV=test glob -c "node --import tsx --test --no-warnings --experimental-test-coverage --test-reporter=cobertura --test-reporter-destination=coverage/cobertura-coverage.xml --test-reporter=spec --test-reporter-destination=stdout" "./src/**/__tests__/**/*.[jt]s"'
65
+ },
66
+ dependencies: {
67
+ chalk: "^5.4.1",
68
+ commander: "^13.1.0",
69
+ ora: "^8.2.0"
70
+ },
71
+ devDependencies: {
72
+ "@release-it/conventional-changelog": "^10.0.0",
73
+ "@rollup/plugin-node-resolve": "^16.0.1",
74
+ "@rollup/plugin-terser": "^0.4.4",
75
+ "@stylistic/eslint-plugin": "^4.2.0",
76
+ "@types/node": "^22.15.3",
77
+ cobertura: "^1.0.1",
78
+ eslint: "^9.20.0",
79
+ "eslint-config-phun-ky": "^1.0.0",
80
+ "git-cz": "^4.9.0",
81
+ "onnxruntime-web": "^1.22.0",
82
+ prettier: "^3.2.5",
83
+ putout: "^40.1.9",
84
+ "release-it": "^19.0.1",
85
+ "remark-github": "^12.0.0",
86
+ "remark-toc": "^9.0.0",
87
+ tslib: "^2.3.1",
88
+ tsup: "^8.4.0",
89
+ tsx: "^4.7.1",
90
+ typedoc: "^0.28.3",
91
+ "typedoc-plugin-frontmatter": "^1.0.0",
92
+ "typedoc-plugin-markdown": "^4.2.3",
93
+ "typedoc-plugin-mdn-links": "^5.0.1",
94
+ "typedoc-plugin-no-inherit": "^1.4.0",
95
+ "typedoc-plugin-remark": "^2.0.0",
96
+ "typedoc-plugin-rename-defaults": "^0.7.1",
97
+ typescript: "^5.0.0",
98
+ "unified-prettier": "^2.0.1"
99
+ },
100
+ engines: {
101
+ node: ">=22.0.0",
102
+ npm: ">=10.8.2"
103
+ },
104
+ publishConfig: {
105
+ access: "public"
106
+ }
107
+ };
108
+
109
+ // src/utils/check-deps.ts
10
110
  import chalk from "chalk";
11
- import ora from "ora";
111
+ import { spawnSync } from "node:child_process";
112
+ var printError = (title, body) => {
113
+ console.error(`
114
+ ${chalk.red.bold("\u2718")} ${chalk.red.bold(title)}`);
115
+ console.error(chalk.white(body));
116
+ };
117
+ var checkPythonAvailable = () => {
118
+ const result = spawnSync("python3", ["--version"], { encoding: "utf-8" });
119
+ if (result.error || result.status !== 0) {
120
+ printError(
121
+ "Python 3 is not available.",
122
+ "Please install it from https://www.python.org/downloads/ and ensure it is added to your PATH."
123
+ );
124
+ process.exit(1);
125
+ }
126
+ };
127
+ var checkPythonDeps = () => {
128
+ const check = spawnSync(
129
+ "python3",
130
+ [
131
+ "-c",
132
+ `
133
+ import sys
134
+ missing = []
135
+ for module in ['torch', 'onnx', 'onnxsim', 'onnxruntime']:
136
+ try:
137
+ __import__(module)
138
+ except ImportError:
139
+ missing.append(module)
140
+ if missing:
141
+ print(', '.join(missing))
142
+ sys.exit(1)
143
+ `
144
+ ],
145
+ { encoding: "utf-8" }
146
+ );
147
+ if (check.status !== 0) {
148
+ const missing = check.stdout.trim().split(",").filter(Boolean);
149
+ printError(
150
+ "Missing Python dependencies.",
151
+ `Please install the following packages:
152
+
153
+ ${chalk.yellow(
154
+ `python3 -m pip install ${missing.join(" ")}`
155
+ )}`
156
+ );
157
+ process.exit(1);
158
+ }
159
+ };
160
+
161
+ // src/utils/convert.ts
12
162
  import { spawn } from "node:child_process";
13
163
  import fs from "node:fs";
14
- import path, { dirname } from "node:path";
15
- import { fileURLToPath } from "node:url";
16
- var __filename = fileURLToPath(import.meta.url);
17
- var __dirname = dirname(__filename);
164
+ import path from "node:path";
165
+
166
+ // src/utils/log-level.ts
167
+ var currentLevel = "info";
168
+ var levels = {
169
+ silent: 0,
170
+ error: 1,
171
+ warn: 2,
172
+ info: 3,
173
+ debug: 4
174
+ };
175
+ var setLogLevel = (level) => {
176
+ currentLevel = level;
177
+ };
178
+ var shouldLog = (level) => {
179
+ return levels[level] <= levels[currentLevel];
180
+ };
181
+ var log = {
182
+ debug: (...args) => shouldLog("debug") && console.debug("[debug]", ...args),
183
+ info: (...args) => shouldLog("info") && console.info("[info]", ...args),
184
+ warn: (...args) => shouldLog("warn") && console.warn("[warn]", ...args),
185
+ error: (...args) => shouldLog("error") && console.error("[error]", ...args)
186
+ };
187
+
188
+ // src/utils/convert.ts
18
189
  var convert = async (inputPath, outputDir, opts) => {
19
190
  if (!fs.existsSync(inputPath)) {
20
191
  throw new Error(`Input model file not found: ${inputPath}`);
21
192
  }
22
- const spinner = ora("\u{1F504} Converting model to ONNX...").start();
193
+ log.info("Converting model to ONNX...");
23
194
  return new Promise((resolve, reject) => {
24
- const scriptPath = path.resolve(__dirname, "../../python/convert.py");
195
+ const scriptPath = path.resolve(process.cwd(), "python/convert.py");
196
+ log.debug("Script path for `convert.py`:", scriptPath);
25
197
  const args = [
26
198
  scriptPath,
27
199
  "--input",
@@ -33,17 +205,18 @@ var convert = async (inputPath, outputDir, opts) => {
33
205
  ];
34
206
  if (opts.quantize) args.push("--quantize");
35
207
  const python = spawn("python3", args);
36
- python.stdout.on("data", (data) => process.stdout.write(data));
37
- python.stderr.on(
38
- "data",
39
- (data) => process.stderr.write(chalk.red(data.toString()))
40
- );
208
+ python.stdout.on("data", (data) => {
209
+ log.debug("[python stdout]", data.toString());
210
+ });
211
+ python.stderr.on("data", (data) => {
212
+ log.error("[python stderr]", data.toString());
213
+ });
41
214
  python.on("close", (code) => {
42
215
  if (code === 0) {
43
- spinner.succeed("\u2705 Model converted successfully.");
216
+ log.info("Model converted successfully");
44
217
  resolve();
45
218
  } else {
46
- spinner.fail("\u274C Model conversion failed.");
219
+ log.error("Model conversion failed");
47
220
  reject(new Error(`convert.py exited with code ${code}`));
48
221
  }
49
222
  });
@@ -51,11 +224,10 @@ var convert = async (inputPath, outputDir, opts) => {
51
224
  };
52
225
 
53
226
  // src/utils/generate-wrapper.ts
54
- import ora2 from "ora";
55
227
  import fs2 from "node:fs";
56
228
  import path2 from "node:path";
57
229
  var generateWrapper = async (outputDir, opts) => {
58
- const spinner = ora2("\u{1F6E0} Generating wrapper files...").start();
230
+ log.info("Generating wrapper files...");
59
231
  const wrapper = `import { InferenceSession, Tensor } from 'onnxruntime-web';
60
232
 
61
233
  const softmax = (logits) => {
@@ -112,36 +284,55 @@ export function loadModel(): Promise<LoadedModel>;`;
112
284
  try {
113
285
  fs2.writeFileSync(path2.join(outputDir, "wrapped.ts"), wrapper);
114
286
  fs2.writeFileSync(path2.join(outputDir, "wrapped.d.ts"), typings);
115
- spinner.succeed("\u2705 Wrapper files generated.");
287
+ log.info("Wrapper files generated");
116
288
  } catch (error) {
117
- spinner.fail("\u274C Failed to generate wrapper files.");
289
+ log.error("Failed generate wrapper files");
118
290
  throw error;
119
291
  }
120
292
  };
121
293
 
122
294
  // src/wrapture.ts
123
295
  var program = new Command();
124
- program.name("wrapture").description("\u{1F300} One-click model exporter: from PyTorch to Web-ready JS/TS").version("0.1.0").requiredOption("-i, --input <file>", "Path to the PyTorch model (.pt)").requiredOption(
296
+ program.name("wrapture").description(
297
+ `\u{1F300} ${chalk2.blue("One-click model exporter: ")}from PyTorch to Web-ready JS/TS.
298
+
299
+ Wrapture lets you go from a Python-trained model to deployable JavaScript with a single command.
300
+ It generates TypeScript bindings and a Web/Node-compatible wrapper, using WebGPU/WASM-ready ONNX runtimes.
301
+
302
+ Report issues here: https://github.com/phun-ky/wrapture`
303
+ ).version(package_default.version).requiredOption("-i, --input <file>", "path to the PyTorch model (.pt)").requiredOption(
125
304
  "-o, --output <dir>",
126
- "Output directory for the wrapped model"
127
- ).option("--quantize", "Apply quantization to reduce model size").option("--format <type>", "Export format: onnx (default)", "onnx").option(
305
+ "output directory for the wrapped model"
306
+ ).option("--quantize", "apply quantization to reduce model size").option("--format <type>", "export format: onnx (default)", "onnx").option(
128
307
  "--backend <backend>",
129
- "Inference backend: webgpu | wasm | cpu",
308
+ "inference backend: webgpu | wasm | cpu",
130
309
  "webgpu"
310
+ ).option(
311
+ "--logLevel <level>",
312
+ "set log level: silent | error | warn | info | debug",
313
+ "error"
131
314
  ).action(async (opts) => {
315
+ checkPythonAvailable();
316
+ checkPythonDeps();
132
317
  const input = path3.resolve(opts.input);
133
318
  const output = path3.resolve(opts.output);
319
+ setLogLevel(
320
+ process.env.LOGLEVEL || opts.logLevel || "error"
321
+ );
134
322
  if (!existsSync(input)) {
135
- console.error(chalk2.red(`Input file not found: ${input}`));
323
+ console.error(
324
+ `${chalk2.red.bold("\u2718 Input file not found:")} ${chalk2.white(input)}`
325
+ );
136
326
  process.exit(1);
137
327
  }
138
- console.log(chalk2.cyan("\u2728 Wrapture: Exporting model..."));
328
+ const spinner = ora("Wrapture: Exporting model...").start();
139
329
  try {
140
330
  await convert(input, output, opts);
141
331
  await generateWrapper(output, opts);
142
- console.log(chalk2.green("\u2705 Done! Your model is wrapped and ready."));
332
+ spinner.succeed("Done! Your model is wrapped and ready.");
143
333
  } catch (err) {
144
- console.error(chalk2.red("\u274C Failed to export model:"), err);
334
+ spinner.fail("Failed to export model:");
335
+ console.error(err);
145
336
  process.exit(1);
146
337
  }
147
338
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrapture",
3
- "version": "0.0.2",
3
+ "version": "0.1.0",
4
4
  "description": "Wrapture lets you go from a Python-trained model to deployable JavaScript with a single command. It generates TypeScript bindings and a Web/Node-compatible wrapper, using WebGPU/WASM-ready ONNX runtimes.",
5
5
  "keywords": [
6
6
  "onnx",
package/python/convert.py CHANGED
@@ -43,9 +43,9 @@ def convert_to_onnx(input_path, output_path, quantize=False):
43
43
  assert check, "Simplified model could not be validated"
44
44
  onnx.checker.check_model(model_simp) # throw if broken
45
45
  onnx.save(model_simp, output_model_path)
46
- print("βœ… ONNX model simplified.")
46
+ print("βœ“ ONNX model simplified.")
47
47
 
48
- print(f"βœ… Exported ONNX model to: {output_model_path}")
48
+ print(f"βœ“ Exported ONNX model to: {output_model_path}")
49
49
 
50
50
  if quantize:
51
51
  quant_model_path = os.path.join(output_path, 'model_quant.onnx')
@@ -0,0 +1,55 @@
1
+ /* global process */
2
+ import chalk from 'chalk';
3
+
4
+ import { spawnSync } from 'node:child_process';
5
+
6
+ const printError = (title: string, body: string) => {
7
+ console.error(`\n${chalk.red.bold('✘')} ${chalk.red.bold(title)}`);
8
+ console.error(chalk.white(body));
9
+ };
10
+
11
+ export const checkPythonAvailable = (): void => {
12
+ const result = spawnSync('python3', ['--version'], { encoding: 'utf-8' });
13
+
14
+ if (result.error || result.status !== 0) {
15
+ printError(
16
+ 'Python 3 is not available.',
17
+ 'Please install it from https://www.python.org/downloads/ and ensure it is added to your PATH.'
18
+ );
19
+ process.exit(1);
20
+ }
21
+ };
22
+
23
+ export const checkPythonDeps = (): void => {
24
+ const check = spawnSync(
25
+ 'python3',
26
+ [
27
+ '-c',
28
+ `
29
+ import sys
30
+ missing = []
31
+ for module in ['torch', 'onnx', 'onnxsim', 'onnxruntime']:
32
+ try:
33
+ __import__(module)
34
+ except ImportError:
35
+ missing.append(module)
36
+ if missing:
37
+ print(', '.join(missing))
38
+ sys.exit(1)
39
+ `
40
+ ],
41
+ { encoding: 'utf-8' }
42
+ );
43
+
44
+ if (check.status !== 0) {
45
+ const missing = check.stdout.trim().split(',').filter(Boolean);
46
+
47
+ printError(
48
+ 'Missing Python dependencies.',
49
+ `Please install the following packages:\n\n ${chalk.yellow(
50
+ `python3 -m pip install ${missing.join(' ')}`
51
+ )}`
52
+ );
53
+ process.exit(1);
54
+ }
55
+ };
@@ -1,15 +1,10 @@
1
1
  /* eslint-disable import/no-unused-modules */
2
2
  /* global process */
3
- import chalk from 'chalk';
4
- import ora from 'ora';
5
-
6
3
  import { spawn } from 'node:child_process';
7
4
  import fs from 'node:fs';
8
- import path, { dirname } from 'node:path';
9
- import { fileURLToPath } from 'node:url';
5
+ import path from 'node:path';
10
6
 
11
- const __filename = fileURLToPath(import.meta.url);
12
- const __dirname = dirname(__filename);
7
+ import { log } from './log-level.js';
13
8
 
14
9
  /**
15
10
  * Options for the {@link convert} function.
@@ -60,10 +55,13 @@ export const convert = async (
60
55
  throw new Error(`Input model file not found: ${inputPath}`);
61
56
  }
62
57
 
63
- const spinner = ora('πŸ”„ Converting model to ONNX...').start();
58
+ log.info('Converting model to ONNX...');
64
59
 
65
60
  return new Promise((resolve, reject) => {
66
- const scriptPath = path.resolve(__dirname, '../../python/convert.py');
61
+ const scriptPath = path.resolve(process.cwd(), 'python/convert.py');
62
+
63
+ log.debug('Script path for `convert.py`:', scriptPath);
64
+
67
65
  const args = [
68
66
  scriptPath,
69
67
  '--input',
@@ -78,18 +76,21 @@ export const convert = async (
78
76
 
79
77
  const python = spawn('python3', args);
80
78
 
81
- python.stdout.on('data', (data) => process.stdout.write(data));
82
- python.stderr.on('data', (data) =>
83
- process.stderr.write(chalk.red(data.toString()))
84
- );
79
+ python.stdout.on('data', (data) => {
80
+ log.debug('[python stdout]', data.toString());
81
+ });
82
+
83
+ python.stderr.on('data', (data) => {
84
+ log.error('[python stderr]', data.toString());
85
+ });
85
86
 
86
87
  python.on('close', (code) => {
87
88
  if (code === 0) {
88
- spinner.succeed('βœ… Model converted successfully.');
89
+ log.info('Model converted successfully');
89
90
 
90
91
  resolve();
91
92
  } else {
92
- spinner.fail('❌ Model conversion failed.');
93
+ log.error('Model conversion failed');
93
94
 
94
95
  reject(new Error(`convert.py exited with code ${code}`));
95
96
  }
@@ -1,8 +1,9 @@
1
- import ora from 'ora';
2
-
1
+ /* eslint-disable import/no-unused-modules */
3
2
  import fs from 'node:fs';
4
3
  import path from 'node:path';
5
4
 
5
+ import { log } from './log-level.js';
6
+
6
7
  /**
7
8
  * Options for generating ONNX wrapper files.
8
9
  */
@@ -38,10 +39,11 @@ export interface GenerateWrapperOptionsInterface {
38
39
  */
39
40
  export const generateWrapper = async (
40
41
  outputDir: string,
41
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+
42
43
  opts: GenerateWrapperOptionsInterface
43
44
  ): Promise<void> => {
44
- const spinner = ora('πŸ›  Generating wrapper files...').start();
45
+ log.info('Generating wrapper files...');
46
+
45
47
  const wrapper = `import { InferenceSession, Tensor } from 'onnxruntime-web';
46
48
 
47
49
  const softmax = (logits) => {
@@ -99,9 +101,10 @@ export function loadModel(): Promise<LoadedModel>;`;
99
101
  try {
100
102
  fs.writeFileSync(path.join(outputDir, 'wrapped.ts'), wrapper);
101
103
  fs.writeFileSync(path.join(outputDir, 'wrapped.d.ts'), typings);
102
- spinner.succeed('βœ… Wrapper files generated.');
104
+
105
+ log.info('Wrapper files generated');
103
106
  } catch (error) {
104
- spinner.fail('❌ Failed to generate wrapper files.');
107
+ log.error('Failed generate wrapper files');
105
108
  throw error;
106
109
  }
107
110
  };
@@ -0,0 +1,31 @@
1
+ /* eslint-disable no-console */
2
+ export type LogLevelType = 'silent' | 'error' | 'warn' | 'info' | 'debug';
3
+
4
+ let currentLevel: LogLevelType = 'info';
5
+
6
+ const levels: Record<LogLevelType, number> = {
7
+ silent: 0,
8
+ error: 1,
9
+ warn: 2,
10
+ info: 3,
11
+ debug: 4
12
+ };
13
+
14
+ export const setLogLevel = (level: LogLevelType) => {
15
+ currentLevel = level;
16
+ };
17
+
18
+ const shouldLog = (level: LogLevelType): boolean => {
19
+ return levels[level] <= levels[currentLevel];
20
+ };
21
+
22
+ export const log = {
23
+ debug: (...args: unknown[]) =>
24
+ shouldLog('debug') && console.debug('[debug]', ...args),
25
+ info: (...args: unknown[]) =>
26
+ shouldLog('info') && console.info('[info]', ...args),
27
+ warn: (...args: unknown[]) =>
28
+ shouldLog('warn') && console.warn('[warn]', ...args),
29
+ error: (...args: unknown[]) =>
30
+ shouldLog('error') && console.error('[error]', ...args)
31
+ };
package/src/wrapture.ts CHANGED
@@ -2,48 +2,76 @@
2
2
  /* global process */
3
3
  import chalk from 'chalk';
4
4
  import { Command } from 'commander';
5
+ import ora from 'ora';
5
6
 
6
7
  import { existsSync } from 'node:fs';
7
8
  import path from 'node:path';
8
9
 
10
+ import pkg from '../package.json';
11
+
12
+ import { checkPythonAvailable, checkPythonDeps } from './utils/check-deps.js';
9
13
  import { convert } from './utils/convert.js';
10
14
  import { generateWrapper } from './utils/generate-wrapper.js';
15
+ import { LogLevelType, setLogLevel } from './utils/log-level.js';
11
16
 
12
17
  const program = new Command();
13
18
 
14
19
  program
15
20
  .name('wrapture')
16
- .description('πŸŒ€ One-click model exporter: from PyTorch to Web-ready JS/TS')
17
- .version('0.1.0')
18
- .requiredOption('-i, --input <file>', 'Path to the PyTorch model (.pt)')
21
+ .description(
22
+ `πŸŒ€ ${chalk.blue('One-click model exporter: ')}from PyTorch to Web-ready JS/TS.
23
+
24
+ Wrapture lets you go from a Python-trained model to deployable JavaScript with a single command.
25
+ It generates TypeScript bindings and a Web/Node-compatible wrapper, using WebGPU/WASM-ready ONNX runtimes.
26
+
27
+ Report issues here: https://github.com/phun-ky/wrapture`
28
+ )
29
+ .version(pkg.version)
30
+ .requiredOption('-i, --input <file>', 'path to the PyTorch model (.pt)')
19
31
  .requiredOption(
20
32
  '-o, --output <dir>',
21
- 'Output directory for the wrapped model'
33
+ 'output directory for the wrapped model'
22
34
  )
23
- .option('--quantize', 'Apply quantization to reduce model size')
24
- .option('--format <type>', 'Export format: onnx (default)', 'onnx')
35
+ .option('--quantize', 'apply quantization to reduce model size')
36
+ .option('--format <type>', 'export format: onnx (default)', 'onnx')
25
37
  .option(
26
38
  '--backend <backend>',
27
- 'Inference backend: webgpu | wasm | cpu',
39
+ 'inference backend: webgpu | wasm | cpu',
28
40
  'webgpu'
29
41
  )
42
+ .option(
43
+ '--logLevel <level>',
44
+ 'set log level: silent | error | warn | info | debug',
45
+ 'error'
46
+ )
30
47
  .action(async (opts) => {
48
+ checkPythonAvailable();
49
+ checkPythonDeps();
50
+
31
51
  const input = path.resolve(opts.input);
32
52
  const output = path.resolve(opts.output);
33
53
 
54
+ setLogLevel(
55
+ (process.env.LOGLEVEL as LogLevelType) || opts.logLevel || 'error'
56
+ );
57
+
34
58
  if (!existsSync(input)) {
35
- console.error(chalk.red(`Input file not found: ${input}`));
59
+ console.error(
60
+ `${chalk.red.bold('✘ Input file not found:')} ${chalk.white(input)}`
61
+ );
36
62
  process.exit(1);
37
63
  }
38
64
 
39
- console.log(chalk.cyan('✨ Wrapture: Exporting model...'));
65
+ const spinner = ora('Wrapture: Exporting model...').start();
40
66
 
41
67
  try {
42
68
  await convert(input, output, opts);
43
69
  await generateWrapper(output, opts);
44
- console.log(chalk.green('βœ… Done! Your model is wrapped and ready.'));
70
+ spinner.succeed('Done! Your model is wrapped and ready.');
45
71
  } catch (err) {
46
- console.error(chalk.red('❌ Failed to export model:'), err);
72
+ spinner.fail('Failed to export model:');
73
+ console.error(err);
74
+
47
75
  process.exit(1);
48
76
  }
49
77
  });