Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| A project is an app or a library: libraries show their package and how to ship a release, not production | 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 | } |