@base44-preview/cli 0.0.54-pr.538.e94d5b7 → 0.0.54-pr.539.90f90ec

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
@@ -235154,24 +235154,39 @@ function getTestOverrides() {
235154
235154
  // src/core/auth/config.ts
235155
235155
  var TOKEN_REFRESH_BUFFER_MS = 60 * 1000;
235156
235156
  var refreshPromise = null;
235157
- function readEnvAuth() {
235157
+ function decodeJwtClaims(token) {
235158
+ const parts = token.split(".");
235159
+ if (parts.length !== 3) {
235160
+ return null;
235161
+ }
235162
+ try {
235163
+ return JSON.parse(Buffer.from(parts[1], "base64url").toString("utf8"));
235164
+ } catch {
235165
+ return null;
235166
+ }
235167
+ }
235168
+ async function seedAuthFromEnv() {
235158
235169
  const accessToken = process.env.BASE44_ACCESS_TOKEN;
235159
235170
  if (!accessToken) {
235160
- return null;
235171
+ return false;
235161
235172
  }
235162
- return {
235173
+ const refreshToken = process.env.BASE44_REFRESH_TOKEN;
235174
+ const claims = decodeJwtClaims(accessToken);
235175
+ const sub = typeof claims?.sub === "string" ? claims.sub : undefined;
235176
+ const exp = typeof claims?.exp === "number" ? claims.exp : undefined;
235177
+ if (!refreshToken || !sub || !exp) {
235178
+ return false;
235179
+ }
235180
+ await writeAuth({
235163
235181
  accessToken,
235164
- refreshToken: process.env.BASE44_REFRESH_TOKEN ?? "",
235165
- expiresAt: Number.POSITIVE_INFINITY,
235166
- email: "",
235167
- name: ""
235168
- };
235182
+ refreshToken,
235183
+ expiresAt: exp * 1000,
235184
+ email: sub,
235185
+ name: sub
235186
+ });
235187
+ return true;
235169
235188
  }
235170
235189
  async function readAuth() {
235171
- const envAuth = readEnvAuth();
235172
- if (envAuth) {
235173
- return envAuth;
235174
- }
235175
235190
  try {
235176
235191
  const authData = await readJsonFile(getAuthFilePath());
235177
235192
  const result = AuthDataSchema.safeParse(authData);
@@ -235208,9 +235223,6 @@ function isTokenExpired(auth) {
235208
235223
  return Date.now() >= auth.expiresAt - TOKEN_REFRESH_BUFFER_MS;
235209
235224
  }
235210
235225
  async function refreshAndSaveTokens() {
235211
- if (readEnvAuth()) {
235212
- return null;
235213
- }
235214
235226
  if (refreshPromise) {
235215
235227
  return refreshPromise;
235216
235228
  }
@@ -244410,6 +244422,7 @@ async function login({
244410
244422
 
244411
244423
  // src/cli/utils/command/middleware.ts
244412
244424
  async function ensureAuth(ctx) {
244425
+ await seedAuthFromEnv();
244413
244426
  const loggedIn = await isLoggedIn();
244414
244427
  if (!loggedIn) {
244415
244428
  ctx.log.info("You need to login first to continue.");
@@ -251792,8 +251805,7 @@ function getLogoutCommand() {
251792
251805
  // src/cli/commands/auth/whoami.ts
251793
251806
  async function whoami(_ctx) {
251794
251807
  const auth2 = await readAuth();
251795
- const identity4 = auth2.email || "environment credentials";
251796
- return { outroMessage: `Logged in as: ${theme.styles.bold(identity4)}` };
251808
+ return { outroMessage: `Logged in as: ${theme.styles.bold(auth2.email)}` };
251797
251809
  }
251798
251810
  function getWhoamiCommand() {
251799
251811
  return new Base44Command("whoami", { requireAppConfig: false }).description("Display current authenticated user").action(whoami);
@@ -253140,6 +253152,28 @@ async function executeCreate({
253140
253152
  return await completeProjectSetup({ projectId, name: name2, resolvedPath, deploy: deploy5, skills, isInteractive }, { log, runTask: runTask2 });
253141
253153
  }
253142
253154
  async function createAction({ log, runTask: runTask2, isNonInteractive }, name2, options) {
253155
+ const existingAppId = process.env.BASE44_APP_ID;
253156
+ if (existingAppId && !options.force) {
253157
+ if (isNonInteractive) {
253158
+ throw new InvalidInputError(`BASE44_APP_ID is set (${existingAppId}) — this environment already has a Base44 app, so \`create\` won't make a new one.`, {
253159
+ hints: [
253160
+ {
253161
+ message: "Run `base44 init` to scaffold a project for the existing app"
253162
+ },
253163
+ { message: "Or pass --force to create a new app anyway" }
253164
+ ]
253165
+ });
253166
+ }
253167
+ const proceed = await Re({
253168
+ message: `BASE44_APP_ID is set (${existingAppId}). This environment already has a Base44 app — \`base44 init\` scaffolds for it, while \`create\` makes a new one. Create a new app anyway?`,
253169
+ initialValue: false
253170
+ });
253171
+ if (Ct(proceed) || !proceed) {
253172
+ return {
253173
+ outroMessage: "Run `base44 init` to scaffold a project for the existing app"
253174
+ };
253175
+ }
253176
+ }
253143
253177
  if (name2 && !options.path) {
253144
253178
  options.path = `./${import_kebabCase.default(name2)}`;
253145
253179
  }
@@ -253163,7 +253197,7 @@ function getCreateCommand() {
253163
253197
  return new Base44Command("create", {
253164
253198
  requireAppConfig: false,
253165
253199
  fullBanner: true
253166
- }).description("Create a new Base44 project").addArgument(new Argument("name", "Project name").argOptional()).option("-p, --path <path>", "Path where to create the project").option("-t, --template <id>", "Template ID (e.g., backend-only, backend-and-client)").option("--deploy", "Build and deploy the site").option("--no-skills", "Skip AI agent skills installation").addHelpText("after", `
253200
+ }).description("Create a new Base44 project").addArgument(new Argument("name", "Project name").argOptional()).option("-p, --path <path>", "Path where to create the project").option("-t, --template <id>", "Template ID (e.g., backend-only, backend-and-client)").option("--deploy", "Build and deploy the site").option("--no-skills", "Skip AI agent skills installation").option("--force", "Create a new app even when BASE44_APP_ID is set in the environment").addHelpText("after", `
253167
253201
  Examples:
253168
253202
  $ base44 create my-app Creates a base44 project at ./my-app
253169
253203
  $ base44 create my-todo-app --template backend-and-client Creates a base44 backend-and-client project at ./my-todo-app
@@ -253272,29 +253306,22 @@ function resolveAppId(options) {
253272
253306
  hints: [
253273
253307
  { message: "Pass it explicitly with --app-id <id>" },
253274
253308
  {
253275
- message: "Or set BASE44_APP_ID (the Stripe Projects CLI writes it to .env via `stripe projects env --pull`)"
253309
+ message: "Or set the BASE44_APP_ID environment variable (e.g. via .env)"
253276
253310
  }
253277
253311
  ]
253278
253312
  });
253279
253313
  }
253280
253314
  return appId;
253281
253315
  }
253282
- async function executeInit({
253283
- template: template2,
253284
- name: rawName,
253285
- description,
253286
- appId,
253287
- projectPath,
253288
- deploy: deploy5,
253289
- skills,
253290
- isInteractive
253291
- }, { log, runTask: runTask2 }) {
253292
- const name2 = rawName.trim();
253293
- const resolvedPath = resolve6(projectPath);
253316
+ async function initAction({ log, runTask: runTask2 }, name2, options) {
253317
+ const appId = resolveAppId(options);
253318
+ const resolvedPath = resolve6("./");
253319
+ const projectName = (name2 ?? basename4(resolvedPath)).trim();
253320
+ const template2 = await getTemplateById("backend-only");
253321
+ log.info(`Initializing project at ${resolvedPath}`);
253294
253322
  const { projectId, skippedFiles } = await runTask2("Setting up your project...", async () => {
253295
253323
  return await initProjectFiles({
253296
- name: name2,
253297
- description: description?.trim(),
253324
+ name: projectName,
253298
253325
  path: resolvedPath,
253299
253326
  template: template2,
253300
253327
  appId
@@ -253307,83 +253334,24 @@ async function executeInit({
253307
253334
  log.info(`Kept existing file${skippedFiles.length > 1 ? "s" : ""}: ${skippedFiles.join(", ")}`);
253308
253335
  }
253309
253336
  setAppConfig({ id: projectId, projectRoot: resolvedPath });
253310
- return await completeProjectSetup({ projectId, name: name2, resolvedPath, deploy: deploy5, skills, isInteractive }, { log, runTask: runTask2 });
253311
- }
253312
- async function initInteractive(appId, options, ctx) {
253313
- const templates = await listTemplates();
253314
- const templateOptions = templates.map((t) => ({
253315
- value: t,
253316
- label: t.name,
253317
- hint: t.description
253318
- }));
253319
- const result = await Oe({
253320
- template: () => Je({
253321
- message: "Pick an option",
253322
- options: templateOptions
253323
- }),
253324
- name: () => {
253325
- return options.name ? Promise.resolve(options.name) : Ze({
253326
- message: "What is the name of your project?",
253327
- placeholder: basename4(process.cwd()),
253328
- initialValue: basename4(process.cwd()),
253329
- validate: (value) => {
253330
- if (!value || value.trim().length === 0) {
253331
- return "Every project deserves a name";
253332
- }
253333
- }
253334
- });
253335
- },
253336
- projectPath: () => Ze({
253337
- message: "Where should we set up your project?",
253338
- placeholder: "./",
253339
- initialValue: options.path ?? "./"
253340
- })
253341
- }, {
253342
- onCancel: onPromptCancel
253343
- });
253344
- return await executeInit({
253345
- template: result.template,
253346
- name: result.name,
253347
- appId,
253348
- projectPath: result.projectPath,
253349
- deploy: options.deploy,
253350
- skills: options.skills,
253351
- isInteractive: true
253352
- }, ctx);
253353
- }
253354
- async function initNonInteractive(appId, options, ctx) {
253355
- const projectPath = options.path ?? "./";
253356
- const name2 = options.name ?? basename4(resolve6(projectPath));
253357
- ctx.log.info(`Initializing project at ${resolve6(projectPath)}`);
253358
- const template2 = await getTemplateById(options.template ?? DEFAULT_TEMPLATE_ID);
253359
- return await executeInit({
253360
- template: template2,
253361
- name: name2,
253362
- appId,
253363
- projectPath,
253364
- deploy: options.deploy,
253337
+ return await completeProjectSetup({
253338
+ projectId,
253339
+ name: projectName,
253340
+ resolvedPath,
253341
+ deploy: false,
253365
253342
  skills: options.skills,
253366
253343
  isInteractive: false
253367
- }, ctx);
253368
- }
253369
- async function initAction({ log, runTask: runTask2, isNonInteractive }, name2, options) {
253370
- const appId = resolveAppId(options);
253371
- const opts = { ...options, name: options.name ?? name2 };
253372
- const ctx = { log, runTask: runTask2 };
253373
- if (isNonInteractive) {
253374
- return await initNonInteractive(appId, opts, ctx);
253375
- }
253376
- return await initInteractive(appId, opts, ctx);
253344
+ }, { log, runTask: runTask2 });
253377
253345
  }
253378
253346
  function getInitCommand() {
253379
253347
  return new Base44Command("init", {
253380
253348
  requireAppConfig: false,
253381
253349
  fullBanner: true
253382
- }).description("Scaffold a local project for an existing Base44 app (e.g. one provisioned by the Stripe Projects CLI)").addArgument(new Argument("name", "Project name").argOptional()).option("--app-id <id>", "Existing Base44 app ID (defaults to the BASE44_APP_ID environment variable)").option("-p, --path <path>", "Path where to set up the project (defaults to the current directory)").option("-t, --template <id>", "Template ID (e.g., backend-only, backend-and-client)").option("--deploy", "Build and deploy the site").option("--no-skills", "Skip AI agent skills installation").addHelpText("after", `
253350
+ }).description("Scaffold a local project for an existing Base44 app").addArgument(new Argument("name", "Project name").argOptional()).option("--app-id <id>", "Existing Base44 app ID (defaults to the BASE44_APP_ID environment variable)").option("--no-skills", "Skip AI agent skills installation").addHelpText("after", `
253383
253351
  Examples:
253384
- $ base44 init Scaffolds in the current dir using $BASE44_APP_ID
253385
- $ base44 init --app-id app_123 Scaffolds in the current dir for the given app
253386
- $ base44 init my-app --app-id app_123 Scaffolds in the current dir named "my-app"`).action(initAction);
253352
+ $ base44 init Scaffolds the current dir for $BASE44_APP_ID
253353
+ $ base44 init --app-id app_123 Scaffolds the current dir for the given app
253354
+ $ base44 init my-app --app-id app_123 Scaffolds the current dir, named "my-app"`).action(initAction);
253387
253355
  }
253388
253356
 
253389
253357
  // src/cli/commands/project/link.ts
@@ -261810,4 +261778,4 @@ export {
261810
261778
  CLIExitError
261811
261779
  };
261812
261780
 
261813
- //# debugId=7BE6B0F316AC51B064756E2164756E21
261781
+ //# debugId=607796543B00B4D764756E2164756E21