| 1 | /** |
| 2 | * Words and links for a project that is a library or a tool rather than an |
| 3 | * app: which of its repository's packages to show, and how to publish a |
| 4 | * first one. Whether a project is one is decided by the projects service |
| 5 | * (`Project.kind`); this only says it on the pages. |
| 6 | */ |
| 7 | import type { DeploysSetting, Ecosystem, PackageSummary, ProjectEcosystem } from "@g1t/contracts"; |
| 8 | |
| 9 | /** As lib/packages.ts names each registry; repeated so this module stands alone in tests. */ |
| 10 | const REGISTRY: Record<Ecosystem, string> = { |
| 11 | container: "Container", |
| 12 | npm: "npm", |
| 13 | composer: "Composer", |
| 14 | cargo: "Cargo", |
| 15 | go: "Go", |
| 16 | maven: "Maven", |
| 17 | nuget: "NuGet", |
| 18 | rubygems: "RubyGems", |
| 19 | }; |
| 20 | |
| 21 | const DOCS = "https://docs.g1t.sh"; |
| 22 | |
| 23 | /** The choices for "Deployments for this project" in a project's settings. */ |
| 24 | export const DEPLOYS_CHOICES: { value: DeploysSetting; label: string; hint: string }[] = [ |
| 25 | { value: "auto", label: "Detect automatically", hint: "From whether Deployments are on, the packages it publishes and the files at its root." }, |
| 26 | { value: "yes", label: "Deploys", hint: "An app: its overview shows production, previews and domains." }, |
| 27 | { value: "no", label: "Doesn't deploy", hint: "A library or a tool: its overview shows its packages and releases, and offers no deploying." }, |
| 28 | ]; |
| 29 | |
| 30 | /** A registry's guide, and the command that publishes a first version there. */ |
| 31 | export type PublishGuide = { label: string; guide: string; start: string | null }; |
| 32 | |
| 33 | /** The registries with a guide, for a library whose files do not say which it is. */ |
| 34 | export const PUBLISH_GUIDES: PublishGuide[] = [ |
| 35 | { label: "Composer", guide: `${DOCS}/guides/composer/`, start: "git tag v1.0.0 && git push --tags" }, |
| 36 | { label: "npm", guide: `${DOCS}/guides/npm/`, start: "npm publish" }, |
| 37 | { label: "Go", guide: `${DOCS}/guides/go/`, start: "git tag v1.0.0 && git push --tags" }, |
| 38 | { label: "Containers", guide: `${DOCS}/guides/containers/`, start: null }, |
| 39 | ]; |
| 40 | |
| 41 | /** How a library of `ecosystem` publishes its first version; null when its files do not say. */ |
| 42 | export function publishGuide(ecosystem: ProjectEcosystem | null): PublishGuide | null { |
| 43 | switch (ecosystem) { |
| 44 | case "composer": |
| 45 | return PUBLISH_GUIDES[0]!; |
| 46 | case "npm": |
| 47 | return PUBLISH_GUIDES[1]!; |
| 48 | case "go": |
| 49 | return PUBLISH_GUIDES[2]!; |
| 50 | case "cargo": |
| 51 | return { label: "Cargo", guide: `${DOCS}/guides/packages/`, start: null }; |
| 52 | case "python": |
| 53 | return { label: "Python", guide: `${DOCS}/guides/packages/`, start: null }; |
| 54 | default: |
| 55 | return null; |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | /** A package as its own tool names it: `@acme/ui` for npm, the name otherwise. */ |
| 60 | export function packageName(pkg: Pick<PackageSummary, "ecosystem" | "name" | "workspace">): string { |
| 61 | return pkg.ecosystem === "npm" ? `@${pkg.workspace}/${pkg.name}` : pkg.name; |
| 62 | } |
| 63 | |
| 64 | /** `Composer · psr/log 3.0.2`, for a project's card. */ |
| 65 | export function packageLine(pkg: Pick<PackageSummary, "ecosystem" | "name" | "workspace" | "latest">): string { |
| 66 | return `${REGISTRY[pkg.ecosystem]} · ${packageName(pkg)}${pkg.latest ? ` ${pkg.latest}` : ""}`; |
| 67 | } |
| 68 | |
| 69 | /** The package's page. */ |
| 70 | export function packagePath(pkg: Pick<PackageSummary, "ecosystem" | "name" | "workspace">): string { |
| 71 | return `/${pkg.workspace}/-/packages/${pkg.ecosystem}/${pkg.name}`; |
| 72 | } |
| 73 | |
| 74 | /** |
| 75 | * The packages a library's overview shows, from its repository's: what it |
| 76 | * publishes for others to install first, a container image last, as an |
| 77 | * image is how apps ship too. |
| 78 | */ |
| 79 | export function libraryPackages<T extends Pick<PackageSummary, "ecosystem" | "versions" | "updated_at">>(list: T[]): T[] { |
| 80 | return [...list].sort( |
| 81 | (a, b) => |
| 82 | Number(a.ecosystem === "container") - Number(b.ecosystem === "container") || |
| 83 | Number(b.versions > 0) - Number(a.versions > 0) || |
| 84 | b.updated_at.localeCompare(a.updated_at), |
| 85 | ); |
| 86 | } |
| 87 | |
| 88 | /** Whether any of the packages has a version: a release is out. */ |
| 89 | export function hasRelease(list: Pick<PackageSummary, "versions">[]): boolean { |
| 90 | return list.some((pkg) => pkg.versions > 0); |
| 91 | } |