diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..b17436e --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +PUBLIC_REGISTRY_URL= # url of the registry API, this must have a trailing slash and include the version + # example: https://registry.pesde.daimond113.com/v0/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4430b78..92c09d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- New website by @lukadev-0 + ### Fixed - Use updated aliases when reusing lockfile dependencies by @daimond113 - Listen for device flow completion without requiring pressing enter by @daimond113 diff --git a/README.md b/README.md index 5c9dddf..2fa94d5 100644 --- a/README.md +++ b/README.md @@ -6,21 +6,23 @@
-pesde is a package manager for the Luau programming language, supporting multiple runtimes including Roblox and Lune. -pesde has its own registry, however it can also use Wally, and Git repositories as package sources. -It has been designed with multiple targets in mind, namely Roblox, Lune, and Luau. +pesde is a package manager for the Luau programming language, supporting +multiple runtimes including Roblox and Lune. pesde has its own registry, however +it can also use Wally, and Git repositories as package sources. It has been +designed with multiple targets in mind, namely Roblox, Lune, and Luau. ## Installation -pesde can be installed from GitHub Releases. You can find the latest -release [here](https://github.com/daimond113/pesde/releases). Once you have downloaded the binary, -run the following command to install it: +pesde can be installed from GitHub Releases. You can find the latest release +[here](https://github.com/daimond113/pesde/releases). Once you have downloaded +the binary, run the following command to install it: ```sh pesde self-install ``` -Note that pesde manages its own versions, so you can update it by running the following command: +Note that pesde manages its own versions, so you can update it by running the +following command: ```sh pesde self-upgrade @@ -28,19 +30,23 @@ pesde self-upgrade ## Documentation -For more information about its usage, you can check the [documentation](https://docs.pesde.daimond113.com). - -*Currently waiting on [this PR](https://github.com/daimond113/pesde/pull/3) to be merged.* +For more information about its usage, you can check the +[documentation](https://docs.pesde.daimond113.com). ## Registry -The main pesde registry is hosted on [fly.io](https://fly.io). You can find it at https://registry.pesde.daimond113.com. +The main pesde registry is hosted on [fly.io](https://fly.io). You can find it +at https://registry.pesde.daimond113.com. ### Self-hosting -The registry tries to require no modifications to be self-hosted. Please refer to the [example .env file](https://github.com/daimond113/pesde/blob/0.5/registry/.env.example) for more information. +The registry tries to require no modifications to be self-hosted. Please refer +to the +[documentation](http://docs.pesde.daimond113.com/guides/self-hosting-registries) +for more information. ## Previous art -pesde is heavily inspired by [npm](https://www.npmjs.com/), [pnpm](https://pnpm.io/), [Wally](https://wally.run), -and [Cargo](https://doc.rust-lang.org/cargo/). +pesde is heavily inspired by [npm](https://www.npmjs.com/), +[pnpm](https://pnpm.io/), [Wally](https://wally.run), and +[Cargo](https://doc.rust-lang.org/cargo/). diff --git a/assets/logomark.svg b/assets/logomark.svg new file mode 100644 index 0000000..4772b9b --- /dev/null +++ b/assets/logomark.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..d10a8bf --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,22 @@ +# build output +dist/ +# generated types +.astro/ +.vercel/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store diff --git a/docs/.prettierrc b/docs/.prettierrc new file mode 100644 index 0000000..20791be --- /dev/null +++ b/docs/.prettierrc @@ -0,0 +1,14 @@ +{ + "useTabs": true, + "printWidth": 100, + "semi": false, + "plugins": ["prettier-plugin-astro", "prettier-plugin-tailwindcss"], + "overrides": [ + { + "files": "*.astro", + "options": { + "parser": "astro" + } + } + ] +} diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs new file mode 100644 index 0000000..41d2334 --- /dev/null +++ b/docs/astro.config.mjs @@ -0,0 +1,110 @@ +import starlight from "@astrojs/starlight" +import tailwind from "@astrojs/tailwind" +import { defineConfig } from "astro/config" + +import vercel from "@astrojs/vercel/serverless" + +// https://astro.build/config +export default defineConfig({ + integrations: [ + starlight({ + title: "pesde docs", + social: { + github: "https://github.com/daimond113/pesde", + }, + sidebar: [ + { + label: "Intro", + items: [{ slug: "" }, { slug: "installation" }, { slug: "quickstart" }], + }, + { + label: "Guides", + autogenerate: { directory: "guides" }, + }, + { + label: "Reference", + autogenerate: { directory: "reference" }, + }, + { + label: "Registry", + autogenerate: { directory: "registry" }, + }, + ], + components: { + SiteTitle: "./src/components/SiteTitle.astro", + }, + customCss: ["./src/tailwind.css", "@fontsource-variable/nunito-sans"], + favicon: "/favicon.ico", + head: [ + { + tag: "meta", + attrs: { + name: "theme-color", + content: "#F19D1E", + }, + }, + { + tag: "meta", + attrs: { + property: "og:image", + content: "/favicon-48x48.png", + }, + }, + { + tag: "meta", + attrs: { + name: "twitter:card", + content: "summary", + }, + }, + { + tag: "link", + attrs: { + rel: "icon", + type: "image/png", + href: "/favicon-48x48.png", + sizes: "48x48", + }, + }, + { + tag: "link", + attrs: { + rel: "icon", + type: "image/svg+xml", + href: "/favicon.svg", + }, + }, + { + tag: "link", + attrs: { + rel: "apple-touch-icon", + sizes: "180x180", + href: "/apple-touch-icon.png", + }, + }, + { + tag: "meta", + attrs: { + name: "apple-mobile-web-app-title", + content: "pesde docs", + }, + }, + { + tag: "link", + attrs: { + rel: "manifest", + href: "/site.webmanifest", + }, + }, + ], + }), + tailwind({ + applyBaseStyles: false, + }), + ], + vite: { + envDir: "..", + }, + output: "hybrid", + adapter: vercel(), +}) diff --git a/docs/bun.lockb b/docs/bun.lockb new file mode 100755 index 0000000..cd13c41 Binary files /dev/null and b/docs/bun.lockb differ diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 0000000..b2f7aa2 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,30 @@ +{ + "name": "docs", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro check && astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/check": "^0.9.3", + "@astrojs/starlight": "^0.28.2", + "@astrojs/starlight-tailwind": "^2.0.3", + "@astrojs/tailwind": "^5.1.1", + "@astrojs/vercel": "^7.8.1", + "@fontsource-variable/nunito-sans": "^5.1.0", + "@shikijs/rehype": "^1.21.0", + "astro": "^4.15.9", + "sharp": "^0.33.5", + "shiki": "^1.21.0", + "tailwindcss": "^3.4.13", + "typescript": "^5.6.2" + }, + "devDependencies": { + "prettier-plugin-astro": "^0.14.1", + "prettier-plugin-tailwindcss": "^0.6.8" + } +} diff --git a/docs/public/apple-touch-icon.png b/docs/public/apple-touch-icon.png new file mode 100644 index 0000000..0d6cb91 Binary files /dev/null and b/docs/public/apple-touch-icon.png differ diff --git a/docs/public/favicon-48x48.png b/docs/public/favicon-48x48.png new file mode 100644 index 0000000..c9b5d34 Binary files /dev/null and b/docs/public/favicon-48x48.png differ diff --git a/docs/public/favicon.ico b/docs/public/favicon.ico new file mode 100644 index 0000000..b701ce6 Binary files /dev/null and b/docs/public/favicon.ico differ diff --git a/docs/public/favicon.svg b/docs/public/favicon.svg new file mode 100644 index 0000000..4772b9b --- /dev/null +++ b/docs/public/favicon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/docs/public/site.webmanifest b/docs/public/site.webmanifest new file mode 100644 index 0000000..4f0f430 --- /dev/null +++ b/docs/public/site.webmanifest @@ -0,0 +1,21 @@ +{ + "name": "pesde", + "short_name": "pesde", + "icons": [ + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#f19d1e", + "background_color": "#0a0704", + "display": "standalone" +} \ No newline at end of file diff --git a/docs/public/web-app-manifest-192x192.png b/docs/public/web-app-manifest-192x192.png new file mode 100644 index 0000000..e8fc903 Binary files /dev/null and b/docs/public/web-app-manifest-192x192.png differ diff --git a/docs/public/web-app-manifest-512x512.png b/docs/public/web-app-manifest-512x512.png new file mode 100644 index 0000000..f817b7a Binary files /dev/null and b/docs/public/web-app-manifest-512x512.png differ diff --git a/docs/src/components/SiteTitle.astro b/docs/src/components/SiteTitle.astro new file mode 100644 index 0000000..c3da7d5 --- /dev/null +++ b/docs/src/components/SiteTitle.astro @@ -0,0 +1,30 @@ +
+ + + pesde + + + + + + + + / + docs +
diff --git a/docs/src/content/config.ts b/docs/src/content/config.ts new file mode 100644 index 0000000..45f60b0 --- /dev/null +++ b/docs/src/content/config.ts @@ -0,0 +1,6 @@ +import { defineCollection } from 'astro:content'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ schema: docsSchema() }), +}; diff --git a/docs/src/content/docs/guides/binary-packages.mdx b/docs/src/content/docs/guides/binary-packages.mdx new file mode 100644 index 0000000..250d46e --- /dev/null +++ b/docs/src/content/docs/guides/binary-packages.mdx @@ -0,0 +1,41 @@ +--- +title: Using Binary Packages +description: Learn how to use binary packages. +--- + +A **binary package** is a package that contains a binary export. + +Binary packages can be run like a normal program. There are several ways to use +binary packages with pesde. + +## Using `pesde x` + +The `pesde x` command can be used to run a one-off binary package. This is +useful for running a binary package without installing it or outside of a pesde +project. + +```sh +pesde x pesde/hello +# Hello, pesde! (pesde/hello@1.0.0, lune) +``` + +## Installing a binary package + +Binary packages can be installed using the `pesde add` and `pesde install` +commands. + +This requires a `pesde.toml` file to be present in the current directory, and +will add the binary package to the `dependencies` section of the file. + +```sh +pesde add pesde/hello +pesde install +``` + +This will add the binary package to your `PATH`, meaning that it can be run +anywhere! + +```sh +hello +# Hello, pesde! (pesde/hello@1.0.0, lune) +``` \ No newline at end of file diff --git a/docs/src/content/docs/guides/dependencies.mdx b/docs/src/content/docs/guides/dependencies.mdx new file mode 100644 index 0000000..8fafc79 --- /dev/null +++ b/docs/src/content/docs/guides/dependencies.mdx @@ -0,0 +1,170 @@ +--- +title: Specifying Dependencies +description: Learn how to specify dependencies in your pesde project. +--- + +import { Aside, FileTree, LinkCard } from "@astrojs/starlight/components" + +The `[dependencies]` section of your `pesde.toml` file is where you specify the +dependencies of your project. + +pesde supports multiple types of dependencies. + +## pesde Dependencies + +The most common type of dependency are pesde dependencies. These are +dependencies on packages published to a [pesde registry](https://pesde.daimond113.com). + +```toml title="pesde.toml" +[indices] +default = "https://github.com/daimond113/pesde-index" + +[dependencies] +hello = { name = "pesde/hello", version = "^1.0.0" } +``` + +In this example, we're specifying a dependency on the `pesde/hello` package on +the official pesde registry with a version constraint of `^1.0.0`. + +You can also add a dependency by running the following command: + +```sh +pesde add pesde/hello +``` + +## Git Dependencies + +Git dependencies are dependencies on packages hosted on a Git repository. + +```toml title="pesde.toml" +[dependencies] +acme = { repo = "acme/package", rev = "main" } +``` + +In this example, we're specifying a dependency on the package contained within +the `acme/package` GitHub repository at the `main` branch. + +You can also use a URL to specify the Git repository and a specific commit. + +```toml title="pesde.toml" +[dependencies] +acme = { repo = "https://git.acme.local/package.git", rev = "aeff6" } +``` + +You can also specify a path if the package is not at the root of the repository. + + + +- acme/package.git + - pkgs/ + - **foo/** + - pesde.toml + - ... + + + +```toml title="pesde.toml" +[dependencies] +foo = { repo = "acme/package", rev = "main", path = "pkgs/foo" } +``` + +The path specified by the Git dependency must either be a valid pesde package or +a [Wally][wally] package. + +You can also add a Git dependency by running the following command: + +```sh +# From Git URL +pesde add https://git.acme.local/package.git#aeff6 + +# From GitHub repository +pesde add gh#acme/package#main +``` + +## Wally Dependencies + +Wally dependencies are dependencies on packages published to a +[Wally registry][wally]. Wally is a package manager for Roblox and thus Wally +dependencies should only be used in Roblox projects. + +```toml title="pesde.toml" +[wally_indices] +default = "https://github.com/UpliftGames/wally-index" + +[dependencies] +foo = { wally = "acme/package", version = "^1.0.0" } +``` + +In this example, we're specifying a dependency on the `acme/package` package +on the official Wally registry with a version constraint of `^1.0.0`. + + + +You can also add a Wally dependency by running the following command: + +```sh +pesde add wally#acme/package +``` + +[wally]: https://wally.run/ + +## Workspace Dependencies + +Packages within a workspace can depend on each other. For example, if `foo` +and `bar` are both packages in the same workspace, you can add a dependency to +`bar` in the `foo/pesde.toml` file: + +```toml title="foo/pesde.toml" +[dependencies] +bar = { workspace = "acme/bar", version = "^" } +``` + +You can also add a workspace dependency by running the following command: + +```sh +pesde add workspace:acme/bar +``` + + + +## Peer Dependencies + +Peer dependencies are dependencies that are not installed automatically when +used by another package. They need to be installed by the user of the package. + +```toml title="pesde.toml" +[peer_dependencies] +foo = { name = "acme/foo", version = "^1.0.0" } +``` + +You can add a peer dependency by passing `--peer` to the `pesde add` command: + +```sh +pesde add --peer acme/foo +``` + +## Dev Dependencies + +Dev dependencies are dependencies that are only used during development. They +are not installed when the package is used as a dependency. + +```toml title="pesde.toml" +[dev_dependencies] +foo = { name = "acme/foo", version = "^1.0.0" } +``` + +You can add a dev dependency by passing `--dev` to the `pesde add` command: + +```sh +pesde add --dev acme/foo +``` diff --git a/docs/src/content/docs/guides/overrides.mdx b/docs/src/content/docs/guides/overrides.mdx new file mode 100644 index 0000000..fc28c1c --- /dev/null +++ b/docs/src/content/docs/guides/overrides.mdx @@ -0,0 +1,80 @@ +--- +title: Overriding Dependencies +description: Learn how to override and patch dependencies in pesde. +--- + +import { Aside } from '@astrojs/starlight/components' + +pesde has several ways to override or patch dependencies in your project. + +## Dependency Overrides + +Dependency overrides allow you to replace a dependency of a dependency with a +different version or package. + +Let's say you have a project with the following dependencies: + +```toml title="pesde.toml" +[dependencies] +foo = { name = "acme/foo", version = "^1.0.0" } +``` + +But `foo` depends on `bar` 1.0.0, and you want to use `bar` 2.0.0 instead. You +can override the `bar` dependency in your `pesde.toml` file: + +```toml title="pesde.toml" +[dependencies] +foo = { name = "acme/foo", version = "^1.0.0" } + +[overrides] +"foo>bar" = { name = "acme/bar", version = "^2.0.0" } +``` + +Now, when you run `pesde install`, `bar` 2.0.0 will be used instead of 1.0.0. + +You can learn more about the syntax for dependency overrides in the +[reference](/reference/manifest#overrides). + +## Patching Dependencies + +Patching allows you to modify the source code of a dependency. + +To patch a dependency, you can use the `pesde patch` and `pesde patch-commit` +commands. + +Let's say you have the following dependency in your `pesde.toml` file: + +```toml title="pesde.toml" +[target] +environment = "luau" + +[dependencies] +foo = { name = "acme/foo", version = "^1.0.0" } +``` + +And you want to patch `foo` to fix a bug. You can run the following command: + +```sh +pesde patch "acme/foo@1.0.0 luau" + +# done! modify the files in the directory, then run `pesde patch-commit /x/y/z` +# to apply. +# warning: do not commit these changes +# note: the pesde.toml file will be ignored when patching +``` + +pesde will copy the source code of `foo` to a temporary directory, in this case +`/x/y/z`. You can then modify the files in this directory. Once you're done, +run `pesde patch-commit /x/y/z` to apply the changes. + +This will create a patch within the `patches` directory of your project, and +add an entry to `[patches]`. Then, next time you run `pesde install`, the patch +will be applied to the dependency. + + + diff --git a/docs/src/content/docs/guides/publishing.mdx b/docs/src/content/docs/guides/publishing.mdx new file mode 100644 index 0000000..e111f31 --- /dev/null +++ b/docs/src/content/docs/guides/publishing.mdx @@ -0,0 +1,94 @@ +--- +title: Publishing Packages +description: Learn how to publish packages to the pesde registry. +--- + +## Configuration + +Before you can publish a package, you must configure the required fields in your +`pesde.toml` file. + +### `includes` + +The `includes` field is a list of files and directories that should be included +in the package. + +```toml +includes = [ + "pesde.toml", + "README.md", + "LICENSE", + "init.luau", +] +``` + +### `target` + +The `target` field defines the environment where the package can be run. + +Here, you must also specify the `lib` and/or `bin` fields to indicate the path +of the exported library or binary. + +```toml +[target] +environment = "luau" +lib = "init.luau" +``` + +#### Roblox + +`bin` is not supported in Roblox packages. You must also specify a list of +`build_files`. These are the files that should be synced into Roblox. They are +passed to the `roblox_sync_config_generator` script. + +For more information, see [Roblox](/guides/roblox). + +```toml +[target] +environment = "roblox" +lib = "init.luau" +build_files = ["init.luau"] +``` + +## Authentication + +Before you can publish a package, you must authenticate with your GitHub account. + +```sh +pesde auth login +``` + +You will be given a code and prompted to open the GitHub authentication page in +your browser. You must enter the code to authenticate. + +## Publishing + +To publish a package, run the following command: + +```sh +pesde publish +``` + +You will be prompted to confirm the package details before publishing. + +Once a package is published, others will be able to install it. You may not +remove a package once it has been published. You may not publish a package with +an already existing version. + +## Multi-target Packages + +You may publish packages under the same name and version but with different +targets. This allows you to publish a package that can be used in multiple +environments. + +For example, you may publish a package that can be used in both Roblox and +Luau environments by publishing two versions of the package, one for each +environment. + +## Documentation + +The `README.md` file in the root of the package will be displayed on the +[pesde registry website](https://pesde.daimond113.com/). + +If you have a `docs` directory in the root of the package, they will be +hosted by pesde and be accessible on the pesde website. diff --git a/docs/src/content/docs/guides/roblox.mdx b/docs/src/content/docs/guides/roblox.mdx new file mode 100644 index 0000000..b35517e --- /dev/null +++ b/docs/src/content/docs/guides/roblox.mdx @@ -0,0 +1,36 @@ +--- +title: Roblox +description: Using pesde in a Roblox project. +--- + +pesde can be used in Roblox projects, however this requires some extra setup. +Namely, you need to specify a `roblox_sync_config_generator` script in order +to generate the adequate configuration for the sync tool you are using. + +The [`pesde-scripts`](https://github.com/daimond113/pesde-scripts) +repository contains a list of scripts for different sync tools. If the tool +you are using is not supported, you can write your own script and submit a PR +to get it added. + +These scripts are automatically cloned into the `~/.pesde/scripts` folder and +kept up to date when you use pesde. + +## Usage with Rojo + +[Rojo](https://rojo.space/) is a popular tool for syncing files into Roblox +Studio. + +Running `pesde init` will prompt you to select a target, select +`roblox` or `roblox_server` in this case. This will setup the configuration +needed to use pesde in a project using Rojo. + +## Usage with other tools + +If you are using a different sync tool, you should look for it's scripts in the +pesde-scripts repository. If you cannot find them, you can write your own and +optionally submit a PR to help others using the same tool as you get started +quicker. + +Scaffold your project with `pesde init`, select the `roblox` or `roblox_server` +target, and then replace the `.pesde/roblox_sync_config_generator.luau` script +with the one you want to use. diff --git a/docs/src/content/docs/guides/self-hosting-registries.mdx b/docs/src/content/docs/guides/self-hosting-registries.mdx new file mode 100644 index 0000000..dc8c3bf --- /dev/null +++ b/docs/src/content/docs/guides/self-hosting-registries.mdx @@ -0,0 +1,204 @@ +--- +title: Self Hosting Registries +description: Learn how to self host registries for pesde. +--- + +You can self host registries for pesde. This is useful if you want a private +registry or if you a separate registry for other reasons. + +## Making the index repository + +The index is a repository that contains metadata about all the packages in the +registry. + +An index contains a `config.toml` file with configuration options. + +To create an index, create a new repository and add a `config.toml` file with +the following content: + +```toml title="config.toml" +# The URL of the registry API +api = "https://registry.acme.local/" + +# Package download URL (optional) +download = "{API_URL}/v0/packages/{PACKAGE}/{PACKAGE_VERSION}/{PACKAGE_TARGET}" + +# the client ID of the GitHub OAuth app (optional) +github_oauth_client_id = "a1d648966fdfbdcd9295" + +# whether to allow packages with Git dependencies (default: false) +git_allowed = true + +# whether to allow packages which depend on packages from other registries +# (default: false) +other_registries_allowed = true + +# whether to allow packages with Wally dependencies (default: false) +wally_allowed = false + +# the maximum size of the archive in bytes (default: 4MB) +max_archive_size = 4194304 +``` + +- **api**: The URL of the registry API. See below for more information. + +- **download**: The URL to download packages from. This is optional and + defaults to the correct URL for the official pesde registry implementation. + You only need this if you are using a custom registry implementation. + + This string can contain the following placeholders: + + - `{API_URL}`: The API URL (as specified in the `api` field). + - `{PACKAGE}`: The package name. + - `{PACKAGE_VERSION}`: The package version. + - `{PACKAGE_TARGET}`: The package target. + + Defaults to `{API_URL}/v0/packages/{PACKAGE}/{PACKAGE_VERSION}/{PACKAGE_TARGET}`. + +- **github_oauth_client_id**: This is required if you use GitHub OAuth for + authentication. See below for more information. + +- **git_allowed**: Whether to allow packages with Git dependencies. This is + optional and defaults to `false`. + +- **other_registries_allowed**: Whether to allow packages which depend on + packages from other registries. This is optional and defaults to `false`. + +- **wally_allowed**: Whether to allow packages with Wally dependencies. This is + optional and defaults to `false`. + +- **max_archive_size**: The maximum size of the archive in bytes. This is + optional and defaults to `4194304` (4MB). + +You should then push this repository to [GitHub](https://github.com/). + +## Configuring the registry + +The registry is a web server that provides package downloads and the ability to +publish packages. + +The official registry implementation is available in the +[pesde GitHub repository](https://github.com/daimond113/pesde/tree/0.5/registry). + +Configuring the registry is done using environment variables. In order to allow +the registry to access the index repository, you must use a personal access +token of a GitHub account that has access to the index repository. We recommend +using a separate GitHub account for this purpose. + +For instructions on how to create a personal access token, see the +[GitHub documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens). +The access token must have read and write access to the index repository. + +### General configuration + +- **INDEX_REPO_URL**: The URL of the index repository. This is required.\ + Example: `https://github.com/daimond113/pesde-index.git` + +- **GITHUB_USERNAME**: The username of the GitHub account that has access to the + index repository. This is required. + +- **GITHUB_PAT**: The personal access token of the GitHub account specified by + `GITHUB_USERNAME`. This is required. + +- **COMMITTER_GIT_NAME**: The name to use for the committer when updating the + index repository.\ + Example: `pesde index updater` + +- **COMMITTER_GIT_EMAIL**: The email to use for the committer when updating the + index repository.\ + Example: `pesde@localhost` + +- **ADDRESS**: The address to bind the server to.\ + Default: `127.0.0.1` + +- **PORT**: The port to bind the server to.\ + Default: `8080` + +### Authentication configuration + +The registry supports multiple authentication methods, which are documented +below. + +#### General configuration + +- **READ_NEEDS_AUTH**: If set to any value, reading data requires + authentication. If not set, anyone can read from the registry. + This is optional. + +#### Single token authentication + +Allows read and write access to the registry using a single token. + +- **ACCESS_TOKEN**: The token to use for authentication. + +#### Multiple token authentication + +Allows read and write access to the registry using different tokens. + +- **READ_ACCESS_TOKEN**: The token that grants read access. +- **WRITE_ACCESS_TOKEN**: The token that grants write access. + +#### GitHub OAuth authentication + +Allows clients to get read and write access to the registry using GitHub OAuth. +This requires a GitHub OAuth app, instructions to create one can be found +in the [GitHub documentation](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app). + +- **GITHUB_CLIENT_SECRET**: The client secret of the GitHub OAuth app. + +#### No authentication + +If none of the above variables are set, **anyone** will be able to read and +write to the registry. + +### Storage configuration + +The registry supports multiple storage backends, which are documented below. + +#### File system storage + +Stores packages on the file system. + +- **FS_STORAGE_ROOT**: The root directory where packages are stored. + +#### S3 storage + +Stores packages on an S3 compatible storage service, such as +[Amazon S3](https://aws.amazon.com/s3/) or +[Cloudflare R2](https://www.cloudflare.com/r2/). + +- **S3_ENDPOINT**: The endpoint of the S3 bucket to store packages in. +- **S3_BUCKET_NAME**: The name of the bucket. +- **S3_REGION**: The region of the bucket. +- **S3_ACCESS_KEY**: The access key to use. +- **S3_SECRET_KEY**: The secret key to use. + +### Sentry configuration + +The registry supports [Sentry](https://sentry.io/) for error tracking. + +- **SENTRY_DSN**: The DSN of the Sentry instance. + +## Running the registry + +First clone the repository and navigate to the repository directory: + +```sh +git clone https://github.com/daimond113/pesde.git +cd pesde +``` + +You can then build the registry using the following command: + +```sh +cargo build --release -p pesde-registry +``` + +This will build the registry. The resulting binary will be located at +`target/release/pesde-registry` or `target/release/pesde-registry.exe`. + +After setting the environment variables, you can run the registry using the +by executing the binary. + +The registry must be exposed at the URL specified in the `api` field of the +index repository configuration. diff --git a/docs/src/content/docs/guides/workspaces.mdx b/docs/src/content/docs/guides/workspaces.mdx new file mode 100644 index 0000000..4b7bb52 --- /dev/null +++ b/docs/src/content/docs/guides/workspaces.mdx @@ -0,0 +1,100 @@ +--- +title: Workspaces +description: Learn how to use workspaces in pesde. +--- + +import { FileTree, LinkCard } from "@astrojs/starlight/components" + +Workspaces allow you to work with multiple pesde projects within a single +repository. Packages within a workspace can depend on each other. And you can +run commands like install or publish on every package in the workspace at once. + +Let's say you have a repository with the following structure: + + + +- pesde.toml +- pkgs/ + - foo/ + - pesde.toml + - ... + - bar/ + - pesde.toml + - ... + + + +Within the root `pesde.toml` file, we can define a workspace: + +```toml title="pesde.toml" +name = "acme/root" +version = "0.0.0" +private = "true" + +workspace_members = ["pkgs/*"] + +[target] +environment = "luau" +``` + +Now, each folder within the `pkgs/` directory is considered a package in the +workspace. You can run commands like `pesde install` or `pesde publish` from +the root of the repository to run them on every package in the workspace. + +## Workspace Dependencies + +Packages within a workspace can depend on each other. For example, if `foo` +depends on `bar`, you can add a dependency to `bar` in the `foo/pesde.toml` file: + +```toml title="pkgs/foo/pesde.toml" +name = "acme/foo" +version = "1.0.0" + +[dependencies] +bar = { workspace = "acme/bar", version = "^" } +``` + +Workspace dependencies are replaced with normal pesde dependencies when +publishing. + +The `version` field can either contain `^`, `*`, `=`, `~`, or a specific version +requirement, such as `^1.0.0`. If you use `^`, `=`, or `~`, it will be replaced +with the version of the package in the workspace when publishing. + +For example, if you had the following: + +```toml title="pesde.toml" +[dependencies] +bar = { workspace = "acme/bar", version = "^" } +qux = { workspace = "acme/qux", version = "=" } +qar = { workspace = "acme/qar", version = "~" } +zoo = { workspace = "acme/zoo", version = "^2.1.0" } +baz = { workspace = "acme/baz", version = "*" } +``` + +If `bar`, `baz`, `qux`, `qar`, and `zoo` are all at version `2.1.5` in the +workspace, the `pesde.toml` file will be transformed into the following when +publishing. + +```toml title="pesde.toml" +[dependencies] +bar = { name = "acme/bar", version = "^2.1.5" } +qux = { name = "acme/qux", version = "=2.1.5" } +qar = { name = "acme/qar", version = "~2.1.5" } +zoo = { name = "acme/zoo", version = "^2.1.0" } +baz = { name = "acme/baz", version = "*" } +``` + +A `target` field can be added to the `dependencies` table to specify a target +environment for the dependency. + +```toml title="pesde.toml" +[dependencies] +bar = { workspace = "acme/bar", version = "^", target = "luau" } +``` + + diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx new file mode 100644 index 0000000..45255fc --- /dev/null +++ b/docs/src/content/docs/index.mdx @@ -0,0 +1,32 @@ +--- +title: What is pesde? +description: A package manager for the Luau programming language, supporting multiple runtimes including Roblox and Lune. +--- + +pesde is a package manager for the Luau programming language. + +## Why use pesde? + +When you write code, you often want to use libraries or frameworks that others +have written. Manually downloading and managing these can be cumbersome. + +These libraries or frameworks can be distributed as packages. You can then +easily install and use these packages using pesde. pesde will automatically +download and manage the packages, and their dependencies, for you. + +## Multi-target support + +Luau can run in a lot of different places, such as on [Roblox][roblox], or in +[Lune][lune]. + +pesde is designed to work with all of these runtimes. Packages can publish +multiple versions of themselves, each tailored to a specific runtime. + +[registry]: https://pesde.daimond113.com/ +[roblox]: https://www.roblox.com/ +[lune]: https://lune-org.github.io/docs + +## The pesde registry + +The [pesde registry][registry] is where anyone can publish their packages for +others to use. diff --git a/docs/src/content/docs/installation.mdx b/docs/src/content/docs/installation.mdx new file mode 100644 index 0000000..3cb8f8c --- /dev/null +++ b/docs/src/content/docs/installation.mdx @@ -0,0 +1,89 @@ +--- +title: Installation +description: Install pesde +--- + +import { Aside, Steps, TabItem, Tabs } from "@astrojs/starlight/components" + +## Prerequisites + +pesde requires [Lune](https://lune-org.github.io/docs) to be installed on your +system in order to function properly. + +You can follow the installation instructions in the +[Lune documentation](https://lune-org.github.io/docs/getting-started/1-installation). + +## Installing pesde + + + +1. Go to the [GitHub releases page](https://github.com/daimond113/pesde/releases/latest). + +2. Download the corresponding archive for your operating system. You can choose + whether to use the `.zip` or `.tar.gz` files. + +3. Extract the downloaded archive to a folder on your computer. + +4. Open a terminal and locate the path of the extracted `pesde` binary. + + + + + If you extracted the archive to `C:\Users\User\Downloads`, the path to the + `pesde` binary would be `C:\Users\User\Downloads\pesde.exe`. + + You can then run the `self-install` command: + + ```ps + C:\Users\User\Downloads\pesde.exe self-install + ``` + + pesde should now be installed on your system. You may need to restart your + computer for the changes to take effect. + + + + + If you extracted the archive to `~/Downloads`, the path to the `pesde` + binary would be `~/Downloads/pesde`. + + You must then add execute permissions and run the `self-install` command: + + ```sh + chmod +x ~/Downloads/pesde + ~/Downloads/pesde self-install + ``` + + pesde should now be installed on your system. You will need to update your + shell configuration file to add the pesde binary to your `PATH` + environment variable. + + ```sh title=".zshrc" + export PATH = "$PATH:/home/user/.pesde/bin" + ``` + + You should then be able to run `pesde` after restarting your shell. + + + + + 5. Verify that pesde is installed by running the following command: + + ```sh + pesde -v + ``` + + This command should output the version of pesde that you installed. + + + + diff --git a/docs/src/content/docs/quickstart.mdx b/docs/src/content/docs/quickstart.mdx new file mode 100644 index 0000000..10ce4d9 --- /dev/null +++ b/docs/src/content/docs/quickstart.mdx @@ -0,0 +1,142 @@ +--- +title: Quickstart +description: Start using pesde +--- + +import { FileTree } from "@astrojs/starlight/components" + +Let's make a simple Luau program that uses the `pesde/hello` package to print +hello to the terminal. + +## Scaffolding the project + +In your terminal, run the following commands to create a folder and navigate +into it. + +```sh +mkdir hello-pesde +cd hello-pesde +``` + +Then, we'll use `pesde init` to scaffold a new pesde project. The command will +ask you a few questions to set up the project. Our project will be named +`/hello_pesde`, replace `` with a username of your choice. +The name may only contain lowercase letters, numbers, and underscores. The +environment we're targeting is `luau`. + +```sh +pesde init + +# What is the name of the project? /hello_pesde +# What is the description of the project? (leave empty for none) +# Who are the authors of this project? (leave empty for none, comma separated) +# What is the repository URL of this project? (leave empty for none) +# What is the license of this project? (leave empty for none) MIT +# What environment are you targeting for your package? luau +# Would you like to setup a default roblox_sync_config_generator script? No +``` + +The command will create a `pesde.toml` file in the current folder. Go ahead +and open this file in your text editor of choice. + +## Adding a main script + +Under the `[target]` section, we're going to add a `bin` field to specify +the path to the main script of our package. + +```diff lang="toml" title="pesde.toml" + name = "/hello_pesde" + version = "0.1.0" + license = "MIT" + + [target] + environment = "luau" ++ bin = "main.luau" + + [indices] + default = "https://github.com/daimond113/pesde-index" +``` + +Don't forget to save the file after making the changes. + +Now, lets create a `main.luau` file in the project folder and add the following +code to it. + +```luau title="main.luau" +print("Hello, pesde!") +``` + +## Running the script + +Then, we can run the following command to run the script. + +```sh +pesde run +``` + +You should see `Hello, pesde!` printed to the terminal. + +## Install a dependency + +Let's use the `pesde/hello` package instead of printing ourselves. + +Run the following command to add the package to `pesde.toml`. + +```sh +pesde add pesde/hello +``` + +You should see that `pesde.toml` has been updated with the new dependency. + +```diff lang="toml" title="pesde.toml" + name = "lukadev_0/hello_pesde" + version = "0.1.0" + license = "MIT" + + [target] + environment = "luau" + bin = "main.luau" + + [indices] + default = "https://github.com/daimond113/pesde-index" + ++ [dependencies] ++ hello = { name = "pesde/hello", version = "^1.0.0" } +``` + +Run the following command to install the new dependency. + +```sh +pesde install +``` + +You should see that pesde has created a `luau_packages` folder containing the +newly installed package. It has alsoo created a `pesde.lock` file, this file +contains the exact versions of the dependencies that were installed so that +they can be installed again in the future. + + + +- luau_packages/ + - hello.luau + - ... +- main.luau +- pesde.lock +- pesde.toml + + + +Let's update the `main.luau` file to use the `pesde/hello` package. + +```luau title="main.luau" +local hello = require("./luau_packages/hello") + +hello() +``` + +If we run the script again, we should see something printed to the terminal. + +```sh +pesde run +# Hello, pesde! (pesde/hello@1.0.0, luau) +``` \ No newline at end of file diff --git a/docs/src/content/docs/reference/cli.mdx b/docs/src/content/docs/reference/cli.mdx new file mode 100644 index 0000000..48fdea3 --- /dev/null +++ b/docs/src/content/docs/reference/cli.mdx @@ -0,0 +1,188 @@ +--- +title: pesde CLI +description: Reference for the pesde CLI. +--- + +import { LinkCard } from "@astrojs/starlight/components" + +The pesde CLI is the primary way to interact with pesde projects. It provides +commands for installing dependencies, running scripts, and more. + +## `pesde auth` + +Authentication-related commands. + +- `-i, --index`: The index of which token to manipulate. May be a URL or an alias. + Defaults to the default + index of the current project or the default index set in the config. + +### `pesde auth login` + +Sets the token for the index. + +- `-t, --token`: The token to set. + +If no token is provided, you will be prompted to authenticate with GitHub. A +code will be provided that you can paste into the GitHub authentication prompt. + +### `pesde auth logout` + +Removes the stored token for the index. + +### `pesde auth whoami` + +Prints the username of the currently authenticated user of the index. Only +works if the token is a GitHub token. + +## `pesde config` + +Configuration-related commands. + +### `pesde config default-index` + +```sh +pesde config default-index [INDEX] +``` + +Configures the default index. If no index is provided, the current default index +is printed. + +- `-r, --reset`: Resets the default index. + +The default index is [`pesde-index`](https://github.com/daimond113/pesde-index). + +### `pesde config scripts-repo` + +```sh +pesde config scripts-repo [REPO] +``` + +Configures the scripts repository. If no repository is provided, the current +scripts repository is printed. + +- `-r, --reset`: Resets the scripts repository. + +The default scripts repository is [`pesde-scripts`](https://github.com/daimond113/pesde-scripts). + +## `pesde init` + +Initializes a new pesde project in the current directory. + +## `pesde run` + +Runs a script from the current project using Lune. + +```sh +pesde run [SCRIPT] [ -- ...] +``` + +If no script is provided, it will run the script specified by `target.bin` +in `pesde.toml`. + +If a path is provided, it will run the script at that path. + +If a script defined in `[scripts]` is provided, it will run that script. + +If a package name is provided, it will run the script specified by `target.bin` +in that package. + +Arguments can be passed to the script by using `--` followed by the arguments. + +```sh +pesde run foo -- --arg1 --arg2 +``` + +## `pesde install` + +Installs dependencies for the current project. + +- `-t, --threads`: The number of threads to use for downloading dependencies. +- `--locked`: Whether to error if the lockfile is out of date. +- `--prod`: Whether to skip installing dev dependencies. + +## `pesde publish` + +Publishes the current project to the pesde registry. + +- `-d, --dry-run`: Whether to perform a dry run. This will output a + tarball containing the package that would be published, but will not actually + publish it. +- `-y, --yes`: Whether to skip the confirmation prompt. + +## `pesde self-install` + +Performs the pesde installation process. This should be the first command run +after downloading the pesde binary. + +## `pesde self-upgrade` + +Upgrades the pesde binary to the latest version. + +## `pesde patch` + +```sh +pesde patch +``` + +Prepares a patching environment for a package. This will copy the source code of +the package to a temporary directory. + +The package specified must be in the format `@ `. + + + +## `pesde patch-commit` + +```sh +pesde patch-commit +``` + +Applies the changes made in the patching environment created by `pesde patch`. + +## `pesde add` + +```sh +pesde add +``` + +Adds a package to the dependencies of the current project. + +- `-i, --index `: The index in which to search for the package. +- `-t, --target `: The target environment for the package. +- `-a, --alias `: The alias to use for the package, defaults to the + package name. +- `-p, --peer`: Adds the package as a peer dependency. +- `-d, --dev`: Adds the package as a dev dependency. + +The following formats are supported: + +```sh +pesde add pesde/hello +pesde add gh#acme/package#main +pesde add https://git.acme.local/package.git#aeff6 +``` + +## `pesde update` + +Updates the dependencies of the current project. + +- `-t, --threads`: The number of threads to use for downloading dependencies. + +## `pesde x` + +Runs a one-off binary package. + +```sh +pesde x +``` + +This is useful for running a binary package without installing it or outside of +a pesde project. + +```sh +pesde x pesde/hello +``` diff --git a/docs/src/content/docs/reference/manifest.mdx b/docs/src/content/docs/reference/manifest.mdx new file mode 100644 index 0000000..9156e00 --- /dev/null +++ b/docs/src/content/docs/reference/manifest.mdx @@ -0,0 +1,405 @@ +--- +title: pesde.toml +description: Reference for `pesde.toml` +--- + +import { LinkCard } from "@astrojs/starlight/components" + +`pesde.toml` is the manifest file for a pesde package. It contains metadata about +the package and its dependencies. + +## Top-level fields + +```toml +name = "acme/package" +version = "1.2.3" +description = "A package that does foo and bar" +license = "MIT" +authors = ["John Doe (https://acme.local)"] +repository = "https://github.com/acme/package" +``` + +### `name` + +The name of the package. This is used to identify the package in the registry. + +The name consists of a scope and a package name, separated by a slash (`/`). It +may only contain lowercase letters, numbers, and underscores. + +The first one to publish to a given scope gets to own it. If you want multiple +people to be able to publish to the same scope, you can send a pull request to +the [pesde-index GitHub repository](https://github.com/daimond113/pesde-index) +and add the GitHub user ID of the other person to the `owners` field of the +`scope.toml` file of the given scope. For more information, see +[policies](/registry/policies#package-ownership). + +### `version` + +The version of the package. This must be a valid [SemVer](https://semver.org/) +version, such as `1.2.3`. + +### `description` + +A short description of the package. This is displayed on the package page in the +registry. + +### `license` + +The license of the package. It is recommended to use a +[SPDX license identifier](https://spdx.org/licenses/), such as `MIT` or +`Apache-2.0`. + +### `authors` + +A list of authors of the package. Each author is a string containing the name of +the author, optionally followed by an email address in angle brackets, and a +website URL in parentheses. For example: + +```toml +authors = ["John Doe (https://acme.local)"] +``` + +### `repository` + +The URL of the repository where the package is hosted. This is displayed on the +package page in the registry. + +### `private` + +A boolean indicating whether the package is private. If set to `true`, the +package cannot be published to the registry. + +### `includes` + +List of top-level files and directories to include in the package when +publishing. Files not listed here will not be published. + +```toml +includes = [ + "pesde.toml", + "README.md", + "LICENSE", + "init.luau", + "docs", +] +``` + +### `pesde_version` + +The version of pesde to use within this project. The `pesde` CLI will look at +this field and run the correct version of pesde for this project. + +### `workspace_members` + +A list of globs containing the members of this workspace. + + + + +## `[target]` + +The `[target]` section contains information about the target platform for the +package. + +```toml +[target] +environment = "luau" +lib = "init.luau" +``` + +### `environment` + +The target environment for the package. This can be one of the following: + +- `luau`: Standalone Luau code that can be run using the `luau` CLI. +- `lune`: Luau code that requires the Lune runtime. +- `roblox`: Luau code that must be run in Roblox. +- `roblox_server`: Same as `roblox`, but only for server-side code. + +### `lib` + +**Allowed in:** `luau`, `lune`, `roblox`, `roblox_server` + +The entry point of the library exported by the package. This file is what will +be required when the package is loaded using `require`. + +### `bin` + +**Allowed in:** `luau`, `lune` + +The entry point of the binary exported by the package. This file is what will be +run when the package is executed as a binary. + + + +### `build_files` + +**Allowed in:** `roblox`, `roblox_server` + +A list of files that should be synced to Roblox when the package is installed. + +```toml +build_files = [ + "init.luau", + "foo.luau", +] +``` + +These files are passed to [`roblox_sync_config_generator`](#roblox_sync_config_generator) +when the package is installed in order to generate the necessary configuration. + +## `[scripts]` + +The `[scripts]` section contains scripts that can be run using the `pesde run` +command. These scripts are run using [Lune](https://lune-org.github.io/docs). + +```toml +[scripts] +build = "sripts/build.luau" +test = "scripts/test.luau" +``` + +There are also a few special scripts that are run in certain cases by pesde. + +### `roblox_sync_config_generator` + +This is responsible for generating adequate configuration files for Roblox +sync tools. + +`process.args` will contain the directory containing the package, and the list +of files specified within the [`target.build_files`](#build_files) of the +package. + +You can find template scripts inside the +[`pesde-scripts` repository](https://github.com/daimond113/pesde-scripts) +for various sync tools. + + + + + +### `sourcemap_generator` + +This is responsible for generating source maps for packages that are installed. +This is required to get proper types support when using +[Wally dependencies](/guides/dependencies/#wally-dependencies). + +The script will receive the path to the package directory as the first argument +through `process.args`. + + + +## `[indices]` + +The `[indices]` section contains a list of pesde indices where packages can be +installed from. + +```toml +[indices] +default = "https://github.com/daimond113/pesde-index" +acme = "https://github.com/acme/pesde-index" +``` + +These can then be referenced in the [`dependencies`](#dependencies) of the +package. The `default` index is used if no index is specified. + +```toml +[dependencies] +foo = { name = "acme/foo", version = "1.2.3", index = "acme" } +``` + +## `[wally_indices]` + +The `[wally_indices]` section contains a list of Wally indices where packages +can be installed from. This is used for +[Wally dependencies](/guides/dependencies/#wally-dependencies). + +```toml +[wally_indices] +default = "https://github.com/UpliftGames/wally-index" +acme = "https://github.com/acme/wally-index" +``` + +These can then be referenced in the [`dependencies`](#dependencies) of the +package. The `default` index is used if no index is specified. + +```toml +[dependencies] +foo = { wally = "acme/foo", version = "1.2.3", index = "acme" } +``` + +## `[overrides]` + +The `[overrides]` section contains a list of overrides for dependencies. This +allows you to replace certain dependencies with different versions or even +different packages. + +```toml +[overrides] +"bar>baz" = { name = "acme/baz", version = "1.0.0" } +"foo>bar,baz>bar" = { name = "acme/bar", version = "2.0.0" } +``` + +The above example will replace the `baz` dependency of the `bar` package with +version `1.0.0`, and the `bar` and `baz` dependencies of the `foo` package with +version `2.0.0`. + +Each key in the overrides table is a comma-separated list of package paths. The +path is a list of package names separated by `>`. For example, `foo>bar>baz` +refers to the `baz` dependency of the `bar` package, which is a dependency of +the `foo` package. + + + +## `[patches]` + +The `[patches]` section contains a list of patches for dependencies. This allows +you to modify the source code of dependencies. + +```toml +[patches] +"acme/foo" = { "1.0.0 luau" = "patches/acme+foo-1.0.0+luau.patch" } +``` + +The above example will patch version `1.0.0` with the `luau` target of the +`acme/foo` package using the `patches/acme+foo-1.0.0+luau.patch` file. + +Each key in the patches table is the package name, and the value is a table +where the keys are the version and target, and the value is the path to the +patch. + +The patches can be generated using the `pesde patch` command. + + + +## `[place]` + +This is used in Roblox projects to specify where packages are located in the +Roblox datamodel. + +```toml +[place] +shared = "game.ReplicatedStorage.Packages" +server = "game.ServerScriptService.Packages" +``` + +## `[dependencies]` + +The `[dependencies]` section contains a list of dependencies for the package. + +```toml +[dependencies] +foo = { name = "acme/foo", version = "1.2.3" } +bar = { wally = "acme/bar", version = "2.3.4" } +baz = { git = "acme/baz", rev = "main" } +``` + +Each key in the dependencies table is the name of the dependency, and the value +is a dependency specifier. + +There are several types of dependency specifiers. + +### pesde + +```toml +[dependencies] +foo = { name = "acme/foo", version = "1.2.3", index = "acme", target = "lune" } +``` + +**pesde dependencies** contain the following fields: + +- `name`: The name of the package. +- `version`: The version of the package. +- `index`: The [pesde index](#indices) to install the package from. If not + specified, the `default` index is used. +- `target`: The target platform for the package. If not specified, the target + platform of the current package is used. + +### Wally + +```toml +[dependencies] +foo = { wally = "acme/foo", version = "1.2.3", index = "acme" } +``` + +**Wally dependencies** contain the following fields: + +- `wally`: The name of the package. +- `version`: The version of the package. +- `index`: The [Wally index](#wally_indices) to install the package from. If not + specified, the `default` index is used. + +### Git + +```toml +[dependencies] +foo = { git = "acme/packages", rev = "main", path = "foo" } +``` + +**Git dependencies** contain the following fields: + +- `git`: The URL of the Git repository. + This can either be `/` for a GitHub repository, or a full URL. +- `rev`: The Git revision to install. This can be a branch, tag, or commit hash. +- `path`: The path within the repository to install. If not specified, the root + of the repository is used. + +## `[peer_dependencies]` + +The `[peer_dependencies]` section contains a list of peer dependencies for the +package. These are dependencies that are required by the package, but are not +installed automatically. Instead, they must be installed by the user of the +package. + +```toml +[peer_dependencies] +foo = { name = "acme/foo", version = "1.2.3" } +``` + +## `[dev_dependencies]` + +The `[dev_dependencies]` section contains a list of development dependencies for +the package. These are dependencies that are only required during development, +such as testing libraries or build tools. They are not installed when the +package is used by another package. + +```toml +[dev_dependencies] +foo = { name = "acme/foo", version = "1.2.3" } +``` + +
+ + diff --git a/docs/src/content/docs/registry/policies.md b/docs/src/content/docs/registry/policies.md new file mode 100644 index 0000000..707d467 --- /dev/null +++ b/docs/src/content/docs/registry/policies.md @@ -0,0 +1,96 @@ +--- +title: Policies +description: Policies for the pesde registry +--- + +The following policies apply to the [official public pesde registry](https://registry.pesde.daimond113.com) +and its related services, such as the index repository or websites. +They may not apply to other registries. By using the pesde registry, you agree +to these policies. + +If anything is unclear, please [contact us](#contact-us), and we will be happy +to help. + +## Contact Us + +You can contact us at [pesde@daimond113.com](mailto:pesde@daimond113.com). In +case of a security issue, please prefix the subject with `[SECURITY]`. + +## Permitted content + +The pesde registry is a place for Luau-related packages. This includes: + +- Libraries +- Frameworks +- Tools + +The following content is forbidden: + +- Malicious, vulnerable code +- Illegal, harmful content +- Miscellaneous files (doesn't include configuration files, documentation, etc.) + +pesde is not responsible for the content of packages, the scope owner is. It +is the responsibility of the scope owner to ensure that the content of their +packages is compliant with the permitted content policy. + +If you believe a package is breaking these requirements, please [contact us](#contact-us). + +## Package removal + +pesde does not support removing packages for reasons such as abandonment. A +package may only be removed for the following reasons: + +- The package is breaking the permitted content policy +- The package contains security vulnerabilities +- The package must be removed for legal reasons (e.g. DMCA takedown) + +In case a secret has been published to the registry, it must be invalidated. +If you believe a package should be removed, please [contact us](#contact-us). +We will review your request and take action if necessary. + +If we find that a package is breaking the permitted content policy, we will +exercise our right to remove it from the registry without notice. + +pesde reserves the right to remove any package from the registry at any time for +any or no reason, without notice. + +## Package ownership + +Packages are owned by scopes. Scope ownership is determined by the first person +to publish a package to the scope. The owner of the scope may send a pull request +to the index repository adding team members' user IDs to the scope's `scope.toml` +file to give them access to the scope, however at least one package must be +published to the scope before this can be done. The owner may also remove team +members from the scope. + +A scope's true owner's ID must appear first in the `owners` field of the scope's +`scope.toml` file. Ownership may be transferred by the current owner sending a +pull request to the index repository, and the new owner confirming the transfer. + +Only the owner may add or remove team members from the scope. + +pesde reserves the right to override scope ownership in the case of a dispute, +such as if the original owner is unresponsive or multiple parties claim ownership. + +## Scope squatting + +Scope squatting is the act of creating a scope with the intent of preventing +others from using it, without any intention of using it yourself. This is +forbidden and can result in the removal (release) of the scope and its packages +from the registry without notice. + +If you believe a scope is being squatted, please [contact us](#contact-us). +We will review your request and take action if necessary. + +## API Usage + +The pesde registry has an API for querying, downloading, and publishing packages. +Only non-malicious use is permitted. Malicious uses include: + +- **Service Degradation**: this includes sending an excessive amount of requests + to the registry in order to degrade the service +- **Exploitation**: this includes trying to break the security of the registry + in order to gain unauthorized access +- **Harmful content**: this includes publishing harmful (non-law compliant, + purposefully insecure) content diff --git a/docs/src/env.d.ts b/docs/src/env.d.ts new file mode 100644 index 0000000..acef35f --- /dev/null +++ b/docs/src/env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/docs/src/tailwind.css b/docs/src/tailwind.css new file mode 100644 index 0000000..a5ca780 --- /dev/null +++ b/docs/src/tailwind.css @@ -0,0 +1,11 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root[data-theme="light"] { + --sl-color-bg: rgb(255 245 230); +} + +:root[data-theme="light"] .sidebar-pane { + background-color: var(--sl-color-bg); +} diff --git a/docs/tailwind.config.ts b/docs/tailwind.config.ts new file mode 100644 index 0000000..32bae0d --- /dev/null +++ b/docs/tailwind.config.ts @@ -0,0 +1,36 @@ +import starlightPlugin from "@astrojs/starlight-tailwind" +import type { Config } from "tailwindcss" +import defaultTheme from "tailwindcss/defaultTheme" + +export default { + content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"], + + theme: { + extend: { + fontFamily: { + sans: ["Nunito Sans Variable", ...defaultTheme.fontFamily.sans], + }, + colors: { + accent: { + 200: "rgb(241 157 30)", + 600: "rgb(120 70 10)", + 900: "rgb(24 16 8)", + 950: "rgb(10 7 4)", + }, + gray: { + 100: "rgb(245 230 210)", + 200: "rgb(228 212 192)", + 300: "rgb(198 167 140)", + 400: "rgb(142 128 112)", + 500: "rgb(84 70 50)", + 600: "rgb(65 50 41)", + 700: "rgb(50 42 35)", + 800: "rgb(28 22 17)", + 900: "rgb(10 7 4)", + }, + }, + }, + }, + + plugins: [starlightPlugin()], +} as Config diff --git a/docs/tsconfig.json b/docs/tsconfig.json new file mode 100644 index 0000000..a3f6981 --- /dev/null +++ b/docs/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "astro/tsconfigs/strict" +} diff --git a/registry/src/endpoints/publish_version.rs b/registry/src/endpoints/publish_version.rs index d6a38ab..043f5ff 100644 --- a/registry/src/endpoints/publish_version.rs +++ b/registry/src/endpoints/publish_version.rs @@ -61,7 +61,7 @@ const ADDITIONAL_FORBIDDEN_FILES: &[&str] = &["default.project.json"]; struct DocEntryInfo { #[serde(default)] label: Option, - #[serde(default)] + #[serde(default, alias = "position")] sidebar_position: Option, #[serde(default)] collapsed: bool, diff --git a/website/.gitignore b/website/.gitignore new file mode 100644 index 0000000..79518f7 --- /dev/null +++ b/website/.gitignore @@ -0,0 +1,21 @@ +node_modules + +# Output +.output +.vercel +/.svelte-kit +/build + +# OS +.DS_Store +Thumbs.db + +# Env +.env +.env.* +!.env.example +!.env.test + +# Vite +vite.config.js.timestamp-* +vite.config.ts.timestamp-* diff --git a/website/.npmrc b/website/.npmrc new file mode 100644 index 0000000..b6f27f1 --- /dev/null +++ b/website/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/website/.prettierignore b/website/.prettierignore new file mode 100644 index 0000000..ab78a95 --- /dev/null +++ b/website/.prettierignore @@ -0,0 +1,4 @@ +# Package Managers +package-lock.json +pnpm-lock.yaml +yarn.lock diff --git a/website/.prettierrc b/website/.prettierrc new file mode 100644 index 0000000..4ebb478 --- /dev/null +++ b/website/.prettierrc @@ -0,0 +1,14 @@ +{ + "useTabs": true, + "printWidth": 100, + "semi": false, + "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], + "overrides": [ + { + "files": "*.svelte", + "options": { + "parser": "svelte" + } + } + ] +} diff --git a/website/bun.lockb b/website/bun.lockb new file mode 100755 index 0000000..db992e7 Binary files /dev/null and b/website/bun.lockb differ diff --git a/website/eslint.config.js b/website/eslint.config.js new file mode 100644 index 0000000..b36887c --- /dev/null +++ b/website/eslint.config.js @@ -0,0 +1,33 @@ +import js from "@eslint/js" +import ts from "typescript-eslint" +import svelte from "eslint-plugin-svelte" +import prettier from "eslint-config-prettier" +import globals from "globals" + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + js.configs.recommended, + ...ts.configs.recommended, + ...svelte.configs["flat/recommended"], + prettier, + ...svelte.configs["flat/prettier"], + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + }, + }, + }, + { + files: ["**/*.svelte"], + languageOptions: { + parserOptions: { + parser: ts.parser, + }, + }, + }, + { + ignores: ["build/", ".svelte-kit/", "dist/"], + }, +] diff --git a/website/package.json b/website/package.json new file mode 100644 index 0000000..9a26eeb --- /dev/null +++ b/website/package.json @@ -0,0 +1,70 @@ +{ + "name": "website", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "lint": "prettier --check . && eslint .", + "format": "prettier --write ." + }, + "devDependencies": { + "@sveltejs/adapter-vercel": "^5.4.6", + "@sveltejs/kit": "^2.7.3", + "@sveltejs/vite-plugin-svelte": "^4.0.0", + "@tailwindcss/typography": "^0.5.15", + "@types/eslint": "^9.6.1", + "@types/gunzip-maybe": "^1.4.2", + "@types/tar-stream": "^3.1.3", + "autoprefixer": "^10.4.20", + "eslint": "^9.13.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-svelte": "^2.46.0", + "globals": "^15.11.0", + "mdsvex": "^0.12.3", + "prettier": "^3.3.3", + "prettier-plugin-svelte": "^3.2.7", + "prettier-plugin-tailwindcss": "^0.6.8", + "svelte": "^5.1.4", + "svelte-check": "^4.0.5", + "tailwindcss": "^3.4.14", + "typescript": "^5.6.3", + "typescript-eslint": "^8.12.2", + "vite": "^5.4.10" + }, + "type": "module", + "dependencies": { + "@fontsource-variable/nunito-sans": "^5.1.0", + "@shikijs/rehype": "^1.22.2", + "@types/hast": "^3.0.4", + "@types/unist": "^3.0.3", + "bits-ui": "next", + "date-fns": "^4.1.0", + "gunzip-maybe": "^1.4.2", + "hast-util-heading": "^3.0.0", + "hast-util-heading-rank": "^3.0.0", + "hast-util-to-text": "^4.0.2", + "lucide-svelte": "^0.446.0", + "rehype-infer-description-meta": "^2.0.0", + "rehype-raw": "^7.0.0", + "rehype-sanitize": "^6.0.0", + "rehype-slug": "^6.0.0", + "rehype-stringify": "^10.0.1", + "remark-frontmatter": "^5.0.0", + "remark-gemoji": "^8.0.0", + "remark-gfm": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.1", + "shiki": "^1.22.2", + "tar-stream": "^3.1.7", + "unified": "^11.0.5", + "unist-util-map": "^4.0.0", + "vfile": "^6.0.3" + }, + "patchedDependencies": { + "@shikijs/rehype@1.22.0": "patches/@shikijs%2Frehype@1.22.0.patch" + } +} diff --git a/website/patches/@shikijs%2Frehype@1.22.0.patch b/website/patches/@shikijs%2Frehype@1.22.0.patch new file mode 100644 index 0000000..a2e86a8 --- /dev/null +++ b/website/patches/@shikijs%2Frehype@1.22.0.patch @@ -0,0 +1,26 @@ +@shikis/rehype doesn't use the `fallbackLanguage` if `lazy` is used. + +--- a/dist/core.mjs ++++ b/dist/core.mjs +@@ -1,6 +1,8 @@ + import { visit } from 'unist-util-visit'; + import { toString } from 'hast-util-to-string'; + ++import { bundledLanguages } from 'shiki'; ++ + const InlineCodeHandlers = { + "tailing-curly-colon": (_tree, node) => { + const raw = toString(node); +@@ -90,8 +92,12 @@ function rehypeShikiFromHighlighter(highlighter, options) { + const languageQueue = []; + const queue = []; + function getLanguage(lang) { + if (!lang) + return defaultLanguage; ++ ++ if (!(lang in bundledLanguages)) ++ return fallbackLanguage; ++ + if (highlighter.getLoadedLanguages().includes(lang)) + return lang; + if (lazy) { diff --git a/website/postcss.config.js b/website/postcss.config.js new file mode 100644 index 0000000..1a52624 --- /dev/null +++ b/website/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/website/src/app.css b/website/src/app.css new file mode 100644 index 0000000..0883f6a --- /dev/null +++ b/website/src/app.css @@ -0,0 +1,92 @@ +@import "tailwindcss/base"; +@import "tailwindcss/components"; +@import "tailwindcss/utilities"; + +:root { + --color-background: 255 245 230; + --color-card: 245 230 210; + --color-card-hover: 240 225 205; + --color-border: 200 180 160; + --color-header: 250 234 215; + + --color-body: 84 70 50; + --color-heading: 70 55 35; + --color-light: 0 0 0; + + --color-input-bg: 245 230 210; + --color-input-border: 180 160 140; + --color-placeholder: 130 90 40; + + --color-primary: 120 70 10; + --color-primary-hover: 255 172 42; + --color-primary-bg: 241 157 30; + --color-primary-fg: 10 7 4; + + --shiki-foreground: rgb(var(--color-heading)); + --shiki-background: rgb(var(--color-card)); + --shiki-token-constant: color-mix(in srgb, rgb(120 140 230), rgb(var(--color-light)) 50%); + --shiki-token-string: rgb(var(--color-heading)); + --shiki-token-comment: rgb(var(--color-body)); + --shiki-token-keyword: color-mix(in srgb, rgb(var(--color-primary)), rgb(var(--color-light)) 50%); + --shiki-token-parameter: rgb(var(--color-heading)); + --shiki-token-function: rgb(var(--color-primary)); + --shiki-token-string-expression: color-mix( + in srgb, + rgb(120 230 140), + rgb(var(--color-light)) 50% + ); + --shiki-token-punctuation: rgb(var(--color-heading)); + --shiki-token-link: rgb(var(--color-primary)); +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: 10 7 4; + --color-card: 28 22 17; + --color-card-hover: 40 32 25; + --color-border: 28 22 17; + --color-header: 20 16 12; + + --color-body: 198 167 140; + --color-heading: 227 213 200; + --color-light: 255 255 255; + + --color-input-bg: 20 13 8; + --color-input-border: 78 60 40; + --color-placeholder: 169 147 128; + + --color-primary: 241 157 30; + --color-primary-hover: 255 172 42; + --color-primary-bg: 241 157 30; + --color-primary-fg: 10 7 4; + } +} + +html { + scroll-padding-top: theme(spacing.24); + color-scheme: light dark; +} + +body { + background-color: theme(colors.background); + color: theme(colors.body); +} + +@keyframes cursor-blink { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0; + } +} + +.hide-scrollbar::-webkit-scrollbar { + display: none; +} + +.hide-scrollbar { + -ms-overflow-style: none; + scrollbar-width: none; +} diff --git a/website/src/app.d.ts b/website/src/app.d.ts new file mode 100644 index 0000000..f70d0e1 --- /dev/null +++ b/website/src/app.d.ts @@ -0,0 +1,13 @@ +// See https://kit.svelte.dev/docs/types#app +// for information about these interfaces +declare global { + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } +} + +export {} diff --git a/website/src/app.html b/website/src/app.html new file mode 100644 index 0000000..77a5ff5 --- /dev/null +++ b/website/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/website/src/lib/components/GitHub.svelte b/website/src/lib/components/GitHub.svelte new file mode 100644 index 0000000..a808d35 --- /dev/null +++ b/website/src/lib/components/GitHub.svelte @@ -0,0 +1,11 @@ + + + + GitHub + + diff --git a/website/src/lib/components/Logo.svelte b/website/src/lib/components/Logo.svelte new file mode 100644 index 0000000..f333830 --- /dev/null +++ b/website/src/lib/components/Logo.svelte @@ -0,0 +1,23 @@ + + pesde + + + + + + diff --git a/website/src/lib/components/Logomark.svelte b/website/src/lib/components/Logomark.svelte new file mode 100644 index 0000000..21e8346 --- /dev/null +++ b/website/src/lib/components/Logomark.svelte @@ -0,0 +1,9 @@ + + pesde + + diff --git a/website/src/lib/components/Select.svelte b/website/src/lib/components/Select.svelte new file mode 100644 index 0000000..f593bff --- /dev/null +++ b/website/src/lib/components/Select.svelte @@ -0,0 +1,74 @@ + + + + + {#snippet child({ props })} + {#if trigger} + {@render trigger(props, triggerLabel)} + {:else} + + {/if} + {/snippet} + + + + {#each items as { value, label, disabled } (value)} + + {#snippet children({ selected })} + {label} + {#if selected} + + {/if} + {/snippet} + + {/each} + + + diff --git a/website/src/lib/markdown.ts b/website/src/lib/markdown.ts new file mode 100644 index 0000000..2cab9b2 --- /dev/null +++ b/website/src/lib/markdown.ts @@ -0,0 +1,116 @@ +import rehypeShikiFromHighlighter from "@shikijs/rehype/core" +import type { Nodes } from "hast" +import { heading } from "hast-util-heading" +import { headingRank } from "hast-util-heading-rank" +import { toText } from "hast-util-to-text" +import rehypeInferDescriptionMeta from "rehype-infer-description-meta" +import rehypeRaw from "rehype-raw" +import rehypeSanitize from "rehype-sanitize" +import rehypeSlug from "rehype-slug" +import rehypeStringify from "rehype-stringify" +import remarkFrontmatter from "remark-frontmatter" +import remarkGemoji from "remark-gemoji" +import remarkGfm from "remark-gfm" +import remarkParse from "remark-parse" +import remarkRehype from "remark-rehype" +import { createCssVariablesTheme, createHighlighter } from "shiki" +import { unified } from "unified" +import type { Node } from "unist" +import { map } from "unist-util-map" + +const highlighter = createHighlighter({ + themes: [], + langs: [], +}) + +export const markdown = (async () => { + return unified() + .use(remarkParse) + .use(remarkFrontmatter) + .use(remarkGfm) + .use(remarkGemoji) + .use(remarkRehype, { allowDangerousHtml: true }) + .use(rehypeRaw) + .use(rehypeSanitize) + .use(rehypeShikiFromHighlighter, await highlighter, { + lazy: true, + theme: createCssVariablesTheme({ + name: "css-variables", + variablePrefix: "--shiki-", + variableDefaults: {}, + fontStyle: true, + }), + fallbackLanguage: "text", + }) + .use(rehypeStringify) + .freeze() +})() + +export type TocItem = { + id: string + title: string + level: number +} + +export const docsMarkdown = (async () => { + return unified() + .use(remarkParse) + .use(remarkFrontmatter) + .use(remarkGfm) + .use(remarkGemoji) + .use(remarkRehype, { allowDangerousHtml: true, clobberPrefix: "" }) + .use(rehypeSlug) + .use(() => (node, file) => { + const toc: TocItem[] = [] + file.data.toc = toc + + return map(node as Nodes, (node) => { + if (node.type === "element" && node.tagName === "a") { + const fullUrl = new URL(node.properties.href as string, `file://${file.path}`) + + let href = node.properties.href as string + if (fullUrl.protocol === "file:") { + href = file.data.basePath + fullUrl.pathname.replace(/\.mdx?$/, "") + fullUrl.hash + } + + return { + ...node, + properties: { + ...node.properties, + href, + }, + } + } + + if (heading(node)) { + const rank = headingRank(node) + if (rank && typeof node.properties.id === "string" && rank >= 2 && rank <= 3) { + toc.push({ + id: node.properties.id, + title: toText(node), + level: rank, + }) + } + } + + return node + }) as Node + }) + .use(rehypeRaw) + .use(rehypeSanitize) + .use(rehypeShikiFromHighlighter, await highlighter, { + lazy: true, + theme: createCssVariablesTheme({ + name: "css-variables", + variablePrefix: "--shiki-", + variableDefaults: {}, + fontStyle: true, + }), + fallbackLanguage: "text", + }) + .use(rehypeInferDescriptionMeta, { + selector: "p", + }) + .use(rehypeStringify) + .freeze() +})() diff --git a/website/src/lib/registry-api.ts b/website/src/lib/registry-api.ts new file mode 100644 index 0000000..99900ae --- /dev/null +++ b/website/src/lib/registry-api.ts @@ -0,0 +1,106 @@ +import { PUBLIC_REGISTRY_URL } from "$env/static/public" + +export type SearchResponse = { + count: number + data: PackageResponse[] +} + +export type PackageVersionsResponse = PackageResponse[] + +export type PackageVersionResponse = PackageResponse + +export type PackageResponse = { + name: string + version: string + targets: TargetInfo[] + description: string + published_at: string + license?: string + authors?: string[] + repository?: string + dependencies: Record + docs?: DocEntry[] +} + +export type TargetInfo = { + kind: TargetKind + lib: boolean + bin: boolean +} + +export type TargetKind = "roblox" | "roblox_server" | "lune" | "luau" + +export type DependencyEntry = [DependencyInfo, DependencyKind] + +export type DependencyInfo = + | { + index: string + name: string + target?: string + version: string + } + | { + index: string + wally: string + version: string + } + +export type DependencyKind = "standard" | "peer" | "dev" + +export type DocEntry = DocEntryCategory | DocEntryPage + +export type DocEntryBase = { + label: string + position: number +} + +export type DocEntryCategory = DocEntryBase & { + items?: DocEntry[] + collapsed?: boolean +} + +export type DocEntryPage = DocEntryBase & { + name: string + hash: string +} + +export const TARGET_KIND_DISPLAY_NAMES: Record = { + roblox: "Roblox", + roblox_server: "Roblox (server)", + lune: "Lune", + luau: "Luau", +} + +export const DEPENDENCY_KIND_DISPLAY_NAMES: Record = { + standard: "Dependencies", + peer: "Peer Dependencies", + dev: "Dev Dependencies", +} + +export class RegistryHttpError extends Error { + name = "RegistryError" + constructor( + message: string, + public response: Response, + ) { + super(message) + } +} + +export async function fetchRegistryJson( + path: string, + fetcher: typeof fetch, + options?: RequestInit, +): Promise { + const response = await fetchRegistry(path, fetcher, options) + return response.json() +} + +export async function fetchRegistry(path: string, fetcher: typeof fetch, options?: RequestInit) { + const response = await fetcher(new URL(path, PUBLIC_REGISTRY_URL), options) + if (!response.ok) { + throw new RegistryHttpError(`Failed to fetch ${response.url}: ${response.statusText}`, response) + } + + return response +} diff --git a/website/src/routes/(app)/+error.svelte b/website/src/routes/(app)/+error.svelte new file mode 100644 index 0000000..99b3ae6 --- /dev/null +++ b/website/src/routes/(app)/+error.svelte @@ -0,0 +1,8 @@ + + +
+

{$page.status}

+

{$page.error?.message}

+
diff --git a/website/src/routes/(app)/+layout.svelte b/website/src/routes/(app)/+layout.svelte new file mode 100644 index 0000000..29c6736 --- /dev/null +++ b/website/src/routes/(app)/+layout.svelte @@ -0,0 +1,14 @@ + + +
+ +
+ {@render children()} +
+ +