@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 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
+ ```