diff --git a/.changeset/famous-stingrays-stare.md b/.changeset/famous-stingrays-stare.md new file mode 100644 index 000000000..070adeea4 --- /dev/null +++ b/.changeset/famous-stingrays-stare.md @@ -0,0 +1,5 @@ +--- +'@xata.io/cli': patch +--- + +Add ability to interactively select branch on xata init when main branch does not exist diff --git a/cli/src/base.ts b/cli/src/base.ts index 5dacc4473..a2921fc3e 100644 --- a/cli/src/base.ts +++ b/cli/src/base.ts @@ -346,7 +346,13 @@ export abstract class BaseCommand extends Command { workspace: string, region: string, database: string, - options: { allowEmpty?: boolean; allowCreate?: boolean; title?: string } = {} + options: { + allowEmpty?: boolean; + allowCreate?: boolean; + title?: string; + // Branch to default if exists + defaultBranch?: string; + } = {} ): Promise { const xata = await this.getXataClient(); const { branches = [] } = await xata.api.branches.getBranchList({ workspace, region, database }); @@ -354,6 +360,10 @@ export abstract class BaseCommand extends Command { const EMPTY_CHOICE = '$empty'; const CREATE_CHOICE = '$create'; + if (options.defaultBranch && branches.map(({ name }) => name).includes(options.defaultBranch)) { + return options.defaultBranch; + } + if (branches.length > 0) { const choices = branches.map((db) => ({ title: db.name, diff --git a/cli/src/commands/codegen/index.ts b/cli/src/commands/codegen/index.ts index 9a06ee095..3945d1fef 100644 --- a/cli/src/commands/codegen/index.ts +++ b/cli/src/commands/codegen/index.ts @@ -122,7 +122,7 @@ export default class Codegen extends BaseCommand { this.log(`Generated Xata code to ./${relative(process.cwd(), output)}`); } - static async runIfConfigured(projectConfig?: ProjectConfig) { - if (projectConfig?.codegen?.output) return Codegen.run([]); + static async runIfConfigured(projectConfig?: ProjectConfig, flags?: any[]) { + if (projectConfig?.codegen?.output) return Codegen.run(flags ?? []); } } diff --git a/cli/src/commands/init/index.test.ts b/cli/src/commands/init/index.test.ts index a801ba68d..9cf3cd582 100644 --- a/cli/src/commands/init/index.test.ts +++ b/cli/src/commands/init/index.test.ts @@ -58,8 +58,16 @@ const fetchImplementation = (url: string, request: any) => { ok: true, json: async () => ({ meta: { cursor: '', more: false }, logs: [] }) }; + } else if (url === `https://test-1234.${REGION}.xata.sh/dbs/db1` && request.method === 'GET') { + return { + ok: true, + json: async () => { + return { + branches: [{ name: 'main', id: 'main' }] + }; + } + }; } - throw new Error(`Unexpected fetch request: ${url} ${request.method}`); }; diff --git a/cli/src/commands/init/index.ts b/cli/src/commands/init/index.ts index eb19578cf..5733624ba 100644 --- a/cli/src/commands/init/index.ts +++ b/cli/src/commands/init/index.ts @@ -45,6 +45,8 @@ const packageManagers = { } }; +const DEFAULT_BRANCH = 'main'; + const isPackageManagerInstalled = (packageManager: PackageManager) => which.sync(packageManager.command, { nothrow: true }); @@ -134,6 +136,16 @@ export default class Init extends BaseCommand { const { workspace, region, database, databaseURL } = await this.getParsedDatabaseURL(flags.db, true); + const detectedBranch = this.getCurrentBranchName(); + const branch = + detectedBranch === DEFAULT_BRANCH + ? await this.getBranch(workspace, region, database, { + allowCreate: false, + allowEmpty: false, + defaultBranch: DEFAULT_BRANCH + }) + : detectedBranch; + this.projectConfig = { databaseURL }; const ignoreEnvFile = await this.promptIgnoreEnvFile(); @@ -146,7 +158,7 @@ export default class Init extends BaseCommand { await this.writeConfig(); this.log(); - await this.writeEnvFile(workspace, region, database); + await this.writeEnvFile(workspace, region, database, branch); if (ignoreEnvFile) { await this.ignoreEnvFile(); @@ -157,14 +169,13 @@ export default class Init extends BaseCommand { await this.installPackage(packageManager, '@xata.io/client'); } - const branch = this.getCurrentBranchName(); if (schema) { await this.deploySchema(workspace, region, database, branch, schema); } // Run pull to retrieve remote migrations, remove any local migrations, and generate code await Pull.run([branch, '-f', '--skip-code-generation']); - await Codegen.runIfConfigured(this.projectConfig); + await Codegen.runIfConfigured(this.projectConfig, [`--branch=${branch}`]); await this.delay(1000); @@ -194,7 +205,7 @@ export default class Init extends BaseCommand { }columns at https://app.xata.io/workspaces/${workspace}/dbs/${database}:${region}` ); this.log(); - this.info(`Use ${chalk.bold(`xata pull main`)} to regenerate code and types from your Xata database`); + this.info(`Use ${chalk.bold(`xata pull ${branch}`)} to regenerate code and types from your Xata database`); } else { this.log(`To make your first query:`); this.log(``); @@ -375,7 +386,7 @@ export default class Init extends BaseCommand { return envFile; } - async writeEnvFile(workspace: string, region: string, database: string) { + async writeEnvFile(workspace: string, region: string, database: string, branch: string) { const envFile = await this.findEnvFile(); const doesEnvFileExist = await this.access(envFile); @@ -398,7 +409,7 @@ export default class Init extends BaseCommand { if (containsXataApiKey) { this.warn(`Your ${envFile} file already contains XATA_API_KEY key. skipping...`); } else { - const setBranch = `XATA_BRANCH=main`; + const setBranch = `XATA_BRANCH=${branch}`; if (content) content += '\n\n'; content += '# [Xata] Configuration used by the CLI and the SDK\n'; content += '# Make sure your framework/tooling loads this file on startup to have it available for the SDK\n';