Skip to content

Commit

Permalink
feat: million cli (#572)
Browse files Browse the repository at this point in the history
  • Loading branch information
kunal00000 authored Sep 14, 2023
1 parent f1c71bb commit 2663218
Show file tree
Hide file tree
Showing 12 changed files with 1,038 additions and 3 deletions.
46 changes: 46 additions & 0 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## Million Setup Wizard

The Million Setup Wizard is a tool for configuring your project with million js.

## Usage

You can use the Million Setup Wizard:

```bash copy code
npx million@latest
```

This command will automatically detect your project's build environment and configure the Million.js settings accordingly.

## Features

- Automatically detects the build environment (Next.js, Vite, Webpack, etc.).
- Provides options to pick a compatible build tool if automatic detection fails.
- Creates or updates the Million.js configuration with auto mode options.
- Ensures compatibility with Next.js and detects the App router (RSC mode).

## Compatibility

The Million CLI is currently compatible with the following build tools:

- Next.js
- Gatsby
- Astro
- Vite
- Create-React-App
- Webpack
- Rollup

## Documentation

For detailed documentation and usage instructions, please refer to the official [Million Documentation](https://million.dev/docs/install).

## Troubleshooting

If you encounter any issues or need assistance, please visit the installation page in the Million Documentation for guidance.

If you feel there's some bugs or errors, please report them at [Report Bug](https://github.com/aidenybai/million/issues)

### License

This project is licensed under the MIT License - see the LICENSE.md file for details.
49 changes: 49 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"name": "million_setup_wizard",
"version": "0.0.1",
"description": "Million.js is an extremely fast and lightweight <4kb virtual DOM that makes React up to 70% faster. By using a fine-tuned, optimized virtual DOM, Million.js reduces the overhead of React.",
"keywords": [
"cli",
"million js",
"fast",
"react"
],
"main": "dist/index.js",
"repository": {
"type": "git",
"url": "https://github.com/aidenybai/million.git",
"directory": "packages/cli"
},
"homepage": "https://million.dev/",
"author": "Aiden Bai",
"bugs": "https://github.com/aidenybai/million/issues",
"license": "MIT",
"files": [
"README.md",
"dist"
],
"bin": {
"million": "./dist/index.js"
},
"dependencies": {
"@clack/prompts": "^0.7.0",
"chalk": "^5.3.0",
"diff": "^5.1.0",
"gradient-string": "^2.0.2"
},
"scripts": {
"prepare": "esbuild --bundle src/index.ts --platform=node --outfile=dist/index.js",
"link": "yarn unlink --global && chmod +x dist/index.js && yarn link",
"dev": "node ./dist/index.js",
"prepublishOnly": "pnpm run build",
"clean": "rm -r dist node_modules"
},
"devDependencies": {
"@types/diff": "^5.0.3",
"@types/gradient-string": "^1.1.2",
"@types/node": "^18.14.1",
"esbuild": "^0.14.54",
"prettier": "^2.8.4",
"typescript": "^5.1.6"
}
}
36 changes: 36 additions & 0 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#! /usr/bin/env node

import { intro, outro } from '@clack/prompts';
import chalk from 'chalk';
import gradient from 'gradient-string';
import { installPackage } from './utils/package-manager.js';
import { abort } from './utils/utils.js';
import { handleConfigFile } from './utils/config.js';
import { isPackageInstalled } from './utils/package-json.js';

async function runMillionWizard(): Promise<void> {
const isMillionAlreadyInstalled = await isPackageInstalled();
await installPackage({
packageName: 'million',
alreadyInstalled: isMillionAlreadyInstalled,
});
await handleConfigFile();
}

async function main() {
intro(showWelcomeScreen());
await runMillionWizard();
outro(`${chalk.bold.green('✓ ')} You're all set!`);
}

main().catch(() => {
abort(
'Failed to setup Million.js, refer to the docs for manual setup: https://million.dev/docs/install',
);
});

function showWelcomeScreen() {
const textGradient = gradient('#efa0a5', '#a788ec');
const text = `${chalk.bold(textGradient('Million.js'))}`;
return text;
}
21 changes: 21 additions & 0 deletions packages/cli/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export interface PackageDotJson {
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
}

export interface PackageManager {
name: string;
label: string;
lockFile: string;
installCommand: string;
}

export interface BuildTool {
name: string;
label: string;
bundler: string;
configFilePath: string;
possibleFileNames: string[];
configFileContent: string;
configFileContentRSC?: string;
}
101 changes: 101 additions & 0 deletions packages/cli/src/utils/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import * as fs from 'fs';
import * as path from 'path';
import * as clack from '@clack/prompts';
import chalk from 'chalk';
import { buildTools } from './constants';
import { modifyConfigFile } from './modify-config';
import { abortIfCancelled, getNextRouter } from './utils';
import type { BuildTool } from '../types';

export function detectBuildTool(): BuildTool | null {
/**
* Detect build tool by checking names of config files if they exist
*/
for (const buildTool of buildTools) {
for (const fileName of buildTool.possibleFileNames) {
/**
* Check for all extentions
*/
if (fs.existsSync(path.join(process.cwd(), fileName))) {
const currentbuildTool = { ...buildTool, configFilePath: fileName };
clack.log.success(
`Detected ${chalk.bold(currentbuildTool.name)} project.`,
);
return currentbuildTool;
}
}
}
// No build tool detected using config files
return null;
}

export async function getBuildTool(): Promise<BuildTool> {
/**
* Ask user to select a build tool
*/
const selectedBuildTool: BuildTool | symbol = await abortIfCancelled(
clack.select({
message: 'Please select your build tool.',
options: buildTools.map((buildTool) => ({
value: buildTool,
label: buildTool.label,
})),
}),
);

return selectedBuildTool;
}

export async function handleConfigFile(): Promise<void> {
// Create or Modify config file
const detectedBuildTool = detectBuildTool();

if (detectedBuildTool) {
// Modify existing config file
clack.note(
`found existing ${detectedBuildTool.configFilePath} file.`,
`Transforming ${chalk.cyan(detectedBuildTool.configFilePath)}`,
);
await modifyConfigFile(detectedBuildTool);
return;
}

/**
* Create a new config file
*/
const buildTool: BuildTool = await getBuildTool();

const targetFilePath = path.join(process.cwd(), buildTool.configFilePath);

if (buildTool.name === 'next') {
/**
* Create config file for 'next' project
* Check next router for rsc configuration (App router uses React Server Components)
*/
const nextRouter: 'app' | 'pages' = await getNextRouter();

clack.note(
`at ${chalk.green(targetFilePath)}`,
`Created ${chalk.green(buildTool.configFilePath)} file`,
);

nextRouter === 'app'
? await fs.promises.writeFile(
targetFilePath,
buildTool.configFileContentRSC!,
)
: await fs.promises.writeFile(
targetFilePath,
buildTool.configFileContent,
);
} else {
/**
* Create config file for build tools other than 'next'
*/
clack.note(
`at ${chalk.green(targetFilePath)}`,
`Created ${chalk.green(buildTool.configFilePath)} file`,
);
await fs.promises.writeFile(targetFilePath, buildTool.configFileContent);
}
}
Loading

2 comments on commit 2663218

@vercel
Copy link

@vercel vercel bot commented on 2663218 Sep 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

sink – ./packages/kitchen-sink

sink-git-main-millionjs.vercel.app
sink-millionjs.vercel.app
million-kitchen-sink-atit.vercel.app
sink.million.dev

@vercel
Copy link

@vercel vercel bot commented on 2663218 Sep 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

million-kitchen-sink – ./packages/kitchen-sink

million-kitchen-sink-git-main-millionjs.vercel.app
million-kitchen-sink.vercel.app
million-kitchen-sink-millionjs.vercel.app

Please sign in to comment.