@yaonyan/jsr2npm 0.1.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 +342 -0
- package/bin/jsr2npm.mjs +9941 -0
- package/package.json +25 -0
- package/types/cli.d.ts +2 -0
- package/types/cli.d.ts.map +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 yao
|
|
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,342 @@
|
|
|
1
|
+
# JSR to NPM Converter
|
|
2
|
+
|
|
3
|
+
> **Bridge the gap**: Publish JSR packages to NPM with zero hassle
|
|
4
|
+
|
|
5
|
+
We can publish JSR packages with npm deps, but not vice versa, so **jsr2npm**
|
|
6
|
+
fills the gap by converting JSR packages to NPM-compatible format.
|
|
7
|
+
|
|
8
|
+
## ✨ Key Features
|
|
9
|
+
|
|
10
|
+
- 🎯 **Zero Configuration** - Works out of the box, just specify package name
|
|
11
|
+
and version
|
|
12
|
+
- 📦 **Preserves JSR Exports** - Keeps your original module structure intact
|
|
13
|
+
- 🔧 **CLI Tools Support** - Add executable commands with simple `bin`
|
|
14
|
+
configuration
|
|
15
|
+
- 🚀 **Smart Bundling** - Bundles JSR/Deno code while keeping NPM deps external
|
|
16
|
+
- 📝 **Type Definitions** - Automatically copies TypeScript declarations
|
|
17
|
+
- 🔄 **CI/CD Ready** - Easy GitHub Actions integration for automated publishing
|
|
18
|
+
- 💎 **Clean & Simple** - Minimal config, maximum clarity
|
|
19
|
+
|
|
20
|
+
## Why jsr2npm?
|
|
21
|
+
|
|
22
|
+
JSR is great for publishing TypeScript/Deno packages, but the NPM ecosystem is
|
|
23
|
+
still huge.
|
|
24
|
+
|
|
25
|
+
Many developers want to:
|
|
26
|
+
|
|
27
|
+
- Publish CLI tools that work with `npx`
|
|
28
|
+
- Make their JSR packages available on NPM
|
|
29
|
+
- Support both ecosystems without maintaining duplicate code
|
|
30
|
+
- Write pure TypeScript with Deno, publish to NPM
|
|
31
|
+
|
|
32
|
+
**jsr2npm** automates this entire process while preserving your package
|
|
33
|
+
structure and metadata.
|
|
34
|
+
|
|
35
|
+
## How to Use
|
|
36
|
+
|
|
37
|
+
1. **Create a `jsr2npm.config.json` file:**
|
|
38
|
+
|
|
39
|
+
### Basic Package (Uses JSR exports as-is)
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"packages": [
|
|
43
|
+
{
|
|
44
|
+
"name": "@scope/package",
|
|
45
|
+
"version": "latest",
|
|
46
|
+
"packageJson": {
|
|
47
|
+
"name": "@myorg/package",
|
|
48
|
+
"description": "Package description"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### CLI Tool (Adds bin command)
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"packages": [
|
|
59
|
+
{
|
|
60
|
+
"name": "@scope/cli-tool",
|
|
61
|
+
"version": "latest",
|
|
62
|
+
"bin": {
|
|
63
|
+
"your-command": "src/bin.ts"
|
|
64
|
+
},
|
|
65
|
+
"packageJson": {
|
|
66
|
+
"name": "@myorg/cli-tool",
|
|
67
|
+
"description": "Your CLI tool description"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Configuration:**
|
|
75
|
+
- `name` (required): JSR package name
|
|
76
|
+
- `version` (required): JSR package version
|
|
77
|
+
- `bin` (optional): CLI commands to add
|
|
78
|
+
- Key: command name (e.g., "mycli")
|
|
79
|
+
- Value: source file path (e.g., "src/bin.ts")
|
|
80
|
+
- Bundles to `bin/{command}.mjs` automatically
|
|
81
|
+
- **JSR exports are preserved completely**
|
|
82
|
+
- `packageJson` (optional): Override package.json fields
|
|
83
|
+
|
|
84
|
+
**Available `packageJson` overrides:**
|
|
85
|
+
- `name`: NPM package name (recommended, e.g., "@myorg/cli-tool")
|
|
86
|
+
- `version`: Override the package version
|
|
87
|
+
- `description`: Override package description
|
|
88
|
+
- `author`: Override author (string or object with name/email/url)
|
|
89
|
+
- `license`: Override license
|
|
90
|
+
- `homepage`: Override homepage URL
|
|
91
|
+
- `repository`: Override repository (string or object with type/url)
|
|
92
|
+
- `keywords`: Override keywords array
|
|
93
|
+
- `scripts`: Merge additional scripts
|
|
94
|
+
|
|
95
|
+
2. **Run the script:**
|
|
96
|
+
```bash
|
|
97
|
+
deno run --allow-all cli.ts
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Or use the remote version:
|
|
101
|
+
```bash
|
|
102
|
+
deno run --allow-all https://raw.githubusercontent.com/yaonyan/jsr2npm/main/cli.ts
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## How It Works
|
|
106
|
+
|
|
107
|
+
```mermaid
|
|
108
|
+
graph TD
|
|
109
|
+
A[Read jsr2npm.config.json] --> B[Create Workspace Folder]
|
|
110
|
+
B --> C[Download JSR Package<br/>npm install @jsr/...]
|
|
111
|
+
C --> D[Bundle Code with esbuild]
|
|
112
|
+
D --> E[Analyze Dependencies]
|
|
113
|
+
E --> F{Dependency Type?}
|
|
114
|
+
F -->|JSR/Deno Code| G[Include in Bundle]
|
|
115
|
+
F -->|NPM Package| H[Mark as External]
|
|
116
|
+
F -->|Node.js Built-in| H
|
|
117
|
+
G --> I[Generate package.json]
|
|
118
|
+
H --> I
|
|
119
|
+
I --> J[Set External NPM Deps<br/>with Correct Versions]
|
|
120
|
+
J --> K[Preserve JSR Exports]
|
|
121
|
+
K --> L[Copy Types & Files]
|
|
122
|
+
L --> M[dist/ Ready to Publish]
|
|
123
|
+
|
|
124
|
+
style E fill:#ff9,stroke:#333,stroke-width:2px
|
|
125
|
+
style F fill:#f9f,stroke:#333,stroke-width:3px
|
|
126
|
+
style J fill:#9ff,stroke:#333,stroke-width:2px
|
|
127
|
+
style M fill:#9f9,stroke:#333,stroke-width:2px
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The script automates these steps:
|
|
131
|
+
|
|
132
|
+
1. **Create Workspace** - Creates `__scope__package_version/` folder for
|
|
133
|
+
organization
|
|
134
|
+
2. **Download JSR Package** - Uses `npm install` to fetch the package from JSR
|
|
135
|
+
registry
|
|
136
|
+
3. **Bundle with esbuild** - Processes the code and intelligently handles
|
|
137
|
+
dependencies
|
|
138
|
+
4. **Analyze Dependencies** - **Core feature**: Separates different types of
|
|
139
|
+
dependencies:
|
|
140
|
+
- **JSR/Deno code**: Bundled into the output
|
|
141
|
+
- **NPM packages**: Marked as external dependencies
|
|
142
|
+
- **Node.js built-ins**: Marked as external
|
|
143
|
+
5. **Generate package.json** - Creates NPM metadata with:
|
|
144
|
+
- **External NPM dependencies with correct versions** (automatically
|
|
145
|
+
detected)
|
|
146
|
+
- Preserved JSR `exports` field
|
|
147
|
+
- Type definitions paths
|
|
148
|
+
- `bin` field for CLI commands (if configured)
|
|
149
|
+
6. **Copy Files** - Includes TypeScript declarations, README, and LICENSE
|
|
150
|
+
7. **Output** - Ready-to-publish NPM package in `dist/` folder
|
|
151
|
+
|
|
152
|
+
## Requirements
|
|
153
|
+
|
|
154
|
+
- [Deno](https://deno.land/)
|
|
155
|
+
- [Node.js](https://nodejs.org/) (which includes `npx`)
|
|
156
|
+
|
|
157
|
+
## Usage
|
|
158
|
+
|
|
159
|
+
### Local Development
|
|
160
|
+
|
|
161
|
+
Run the conversion locally:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
deno run -A cli.ts
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Or use the remote version:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
deno run -A https://raw.githubusercontent.com/yaonyan/jsr2npm/main/cli.ts
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The converted packages will be in `__<scope>__<package>_<version>/dist/`
|
|
174
|
+
directories.
|
|
175
|
+
|
|
176
|
+
### Publishing to npm
|
|
177
|
+
|
|
178
|
+
After conversion, you can publish manually:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# For a single package
|
|
182
|
+
cd __scope__package_version/dist
|
|
183
|
+
npm publish --access public
|
|
184
|
+
|
|
185
|
+
# For multiple packages (skip if already published)
|
|
186
|
+
for dir in __*_*/dist; do
|
|
187
|
+
cd "$dir"
|
|
188
|
+
NAME=$(node -p "require('./package.json').name")
|
|
189
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
190
|
+
|
|
191
|
+
if npm view "$NAME@$VERSION" version 2>/dev/null; then
|
|
192
|
+
echo "Skipping $NAME@$VERSION (already published)"
|
|
193
|
+
else
|
|
194
|
+
npm publish --access public
|
|
195
|
+
fi
|
|
196
|
+
cd ../..
|
|
197
|
+
done
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
````
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Setting up Automated CI/CD (For Package Maintainers)
|
|
204
|
+
|
|
205
|
+
If you maintain a JSR package with CLI tools and want to automatically publish npm versions, follow these steps:
|
|
206
|
+
|
|
207
|
+
### Step 1: Add jsr2npm Config to Your Repository
|
|
208
|
+
|
|
209
|
+
Create `jsr2npm.config.json` in your JSR package repository root:
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"packages": [
|
|
214
|
+
{
|
|
215
|
+
"name": "@your-scope/your-package",
|
|
216
|
+
"version": "0.1.0",
|
|
217
|
+
"bin": {
|
|
218
|
+
"your-command": "src/cli.ts"
|
|
219
|
+
},
|
|
220
|
+
"packageJson": {
|
|
221
|
+
"name": "@npm-org/package-name",
|
|
222
|
+
"description": "Your package description"
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
]
|
|
226
|
+
}
|
|
227
|
+
````
|
|
228
|
+
|
|
229
|
+
### Step 2: Create GitHub Workflow
|
|
230
|
+
|
|
231
|
+
Create `.github/workflows/publish-npm.yml`:
|
|
232
|
+
|
|
233
|
+
```yaml
|
|
234
|
+
name: Publish CLI to NPM
|
|
235
|
+
|
|
236
|
+
on:
|
|
237
|
+
workflow_dispatch:
|
|
238
|
+
push:
|
|
239
|
+
tags:
|
|
240
|
+
- "v*"
|
|
241
|
+
|
|
242
|
+
jobs:
|
|
243
|
+
convert-and-publish:
|
|
244
|
+
runs-on: ubuntu-latest
|
|
245
|
+
|
|
246
|
+
permissions:
|
|
247
|
+
contents: write
|
|
248
|
+
id-token: write
|
|
249
|
+
|
|
250
|
+
steps:
|
|
251
|
+
- name: Checkout repository
|
|
252
|
+
uses: actions/checkout@v4
|
|
253
|
+
|
|
254
|
+
- name: Setup Deno
|
|
255
|
+
uses: denoland/setup-deno@v2
|
|
256
|
+
with:
|
|
257
|
+
deno-version: v2.x
|
|
258
|
+
|
|
259
|
+
- name: Setup Node.js
|
|
260
|
+
uses: actions/setup-node@v4
|
|
261
|
+
with:
|
|
262
|
+
node-version: "20"
|
|
263
|
+
registry-url: "https://registry.npmjs.org"
|
|
264
|
+
|
|
265
|
+
- name: Run JSR to NPM conversion
|
|
266
|
+
run: deno run -A https://raw.githubusercontent.com/yaonyan/jsr2npm/main/cli.ts
|
|
267
|
+
|
|
268
|
+
- name: Publish to npm
|
|
269
|
+
run: |
|
|
270
|
+
for dir in __*_*/dist; do
|
|
271
|
+
cd "$dir"
|
|
272
|
+
NAME=$(node -p "require('./package.json').name")
|
|
273
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
274
|
+
|
|
275
|
+
if npm view "$NAME@$VERSION" version 2>/dev/null; then
|
|
276
|
+
echo "Skipping $NAME@$VERSION (already published)"
|
|
277
|
+
else
|
|
278
|
+
npm publish --access public --provenance
|
|
279
|
+
fi
|
|
280
|
+
cd ../..
|
|
281
|
+
done
|
|
282
|
+
env:
|
|
283
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
284
|
+
|
|
285
|
+
- name: Upload artifacts
|
|
286
|
+
uses: actions/upload-artifact@v4
|
|
287
|
+
with:
|
|
288
|
+
name: npm-package
|
|
289
|
+
path: __*_*/dist/
|
|
290
|
+
retention-days: 7
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Step 3: Add NPM Token
|
|
294
|
+
|
|
295
|
+
1. Go to [npmjs.com](https://www.npmjs.com/) → Account Settings → Access Tokens
|
|
296
|
+
2. Create a new **Automation** token
|
|
297
|
+
3. Add to your GitHub repository: Settings → Secrets → Actions → New repository
|
|
298
|
+
secret
|
|
299
|
+
- Name: `NPM_TOKEN`
|
|
300
|
+
- Value: Your npm token
|
|
301
|
+
|
|
302
|
+
### Step 4: Trigger Publishing
|
|
303
|
+
|
|
304
|
+
**Before publishing, update the version in `jsr2npm.config.json` to match your
|
|
305
|
+
release.**
|
|
306
|
+
|
|
307
|
+
Then trigger the workflow:
|
|
308
|
+
|
|
309
|
+
**Option A: Manual trigger**
|
|
310
|
+
|
|
311
|
+
- Go to Actions tab → "Publish CLI to NPM" → Run workflow
|
|
312
|
+
|
|
313
|
+
**Option B: Tag and push**
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
# Update version in jsr2npm.config.json first!
|
|
317
|
+
git add jsr2npm.config.json
|
|
318
|
+
git commit -m "Release v1.0.0"
|
|
319
|
+
git tag v1.0.0
|
|
320
|
+
git push origin main --tags
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Done! Your package will be published to npm.
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Example Output
|
|
328
|
+
|
|
329
|
+
After conversion, you'll have a structure like:
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
__scope__package_1.0.0/
|
|
333
|
+
├── node_modules/ (JSR package and dependencies)
|
|
334
|
+
└── dist/ (Ready to publish)
|
|
335
|
+
├── package.json (Generated for npm, preserves JSR exports)
|
|
336
|
+
├── bin/ (CLI tools, if configured)
|
|
337
|
+
│ └── command.mjs (Bundled executable)
|
|
338
|
+
├── types/ (TypeScript declarations)
|
|
339
|
+
│ └── mod.d.ts
|
|
340
|
+
├── README.md (Copied from source)
|
|
341
|
+
└── LICENSE (Copied from source)
|
|
342
|
+
```
|