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