-
-
Notifications
You must be signed in to change notification settings - Fork 7
feat: make ATTW an optional dependency with auto-install prompt #107
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ export interface Options { | |
| root?: string; | ||
| pack?: PackType; | ||
| manifest?: string[]; | ||
| attw?: boolean; | ||
|
Contributor
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 is what i was trying to explain in discord the other day: we shouldn't be exposing any of this as "attw". we should have a feature to enable "type checking". right now we happen to use attw under the hood, but we may not in future. it shouldn't matter to the user
Contributor
Author
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.
|
||
| } | ||
|
|
||
| export interface StatLike<T> { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| import {createRequire} from 'node:module'; | ||
| import {spawn} from 'node:child_process'; | ||
| import {detect, resolveCommand} from 'package-manager-detector'; | ||
| import * as p from '@clack/prompts'; | ||
| import c from 'picocolors'; | ||
|
|
||
| const require = createRequire(import.meta.url); | ||
|
|
||
| /** | ||
| * Checks if a package is installed and can be imported | ||
| */ | ||
| export function isPackageInstalled(packageName: string): boolean { | ||
| try { | ||
| // Check only in current directory's node_modules, not parent directories | ||
| const {resolve} = require('node:path'); | ||
dreyfus92 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const localPath = resolve('./node_modules', packageName); | ||
| require.resolve(localPath); | ||
| return true; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Prompts the user to install a missing package | ||
| * Returns true if user wants to proceed with installation | ||
| */ | ||
| export async function promptToInstall(packageName: string): Promise<boolean> { | ||
| p.log.warn( | ||
| `${c.yellow('Optional dependency not found:')} ${c.bold(packageName)}` | ||
| ); | ||
| p.log.message(`This package is required for the feature you've enabled.`, { | ||
| spacing: 0 | ||
| }); | ||
|
|
||
| const shouldInstall = await p.confirm({ | ||
| message: `Would you like to install ${c.cyan(packageName)} now?` | ||
| }); | ||
|
|
||
| if (p.isCancel(shouldInstall)) { | ||
| return false; | ||
| } | ||
|
|
||
| return shouldInstall; | ||
| } | ||
|
|
||
| /** | ||
| * Automatically installs a package using the detected package manager | ||
| */ | ||
| export async function installPackage(packageName: string): Promise<boolean> { | ||
| const detected = await detect(); | ||
| const agent = detected?.agent || 'npm'; | ||
|
|
||
| const resolved = resolveCommand(agent, 'add', [packageName]); | ||
|
|
||
| if (!resolved) { | ||
| p.log.error(`Failed to resolve install command for ${c.cyan(agent)}`); | ||
| return false; | ||
| } | ||
|
|
||
| p.log.info(`Installing ${c.cyan(packageName)} with ${c.cyan(agent)}...`); | ||
|
|
||
| return new Promise((resolve) => { | ||
| const child = spawn(resolved.command, resolved.args, { | ||
| stdio: 'inherit', | ||
| cwd: process.cwd() | ||
| }); | ||
|
|
||
| child.on('close', (code) => { | ||
| if (code === 0) { | ||
| p.log.success(`Successfully installed ${c.cyan(packageName)}!`); | ||
| resolve(true); | ||
| } else { | ||
| p.log.error(`Failed to install ${c.cyan(packageName)}`); | ||
| resolve(false); | ||
| } | ||
| }); | ||
| }); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.