@base44-preview/cli 0.0.54-pr.538.e94d5b7 → 0.0.54-pr.539.4825ad9
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 +111 -143
- package/dist/cli/index.js.map +15 -15
- package/package.json +1 -1
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
|
|
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
|
|
235171
|
+
return false;
|
|
235161
235172
|
}
|
|
235162
|
-
|
|
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
|
|
235165
|
-
expiresAt:
|
|
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
|
-
|
|
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 scaffold` to set up 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 scaffold\` sets up a project 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 scaffold` to set up 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
|
|
@@ -253263,129 +253297,6 @@ function printStripeResult(r, log) {
|
|
|
253263
253297
|
log.info(` Connectors dashboard: ${theme.colors.links(getConnectorsUrl())}`);
|
|
253264
253298
|
}
|
|
253265
253299
|
|
|
253266
|
-
// src/cli/commands/project/init.ts
|
|
253267
|
-
import { basename as basename4, resolve as resolve6 } from "node:path";
|
|
253268
|
-
function resolveAppId(options) {
|
|
253269
|
-
const appId = options.appId ?? process.env.BASE44_APP_ID;
|
|
253270
|
-
if (!appId) {
|
|
253271
|
-
throw new InvalidInputError("No app ID found. `base44 init` scaffolds a local project for an existing Base44 app.", {
|
|
253272
|
-
hints: [
|
|
253273
|
-
{ message: "Pass it explicitly with --app-id <id>" },
|
|
253274
|
-
{
|
|
253275
|
-
message: "Or set BASE44_APP_ID (the Stripe Projects CLI writes it to .env via `stripe projects env --pull`)"
|
|
253276
|
-
}
|
|
253277
|
-
]
|
|
253278
|
-
});
|
|
253279
|
-
}
|
|
253280
|
-
return appId;
|
|
253281
|
-
}
|
|
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);
|
|
253294
|
-
const { projectId, skippedFiles } = await runTask2("Setting up your project...", async () => {
|
|
253295
|
-
return await initProjectFiles({
|
|
253296
|
-
name: name2,
|
|
253297
|
-
description: description?.trim(),
|
|
253298
|
-
path: resolvedPath,
|
|
253299
|
-
template: template2,
|
|
253300
|
-
appId
|
|
253301
|
-
});
|
|
253302
|
-
}, {
|
|
253303
|
-
successMessage: theme.colors.base44Orange("Project created successfully"),
|
|
253304
|
-
errorMessage: "Failed to create project"
|
|
253305
|
-
});
|
|
253306
|
-
if (skippedFiles.length > 0) {
|
|
253307
|
-
log.info(`Kept existing file${skippedFiles.length > 1 ? "s" : ""}: ${skippedFiles.join(", ")}`);
|
|
253308
|
-
}
|
|
253309
|
-
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,
|
|
253365
|
-
skills: options.skills,
|
|
253366
|
-
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);
|
|
253377
|
-
}
|
|
253378
|
-
function getInitCommand() {
|
|
253379
|
-
return new Base44Command("init", {
|
|
253380
|
-
requireAppConfig: false,
|
|
253381
|
-
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", `
|
|
253383
|
-
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);
|
|
253387
|
-
}
|
|
253388
|
-
|
|
253389
253300
|
// src/cli/commands/project/link.ts
|
|
253390
253301
|
function validateNonInteractiveFlags2(command2) {
|
|
253391
253302
|
const { create: create4, name: name2, projectId } = command2.opts();
|
|
@@ -253655,6 +253566,63 @@ function getLogsCommand() {
|
|
|
253655
253566
|
return new Base44Command("logs").description("Fetch function logs for this app").option("--function <names>", "Filter by function name(s), comma-separated. If omitted, fetches logs for all project functions").option("--since <datetime>", "Show logs from this time (ISO format)", normalizeDatetime).option("--until <datetime>", "Show logs until this time (ISO format)", normalizeDatetime).addOption(new Option("--level <level>", "Filter by log level").choices([...LogLevelSchema.options]).hideHelp()).option("-n, --limit <n>", "Results per page (1-1000, default: 50)").addOption(new Option("--order <order>", "Sort order").choices(["asc", "desc"])).action(logsAction);
|
|
253656
253567
|
}
|
|
253657
253568
|
|
|
253569
|
+
// src/cli/commands/project/scaffold.ts
|
|
253570
|
+
import { basename as basename4, resolve as resolve6 } from "node:path";
|
|
253571
|
+
function resolveAppId(options) {
|
|
253572
|
+
const appId = options.appId ?? process.env.BASE44_APP_ID;
|
|
253573
|
+
if (!appId) {
|
|
253574
|
+
throw new InvalidInputError("No app ID found. `base44 scaffold` sets up a local project for an existing Base44 app.", {
|
|
253575
|
+
hints: [
|
|
253576
|
+
{ message: "Pass it explicitly with --app-id <id>" },
|
|
253577
|
+
{
|
|
253578
|
+
message: "Or set the BASE44_APP_ID environment variable (e.g. via .env)"
|
|
253579
|
+
}
|
|
253580
|
+
]
|
|
253581
|
+
});
|
|
253582
|
+
}
|
|
253583
|
+
return appId;
|
|
253584
|
+
}
|
|
253585
|
+
async function scaffoldAction({ log, runTask: runTask2 }, name2, options) {
|
|
253586
|
+
const appId = resolveAppId(options);
|
|
253587
|
+
const resolvedPath = resolve6("./");
|
|
253588
|
+
const projectName = (name2 ?? basename4(resolvedPath)).trim();
|
|
253589
|
+
const template2 = await getTemplateById("backend-only");
|
|
253590
|
+
log.info(`Scaffolding project at ${resolvedPath}`);
|
|
253591
|
+
const { projectId, skippedFiles } = await runTask2("Setting up your project...", async () => {
|
|
253592
|
+
return await initProjectFiles({
|
|
253593
|
+
name: projectName,
|
|
253594
|
+
path: resolvedPath,
|
|
253595
|
+
template: template2,
|
|
253596
|
+
appId
|
|
253597
|
+
});
|
|
253598
|
+
}, {
|
|
253599
|
+
successMessage: theme.colors.base44Orange("Project created successfully"),
|
|
253600
|
+
errorMessage: "Failed to create project"
|
|
253601
|
+
});
|
|
253602
|
+
if (skippedFiles.length > 0) {
|
|
253603
|
+
log.info(`Kept existing file${skippedFiles.length > 1 ? "s" : ""}: ${skippedFiles.join(", ")}`);
|
|
253604
|
+
}
|
|
253605
|
+
setAppConfig({ id: projectId, projectRoot: resolvedPath });
|
|
253606
|
+
return await completeProjectSetup({
|
|
253607
|
+
projectId,
|
|
253608
|
+
name: projectName,
|
|
253609
|
+
resolvedPath,
|
|
253610
|
+
deploy: false,
|
|
253611
|
+
skills: options.skills,
|
|
253612
|
+
isInteractive: false
|
|
253613
|
+
}, { log, runTask: runTask2 });
|
|
253614
|
+
}
|
|
253615
|
+
function getScaffoldCommand() {
|
|
253616
|
+
return new Base44Command("scaffold", {
|
|
253617
|
+
requireAppConfig: false,
|
|
253618
|
+
fullBanner: true
|
|
253619
|
+
}).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", `
|
|
253620
|
+
Examples:
|
|
253621
|
+
$ base44 scaffold Scaffolds the current dir for $BASE44_APP_ID
|
|
253622
|
+
$ base44 scaffold --app-id app_123 Scaffolds the current dir for the given app
|
|
253623
|
+
$ base44 scaffold my-app --app-id app_123 Scaffolds the current dir, named "my-app"`).action(scaffoldAction);
|
|
253624
|
+
}
|
|
253625
|
+
|
|
253658
253626
|
// src/cli/commands/secrets/delete.ts
|
|
253659
253627
|
async function deleteSecretAction({ runTask: runTask2 }, key) {
|
|
253660
253628
|
await runTask2(`Deleting secret "${key}"`, async () => {
|
|
@@ -257549,7 +257517,7 @@ function createProgram(context) {
|
|
|
257549
257517
|
program2.addCommand(getWhoamiCommand());
|
|
257550
257518
|
program2.addCommand(getLogoutCommand());
|
|
257551
257519
|
program2.addCommand(getCreateCommand());
|
|
257552
|
-
program2.addCommand(
|
|
257520
|
+
program2.addCommand(getScaffoldCommand());
|
|
257553
257521
|
program2.addCommand(getDashboardCommand());
|
|
257554
257522
|
program2.addCommand(getDeployCommand2());
|
|
257555
257523
|
program2.addCommand(getLinkCommand());
|
|
@@ -261810,4 +261778,4 @@ export {
|
|
|
261810
261778
|
CLIExitError
|
|
261811
261779
|
};
|
|
261812
261780
|
|
|
261813
|
-
//# debugId=
|
|
261781
|
+
//# debugId=F9E7F25C4BCCD31164756E2164756E21
|