everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
1 lines • 9.92 kB
Source Map (JSON)
{"version":3,"file":"status.mjs","names":[],"sources":["../../src/cli/status.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { MISSING_CONFIG_MESSAGE, readAuthoredConfigInput } from \"../config\";\nimport type { StatusResult } from \"../contract\";\nimport { fetchBosConfigFromFastKv } from \"../fastkv\";\nimport { fetchJsonOrNull } from \"../http-client\";\nimport { readInstalledFrameworkVersion, resolveFrameworkPackage } from \"./framework-version\";\nimport { readSnapshot } from \"./snapshot\";\n\nconst FRAMEWORK_PACKAGES = [\"everything-dev\", \"every-plugin\"];\n\nconst CATALOG_TOOL_PACKAGES = [\n \"@rspack/core\",\n \"@rspack/cli\",\n \"@rsbuild/core\",\n \"@rsbuild/plugin-react\",\n \"@module-federation/enhanced\",\n \"@module-federation/node\",\n \"@module-federation/rsbuild-plugin\",\n \"@module-federation/runtime-core\",\n \"@module-federation/sdk\",\n \"@module-federation/dts-plugin\",\n] as const;\n\nconst PRERELEASE_PATTERN = /-[0-9A-Za-z.-]+$/;\n\n/**\n * The dist-tag to compare an installed version against: prerelease installs\n * track the `rc` dist-tag (the changesets pre-mode train), stable installs\n * track `latest`. Falls back to `latest` when no `rc` tag is published.\n */\nexport function resolveUpdateDistTag(installed: string | undefined): \"rc\" | \"latest\" {\n return installed && PRERELEASE_PATTERN.test(installed) ? \"rc\" : \"latest\";\n}\n\n/** The version a given dist-tag currently points at, or null when absent. */\nexport function pickDistTagVersion(\n distTags: Record<string, string> | undefined,\n tag: \"rc\" | \"latest\",\n): string | null {\n return distTags?.[tag] ?? null;\n}\n\nconst SEMVER_PATTERN =\n /^(?<core>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)(?:-(?<prerelease>[0-9A-Za-z.-]+))?(?:\\+[\\w.-]+)?$/;\n\ninterface ParsedVersion {\n core: readonly number[];\n prerelease: readonly (number | string)[];\n}\n\nfunction parseVersion(version: string | undefined): ParsedVersion | null {\n if (!version) return null;\n const match = SEMVER_PATTERN.exec(version.trim().replace(/^[\\^~>=v]+/, \"\"));\n if (!match?.groups) return null;\n const prerelease = match.groups.prerelease\n ? match.groups.prerelease.split(\".\").map((id) => (/^\\d+$/.test(id) ? Number(id) : id))\n : [];\n return {\n core: [Number(match.groups.core), Number(match.groups.minor), Number(match.groups.patch)],\n prerelease,\n };\n}\n\nfunction comparePrerelease(a: ParsedVersion[\"prerelease\"], b: ParsedVersion[\"prerelease\"]): number {\n if (a.length === 0 && b.length === 0) return 0;\n if (a.length === 0) return 1;\n if (b.length === 0) return -1;\n const length = Math.max(a.length, b.length);\n for (let i = 0; i < length; i += 1) {\n const left = a[i];\n const right = b[i];\n if (left === undefined) return -1;\n if (right === undefined) return 1;\n if (typeof left === \"number\" && typeof right === \"number\") {\n if (left !== right) return left < right ? -1 : 1;\n } else if (typeof left === \"number\") {\n return -1;\n } else if (typeof right === \"number\") {\n return 1;\n } else if (left !== right) {\n return left < right ? -1 : 1;\n }\n }\n return 0;\n}\n\n/**\n * Semver-ordered comparison of two version strings: -1 when `a` is older than\n * `b`, 1 when newer, 0 when equal. Unparseable versions compare as equal —\n * the update check must never fire on versions it cannot order (that is how\n * an install ahead of npm got flagged \"outdated\" with a downgrade arrow).\n */\nexport function compareSemver(a: string | undefined, b: string | undefined): number {\n const left = parseVersion(a);\n const right = parseVersion(b);\n if (!left || !right) return 0;\n for (let i = 0; i < left.core.length; i += 1) {\n if (left.core[i] !== right.core[i]) return left.core[i]! < right.core[i]! ? -1 : 1;\n }\n return comparePrerelease(left.prerelease, right.prerelease);\n}\n\nasync function fetchLatestNpmVersion(\n packageName: string,\n tag: \"rc\" | \"latest\",\n): Promise<string | null> {\n if (tag === \"latest\") {\n return fetchJsonOrNull<{ version: string }>(\n `https://registry.npmjs.org/${packageName}/latest`,\n {\n headers: { Accept: \"application/json\" },\n retries: 0,\n },\n ).then((data) => data?.version ?? null);\n }\n const packument = await fetchJsonOrNull<{ \"dist-tags\"?: Record<string, string> }>(\n `https://registry.npmjs.org/${packageName}`,\n {\n headers: { Accept: \"application/vnd.npm.install-v1+json\" },\n retries: 0,\n },\n );\n return pickDistTagVersion(packument?.[\"dist-tags\"], tag);\n}\n\nfunction readInstalledVersion(projectDir: string, packageName: string): string | undefined {\n return readInstalledFrameworkVersion(projectDir, packageName);\n}\n\nfunction checkEnvFile(projectDir: string): \"found\" | \"missing\" | \"example-only\" {\n if (existsSync(join(projectDir, \".env\"))) return \"found\";\n if (existsSync(join(projectDir, \".env.example\"))) return \"example-only\";\n return \"missing\";\n}\n\nasync function checkParentReachable(extendsRef: string | undefined): Promise<boolean | undefined> {\n if (!extendsRef?.startsWith(\"bos://\")) return undefined;\n try {\n const config = await fetchBosConfigFromFastKv(extendsRef);\n return config !== null;\n } catch {\n return false;\n }\n}\n\nexport async function getStatus(projectDir: string): Promise<StatusResult> {\n const authored = await readAuthoredConfigInput(projectDir);\n if (!authored) {\n return {\n status: \"error\",\n error: `${MISSING_CONFIG_MESSAGE} in current directory`,\n packages: [],\n envFile: \"missing\",\n };\n }\n\n const config = authored as Record<string, unknown>;\n\n const packageNames = [...FRAMEWORK_PACKAGES];\n for (const name of CATALOG_TOOL_PACKAGES) {\n if (readInstalledVersion(projectDir, name)) {\n packageNames.push(name);\n }\n }\n\n const packages = await Promise.all(\n packageNames.map(async (name) => {\n const resolved = resolveFrameworkPackage(projectDir, name);\n const tag = FRAMEWORK_PACKAGES.includes(name)\n ? resolveUpdateDistTag(resolved.installedVersion)\n : \"latest\";\n const latest = await fetchLatestNpmVersion(name, tag);\n return {\n name,\n installed: resolved.installedVersion,\n latest: latest ?? undefined,\n isLinked: resolved.isLinked,\n specifier: resolved.specifier,\n };\n }),\n );\n\n const snapshot = await readSnapshot(projectDir);\n\n const extendsRef = config.extends as string | undefined;\n const parentReachable = await checkParentReachable(extendsRef);\n\n return {\n status: \"ok\",\n extends: extendsRef,\n account: config.account as string | undefined,\n domain: config.domain as string | undefined,\n packages,\n lastSync: snapshot?.timestamp,\n envFile: checkEnvFile(projectDir),\n parentReachable,\n };\n}\n"],"mappings":"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"}