pynect 0.0.0 → 0.2.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/LICENSE +1 -1
- package/README.md +503 -2
- package/SECURITY.md +34 -0
- package/binding.gyp +67 -0
- package/dist/cli/codegen.d.ts +3 -0
- package/dist/cli/codegen.d.ts.map +1 -0
- package/dist/cli/codegen.js +543 -0
- package/dist/cli/codegen.js.map +1 -0
- package/dist/cli/sync.d.ts +3 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +47 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/config/project.d.ts +113 -0
- package/dist/config/project.d.ts.map +1 -0
- package/dist/config/project.js +344 -0
- package/dist/config/project.js.map +1 -0
- package/dist/core/isolated-worker.d.ts +39 -0
- package/dist/core/isolated-worker.d.ts.map +1 -0
- package/dist/core/isolated-worker.js +178 -0
- package/dist/core/isolated-worker.js.map +1 -0
- package/dist/core/py-callable.d.ts +67 -0
- package/dist/core/py-callable.d.ts.map +1 -0
- package/dist/core/py-callable.js +104 -0
- package/dist/core/py-callable.js.map +1 -0
- package/dist/core/py-context.d.ts +76 -0
- package/dist/core/py-context.d.ts.map +1 -0
- package/dist/core/py-context.js +239 -0
- package/dist/core/py-context.js.map +1 -0
- package/dist/core/py-iterator.d.ts +84 -0
- package/dist/core/py-iterator.d.ts.map +1 -0
- package/dist/core/py-iterator.js +243 -0
- package/dist/core/py-iterator.js.map +1 -0
- package/dist/core/py-module.d.ts +53 -0
- package/dist/core/py-module.d.ts.map +1 -0
- package/dist/core/py-module.js +162 -0
- package/dist/core/py-module.js.map +1 -0
- package/dist/core/py-proxy.d.ts +75 -0
- package/dist/core/py-proxy.d.ts.map +1 -0
- package/dist/core/py-proxy.js +563 -0
- package/dist/core/py-proxy.js.map +1 -0
- package/dist/core/py-runtime.d.ts +113 -0
- package/dist/core/py-runtime.d.ts.map +1 -0
- package/dist/core/py-runtime.js +528 -0
- package/dist/core/py-runtime.js.map +1 -0
- package/dist/env/executables.d.ts +3 -0
- package/dist/env/executables.d.ts.map +1 -0
- package/dist/env/executables.js +14 -0
- package/dist/env/executables.js.map +1 -0
- package/dist/env/package-installer.d.ts +232 -0
- package/dist/env/package-installer.d.ts.map +1 -0
- package/dist/env/package-installer.js +615 -0
- package/dist/env/package-installer.js.map +1 -0
- package/dist/env/project-environment.d.ts +64 -0
- package/dist/env/project-environment.d.ts.map +1 -0
- package/dist/env/project-environment.js +388 -0
- package/dist/env/project-environment.js.map +1 -0
- package/dist/env/pyfig-adapter.d.ts +38 -0
- package/dist/env/pyfig-adapter.d.ts.map +1 -0
- package/dist/env/pyfig-adapter.js +10 -0
- package/dist/env/pyfig-adapter.js.map +1 -0
- package/dist/env/python-detector.d.ts +48 -0
- package/dist/env/python-detector.d.ts.map +1 -0
- package/dist/env/python-detector.js +182 -0
- package/dist/env/python-detector.js.map +1 -0
- package/dist/env/python-provisioner.d.ts +16 -0
- package/dist/env/python-provisioner.d.ts.map +1 -0
- package/dist/env/python-provisioner.js +42 -0
- package/dist/env/python-provisioner.js.map +1 -0
- package/dist/env/venv-manager.d.ts +56 -0
- package/dist/env/venv-manager.d.ts.map +1 -0
- package/dist/env/venv-manager.js +160 -0
- package/dist/env/venv-manager.js.map +1 -0
- package/dist/index.d.ts +182 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +394 -0
- package/dist/index.js.map +1 -0
- package/dist/native/native-addon-loader.d.ts +13 -0
- package/dist/native/native-addon-loader.d.ts.map +1 -0
- package/dist/native/native-addon-loader.js +171 -0
- package/dist/native/native-addon-loader.js.map +1 -0
- package/dist/plugins/builtin/numpy-plugin.d.ts +17 -0
- package/dist/plugins/builtin/numpy-plugin.d.ts.map +1 -0
- package/dist/plugins/builtin/numpy-plugin.js +41 -0
- package/dist/plugins/builtin/numpy-plugin.js.map +1 -0
- package/dist/plugins/builtin/pandas-plugin.d.ts +19 -0
- package/dist/plugins/builtin/pandas-plugin.d.ts.map +1 -0
- package/dist/plugins/builtin/pandas-plugin.js +57 -0
- package/dist/plugins/builtin/pandas-plugin.js.map +1 -0
- package/dist/plugins/builtin/torch-plugin.d.ts +23 -0
- package/dist/plugins/builtin/torch-plugin.d.ts.map +1 -0
- package/dist/plugins/builtin/torch-plugin.js +50 -0
- package/dist/plugins/builtin/torch-plugin.js.map +1 -0
- package/dist/plugins/index.d.ts +7 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +12 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/plugin-manager.d.ts +26 -0
- package/dist/plugins/plugin-manager.d.ts.map +1 -0
- package/dist/plugins/plugin-manager.js +174 -0
- package/dist/plugins/plugin-manager.js.map +1 -0
- package/dist/plugins/plugin.interface.d.ts +41 -0
- package/dist/plugins/plugin.interface.d.ts.map +1 -0
- package/dist/plugins/plugin.interface.js +12 -0
- package/dist/plugins/plugin.interface.js.map +1 -0
- package/dist/serialization/data-frame-bridge.d.ts +141 -0
- package/dist/serialization/data-frame-bridge.d.ts.map +1 -0
- package/dist/serialization/data-frame-bridge.js +355 -0
- package/dist/serialization/data-frame-bridge.js.map +1 -0
- package/dist/serialization/msg-pack-serializer.d.ts +45 -0
- package/dist/serialization/msg-pack-serializer.d.ts.map +1 -0
- package/dist/serialization/msg-pack-serializer.js +242 -0
- package/dist/serialization/msg-pack-serializer.js.map +1 -0
- package/dist/serialization/numpy-bridge.d.ts +96 -0
- package/dist/serialization/numpy-bridge.d.ts.map +1 -0
- package/dist/serialization/numpy-bridge.js +323 -0
- package/dist/serialization/numpy-bridge.js.map +1 -0
- package/dist/serialization/serializer.d.ts +78 -0
- package/dist/serialization/serializer.d.ts.map +1 -0
- package/dist/serialization/serializer.js +281 -0
- package/dist/serialization/serializer.js.map +1 -0
- package/dist/types/addon.d.ts +131 -0
- package/dist/types/addon.d.ts.map +1 -0
- package/dist/types/addon.js +32 -0
- package/dist/types/addon.js.map +1 -0
- package/dist/types/config.d.ts +236 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +61 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +12 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/python.d.ts +235 -0
- package/dist/types/python.d.ts.map +1 -0
- package/dist/types/python.js +7 -0
- package/dist/types/python.js.map +1 -0
- package/dist/utils/error-translator.d.ts +83 -0
- package/dist/utils/error-translator.d.ts.map +1 -0
- package/dist/utils/error-translator.js +210 -0
- package/dist/utils/error-translator.js.map +1 -0
- package/dist/utils/locking.d.ts +3 -0
- package/dist/utils/locking.d.ts.map +1 -0
- package/dist/utils/locking.js +10 -0
- package/dist/utils/locking.js.map +1 -0
- package/dist/utils/logger.d.ts +27 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +115 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/memory-monitor.d.ts +43 -0
- package/dist/utils/memory-monitor.d.ts.map +1 -0
- package/dist/utils/memory-monitor.js +143 -0
- package/dist/utils/memory-monitor.js.map +1 -0
- package/package.json +93 -17
- package/prebuilds/darwin-arm64/pynect-prebuild.json +8 -0
- package/prebuilds/darwin-arm64/pynect_addon.node +0 -0
- package/prebuilds/darwin-x64/pynect-prebuild.json +8 -0
- package/prebuilds/darwin-x64/pynect_addon.node +0 -0
- package/prebuilds/linux-arm64/pynect-prebuild.json +9 -0
- package/prebuilds/linux-arm64/pynect_addon.node +0 -0
- package/prebuilds/linux-x64/pynect-prebuild.json +9 -0
- package/prebuilds/linux-x64/pynect_addon.node +0 -0
- package/prebuilds/win32-arm64/pynect-prebuild.json +8 -0
- package/prebuilds/win32-arm64/pynect_addon.node +0 -0
- package/prebuilds/win32-x64/pynect-prebuild.json +8 -0
- package/prebuilds/win32-x64/pynect_addon.node +0 -0
- package/python/ast_inspector.py +248 -0
- package/python/error_handler.py +432 -0
- package/python/isolated_worker.py +94 -0
- package/python/pynect_dispatcher.py +382 -0
- package/python/pynect_runtime.py +574 -0
- package/python/serializer.py +373 -0
- package/python/type_inspector.py +315 -0
- package/scripts/build-native.js +50 -0
- package/scripts/cli.js +21 -0
- package/scripts/ensure-native.js +85 -0
- package/scripts/postinstall.js +40 -0
- package/scripts/pyfig.js +128 -0
- package/scripts/python-provisioner.js +23 -0
- package/scripts/smoke-python-boundary.js +103 -0
- package/src/native/gil_guard.cpp +25 -0
- package/src/native/gil_guard.h +174 -0
- package/src/native/native-addon-loader.ts +218 -0
- package/src/native/pynect_addon.cpp +942 -0
- package/src/native/python_bridge.cpp +904 -0
- package/src/native/python_bridge.h +263 -0
- package/src/native/thread_pool.cpp +375 -0
- package/src/native/thread_pool.h +185 -0
- package/src/native/type_converter.cpp +906 -0
- package/src/native/type_converter.h +271 -0
- package/index.d.ts +0 -3
- package/index.js +0 -3
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2026 Reggie Bowser
|
|
3
|
+
Copyright (c) 2026 Reggie Bowser and NodePyX contributors
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -1,5 +1,506 @@
|
|
|
1
1
|
# Pynect
|
|
2
2
|
|
|
3
|
-
Pynect
|
|
3
|
+
Pynect lets Node.js and Bun call Python modules in-process with generated TypeScript declarations and optional Python-side Pydantic validation. Python type hints remain the source of truth, so projects do not need a separately maintained controller interface or TypeScript validation schema.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Python remains responsible for normalization and validation. If Pydantic 1 or 2 is importable, annotated arguments and return values are validated automatically. Pydantic is optional; Pynect does not install it.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
bun add --trust pynect
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Declare application Python dependencies. Pynect's trusted postinstall creates the uv project and synchronizes the locked environment:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"pynect": {
|
|
18
|
+
"project": {
|
|
19
|
+
"requires-python": ">=3.11,<3.13",
|
|
20
|
+
"dependencies": ["pydantic>=2,<3"]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The `pynect` value is a JSON projection of the generated `pyproject.toml`. Omitted
|
|
27
|
+
`schemaVersion` means the latest schema supported by the installed Pynect release.
|
|
28
|
+
The same shape is accepted programmatically:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { init } from 'pynect';
|
|
32
|
+
|
|
33
|
+
await init({
|
|
34
|
+
project: {
|
|
35
|
+
'requires-python': '>=3.11,<3.13',
|
|
36
|
+
dependencies: ['pydantic>=2,<3'],
|
|
37
|
+
},
|
|
38
|
+
tool: {
|
|
39
|
+
pynect: { autoSync: 'if-missing' },
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
When lifecycle scripts are disabled or Pynect is not trusted, run `bunx --bun pynect sync` explicitly.
|
|
45
|
+
|
|
46
|
+
Current Bun releases and Node.js 22 or newer are supported. Bun-only systems do not need a `node` executable. A preinstalled Python or uv is also unnecessary: Pynect uses Pyfig 0.4 to reuse a compatible application environment or create `<project-root>/node_modules/.pyfig/venv`, installing its pinned uv and a managed GIL-enabled Python 3.12 when no compatible embeddable CPython exists. A matching Python 3.12 prebuild is loaded when available; other Python minors and incompatible platform baselines fall back to compiling with the active JavaScript runtime from `process.execPath` and require a C++ toolchain.
|
|
47
|
+
|
|
48
|
+
## Quick start
|
|
49
|
+
|
|
50
|
+
Add a typed Python module such as `calculator.py`:
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
def add(left: int, right: int) -> int:
|
|
54
|
+
return left + right
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Generate declarations for the project. With no module arguments, Pynect discovers Python files under conventional `src` or `python` source roots, falling back to the current directory. Public members are included by default; private modules, private members, and files ending in `_example.py` are skipped:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
bunx --bun pynect codegen
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`bunx --bun` makes Bun execute the package binary itself, so codegen does not require a separate Node.js installation.
|
|
64
|
+
|
|
65
|
+
Code generation uses [Pacwich](https://github.com/smorsic/pacwich) to resolve the current package or monorepo workspace. By default it also adds the generated declarations to `tsconfig.json`, adds a `codegen` package script when one does not exist, and ignores the generated metadata directory in `.gitignore`.
|
|
66
|
+
|
|
67
|
+
Use the generated module type directly:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { importModule } from 'pynect';
|
|
71
|
+
|
|
72
|
+
const calculator = await importModule('calculator');
|
|
73
|
+
console.log(await calculator.add(2, 3));
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`importModule()` initializes the shared runtime with defaults on first use and the runtime shuts down automatically when the process finishes. Call `init(config)` first only when custom runtime settings are needed. Call `shutdown()` explicitly only when the application needs to release Python before process exit.
|
|
77
|
+
|
|
78
|
+
## Add Pydantic validation
|
|
79
|
+
|
|
80
|
+
For Python-side normalization and validation, use Pydantic models in a module such as `users.py`:
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from pydantic import BaseModel
|
|
84
|
+
|
|
85
|
+
class UserInput(BaseModel):
|
|
86
|
+
name: str
|
|
87
|
+
age: int
|
|
88
|
+
|
|
89
|
+
class UserResult(BaseModel):
|
|
90
|
+
id: int
|
|
91
|
+
name: str
|
|
92
|
+
|
|
93
|
+
def create_user(data: UserInput) -> UserResult:
|
|
94
|
+
return UserResult(id=1, name=data.name)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Regenerate the project declarations:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
bunx --bun pynect codegen
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Then restrict the dispatcher to fully typed members in that module:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import { init, importModule } from 'pynect';
|
|
107
|
+
|
|
108
|
+
await init({
|
|
109
|
+
dispatcher: {
|
|
110
|
+
include: ['users.*'],
|
|
111
|
+
typedOnly: true,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const users = await importModule('users');
|
|
116
|
+
const user = await users.create_user({ name: 'Alice', age: 30 });
|
|
117
|
+
console.log(user.name);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
When Pydantic is installed in the selected Python environment, the input object becomes a `UserInput` before the function runs. The returned `UserResult` is validated and converted to JSON-compatible Python values before it crosses back to JavaScript. Without Pydantic, the annotated Python call still works but Pydantic validation is skipped.
|
|
121
|
+
|
|
122
|
+
## Why Pynect
|
|
123
|
+
|
|
124
|
+
Pynect and [PyBridge](https://github.com/marcj/pybridge) connect TypeScript and Python with different execution models. Pynect may be a better fit when you want:
|
|
125
|
+
|
|
126
|
+
- CPython embedded in the Node.js or Bun process instead of a Python subprocess connected over standard input and output.
|
|
127
|
+
- TypeScript declarations generated by inspecting Python modules instead of a separately maintained TypeScript controller interface.
|
|
128
|
+
- Direct proxy access to Python modules, classes, objects, and functions.
|
|
129
|
+
- Optional Pydantic 1 or 2 validation and normalization in Python, including Python-defined validators and serializers.
|
|
130
|
+
- Include, exclude, type-hint, and export policies enforced at the dispatcher boundary.
|
|
131
|
+
- Automatic embeddable-Python discovery with a checksum-verified uv fallback when Python is unavailable or lacks development headers.
|
|
132
|
+
|
|
133
|
+
PyBridge may be a better fit when every call must be process-isolated, or when RxJS generator streaming or Deepkit runtime serialization and reflection matter more than direct in-process access.
|
|
134
|
+
|
|
135
|
+
The main tradeoff is isolation versus integration. Normal Pynect proxy calls avoid subprocess transport and duplicate controller definitions, while its optional JSON-only worker provides hard termination for selected calls. Supported Python 3.12 platform prebuilds avoid a local compiler; fallback builds still require a C++ toolchain.
|
|
136
|
+
|
|
137
|
+
## Python and native build
|
|
138
|
+
|
|
139
|
+
The package first loads a prebuilt N-API addon whose platform, architecture, Python minor, N-API version, and Linux glibc baseline match the active process. On Linux and macOS, Pynect materializes that addon beside a symlink to the exact `libpython` selected by Pyfig, so the binary does not depend on the CI machine's Python path. It then checks for an exact local build whose manifest names the selected interpreter. If neither addon works, Pynect lazily builds one against that interpreter. The builder is launched with `process.execPath`, so Bun launches Bun and Node.js launches Node.js instead of assuming a `node` command exists. The same approach works with another Node-compatible runtime when it implements the child-process and N-API behavior Pynect needs.
|
|
140
|
+
|
|
141
|
+
```mermaid
|
|
142
|
+
graph TD;
|
|
143
|
+
A[First runtime initialization] --> B[Pyfig selects application Python];
|
|
144
|
+
B --> C{Compatible prebuild or exact local addon loads};
|
|
145
|
+
C -->|Yes| G[Initialize embedded CPython];
|
|
146
|
+
C -->|No| D[Launch builder with process execPath];
|
|
147
|
+
D --> E[Build against selected Python headers and library];
|
|
148
|
+
E --> F[Load newly built addon];
|
|
149
|
+
F --> G;
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Pynect requires Python 3.10 or newer, `Python.h`, a linkable CPython library, and the standard GIL-enabled ABI. It rejects a runtime-only or free-threaded installation instead of compiling against unrelated `python3-config` output. When no compatible interpreter exists, Pyfig downloads the pinned uv archive from Astral's GitHub release, verifies its SHA-256 checksum, and installs managed Python 3.12.
|
|
153
|
+
|
|
154
|
+
Builds, the embedded runtime, codegen, isolated workers, and uv package operations all use the same Pyfig-selected interpreter. Pyfig reuses a compatible active or root `.venv`; otherwise it creates the application-private `node_modules/.pyfig/venv`. `virtualenv.path` is deprecated and, when provided for compatibility, must resolve to the selected environment.
|
|
155
|
+
|
|
156
|
+
## Locked application environment
|
|
157
|
+
|
|
158
|
+
One application owns one Pyfig-selected environment and one `pynect.lock`. Reusable npm packages contribute requirements and exposed modules through their `package.json` without installing anything themselves:
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"name": "@acme/name-generator",
|
|
163
|
+
"dependencies": {
|
|
164
|
+
"pynect": "^0.2.0"
|
|
165
|
+
},
|
|
166
|
+
"pynect": {
|
|
167
|
+
"project": {
|
|
168
|
+
"requires-python": ">=3.11,<3.13",
|
|
169
|
+
"dependencies": ["name-generator>=1,<2"]
|
|
170
|
+
},
|
|
171
|
+
"tool": {
|
|
172
|
+
"pynect": {
|
|
173
|
+
"modules": {
|
|
174
|
+
"generator": {
|
|
175
|
+
"import": "name_generator",
|
|
176
|
+
"include": ["generate_name"]
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`pynect sync` walks the installed npm dependency graph and writes one minimal generated uv project beside the resolved Pynect installation, normally at `node_modules/.pynect/pyproject.toml`. Hoisted installations add a stable application-specific directory below `.pynect` so workspaces cannot overwrite one another. uv performs dependency resolution, writes its native universal lock, and exactly synchronizes the environment selected by Pyfig; Pynect copies that native lock to the configured `pynect.lock` path for check-in. uv's shared cache avoids repeated downloads across environments. Pynect records the environment path, manifest hash, lock hash, Python ABI, platform, and contributing packages in the generated directory's `.pynect-state.json`.
|
|
186
|
+
|
|
187
|
+
Pynect does not implement a Python package resolver. Conflicts and platform-specific selections are handled by uv, while Pynect adds the npm packages that contributed each top-level requirement to failure output. Dependency manifests may declare `project` dependency metadata and `tool.pynect.modules`; Python selection, installation policy, generated-file and lockfile placement, indexes, and credentials remain application-owned.
|
|
188
|
+
|
|
189
|
+
The root application may resolve a known conflict explicitly without changing a dependency package:
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"pynect": {
|
|
194
|
+
"tool": {
|
|
195
|
+
"uv": {
|
|
196
|
+
"override-dependencies": ["image-lib>=2,<3"]
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Overrides are emitted as uv's native `tool.uv.override-dependencies` configuration and included in the manifest fingerprint. Configure private indexes with uv's application environment variables such as `UV_DEFAULT_INDEX`; keep credentials outside `package.json`.
|
|
204
|
+
|
|
205
|
+
Exposed module ids are namespaced by npm package name:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
import { importModule } from 'pynect';
|
|
209
|
+
|
|
210
|
+
const generator = await importModule('@acme/name-generator:generator');
|
|
211
|
+
console.log(await generator.generate_name());
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
The aggregated `modules.include` patterns are enforced by the runtime dispatcher. When `include` is omitted, that manifest exposes the module's public callables; application dispatcher includes are additive, and excludes always win.
|
|
215
|
+
|
|
216
|
+
Normal runtime startup validates the lock and environment state without network access. Applications that want development-time repair may opt in with `"tool": { "pynect": { "autoSync": "if-missing" } }`; the default is `"never"`. Production and CI should use an explicit frozen sync:
|
|
217
|
+
|
|
218
|
+
```sh
|
|
219
|
+
bunx --bun pynect sync --frozen
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Pynect's postinstall runs the same sync automatically when a reachable npm package contributes a `pynect` manifest. Set `PYNECT_SKIP_POSTINSTALL=1` to opt out. npm users can also use `--ignore-scripts`; Bun users must explicitly trust `pynect` because Bun blocks dependency lifecycle scripts by default:
|
|
223
|
+
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"trustedDependencies": ["pynect"]
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
An application may always keep installation side-effect free and run `pynect sync` explicitly instead.
|
|
231
|
+
|
|
232
|
+
Package and programmatic configuration use the same JSON pyproject projection. Configuration precedence is API or CLI, environment, root `package.json`, then default:
|
|
233
|
+
|
|
234
|
+
| package.json / API | Environment | CLI | Default |
|
|
235
|
+
| --- | --- | --- | --- |
|
|
236
|
+
| `tool.pynect.python` | `PYNECT_PYTHON` | `--python` | auto-detect |
|
|
237
|
+
| `project["requires-python"]` | `PYNECT_REQUIRES_PYTHON` | `--requires-python` | `>=3.10.0 <4.0.0` |
|
|
238
|
+
| `tool.pynect.managedPython` | `PYNECT_MANAGED_PYTHON` | `--managed-python` | `3.12` |
|
|
239
|
+
| `tool.pynect.uvVersion` | `PYNECT_UV_VERSION` | `--uv-version` | Pyfig's pinned release |
|
|
240
|
+
| `tool.pynect.installPython` | `PYNECT_INSTALL_PYTHON` | `--install-python` | `true` |
|
|
241
|
+
| `tool.pynect.installUv` | `PYNECT_INSTALL_UV` | `--install-uv` | `true` |
|
|
242
|
+
| `tool.pynect.createVirtualEnvironment` | `PYNECT_CREATE_VIRTUAL_ENVIRONMENT` | `--create-virtual-environment` | `true` |
|
|
243
|
+
| `tool.pynect.autoSync` | `PYNECT_AUTO_SYNC` | n/a | `never` |
|
|
244
|
+
| `tool.pynect.lockfile` | `PYNECT_LOCKFILE` | `--lockfile` | `pynect.lock` |
|
|
245
|
+
| `tool.pynect.generatedDirectory` | `PYNECT_GENERATED_DIRECTORY` | `--generated-directory` | beside the Pynect install |
|
|
246
|
+
|
|
247
|
+
Relative generated-directory values resolve from the application root. This lets linked, global, read-only, or nonstandard installations choose a writable runtime location without changing dependency manifests. `--offline` prohibits network access. `--frozen` passes uv's `--locked` check and refuses to rewrite an outdated lock. The deprecated flat package keys, `PYNECT_AUTO_INSTALL`, and runtime `autoInstallPython` name remain compatibility aliases; new configuration should use the nested names above. Runtime `virtualenv.autoInstall` is no longer supported because independent startup installs cannot resolve the complete npm dependency graph safely.
|
|
248
|
+
|
|
249
|
+
Pynect uses [loqkit](https://www.npmjs.com/package/loqkit) for JavaScript critical sections. Project sync and native builds use its default layered memory, worker-thread, and cross-process file locks. Runtime lifecycle and Python garbage collection use memory-scoped locks because those resources belong to one JavaScript process. Pynect does not maintain separate promise, module, inspection, or proxy memo caches; new memoized getters should use loqkit's `memoize` primitive.
|
|
250
|
+
|
|
251
|
+
Pyfig's managed-tool provisioning uses its own check-lock-check sections:
|
|
252
|
+
|
|
253
|
+
1. Check for an existing tool.
|
|
254
|
+
2. Acquire a cross-process file lock.
|
|
255
|
+
3. Check again.
|
|
256
|
+
4. Install only if it is still absent.
|
|
257
|
+
|
|
258
|
+
A C++ build toolchain is required only when no compatible prebuild is available. On Windows, fallback builds need Visual Studio Build Tools with the Desktop development with C++ workload. Set `PYNECT_AUTO_INSTALL=0` to prohibit managed Python downloads while still allowing environment creation from a compatible setup-python or system interpreter. Set `PYNECT_INSTALL_UV=0` to prohibit uv installation, `PYNECT_CREATE_VIRTUAL_ENVIRONMENT=0` to require an existing compatible environment, or `PYNECT_PYTHON` to check a specific interpreter first.
|
|
259
|
+
|
|
260
|
+
## Codegen selection
|
|
261
|
+
|
|
262
|
+
The simplest form discovers project modules and generates every public member:
|
|
263
|
+
|
|
264
|
+
```sh
|
|
265
|
+
bunx --bun pynect codegen
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Pass module names when you only want specific modules:
|
|
269
|
+
|
|
270
|
+
```sh
|
|
271
|
+
bunx --bun pynect codegen users billing
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Add repeatable include and exclude patterns when a project needs a narrower surface. Supplying `--include` restricts output to matching members. Supplying `--typed` restricts output to fully typed members. `--exclude` always excludes. Patterns match leaf or qualified names:
|
|
275
|
+
|
|
276
|
+
```sh
|
|
277
|
+
bunx --bun pynect codegen users billing \
|
|
278
|
+
--include 'users.*' \
|
|
279
|
+
--include 'billing.Invoice*' \
|
|
280
|
+
--exclude '*internal*' \
|
|
281
|
+
--typed
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
For reusable settings, put the same options in `pynect.config.json`:
|
|
285
|
+
|
|
286
|
+
```json
|
|
287
|
+
{
|
|
288
|
+
"src": ["./python"],
|
|
289
|
+
"outDir": "./generated",
|
|
290
|
+
"include": ["users.*", "billing.Invoice*"],
|
|
291
|
+
"exclude": ["*internal*"],
|
|
292
|
+
"typed": true,
|
|
293
|
+
"configure": true
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
The CLI uses Commander. Configuration precedence is CLI, environment, JSON config, then defaults. Set `"configure": false` or pass `--no-configure` to prevent edits to `tsconfig.json`, `package.json`, and `.gitignore`. Use `--tsconfig` when the workspace uses a nonstandard config filename.
|
|
298
|
+
|
|
299
|
+
Automatic discovery skips directories, packages, and modules whose names begin with `_`, common environment and build directories, and files ending in `_example.py`. The same private-package rule applies to explicitly requested module paths. Use repeatable `--src` options when Python lives somewhere else:
|
|
300
|
+
|
|
301
|
+
```sh
|
|
302
|
+
bunx --bun pynect codegen --src ./backend --src ./shared-python
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Local source files are parsed with Python's AST and are not imported during generation. Explicit installed modules that cannot be resolved under a configured source root use live inspection so packages such as NumPy and pandas can still expose their runtime API.
|
|
306
|
+
|
|
307
|
+
Use centralized overrides for opaque extension types or legacy untyped functions:
|
|
308
|
+
|
|
309
|
+
```json
|
|
310
|
+
{
|
|
311
|
+
"typeOverrides": {
|
|
312
|
+
"UUID": "string",
|
|
313
|
+
"Decimal": "number"
|
|
314
|
+
},
|
|
315
|
+
"signatureOverrides": {
|
|
316
|
+
"legacy.lookup": "(userId: string): Promise<User>",
|
|
317
|
+
"legacy.Client.fetch": "(limit?: number): Promise<User[]>"
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Type overrides map a Python annotation name wherever it appears. Signature overrides are keyed by the fully qualified function or method name and replace its generated TypeScript call signature.
|
|
323
|
+
|
|
324
|
+
Other commands:
|
|
325
|
+
|
|
326
|
+
```sh
|
|
327
|
+
bunx pynect codegen --list
|
|
328
|
+
bunx pynect codegen --all
|
|
329
|
+
bunx pynect codegen --clear
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
`--all` means all modules tracked in generated metadata. Within each requested module, the default is all public members. Use `--exported` to require the `@export` marker or `--typed` to require complete parameter and return type hints.
|
|
333
|
+
|
|
334
|
+
## Raw module imports
|
|
335
|
+
|
|
336
|
+
Generated declarations are the normal application workflow. For exploration, third-party packages, or Python modules that do not need generated types, import a module directly:
|
|
337
|
+
|
|
338
|
+
```ts
|
|
339
|
+
import { importModule } from 'pynect';
|
|
340
|
+
|
|
341
|
+
const math = await importModule('math');
|
|
342
|
+
console.log(await math.sqrt(9));
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Raw imports return a dynamic Python proxy. Run codegen when the module should provide TypeScript inference in application code.
|
|
346
|
+
|
|
347
|
+
## Runtime policy
|
|
348
|
+
|
|
349
|
+
```ts
|
|
350
|
+
await init({
|
|
351
|
+
autoShutdown: true,
|
|
352
|
+
dispatcher: {
|
|
353
|
+
include: ['my_app.*'],
|
|
354
|
+
exclude: ['*.admin.*', '*._*'],
|
|
355
|
+
typedOnly: true,
|
|
356
|
+
exportedOnly: false,
|
|
357
|
+
validation: 'auto', // auto, required, or off
|
|
358
|
+
},
|
|
359
|
+
allowUnsafeCode: false,
|
|
360
|
+
allowPackageInstall: false,
|
|
361
|
+
includeTracebacks: false,
|
|
362
|
+
});
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
`autoShutdown` defaults to `true` for both the embedded runtime and the optional isolated worker. Set it to `false` only when the host owns lifecycle and will call `shutdown()` explicitly.
|
|
366
|
+
|
|
367
|
+
Defaults are intentionally conservative around dangerous bridge features:
|
|
368
|
+
|
|
369
|
+
- Raw `eval`, `exec`, file execution, contexts, and native-addon access are disabled.
|
|
370
|
+
- Runtime package installation is disabled.
|
|
371
|
+
- Python tracebacks are hidden.
|
|
372
|
+
- Private callables and modules are rejected.
|
|
373
|
+
- Excludes override includes and decorators.
|
|
374
|
+
- Pydantic validation is automatic only when Pydantic is already importable.
|
|
375
|
+
|
|
376
|
+
Every normal proxy function, method, and constructor call passes through this policy and validation dispatcher.
|
|
377
|
+
`typedOnly` and `exportedOnly` are independent: enabling both requires every callable to be explicitly exported and fully typed.
|
|
378
|
+
|
|
379
|
+
The worker pool defaults to the larger of four workers or the host's available CPU count. This improves queue scheduling; the CPython GIL still prevents CPU-bound Python bytecode from running in parallel within one interpreter.
|
|
380
|
+
|
|
381
|
+
## Cancellation and timeouts
|
|
382
|
+
|
|
383
|
+
`callTimeout` limits time waiting in the native queue. `executionTimeout` separately cancels asynchronous Python execution:
|
|
384
|
+
|
|
385
|
+
```ts
|
|
386
|
+
await init({
|
|
387
|
+
callTimeout: 2_000,
|
|
388
|
+
executionTimeout: 10_000,
|
|
389
|
+
});
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Every generated function and method includes a typed `withOptions()` call:
|
|
393
|
+
|
|
394
|
+
```ts
|
|
395
|
+
import { importModule } from 'pynect';
|
|
396
|
+
|
|
397
|
+
const jobs = await importModule('jobs');
|
|
398
|
+
const controller = new AbortController();
|
|
399
|
+
|
|
400
|
+
setTimeout(() => controller.abort(), 1_000);
|
|
401
|
+
await jobs.run_job.withOptions(
|
|
402
|
+
{ signal: controller.signal, executionTimeout: 5_000 },
|
|
403
|
+
{ id: 42 },
|
|
404
|
+
);
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
`withOptions` is a property on the callable, so it does not consume a sibling module name such as `run_jobWithOptions`. If a Python callable itself defines a `withOptions` attribute, use the exported `PYNECT_WITH_OPTIONS` symbol for the bridge operation:
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
import { PYNECT_WITH_OPTIONS } from 'pynect';
|
|
411
|
+
|
|
412
|
+
await jobs.run_job[PYNECT_WITH_OPTIONS](
|
|
413
|
+
{ executionTimeout: 5_000 },
|
|
414
|
+
{ id: 42 },
|
|
415
|
+
);
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
Queued calls are removed before execution when possible. Running async functions are cancelled on the persistent asyncio loop. Arbitrary synchronous CPython code cannot be interrupted safely inside the Node.js process.
|
|
419
|
+
|
|
420
|
+
## Isolated calls
|
|
421
|
+
|
|
422
|
+
Enable the optional worker when a call needs a hard timeout or when an ordinary Python interpreter crash should be contained outside the Node.js process:
|
|
423
|
+
|
|
424
|
+
```ts
|
|
425
|
+
import { callIsolated, init, shutdown } from 'pynect';
|
|
426
|
+
|
|
427
|
+
await init({
|
|
428
|
+
isolation: {
|
|
429
|
+
enabled: true,
|
|
430
|
+
timeout: 30_000,
|
|
431
|
+
},
|
|
432
|
+
dispatcher: {
|
|
433
|
+
include: ['jobs.*'],
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
try {
|
|
438
|
+
const result = await callIsolated(
|
|
439
|
+
'jobs',
|
|
440
|
+
'run_job',
|
|
441
|
+
[{ id: 42 }],
|
|
442
|
+
{ timeout: 5_000 },
|
|
443
|
+
);
|
|
444
|
+
console.log(result);
|
|
445
|
+
} finally {
|
|
446
|
+
await shutdown();
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Isolated calls use a lazy persistent Python child process and JSON-compatible arguments and results. Calls through that worker are serialized. A timeout or abort terminates it, rejects its outstanding calls, and lets the next call start a fresh worker. The child process still has the operating-system permissions of the current user; use an OS sandbox or container for hostile code.
|
|
451
|
+
|
|
452
|
+
## Pydantic modes
|
|
453
|
+
|
|
454
|
+
- `auto`: validate every supported argument and return annotation when Pydantic 1 or 2 is available; otherwise preserve Python behavior. This is the default for all normal callable dispatches.
|
|
455
|
+
- `required`: reject calls when Pydantic is missing or cannot build a validator for an annotation.
|
|
456
|
+
- `off`: never ask Pydantic to validate.
|
|
457
|
+
|
|
458
|
+
Pydantic models, aliases, defaults, nested models, enums, dates, UUIDs, and standard annotated containers use Pydantic's own validation and serialization behavior. Custom validators and serializers run in Python; Pynect does not attempt to reproduce them in TypeScript.
|
|
459
|
+
|
|
460
|
+
Pydantic cannot infer a validation target for an unannotated value, and some extension callables do not expose an inspectable signature. Those calls still pass through the dispatcher and its access policy, but their untyped values retain normal Python behavior.
|
|
461
|
+
|
|
462
|
+
## Current limits
|
|
463
|
+
|
|
464
|
+
- Normal proxy calls are in-process. A native Python crash can terminate Node or Bun; use `callIsolated()` where a process boundary is required.
|
|
465
|
+
- In-process execution timeouts and aborts are cooperative for async functions. Hard termination of synchronous code requires `callIsolated()`.
|
|
466
|
+
- Async Python uses one persistent asyncio loop. CPU-bound work still needs Python multiprocessing or native extensions that release the GIL.
|
|
467
|
+
- Local modules use safe AST inspection, but codegen for explicitly requested installed packages imports those packages and may run their import-time code.
|
|
468
|
+
- The isolated worker is not an operating-system sandbox and supports only JSON-compatible calls, not Python object proxies.
|
|
469
|
+
- GitHub Actions builds Python 3.12 native artifacts for Linux, macOS, and Windows on x64 and ARM64. Those artifacts are not yet attached to releases or downloaded during package installation.
|
|
470
|
+
|
|
471
|
+
See [SECURITY.md](./SECURITY.md) before exposing imports or call patterns to untrusted input.
|
|
472
|
+
|
|
473
|
+
## Development
|
|
474
|
+
|
|
475
|
+
```sh
|
|
476
|
+
bun install --frozen-lockfile
|
|
477
|
+
bun run verify
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
`verify` type-checks, rebuilds the addon, and runs the shared-interpreter smoke test. `scripts/docker-zero-python.sh` is the clean-container reproduction: it starts from the official Bun image, asserts that Node.js, Python, and uv are absent, installs the registry-published Pyfig dependency plus only the C++ toolchain, then verifies Pyfig bootstrap, lazy native compilation through Bun, and the full Pynect native boundary. The separate `Native binaries` workflow runs for native or Python-boundary changes and can also be started manually.
|
|
481
|
+
|
|
482
|
+
### Publishing
|
|
483
|
+
|
|
484
|
+
Local publishing uses the package-scoped npm token at `~/.secrets/npm/pynect-publish-token`. The file contains only the raw token and must never be copied into the repository, an npm command-line argument, or a log. The token is limited to `pynect`, has package read/write access, has no organization access, bypasses publish-time 2FA, and expires January 30, 2027.
|
|
485
|
+
|
|
486
|
+
Load the token only into the current PowerShell process, verify the npm identity, and publish from a clean `main` branch:
|
|
487
|
+
|
|
488
|
+
```powershell
|
|
489
|
+
$tokenPath = Join-Path $env:USERPROFILE '.secrets\npm\pynect-publish-token'
|
|
490
|
+
$env:NPM_TOKEN = (Get-Content -Raw -LiteralPath $tokenPath).Trim()
|
|
491
|
+
|
|
492
|
+
try {
|
|
493
|
+
npm whoami --registry=https://registry.npmjs.org/
|
|
494
|
+
npm publish
|
|
495
|
+
} finally {
|
|
496
|
+
Remove-Item Env:NPM_TOKEN -ErrorAction SilentlyContinue
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
npm plans to remove direct publishing with bypass-2FA granular tokens in January 2027. Replace this local flow with trusted publishing before that cutoff; until then, rotate the token at the same secret path without changing repository files.
|
|
501
|
+
|
|
502
|
+
## Project history
|
|
503
|
+
|
|
504
|
+
Pynect builds on [NodePyX](https://github.com/Brah-Timo/nodepyx) and retains its Git history and contributor attribution. Its public API, dispatcher policy, optional Pydantic integration, Python provisioning, codegen, and Windows build path have been revised for this project.
|
|
505
|
+
|
|
506
|
+
MIT licensed.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
Pynect embeds Python in the JavaScript process. Treat every imported module and callable as trusted code with the permissions of that process.
|
|
4
|
+
|
|
5
|
+
## Safe defaults
|
|
6
|
+
|
|
7
|
+
- Raw Python code execution and native-addon access require `allowUnsafeCode: true`.
|
|
8
|
+
- Package installation requires `allowPackageInstall: true`.
|
|
9
|
+
- Tracebacks are hidden unless `includeTracebacks: true`.
|
|
10
|
+
- Dispatcher include, exclude, type-hint, and export policies are enforced inside the native call path.
|
|
11
|
+
- Dependency manifests cannot select indexes, credentials, interpreters, or installation policy.
|
|
12
|
+
- Postinstall synchronization runs only when lifecycle scripts are enabled (and, with Bun, Pynect is trusted); set `PYNECT_SKIP_POSTINSTALL=1` or disable lifecycle scripts to require explicit synchronization.
|
|
13
|
+
- Normal runtime startup validates the checked lock and environment fingerprint without installing packages.
|
|
14
|
+
- Local codegen discovery uses AST parsing and does not execute application modules.
|
|
15
|
+
- Private module and callable names are rejected; explicit excludes always win.
|
|
16
|
+
- Python package specifications and module identifiers are validated before subprocess use.
|
|
17
|
+
- Pyfig pins uv, downloads only Astral's GitHub release archive, and verifies its SHA-256 checksum before extraction.
|
|
18
|
+
- Pynect project sync and native builds use loqkit's layered memory, worker-thread, and cross-process file locks; process-owned runtime and garbage-collection sections use its memory lock.
|
|
19
|
+
- Pyfig and uv retain ownership of their package and managed-tool synchronization.
|
|
20
|
+
- uv owns Python dependency resolution and exact environment synchronization through the generated non-package `pyproject.toml`; Pynect does not implement a parallel resolver.
|
|
21
|
+
|
|
22
|
+
## Deployment guidance
|
|
23
|
+
|
|
24
|
+
Use a narrow dispatcher include list, run under a low-privilege operating-system account, and keep `allowUnsafeCode` and `allowPackageInstall` disabled for applications that process untrusted input. Do not let request data select module names, attribute paths, package specifications, Python code, or filesystem paths.
|
|
25
|
+
|
|
26
|
+
Pydantic validates data shapes; it is not a sandbox. Validators and serializers are Python code and must be trusted.
|
|
27
|
+
|
|
28
|
+
`callIsolated()` protects the Node.js process from a worker crash and allows hard termination on timeout. It does not reduce filesystem, network, environment, or operating-system permissions. Run hostile code in a separately secured account, container, virtual machine, or platform sandbox.
|
|
29
|
+
|
|
30
|
+
Codegen for explicitly requested installed modules uses runtime inspection and imports the package. Only inspect third-party packages you trust.
|
|
31
|
+
|
|
32
|
+
## Reporting
|
|
33
|
+
|
|
34
|
+
Report vulnerabilities privately to the repository owner before opening a public issue. Include the affected commit, platform, Python version, JavaScript runtime and version, and a minimal reproduction without secrets.
|
package/binding.gyp
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"targets": [{
|
|
3
|
+
"target_name": "pynect_addon",
|
|
4
|
+
"sources": [
|
|
5
|
+
"src/native/pynect_addon.cpp",
|
|
6
|
+
"src/native/python_bridge.cpp",
|
|
7
|
+
"src/native/type_converter.cpp",
|
|
8
|
+
"src/native/thread_pool.cpp",
|
|
9
|
+
"src/native/gil_guard.cpp"
|
|
10
|
+
],
|
|
11
|
+
"include_dirs": [
|
|
12
|
+
"<!@(node -p \"require('node-addon-api').include\")",
|
|
13
|
+
"<!(node -p \"process.env.PYNECT_PYTHON_INCLUDE_DIR || (() => { throw new Error('PYNECT_PYTHON_INCLUDE_DIR is required') })()\")"
|
|
14
|
+
],
|
|
15
|
+
"cflags_cc": [
|
|
16
|
+
"-std=c++17",
|
|
17
|
+
"-O2",
|
|
18
|
+
"-Wall",
|
|
19
|
+
"-Wextra",
|
|
20
|
+
"-Wno-unused-parameter"
|
|
21
|
+
],
|
|
22
|
+
"cflags!": ["-fno-exceptions"],
|
|
23
|
+
"cflags_cc!": ["-fno-exceptions"],
|
|
24
|
+
"defines": [
|
|
25
|
+
"NAPI_CPP_EXCEPTIONS",
|
|
26
|
+
"NAPI_VERSION=8",
|
|
27
|
+
"PY_SSIZE_T_CLEAN"
|
|
28
|
+
],
|
|
29
|
+
"conditions": [
|
|
30
|
+
["OS=='linux'", {
|
|
31
|
+
"cflags_cc": ["-fvisibility=hidden"],
|
|
32
|
+
"libraries": [
|
|
33
|
+
"<!(node -p \"process.env.PYNECT_PYTHON_LIBRARY || (() => { throw new Error('PYNECT_PYTHON_LIBRARY is required') })()\")",
|
|
34
|
+
"-ldl"
|
|
35
|
+
],
|
|
36
|
+
"ldflags": [
|
|
37
|
+
"-Wl,-rpath,<!(node -p \"process.env.PYNECT_PYTHON_LIBRARY_DIR || (() => { throw new Error('PYNECT_PYTHON_LIBRARY_DIR is required') })()\")",
|
|
38
|
+
"-Wl,-rpath,'$$ORIGIN'",
|
|
39
|
+
"-static-libgcc",
|
|
40
|
+
"-static-libstdc++"
|
|
41
|
+
]
|
|
42
|
+
}],
|
|
43
|
+
["OS=='mac'", {
|
|
44
|
+
"libraries": [
|
|
45
|
+
"<!(node -p \"process.env.PYNECT_PYTHON_LIBRARY || (() => { throw new Error('PYNECT_PYTHON_LIBRARY is required') })()\")"
|
|
46
|
+
],
|
|
47
|
+
"xcode_settings": {
|
|
48
|
+
"MACOSX_DEPLOYMENT_TARGET": "11.0",
|
|
49
|
+
"OTHER_CFLAGS": ["-std=c++17", "-stdlib=libc++"],
|
|
50
|
+
"LD_RUNPATH_SEARCH_PATHS": ["@loader_path"],
|
|
51
|
+
"GCC_ENABLE_CPP_EXCEPTIONS": "YES"
|
|
52
|
+
}
|
|
53
|
+
}],
|
|
54
|
+
["OS=='win'", {
|
|
55
|
+
"libraries": [
|
|
56
|
+
"<!(node -p \"process.env.PYNECT_PYTHON_LIBRARY || (() => { throw new Error('PYNECT_PYTHON_LIBRARY is required') })()\")"
|
|
57
|
+
],
|
|
58
|
+
"msvs_settings": {
|
|
59
|
+
"VCCLCompilerTool": {
|
|
60
|
+
"ExceptionHandling": 1,
|
|
61
|
+
"AdditionalOptions": ["/std:c++17"]
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}]
|
|
65
|
+
]
|
|
66
|
+
}]
|
|
67
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/cli/codegen.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AA6G5C,wBAAgB,oBAAoB,CAAC,IAAI,SAAY,GAAG,OAAO,CAwB9D"}
|