-
-
Notifications
You must be signed in to change notification settings - Fork 126
Verify runtime version in fedify init
#981
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
59bd37e
d3dedb8
c4cdc1c
4e86690
dd6dc78
af665c1
1dd33c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| - Added runtime version verification to `fedify init`. It checks that the | ||
| selected Deno, Bun, or Node.js meets Fedify's minimum version, or a higher | ||
| version required by a framework (such as Astro's Node.js 22.12), before | ||
| generating a project. A missing, malformed, or unsupported runtime now | ||
| produces a clear error in non-interactive mode and disables the affected | ||
| package managers in interactive mode. [[#964], [#981] by Lee Jeongmin] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,27 @@ | ||
| import { pipe, when } from "@fxts/core"; | ||
| import { select } from "@inquirer/prompts"; | ||
| import { message } from "@optique/core/message"; | ||
| import { message, optionName, text } from "@optique/core/message"; | ||
| import { print } from "@optique/run"; | ||
| import process from "node:process"; | ||
| import { PACKAGE_MANAGER } from "../const.ts"; | ||
| import { | ||
| checkAllRuntimes, | ||
| getInstallUrl, | ||
| isPackageManagerAvailable, | ||
| kvStores, | ||
| messageQueues, | ||
| packageManagers, | ||
| runtimes, | ||
| } from "../lib.ts"; | ||
| import type { PackageManager, WebFramework } from "../types.ts"; | ||
| import type { | ||
| PackageManager, | ||
| Runtime, | ||
| RuntimeCheck, | ||
| WebFramework, | ||
| } from "../types.ts"; | ||
| import { printErrorMessage } from "../utils.ts"; | ||
| import webFrameworks from "../webframeworks/mod.ts"; | ||
| import { pmToRt } from "../webframeworks/utils.ts"; | ||
|
|
||
| /** | ||
| * Fills in the package manager by prompting the user if not provided. | ||
|
|
@@ -27,30 +36,73 @@ const fillPackageManager: // | |
| (options: T) => // | ||
| Promise<Omit<T, "packageManager"> & { packageManager: PackageManager }> = // | ||
| async ({ packageManager, ...options }) => { | ||
| const pm = packageManager ?? await askPackageManager(options.webFramework); | ||
| if (await isPackageManagerAvailable(pm)) { | ||
| const choices = await calculateChoices(options.webFramework); | ||
| if (packageManager != null) { | ||
| const pm = packageManager; | ||
| const choice = choices.find(({ value }) => value === pm)!; | ||
| if (choice.disabled != null) { | ||
| print(message`${optionName(choice.name)} ${text(choice.disabled)}`); | ||
| process.exit(1); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this exit is unnecessary because we can ask again with |
||
| } | ||
| if (!await isPackageManagerAvailable(pm)) { | ||
| noticeInstallUrl(pm); | ||
| process.exit(1); | ||
| } | ||
|
Comment on lines
+47
to
+50
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This branch doesn't seem necessary because the available PMs are tested in |
||
| return ({ ...options, packageManager: pm }); | ||
| } | ||
| noticeInstallUrl(pm); | ||
| return await fillPackageManager(options) as // | ||
| typeof options & { packageManager: PackageManager }; | ||
| while (true) { | ||
| const pm = await askPackageManager(choices); | ||
| if (await isPackageManagerAvailable(pm)) { | ||
| return ({ ...options, packageManager: pm }); | ||
| } | ||
| noticeInstallUrl(pm); | ||
| } | ||
|
Comment on lines
+53
to
+59
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Like what I said at above, |
||
| }; | ||
|
|
||
| export default fillPackageManager; | ||
|
|
||
| const askPackageManager = (wf: WebFramework) => | ||
| const calculateChoices = async (wf: WebFramework) => { | ||
| const runtimeChecks = await checkAllRuntimes( | ||
| webFrameworks[wf].minRuntimeVersions, | ||
| ); | ||
| const choices = PACKAGE_MANAGER.map(choicePackageManager(wf, runtimeChecks)); | ||
| if (choices.every((choice) => choice.disabled)) { | ||
| printErrorMessage`No package manager with a supported runtime is available for ${ | ||
| webFrameworks[wf].label | ||
| }.`; | ||
| process.exit(1); | ||
| } | ||
|
userjmmm marked this conversation as resolved.
|
||
| return choices; | ||
| }; | ||
|
|
||
| const askPackageManager = ( | ||
| choices: Awaited<ReturnType<typeof calculateChoices>>, | ||
| ) => | ||
| select<PackageManager>({ | ||
| message: "Choose the package manager to use", | ||
| choices: PACKAGE_MANAGER.map(choicePackageManager(wf)), | ||
| choices, | ||
| }); | ||
|
|
||
| const choicePackageManager = (wf: WebFramework) => (value: PackageManager) => ({ | ||
| name: isWfSupportsPm(wf, value) | ||
| ? value | ||
| : `${value} (not supported with ${webFrameworks[wf].label})`, | ||
| value, | ||
| disabled: !isWfSupportsPm(wf, value), | ||
| }); | ||
| const choicePackageManager = | ||
| (wf: WebFramework, runtimeChecks: Record<Runtime, RuntimeCheck>) => | ||
| (value: PackageManager) => { | ||
| const check = runtimeChecks[pmToRt(value)]; | ||
| const label = runtimes[pmToRt(value)].label; | ||
| const disabled = !isWfSupportsPm(wf, value) | ||
| ? `not supported with ${webFrameworks[wf].label}` | ||
| : check.status === "unsupported" | ||
| ? `requires ${label} ${check.required} or later` | ||
| : check.status === "missing" | ||
| ? `requires ${label} which is not installed` | ||
| : check.status === "malformed" | ||
| ? `could not detect ${label} version` | ||
| : ""; | ||
| return disabled === "" ? { name: value, value } : { | ||
| name: value, | ||
| value, | ||
| disabled, | ||
| }; | ||
| }; | ||
|
|
||
| const isWfSupportsPm = ( | ||
| wf: WebFramework, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This definition seems unnecessary.