Wally Logo

Wally, a package manager for Roblox

* [Installation](#installation) * [Commands](#commands) * [Prior Art](#prior-art) * [Manifest Format](#manifest-format) * [Lockfile Format](#lockfile-format) * [Registries](#registries) * [License](#license) ## About Wally is a package manager for Roblox inspired by Cargo (Rust) and npm (JavaScript). It brings the familiar, community-oriented world of sharing code from other communities into the Roblox ecosystem. Wally has two pieces that work together: a command line tool named `wally` and a registry server that hosts packages. Most users will only interact with the command line tool, but both are available in this repository. ## Installation ### From GitHub Pre-built binaries are available for Windows, macOS, and Linux from the [GitHub Releases Page for Wally][releases]. [releases]: https://github.com/UpliftGames/wally/releases ### With Foreman [Foreman][foreman] is a toolchain manager developed for the Roblox community. You can use it to install Wally: ``` toml wally = { source = "UpliftGames/wally", version = "0.3.2" } ``` [foreman]: https://github.com/Roblox/foreman ### From Source It's straightforward to compile Wally from source. Wally requires Rust 1.51.0 or newer. Clone the repository and use: ```bash cargo install --locked --path . ``` ## Commands ### `wally init` Create a new, empty package. Parity with: * `cargo init` * `npm init` ### `wally install [--locked]` Installs all packages. `--locked` matches `cargo XXX --locked`, which will error if there is not an up-to-date lockfile. Intended for use on CI machines. (locked is a planned feature and not yet implemented) Parity with: * `npm install` with no arguments ### `wally update [package-names]` (unimplemented) Update packages recursively. By default, will update all packages. If any package names are given (in the form `scope/name` or `scope/name@version-req`), just those packages will be updated instead. Parity with: * `cargo publish` * `npm update` (npm 7+, equivalent to `--depth 9999` in npm 6.x and older) ### `wally publish` Publish the current package. Parity with: * `cargo publish` * `npm publish` ### `wally login` Log into an account to publish packages to a registry. You can also directly provide a token via `wally login --token "$WALLY_AUTH_TOKEN"`. Parity with: * `cargo login` * `npm login` ### `wally logout` Log out of a registry account. Parity with: * `cargo logout` * `npm logout` ### `wally package [--list] --output ` Package the current project as a zip file suitable for uploading to the package registry. Useful for adding entries to the registry and debugging what ends up in the blob that will be uploaded. `--list` will output which files will be included instead of creating a zip file. Parity with: * `cargo package` ### `wally manifest-to-json` Prints the current project's manifest as a line of JSON. Used for adding entries to the package index. Parity with: * `cargo read-manifest` ### `wally search ` Search the registry to see what packages are available. ## Prior Art Wally aims to stand on the shoulders of giants. Decisions we make are in part backed up by looking at other package managers and other public documentation: * [*So you want to write a package manager*](https://medium.com/@sdboyer/so-you-want-to-write-a-package-manager-4ae9c17d9527) * [crates.io](https://crates.io/) and [Cargo](https://github.com/rust-lang/cargo) from the Rust ecosystem * [npm](https://npmjs.org/) from the JavaScript ecosystem * [PyPI](https://pypi.org/), [pip](https://pip.pypa.io/en/stable/), [pipenv](https://pypi.org/project/pipenv/), and [Poetry](https://python-poetry.org/) from Python ## Manifest Format The package manifest file describes a package and all of the packages it depends on. Package manifests are written in [TOML][toml] and stored in a file named `wally.toml`. Manifest files are written by humans. They can contain comments and formatting decisions that are tough to preserve with automatic editing tools. This should be okay -- editing a package manifest should be easy. Manifest files define all necessary information about a package. Here is an example package manifest, annotated with comments: ```toml [package] # Package names are always "SCOPE/NAME" # They can include lowercase letters, numbers, and dashes. name = "lpghatguy/asink" # Descriptions are free-form. These will be used as part of package listings # and search results. description = "Asynchronous programming primitives" # Versions follow Semantic Versioning. # https://semver.org/ version = "2.0.7" # Contains an SPDX License Expression. # Licenses are required for publishing code to public registries. license = "MIT OR Apache-2.0" # The author list is a free-form list, but conventionally contains names and # email addresses. authors = ["Lucien Greathouse "] # Packages belong to a "realm", which helps prevent using code in the wrong # context. For now, we have "server" and "shared" realms. # The server realm should only be used for packages which shouldn't be replicated. realm = "shared" # Wally supports multiple registries. # This feature can be used to have split public/private registries to # keep internal code private and isolated. registry = "https://github.com/upliftgames/wally-index" # You can also specify files to include or exclude from the package # By default gitignore files are respected and Wally won't include hidden # files/directories or packages downloaded by Wally. # include = [] exclude = ["node_modules"] # Packages can be marked as private to prevent them from being published. private = true [dependencies] # Most dependencies will look like this. # # The name on the left is an alias. It defines what name we would like to # use to refer to this package. # # The value on the right will usually be a string of the form # "SCOPE/NAME@VERSION_REQ" # Versions are SemVer version requirements. The default behavior matches # Cargo, or npm with the `^` version specifier. Roact = "roblox/roact@1.2.0" Promise = "evaera/promise@2.0.1" [server-dependencies] # Dependencies in the server realm can be required here as shown above. # These are dependencies which should only ever exist on the server. [dev-dependencies] # Dev dependencies can be server or shared but are only needed during development. TestEZ = "roblox/testez@0.4.1" ``` ## Lockfile Format The lockfile contains the exact versions of each dependency that a project depends on. They're a critical feature that ensures that everyone who works on a game is getting the exact same version of every package. Lockfiles are written in [TOML][toml] and stored in a file named `wally.lock`. They're human-readable, but are only written by tools. We've optimized the lockfile format for reading as well as diffing so that they're as easy to review as possible. ```toml [[package]] name = "registry:lpghatguy/asink" version = "2.0.7" dependencies = [ "registry:roblox/roact", "registry:evaera/roblox-lua-promise", "registry:roblox/mono-thing", "git:https://github.com/Roblox/cool-thing.git", ] [[package]] name = "registry:evaera/roblox-lua-promise" version = "2.1.0" checksum = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" [[package]] name = "registry:roblox/mono-thing" version = "1.3.2" checksum = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" [[package]] name = "git:https://github.com/Roblox/cool-thing.git" rev = "foo" commit = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" ``` ## Registries Like many programming language package managers, Wally packages are published to a registry. A Wally registry consists of two pieces, inspired by Cargo and crates.io: * A Git repository containing a package index * A registry API that handles downloading and publishing package contents The official Wally registry is available at https://github.com/upliftgames/wally-index. ### Registry API * GET `/v1/package-contents///` * Returns the contents of a package for installation * Package contents are ZIP files * GET `/v1/package-metadata//` * Returns metadata for a package * GET `/v1/package-search?query=phrase` * Query what packages are available on this registry * POST `/api/v1/publish` * Client will post a package tarball that is extracted and published from the server. [toml]: https://toml.io/ ## License Wally is available under the terms of the Mozilla Public License Version 2.0. Terms and conditions are available in [LICENSE.txt](LICENSE.txt) or at .