diff --git a/packages/cli/src/getTasks.ts b/packages/cli/src/getTasks.ts index a1034fac62..1612f16f16 100644 --- a/packages/cli/src/getTasks.ts +++ b/packages/cli/src/getTasks.ts @@ -11,7 +11,7 @@ type Task = { dir: string; script: string; manifest: BaseManifest }; export async function getTaskList(taskNames: string[]): Promise { const packages: Package[] = []; - for await (const filePath of glob("{apps,packages}/*/package.json", { cwd })) { + for await (const filePath of glob(["package.json", "{apps,packages}/*/package.json"], { cwd })) { const absPath = join(cwd, filePath); const { default: manifest } = await import(absPath, { with: { type: "json" } }); packages.push({ rootDir: dirname(absPath), manifest }); @@ -29,7 +29,10 @@ export async function getTaskList(taskNames: string[]): Promise { dirs.flatMap(dir => taskNames.flatMap(task => { const manifest = graph[dir].package.manifest; - if (manifest?.scripts && task in manifest.scripts) return { dir, script: manifest.scripts[task], manifest }; + if (manifest?.scripts && task in manifest.scripts) { + const script = manifest.scripts[task]; + if (!script.includes("vite-plus")) return { dir, script, manifest }; + } return []; }) ) diff --git a/packages/cli/src/runTasks.ts b/packages/cli/src/runTasks.ts index b119f4dbc5..31d06615b6 100644 --- a/packages/cli/src/runTasks.ts +++ b/packages/cli/src/runTasks.ts @@ -2,6 +2,7 @@ import { join } from "node:path"; import { parseArgs } from "node:util"; import { multiplex, type Command } from "multiplexer"; import { getTaskList } from "./getTasks.ts"; +import { spawn } from "node:child_process"; export async function runTasks(): Promise { const { positionals } = parseArgs({ allowPositionals: true }); @@ -28,6 +29,9 @@ export async function runTasks(): Promise { ); } - multiplex(commands); + const all = commands.flat(); + if (all.length > 1) multiplex(commands); + else if (all.length === 1) spawn(all[0].cmd, all[0].args, { stdio: "inherit" }); + else console.error("404 Task Not Found"); } } diff --git a/packages/global/package.json b/packages/global/package.json index 28356219c3..ddd3679b70 100644 --- a/packages/global/package.json +++ b/packages/global/package.json @@ -20,5 +20,9 @@ }, "engines": { "node": ">=20.11.0" + }, + "dependencies": { + "@clack/core": "^0.5.0", + "@clack/prompts": "^0.11.0" } } diff --git a/packages/global/src/command/new.ts b/packages/global/src/command/new.ts index b82ad1a519..63b7001e79 100644 --- a/packages/global/src/command/new.ts +++ b/packages/global/src/command/new.ts @@ -1,11 +1,17 @@ -import { cp } from "node:fs/promises"; +import { cp, readdir } from "node:fs/promises"; import { join } from "node:path"; -export default async function copyTemplateFiles(targetDir: string) { - await copyFiles(targetDir); +const templatesDir = join(import.meta.dirname, "../../templates"); + +export async function getAvailableTemplates(): Promise { + const dirs = await readdir(templatesDir); + return dirs; +} + +export async function copyTemplateFiles(templateDir: string, targetDir: string): Promise { + await copyFiles(templateDir, targetDir); } -async function copyFiles(targetDir: string) { - const templateDir = join(import.meta.dirname, "../../template"); +async function copyFiles(templateDir: string, targetDir: string): Promise { await cp(templateDir, targetDir, { force: true, recursive: true }); } diff --git a/packages/global/src/command/tasks.ts b/packages/global/src/command/tasks.ts new file mode 100644 index 0000000000..898f60d8e3 --- /dev/null +++ b/packages/global/src/command/tasks.ts @@ -0,0 +1,70 @@ +import { join } from "node:path"; +import { spawn } from "node:child_process"; +import { intro, select, outro, text, confirm, tasks } from "@clack/prompts"; +import { getAvailableTemplates, copyTemplateFiles } from "./new.ts"; + +export const questionnaire = async (): Promise => { + intro("Let's create a new Vite+ project"); + + const availableTemplates = await getAvailableTemplates(); + + const targetDir = await text({ + message: "Where should we create your project?", + placeholder: "./", + initialValue: "./", + validate(value) { + if (!value || value.startsWith("..") || !value.startsWith(".")) return "Please enter a relative path"; + } + }); + + const isUseTypeScript = await select({ + message: "Do you plan to use TypeScript?", + options: [ + { value: "ts", label: "TypeScript" }, + { value: "js", label: "JavaScript with JSDoc" } + ] + }); + + const templateDir = await select({ + message: "Please choose a project template", + options: availableTemplates.map(template => ({ + value: template, + label: template + })) + }); + + const isInstallDependencies = await confirm({ + message: "Do you want to install dependencies?", + initialValue: true + }); + + const t = [ + { + title: "Copying template files", + task: async () => { + const sourceTemplateDir = join(import.meta.dirname, "../../templates", templateDir); + const targetDirPath = join(process.cwd(), targetDir); + await copyTemplateFiles(sourceTemplateDir, targetDirPath); + return "Copied template files"; + } + } + ]; + + if (isInstallDependencies) { + t.push({ + title: "Installing dependencies", + task: async () => { + await new Promise(resolve => { + const targetDirPath = join(process.cwd(), targetDir); + const p = spawn("pnpm", ["install"], { cwd: targetDirPath }); + p.on("exit", resolve); + }); + return "Installed dependencies using pnpm"; + } + }); + } + + await tasks(t); + + outro("Enjoy Vite+"); +}; diff --git a/packages/global/src/index.ts b/packages/global/src/index.ts index 00a3b3475a..f96207b826 100644 --- a/packages/global/src/index.ts +++ b/packages/global/src/index.ts @@ -1,17 +1,14 @@ -import { execFileSync } from "node:child_process"; import { parseArgs } from "node:util"; -import copyTemplateFiles from "./command/new.ts"; import { join } from "node:path"; +import { questionnaire } from "./command/tasks.ts"; try { const { positionals } = parseArgs({ allowPositionals: true }); - const [command, dir] = positionals; + const [command] = positionals; if (command === "new") { - const targetDir = dir ?? process.cwd(); - await copyTemplateFiles(targetDir); - execFileSync("pnpm", ["install"], { stdio: "inherit" }); + await questionnaire(); } else { const { default: main } = await import(join(process.cwd(), "node_modules/vite-plus/dist/index.js")); main(); diff --git a/packages/global/template/.npmrc b/packages/global/templates/minimal-js/.npmrc similarity index 100% rename from packages/global/template/.npmrc rename to packages/global/templates/minimal-js/.npmrc diff --git a/packages/global/templates/minimal-js/.oxlintrc.json b/packages/global/templates/minimal-js/.oxlintrc.json new file mode 100644 index 0000000000..d71deeeee8 --- /dev/null +++ b/packages/global/templates/minimal-js/.oxlintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "no-eval": "error" + } +} diff --git a/packages/global/template/apps/spa/index.html b/packages/global/templates/minimal-js/index.html similarity index 100% rename from packages/global/template/apps/spa/index.html rename to packages/global/templates/minimal-js/index.html diff --git a/packages/global/templates/minimal-js/package.json b/packages/global/templates/minimal-js/package.json new file mode 100644 index 0000000000..7205e075c2 --- /dev/null +++ b/packages/global/templates/minimal-js/package.json @@ -0,0 +1,29 @@ +{ + "name": "vite-plus-template-minimal-js", + "private": true, + "version": "0.0.0", + "type": "module", + "main": "src/index.js", + ".": { + "types": "dist/index.d.ts", + "default": "src/index.js" + }, + "scripts": { + "build": "tsc --build --verbose", + "dev": "vite", + "lint": "oxlint", + "all": "vite-plus task build lint" + }, + "dependencies": { + "vite": "^7.0.0" + }, + "devDependencies": { + "@types/node": "^24.0.4", + "multiplexer": "^0.0.0", + "oxlint": "^1.3.0", + "tsdown": "^0.12.8", + "typescript": "^5.8.3", + "vite-plus": "^0.0.0" + }, + "packageManager": "pnpm@10.12.1" +} diff --git a/packages/global/templates/minimal-js/src/index.js b/packages/global/templates/minimal-js/src/index.js new file mode 100644 index 0000000000..f651ac386a --- /dev/null +++ b/packages/global/templates/minimal-js/src/index.js @@ -0,0 +1,11 @@ +/** + * Greetings earthlings, we have not taken over your radiooooo 🎶 + * + * @param {string} name + * @returns {string} + */ +export const greet = name => { + return `Hello, ${name}!`; +}; + +console.log(greet("World")); diff --git a/packages/global/templates/minimal-js/tsconfig.json b/packages/global/templates/minimal-js/tsconfig.json new file mode 100644 index 0000000000..7efb1fe5a2 --- /dev/null +++ b/packages/global/templates/minimal-js/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "allowJs": true, + "allowSyntheticDefaultImports": true, + "checkJs": true, + "declaration": true, + "emitDeclarationOnly": true, + "lib": ["esnext", "dom", "dom.iterable"], + "module": "esnext", + "moduleResolution": "bundler", + "noEmitOnError": true, + "noErrorTruncation": true, + "outDir": "dist", + "resolveJsonModule": true, + "strict": true, + "target": "esnext", + "types": ["node"], + "verbatimModuleSyntax": true + }, + "include": ["src"] +} diff --git a/packages/global/templates/minimal/.npmrc b/packages/global/templates/minimal/.npmrc new file mode 100644 index 0000000000..83ffcad92e --- /dev/null +++ b/packages/global/templates/minimal/.npmrc @@ -0,0 +1,2 @@ +registry=http://localhost:4873 +//localhost:4873/:_authToken=fake diff --git a/packages/global/templates/minimal/index.html b/packages/global/templates/minimal/index.html new file mode 100644 index 0000000000..04819b329a --- /dev/null +++ b/packages/global/templates/minimal/index.html @@ -0,0 +1 @@ + diff --git a/packages/global/templates/minimal/package.json b/packages/global/templates/minimal/package.json new file mode 100644 index 0000000000..f17b529464 --- /dev/null +++ b/packages/global/templates/minimal/package.json @@ -0,0 +1,28 @@ +{ + "name": "vite-plus-template-minimal-js", + "private": true, + "version": "0.0.0", + "type": "module", + ".": { + "types": "dist/index.d.ts", + "default": "dist/index.js" + }, + "scripts": { + "build": "tsc --build --verbose", + "dev": "vite", + "lint": "oxlint", + "all": "vite-plus task build lint" + }, + "dependencies": { + "vite": "^7.0.0" + }, + "devDependencies": { + "@types/node": "^24.0.4", + "multiplexer": "^0.0.0", + "oxlint": "^1.3.0", + "tsdown": "^0.12.8", + "typescript": "^5.8.3", + "vite-plus": "^0.0.0" + }, + "packageManager": "pnpm@10.12.1" +} diff --git a/packages/global/templates/minimal/src/index.ts b/packages/global/templates/minimal/src/index.ts new file mode 100644 index 0000000000..a8141d3b18 --- /dev/null +++ b/packages/global/templates/minimal/src/index.ts @@ -0,0 +1 @@ +console.log("Hello, world!"); diff --git a/packages/global/templates/minimal/tsconfig.json b/packages/global/templates/minimal/tsconfig.json new file mode 100644 index 0000000000..0a4864cf93 --- /dev/null +++ b/packages/global/templates/minimal/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "lib": ["esnext", "dom", "dom.iterable"], + "module": "esnext", + "moduleResolution": "bundler", + "noEmitOnError": true, + "noErrorTruncation": true, + "outDir": "dist", + "resolveJsonModule": true, + "strict": true, + "target": "esnext", + "types": ["node"], + "verbatimModuleSyntax": true + }, + "include": ["src"] +} diff --git a/packages/global/template/.gitignore b/packages/global/templates/monorepo/.gitignore similarity index 100% rename from packages/global/template/.gitignore rename to packages/global/templates/monorepo/.gitignore diff --git a/packages/global/templates/monorepo/.npmrc b/packages/global/templates/monorepo/.npmrc new file mode 100644 index 0000000000..83ffcad92e --- /dev/null +++ b/packages/global/templates/monorepo/.npmrc @@ -0,0 +1,2 @@ +registry=http://localhost:4873 +//localhost:4873/:_authToken=fake diff --git a/packages/global/template/.oxlintrc.json b/packages/global/templates/monorepo/.oxlintrc.json similarity index 100% rename from packages/global/template/.oxlintrc.json rename to packages/global/templates/monorepo/.oxlintrc.json diff --git a/packages/global/template/apps/next/next.config.ts b/packages/global/templates/monorepo/apps/next/next.config.ts similarity index 100% rename from packages/global/template/apps/next/next.config.ts rename to packages/global/templates/monorepo/apps/next/next.config.ts diff --git a/packages/global/template/apps/next/package.json b/packages/global/templates/monorepo/apps/next/package.json similarity index 100% rename from packages/global/template/apps/next/package.json rename to packages/global/templates/monorepo/apps/next/package.json diff --git a/packages/global/template/apps/next/public/favicon.ico b/packages/global/templates/monorepo/apps/next/public/favicon.ico similarity index 100% rename from packages/global/template/apps/next/public/favicon.ico rename to packages/global/templates/monorepo/apps/next/public/favicon.ico diff --git a/packages/global/template/apps/next/src/app/layout.tsx b/packages/global/templates/monorepo/apps/next/src/app/layout.tsx similarity index 100% rename from packages/global/template/apps/next/src/app/layout.tsx rename to packages/global/templates/monorepo/apps/next/src/app/layout.tsx diff --git a/packages/global/template/apps/next/src/app/page.tsx b/packages/global/templates/monorepo/apps/next/src/app/page.tsx similarity index 100% rename from packages/global/template/apps/next/src/app/page.tsx rename to packages/global/templates/monorepo/apps/next/src/app/page.tsx diff --git a/packages/global/template/apps/next/tsconfig.json b/packages/global/templates/monorepo/apps/next/tsconfig.json similarity index 100% rename from packages/global/template/apps/next/tsconfig.json rename to packages/global/templates/monorepo/apps/next/tsconfig.json diff --git a/packages/global/templates/monorepo/apps/spa/index.html b/packages/global/templates/monorepo/apps/spa/index.html new file mode 100644 index 0000000000..d86d5c0891 --- /dev/null +++ b/packages/global/templates/monorepo/apps/spa/index.html @@ -0,0 +1 @@ + diff --git a/packages/global/template/apps/spa/package.json b/packages/global/templates/monorepo/apps/spa/package.json similarity index 100% rename from packages/global/template/apps/spa/package.json rename to packages/global/templates/monorepo/apps/spa/package.json diff --git a/packages/global/template/apps/spa/src/index.ts b/packages/global/templates/monorepo/apps/spa/src/index.ts similarity index 100% rename from packages/global/template/apps/spa/src/index.ts rename to packages/global/templates/monorepo/apps/spa/src/index.ts diff --git a/packages/global/template/apps/spa/vite.config.ts b/packages/global/templates/monorepo/apps/spa/vite.config.ts similarity index 100% rename from packages/global/template/apps/spa/vite.config.ts rename to packages/global/templates/monorepo/apps/spa/vite.config.ts diff --git a/packages/global/template/demo-countdown.sh b/packages/global/templates/monorepo/demo-countdown.sh similarity index 100% rename from packages/global/template/demo-countdown.sh rename to packages/global/templates/monorepo/demo-countdown.sh diff --git a/packages/global/template/demo-stream.sh b/packages/global/templates/monorepo/demo-stream.sh similarity index 100% rename from packages/global/template/demo-stream.sh rename to packages/global/templates/monorepo/demo-stream.sh diff --git a/packages/global/template/demo.ts b/packages/global/templates/monorepo/demo.ts similarity index 100% rename from packages/global/template/demo.ts rename to packages/global/templates/monorepo/demo.ts diff --git a/packages/global/template/demo2.ts b/packages/global/templates/monorepo/demo2.ts similarity index 100% rename from packages/global/template/demo2.ts rename to packages/global/templates/monorepo/demo2.ts diff --git a/packages/global/template/package.json b/packages/global/templates/monorepo/package.json similarity index 88% rename from packages/global/template/package.json rename to packages/global/templates/monorepo/package.json index 0cf171d323..641d901786 100644 --- a/packages/global/template/package.json +++ b/packages/global/templates/monorepo/package.json @@ -1,5 +1,5 @@ { - "name": "my-vite-plus-monorepo", + "name": "vite-plus-template-monorepo", "private": true, "version": "0.0.0", "type": "module", diff --git a/packages/global/template/packages/logger/.oxlintrc.json b/packages/global/templates/monorepo/packages/logger/.oxlintrc.json similarity index 100% rename from packages/global/template/packages/logger/.oxlintrc.json rename to packages/global/templates/monorepo/packages/logger/.oxlintrc.json diff --git a/packages/global/template/packages/logger/package.json b/packages/global/templates/monorepo/packages/logger/package.json similarity index 100% rename from packages/global/template/packages/logger/package.json rename to packages/global/templates/monorepo/packages/logger/package.json diff --git a/packages/global/template/packages/logger/src/index.ts b/packages/global/templates/monorepo/packages/logger/src/index.ts similarity index 100% rename from packages/global/template/packages/logger/src/index.ts rename to packages/global/templates/monorepo/packages/logger/src/index.ts diff --git a/packages/global/template/packages/logger/tests/log.spec.ts b/packages/global/templates/monorepo/packages/logger/tests/log.spec.ts similarity index 100% rename from packages/global/template/packages/logger/tests/log.spec.ts rename to packages/global/templates/monorepo/packages/logger/tests/log.spec.ts diff --git a/packages/global/template/packages/logger/tsconfig.json b/packages/global/templates/monorepo/packages/logger/tsconfig.json similarity index 100% rename from packages/global/template/packages/logger/tsconfig.json rename to packages/global/templates/monorepo/packages/logger/tsconfig.json diff --git a/packages/global/template/packages/logger/vite.config.ts b/packages/global/templates/monorepo/packages/logger/vite.config.ts similarity index 100% rename from packages/global/template/packages/logger/vite.config.ts rename to packages/global/templates/monorepo/packages/logger/vite.config.ts diff --git a/packages/global/template/pnpm-workspace.yaml b/packages/global/templates/monorepo/pnpm-workspace.yaml similarity index 100% rename from packages/global/template/pnpm-workspace.yaml rename to packages/global/templates/monorepo/pnpm-workspace.yaml diff --git a/packages/global/template/scripts/script1.ts b/packages/global/templates/monorepo/scripts/script1.ts similarity index 100% rename from packages/global/template/scripts/script1.ts rename to packages/global/templates/monorepo/scripts/script1.ts diff --git a/packages/global/template/tsconfig.json b/packages/global/templates/monorepo/tsconfig.json similarity index 100% rename from packages/global/template/tsconfig.json rename to packages/global/templates/monorepo/tsconfig.json diff --git a/packages/global/template/vite.config.ts b/packages/global/templates/monorepo/vite.config.ts similarity index 100% rename from packages/global/template/vite.config.ts rename to packages/global/templates/monorepo/vite.config.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index db3721b7c0..58ce8337fb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,13 @@ importers: version: 1000.6.0 packages/global: + dependencies: + '@clack/core': + specifier: ^0.5.0 + version: 0.5.0 + '@clack/prompts': + specifier: ^0.11.0 + version: 0.11.0 devDependencies: tsdown: specifier: ^0.12.1 @@ -201,6 +208,12 @@ packages: resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} engines: {node: '>=6.9.0'} + '@clack/core@0.5.0': + resolution: {integrity: sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==} + + '@clack/prompts@0.11.0': + resolution: {integrity: sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw==} + '@docsearch/css@3.8.2': resolution: {integrity: sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==} @@ -1908,6 +1921,9 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -2386,6 +2402,17 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 + '@clack/core@0.5.0': + dependencies: + picocolors: 1.1.1 + sisteransi: 1.0.5 + + '@clack/prompts@0.11.0': + dependencies: + '@clack/core': 0.5.0 + picocolors: 1.1.1 + sisteransi: 1.0.5 + '@docsearch/css@3.8.2': {} '@docsearch/css@3.9.0': {} @@ -3791,7 +3818,7 @@ snapshots: rfdc@1.4.1: {} - rolldown-plugin-dts@0.13.4(rolldown@1.0.0-beta.9)(typescript@5.8.3): + rolldown-plugin-dts@0.13.4(rolldown@1.0.0-beta.9(@oxc-project/runtime@0.71.0))(typescript@5.8.3): dependencies: '@babel/generator': 7.27.1 '@babel/parser': 7.27.2 @@ -3923,6 +3950,8 @@ snapshots: siginfo@2.0.0: {} + sisteransi@1.0.5: {} + source-map-js@1.2.1: {} space-separated-tokens@2.0.2: {} @@ -4000,7 +4029,7 @@ snapshots: empathic: 1.1.0 hookable: 5.5.3 rolldown: 1.0.0-beta.9(@oxc-project/runtime@0.71.0) - rolldown-plugin-dts: 0.13.4(rolldown@1.0.0-beta.9)(typescript@5.8.3) + rolldown-plugin-dts: 0.13.4(rolldown@1.0.0-beta.9(@oxc-project/runtime@0.71.0))(typescript@5.8.3) semver: 7.7.2 tinyexec: 1.0.1 tinyglobby: 0.2.13