How to publish a package to JSR.io

with Deno 2

13.10.2024

jsrdenoende
Gregor Wedlich
Gregor Wedlich
Life, the Universe and Everything.
Donate with:
Lightning
Alby

Table of Contents

    I’m currently quite taken with Deno and its ecosystem. Since version 2 was released a few days ago, I’ve been diving deeper into various aspects of Deno. One of the things I’ve explored is the package manager JSR, which can actually be viewed as a separate tool since it works independently and doesn’t require Deno itself. However, it complements the whole Deno ecosystem quite nicely. In this brief tutorial, I want to give you an overview of how simple it is to publish your own JSR packages.

    Create Project

    To start, initialize your project with the following command:

    1deno init orakel-otter // orakel-otter is the e.g. name of our app :-)

    Open the Project

    Run these commands to navigate to the project directory and start the program:

    1cd orakel-otter 2 3deno run main.ts 4 5deno task dev

    Clean Up

    For this tutorial, we can delete the main_test.ts file. However, it’s fine to keep it if you wish. Open main.ts and remove the automatically generated code. Now, we’ll add some example code.

    Create our app

    I have a simple program here which gets the current prices of Bitcoin from an API. Unfortunately I couldn't think of anything better, but it's just to illustrate how publishing JSR packages with Deno 2 works. We named it 🦦 Orakel Otter 🔮 :-)

    Below is our simple program that retrieves the current Bitcoin prices from an API:

    1type Response = [string, number][]; 2 3async function orakelOtter(currency: string = "ALL"): Promise<Response> { 4 try { 5 const response = await fetch("https://mempool.space/api/v1/prices/"); 6 const pricesObj = await response.json(); 7 const prices = Object.entries(pricesObj); 8 9 if (currency === "ALL") { 10 return prices as Response; 11 } 12 13 const filteredPrice = prices.filter( 14 (price) => price[0] === currency?.toUpperCase() 15 ); 16 17 if (filteredPrice.length > 0) { 18 return [...prices[0], filteredPrice[0]] as Response; 19 } else { 20 throw new Error(`Currency ${currency} not found.`); 21 } 22 } catch (error) { 23 console.error(error); 24 return []; 25 } 26} 27 28const getPrice = await orakelOtter(); 29console.log(getPrice);

    Run the following command to test the program:

    deno task dev

    The terminal will ask for permission to access the network. Confirm with y to proceed:

    1Watcher File change detected! Restarting! 2┏ ⚠️ Deno requests net access to "mempool.space:443". 3┠─ Requested by `fetch()` API. 4┠─ Learn more at: https://docs.deno.com/go/--allow-net 5┠─ Run again with --allow-net to bypass this prompt. 6┗ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all net permissions) > y

    Once granted, you should see output similar to this:

    1✅ Granted net access to "mempool.space:443". 2[ 3 [ "time", 1728830104 ], 4 [ "USD", 62513 ], 5 [ "EUR", 57121 ], 6 [ "GBP", 47771 ], 7 [ "CAD", 86060 ], 8 [ "CHF", 53563 ], 9 [ "AUD", 92464 ], 10 [ "JPY", 9344100 ] 11]

    Prepare the Project for Publishing on JSR.IO

    To publish the package on JSR.IO, you’ll need an account. Once logged in, go to your avatar, select “+ Publish a package,” and create a scope. For example, use your initials as the scope. After that, name your package (e.g., orakel-otter) and click “Create.”

    Before publishing, let’s update main.ts and add documentation.

    Code Adjustments

    In main.ts, make these changes:

    1. Remove the console.log() line and the instantiation.
    1const getPrice = await orakelOtter(); 2console.log(getPrice);
    1. Add export to the orakelOtter function to make it accessible as a module.
    2. Add documentation for the function, which is optional but recommended for better JSR scoring.
    1/** 2 * Fetches the current prices for various currencies from the Mempool.space API. 3 * 4 * @param currency - The currency (USD, EUR, GBP, CAD, CHF, AUD, JPY) to filter the prices for. If not provided, returns all available prices. 5 * @returns An array of tuples, where the first element is the currency code and the second element is the current price. 6 * @throws {Error} If the specified currency is not found in the API response. 7 */ 8export async function orakelOtter(currency: string = "ALL"): Promise<Response> { 9 // Function code remains unchanged 10}
    1. Update the deno.json file with required fields: name, version, and exports. Also, include license:
    1{ 2 "name": "@gw/orakel-otter", 3 "version": "0.0.1", 4 "license": "MIT", 5 "exports": "./main.ts" 6}

    The name should include the scope (e.g., @gw/orakel-otter), the version must follow SemVer format.

    Publishing the Package

    You can publish via CLI or GitHub Actions. For this tutorial, we’ll use the CLI.

    Run a dry run to ensure everything is set up correctly:

    1deno publish --dry-run

    If successful, proceed to publish without the --dry-run:

    1deno publish

    You’ll need to authenticate in your browser, approve the permissions, and your package will be published!

    Conclusion

    While this tutorial doesn’t cover every detail, it provides the key points needed to publish a package on JSR. Note that JSR rates packages based on several criteria that contribute to the “JSR Score.” Aim for thorough documentation and best practices to achieve a high score.

    For more details, check out the following documentation

    JSR Documentation

    Deno Documentation

    Ryan Dahl the creator of Nodejs and Deno about Deno 2 and JSR:

    By loading the video, you agree to the privacy policy of YouTube. The video will be loaded from YouTube's servers.

    Useful Links

    Project on GitHub

    Project on jsr.io


    Comments: