0
# Package Management
1
2
npm package installation with automatic dependency resolution, enabling JavaScript module usage within Python applications through the persistent interpreter's require() system.
3
4
## Capabilities
5
6
### JavaScript Package Installation
7
8
Downloads and installs JavaScript packages from npmjs.org with automatic dependency resolution. Packages are installed in a CommonJS-compatible directory structure that can be used with the JSInterpreter's require() system.
9
10
```python { .api }
11
def install_jspackage(package_name, version, modulesdir):
12
"""
13
Installs a JavaScript package downloaded from npmjs.org.
14
15
Parameters:
16
- package_name: str - Name of the npm package to install
17
- version: str or None - Version specifier (semver compatible) or None for latest
18
- modulesdir: str - Directory where to install JavaScript packages
19
20
Returns:
21
None - Prints installation progress to stdout
22
23
Raises:
24
JSPackageInstallError: When package installation fails
25
- Error code 2: Version not found
26
- Error code 3: Unable to detect download URL
27
28
Note: Currently unable to resolve conflicting dependencies
29
"""
30
```
31
32
Usage example:
33
34
```python
35
import dukpy
36
37
# Install latest version of a package
38
dukpy.install_jspackage('lodash', None, './js_modules')
39
40
# Install specific version
41
dukpy.install_jspackage('react', '16.14.0', './node_modules')
42
43
# Install package with complex name
44
dukpy.install_jspackage('@babel/core', '7.12.0', './js_modules')
45
46
# Use installed packages
47
interpreter = dukpy.JSInterpreter()
48
interpreter.loader.register_path('./js_modules')
49
50
result = interpreter.evaljs("""
51
var _ = require('lodash');
52
_.chunk(['a', 'b', 'c', 'd'], 2)
53
""")
54
print(result) # [['a', 'b'], ['c', 'd']]
55
```
56
57
### Command Line Installation
58
59
The `dukpy-install` command provides shell access to package installation functionality with the same capabilities as the Python API.
60
61
```python { .api }
62
def main():
63
"""
64
CLI entry point for dukpy-install command.
65
66
Usage: dukpy-install [-d DESTINATION] package_name [version]
67
68
Arguments:
69
- package_name: Name of the npm package to install
70
- version: Optional version specifier
71
- --destination, -d: Installation directory (default: ./js_modules)
72
73
Returns:
74
int - Exit code (0 for success, error code for failures)
75
"""
76
```
77
78
Command line usage:
79
80
```bash
81
# Install latest version
82
dukpy-install lodash
83
84
# Install specific version
85
dukpy-install react 16.14.0
86
87
# Install to custom directory
88
dukpy-install -d ./my_modules moment
89
90
# Install scoped package
91
dukpy-install @angular/core 12.0.0
92
```
93
94
### Dependency Resolution
95
96
The package installer automatically resolves and installs all required dependencies using npm's dependency information. Dependencies are flattened into the target directory structure.
97
98
```python
99
# Example of automatic dependency resolution
100
dukpy.install_jspackage('express', '4.17.1', './js_modules')
101
102
# This will install:
103
# - express@4.17.1
104
# - accepts@1.3.7
105
# - array-flatten@1.1.1
106
# - body-parser@1.19.0
107
# - cookie@0.4.0
108
# - cookie-signature@1.0.6
109
# - debug@2.6.9
110
# - depd@1.1.2
111
# ... and many more dependencies
112
```
113
114
### Version Resolution
115
116
Supports semantic versioning (semver) for flexible version specification using the semver JavaScript library for version matching.
117
118
```python
119
import dukpy
120
121
# Latest version
122
dukpy.install_jspackage('moment', None, './js_modules')
123
124
# Exact version
125
dukpy.install_jspackage('moment', '2.29.1', './js_modules')
126
127
# Version range
128
dukpy.install_jspackage('moment', '^2.29.0', './js_modules') # 2.29.x
129
dukpy.install_jspackage('moment', '~2.29.1', './js_modules') # 2.29.1 - 2.29.x
130
dukpy.install_jspackage('moment', '>=2.28.0', './js_modules') # 2.28.0 or higher
131
```
132
133
### Integration with Module Loading
134
135
Installed packages integrate seamlessly with the JSInterpreter's module loading system. Register the installation directory as a module search path to enable require() access.
136
137
```python
138
import dukpy
139
140
# Install packages
141
dukpy.install_jspackage('lodash', None, './js_modules')
142
dukpy.install_jspackage('moment', None, './js_modules')
143
144
# Create interpreter and register module path
145
interpreter = dukpy.JSInterpreter()
146
interpreter.loader.register_path('./js_modules')
147
148
# Use packages in JavaScript
149
result = interpreter.evaljs("""
150
var _ = require('lodash');
151
var moment = require('moment');
152
153
var data = [
154
{ name: 'Alice', date: '2023-01-15' },
155
{ name: 'Bob', date: '2023-02-20' },
156
{ name: 'Charlie', date: '2023-01-10' }
157
];
158
159
var sorted = _.sortBy(data, function(item) {
160
return moment(item.date).unix();
161
});
162
163
_.map(sorted, 'name')
164
""")
165
166
print(result) # ['Charlie', 'Alice', 'Bob']
167
```
168
169
## Error Handling
170
171
```python { .api }
172
class JSPackageInstallError(Exception):
173
"""
174
Exception raised when package installation fails.
175
176
Provides specific error codes for different failure types:
177
- Code 2: Version not found
178
- Code 3: Unable to detect download URL
179
"""
180
181
def __init__(self, msg, error_code):
182
"""
183
Initialize with error message and code.
184
185
Parameters:
186
- msg: str - Error description
187
- error_code: int - Specific error code
188
"""
189
super().__init__(msg)
190
self.error_code = error_code
191
```
192
193
Error handling example:
194
195
```python
196
import dukpy
197
198
try:
199
# Attempt to install non-existent version
200
dukpy.install_jspackage('lodash', '999.999.999', './js_modules')
201
except dukpy.JSPackageInstallError as e:
202
print(f"Installation failed: {e}")
203
print(f"Error code: {e.error_code}")
204
205
try:
206
# Attempt to install non-existent package
207
dukpy.install_jspackage('this-package-does-not-exist', None, './js_modules')
208
except dukpy.JSPackageInstallError as e:
209
print(f"Installation failed: {e}")
210
print(f"Error code: {e.error_code}")
211
```
212
213
## Installation Output
214
215
Package installation provides detailed progress information:
216
217
```python
218
dukpy.install_jspackage('react', '16.14.0', './js_modules')
219
220
# Output:
221
# Packages going to be installed: react->16.14.0, loose-envify->1.4.0, js-tokens->4.0.0, object-assign->4.1.1
222
# Fetching https://registry.npmjs.org/react/-/react-16.14.0.tgz............................
223
# Fetching https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz............
224
# Fetching https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz............
225
# Fetching https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz............
226
# Installing react in ./js_modules Done!
227
```
228
229
## Limitations
230
231
- **Dependency Conflicts**: Currently unable to resolve conflicting dependencies between packages
232
- **Binary Dependencies**: Cannot install packages with native binary dependencies
233
- **Platform Compatibility**: Some packages may have platform-specific requirements not handled by the installer
234
- **Version Locking**: No package-lock.json equivalent for reproducible installations