-
Notifications
You must be signed in to change notification settings - Fork 99
feat(cli): add tab completions #1082
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 9 commits
3ce4f79
447e1a3
0461d5c
394e3bc
2bf2b6c
22fc13c
8877baa
81e36cf
d1babb4
632781d
2252472
87e58f9
1860f10
63b2c8b
d4213cd
d64d259
c7352b5
4e7d9bc
6325654
f15c787
1ede8e8
c1c28d0
243bf65
c016105
590290c
d37a720
166246a
c9c8bf7
44a49d1
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,74 @@ | ||
| /** generate completion data from nitropack and Nuxt starter repo */ | ||
|
|
||
| import { writeFile } from 'node:fs/promises' | ||
| import { createRequire } from 'node:module' | ||
| import { fileURLToPath } from 'node:url' | ||
| import { dirname, join, resolve } from 'node:path' | ||
|
|
||
| const require = createRequire(import.meta.url) | ||
| const __dirname = dirname(fileURLToPath(import.meta.url)) | ||
|
|
||
| interface PresetMeta { | ||
| _meta?: { name: string } | ||
|
Check failure on line 12 in packages/nuxi/scripts/generate-completions-data.ts
|
||
| } | ||
|
|
||
| async function generateCompletionData() { | ||
| const data: { | ||
|
Check failure on line 16 in packages/nuxi/scripts/generate-completions-data.ts
|
||
| nitroPresets: string[] | ||
|
Check failure on line 17 in packages/nuxi/scripts/generate-completions-data.ts
|
||
| templates: string[] | ||
|
Check failure on line 18 in packages/nuxi/scripts/generate-completions-data.ts
|
||
| } = { | ||
| nitroPresets: [], | ||
| templates: [], | ||
| } | ||
|
|
||
| const nitropackPath = dirname(require.resolve('nitropack/package.json')) | ||
| const presetsPath = join(nitropackPath, 'dist/presets/_all.gen.mjs') | ||
| const { default: allPresets } = await import(presetsPath) as { default: PresetMeta[] } | ||
|
|
||
| data.nitroPresets = allPresets | ||
| .map(preset => preset._meta?.name) | ||
| .filter((name): name is string => Boolean(name)) | ||
| .filter(name => !['base-worker', 'nitro-dev', 'nitro-prerender'].includes(name)) | ||
| .filter((name, index, array) => array.indexOf(name) === index) | ||
| .sort() | ||
|
|
||
| const response = await fetch( | ||
| 'https://api.github.com/repos/nuxt/starter/contents/templates?ref=templates' | ||
| ) | ||
|
|
||
| if (!response.ok) { | ||
| throw new Error(`GitHub API error: ${response.status}`) | ||
| } | ||
|
|
||
| const files = await response.json() as Array<{ name: string; type: string }> | ||
|
|
||
| const templateEntries = files | ||
| .filter(file => { | ||
| if (file.type === 'dir') return true | ||
| if (file.type === 'file' && file.name.endsWith('.json') && file.name !== 'content.json') { | ||
| return true | ||
| } | ||
| return false | ||
| }) | ||
| .map(file => file.name.replace('.json', '')) | ||
|
|
||
| data.templates = Array.from(new Set(templateEntries)) | ||
| .filter(name => name !== 'community') | ||
| .sort() | ||
|
|
||
| const outputPath = resolve(__dirname, '../src/utils/completions-data.ts') | ||
| const content = `/** Auto-generated file */ | ||
|
|
||
| export const nitroPresets = ${JSON.stringify(data.nitroPresets, null, 2)} as const | ||
|
|
||
| export const templates = ${JSON.stringify(data.templates, null, 2)} as const | ||
| ` | ||
|
|
||
| await writeFile(outputPath, content, 'utf-8') | ||
| } | ||
|
|
||
| generateCompletionData().catch((error) => { | ||
| console.error('Failed to generate completion data:', error) | ||
| process.exit(1) | ||
| }) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| import type { ArgsDef, CommandDef } from 'citty' | ||
| import tab from '@bomb.sh/tab/citty' | ||
| import { templates } from './utils/completions-data' | ||
|
|
||
| export async function setupInitCompletions<T extends ArgsDef = ArgsDef>(command: CommandDef<T>) { | ||
| const completion = await tab(command) | ||
|
|
||
| const templateOption = completion.options?.get('template') | ||
| if (templateOption) { | ||
| templateOption.handler = (complete) => { | ||
| for (const template of templates) { | ||
| complete(template, '') | ||
| } | ||
| } | ||
| } | ||
|
|
||
| const logLevelOption = completion.options?.get('logLevel') | ||
| if (logLevelOption) { | ||
| logLevelOption.handler = (complete) => { | ||
| complete('silent', 'No logs') | ||
| complete('info', 'Standard logging') | ||
| complete('verbose', 'Detailed logging') | ||
| } | ||
| } | ||
|
|
||
| return completion | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| import type { ArgsDef, CommandDef } from 'citty' | ||
| import tab from '@bomb.sh/tab/citty' | ||
| import { nitroPresets, templates } from './utils/completions-data' | ||
|
|
||
| export async function initCompletions<T extends ArgsDef = ArgsDef>(command: CommandDef<T>) { | ||
AmirSa12 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const completion = await tab(command) | ||
|
|
||
| const devCommand = completion.commands.get('dev') | ||
| if (devCommand) { | ||
| const portOption = devCommand.options.get('port') | ||
| if (portOption) { | ||
| portOption.handler = (complete) => { | ||
| complete('3000', 'Default development port') | ||
| complete('3001', 'Alternative port') | ||
| complete('8080', 'Common alternative port') | ||
| } | ||
| } | ||
|
|
||
| const hostOption = devCommand.options.get('host') | ||
| if (hostOption) { | ||
| hostOption.handler = (complete) => { | ||
| complete('localhost', 'Local development') | ||
| complete('0.0.0.0', 'Listen on all interfaces') | ||
| complete('127.0.0.1', 'Loopback address') | ||
| } | ||
| } | ||
| } | ||
|
|
||
| const buildCommand = completion.commands.get('build') | ||
| if (buildCommand) { | ||
| const presetOption = buildCommand.options.get('preset') | ||
| if (presetOption) { | ||
| presetOption.handler = (complete) => { | ||
| for (const preset of nitroPresets) { | ||
| complete(preset, '') | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| const initCommand = completion.commands.get('init') | ||
| if (initCommand) { | ||
| const templateOption = initCommand.options.get('template') | ||
| if (templateOption) { | ||
| templateOption.handler = (complete) => { | ||
| for (const template of templates) { | ||
| complete(template, '') | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| const addCommand = completion.commands.get('add') | ||
| if (addCommand) { | ||
| const cwdOption = addCommand.options.get('cwd') | ||
| if (cwdOption) { | ||
| cwdOption.handler = (complete) => { | ||
| complete('.', 'Current directory') | ||
| } | ||
| } | ||
| } | ||
|
|
||
| const logLevelCommands = ['dev', 'build', 'generate', 'preview', 'prepare', 'init'] | ||
| for (const cmdName of logLevelCommands) { | ||
| const cmd = completion.commands.get(cmdName) | ||
| if (cmd) { | ||
| const logLevelOption = cmd.options.get('logLevel') | ||
| if (logLevelOption) { | ||
| logLevelOption.handler = (complete) => { | ||
| complete('silent', 'No logs') | ||
| complete('info', 'Standard logging') | ||
| complete('verbose', 'Detailed logging') | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return completion | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| /** Auto-generated file */ | ||
|
|
||
| export const nitroPresets = [ | ||
| "alwaysdata", | ||
| "aws-amplify", | ||
| "aws-lambda", | ||
| "azure-functions", | ||
| "azure-swa", | ||
| "bun", | ||
| "cleavr", | ||
| "cli", | ||
| "cloudflare-dev", | ||
| "cloudflare-durable", | ||
| "cloudflare-module", | ||
| "cloudflare-module-legacy", | ||
| "cloudflare-pages", | ||
| "cloudflare-pages-static", | ||
| "cloudflare-worker", | ||
| "deno-deploy", | ||
| "deno-server", | ||
| "deno-server-legacy", | ||
| "digital-ocean", | ||
| "edgio", | ||
| "firebase", | ||
| "firebase-app-hosting", | ||
| "flight-control", | ||
| "genezio", | ||
| "github-pages", | ||
| "gitlab-pages", | ||
| "heroku", | ||
| "iis-handler", | ||
| "iis-node", | ||
| "koyeb", | ||
| "netlify", | ||
| "netlify-builder", | ||
| "netlify-edge", | ||
| "netlify-legacy", | ||
| "netlify-static", | ||
| "node-cluster", | ||
| "node-listener", | ||
| "node-server", | ||
| "platform-sh", | ||
| "render-com", | ||
| "service-worker", | ||
| "static", | ||
| "stormkit", | ||
| "vercel", | ||
| "vercel-edge", | ||
| "vercel-static", | ||
| "winterjs", | ||
| "zeabur", | ||
| "zeabur-static", | ||
| "zerops", | ||
| "zerops-static" | ||
| ] as const | ||
|
|
||
| export const templates = [ | ||
| "doc-driven", | ||
| "hub", | ||
| "layer", | ||
| "module", | ||
| "module-devtools", | ||
| "ui", | ||
| "ui-vue", | ||
| "v2-bridge", | ||
| "v3", | ||
| "v4", | ||
| "v4-compat" | ||
| ] as const |
Uh oh!
There was an error while loading. Please reload this page.