npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@turbowarp/packager

v2.0.0

Published

Converts Scratch projects into HTML files, zip archives, or executable programs for Windows, macOS, and Linux.

Downloads

60

Readme

Node.js API

Installing

npm install --save-exact @turbowarp/packager

We suggest that you use --save-exact (or, with yarn, --exact) to make sure you always install the same version. This is important because we don't promise API compatibility across even minor updates.

About the API

Stability

The Node.js API is still in beta.

There are no promises of API stability between updates even across minor updates. Always pin to an exact version and don't update without testing. We don't go out of our way to break the API, but we don't let it stop us from making changes. We try to mention noteworthy changes in the GitHub releases changelog.

Release cadence

We intend to release an updated version of the npm module to npm with every update of TurboWarp Desktop, which currently happens about once a month.

Feature support

All features should work, with the following exceptions:

  • macOS apps in the NW.js or WKWebView environments do not support custom icons and must always use the default icon

Browser support

The Node.js module as published on npm is not intended to work in a browser regardless of any build tool such as webpack. If you need to run in a browser, fork this repository directly and modify the interface as you see fit.

Large assets

Large assets such as Electron binaries are not stored in this repository and will be downloaded from a remote server on demand. While we aren't actively removing old files, we can't promise they will exist forever. Downloads are validated with a SHA-256 checksum and cached locally.

Large assets are cached in node_modules/@turbowarp/packager/.packager-cache. You may want to periodically clean this folder.

Using the API

See demo.js or demo-simple.js for a full example.

First, you can import the module like this:

const Packager = require('@turbowarp/packager');

Load a project

Next you have to get a project file from somewhere. It can be a project.json or a full sb, sb2, or sb3 file. The packager doesn't provide any API for this, you have to find it on your own. Your data must be an ArrayBuffer, Uint8Array, or Node.js Buffer.

// Fetch a remote URL:
const fetch = require('cross-fetch').default; // or whatever your favorite HTTP library is
const projectData = await (await fetch('https://packager.turbowarp.org/example.sb3')).arrayBuffer();

// or use a local file:
const fs = require('fs');
const projectData = fs.readFileSync('project.sb3');

// or fetch a shared Scratch project:
const fetch = require('cross-fetch').default; // or whatever your favorite HTTP library is
const id = '437419376';
const projectMetadata = await (await fetch(`https://trampoline.turbowarp.org/api/projects/${id}`)).json();
const token = projectMetadata.project_token;
const projectData = await (await fetch(`https://projects.scratch.mit.edu/${id}?token=${token}`)).arrayBuffer();

Now you have to tell the packager to load the project. The packager will parse it, do some analysis, and download any needed assets if the input was just a project.json. This must be done once for every project. The result of this processes can be reused as many times as you want.

You may specify a "progress callback" that the loader may call periodically with progress updates. type will be a string like assets or compress. Depending on the type, a might be "loaded" and b might be "total", or a might be a percent [0-1] in which case b is unused.

const progressCallback = (type, a, b) => {};
const loadedProject = await Packager.loadProject(projectData, progressCallback);

Package the project

Now you can make a Packager.

const packager = new Packager.Packager();
packager.project = loadedProject;

packager.options has a lot of options on it for you to consider. You can log the object or see packager.js and look for DEFAULT_OPTIONS to see what options are available.

We recommend that you avoid overwriting the entirety of packager.options as this will cause issues when the structure of the options object changes in future updates. Instead, just update the properties you want to change from the defaults.

// GOOD:
packager.options.turbo = true;
packager.options.custom.js = "/* */";

// BAD (DO NOT DO THIS):
packager.options = {
  turbo: true,
  custom: {
    js: "/* */"
  },
  // ...
};

Even if you add ...packager.options the second example is still broken: options.custom also has a css property which is accidentally being set to undefined which is undefined behavior. Instead of remembering to do ...packager.options.xyz everywhere, it's best to just avoid completely redefining options whenever possible.

Some options expect an image as an argument. In the Node.js module, there is a special class to use for these, new Packager.Image(mimeType, buffer):

packager.options.app.icon = new Packager.Image('image/png', fs.readFileSync('icon.png'));

Note that a Packager is a single-use object; you must make a new Packager each time you want to package a project.

Now you can finally actually package the project.

const result = await packager.package();

// Suggested file name including file extension based on packager's options.
// This is not sanitized so it could contain things like path traversal exploits. Be careful.
const filename = result.filename;

// MIME type of the packaged project. Either "text/html" or "application/zip"
const type = result.type;

// The packaged project's data. Will be either a string (for type text/html) or ArrayBuffer (for type application/zip).
const data = result.data;

You can also add progress listeners on the packager using something similar to the addEventListener you're familiar with. Note that these aren't actually EventTargets, just a tiny shim that looks similar, so some things like once won't work and the events don't have very many properties on them.

// do this before calling package()
packager.addEventListener('zip-progress', ({detail}) => {
  // Used when compressing projects as zips
  console.log('Packager progress zip-progress', detail);
});
packager.addEventListener('large-asset-fetch', ({detail}) => {
  // Used when fetching large assets such as Electron binaries
  console.log('Packager progress large-asset-fetch', detail);
});

What you do with data is now entirely up to you.

Be mindful of the copyright on the projects you package.