g1t/apps/web/app/lib/packages.ts

83 lines3,107 bytesCodeBlame
1/**
2 * Words and commands for the Packages pages: sizes, digests, and how each
3 * registry's own tool logs in and installs.
4 */
5import type { Ecosystem, PackageSummary } from "@g1t/contracts";
6
7/** What each registry is called on the pages. */
8export const ECOSYSTEM_LABEL: Record<Ecosystem, string> = {
9 container: "Container",
10 npm: "npm",
11 composer: "Composer",
12 cargo: "Cargo",
13 go: "Go",
14};
15
16/** "0 B", "812 KB", "12.3 MB", "1.4 GB", in powers of 1,000 as registries show them. */
17export function formatBytes(bytes: number): string {
18 if (!Number.isFinite(bytes) || bytes <= 0) return "0 B";
19 const units = ["B", "KB", "MB", "GB", "TB"];
20 let value = bytes;
21 let unit = 0;
22 while (value >= 1000 && unit < units.length - 1) {
23 value /= 1000;
24 unit++;
25 }
26 const shown = unit === 0 || value >= 100 ? Math.round(value) : Number(value.toFixed(1));
27 return `${shown} ${units[unit]}`;
28}
29
30/** `sha256:3f2a…` shortened to `3f2a9c1b7d0e` for lists. */
31export function shortDigest(digest: string): string {
32 return digest.replace(/^sha256:/, "").slice(0, 12);
33}
34
35/** The host packages are published to and installed from. */
36export function registryHost(address: string): string {
37 return address.split("/")[0] || "g1t.sh";
38}
39
40/**
41 * How to log in and install `pkg` at `version` (a tag or version) with its
42 * tool. `you` stands in the username a login takes.
43 */
44export function installCommands(
45 pkg: Pick<PackageSummary, "ecosystem" | "address" | "name" | "workspace">,
46 version: string | null,
47 you: string,
48): { login: string; install: string; registry?: string } {
49 const host = registryHost(pkg.address);
50 switch (pkg.ecosystem) {
51 case "container":
52 return {
53 login: `docker login ${host} -u ${you}`,
54 install: `docker pull ${pkg.address}${version ? `:${version}` : ""}`,
55 };
56 case "npm":
57 // The scope's registry (in .npmrc, needed for any install), then the
58 // token a private package also needs.
59 return {
60 registry: `npm config set @${pkg.workspace}:registry=https://${host}/-/npm/`,
61 login: `npm config set //${host}/-/npm/:_authToken=YOUR_TOKEN`,
62 install: `npm install @${pkg.workspace}/${pkg.name}${version ? `@${version}` : ""}`,
63 };
64 case "composer":
65 // The workspace's repository (in composer.json, needed for any
66 // install), then the credentials a private package also needs.
67 return {
68 registry: `composer config repositories.${pkg.workspace} composer https://${host}/-/composer/${pkg.workspace}/`,
69 login: `composer config --global --auth http-basic.${host} ${you} YOUR_TOKEN`,
70 install: `composer require ${pkg.name}${version ? `:${version}` : ""}`,
71 };
72 case "cargo":
73 return {
74 login: `cargo login --registry ${pkg.workspace}`,
75 install: `cargo add ${pkg.name} --registry ${pkg.workspace}${version ? ` --vers ${version}` : ""}`,
76 };
77 case "go":
78 return {
79 login: `go env -w GOPRIVATE=${host}/${pkg.workspace}`,
80 install: `go get ${pkg.address}${version ? `@${version}` : ""}`,
81 };
82 }
83}