Skip to content

Commit 7d7f6cc

Browse files
authored
chore(release): prepare v0.4.0 (#225)
1 parent 81a427b commit 7d7f6cc

19 files changed

Lines changed: 945 additions & 732 deletions

File tree

.github/workflows/ci.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: Setup Node.js
1919
uses: actions/setup-node@v6
2020
with:
21-
node-version: 22
21+
node-version: 24
2222
cache: npm
2323
- name: Setup Python
2424
uses: actions/setup-python@v6
@@ -45,7 +45,7 @@ jobs:
4545
strategy:
4646
fail-fast: false
4747
matrix:
48-
node-version: [20, 22]
48+
node-version: [20, 24]
4949
python-version: ['3.10', '3.11', '3.12']
5050
steps:
5151
- uses: actions/checkout@v6
@@ -68,11 +68,11 @@ jobs:
6868
env:
6969
NODE_OPTIONS: --expose-gc
7070
TYWRAP_PERF_BUDGETS: '1'
71-
run: ${{ (matrix.node-version == 22 && matrix.python-version == '3.11') && 'npm run test:coverage' || 'npm test' }}
71+
run: ${{ (matrix.node-version == 24 && matrix.python-version == '3.11') && 'npm run test:coverage' || 'npm test' }}
7272

7373
- name: Upload coverage to Codecov
7474
uses: codecov/codecov-action@v6
75-
if: matrix.node-version == 22 && matrix.python-version == '3.11'
75+
if: matrix.node-version == 24 && matrix.python-version == '3.11'
7676
with:
7777
token: ${{ secrets.CODECOV_TOKEN }}
7878
files: ./coverage/lcov.info
@@ -124,7 +124,7 @@ jobs:
124124
- name: Setup Node.js
125125
uses: actions/setup-node@v6
126126
with:
127-
node-version: 22
127+
node-version: 24
128128
cache: npm
129129
- name: Setup Python
130130
uses: actions/setup-python@v6
@@ -179,7 +179,7 @@ jobs:
179179
- name: Setup Node.js
180180
uses: actions/setup-node@v6
181181
with:
182-
node-version: 22
182+
node-version: 24
183183
cache: npm
184184
- name: Setup Python
185185
uses: actions/setup-python@v6
@@ -209,7 +209,7 @@ jobs:
209209
- name: Setup Node.js
210210
uses: actions/setup-node@v6
211211
with:
212-
node-version: 22
212+
node-version: 24
213213
cache: npm
214214
- name: Setup Python
215215
uses: actions/setup-python@v6
@@ -239,7 +239,7 @@ jobs:
239239
- name: Setup Node.js
240240
uses: actions/setup-node@v6
241241
with:
242-
node-version: 22
242+
node-version: 24
243243
cache: npm
244244
- name: Setup Python
245245
uses: actions/setup-python@v6

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424

2525
- uses: actions/setup-node@v6
2626
with:
27-
node-version: 22
27+
node-version: 24
2828
cache: npm
2929

3030
- uses: actions/configure-pages@v6

.github/workflows/release.yml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ jobs:
172172
173173
- uses: actions/setup-node@v6
174174
with:
175-
node-version: 22
175+
node-version: 24
176176
cache: npm
177177

178178
- name: Skip if version is already published
@@ -212,12 +212,6 @@ jobs:
212212
NODE_OPTIONS: --expose-gc
213213
TYWRAP_PERF_BUDGETS: '1'
214214

215-
- name: Switch to Node 24 for npm trusted publishing
216-
if: ${{ steps.npm_registry.outputs.already_published != 'true' }}
217-
uses: actions/setup-node@v6
218-
with:
219-
node-version: 24
220-
221215
- name: Publish to npm
222216
if: ${{ steps.npm_registry.outputs.already_published != 'true' }}
223217
env:

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
# Changelog
22

3+
## [0.4.0](https://github.com/bbopen/tywrap/compare/v0.3.1...v0.4.0) (2026-04-12)
4+
5+
### Features
6+
7+
* add development hot reload helpers through `tywrap/dev`
8+
* add Node watch sessions that regenerate wrappers and swap the active bridge
9+
* pass the resolved config into bridge recreation during reloads
10+
11+
### Bug Fixes
12+
13+
* add structured generation failures and CLI handling for fatal vs stale output states
14+
* harden Node worker warmup, worker-pool publishing, and timeout recovery behavior
15+
* reject legacy config-based reload fields and point users to the new dev helpers
16+
* update docs to describe the real hot reload support matrix across Node, Pyodide, and HTTP
17+
318
## [0.3.1](https://github.com/bbopen/tywrap/compare/v0.3.0...v0.3.1) (2026-04-11)
419

520

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ TypeScript wrapper for Python libraries with full type safety.
1919

2020
- **Full Type Safety** - TypeScript definitions generated from Python source
2121
analysis
22+
- **Development Hot Reload** - Real Node watch sessions regenerate wrappers and
23+
swap the active bridge without re-importing generated modules
2224
- **Generic-Aware Declarations** - Preserves simple `TypeVar` and callable
2325
`ParamSpec` generics in generated `.ts` and `.d.ts` output
2426
- **Multi-Runtime** - Node.js (subprocess) and browsers (Pyodide)
@@ -62,6 +64,10 @@ For CI (or to verify a dependency upgrade didn’t change the generated surface)
6264
npx tywrap generate --check
6365
```
6466

67+
For local Node development, `tywrap/dev` gives you real hot reload: watch local
68+
Python package trees, regenerate wrappers, and swap the active bridge while
69+
keeping the last known good state if regeneration fails.
70+
6571
```typescript
6672
import { NodeBridge } from 'tywrap/node';
6773
import { setRuntimeBridge } from 'tywrap/runtime';
@@ -105,6 +111,31 @@ need the full environment. Large JSONL responses are capped by `maxLineLength`
105111
You can cap payload sizes with `TYWRAP_CODEC_MAX_BYTES` (responses) and
106112
`TYWRAP_REQUEST_MAX_BYTES` (requests) to keep JSONL traffic bounded.
107113

114+
## Development Hot Reload
115+
116+
```typescript
117+
import { startNodeWatchSession } from 'tywrap/dev';
118+
import { NodeBridge } from 'tywrap/node';
119+
120+
const session = await startNodeWatchSession({
121+
configFile: './tywrap.config.ts',
122+
createBridge: async config =>
123+
new NodeBridge({
124+
pythonPath: config.runtime.node?.pythonPath ?? 'python3',
125+
timeoutMs: config.runtime.node?.timeout ?? 30000,
126+
}),
127+
});
128+
```
129+
130+
- **Node**: full watch + wrapper regeneration + bridge swap
131+
- **Pyodide**: use `createBridgeReloader(...)` from `tywrap/dev` for manual
132+
bridge replacement
133+
- **HTTP**: restart or redeploy the remote server outside tywrap
134+
135+
The Node watch session manages local package trees, refreshes nested directory
136+
watchers when package layouts change, and keeps the last known good generated
137+
output and bridge active if regeneration returns structured failures.
138+
108139
### Browser (Pyodide)
109140

110141
```typescript

docs/guide/configuration.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,9 @@ sparse matrix classes (csr/csc/coo) to structured sparse objects.
289289
| `batching` | `boolean` | `false` | Batch multiple operations |
290290
| `compression` | `'auto' \| 'gzip' \| 'brotli' \| 'none'` | `'none'` | Output compression |
291291

292-
## Development Reload Helpers
292+
## Development Hot Reload Helpers
293293

294-
Development reload is no longer configured inside `tywrap.config.*`.
294+
Development hot reload is no longer configured inside `tywrap.config.*`.
295295

296296
Use `tywrap/dev` instead:
297297

docs/guide/getting-started.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,10 @@ async function demo() {
277277
}
278278
```
279279

280-
## Development Workflow
280+
## Development Workflow (Hot Reload)
281281

282-
Use `tywrap/dev` for wrapper regeneration plus bridge replacement:
282+
Use `tywrap/dev` for development hot reload: wrapper regeneration plus bridge
283+
replacement.
283284

284285
```typescript
285286
import { startNodeWatchSession } from 'tywrap/dev';
@@ -295,8 +296,9 @@ const session = await startNodeWatchSession({
295296
});
296297
```
297298

298-
For Pyodide, use `createBridgeReloader(...)` from `tywrap/dev` for manual bridge
299-
replacement. For HTTP, restart or redeploy the remote server outside tywrap.
299+
For Pyodide, use `createBridgeReloader(...)` from `tywrap/dev` for manual
300+
bridge replacement. For HTTP, restart or redeploy the remote server outside
301+
tywrap.
300302

301303
`startNodeWatchSession(...)` watches local package directories as directory
302304
trees, refreshes those trees when nested directories change, and keeps the last

docs/guide/runtimes/comparison.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ tywrap supports five runtime configurations. Choose based on your environment.
1111
| Apache Arrow transport ||||||
1212
| Virtual environment support ||||| Server-side |
1313
| Process pooling (experimental) ||||||
14+
| Development hot reload |||| Manual bridge reload | External |
1415
| Tested in CI ||| Mocked |||
1516

1617
## Import Paths

docs/guide/runtimes/node.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ The Node.js runtime:
2727
Both bridges share the same JSONL core for protocol validation, timeouts, and
2828
stderr buffering.
2929

30-
## Development Reload
30+
## Development Hot Reload
3131

32-
Node wrapper regeneration plus bridge replacement lives in `tywrap/dev`, not in
33-
`tywrap.config.*`.
32+
Node hot reload in tywrap means wrapper regeneration plus bridge replacement.
33+
It lives in `tywrap/dev`, not in `tywrap.config.*`.
3434

3535
```typescript
3636
import { startNodeWatchSession } from 'tywrap/dev';

docs/index.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,26 @@ setRuntimeBridge(new NodeBridge({ pythonPath: 'python3' }));
2424
const result = await math.sqrt(16); // 4 — fully typed
2525
```
2626

27+
## Development Hot Reload
28+
29+
```typescript
30+
import { startNodeWatchSession } from 'tywrap/dev';
31+
import { NodeBridge } from 'tywrap/node';
32+
33+
const session = await startNodeWatchSession({
34+
configFile: './tywrap.config.ts',
35+
createBridge: async config =>
36+
new NodeBridge({
37+
pythonPath: config.runtime.node?.pythonPath ?? 'python3',
38+
timeoutMs: config.runtime.node?.timeout ?? 30000,
39+
}),
40+
});
41+
```
42+
43+
Use `reloadNow()` for an explicit rebuild or `close()` to stop watching. Node
44+
gets full hot reload, Pyodide gets manual bridge replacement through
45+
`createBridgeReloader(...)`, and HTTP reload remains external to tywrap.
46+
2747
> ⚠️ **Experimental** — APIs may change before v1.0.0. See [Releases](https://github.com/bbopen/tywrap/releases) for breaking changes.
2848
2949
> If tywrap saves you time, a ⭐ on [GitHub](https://github.com/bbopen/tywrap) helps others find it.

0 commit comments

Comments
 (0)