create-idp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +205 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +702 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +46 -0
  7. package/templates/empty/README.md +3 -0
  8. package/templates/empty/_gitignore +6 -0
  9. package/templates/empty/_template.json +6 -0
  10. package/templates/node-ts/README.md +21 -0
  11. package/templates/node-ts/_gitignore +7 -0
  12. package/templates/node-ts/_template.json +16 -0
  13. package/templates/node-ts/package.json +19 -0
  14. package/templates/node-ts/src/index.ts +1 -0
  15. package/templates/node-ts/tsconfig.json +17 -0
  16. package/templates/node-ts/tsup.config.ts +9 -0
  17. package/templates/python-uv/README.md +22 -0
  18. package/templates/python-uv/_gitignore +30 -0
  19. package/templates/python-uv/_template.json +14 -0
  20. package/templates/python-uv/pyproject.toml +20 -0
  21. package/templates/python-uv/src/project_name/__init__.py +10 -0
  22. package/templates/python-uv/src/project_name/__main__.py +4 -0
  23. package/templates/react-ts/_gitignore +6 -0
  24. package/templates/react-ts/_template.json +13 -0
  25. package/templates/react-ts/index.html +13 -0
  26. package/templates/react-ts/package.json +23 -0
  27. package/templates/react-ts/src/App.css +14 -0
  28. package/templates/react-ts/src/App.tsx +12 -0
  29. package/templates/react-ts/src/index.css +11 -0
  30. package/templates/react-ts/src/main.tsx +10 -0
  31. package/templates/react-ts/tsconfig.json +20 -0
  32. package/templates/react-ts/vite.config.ts +6 -0
  33. package/templates/template.config.json +34 -0
  34. package/templates/vue-ts/_gitignore +6 -0
  35. package/templates/vue-ts/_template.json +13 -0
  36. package/templates/vue-ts/index.html +13 -0
  37. package/templates/vue-ts/package.json +20 -0
  38. package/templates/vue-ts/src/App.vue +37 -0
  39. package/templates/vue-ts/src/main.ts +5 -0
  40. package/templates/vue-ts/src/style.css +11 -0
  41. package/templates/vue-ts/src/vite-env.d.ts +7 -0
  42. package/templates/vue-ts/tsconfig.json +20 -0
  43. package/templates/vue-ts/vite.config.ts +6 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../package.json","../src/prompts.ts","../src/utils.ts","../src/scaffold.ts","../src/git.ts","../src/config.ts","../src/github-api.ts","../src/post-init.ts","../src/update-check.ts","../src/github-setup.ts","../src/index.ts"],"sourcesContent":["import { Command } from 'commander'\nimport pc from 'picocolors'\nimport { version } from '../package.json'\nimport { runPrompts } from './prompts.js'\nimport { scaffoldProject } from './scaffold.js'\nimport { initGit, createGithubRepo } from './git.js'\nimport { runPostInit } from './post-init.js'\nimport { loadConfig, getConfigPath } from './config.js'\nimport { checkForUpdates } from './update-check.js'\nimport { runGitHubSetup, showConfig } from './github-setup.js'\nimport type { CliOptions, ProjectOptions } from './types.js'\n\nexport async function createCli(): Promise<Command> {\n const program = new Command()\n\n program\n .name('create-idp')\n .description('CLI 脚手架工具,快速创建项目并可选初始化 GitHub 仓库')\n .version(version)\n .argument('[project-name]', '项目名称')\n .option('-t, --template <template>', '使用指定模板')\n .option('--github', '在 GitHub 创建远程仓库')\n .option('--public', '创建公开仓库 (默认私有)')\n .option('--no-git', '跳过 Git 初始化')\n .option('--no-install', '跳过依赖安装')\n .action(async (projectName: string | undefined, options: CliOptions) => {\n console.log()\n console.log(` ${pc.cyan('create-idp')} ${pc.dim(`v${version}`)}`)\n console.log()\n\n // 异步检查更新(不阻塞主流程)\n checkForUpdates(version).catch(() => {})\n\n // 加载用户配置\n const userConfig = loadConfig()\n\n try {\n const projectOptions = await runPrompts(projectName, options, userConfig)\n await executeProject(projectOptions)\n } catch (err) {\n if ((err as Error).message === 'PROMPT_CANCELLED') {\n console.log(pc.yellow('\\n操作已取消'))\n process.exit(0)\n }\n throw err\n }\n })\n\n // config 子命令\n program\n .command('config')\n .description('管理配置')\n .option('--setup-github', '配置 GitHub Token')\n .option('--show', '显示当前配置')\n .option('--path', '显示配置文件路径')\n .action(async (options: { setupGithub?: boolean; show?: boolean; path?: boolean }) => {\n if (options.setupGithub) {\n const success = await runGitHubSetup()\n process.exit(success ? 0 : 1)\n } else if (options.show) {\n showConfig()\n } else if (options.path) {\n console.log(getConfigPath())\n } else {\n // 默认显示帮助\n console.log()\n console.log(pc.cyan('配置管理命令:'))\n console.log()\n console.log(` ${pc.dim('create-idp config --setup-github')} 配置 GitHub Token`)\n console.log(` ${pc.dim('create-idp config --show')} 显示当前配置`)\n console.log(` ${pc.dim('create-idp config --path')} 显示配置文件路径`)\n console.log()\n }\n })\n\n return program\n}\n\nasync function executeProject(options: ProjectOptions): Promise<void> {\n const templateConfig = await scaffoldProject(options)\n console.log(pc.green('✔ 项目文件已生成'))\n\n if (!options.noInstall && templateConfig?.postInit) {\n await runPostInit(options.targetDir, templateConfig.postInit)\n console.log(pc.green('✔ 依赖安装完成'))\n }\n\n if (options.initGit) {\n await initGit(options.targetDir)\n console.log(pc.green('✔ Git 仓库已初始化'))\n }\n\n if (options.createGithub) {\n const repoUrl = await createGithubRepo(\n options.projectName,\n options.targetDir,\n options.isPublic\n )\n if (repoUrl) {\n console.log(pc.green(`✔ GitHub 仓库已创建: ${pc.cyan(repoUrl)}`))\n }\n }\n\n console.log()\n const pm = templateConfig?.packageManager ?? 'pnpm'\n const cdCmd = options.targetDir !== process.cwd()\n ? `cd ${options.projectName} && `\n : ''\n console.log(pc.dim(` ${cdCmd}${pm} dev`))\n console.log()\n}\n","{\n \"name\": \"create-idp\",\n \"version\": \"0.1.0\",\n \"description\": \"CLI 脚手架工具,快速创建项目并可选初始化 GitHub 仓库\",\n \"type\": \"module\",\n \"bin\": {\n \"create-idp\": \"./dist/index.js\"\n },\n \"files\": [\n \"dist\",\n \"templates\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest\",\n \"test:run\": \"vitest run\",\n \"prepublishOnly\": \"pnpm build\"\n },\n \"keywords\": [\n \"cli\",\n \"scaffold\",\n \"create\",\n \"idp\",\n \"template\",\n \"generator\"\n ],\n \"author\": \"\",\n \"license\": \"MIT\",\n \"devDependencies\": {\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/node\": \"^22.10.7\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.3\",\n \"vitest\": \"^3.0.4\"\n },\n \"dependencies\": {\n \"@inquirer/prompts\": \"^7.2.1\",\n \"commander\": \"^13.0.0\",\n \"fs-extra\": \"^11.2.0\",\n \"picocolors\": \"^1.1.1\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n}\n","import path from 'node:path'\nimport fs from 'node:fs'\nimport { input, select, confirm } from '@inquirer/prompts'\nimport pc from 'picocolors'\nimport { getTemplatesDir, isValidPackageName, toValidPackageName, isEmpty } from './utils.js'\nimport type { CliOptions, ProjectOptions, TemplateRegistry, UserConfig } from './types.js'\n\nexport async function runPrompts(\n argProjectName: string | undefined,\n options: CliOptions,\n userConfig: UserConfig = {}\n): Promise<ProjectOptions> {\n const defaults = userConfig.defaults ?? {}\n const templatesDir = getTemplatesDir()\n const registryPath = path.join(templatesDir, 'template.config.json')\n const registry: TemplateRegistry = JSON.parse(\n fs.readFileSync(registryPath, 'utf-8')\n )\n\n let projectName = argProjectName\n\n if (!projectName) {\n projectName = await input({\n message: '项目名称:',\n default: 'my-project',\n validate: (value) => {\n if (!value.trim()) {\n return '项目名称不能为空'\n }\n if (!isValidPackageName(toValidPackageName(value))) {\n return '无效的项目名称'\n }\n return true\n }\n })\n }\n\n const validName = toValidPackageName(projectName)\n const targetDir = path.resolve(process.cwd(), validName)\n\n if (fs.existsSync(targetDir) && !isEmpty(targetDir)) {\n const overwrite = await confirm({\n message: `目标目录 \"${validName}\" 非空,是否继续? (将覆盖已有文件)`,\n default: false\n })\n if (!overwrite) {\n const error = new Error('PROMPT_CANCELLED')\n throw error\n }\n }\n\n let template = options.template\n if (!template) {\n // 配置文件中的默认模板\n const defaultTemplate = defaults.template\n const templateChoices = registry.templates.map((t) => ({\n name: `${t.displayName} ${pc.dim(`- ${t.description}`)}`,\n value: t.name\n }))\n\n template = await select({\n message: '选择模板:',\n choices: templateChoices,\n default: defaultTemplate && registry.templates.some((t) => t.name === defaultTemplate)\n ? defaultTemplate\n : undefined\n })\n } else {\n const found = registry.templates.find((t) => t.name === template)\n if (!found) {\n console.log(pc.red(`错误: 未找到模板 \"${template}\"`))\n console.log(pc.dim(`可用模板: ${registry.templates.map((t) => t.name).join(', ')}`))\n process.exit(1)\n }\n }\n\n let initGit = options.git !== false\n if (options.git === undefined) {\n initGit = await confirm({\n message: '初始化 Git 仓库?',\n default: true\n })\n }\n\n let createGithub = options.github ?? false\n if (initGit && options.github === undefined) {\n createGithub = await confirm({\n message: '在 GitHub 创建远程仓库?',\n default: defaults.github ?? false\n })\n }\n\n let isPublic = options.public ?? false\n if (createGithub && options.public === undefined) {\n const publicDefault = defaults.public ?? false\n isPublic = await select({\n message: '仓库可见性:',\n choices: [\n { name: 'private (私有)', value: false },\n { name: 'public (公开)', value: true }\n ],\n default: publicDefault\n }) as boolean\n }\n\n return {\n projectName: validName,\n template,\n targetDir,\n initGit,\n createGithub,\n isPublic,\n noInstall: options.install === false\n }\n}\n","import path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { spawn } from 'node:child_process'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\nexport function getTemplatesDir(): string {\n return path.resolve(__dirname, '..', 'templates')\n}\n\nexport function isValidPackageName(name: string): boolean {\n return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name)\n}\n\nexport function toValidPackageName(name: string): string {\n return name\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/^[._]/, '')\n .replace(/[^a-z0-9-~]+/g, '-')\n}\n\nexport function isEmpty(dirPath: string): boolean {\n const fs = require('node:fs')\n if (!fs.existsSync(dirPath)) {\n return true\n }\n const files = fs.readdirSync(dirPath)\n return files.length === 0 || (files.length === 1 && files[0] === '.git')\n}\n\nexport function execAsync(\n command: string,\n args: string[],\n options: { cwd?: string; stdio?: 'inherit' | 'pipe' } = {}\n): Promise<{ code: number; stdout: string; stderr: string }> {\n return new Promise((resolve) => {\n const proc = spawn(command, args, {\n cwd: options.cwd,\n stdio: options.stdio === 'inherit' ? 'inherit' : 'pipe',\n shell: true\n })\n\n let stdout = ''\n let stderr = ''\n\n if (proc.stdout) {\n proc.stdout.on('data', (data) => {\n stdout += data.toString()\n })\n }\n\n if (proc.stderr) {\n proc.stderr.on('data', (data) => {\n stderr += data.toString()\n })\n }\n\n proc.on('close', (code) => {\n resolve({ code: code ?? 1, stdout, stderr })\n })\n\n proc.on('error', () => {\n resolve({ code: 1, stdout, stderr })\n })\n })\n}\n\nexport async function commandExists(command: string): Promise<boolean> {\n const result = await execAsync('which', [command])\n return result.code === 0\n}\n","import path from 'node:path'\nimport fs from 'fs-extra'\nimport { getTemplatesDir } from './utils.js'\nimport type { ProjectOptions, TemplateConfig, TemplateRegistry } from './types.js'\n\nexport async function scaffoldProject(\n options: ProjectOptions\n): Promise<TemplateConfig | null> {\n const templatesDir = getTemplatesDir()\n const registryPath = path.join(templatesDir, 'template.config.json')\n const registry: TemplateRegistry = await fs.readJson(registryPath)\n\n const templateEntry = registry.templates.find((t) => t.name === options.template)\n if (!templateEntry) {\n throw new Error(`未找到模板: ${options.template}`)\n }\n\n const templateDir = path.join(templatesDir, templateEntry.dir)\n const templateConfigPath = path.join(templateDir, '_template.json')\n\n let templateConfig: TemplateConfig | null = null\n if (await fs.pathExists(templateConfigPath)) {\n templateConfig = await fs.readJson(templateConfigPath)\n }\n\n await fs.ensureDir(options.targetDir)\n\n const files = await fs.readdir(templateDir)\n\n for (const file of files) {\n if (file === '_template.json') {\n continue\n }\n\n const srcPath = path.join(templateDir, file)\n let destFileName = file\n\n if (templateConfig?.fileRenames?.[file]) {\n destFileName = templateConfig.fileRenames[file]\n if (destFileName === '{{projectName}}') {\n destFileName = options.projectName\n }\n }\n\n const destPath = path.join(options.targetDir, destFileName)\n const stat = await fs.stat(srcPath)\n\n if (stat.isDirectory()) {\n await copyDirectory(srcPath, destPath, options.projectName, templateConfig)\n } else {\n await copyFile(srcPath, destPath, options.projectName, templateConfig)\n }\n }\n\n return templateConfig\n}\n\nasync function copyDirectory(\n srcDir: string,\n destDir: string,\n projectName: string,\n config: TemplateConfig | null\n): Promise<void> {\n await fs.ensureDir(destDir)\n const files = await fs.readdir(srcDir)\n\n for (const file of files) {\n const srcPath = path.join(srcDir, file)\n let destFileName = file\n\n if (config?.fileRenames?.[file]) {\n destFileName = config.fileRenames[file]\n if (destFileName === '{{projectName}}') {\n destFileName = projectName\n }\n }\n\n const destPath = path.join(destDir, destFileName)\n const stat = await fs.stat(srcPath)\n\n if (stat.isDirectory()) {\n await copyDirectory(srcPath, destPath, projectName, config)\n } else {\n await copyFile(srcPath, destPath, projectName, config)\n }\n }\n}\n\nasync function copyFile(\n srcPath: string,\n destPath: string,\n projectName: string,\n config: TemplateConfig | null\n): Promise<void> {\n const binaryExtensions = [\n '.png', '.jpg', '.jpeg', '.gif', '.ico', '.webp',\n '.woff', '.woff2', '.ttf', '.eot',\n '.zip', '.tar', '.gz'\n ]\n\n const ext = path.extname(srcPath).toLowerCase()\n\n if (binaryExtensions.includes(ext)) {\n await fs.copy(srcPath, destPath)\n return\n }\n\n let content = await fs.readFile(srcPath, 'utf-8')\n\n content = content.replace(/\\{\\{projectName\\}\\}/g, projectName)\n\n if (config?.variables) {\n for (const [key, value] of Object.entries(config.variables)) {\n const placeholder = `{{${key}}}`\n const replacement = value === '{{projectName}}' ? projectName : value\n content = content.replace(new RegExp(placeholder.replace(/[{}]/g, '\\\\$&'), 'g'), replacement)\n }\n }\n\n await fs.writeFile(destPath, content, 'utf-8')\n}\n","import pc from 'picocolors'\nimport { execAsync } from './utils.js'\nimport { loadConfig, getConfigPath } from './config.js'\nimport { validateToken, createRepository } from './github-api.js'\n\nexport async function initGit(targetDir: string): Promise<void> {\n await execAsync('git', ['init'], { cwd: targetDir })\n await execAsync('git', ['add', '-A'], { cwd: targetDir })\n await execAsync('git', ['commit', '-m', 'Initial commit'], { cwd: targetDir })\n}\n\nexport interface CreateGithubRepoResult {\n success: boolean\n repoUrl?: string\n error?: string\n}\n\nexport async function createGithubRepo(\n repoName: string,\n targetDir: string,\n isPublic: boolean\n): Promise<string | null> {\n const config = loadConfig()\n\n // 检查 Token 是否配置\n if (!config.github?.token) {\n console.log(pc.yellow('⚠ 未配置 GitHub Token,跳过仓库创建'))\n console.log(pc.dim(` 运行 ${pc.cyan('create-idp config --setup-github')} 配置 Token`))\n console.log(pc.dim(` 配置文件路径: ${getConfigPath()}`))\n return null\n }\n\n const token = config.github.token\n const defaultOrg = config.github.defaultOrg\n\n // 验证 Token\n const validateResult = await validateToken(token)\n if (!validateResult.success) {\n console.log(pc.yellow(`⚠ GitHub Token 无效: ${validateResult.error}`))\n if (validateResult.rateLimitReset) {\n console.log(pc.dim(` Rate limit 将在 ${validateResult.rateLimitReset.toLocaleString()} 重置`))\n }\n console.log(pc.dim(` 运行 ${pc.cyan('create-idp config --setup-github')} 重新配置`))\n return null\n }\n\n const username = validateResult.data.login\n\n // 创建仓库\n const createResult = await createRepository(token, {\n name: repoName,\n isPrivate: !isPublic,\n org: defaultOrg\n })\n\n if (!createResult.success) {\n if (createResult.statusCode === 422) {\n console.log(pc.yellow(`⚠ 仓库 \"${repoName}\" 已存在,请选择其他名称`))\n } else if (createResult.rateLimitReset) {\n console.log(pc.yellow(`⚠ API 请求次数已达上限`))\n console.log(pc.dim(` 将在 ${createResult.rateLimitReset.toLocaleString()} 重置`))\n } else {\n console.log(pc.yellow(`⚠ 创建仓库失败: ${createResult.error}`))\n }\n return null\n }\n\n const repo = createResult.data\n\n // 添加远程仓库并推送\n const remoteResult = await execAsync(\n 'git',\n ['remote', 'add', 'origin', repo.clone_url],\n { cwd: targetDir }\n )\n\n if (remoteResult.code !== 0) {\n // remote 可能已存在,尝试更新\n await execAsync(\n 'git',\n ['remote', 'set-url', 'origin', repo.clone_url],\n { cwd: targetDir }\n )\n }\n\n // 推送到远程\n const pushResult = await execAsync(\n 'git',\n ['push', '-u', 'origin', 'main'],\n { cwd: targetDir }\n )\n\n if (pushResult.code !== 0) {\n // 尝试推送 master 分支\n const pushMaster = await execAsync(\n 'git',\n ['push', '-u', 'origin', 'master'],\n { cwd: targetDir }\n )\n if (pushMaster.code !== 0) {\n console.log(pc.yellow(`⚠ 推送失败: ${pushResult.stderr || pushMaster.stderr}`))\n console.log(pc.dim(` 仓库已创建: ${repo.html_url}`))\n console.log(pc.dim(' 请手动推送代码'))\n return repo.html_url\n }\n }\n\n return repo.html_url\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport type { UserConfig } from './types.js'\n\nconst CONFIG_PATH = path.join(os.homedir(), '.create-idp.json')\n\nexport function loadConfig(): UserConfig {\n try {\n if (fs.existsSync(CONFIG_PATH)) {\n const content = fs.readFileSync(CONFIG_PATH, 'utf-8')\n return JSON.parse(content) as UserConfig\n }\n } catch {\n // 配置文件损坏或读取失败,返回空配置\n }\n return {}\n}\n\nexport function saveConfig(config: UserConfig): void {\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), 'utf-8')\n // 设置文件权限为 600 (仅所有者可读写),保护 Token 安全\n fs.chmodSync(CONFIG_PATH, 0o600)\n}\n\nexport function getConfigPath(): string {\n return CONFIG_PATH\n}\n","import type { GitHubUser, GitHubRepoResponse, GitHubApiError } from './types.js'\n\nconst GITHUB_API_BASE = 'https://api.github.com'\n\ninterface GitHubApiResult<T> {\n success: true\n data: T\n}\n\ninterface GitHubApiFailure {\n success: false\n error: string\n statusCode?: number\n rateLimitReset?: Date\n}\n\ntype GitHubApiResponse<T> = GitHubApiResult<T> | GitHubApiFailure\n\nasync function githubFetch<T>(\n endpoint: string,\n token: string,\n options: RequestInit = {}\n): Promise<GitHubApiResponse<T>> {\n const url = `${GITHUB_API_BASE}${endpoint}`\n\n try {\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Accept': 'application/vnd.github+json',\n 'Authorization': `Bearer ${token}`,\n 'X-GitHub-Api-Version': '2022-11-28',\n 'User-Agent': 'create-idp',\n ...options.headers,\n },\n })\n\n // 处理 Rate Limit\n if (response.status === 403) {\n const rateLimitRemaining = response.headers.get('x-ratelimit-remaining')\n const rateLimitReset = response.headers.get('x-ratelimit-reset')\n\n if (rateLimitRemaining === '0' && rateLimitReset) {\n const resetDate = new Date(parseInt(rateLimitReset) * 1000)\n return {\n success: false,\n error: 'API 请求次数已达上限',\n statusCode: 403,\n rateLimitReset: resetDate,\n }\n }\n }\n\n // 处理未授权\n if (response.status === 401) {\n return {\n success: false,\n error: 'Token 无效或已过期',\n statusCode: 401,\n }\n }\n\n // 处理其他错误\n if (!response.ok) {\n const errorData = await response.json() as GitHubApiError\n return {\n success: false,\n error: errorData.message || `请求失败: ${response.status}`,\n statusCode: response.status,\n }\n }\n\n const data = await response.json() as T\n return { success: true, data }\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : '网络请求失败',\n }\n }\n}\n\n/**\n * 验证 Token 并获取用户信息\n */\nexport async function validateToken(token: string): Promise<GitHubApiResponse<GitHubUser>> {\n return githubFetch<GitHubUser>('/user', token)\n}\n\nexport interface CreateRepoOptions {\n name: string\n description?: string\n isPrivate: boolean\n org?: string\n}\n\n/**\n * 创建 GitHub 仓库\n */\nexport async function createRepository(\n token: string,\n options: CreateRepoOptions\n): Promise<GitHubApiResponse<GitHubRepoResponse>> {\n const endpoint = options.org\n ? `/orgs/${options.org}/repos`\n : '/user/repos'\n\n const body = {\n name: options.name,\n description: options.description || `Created with create-idp`,\n private: options.isPrivate,\n auto_init: false,\n }\n\n return githubFetch<GitHubRepoResponse>(endpoint, token, {\n method: 'POST',\n body: JSON.stringify(body),\n })\n}\n\n/**\n * 检查仓库是否存在\n */\nexport async function checkRepoExists(\n token: string,\n owner: string,\n repo: string\n): Promise<boolean> {\n const result = await githubFetch<GitHubRepoResponse>(\n `/repos/${owner}/${repo}`,\n token\n )\n return result.success\n}\n","import pc from 'picocolors'\nimport { execAsync } from './utils.js'\nimport type { PostInitCommand } from './types.js'\n\nexport async function runPostInit(\n targetDir: string,\n commands: PostInitCommand[]\n): Promise<void> {\n for (const cmd of commands) {\n console.log(pc.dim(` ${cmd.description}...`))\n const [command, ...args] = cmd.command.split(' ')\n const result = await execAsync(command, args, {\n cwd: targetDir,\n stdio: 'pipe'\n })\n\n if (result.code !== 0) {\n console.log(pc.yellow(`⚠ ${cmd.description} 失败`))\n if (result.stderr) {\n console.log(pc.dim(result.stderr.slice(0, 200)))\n }\n }\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport pc from 'picocolors'\n\nconst CACHE_PATH = path.join(os.homedir(), '.create-idp-update-check')\nconst CACHE_TTL = 24 * 60 * 60 * 1000 // 24 小时\nconst PACKAGE_NAME = 'create-idp'\n\ninterface UpdateCache {\n lastCheck: number\n latestVersion: string\n}\n\nfunction readCache(): UpdateCache | null {\n try {\n if (fs.existsSync(CACHE_PATH)) {\n const content = fs.readFileSync(CACHE_PATH, 'utf-8')\n return JSON.parse(content) as UpdateCache\n }\n } catch {\n // 忽略缓存读取错误\n }\n return null\n}\n\nfunction writeCache(cache: UpdateCache): void {\n try {\n fs.writeFileSync(CACHE_PATH, JSON.stringify(cache), 'utf-8')\n } catch {\n // 忽略缓存写入错误\n }\n}\n\nasync function fetchLatestVersion(): Promise<string | null> {\n try {\n const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`)\n if (!response.ok) {\n return null\n }\n const data = (await response.json()) as { version: string }\n return data.version\n } catch {\n // 网络请求失败,静默处理\n return null\n }\n}\n\nfunction compareVersions(current: string, latest: string): number {\n const currentParts = current.split('.').map(Number)\n const latestParts = latest.split('.').map(Number)\n\n for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {\n const c = currentParts[i] || 0\n const l = latestParts[i] || 0\n if (c < l) return -1\n if (c > l) return 1\n }\n return 0\n}\n\nexport async function checkForUpdates(currentVersion: string): Promise<void> {\n const cache = readCache()\n const now = Date.now()\n\n let latestVersion: string | null = null\n\n // 检查缓存是否有效\n if (cache && now - cache.lastCheck < CACHE_TTL) {\n latestVersion = cache.latestVersion\n } else {\n // 缓存过期,重新获取\n latestVersion = await fetchLatestVersion()\n if (latestVersion) {\n writeCache({ lastCheck: now, latestVersion })\n }\n }\n\n // 比较版本并提示\n if (latestVersion && compareVersions(currentVersion, latestVersion) < 0) {\n console.log()\n console.log(\n pc.yellow(` \\u26A0 发现新版本 ${pc.bold(latestVersion)},当前 ${currentVersion}`)\n )\n console.log(pc.cyan(` 运行 ${pc.bold(`npm update -g ${PACKAGE_NAME}`)} 更新`))\n console.log()\n }\n}\n","import { input, confirm } from '@inquirer/prompts'\nimport pc from 'picocolors'\nimport { loadConfig, saveConfig } from './config.js'\nimport { validateToken } from './github-api.js'\n\nconst TOKEN_HELP_URL = 'https://github.com/settings/tokens/new?scopes=repo&description=create-idp'\n\n/**\n * 运行 GitHub Token 配置引导\n */\nexport async function runGitHubSetup(): Promise<boolean> {\n console.log()\n console.log(pc.cyan('配置 GitHub Token'))\n console.log()\n console.log('需要一个具有 repo 权限的 Personal Access Token (Classic) 来创建仓库。')\n console.log()\n console.log(pc.dim('获取步骤:'))\n console.log(pc.dim('1. 访问 GitHub Settings > Developer settings > Personal access tokens'))\n console.log(pc.dim('2. 点击 \"Generate new token (classic)\"'))\n console.log(pc.dim('3. 勾选 \"repo\" 权限'))\n console.log(pc.dim('4. 生成并复制 Token'))\n console.log()\n console.log(pc.dim(`快捷链接: ${TOKEN_HELP_URL}`))\n console.log()\n\n const token = await input({\n message: '请输入 GitHub Token:',\n validate: (value) => {\n if (!value.trim()) {\n return 'Token 不能为空'\n }\n if (!value.startsWith('ghp_') && !value.startsWith('github_pat_')) {\n return 'Token 格式不正确,应以 ghp_ 或 github_pat_ 开头'\n }\n return true\n }\n })\n\n console.log()\n console.log(pc.dim('正在验证 Token...'))\n\n const result = await validateToken(token.trim())\n\n if (!result.success) {\n console.log(pc.red(`✗ Token 验证失败: ${result.error}`))\n if (result.rateLimitReset) {\n console.log(pc.dim(` Rate limit 将在 ${result.rateLimitReset.toLocaleString()} 重置`))\n }\n return false\n }\n\n const user = result.data\n console.log(pc.green(`✔ Token 有效,已登录为: ${user.login}${user.name ? ` (${user.name})` : ''}`))\n console.log()\n\n // 询问是否设置默认组织\n const setOrg = await confirm({\n message: '是否设置默认组织? (否则仓库将创建在个人账户下)',\n default: false\n })\n\n let defaultOrg: string | undefined\n if (setOrg) {\n defaultOrg = await input({\n message: '默认组织名称:',\n validate: (value) => {\n if (!value.trim()) {\n return '组织名称不能为空'\n }\n return true\n }\n })\n defaultOrg = defaultOrg.trim()\n }\n\n // 保存配置\n const config = loadConfig()\n config.github = {\n token: token.trim(),\n ...(defaultOrg && { defaultOrg })\n }\n saveConfig(config)\n\n console.log()\n console.log(pc.green('✔ GitHub 配置已保存'))\n console.log(pc.dim(' 配置文件已设置为仅当前用户可读'))\n\n return true\n}\n\n/**\n * 显示当前配置\n */\nexport function showConfig(): void {\n const config = loadConfig()\n\n console.log()\n console.log(pc.cyan('当前配置:'))\n console.log()\n\n if (config.defaults) {\n console.log(pc.dim('defaults:'))\n if (config.defaults.github !== undefined) {\n console.log(` github: ${config.defaults.github}`)\n }\n if (config.defaults.public !== undefined) {\n console.log(` public: ${config.defaults.public}`)\n }\n if (config.defaults.template !== undefined) {\n console.log(` template: ${config.defaults.template}`)\n }\n }\n\n if (config.github) {\n console.log(pc.dim('github:'))\n if (config.github.token) {\n const masked = config.github.token.slice(0, 8) + '...' + config.github.token.slice(-4)\n console.log(` token: ${masked}`)\n }\n if (config.github.defaultOrg) {\n console.log(` defaultOrg: ${config.github.defaultOrg}`)\n }\n }\n\n if (!config.defaults && !config.github) {\n console.log(pc.dim('(无配置)'))\n }\n\n console.log()\n}\n","import { createCli } from './cli.js'\n\nasync function main(): Promise<void> {\n const program = await createCli()\n await program.parseAsync(process.argv)\n}\n\nmain().catch((err) => {\n console.error(err)\n process.exit(1)\n})\n"],"mappings":"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","names":["pc","path","fs","path","initGit","path","fs","path","fs","pc","fs","path","pc","pc","pc","fs","path","os","pc","input","confirm","pc","pc","input","confirm","pc"]}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "create-idp",
3
+ "version": "0.1.0",
4
+ "description": "CLI 脚手架工具,快速创建项目并可选初始化 GitHub 仓库",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-idp": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "templates"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsup",
15
+ "dev": "tsup --watch",
16
+ "test": "vitest",
17
+ "test:run": "vitest run",
18
+ "prepublishOnly": "pnpm build"
19
+ },
20
+ "keywords": [
21
+ "cli",
22
+ "scaffold",
23
+ "create",
24
+ "idp",
25
+ "template",
26
+ "generator"
27
+ ],
28
+ "author": "",
29
+ "license": "MIT",
30
+ "devDependencies": {
31
+ "@types/fs-extra": "^11.0.4",
32
+ "@types/node": "^22.10.7",
33
+ "tsup": "^8.3.5",
34
+ "typescript": "^5.7.3",
35
+ "vitest": "^3.0.4"
36
+ },
37
+ "dependencies": {
38
+ "@inquirer/prompts": "^7.2.1",
39
+ "commander": "^13.0.0",
40
+ "fs-extra": "^11.2.0",
41
+ "picocolors": "^1.1.1"
42
+ },
43
+ "engines": {
44
+ "node": ">=18.0.0"
45
+ }
46
+ }
@@ -0,0 +1,3 @@
1
+ # {{projectName}}
2
+
3
+ 项目已创建,开始编写你的代码吧!
@@ -0,0 +1,6 @@
1
+ node_modules/
2
+ dist/
3
+ *.log
4
+ .DS_Store
5
+ .env
6
+ .env.local
@@ -0,0 +1,6 @@
1
+ {
2
+ "description": "空项目模板",
3
+ "fileRenames": {
4
+ "_gitignore": ".gitignore"
5
+ }
6
+ }
@@ -0,0 +1,21 @@
1
+ # {{projectName}}
2
+
3
+ Node.js + TypeScript 项目
4
+
5
+ ## 开发
6
+
7
+ ```bash
8
+ pnpm dev
9
+ ```
10
+
11
+ ## 构建
12
+
13
+ ```bash
14
+ pnpm build
15
+ ```
16
+
17
+ ## 测试
18
+
19
+ ```bash
20
+ pnpm test
21
+ ```
@@ -0,0 +1,7 @@
1
+ node_modules/
2
+ dist/
3
+ *.log
4
+ .DS_Store
5
+ .env
6
+ .env.local
7
+ coverage/
@@ -0,0 +1,16 @@
1
+ {
2
+ "description": "Node.js + TypeScript 项目模板",
3
+ "packageManager": "pnpm",
4
+ "postInit": [
5
+ {
6
+ "command": "pnpm install",
7
+ "description": "安装依赖"
8
+ }
9
+ ],
10
+ "variables": {
11
+ "PROJECT_NAME": "{{projectName}}"
12
+ },
13
+ "fileRenames": {
14
+ "_gitignore": ".gitignore"
15
+ }
16
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "tsx watch src/index.ts",
7
+ "build": "tsup",
8
+ "start": "node dist/index.js",
9
+ "test": "vitest",
10
+ "test:run": "vitest run"
11
+ },
12
+ "devDependencies": {
13
+ "@types/node": "^22.10.7",
14
+ "tsup": "^8.3.5",
15
+ "tsx": "^4.19.2",
16
+ "typescript": "^5.7.3",
17
+ "vitest": "^3.0.4"
18
+ }
19
+ }
@@ -0,0 +1 @@
1
+ console.log('Hello from {{projectName}}!')
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "outDir": "./dist",
11
+ "rootDir": "./src",
12
+ "declaration": true,
13
+ "resolveJsonModule": true
14
+ },
15
+ "include": ["src/**/*"],
16
+ "exclude": ["node_modules", "dist"]
17
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'tsup'
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ format: ['esm'],
6
+ target: 'node18',
7
+ clean: true,
8
+ dts: true
9
+ })
@@ -0,0 +1,22 @@
1
+ # {{projectName}}
2
+
3
+ Python 项目,使用 uv 包管理器
4
+
5
+ ## 开发
6
+
7
+ ```bash
8
+ uv run python -m {{projectName}}
9
+ ```
10
+
11
+ ## 测试
12
+
13
+ ```bash
14
+ uv run pytest
15
+ ```
16
+
17
+ ## 格式化
18
+
19
+ ```bash
20
+ uv run ruff check --fix
21
+ uv run ruff format
22
+ ```
@@ -0,0 +1,30 @@
1
+ # Byte-compiled
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+
11
+ # Virtual environments
12
+ .venv/
13
+ venv/
14
+ ENV/
15
+
16
+ # IDE
17
+ .idea/
18
+ .vscode/
19
+ *.swp
20
+
21
+ # Testing
22
+ .pytest_cache/
23
+ .coverage
24
+ htmlcov/
25
+
26
+ # Misc
27
+ .DS_Store
28
+ *.log
29
+ .env
30
+ .env.local
@@ -0,0 +1,14 @@
1
+ {
2
+ "description": "Python 项目模板 (使用 uv)",
3
+ "packageManager": "uv",
4
+ "postInit": [
5
+ {
6
+ "command": "uv sync",
7
+ "description": "安装依赖"
8
+ }
9
+ ],
10
+ "fileRenames": {
11
+ "_gitignore": ".gitignore",
12
+ "project_name": "{{projectName}}"
13
+ }
14
+ }
@@ -0,0 +1,20 @@
1
+ [project]
2
+ name = "{{projectName}}"
3
+ version = "0.1.0"
4
+ description = ""
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ dependencies = []
8
+
9
+ [project.scripts]
10
+ {{projectName}} = "{{projectName}}:main"
11
+
12
+ [build-system]
13
+ requires = ["hatchling"]
14
+ build-backend = "hatchling.build"
15
+
16
+ [tool.uv]
17
+ dev-dependencies = [
18
+ "pytest>=8.0.0",
19
+ "ruff>=0.8.0",
20
+ ]
@@ -0,0 +1,10 @@
1
+ """{{projectName}} - 主入口"""
2
+
3
+
4
+ def main() -> None:
5
+ """程序入口函数"""
6
+ print(f"Hello from {{projectName}}!")
7
+
8
+
9
+ if __name__ == "__main__":
10
+ main()
@@ -0,0 +1,4 @@
1
+ from . import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
@@ -0,0 +1,6 @@
1
+ node_modules/
2
+ dist/
3
+ *.log
4
+ .DS_Store
5
+ .env
6
+ .env.local
@@ -0,0 +1,13 @@
1
+ {
2
+ "description": "React + TypeScript 项目模板",
3
+ "packageManager": "pnpm",
4
+ "postInit": [
5
+ {
6
+ "command": "pnpm install",
7
+ "description": "安装依赖"
8
+ }
9
+ ],
10
+ "fileRenames": {
11
+ "_gitignore": ".gitignore"
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>{{projectName}}</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "private": true,
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc -b && vite build",
9
+ "lint": "eslint .",
10
+ "preview": "vite preview"
11
+ },
12
+ "dependencies": {
13
+ "react": "^18.3.1",
14
+ "react-dom": "^18.3.1"
15
+ },
16
+ "devDependencies": {
17
+ "@types/react": "^18.3.18",
18
+ "@types/react-dom": "^18.3.5",
19
+ "@vitejs/plugin-react": "^4.3.4",
20
+ "typescript": "^5.7.3",
21
+ "vite": "^6.0.7"
22
+ }
23
+ }
@@ -0,0 +1,14 @@
1
+ .app {
2
+ text-align: center;
3
+ padding: 2rem;
4
+ }
5
+
6
+ h1 {
7
+ color: #333;
8
+ }
9
+
10
+ code {
11
+ background: #f4f4f4;
12
+ padding: 0.2rem 0.4rem;
13
+ border-radius: 4px;
14
+ }
@@ -0,0 +1,12 @@
1
+ import './App.css'
2
+
3
+ function App() {
4
+ return (
5
+ <div className="app">
6
+ <h1>{{projectName}}</h1>
7
+ <p>编辑 <code>src/App.tsx</code> 开始开发</p>
8
+ </div>
9
+ )
10
+ }
11
+
12
+ export default App
@@ -0,0 +1,11 @@
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ body {
8
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
9
+ -webkit-font-smoothing: antialiased;
10
+ -moz-osx-font-smoothing: grayscale;
11
+ }
@@ -0,0 +1,10 @@
1
+ import { StrictMode } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import App from './App.tsx'
4
+ import './index.css'
5
+
6
+ createRoot(document.getElementById('root')!).render(
7
+ <StrictMode>
8
+ <App />
9
+ </StrictMode>,
10
+ )
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "isolatedModules": true,
11
+ "moduleDetection": "force",
12
+ "noEmit": true,
13
+ "jsx": "react-jsx",
14
+ "strict": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noFallthroughCasesInSwitch": true
18
+ },
19
+ "include": ["src"]
20
+ }
@@ -0,0 +1,6 @@
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ })
@@ -0,0 +1,34 @@
1
+ {
2
+ "templates": [
3
+ {
4
+ "name": "empty",
5
+ "displayName": "空项目",
6
+ "description": "仅包含基础配置的空项目",
7
+ "dir": "empty"
8
+ },
9
+ {
10
+ "name": "node-ts",
11
+ "displayName": "Node.js + TypeScript",
12
+ "description": "Node.js 项目,使用 TypeScript 和 pnpm",
13
+ "dir": "node-ts"
14
+ },
15
+ {
16
+ "name": "react-ts",
17
+ "displayName": "React + TypeScript",
18
+ "description": "React 18 项目,使用 Vite 和 TypeScript",
19
+ "dir": "react-ts"
20
+ },
21
+ {
22
+ "name": "vue-ts",
23
+ "displayName": "Vue + TypeScript",
24
+ "description": "Vue 3 项目,使用 Vite 和 TypeScript",
25
+ "dir": "vue-ts"
26
+ },
27
+ {
28
+ "name": "python-uv",
29
+ "displayName": "Python (uv)",
30
+ "description": "Python 项目,使用 uv 包管理器",
31
+ "dir": "python-uv"
32
+ }
33
+ ]
34
+ }
@@ -0,0 +1,6 @@
1
+ node_modules/
2
+ dist/
3
+ *.log
4
+ .DS_Store
5
+ .env
6
+ .env.local
@@ -0,0 +1,13 @@
1
+ {
2
+ "description": "Vue + TypeScript 项目模板",
3
+ "packageManager": "pnpm",
4
+ "postInit": [
5
+ {
6
+ "command": "pnpm install",
7
+ "description": "安装依赖"
8
+ }
9
+ ],
10
+ "fileRenames": {
11
+ "_gitignore": ".gitignore"
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>{{projectName}}</title>
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="/src/main.ts"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "private": true,
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vue-tsc -b && vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "vue": "^3.5.13"
13
+ },
14
+ "devDependencies": {
15
+ "@vitejs/plugin-vue": "^5.2.1",
16
+ "typescript": "^5.7.3",
17
+ "vite": "^6.0.7",
18
+ "vue-tsc": "^2.2.0"
19
+ }
20
+ }