aws-lambda-layer-cli 1.4.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 +21 -0
- package/README.md +393 -0
- package/bin/aws-lambda-layer.js +89 -0
- package/completion/aws-lambda-layer-completion.bash +101 -0
- package/completion/aws-lambda-layer-completion.zsh +110 -0
- package/package.json +31 -0
- package/scripts/aws-lambda-layer +821 -0
- package/scripts/build_pypi.sh +37 -0
- package/scripts/create_nodejs_layer.sh +459 -0
- package/scripts/create_python_layer.sh +465 -0
- package/scripts/install.js +34 -0
- package/scripts/install.ps1 +663 -0
- package/scripts/install.sh +107 -0
- package/scripts/pypi_resources/__init__.py +9 -0
- package/scripts/pypi_resources/cli.py +83 -0
- package/scripts/sync_version.js +24 -0
- package/scripts/uninstall.ps1 +180 -0
- package/scripts/uninstall.sh +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Yuk Chow
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
# AWS Lambda Layer CLI Tool
|
|
2
|
+
|
|
3
|
+
A command-line tool for creating and publishing AWS Lambda layers for Node.js and Python.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Create Layers**: Generate Lambda layer zip files for Node.js and Python
|
|
8
|
+
- **Publish to AWS**: Directly publish layers to AWS Lambda with IAM credentials
|
|
9
|
+
- **Version Management**: Support for package version specification
|
|
10
|
+
- **Security**: Input validation and sanitization
|
|
11
|
+
- **Smart Naming**: Automatic layer naming with package versions
|
|
12
|
+
- **Multiple Packages**: Support for multiple packages in a single layer
|
|
13
|
+
- **Runtime Versioning**: Specify Node.js or Python versions
|
|
14
|
+
- **Package Managers**: Support for npm (Node.js) and uv/pip (Python)
|
|
15
|
+
- **AWS Profile Support**: Use different AWS profiles for publishing
|
|
16
|
+
- **Region Specification**: Target specific AWS regions
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
### Package managers (recommended)
|
|
21
|
+
|
|
22
|
+
These installs do **not** write to `/usr/local` and do **not** require `sudo`.
|
|
23
|
+
|
|
24
|
+
#### npm (Node.js)
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm i -g aws-lambda-layer-cli
|
|
28
|
+
aws-lambda-layer --help
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
#### pip (Python)
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
python -m pip install --user aws-lambda-layer-cli
|
|
35
|
+
aws-lambda-layer --help
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### uv (Python)
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
uv tool install aws-lambda-layer-cli
|
|
42
|
+
aws-lambda-layer --help
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Linux/macOS
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Clone or download the repository
|
|
49
|
+
git clone <repository-url>
|
|
50
|
+
cd aws-lambda-layer-cli
|
|
51
|
+
|
|
52
|
+
# Run installation script (requires sudo)
|
|
53
|
+
sudo ./scripts/install.sh
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The installation will:
|
|
57
|
+
- Copy scripts to `/usr/local/lib/aws-lambda-layer`
|
|
58
|
+
- Create a symlink in `/usr/local/bin` for global access
|
|
59
|
+
- Install shell completions for bash and zsh
|
|
60
|
+
|
|
61
|
+
### Windows
|
|
62
|
+
|
|
63
|
+
#### Option 1: PowerShell (Recommended)
|
|
64
|
+
|
|
65
|
+
```powershell
|
|
66
|
+
# One-liner installation
|
|
67
|
+
powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/yukcw/aws-lambda-layer-cli/main/scripts/install.ps1 | iex"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Or download and run manually:
|
|
71
|
+
|
|
72
|
+
```powershell
|
|
73
|
+
# Download the installer
|
|
74
|
+
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/yukcw/aws-lambda-layer-cli/main/scripts/install.ps1" -OutFile "install.ps1"
|
|
75
|
+
|
|
76
|
+
# Run the installer (as Administrator)
|
|
77
|
+
.\install.ps1
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This will:
|
|
81
|
+
- Download the tool to `%USERPROFILE%\.aws-lambda-layer`
|
|
82
|
+
- Add it to your PATH
|
|
83
|
+
- Create Windows wrapper scripts
|
|
84
|
+
|
|
85
|
+
#### Option 2: Manual Installation
|
|
86
|
+
|
|
87
|
+
1. Install prerequisites:
|
|
88
|
+
- [Git for Windows](https://gitforwindows.org/) (includes Git Bash)
|
|
89
|
+
- [AWS CLI](https://aws.amazon.com/cli/) (for publish command)
|
|
90
|
+
|
|
91
|
+
2. Download the scripts from the [repository](https://github.com/yukcw/aws-lambda-layer-cli)
|
|
92
|
+
|
|
93
|
+
3. Extract to a directory and add to PATH
|
|
94
|
+
|
|
95
|
+
### Requirements
|
|
96
|
+
|
|
97
|
+
- **Linux/macOS**: Bash shell
|
|
98
|
+
- **Windows**: Windows Subsystem for Linux (WSL) (recommended), or Git Bash/Cygwin
|
|
99
|
+
- **AWS CLI**: Required for `publish` command
|
|
100
|
+
- **Node.js**: Required for Node.js layer creation
|
|
101
|
+
- **Python**: Required for Python layer creation (uv recommended)
|
|
102
|
+
- **zip**: Required for creating zip archives
|
|
103
|
+
|
|
104
|
+
**Note**: If using WSL, ensure that AWS CLI, Node.js, Python, and zip are installed within WSL for proper functionality.
|
|
105
|
+
|
|
106
|
+
## Uninstallation
|
|
107
|
+
|
|
108
|
+
### Package managers
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# npm
|
|
112
|
+
npm uninstall -g aws-lambda-layer-cli
|
|
113
|
+
|
|
114
|
+
# pip
|
|
115
|
+
python -m pip uninstall aws-lambda-layer-cli
|
|
116
|
+
|
|
117
|
+
# uv
|
|
118
|
+
uv tool uninstall aws-lambda-layer-cli
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Linux/macOS
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
sudo ./scripts/uninstall.sh
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Windows
|
|
128
|
+
|
|
129
|
+
#### Using PowerShell
|
|
130
|
+
|
|
131
|
+
```powershell
|
|
132
|
+
# Download and run the uninstaller
|
|
133
|
+
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/yukcw/aws-lambda-layer-cli/main/scripts/uninstall.ps1" -OutFile "uninstall.ps1"
|
|
134
|
+
.\uninstall.ps1
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Or run directly without downloading:
|
|
138
|
+
|
|
139
|
+
```powershell
|
|
140
|
+
powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/yukcw/aws-lambda-layer-cli/main/scripts/uninstall.ps1 | iex"
|
|
141
|
+
```
|
|
142
|
+
#### Troubleshooting Windows Installation
|
|
143
|
+
|
|
144
|
+
If you encounter issues:
|
|
145
|
+
|
|
146
|
+
1. **"bash: command not found"**
|
|
147
|
+
- Install [Git for Windows](https://gitforwindows.org/) or [WSL](https://docs.microsoft.com/en-us/windows/wsl/install)
|
|
148
|
+
- Restart PowerShell/Command Prompt after installation
|
|
149
|
+
|
|
150
|
+
2. **"No such file or directory"**
|
|
151
|
+
- Try running: `bash "$env:USERPROFILE\.aws-lambda-layer\aws-lambda-layer" --help`
|
|
152
|
+
- Or reinstall: `powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/yukcw/aws-lambda-layer-cli/main/scripts/install.ps1 | iex"`
|
|
153
|
+
|
|
154
|
+
3. **Permission issues**
|
|
155
|
+
- Run PowerShell as Administrator
|
|
156
|
+
- Or run: `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser`
|
|
157
|
+
## Usage
|
|
158
|
+
|
|
159
|
+
### Basic Syntax
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# Create a local zip file
|
|
163
|
+
aws-lambda-layer zip --nodejs <packages> [options]
|
|
164
|
+
aws-lambda-layer zip --python <packages> [options]
|
|
165
|
+
|
|
166
|
+
# Publish directly to AWS
|
|
167
|
+
aws-lambda-layer publish --nodejs <packages> [options]
|
|
168
|
+
aws-lambda-layer publish --python <packages> [options]
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Commands
|
|
172
|
+
|
|
173
|
+
- **zip**: Create and package a Lambda layer as zip file
|
|
174
|
+
- **publish**: Create and publish a Lambda layer to AWS (uses IAM credentials)
|
|
175
|
+
- **help**: Show help message
|
|
176
|
+
|
|
177
|
+
### Runtime Options
|
|
178
|
+
|
|
179
|
+
- `--nodejs`, `--node`, `-n`: Create a Node.js Lambda layer
|
|
180
|
+
- `--python`, `--py`, `-p`: Create a Python Lambda layer
|
|
181
|
+
- `--runtime=RUNTIME`: Specify runtime (nodejs or python)
|
|
182
|
+
|
|
183
|
+
### Common Options
|
|
184
|
+
|
|
185
|
+
- `--name`: Name for the output zip file / layer name
|
|
186
|
+
- `--description`: Description for the layer (publish command only)
|
|
187
|
+
- `-h`, `--help`: Show help message
|
|
188
|
+
|
|
189
|
+
### AWS Options (publish command only)
|
|
190
|
+
|
|
191
|
+
- `--profile`: AWS CLI profile to use (default: default profile)
|
|
192
|
+
- `--region`: AWS region (e.g., us-east-1, ap-east-1)
|
|
193
|
+
|
|
194
|
+
### Node.js Specific Options
|
|
195
|
+
|
|
196
|
+
- `--node-version`: Node.js version (default: 24)
|
|
197
|
+
|
|
198
|
+
### Python Specific Options
|
|
199
|
+
|
|
200
|
+
- `--python-version`: Python version (default: 3.14)
|
|
201
|
+
- `--no-uv`: Use pip/venv instead of uv
|
|
202
|
+
|
|
203
|
+
## Examples
|
|
204
|
+
|
|
205
|
+
### Node.js Examples
|
|
206
|
+
|
|
207
|
+
#### Create Local Zip Files
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Single package with version
|
|
211
|
+
aws-lambda-layer zip --nodejs express@4.18.2
|
|
212
|
+
|
|
213
|
+
# Multiple packages with versions
|
|
214
|
+
aws-lambda-layer zip --nodejs express@4.18.2,axios@1.6.2,lodash@4.17.21
|
|
215
|
+
|
|
216
|
+
# With custom name
|
|
217
|
+
aws-lambda-layer zip --nodejs axios,lodash --name utility-layer
|
|
218
|
+
|
|
219
|
+
# With specific Node.js version
|
|
220
|
+
aws-lambda-layer zip --nodejs express@4.18.2 --node-version 20
|
|
221
|
+
|
|
222
|
+
# Scoped packages
|
|
223
|
+
aws-lambda-layer zip --nodejs @babel/core@7.23.0,@babel/types@7.23.0
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### Publish to AWS
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
# Basic publish
|
|
230
|
+
aws-lambda-layer publish --nodejs express@4.18.2 --description "Express layer"
|
|
231
|
+
|
|
232
|
+
# With custom layer name
|
|
233
|
+
aws-lambda-layer publish --nodejs date-fns,uuid --name utility-layer --description "Utility packages"
|
|
234
|
+
|
|
235
|
+
# Using specific AWS profile
|
|
236
|
+
aws-lambda-layer publish --nodejs express@4.18.2 --profile production --description "Express layer"
|
|
237
|
+
|
|
238
|
+
# Specify AWS region
|
|
239
|
+
aws-lambda-layer publish --nodejs axios --region ap-east-1 --description "Axios layer"
|
|
240
|
+
|
|
241
|
+
# With both profile and region
|
|
242
|
+
aws-lambda-layer publish --nodejs lodash --profile dev --region us-east-1 --description "Lodash layer"
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Python Examples
|
|
246
|
+
|
|
247
|
+
#### Create Local Zip Files
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Single package with version
|
|
251
|
+
aws-lambda-layer zip --python numpy==1.26.0
|
|
252
|
+
|
|
253
|
+
# Multiple packages
|
|
254
|
+
aws-lambda-layer zip --python numpy==1.26.0,pandas==2.1.3,requests>=2.31.0
|
|
255
|
+
|
|
256
|
+
# With custom name
|
|
257
|
+
aws-lambda-layer zip --python requests,pytz --name web-utils
|
|
258
|
+
|
|
259
|
+
# With specific Python version
|
|
260
|
+
aws-lambda-layer zip --python numpy==1.26.0 --python-version 3.12
|
|
261
|
+
|
|
262
|
+
# Using pip instead of uv
|
|
263
|
+
aws-lambda-layer zip --python pandas==2.1.3 --no-uv
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
#### Publish to AWS
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
# Basic publish
|
|
270
|
+
aws-lambda-layer publish --python numpy==1.26.0 --description "NumPy layer"
|
|
271
|
+
|
|
272
|
+
# Multiple packages with description
|
|
273
|
+
aws-lambda-layer publish --python requests==2.31.0,pytz==2023.3 --description "Web utilities"
|
|
274
|
+
|
|
275
|
+
# Using specific AWS profile
|
|
276
|
+
aws-lambda-layer publish --python pandas==2.1.3 --profile production --description "Pandas layer"
|
|
277
|
+
|
|
278
|
+
# Specify AWS region
|
|
279
|
+
aws-lambda-layer publish --python numpy==1.26.0 --region us-west-2 --description "NumPy layer"
|
|
280
|
+
|
|
281
|
+
# With both profile and region
|
|
282
|
+
aws-lambda-layer publish --python scikit-learn --profile ml-account --region eu-west-1 --description "ML layer"
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Package Version Formats
|
|
286
|
+
|
|
287
|
+
### Node.js
|
|
288
|
+
- `express@4.18.2` - Exact version
|
|
289
|
+
- `axios` - Latest version
|
|
290
|
+
- `lodash@^4.17.0` - Compatible version
|
|
291
|
+
- `@babel/core@7.23.0,@babel/types@7.23.0` - Multiple scoped packages
|
|
292
|
+
|
|
293
|
+
### Python
|
|
294
|
+
- `numpy==1.26.0` - Exact version
|
|
295
|
+
- `pandas` - Latest version
|
|
296
|
+
- `requests>=2.31.0` - Minimum version
|
|
297
|
+
- `pytz~=2023.3` - Compatible version
|
|
298
|
+
|
|
299
|
+
## Publishing to AWS
|
|
300
|
+
|
|
301
|
+
### Requirements
|
|
302
|
+
|
|
303
|
+
Before using the `publish` command, ensure you have:
|
|
304
|
+
|
|
305
|
+
1. **AWS CLI installed and configured**
|
|
306
|
+
```bash
|
|
307
|
+
aws configure
|
|
308
|
+
# or for specific profile
|
|
309
|
+
aws configure --profile production
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
2. **IAM Permissions**: Your IAM user/role needs:
|
|
313
|
+
- `lambda:PublishLayerVersion`
|
|
314
|
+
- `sts:GetCallerIdentity` (for account verification)
|
|
315
|
+
- `iam:ListAccountAliases` (optional, for account info)
|
|
316
|
+
|
|
317
|
+
3. **Region Configuration**: Either:
|
|
318
|
+
- Set default region: `aws configure set region us-east-1`
|
|
319
|
+
- Or use `--region` flag when publishing
|
|
320
|
+
|
|
321
|
+
4. **zip command installed**: Ensure the `zip` command is available on your system.
|
|
322
|
+
|
|
323
|
+
### Confirmation Prompt
|
|
324
|
+
|
|
325
|
+
When publishing, you'll see:
|
|
326
|
+
1. AWS Account ID
|
|
327
|
+
2. AWS Profile (if specified)
|
|
328
|
+
3. Account Aliases (if available)
|
|
329
|
+
4. Target Region
|
|
330
|
+
5. Confirmation prompt: `Do you want to proceed? [Y/n]:`
|
|
331
|
+
|
|
332
|
+
Press Y (or Enter for default Yes) to proceed, or N to cancel.
|
|
333
|
+
|
|
334
|
+
## Output
|
|
335
|
+
|
|
336
|
+
### Zip Command
|
|
337
|
+
Creates a zip file in the current directory with format:
|
|
338
|
+
- Node.js: `<package-name>-<version>-nodejs<node-version>.zip`
|
|
339
|
+
- Python: `<package-name>-<version>-python<python-version>.zip`
|
|
340
|
+
|
|
341
|
+
### Publish Command
|
|
342
|
+
- Uploads layer to AWS Lambda
|
|
343
|
+
- Returns Layer ARN
|
|
344
|
+
- Shows usage examples
|
|
345
|
+
- Provides command to attach to existing Lambda functions
|
|
346
|
+
|
|
347
|
+
## Troubleshooting
|
|
348
|
+
|
|
349
|
+
### Common Issues
|
|
350
|
+
|
|
351
|
+
1. **AWS credentials not configured**
|
|
352
|
+
```bash
|
|
353
|
+
aws configure
|
|
354
|
+
# or
|
|
355
|
+
aws configure --profile your-profile
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
2. **IAM permissions missing**
|
|
359
|
+
- Ensure your AWS credentials has `lambda:PublishLayerVersion` permission
|
|
360
|
+
|
|
361
|
+
3. **Layer name already exists**
|
|
362
|
+
- Use `--name` option to specify a different name
|
|
363
|
+
- Or delete the existing layer version
|
|
364
|
+
|
|
365
|
+
4. **Zip file too large**
|
|
366
|
+
- AWS limit: 50MB for direct upload
|
|
367
|
+
- Consider using fewer packages or S3 upload for larger layers
|
|
368
|
+
|
|
369
|
+
5. **Region not configured**
|
|
370
|
+
- Use `--region` flag or configure default region:
|
|
371
|
+
```bash
|
|
372
|
+
aws configure set region us-east-1
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## Shell Completion
|
|
376
|
+
|
|
377
|
+
Completions are installed for bash and zsh. Restart your shell or source the completion files:
|
|
378
|
+
|
|
379
|
+
```bash
|
|
380
|
+
# Bash
|
|
381
|
+
source /etc/bash_completion.d/aws-lambda-layer-completion.bash
|
|
382
|
+
|
|
383
|
+
# Zsh
|
|
384
|
+
source /usr/local/share/zsh/site-functions/_aws-lambda-layer
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
## License
|
|
388
|
+
|
|
389
|
+
MIT License
|
|
390
|
+
|
|
391
|
+
## Contributing
|
|
392
|
+
|
|
393
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const { spawnSync } = require('child_process');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
function which(cmd) {
|
|
10
|
+
const isWin = process.platform === 'win32';
|
|
11
|
+
const exts = isWin ? (process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM').split(';') : [''];
|
|
12
|
+
const paths = (process.env.PATH || '').split(path.delimiter);
|
|
13
|
+
|
|
14
|
+
for (const p of paths) {
|
|
15
|
+
if (!p) continue;
|
|
16
|
+
for (const ext of exts) {
|
|
17
|
+
const full = path.join(p, isWin ? cmd + ext.toLowerCase() : cmd);
|
|
18
|
+
if (fs.existsSync(full)) return full;
|
|
19
|
+
// Also check original case on Windows
|
|
20
|
+
const full2 = path.join(p, cmd + ext);
|
|
21
|
+
if (fs.existsSync(full2)) return full2;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function shQuote(s) {
|
|
28
|
+
// Single-quote for bash -lc
|
|
29
|
+
return `'${String(s).replace(/'/g, `'\\''`)}'`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function windowsPathToWsl(p) {
|
|
33
|
+
// C:\Users\me\x -> /mnt/c/Users/me/x
|
|
34
|
+
const m = /^([a-zA-Z]):\\(.*)$/.exec(p);
|
|
35
|
+
if (!m) return null;
|
|
36
|
+
return `/mnt/${m[1].toLowerCase()}/${m[2].replace(/\\/g, '/')}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function cygpathConvert(mode, p) {
|
|
40
|
+
const cygpath = which('cygpath');
|
|
41
|
+
if (!cygpath) return null;
|
|
42
|
+
const res = spawnSync(cygpath, [mode, p], { encoding: 'utf8' });
|
|
43
|
+
if (res.status !== 0) return null;
|
|
44
|
+
return (res.stdout || '').trim();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function run(cmd, args) {
|
|
48
|
+
const res = spawnSync(cmd, args, { stdio: 'inherit' });
|
|
49
|
+
process.exit(res.status ?? 1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const args = process.argv.slice(2);
|
|
53
|
+
const bashScript = path.resolve(__dirname, '..', 'scripts', 'aws-lambda-layer');
|
|
54
|
+
|
|
55
|
+
if (!fs.existsSync(bashScript)) {
|
|
56
|
+
console.error('Error: packaged bash script not found:', bashScript);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// POSIX platforms
|
|
61
|
+
if (process.platform !== 'win32') {
|
|
62
|
+
run('bash', [bashScript, ...args]);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Windows platforms:
|
|
66
|
+
// - Prefer Git Bash / MSYS / Cygwin: convert to POSIX path using cygpath -u
|
|
67
|
+
// - Else attempt WSL: convert to /mnt/<drive>/... and run via wsl.exe
|
|
68
|
+
// - Else give a clear message
|
|
69
|
+
|
|
70
|
+
const posixPath = cygpathConvert('-u', bashScript);
|
|
71
|
+
if (posixPath) {
|
|
72
|
+
run('bash', [posixPath, ...args]);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const wsl = which('wsl.exe') || which('wsl');
|
|
76
|
+
if (wsl) {
|
|
77
|
+
const wslPath = windowsPathToWsl(bashScript);
|
|
78
|
+
if (!wslPath) {
|
|
79
|
+
console.error('Error: unable to convert path for WSL:', bashScript);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const cmd = `bash ${shQuote(wslPath)} ${args.map(shQuote).join(' ')}`.trim();
|
|
84
|
+
run(wsl, ['bash', '-lc', cmd]);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.error('Error: no compatible bash found on Windows.');
|
|
88
|
+
console.error('Install and run this tool inside WSL, or install Git Bash and ensure `bash`/`cygpath` are on PATH.');
|
|
89
|
+
process.exit(1);
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# bash completion for aws-lambda-layer
|
|
2
|
+
|
|
3
|
+
_aws_lambda_layer() {
|
|
4
|
+
local cur prev words cword
|
|
5
|
+
_init_completion || return
|
|
6
|
+
|
|
7
|
+
local commands="zip publish help --help --version"
|
|
8
|
+
local runtime_opts="--nodejs --node -n --python --py -p --runtime"
|
|
9
|
+
local common_opts="--name -h --help"
|
|
10
|
+
local publish_opts="--description --layer-name --profile --region"
|
|
11
|
+
local node_opts="--node-version"
|
|
12
|
+
local python_opts="--python-version --no-uv"
|
|
13
|
+
|
|
14
|
+
case ${cword} in
|
|
15
|
+
1)
|
|
16
|
+
# First argument: main command
|
|
17
|
+
COMPREPLY=($(compgen -W "${commands}" -- "${cur}"))
|
|
18
|
+
;;
|
|
19
|
+
2)
|
|
20
|
+
if [[ ${words[1]} == "zip" ]] || [[ ${words[1]} == "publish" ]]; then
|
|
21
|
+
# Second argument for zip/publish: runtime
|
|
22
|
+
COMPREPLY=($(compgen -W "${runtime_opts}" -- "${cur}"))
|
|
23
|
+
fi
|
|
24
|
+
;;
|
|
25
|
+
3)
|
|
26
|
+
# Third argument: packages (positional)
|
|
27
|
+
if [[ ${words[1]} == "zip" ]] || [[ ${words[1]} == "publish" ]]; then
|
|
28
|
+
# Suggest package format based on runtime
|
|
29
|
+
local has_runtime=""
|
|
30
|
+
for word in "${words[@]:2}"; do
|
|
31
|
+
case ${word} in
|
|
32
|
+
--nodejs|--node|-n|--runtime=nodejs)
|
|
33
|
+
COMPREPLY=("express@4.18.2,lodash")
|
|
34
|
+
return
|
|
35
|
+
;;
|
|
36
|
+
--python|--py|-p|--runtime=python)
|
|
37
|
+
COMPREPLY=("numpy==1.26.0,pandas")
|
|
38
|
+
return
|
|
39
|
+
;;
|
|
40
|
+
esac
|
|
41
|
+
done
|
|
42
|
+
fi
|
|
43
|
+
;;
|
|
44
|
+
*)
|
|
45
|
+
if [[ ${words[1]} == "zip" ]] || [[ ${words[1]} == "publish" ]]; then
|
|
46
|
+
# Determine runtime
|
|
47
|
+
local runtime=""
|
|
48
|
+
for word in "${words[@]:2}"; do
|
|
49
|
+
case ${word} in
|
|
50
|
+
--nodejs|--node|-n)
|
|
51
|
+
runtime="nodejs"
|
|
52
|
+
break
|
|
53
|
+
;;
|
|
54
|
+
--python|--py|-p)
|
|
55
|
+
runtime="python"
|
|
56
|
+
break
|
|
57
|
+
;;
|
|
58
|
+
--runtime=nodejs)
|
|
59
|
+
runtime="nodejs"
|
|
60
|
+
break
|
|
61
|
+
;;
|
|
62
|
+
--runtime=python)
|
|
63
|
+
runtime="python"
|
|
64
|
+
break
|
|
65
|
+
;;
|
|
66
|
+
--runtime)
|
|
67
|
+
# Check next word for runtime value
|
|
68
|
+
local next_word="${words[cword]}"
|
|
69
|
+
if [[ ${next_word} == "nodejs" || ${next_word} == "python" ]]; then
|
|
70
|
+
runtime="${next_word}"
|
|
71
|
+
fi
|
|
72
|
+
break
|
|
73
|
+
;;
|
|
74
|
+
esac
|
|
75
|
+
done
|
|
76
|
+
|
|
77
|
+
if [[ -z ${runtime} ]]; then
|
|
78
|
+
# Still need to choose runtime
|
|
79
|
+
COMPREPLY=($(compgen -W "${runtime_opts}" -- "${cur}"))
|
|
80
|
+
else
|
|
81
|
+
# Runtime chosen, now show appropriate options
|
|
82
|
+
local cmd_opts="${common_opts}"
|
|
83
|
+
if [[ ${words[1]} == "publish" ]]; then
|
|
84
|
+
cmd_opts="${cmd_opts} ${publish_opts}"
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
case ${runtime} in
|
|
88
|
+
nodejs)
|
|
89
|
+
COMPREPLY=($(compgen -W "${cmd_opts} ${node_opts}" -- "${cur}"))
|
|
90
|
+
;;
|
|
91
|
+
python)
|
|
92
|
+
COMPREPLY=($(compgen -W "${cmd_opts} ${python_opts}" -- "${cur}"))
|
|
93
|
+
;;
|
|
94
|
+
esac
|
|
95
|
+
fi
|
|
96
|
+
fi
|
|
97
|
+
;;
|
|
98
|
+
esac
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
complete -F _aws_lambda_layer aws-lambda-layer
|