@base44-preview/cli 0.1.15-pr.630.a6f9272 → 0.1.15-pr.630.f6b9987

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.
package/dist/cli/index.js CHANGED
@@ -269546,7 +269546,7 @@ function getModelCommand() {
269546
269546
 
269547
269547
  // src/cli/commands/app/shared.ts
269548
269548
  import { mkdir as mkdir3, writeFile as writeFile2 } from "node:fs/promises";
269549
- import { join as join21 } from "node:path";
269549
+ import { basename as basename6, join as join21, relative as relative6, resolve as resolve6 } from "node:path";
269550
269550
 
269551
269551
  // src/cli/commands/code/render.ts
269552
269552
  var TOOL_ALIASES = {
@@ -269983,11 +269983,17 @@ async function createAndLinkApp(options) {
269983
269983
  if (options.name && !APP_NAME_RE.test(options.name)) {
269984
269984
  throw new InvalidInputError("The name becomes a directory — letters, digits, dots, dashes and underscores only.");
269985
269985
  }
269986
- const name = options.name ?? (options.importRepo ? repoBasename(options.importRepo) : inventAppName(options.prompt));
269987
- const targetDir = join21(process.cwd(), name);
269986
+ const cwd = process.cwd();
269987
+ const fallbackName = () => options.importRepo ? repoBasename(options.importRepo) : inventAppName(options.prompt);
269988
+ const chosenDir = options.path ? resolve6(cwd, options.path) : await isDirEmpty(cwd) ? cwd : undefined;
269989
+ const dirBase = chosenDir ? basename6(chosenDir) : undefined;
269990
+ const name = options.name ?? (dirBase && APP_NAME_RE.test(dirBase) ? dirBase : fallbackName());
269991
+ const targetDir = chosenDir ?? join21(cwd, name);
269992
+ const here = targetDir === cwd;
269993
+ const dirName = here ? "." : relative6(cwd, targetDir) || name;
269988
269994
  await mkdir3(targetDir, { recursive: true });
269989
269995
  if (await appConfigExists(targetDir)) {
269990
- throw new InvalidInputError(`./${name} is already linked to a Base44 app. Pick another name.`);
269996
+ throw new InvalidInputError(here ? "This directory is already linked to a Base44 app. Run `base44 code` here to keep building it, or pass --path for a new one." : `./${dirName} is already linked to a Base44 app. Pick another name or --path.`);
269991
269997
  }
269992
269998
  const created = options.importRepo ? await createImportedApp({
269993
269999
  appName: name,
@@ -270011,16 +270017,18 @@ async function createAndLinkApp(options) {
270011
270017
  id: created.id,
270012
270018
  editorUrl: `${getBase44ApiUrl()}/apps/${created.id}/editor/preview`,
270013
270019
  repoUrl: created.imported_repo_url ?? undefined,
270014
- dirName: name,
270015
- targetDir
270020
+ dirName,
270021
+ targetDir,
270022
+ here
270016
270023
  };
270017
270024
  }
270018
270025
  function nextStepsLines(app) {
270026
+ const cd = app.here ? "" : `cd ${app.dirName} && `;
270019
270027
  return [
270020
270028
  "",
270021
- `${source_default.bold("Your app lives in")} ./${app.dirName}`,
270022
- source_default.dim(` cd ${app.dirName} && base44 code # keep building with the agent`),
270023
- source_default.dim(` cd ${app.dirName} && base44 app send "…" # one non-interactive turn`)
270029
+ `${source_default.bold("Your app lives in")} ${app.here ? "./ (this directory)" : `./${app.dirName}`}`,
270030
+ source_default.dim(` ${cd}base44 code # keep building with the agent`),
270031
+ source_default.dim(` ${cd}base44 app send "…" # one non-interactive turn`)
270024
270032
  ];
270025
270033
  }
270026
270034
  async function githubReauthLines(error) {
@@ -270253,7 +270261,8 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
270253
270261
  importRepo: options.import,
270254
270262
  mode: options.mode,
270255
270263
  repoName: options.repoName,
270256
- fromBranch: options.fromBranch
270264
+ fromBranch: options.fromBranch,
270265
+ path: options.path
270257
270266
  }));
270258
270267
  } catch (error) {
270259
270268
  for (const line of await githubReauthLines(error) ?? [])
@@ -270264,7 +270273,7 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
270264
270273
  if (app.repoUrl)
270265
270274
  log.message(source_default.dim(`repo ${app.repoUrl}`));
270266
270275
  log.message(source_default.dim(`editor ${app.editorUrl}`));
270267
- log.message(source_default.dim(`linked ./${app.dirName}`));
270276
+ log.message(source_default.dim(`linked ${app.here ? "./ (this directory)" : `./${app.dirName}`}`));
270268
270277
  }
270269
270278
  let finalState;
270270
270279
  let previewUrl;
@@ -270323,7 +270332,7 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
270323
270332
  }
270324
270333
  function getNewCommand() {
270325
270334
  const command = new Base44Command("new", { requireAppContext: false });
270326
- command.description("Create an app and start building: from a prompt (the Base44 template), or over an existing GitHub repo with --import").argument("[prompt]", "What to build; the first agent turn starts immediately").option("--import <repo>", "Build over an existing GitHub repository instead of the template").option("--mode <mode>", "How to import: direct, fork, or copy (default: direct)").option("--name <name>", "Directory and app name (invented when omitted)").option("--repo-name <name>", "Name for the new GitHub repo when forking/copying").option("--from-branch <name>", "Import a specific branch of the repo").action(newAction);
270335
+ command.description("Create an app and start building: from a prompt (the Base44 template), or over an existing GitHub repo with --import").argument("[prompt]", "What to build; the first agent turn starts immediately").option("--import <repo>", "Build over an existing GitHub repository instead of the template").option("--mode <mode>", "How to import: direct, fork, or copy (default: direct)").option("--name <name>", "Directory and app name (invented when omitted)").option("--path <dir>", "Directory to link (default: the current directory when empty, else ./<name>)").option("--repo-name <name>", "Name for the new GitHub repo when forking/copying").option("--from-branch <name>", "Import a specific branch of the repo").action(newAction);
270327
270336
  return command;
270328
270337
  }
270329
270338
 
@@ -270533,7 +270542,7 @@ function getAuthPushCommand() {
270533
270542
  }
270534
270543
 
270535
270544
  // src/cli/commands/auth/social-login.ts
270536
- import { dirname as dirname17, join as join24, resolve as resolve6 } from "node:path";
270545
+ import { dirname as dirname17, join as join24, resolve as resolve7 } from "node:path";
270537
270546
  var PROVIDER_LABELS = {
270538
270547
  google: "Google",
270539
270548
  microsoft: "Microsoft",
@@ -270573,7 +270582,7 @@ async function socialLoginAction({ log, isNonInteractive, runTask }, provider, a
270573
270582
  let clientSecret;
270574
270583
  if (useCustomOAuth && oauth && oauthCli && hasSecretOptions(options)) {
270575
270584
  if (options.envFile) {
270576
- const secrets = await parseEnvFile(resolve6(options.envFile));
270585
+ const secrets = await parseEnvFile(resolve7(options.envFile));
270577
270586
  const value = secrets[oauthCli.envVar];
270578
270587
  if (!value) {
270579
270588
  throw new InvalidInputError(`Key "${oauthCli.envVar}" not found in ${options.envFile}.`);
@@ -270629,7 +270638,7 @@ function getSocialLoginCommand() {
270629
270638
  }
270630
270639
 
270631
270640
  // src/cli/commands/auth/sso.ts
270632
- import { dirname as dirname18, join as join25, resolve as resolve7 } from "node:path";
270641
+ import { dirname as dirname18, join as join25, resolve as resolve8 } from "node:path";
270633
270642
  var SSOConfigFileSchema = object({
270634
270643
  provider: _enum(Object.values(KNOWN_SSO_PROVIDERS)),
270635
270644
  clientId: string2(),
@@ -270645,7 +270654,7 @@ var SSOConfigFileSchema = object({
270645
270654
  ssoName: string2().optional()
270646
270655
  });
270647
270656
  async function loadSSOConfigFile(filePath) {
270648
- const resolved = resolve7(filePath);
270657
+ const resolved = resolve8(filePath);
270649
270658
  const raw = await readJsonFile(resolved);
270650
270659
  const result = SSOConfigFileSchema.safeParse(raw);
270651
270660
  if (!result.success) {
@@ -270733,7 +270742,7 @@ async function ssoEnableAction({ isNonInteractive, runTask }, options) {
270733
270742
  }
270734
270743
  let clientSecret;
270735
270744
  if (merged.envFile && !merged.clientSecret) {
270736
- const secrets = await parseEnvFile(resolve7(merged.envFile));
270745
+ const secrets = await parseEnvFile(resolve8(merged.envFile));
270737
270746
  const value = secrets.sso_client_secret;
270738
270747
  if (!value) {
270739
270748
  throw new InvalidInputError(`Key "sso_client_secret" not found in ${merged.envFile}.`);
@@ -276598,21 +276607,21 @@ async function runGenesisSession(options) {
276598
276607
 
276599
276608
  // src/cli/commands/code/index.ts
276600
276609
  var BRAND_ORANGE2 = "#E86B3C";
276601
- async function bootstrapApp(prompt, footer, emit, onCreated, importRepo) {
276610
+ async function bootstrapApp(prompt, footer, emit, onCreated, importRepo, path) {
276602
276611
  let app;
276603
276612
  try {
276604
- app = await createAndLinkApp({ prompt, importRepo });
276613
+ app = await createAndLinkApp({ prompt, importRepo, path });
276605
276614
  } catch (error) {
276606
276615
  for (const line of await githubReauthLines(error) ?? [])
276607
276616
  emit(line);
276608
276617
  throw error;
276609
276618
  }
276610
276619
  onCreated(app);
276611
- footer.push(source_default.dim(`dir ./${app.dirName}`));
276620
+ footer.push(source_default.dim(`dir ${app.here ? "./" : `./${app.dirName}`}`));
276612
276621
  if (app.repoUrl)
276613
276622
  footer.push(terminalLink("repo", app.repoUrl));
276614
276623
  footer.push(terminalLink("editor", app.editorUrl));
276615
- emit(source_default.dim(`linked ./${app.dirName} (cd ${app.dirName} after the session)`));
276624
+ emit(source_default.dim(app.here ? "linked ./ (this directory)" : `linked ./${app.dirName} (cd ${app.dirName} after the session)`));
276616
276625
  const branchId = await resolveActiveBranchId().catch(() => {
276617
276626
  return;
276618
276627
  });
@@ -276646,8 +276655,8 @@ async function codeAction({ log }, options) {
276646
276655
  linked = true;
276647
276656
  } catch {}
276648
276657
  if (linked) {
276649
- if (options.import) {
276650
- throw new InvalidInputError("--import creates a new app; run it outside a linked project.");
276658
+ if (options.import || options.path) {
276659
+ throw new InvalidInputError("--import and --path create a new app; run them outside a linked project.");
276651
276660
  }
276652
276661
  const branchId = await resolveActiveBranchId().catch(() => {
276653
276662
  return;
@@ -276675,7 +276684,7 @@ async function codeAction({ log }, options) {
276675
276684
  footer,
276676
276685
  createApp: (prompt, emit) => bootstrapApp(prompt, footer, emit, (app) => {
276677
276686
  created = app;
276678
- }, options.import)
276687
+ }, options.import, options.path)
276679
276688
  });
276680
276689
  if (!created) {
276681
276690
  return { outroMessage: "Session closed. No app was created." };
@@ -276687,7 +276696,7 @@ async function codeAction({ log }, options) {
276687
276696
  }
276688
276697
  function getCodeCommand() {
276689
276698
  const command = new Base44Command("code", { requireAppContext: false });
276690
- command.description("Open Base44 Code: an interactive agent session — in an empty directory your first prompt creates the app (add --import <repo> to build over an existing repository)").option("--import <repo>", "Build over an existing GitHub repository instead of the Base44 template").action(codeAction);
276699
+ command.description("Open Base44 Code: an interactive agent session — in an empty directory your first prompt creates the app (add --import <repo> to build over an existing repository)").option("--import <repo>", "Build over an existing GitHub repository instead of the Base44 template").option("--path <dir>", "Directory to link the new app to (default: the current directory when empty, else ./<name>)").action(codeAction);
276691
276700
  return command;
276692
276701
  }
276693
276702
 
@@ -277485,10 +277494,10 @@ function getConnectorsListAvailableCommand() {
277485
277494
  }
277486
277495
 
277487
277496
  // src/cli/commands/connectors/pull.ts
277488
- import { dirname as dirname19, join as join27, resolve as resolve8 } from "node:path";
277497
+ import { dirname as dirname19, join as join27, resolve as resolve9 } from "node:path";
277489
277498
  async function resolveConnectorsDir(options) {
277490
277499
  if (!getAppContext().projectRoot) {
277491
- return resolve8(options.dir ?? "connectors");
277500
+ return resolve9(options.dir ?? "connectors");
277492
277501
  }
277493
277502
  const { project } = await readProjectConfig();
277494
277503
  return join27(dirname19(project.configPath), project.connectorsDir);
@@ -277532,10 +277541,10 @@ function getConnectorsPullCommand() {
277532
277541
  }
277533
277542
 
277534
277543
  // src/cli/commands/connectors/push.ts
277535
- import { resolve as resolve9 } from "node:path";
277544
+ import { resolve as resolve10 } from "node:path";
277536
277545
  async function readConnectorsToPush(options) {
277537
277546
  if (!getAppContext().projectRoot) {
277538
- return readAllConnectors(resolve9(options.dir ?? "connectors"));
277547
+ return readAllConnectors(resolve10(options.dir ?? "connectors"));
277539
277548
  }
277540
277549
  const { connectors } = await readProjectConfig();
277541
277550
  return connectors;
@@ -278004,7 +278013,7 @@ function getBuildCommand() {
278004
278013
  }
278005
278014
 
278006
278015
  // src/cli/commands/project/create.ts
278007
- import { basename as basename6, resolve as resolve10 } from "node:path";
278016
+ import { basename as basename7, resolve as resolve11 } from "node:path";
278008
278017
  var import_kebabCase2 = __toESM(require_kebabCase(), 1);
278009
278018
 
278010
278019
  // src/cli/commands/project/scaffold-shared.ts
@@ -278169,8 +278178,8 @@ async function createInteractive(options, ctx) {
278169
278178
  name: () => {
278170
278179
  return options.name ? Promise.resolve(options.name) : Ze({
278171
278180
  message: "What is the name of your project?",
278172
- placeholder: basename6(process.cwd()),
278173
- initialValue: basename6(process.cwd()),
278181
+ placeholder: basename7(process.cwd()),
278182
+ initialValue: basename7(process.cwd()),
278174
278183
  validate: (value) => {
278175
278184
  if (!value || value.trim().length === 0) {
278176
278185
  return "Every project deserves a name";
@@ -278200,7 +278209,7 @@ async function createInteractive(options, ctx) {
278200
278209
  }, ctx);
278201
278210
  }
278202
278211
  async function createNonInteractive(options, ctx) {
278203
- ctx.log.info(`Creating a new project at ${resolve10(options.path)}`);
278212
+ ctx.log.info(`Creating a new project at ${resolve11(options.path)}`);
278204
278213
  const template = await getTemplateById(options.template ?? DEFAULT_TEMPLATE_ID);
278205
278214
  return await executeCreate({
278206
278215
  template,
@@ -278224,7 +278233,7 @@ async function executeCreate({
278224
278233
  }, ctx) {
278225
278234
  const { log, runTask } = ctx;
278226
278235
  const name = rawName.trim();
278227
- const resolvedPath = resolve10(projectPath);
278236
+ const resolvedPath = resolve11(projectPath);
278228
278237
  const organizationId = await resolveWorkspaceId(ctx, flagWorkspaceId, isInteractive);
278229
278238
  const { projectId } = await runTask("Setting up your project...", async () => {
278230
278239
  return await createProjectFiles({
@@ -278865,7 +278874,7 @@ function getLogsCommand() {
278865
278874
  }
278866
278875
 
278867
278876
  // src/cli/commands/project/scaffold.ts
278868
- import { basename as basename7, resolve as resolve11 } from "node:path";
278877
+ import { basename as basename8, resolve as resolve12 } from "node:path";
278869
278878
  function resolveAppId(options) {
278870
278879
  const appId = options.appId;
278871
278880
  if (!appId) {
@@ -278881,8 +278890,8 @@ function resolveAppId(options) {
278881
278890
  async function scaffoldAction(ctx, name, options, command) {
278882
278891
  const { log, runTask } = ctx;
278883
278892
  const appId = resolveAppId(command.optsWithGlobals());
278884
- const resolvedPath = resolve11("./");
278885
- const projectName = (name ?? basename7(resolvedPath)).trim();
278893
+ const resolvedPath = resolve12("./");
278894
+ const projectName = (name ?? basename8(resolvedPath)).trim();
278886
278895
  const template = await getTemplateById("backend-only");
278887
278896
  log.info(`Scaffolding project at ${resolvedPath}`);
278888
278897
  const { projectId } = await runTask("Setting up your project...", async () => {
@@ -279298,7 +279307,7 @@ function getSecretsListCommand() {
279298
279307
  }
279299
279308
 
279300
279309
  // src/cli/commands/secrets/set.ts
279301
- import { resolve as resolve12 } from "node:path";
279310
+ import { resolve as resolve13 } from "node:path";
279302
279311
  function parseEntries(entries) {
279303
279312
  const secrets = {};
279304
279313
  for (const entry of entries) {
@@ -279329,7 +279338,7 @@ async function setSecretsAction({ log, runTask }, entries, options) {
279329
279338
  validateInput(entries, options);
279330
279339
  let secrets;
279331
279340
  if (options.envFile) {
279332
- secrets = await parseEnvFile(resolve12(options.envFile));
279341
+ secrets = await parseEnvFile(resolve13(options.envFile));
279333
279342
  if (Object.keys(secrets).length === 0) {
279334
279343
  throw new InvalidInputError("The env file contains no valid KEY=VALUE entries.");
279335
279344
  }
@@ -279358,7 +279367,7 @@ function getSecretsCommand() {
279358
279367
  }
279359
279368
 
279360
279369
  // src/cli/commands/site/deploy.ts
279361
- import { resolve as resolve13 } from "node:path";
279370
+ import { resolve as resolve14 } from "node:path";
279362
279371
  async function deployAction2(ctx, options) {
279363
279372
  const { isNonInteractive } = ctx;
279364
279373
  if (isNonInteractive && !options.yes) {
@@ -279436,7 +279445,7 @@ async function deployTarball({ runTask }, project) {
279436
279445
  }
279437
279446
  function siteOutputDir(project) {
279438
279447
  const outputDirectory = project.site?.outputDirectory;
279439
- return outputDirectory ? resolve13(project.root, outputDirectory) : null;
279448
+ return outputDirectory ? resolve14(project.root, outputDirectory) : null;
279440
279449
  }
279441
279450
  function getSiteDeployCommand() {
279442
279451
  const command = new Base44Command("deploy").description("Deploy built site files to Base44 hosting").option("-y, --yes", "Skip confirmation prompt").option("--build", "Build the site before deploying (skips the prompt)").option("--no-build", "Deploy without building (skips the prompt)");
@@ -281938,7 +281947,7 @@ function createCustomIntegrationRoutes(remoteProxy, logger) {
281938
281947
 
281939
281948
  // src/cli/dev/dev-server/watcher.ts
281940
281949
  import { EventEmitter as EventEmitter6 } from "node:events";
281941
- import { relative as relative9 } from "node:path";
281950
+ import { relative as relative10 } from "node:path";
281942
281951
 
281943
281952
  // ../../node_modules/chokidar/index.js
281944
281953
  import { EventEmitter as EventEmitter5 } from "node:events";
@@ -283623,7 +283632,7 @@ class WatchBase44 extends EventEmitter6 {
283623
283632
  ignoreInitial: true
283624
283633
  });
283625
283634
  watcher.on("all", import_debounce4.default(async (_event, path) => {
283626
- this.emit("change", name, relative9(targetPath, path));
283635
+ this.emit("change", name, relative10(targetPath, path));
283627
283636
  }, WATCH_DEBOUNCE_MS));
283628
283637
  watcher.on("error", (err) => {
283629
283638
  this.logger.error(`Watch handler failed for ${targetPath}`, err);
@@ -284133,7 +284142,7 @@ Examples:
284133
284142
  }
284134
284143
 
284135
284144
  // src/cli/commands/project/eject.ts
284136
- import { resolve as resolve17 } from "node:path";
284145
+ import { resolve as resolve18 } from "node:path";
284137
284146
  var import_kebabCase3 = __toESM(require_kebabCase(), 1);
284138
284147
  async function eject(ctx, options, command) {
284139
284148
  const { log, runTask, isNonInteractive } = ctx;
@@ -284197,7 +284206,7 @@ async function eject(ctx, options, command) {
284197
284206
  Ne("Operation cancelled.");
284198
284207
  throw new CLIExitError(0);
284199
284208
  }
284200
- const resolvedPath = resolve17(selectedPath);
284209
+ const resolvedPath = resolve18(selectedPath);
284201
284210
  await runTask("Downloading your project's code...", async (updateMessage) => {
284202
284211
  await createProjectFilesForExistingProject({
284203
284212
  projectId,
@@ -288334,4 +288343,4 @@ export {
288334
288343
  runCLI
288335
288344
  };
288336
288345
 
288337
- //# debugId=72FC25F5FAAAB35A64756E2164756E21
288346
+ //# debugId=291EFF5BA3908B9064756E2164756E21