@base44-preview/cli 0.1.7-pr.585.44bc526 → 0.1.7-pr.585.818cbdc

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
@@ -23352,15 +23352,15 @@ var require_windows = __commonJS((exports, module) => {
23352
23352
  }
23353
23353
  return false;
23354
23354
  }
23355
- function checkStat(stat, path11, options) {
23356
- if (!stat.isSymbolicLink() && !stat.isFile()) {
23355
+ function checkStat(stat2, path11, options) {
23356
+ if (!stat2.isSymbolicLink() && !stat2.isFile()) {
23357
23357
  return false;
23358
23358
  }
23359
23359
  return checkPathExt(path11, options);
23360
23360
  }
23361
23361
  function isexe(path11, options, cb) {
23362
- fs14.stat(path11, function(er, stat) {
23363
- cb(er, er ? false : checkStat(stat, path11, options));
23362
+ fs14.stat(path11, function(er, stat2) {
23363
+ cb(er, er ? false : checkStat(stat2, path11, options));
23364
23364
  });
23365
23365
  }
23366
23366
  function sync(path11, options) {
@@ -23374,20 +23374,20 @@ var require_mode = __commonJS((exports, module) => {
23374
23374
  isexe.sync = sync;
23375
23375
  var fs14 = __require("fs");
23376
23376
  function isexe(path11, options, cb) {
23377
- fs14.stat(path11, function(er, stat) {
23378
- cb(er, er ? false : checkStat(stat, options));
23377
+ fs14.stat(path11, function(er, stat2) {
23378
+ cb(er, er ? false : checkStat(stat2, options));
23379
23379
  });
23380
23380
  }
23381
23381
  function sync(path11, options) {
23382
23382
  return checkStat(fs14.statSync(path11), options);
23383
23383
  }
23384
- function checkStat(stat, options) {
23385
- return stat.isFile() && checkMode(stat, options);
23384
+ function checkStat(stat2, options) {
23385
+ return stat2.isFile() && checkMode(stat2, options);
23386
23386
  }
23387
- function checkMode(stat, options) {
23388
- var mod = stat.mode;
23389
- var uid = stat.uid;
23390
- var gid = stat.gid;
23387
+ function checkMode(stat2, options) {
23388
+ var mod = stat2.mode;
23389
+ var uid = stat2.uid;
23390
+ var gid = stat2.gid;
23391
23391
  var myUid = options.uid !== undefined ? options.uid : process.getuid && process.getuid();
23392
23392
  var myGid = options.gid !== undefined ? options.gid : process.getgid && process.getgid();
23393
23393
  var u = parseInt("100", 8);
@@ -23419,12 +23419,12 @@ var require_isexe = __commonJS((exports, module) => {
23419
23419
  if (typeof Promise !== "function") {
23420
23420
  throw new TypeError("callback not provided");
23421
23421
  }
23422
- return new Promise(function(resolve3, reject) {
23422
+ return new Promise(function(resolve4, reject) {
23423
23423
  isexe(path11, options || {}, function(er, is) {
23424
23424
  if (er) {
23425
23425
  reject(er);
23426
23426
  } else {
23427
- resolve3(is);
23427
+ resolve4(is);
23428
23428
  }
23429
23429
  });
23430
23430
  });
@@ -23486,27 +23486,27 @@ var require_which = __commonJS((exports, module) => {
23486
23486
  opt = {};
23487
23487
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
23488
23488
  const found = [];
23489
- const step = (i) => new Promise((resolve3, reject) => {
23489
+ const step = (i) => new Promise((resolve4, reject) => {
23490
23490
  if (i === pathEnv.length)
23491
- return opt.all && found.length ? resolve3(found) : reject(getNotFoundError(cmd));
23491
+ return opt.all && found.length ? resolve4(found) : reject(getNotFoundError(cmd));
23492
23492
  const ppRaw = pathEnv[i];
23493
23493
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
23494
23494
  const pCmd = path11.join(pathPart, cmd);
23495
23495
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
23496
- resolve3(subStep(p, i, 0));
23496
+ resolve4(subStep(p, i, 0));
23497
23497
  });
23498
- const subStep = (p, i, ii) => new Promise((resolve3, reject) => {
23498
+ const subStep = (p, i, ii) => new Promise((resolve4, reject) => {
23499
23499
  if (ii === pathExt.length)
23500
- return resolve3(step(i + 1));
23500
+ return resolve4(step(i + 1));
23501
23501
  const ext = pathExt[ii];
23502
23502
  isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
23503
23503
  if (!er && is) {
23504
23504
  if (opt.all)
23505
23505
  found.push(p + ext);
23506
23506
  else
23507
- return resolve3(p + ext);
23507
+ return resolve4(p + ext);
23508
23508
  }
23509
- return resolve3(subStep(p, i, ii + 1));
23509
+ return resolve4(subStep(p, i, ii + 1));
23510
23510
  });
23511
23511
  });
23512
23512
  return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
@@ -248258,7 +248258,7 @@ async function createProjectFilesForExistingProject(options) {
248258
248258
  };
248259
248259
  }
248260
248260
  // src/core/project/deploy.ts
248261
- import { resolve as resolve4 } from "node:path";
248261
+ import { resolve as resolve3 } from "node:path";
248262
248262
 
248263
248263
  // src/core/site/api.ts
248264
248264
  async function uploadSite(archivePath) {
@@ -248361,13 +248361,473 @@ async function createArchive(pathToArchive, targetArchivePath) {
248361
248361
  cwd: pathToArchive
248362
248362
  }, ["."]);
248363
248363
  }
248364
- // src/core/site/deploy-app.ts
248365
- import { resolve as resolve3 } from "node:path";
248366
-
248364
+ // src/core/site/gate.ts
248365
+ var STATIC_DEPLOYMENTS_ENV = "BASE44_STATIC_DEPLOYMENTS";
248366
+ function staticDeploymentsEnabled(env2 = process.env) {
248367
+ const value = env2[STATIC_DEPLOYMENTS_ENV];
248368
+ return value === "1" || value === "true";
248369
+ }
248370
+ // src/core/site/manifest.ts
248371
+ import { createHash } from "node:crypto";
248372
+ import { readFile as readFile2, stat } from "node:fs/promises";
248373
+ import { basename as basename4, join as join15 } from "node:path";
248374
+ var MAX_ASSET_SIZE_BYTES = 25 * 1024 * 1024;
248375
+ var MAX_ASSET_COUNT = 1e5;
248376
+ var ASSETS_IGNORE_FILE = ".assetsignore";
248377
+ var ALWAYS_IGNORED = new Set([
248378
+ ASSETS_IGNORE_FILE,
248379
+ "wrangler.json",
248380
+ ".dev.vars"
248381
+ ]);
248382
+ function hashAsset(appId, content) {
248383
+ return createHash("sha256").update(Buffer.from(appId, "utf8")).update(content).digest("hex").slice(0, 32);
248384
+ }
248385
+ async function buildAssetManifest(assetsDir, appId) {
248386
+ const manifest = {};
248387
+ const filesByHash = new Map;
248388
+ const found = await globby("**/*", {
248389
+ cwd: assetsDir,
248390
+ dot: true,
248391
+ onlyFiles: true,
248392
+ followSymbolicLinks: false,
248393
+ ignoreFiles: [ASSETS_IGNORE_FILE]
248394
+ });
248395
+ const relativeFilePaths = found.filter((path11) => !ALWAYS_IGNORED.has(basename4(path11)));
248396
+ if (relativeFilePaths.length > MAX_ASSET_COUNT) {
248397
+ throw new InvalidInputError(`Too many static assets: found ${relativeFilePaths.length}, the limit is ${MAX_ASSET_COUNT} files.`);
248398
+ }
248399
+ for (const relativePath of relativeFilePaths.sort()) {
248400
+ const absolutePath = join15(assetsDir, ...relativePath.split("/"));
248401
+ const { size } = await stat(absolutePath);
248402
+ if (size > MAX_ASSET_SIZE_BYTES) {
248403
+ throw new InvalidInputError(`Static asset "${relativePath}" is ${size} bytes, which exceeds the 25 MiB per-file limit.`);
248404
+ }
248405
+ const content = await readFile2(absolutePath);
248406
+ const hash2 = hashAsset(appId, content);
248407
+ manifest[`/${relativePath}`] = { hash: hash2, size };
248408
+ if (!filesByHash.has(hash2)) {
248409
+ filesByHash.set(hash2, { absolutePath, hash: hash2, size });
248410
+ }
248411
+ }
248412
+ return { manifest, filesByHash };
248413
+ }
248367
248414
  // src/core/site/static-site.ts
248368
248415
  import { readFile as readFile4 } from "node:fs/promises";
248369
248416
  import { join as join16 } from "node:path";
248370
248417
 
248418
+ // src/core/utils/git.ts
248419
+ var GIT_HASH_PATTERN = /^[a-fA-F0-9]{7,64}$/;
248420
+ function isGitCommitHash(value) {
248421
+ return GIT_HASH_PATTERN.test(value);
248422
+ }
248423
+
248424
+ // src/core/site/upload.ts
248425
+ import { readFile as readFile3 } from "node:fs/promises";
248426
+ var UPLOAD_CONCURRENCY = 3;
248427
+ var MAX_ATTEMPTS_PER_UPLOAD = 3;
248428
+ var RETRY_BASE_DELAY_MS = 500;
248429
+ async function uploadPresignedAssets(uploads, assets, onProgress) {
248430
+ let uploadedFiles = 0;
248431
+ let nextUpload = 0;
248432
+ const worker = async () => {
248433
+ while (nextUpload < uploads.length) {
248434
+ const upload = uploads[nextUpload++];
248435
+ await uploadPresignedAssetWithRetry(upload, assets);
248436
+ uploadedFiles++;
248437
+ onProgress?.({ uploadedFiles, totalFiles: uploads.length });
248438
+ }
248439
+ };
248440
+ await Promise.all(Array.from({ length: Math.min(UPLOAD_CONCURRENCY, uploads.length) }, worker));
248441
+ }
248442
+ async function uploadPresignedAssetWithRetry(upload, assets) {
248443
+ const entry = assets.manifest[upload.path];
248444
+ const file2 = entry && assets.filesByHash.get(entry.hash);
248445
+ if (!file2) {
248446
+ throw new InternalError(`Server requested upload of unknown asset path: ${upload.path}`);
248447
+ }
248448
+ const content = await readFile3(file2.absolutePath);
248449
+ let lastError;
248450
+ for (let attempt = 0;attempt < MAX_ATTEMPTS_PER_UPLOAD; attempt++) {
248451
+ if (attempt > 0) {
248452
+ await sleep3(RETRY_BASE_DELAY_MS * 2 ** (attempt - 1));
248453
+ }
248454
+ try {
248455
+ await distribution_default.put(upload.url, {
248456
+ body: new Uint8Array(content),
248457
+ headers: { "Content-Type": upload.contentType },
248458
+ timeout: 120000,
248459
+ retry: 0
248460
+ });
248461
+ return;
248462
+ } catch (error48) {
248463
+ lastError = error48;
248464
+ }
248465
+ }
248466
+ throw await ApiError.fromHttpError(lastError, "uploading static assets");
248467
+ }
248468
+ function sleep3(ms) {
248469
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
248470
+ }
248471
+
248472
+ // src/core/site/static-site.ts
248473
+ async function deployStaticSite(options) {
248474
+ const { outputDir, gitHash, progress } = options;
248475
+ if (!isGitCommitHash(gitHash)) {
248476
+ throw new InvalidInputError(`'${gitHash}' is not a git commit hash.`);
248477
+ }
248478
+ const assets = await buildAssetManifest(outputDir, getAppContext().id);
248479
+ if (!assets.manifest["/index.html"]) {
248480
+ throw new InvalidInputError(`No index.html found in "${outputDir}" — a static site needs one at the output directory root.`);
248481
+ }
248482
+ const created = await createDeployment({
248483
+ git_hash: gitHash,
248484
+ asset_manifest: assets.manifest
248485
+ });
248486
+ progress?.onAssets?.({
248487
+ totalAssets: Object.keys(assets.manifest).length,
248488
+ newAssets: created.assetUploads?.uploads.length ?? 0
248489
+ });
248490
+ if (created.assetUploads) {
248491
+ await uploadPresignedAssets(created.assetUploads.uploads, assets, progress?.onAssetUpload);
248492
+ }
248493
+ const indexHtml = await readFile4(join16(outputDir, "index.html"));
248494
+ const finalized = await finalizeStaticDeployment(created.deploymentId, new Uint8Array(indexHtml));
248495
+ return { deploymentId: finalized.deploymentId };
248496
+ }
248497
+ // src/core/project/deploy.ts
248498
+ function hasResourcesToDeploy(projectData) {
248499
+ const {
248500
+ project,
248501
+ entities,
248502
+ functions,
248503
+ agents,
248504
+ agentSkills,
248505
+ connectors,
248506
+ authConfig
248507
+ } = projectData;
248508
+ const hasSite = Boolean(project.site?.outputDirectory);
248509
+ const hasEntities = entities.length > 0;
248510
+ const hasFunctions = functions.length > 0;
248511
+ const hasAgents = agents.length > 0;
248512
+ const hasAgentSkills = agentSkills.length > 0;
248513
+ const hasConnectors = connectors.length > 0;
248514
+ const hasAuthConfig = authConfig.length > 0;
248515
+ const hasVisibility = Boolean(project.visibility);
248516
+ return hasEntities || hasFunctions || hasAgents || hasAgentSkills || hasConnectors || hasAuthConfig || hasVisibility || hasSite;
248517
+ }
248518
+ async function deployAll(projectData, options) {
248519
+ const {
248520
+ project,
248521
+ entities,
248522
+ functions,
248523
+ agents,
248524
+ agentSkills,
248525
+ connectors,
248526
+ authConfig
248527
+ } = projectData;
248528
+ await setAppVisibility(project.visibility);
248529
+ if (project.visibility) {
248530
+ options?.onVisibilitySet?.(project.visibility);
248531
+ }
248532
+ await entityResource.push(entities);
248533
+ await deployFunctionsSequentially(functions, {
248534
+ onStart: options?.onFunctionStart,
248535
+ onResult: options?.onFunctionResult
248536
+ });
248537
+ await agentSkillResource.push(agentSkills);
248538
+ await agentResource.push(agents);
248539
+ await authConfigResource.push(authConfig);
248540
+ const skipConnectorSync = connectors.length === 0 && hasWorkspaceApiKeyAuth();
248541
+ const connectorResults = skipConnectorSync ? [] : (await pushConnectors(connectors)).results;
248542
+ if (project.site?.outputDirectory) {
248543
+ const outputDir = resolve3(project.root, project.site.outputDirectory);
248544
+ const { appUrl } = await deploySite(outputDir);
248545
+ return { appUrl, connectorResults };
248546
+ }
248547
+ return { connectorResults };
248548
+ }
248549
+ // src/core/clients/base44-client.ts
248550
+ var retriedRequests = new WeakSet;
248551
+ async function captureRequestBody(request, options) {
248552
+ if (request.body == null) {
248553
+ return;
248554
+ }
248555
+ try {
248556
+ const cloned = request.clone();
248557
+ const text = await cloned.text();
248558
+ options.context.__requestBody = text;
248559
+ } catch {}
248560
+ }
248561
+ async function handleUnauthorized(request, _options, response) {
248562
+ if (response.status !== 401) {
248563
+ return;
248564
+ }
248565
+ if (hasWorkspaceApiKeyAuth()) {
248566
+ return;
248567
+ }
248568
+ if (retriedRequests.has(request)) {
248569
+ return;
248570
+ }
248571
+ const newAccessToken = await refreshAndSaveTokens();
248572
+ if (!newAccessToken) {
248573
+ return;
248574
+ }
248575
+ retriedRequests.add(request);
248576
+ const requestId = request.headers.get("X-Request-ID");
248577
+ return distribution_default(request.clone(), {
248578
+ headers: {
248579
+ ...requestId && { "X-Request-ID": requestId },
248580
+ Authorization: `Bearer ${newAccessToken}`
248581
+ }
248582
+ });
248583
+ }
248584
+ var base44Client = distribution_default.create({
248585
+ prefixUrl: getBase44ApiUrl(),
248586
+ headers: {
248587
+ "User-Agent": "Base44 CLI"
248588
+ },
248589
+ hooks: {
248590
+ beforeRequest: [
248591
+ (request) => {
248592
+ request.headers.set("X-Request-ID", randomUUID2());
248593
+ },
248594
+ captureRequestBody,
248595
+ async (request) => {
248596
+ const workspaceApiKey = getWorkspaceApiKeyFromEnv();
248597
+ if (workspaceApiKey && isWorkspaceApiKey(workspaceApiKey)) {
248598
+ request.headers.set("api_key", workspaceApiKey);
248599
+ return;
248600
+ }
248601
+ try {
248602
+ const auth = await readAuth();
248603
+ if (isTokenExpired(auth)) {
248604
+ const newAccessToken = await refreshAndSaveTokens();
248605
+ if (newAccessToken) {
248606
+ request.headers.set("Authorization", `Bearer ${newAccessToken}`);
248607
+ return;
248608
+ }
248609
+ }
248610
+ request.headers.set("Authorization", `Bearer ${auth.accessToken}`);
248611
+ } catch {}
248612
+ }
248613
+ ],
248614
+ afterResponse: [handleUnauthorized]
248615
+ }
248616
+ });
248617
+ function getAppClient() {
248618
+ const { id } = getAppContext();
248619
+ return base44Client.extend({
248620
+ prefixUrl: new URL(`/api/apps/${id}/`, getBase44ApiUrl()).href
248621
+ });
248622
+ }
248623
+ function getSandboxClient(appId) {
248624
+ return base44Client.extend({
248625
+ prefixUrl: new URL(`/api/apps/${appId}/sandbox-bridge/`, getBase44ApiUrl()).href
248626
+ });
248627
+ }
248628
+ // src/core/clients/oauth-client.ts
248629
+ import { randomUUID as randomUUID3 } from "node:crypto";
248630
+ var oauthClient = distribution_default.create({
248631
+ prefixUrl: getBase44ApiUrl(),
248632
+ headers: {
248633
+ "User-Agent": "Base44 CLI"
248634
+ },
248635
+ hooks: {
248636
+ beforeRequest: [
248637
+ (request) => {
248638
+ request.headers.set("X-Request-ID", randomUUID3());
248639
+ }
248640
+ ]
248641
+ }
248642
+ });
248643
+ // src/core/auth/api.ts
248644
+ async function generateDeviceCode() {
248645
+ const response = await oauthClient.post("oauth/device/code", {
248646
+ json: {
248647
+ client_id: AUTH_CLIENT_ID,
248648
+ scope: "apps:read apps:write sandbox:write"
248649
+ },
248650
+ throwHttpErrors: false
248651
+ });
248652
+ if (!response.ok) {
248653
+ throw new ApiError(`Failed to generate device code: ${response.status} ${response.statusText}`, { statusCode: response.status });
248654
+ }
248655
+ const result = DeviceCodeResponseSchema.safeParse(await response.json());
248656
+ if (!result.success) {
248657
+ throw new SchemaValidationError("Invalid device code response from server", result.error);
248658
+ }
248659
+ return result.data;
248660
+ }
248661
+ async function getTokenFromDeviceCode(deviceCode) {
248662
+ const searchParams = new URLSearchParams;
248663
+ searchParams.set("grant_type", "urn:ietf:params:oauth:grant-type:device_code");
248664
+ searchParams.set("device_code", deviceCode);
248665
+ searchParams.set("client_id", AUTH_CLIENT_ID);
248666
+ const response = await oauthClient.post("oauth/token", {
248667
+ body: searchParams.toString(),
248668
+ headers: {
248669
+ "Content-Type": "application/x-www-form-urlencoded"
248670
+ },
248671
+ throwHttpErrors: false
248672
+ });
248673
+ const json2 = await response.json();
248674
+ if (!response.ok) {
248675
+ const errorResult = OAuthErrorSchema.safeParse(json2);
248676
+ if (!errorResult.success) {
248677
+ throw new SchemaValidationError("Token request failed", errorResult.error);
248678
+ }
248679
+ const { error: error48, error_description } = errorResult.data;
248680
+ if (error48 === "authorization_pending" || error48 === "slow_down") {
248681
+ return null;
248682
+ }
248683
+ throw new ApiError(error_description ?? `OAuth error: ${error48}`, {
248684
+ statusCode: response.status
248685
+ });
248686
+ }
248687
+ const result = TokenResponseSchema.safeParse(json2);
248688
+ if (!result.success) {
248689
+ throw new SchemaValidationError("Invalid token response from server", result.error);
248690
+ }
248691
+ return result.data;
248692
+ }
248693
+ async function renewAccessToken(refreshToken) {
248694
+ const searchParams = new URLSearchParams;
248695
+ searchParams.set("grant_type", "refresh_token");
248696
+ searchParams.set("refresh_token", refreshToken);
248697
+ searchParams.set("client_id", AUTH_CLIENT_ID);
248698
+ const response = await oauthClient.post("oauth/token", {
248699
+ body: searchParams.toString(),
248700
+ headers: {
248701
+ "Content-Type": "application/x-www-form-urlencoded"
248702
+ },
248703
+ throwHttpErrors: false
248704
+ });
248705
+ const json2 = await response.json();
248706
+ if (!response.ok) {
248707
+ const errorResult = OAuthErrorSchema.safeParse(json2);
248708
+ if (!errorResult.success) {
248709
+ throw new ApiError(`Token refresh failed: ${response.statusText}`, {
248710
+ statusCode: response.status
248711
+ });
248712
+ }
248713
+ const { error: error48, error_description } = errorResult.data;
248714
+ throw new ApiError(error_description ?? `OAuth error: ${error48}`, {
248715
+ statusCode: response.status
248716
+ });
248717
+ }
248718
+ const result = TokenResponseSchema.safeParse(json2);
248719
+ if (!result.success) {
248720
+ throw new SchemaValidationError("Invalid token response from server", result.error);
248721
+ }
248722
+ return result.data;
248723
+ }
248724
+ async function getUserInfo(accessToken) {
248725
+ const response = await oauthClient.get("oauth/userinfo", {
248726
+ headers: { Authorization: `Bearer ${accessToken}` }
248727
+ });
248728
+ if (!response.ok) {
248729
+ throw new ApiError(`Failed to fetch user info: ${response.status}`, {
248730
+ statusCode: response.status
248731
+ });
248732
+ }
248733
+ const result = UserInfoSchema.safeParse(await response.json());
248734
+ if (!result.success) {
248735
+ throw new SchemaValidationError("Invalid UserInfo response from server", result.error);
248736
+ }
248737
+ return result.data;
248738
+ }
248739
+ // src/cli/commands/auth/login-flow.ts
248740
+ async function generateAndDisplayDeviceCode(log, runTask) {
248741
+ const deviceCodeResponse = await runTask("Generating device code...", async () => {
248742
+ return await generateDeviceCode();
248743
+ }, {
248744
+ successMessage: "Device code generated",
248745
+ errorMessage: "Failed to generate device code"
248746
+ });
248747
+ log.info(`Verification code: ${theme.styles.bold(deviceCodeResponse.userCode)}` + `
248748
+ Please confirm this code at: ${deviceCodeResponse.verificationUri}`);
248749
+ return deviceCodeResponse;
248750
+ }
248751
+ async function waitForAuthentication(deviceCode, expiresIn, interval, runTask) {
248752
+ let tokenResponse;
248753
+ try {
248754
+ await runTask("Waiting for authentication...", async () => {
248755
+ await pWaitFor(async () => {
248756
+ const result = await getTokenFromDeviceCode(deviceCode);
248757
+ if (result !== null) {
248758
+ tokenResponse = result;
248759
+ return true;
248760
+ }
248761
+ return false;
248762
+ }, {
248763
+ interval: interval * 1000,
248764
+ timeout: expiresIn * 1000
248765
+ });
248766
+ }, {
248767
+ successMessage: "Authentication completed!",
248768
+ errorMessage: "Authentication failed"
248769
+ });
248770
+ } catch (error48) {
248771
+ if (error48 instanceof Error && error48.message.includes("timed out")) {
248772
+ throw new AuthExpiredError("Authentication timed out. Please try again.");
248773
+ }
248774
+ throw error48;
248775
+ }
248776
+ if (tokenResponse === undefined) {
248777
+ throw new InternalError("Failed to retrieve authentication token.");
248778
+ }
248779
+ return tokenResponse;
248780
+ }
248781
+ async function saveAuthData(response, userInfo) {
248782
+ const expiresAt = Date.now() + response.expiresIn * 1000;
248783
+ await writeAuth({
248784
+ accessToken: response.accessToken,
248785
+ refreshToken: response.refreshToken,
248786
+ expiresAt,
248787
+ email: userInfo.email,
248788
+ name: userInfo.name
248789
+ });
248790
+ }
248791
+ async function login({
248792
+ log,
248793
+ runTask
248794
+ }) {
248795
+ const deviceCodeResponse = await generateAndDisplayDeviceCode(log, runTask);
248796
+ const token = await waitForAuthentication(deviceCodeResponse.deviceCode, deviceCodeResponse.expiresIn, deviceCodeResponse.interval, runTask);
248797
+ const userInfo = await getUserInfo(token.accessToken);
248798
+ await saveAuthData(token, userInfo);
248799
+ return {
248800
+ outroMessage: `Successfully logged in as ${theme.styles.bold(userInfo.email)}`
248801
+ };
248802
+ }
248803
+
248804
+ // src/cli/utils/command/middleware.ts
248805
+ async function ensureAuth(ctx) {
248806
+ if (hasWorkspaceApiKeyAuth()) {
248807
+ ctx.errorReporter.setContext({
248808
+ user: { email: "workspace-api-key", name: "Workspace API key" }
248809
+ });
248810
+ return;
248811
+ }
248812
+ await seedAuthFromEnv();
248813
+ const loggedIn = await isLoggedIn();
248814
+ if (!loggedIn) {
248815
+ ctx.log.info("You need to login first to continue.");
248816
+ await login(ctx);
248817
+ }
248818
+ try {
248819
+ const userInfo = await readAuth();
248820
+ ctx.errorReporter.setContext({
248821
+ user: { email: userInfo.email, name: userInfo.name }
248822
+ });
248823
+ } catch {}
248824
+ }
248825
+ async function ensureAppContext(ctx, options = {}) {
248826
+ const appContext = await initAppContext(options);
248827
+ ctx.app = appContext;
248828
+ ctx.errorReporter.setContext({ appId: appContext.id });
248829
+ }
248830
+
248371
248831
  // ../../node_modules/is-plain-obj/index.js
248372
248832
  function isPlainObject2(value) {
248373
248833
  if (typeof value !== "object" || value === null) {
@@ -248465,13 +248925,13 @@ var getJoinLength = (uint8Arrays) => {
248465
248925
  var isTemplateString = (templates) => Array.isArray(templates) && Array.isArray(templates.raw);
248466
248926
  var parseTemplates = (templates, expressions) => {
248467
248927
  let tokens = [];
248468
- for (const [index, template] of templates.entries()) {
248928
+ for (const [index, template2] of templates.entries()) {
248469
248929
  tokens = parseTemplate({
248470
248930
  templates,
248471
248931
  expressions,
248472
248932
  tokens,
248473
248933
  index,
248474
- template
248934
+ template: template2
248475
248935
  });
248476
248936
  }
248477
248937
  if (tokens.length === 0) {
@@ -248480,11 +248940,11 @@ var parseTemplates = (templates, expressions) => {
248480
248940
  const [file2, ...commandArguments] = tokens;
248481
248941
  return [file2, commandArguments, {}];
248482
248942
  };
248483
- var parseTemplate = ({ templates, expressions, tokens, index, template }) => {
248484
- if (template === undefined) {
248943
+ var parseTemplate = ({ templates, expressions, tokens, index, template: template2 }) => {
248944
+ if (template2 === undefined) {
248485
248945
  throw new TypeError(`Invalid backslash sequence: ${templates.raw[index]}`);
248486
248946
  }
248487
- const { nextTokens, leadingWhitespaces, trailingWhitespaces } = splitByWhitespaces(template, templates.raw[index]);
248947
+ const { nextTokens, leadingWhitespaces, trailingWhitespaces } = splitByWhitespaces(template2, templates.raw[index]);
248488
248948
  const newTokens = concatTokens(tokens, nextTokens, leadingWhitespaces);
248489
248949
  if (index === expressions.length) {
248490
248950
  return newTokens;
@@ -248493,18 +248953,18 @@ var parseTemplate = ({ templates, expressions, tokens, index, template }) => {
248493
248953
  const expressionTokens = Array.isArray(expression) ? expression.map((expression2) => parseExpression(expression2)) : [parseExpression(expression)];
248494
248954
  return concatTokens(newTokens, expressionTokens, trailingWhitespaces);
248495
248955
  };
248496
- var splitByWhitespaces = (template, rawTemplate) => {
248956
+ var splitByWhitespaces = (template2, rawTemplate) => {
248497
248957
  if (rawTemplate.length === 0) {
248498
248958
  return { nextTokens: [], leadingWhitespaces: false, trailingWhitespaces: false };
248499
248959
  }
248500
248960
  const nextTokens = [];
248501
248961
  let templateStart = 0;
248502
248962
  const leadingWhitespaces = DELIMITERS.has(rawTemplate[0]);
248503
- for (let templateIndex = 0, rawIndex = 0;templateIndex < template.length; templateIndex += 1, rawIndex += 1) {
248963
+ for (let templateIndex = 0, rawIndex = 0;templateIndex < template2.length; templateIndex += 1, rawIndex += 1) {
248504
248964
  const rawCharacter = rawTemplate[rawIndex];
248505
248965
  if (DELIMITERS.has(rawCharacter)) {
248506
248966
  if (templateStart !== templateIndex) {
248507
- nextTokens.push(template.slice(templateStart, templateIndex));
248967
+ nextTokens.push(template2.slice(templateStart, templateIndex));
248508
248968
  }
248509
248969
  templateStart = templateIndex + 1;
248510
248970
  } else if (rawCharacter === "\\") {
@@ -248520,9 +248980,9 @@ var splitByWhitespaces = (template, rawTemplate) => {
248520
248980
  }
248521
248981
  }
248522
248982
  }
248523
- const trailingWhitespaces = templateStart === template.length;
248983
+ const trailingWhitespaces = templateStart === template2.length;
248524
248984
  if (!trailingWhitespaces) {
248525
- nextTokens.push(template.slice(templateStart));
248985
+ nextTokens.push(template2.slice(templateStart));
248526
248986
  }
248527
248987
  return { nextTokens, leadingWhitespaces, trailingWhitespaces };
248528
248988
  };
@@ -249916,8 +250376,8 @@ var disconnect = (anyProcess) => {
249916
250376
  // ../../node_modules/execa/lib/utils/deferred.js
249917
250377
  var createDeferred = () => {
249918
250378
  const methods = {};
249919
- const promise2 = new Promise((resolve3, reject) => {
249920
- Object.assign(methods, { resolve: resolve3, reject });
250379
+ const promise2 = new Promise((resolve4, reject) => {
250380
+ Object.assign(methods, { resolve: resolve4, reject });
249921
250381
  });
249922
250382
  return Object.assign(promise2, methods);
249923
250383
  };
@@ -254281,11 +254741,11 @@ var addConcurrentStream = (concurrentStreams, stream, waitName) => {
254281
254741
  const promises = weakMap.get(stream);
254282
254742
  const promise2 = createDeferred();
254283
254743
  promises.push(promise2);
254284
- const resolve3 = promise2.resolve.bind(promise2);
254285
- return { resolve: resolve3, promises };
254744
+ const resolve4 = promise2.resolve.bind(promise2);
254745
+ return { resolve: resolve4, promises };
254286
254746
  };
254287
- var waitForConcurrentStreams = async ({ resolve: resolve3, promises }, subprocess) => {
254288
- resolve3();
254747
+ var waitForConcurrentStreams = async ({ resolve: resolve4, promises }, subprocess) => {
254748
+ resolve4();
254289
254749
  const [isSubprocessExit] = await Promise.race([
254290
254750
  Promise.allSettled([true, subprocess]),
254291
254751
  Promise.all([false, ...promises])
@@ -254864,522 +255324,6 @@ var {
254864
255324
  getCancelSignal: getCancelSignal2
254865
255325
  } = getIpcExport();
254866
255326
 
254867
- // src/core/utils/git.ts
254868
- var GIT_HASH_PATTERN = /^[a-fA-F0-9]{7,64}$/;
254869
- function isGitCommitHash(value) {
254870
- return GIT_HASH_PATTERN.test(value);
254871
- }
254872
- async function getGitHead(cwd) {
254873
- try {
254874
- const { stdout } = await execa("git", ["rev-parse", "HEAD"], { cwd });
254875
- return stdout.trim();
254876
- } catch {
254877
- return null;
254878
- }
254879
- }
254880
-
254881
- // src/core/site/manifest.ts
254882
- import { createHash } from "node:crypto";
254883
- import { readFile as readFile2, stat } from "node:fs/promises";
254884
- import { basename as basename4, join as join15 } from "node:path";
254885
- var MAX_ASSET_SIZE_BYTES = 25 * 1024 * 1024;
254886
- var MAX_ASSET_COUNT = 1e5;
254887
- var ASSETS_IGNORE_FILE = ".assetsignore";
254888
- var ALWAYS_IGNORED = new Set([
254889
- ASSETS_IGNORE_FILE,
254890
- "wrangler.json",
254891
- ".dev.vars"
254892
- ]);
254893
- function hashAsset(appId, content) {
254894
- return createHash("sha256").update(Buffer.from(appId, "utf8")).update(content).digest("hex").slice(0, 32);
254895
- }
254896
- async function buildAssetManifest(assetsDir, appId) {
254897
- const manifest = {};
254898
- const filesByHash = new Map;
254899
- const found = await globby("**/*", {
254900
- cwd: assetsDir,
254901
- dot: true,
254902
- onlyFiles: true,
254903
- followSymbolicLinks: false,
254904
- ignoreFiles: [ASSETS_IGNORE_FILE]
254905
- });
254906
- const relativeFilePaths = found.filter((path16) => !ALWAYS_IGNORED.has(basename4(path16)));
254907
- if (relativeFilePaths.length > MAX_ASSET_COUNT) {
254908
- throw new InvalidInputError(`Too many static assets: found ${relativeFilePaths.length}, the limit is ${MAX_ASSET_COUNT} files.`);
254909
- }
254910
- for (const relativePath of relativeFilePaths.sort()) {
254911
- const absolutePath = join15(assetsDir, ...relativePath.split("/"));
254912
- const { size } = await stat(absolutePath);
254913
- if (size > MAX_ASSET_SIZE_BYTES) {
254914
- throw new InvalidInputError(`Static asset "${relativePath}" is ${size} bytes, which exceeds the 25 MiB per-file limit.`);
254915
- }
254916
- const content = await readFile2(absolutePath);
254917
- const hash2 = hashAsset(appId, content);
254918
- manifest[`/${relativePath}`] = { hash: hash2, size };
254919
- if (!filesByHash.has(hash2)) {
254920
- filesByHash.set(hash2, { absolutePath, hash: hash2, size });
254921
- }
254922
- }
254923
- return { manifest, filesByHash };
254924
- }
254925
-
254926
- // src/core/site/upload.ts
254927
- import { readFile as readFile3 } from "node:fs/promises";
254928
- var UPLOAD_CONCURRENCY = 3;
254929
- var MAX_ATTEMPTS_PER_UPLOAD = 3;
254930
- var RETRY_BASE_DELAY_MS = 500;
254931
- async function uploadPresignedAssets(uploads, assets, onProgress) {
254932
- let uploadedFiles = 0;
254933
- let nextUpload = 0;
254934
- const worker = async () => {
254935
- while (nextUpload < uploads.length) {
254936
- const upload = uploads[nextUpload++];
254937
- await uploadPresignedAssetWithRetry(upload, assets);
254938
- uploadedFiles++;
254939
- onProgress?.({ uploadedFiles, totalFiles: uploads.length });
254940
- }
254941
- };
254942
- await Promise.all(Array.from({ length: Math.min(UPLOAD_CONCURRENCY, uploads.length) }, worker));
254943
- }
254944
- async function uploadPresignedAssetWithRetry(upload, assets) {
254945
- const entry = assets.manifest[upload.path];
254946
- const file2 = entry && assets.filesByHash.get(entry.hash);
254947
- if (!file2) {
254948
- throw new InternalError(`Server requested upload of unknown asset path: ${upload.path}`);
254949
- }
254950
- const content = await readFile3(file2.absolutePath);
254951
- let lastError;
254952
- for (let attempt = 0;attempt < MAX_ATTEMPTS_PER_UPLOAD; attempt++) {
254953
- if (attempt > 0) {
254954
- await sleep3(RETRY_BASE_DELAY_MS * 2 ** (attempt - 1));
254955
- }
254956
- try {
254957
- await distribution_default.put(upload.url, {
254958
- body: new Uint8Array(content),
254959
- headers: { "Content-Type": upload.contentType },
254960
- timeout: 120000,
254961
- retry: 0
254962
- });
254963
- return;
254964
- } catch (error48) {
254965
- lastError = error48;
254966
- }
254967
- }
254968
- throw await ApiError.fromHttpError(lastError, "uploading static assets");
254969
- }
254970
- function sleep3(ms) {
254971
- return new Promise((resolve3) => setTimeout(resolve3, ms));
254972
- }
254973
-
254974
- // src/core/site/static-site.ts
254975
- async function deployStaticSite(options) {
254976
- const { outputDir, projectRoot, progress } = options;
254977
- const gitHash = await resolveGitHash(projectRoot, options.gitHash);
254978
- const assets = await buildAssetManifest(outputDir, getAppContext().id);
254979
- if (!assets.manifest["/index.html"]) {
254980
- throw new InvalidInputError(`No index.html found in "${outputDir}" — a static site needs one at the output directory root.`);
254981
- }
254982
- const created = await createDeployment({
254983
- git_hash: gitHash,
254984
- asset_manifest: assets.manifest
254985
- });
254986
- progress?.onAssets?.({
254987
- totalAssets: Object.keys(assets.manifest).length,
254988
- newAssets: created.assetUploads?.uploads.length ?? 0
254989
- });
254990
- if (created.assetUploads) {
254991
- await uploadPresignedAssets(created.assetUploads.uploads, assets, progress?.onAssetUpload);
254992
- }
254993
- const indexHtml = await readFile4(join16(outputDir, "index.html"));
254994
- const finalized = await finalizeStaticDeployment(created.deploymentId, new Uint8Array(indexHtml));
254995
- return { deploymentId: finalized.deploymentId, gitHash };
254996
- }
254997
- async function resolveGitHash(projectRoot, explicit) {
254998
- const hash2 = explicit ?? await getGitHead(projectRoot);
254999
- if (!hash2 || !isGitCommitHash(hash2)) {
255000
- throw new InvalidInputError(explicit ? `'${explicit}' is not a git commit hash.` : "Deployments are addressed by the commit that produced the build, and no git commit was found.", {
255001
- hints: [
255002
- {
255003
- message: "Run the deploy from a git checkout, or pass the commit explicitly: base44 site deploy --git-hash <commit>."
255004
- }
255005
- ]
255006
- });
255007
- }
255008
- return hash2;
255009
- }
255010
-
255011
- // src/core/site/deploy-app.ts
255012
- function planAppDeploy(target, staticDeployments) {
255013
- const outputDirectory = target.site?.outputDirectory;
255014
- if (!outputDirectory) {
255015
- return { kind: "none" };
255016
- }
255017
- const outputDir = resolve3(target.root, outputDirectory);
255018
- return staticDeployments ? { kind: "static-deployment", outputDir } : { kind: "static", outputDir };
255019
- }
255020
- function detectAppDeployKind(target, options = {}) {
255021
- return planAppDeploy(target, options.staticDeployments ?? false).kind;
255022
- }
255023
- async function deployAppSite(target, options = {}) {
255024
- const plan = planAppDeploy(target, options.staticDeployments ?? false);
255025
- switch (plan.kind) {
255026
- case "static-deployment": {
255027
- const { deploymentId, gitHash } = await deployStaticSite({
255028
- outputDir: plan.outputDir,
255029
- projectRoot: target.root,
255030
- gitHash: options.gitHash,
255031
- progress: options.progress
255032
- });
255033
- return { kind: "static-deployment", deploymentId, gitHash };
255034
- }
255035
- case "static": {
255036
- const { appUrl } = await deploySite(plan.outputDir);
255037
- return { kind: "static", appUrl };
255038
- }
255039
- case "none":
255040
- return { kind: "none" };
255041
- }
255042
- }
255043
- // src/core/site/gate.ts
255044
- var STATIC_DEPLOYMENTS_ENV = "BASE44_STATIC_DEPLOYMENTS";
255045
- function staticDeploymentsEnabled(env2 = process.env) {
255046
- const value = env2[STATIC_DEPLOYMENTS_ENV];
255047
- return value === "1" || value === "true";
255048
- }
255049
- // src/core/project/deploy.ts
255050
- function hasResourcesToDeploy(projectData) {
255051
- const {
255052
- project,
255053
- entities,
255054
- functions,
255055
- agents,
255056
- agentSkills,
255057
- connectors,
255058
- authConfig
255059
- } = projectData;
255060
- const hasSite = Boolean(project.site?.outputDirectory);
255061
- const hasEntities = entities.length > 0;
255062
- const hasFunctions = functions.length > 0;
255063
- const hasAgents = agents.length > 0;
255064
- const hasAgentSkills = agentSkills.length > 0;
255065
- const hasConnectors = connectors.length > 0;
255066
- const hasAuthConfig = authConfig.length > 0;
255067
- const hasVisibility = Boolean(project.visibility);
255068
- return hasEntities || hasFunctions || hasAgents || hasAgentSkills || hasConnectors || hasAuthConfig || hasVisibility || hasSite;
255069
- }
255070
- async function deployAll(projectData, options) {
255071
- const {
255072
- project,
255073
- entities,
255074
- functions,
255075
- agents,
255076
- agentSkills,
255077
- connectors,
255078
- authConfig
255079
- } = projectData;
255080
- await setAppVisibility(project.visibility);
255081
- if (project.visibility) {
255082
- options?.onVisibilitySet?.(project.visibility);
255083
- }
255084
- await entityResource.push(entities);
255085
- await deployFunctionsSequentially(functions, {
255086
- onStart: options?.onFunctionStart,
255087
- onResult: options?.onFunctionResult
255088
- });
255089
- await agentSkillResource.push(agentSkills);
255090
- await agentResource.push(agents);
255091
- await authConfigResource.push(authConfig);
255092
- const skipConnectorSync = connectors.length === 0 && hasWorkspaceApiKeyAuth();
255093
- const connectorResults = skipConnectorSync ? [] : (await pushConnectors(connectors)).results;
255094
- if (project.site?.outputDirectory) {
255095
- const outputDir = resolve4(project.root, project.site.outputDirectory);
255096
- const { appUrl } = await deploySite(outputDir);
255097
- return { appUrl, connectorResults };
255098
- }
255099
- return { connectorResults };
255100
- }
255101
- // src/core/clients/base44-client.ts
255102
- var retriedRequests = new WeakSet;
255103
- async function captureRequestBody(request, options) {
255104
- if (request.body == null) {
255105
- return;
255106
- }
255107
- try {
255108
- const cloned = request.clone();
255109
- const text = await cloned.text();
255110
- options.context.__requestBody = text;
255111
- } catch {}
255112
- }
255113
- async function handleUnauthorized(request, _options, response) {
255114
- if (response.status !== 401) {
255115
- return;
255116
- }
255117
- if (hasWorkspaceApiKeyAuth()) {
255118
- return;
255119
- }
255120
- if (retriedRequests.has(request)) {
255121
- return;
255122
- }
255123
- const newAccessToken = await refreshAndSaveTokens();
255124
- if (!newAccessToken) {
255125
- return;
255126
- }
255127
- retriedRequests.add(request);
255128
- const requestId = request.headers.get("X-Request-ID");
255129
- return distribution_default(request.clone(), {
255130
- headers: {
255131
- ...requestId && { "X-Request-ID": requestId },
255132
- Authorization: `Bearer ${newAccessToken}`
255133
- }
255134
- });
255135
- }
255136
- var base44Client = distribution_default.create({
255137
- prefixUrl: getBase44ApiUrl(),
255138
- headers: {
255139
- "User-Agent": "Base44 CLI"
255140
- },
255141
- hooks: {
255142
- beforeRequest: [
255143
- (request) => {
255144
- request.headers.set("X-Request-ID", randomUUID2());
255145
- },
255146
- captureRequestBody,
255147
- async (request) => {
255148
- const workspaceApiKey = getWorkspaceApiKeyFromEnv();
255149
- if (workspaceApiKey && isWorkspaceApiKey(workspaceApiKey)) {
255150
- request.headers.set("api_key", workspaceApiKey);
255151
- return;
255152
- }
255153
- try {
255154
- const auth = await readAuth();
255155
- if (isTokenExpired(auth)) {
255156
- const newAccessToken = await refreshAndSaveTokens();
255157
- if (newAccessToken) {
255158
- request.headers.set("Authorization", `Bearer ${newAccessToken}`);
255159
- return;
255160
- }
255161
- }
255162
- request.headers.set("Authorization", `Bearer ${auth.accessToken}`);
255163
- } catch {}
255164
- }
255165
- ],
255166
- afterResponse: [handleUnauthorized]
255167
- }
255168
- });
255169
- function getAppClient() {
255170
- const { id } = getAppContext();
255171
- return base44Client.extend({
255172
- prefixUrl: new URL(`/api/apps/${id}/`, getBase44ApiUrl()).href
255173
- });
255174
- }
255175
- function getSandboxClient(appId) {
255176
- return base44Client.extend({
255177
- prefixUrl: new URL(`/api/apps/${appId}/sandbox-bridge/`, getBase44ApiUrl()).href
255178
- });
255179
- }
255180
- // src/core/clients/oauth-client.ts
255181
- import { randomUUID as randomUUID3 } from "node:crypto";
255182
- var oauthClient = distribution_default.create({
255183
- prefixUrl: getBase44ApiUrl(),
255184
- headers: {
255185
- "User-Agent": "Base44 CLI"
255186
- },
255187
- hooks: {
255188
- beforeRequest: [
255189
- (request) => {
255190
- request.headers.set("X-Request-ID", randomUUID3());
255191
- }
255192
- ]
255193
- }
255194
- });
255195
- // src/core/auth/api.ts
255196
- async function generateDeviceCode() {
255197
- const response = await oauthClient.post("oauth/device/code", {
255198
- json: {
255199
- client_id: AUTH_CLIENT_ID,
255200
- scope: "apps:read apps:write sandbox:write"
255201
- },
255202
- throwHttpErrors: false
255203
- });
255204
- if (!response.ok) {
255205
- throw new ApiError(`Failed to generate device code: ${response.status} ${response.statusText}`, { statusCode: response.status });
255206
- }
255207
- const result = DeviceCodeResponseSchema.safeParse(await response.json());
255208
- if (!result.success) {
255209
- throw new SchemaValidationError("Invalid device code response from server", result.error);
255210
- }
255211
- return result.data;
255212
- }
255213
- async function getTokenFromDeviceCode(deviceCode) {
255214
- const searchParams = new URLSearchParams;
255215
- searchParams.set("grant_type", "urn:ietf:params:oauth:grant-type:device_code");
255216
- searchParams.set("device_code", deviceCode);
255217
- searchParams.set("client_id", AUTH_CLIENT_ID);
255218
- const response = await oauthClient.post("oauth/token", {
255219
- body: searchParams.toString(),
255220
- headers: {
255221
- "Content-Type": "application/x-www-form-urlencoded"
255222
- },
255223
- throwHttpErrors: false
255224
- });
255225
- const json2 = await response.json();
255226
- if (!response.ok) {
255227
- const errorResult = OAuthErrorSchema.safeParse(json2);
255228
- if (!errorResult.success) {
255229
- throw new SchemaValidationError("Token request failed", errorResult.error);
255230
- }
255231
- const { error: error48, error_description } = errorResult.data;
255232
- if (error48 === "authorization_pending" || error48 === "slow_down") {
255233
- return null;
255234
- }
255235
- throw new ApiError(error_description ?? `OAuth error: ${error48}`, {
255236
- statusCode: response.status
255237
- });
255238
- }
255239
- const result = TokenResponseSchema.safeParse(json2);
255240
- if (!result.success) {
255241
- throw new SchemaValidationError("Invalid token response from server", result.error);
255242
- }
255243
- return result.data;
255244
- }
255245
- async function renewAccessToken(refreshToken) {
255246
- const searchParams = new URLSearchParams;
255247
- searchParams.set("grant_type", "refresh_token");
255248
- searchParams.set("refresh_token", refreshToken);
255249
- searchParams.set("client_id", AUTH_CLIENT_ID);
255250
- const response = await oauthClient.post("oauth/token", {
255251
- body: searchParams.toString(),
255252
- headers: {
255253
- "Content-Type": "application/x-www-form-urlencoded"
255254
- },
255255
- throwHttpErrors: false
255256
- });
255257
- const json2 = await response.json();
255258
- if (!response.ok) {
255259
- const errorResult = OAuthErrorSchema.safeParse(json2);
255260
- if (!errorResult.success) {
255261
- throw new ApiError(`Token refresh failed: ${response.statusText}`, {
255262
- statusCode: response.status
255263
- });
255264
- }
255265
- const { error: error48, error_description } = errorResult.data;
255266
- throw new ApiError(error_description ?? `OAuth error: ${error48}`, {
255267
- statusCode: response.status
255268
- });
255269
- }
255270
- const result = TokenResponseSchema.safeParse(json2);
255271
- if (!result.success) {
255272
- throw new SchemaValidationError("Invalid token response from server", result.error);
255273
- }
255274
- return result.data;
255275
- }
255276
- async function getUserInfo(accessToken) {
255277
- const response = await oauthClient.get("oauth/userinfo", {
255278
- headers: { Authorization: `Bearer ${accessToken}` }
255279
- });
255280
- if (!response.ok) {
255281
- throw new ApiError(`Failed to fetch user info: ${response.status}`, {
255282
- statusCode: response.status
255283
- });
255284
- }
255285
- const result = UserInfoSchema.safeParse(await response.json());
255286
- if (!result.success) {
255287
- throw new SchemaValidationError("Invalid UserInfo response from server", result.error);
255288
- }
255289
- return result.data;
255290
- }
255291
- // src/cli/commands/auth/login-flow.ts
255292
- async function generateAndDisplayDeviceCode(log, runTask) {
255293
- const deviceCodeResponse = await runTask("Generating device code...", async () => {
255294
- return await generateDeviceCode();
255295
- }, {
255296
- successMessage: "Device code generated",
255297
- errorMessage: "Failed to generate device code"
255298
- });
255299
- log.info(`Verification code: ${theme.styles.bold(deviceCodeResponse.userCode)}` + `
255300
- Please confirm this code at: ${deviceCodeResponse.verificationUri}`);
255301
- return deviceCodeResponse;
255302
- }
255303
- async function waitForAuthentication(deviceCode, expiresIn, interval, runTask) {
255304
- let tokenResponse;
255305
- try {
255306
- await runTask("Waiting for authentication...", async () => {
255307
- await pWaitFor(async () => {
255308
- const result = await getTokenFromDeviceCode(deviceCode);
255309
- if (result !== null) {
255310
- tokenResponse = result;
255311
- return true;
255312
- }
255313
- return false;
255314
- }, {
255315
- interval: interval * 1000,
255316
- timeout: expiresIn * 1000
255317
- });
255318
- }, {
255319
- successMessage: "Authentication completed!",
255320
- errorMessage: "Authentication failed"
255321
- });
255322
- } catch (error48) {
255323
- if (error48 instanceof Error && error48.message.includes("timed out")) {
255324
- throw new AuthExpiredError("Authentication timed out. Please try again.");
255325
- }
255326
- throw error48;
255327
- }
255328
- if (tokenResponse === undefined) {
255329
- throw new InternalError("Failed to retrieve authentication token.");
255330
- }
255331
- return tokenResponse;
255332
- }
255333
- async function saveAuthData(response, userInfo) {
255334
- const expiresAt = Date.now() + response.expiresIn * 1000;
255335
- await writeAuth({
255336
- accessToken: response.accessToken,
255337
- refreshToken: response.refreshToken,
255338
- expiresAt,
255339
- email: userInfo.email,
255340
- name: userInfo.name
255341
- });
255342
- }
255343
- async function login({
255344
- log,
255345
- runTask
255346
- }) {
255347
- const deviceCodeResponse = await generateAndDisplayDeviceCode(log, runTask);
255348
- const token = await waitForAuthentication(deviceCodeResponse.deviceCode, deviceCodeResponse.expiresIn, deviceCodeResponse.interval, runTask);
255349
- const userInfo = await getUserInfo(token.accessToken);
255350
- await saveAuthData(token, userInfo);
255351
- return {
255352
- outroMessage: `Successfully logged in as ${theme.styles.bold(userInfo.email)}`
255353
- };
255354
- }
255355
-
255356
- // src/cli/utils/command/middleware.ts
255357
- async function ensureAuth(ctx) {
255358
- if (hasWorkspaceApiKeyAuth()) {
255359
- ctx.errorReporter.setContext({
255360
- user: { email: "workspace-api-key", name: "Workspace API key" }
255361
- });
255362
- return;
255363
- }
255364
- await seedAuthFromEnv();
255365
- const loggedIn = await isLoggedIn();
255366
- if (!loggedIn) {
255367
- ctx.log.info("You need to login first to continue.");
255368
- await login(ctx);
255369
- }
255370
- try {
255371
- const userInfo = await readAuth();
255372
- ctx.errorReporter.setContext({
255373
- user: { email: userInfo.email, name: userInfo.name }
255374
- });
255375
- } catch {}
255376
- }
255377
- async function ensureAppContext(ctx, options = {}) {
255378
- const appContext = await initAppContext(options);
255379
- ctx.app = appContext;
255380
- ctx.errorReporter.setContext({ appId: appContext.id });
255381
- }
255382
-
255383
255327
  // src/cli/utils/version-check.ts
255384
255328
  async function checkForUpgrade() {
255385
255329
  const testLatestVersion = getTestOverrides()?.latestVersion;
@@ -256075,7 +256019,7 @@ function getAuthPushCommand() {
256075
256019
  }
256076
256020
 
256077
256021
  // src/cli/commands/auth/social-login.ts
256078
- import { dirname as dirname14, join as join21, resolve as resolve5 } from "node:path";
256022
+ import { dirname as dirname14, join as join21, resolve as resolve4 } from "node:path";
256079
256023
  var PROVIDER_LABELS = {
256080
256024
  google: "Google",
256081
256025
  microsoft: "Microsoft",
@@ -256115,7 +256059,7 @@ async function socialLoginAction({ log, isNonInteractive, runTask: runTask2 }, p
256115
256059
  let clientSecret;
256116
256060
  if (useCustomOAuth && oauth && oauthCli && hasSecretOptions(options)) {
256117
256061
  if (options.envFile) {
256118
- const secrets = await parseEnvFile(resolve5(options.envFile));
256062
+ const secrets = await parseEnvFile(resolve4(options.envFile));
256119
256063
  const value = secrets[oauthCli.envVar];
256120
256064
  if (!value) {
256121
256065
  throw new InvalidInputError(`Key "${oauthCli.envVar}" not found in ${options.envFile}.`);
@@ -256171,7 +256115,7 @@ function getSocialLoginCommand() {
256171
256115
  }
256172
256116
 
256173
256117
  // src/cli/commands/auth/sso.ts
256174
- import { dirname as dirname15, join as join22, resolve as resolve6 } from "node:path";
256118
+ import { dirname as dirname15, join as join22, resolve as resolve5 } from "node:path";
256175
256119
  var SSOConfigFileSchema = exports_external.object({
256176
256120
  provider: exports_external.enum(Object.values(KNOWN_SSO_PROVIDERS)),
256177
256121
  clientId: exports_external.string(),
@@ -256187,7 +256131,7 @@ var SSOConfigFileSchema = exports_external.object({
256187
256131
  ssoName: exports_external.string().optional()
256188
256132
  });
256189
256133
  async function loadSSOConfigFile(filePath) {
256190
- const resolved = resolve6(filePath);
256134
+ const resolved = resolve5(filePath);
256191
256135
  const raw2 = await readJsonFile(resolved);
256192
256136
  const result = SSOConfigFileSchema.safeParse(raw2);
256193
256137
  if (!result.success) {
@@ -256275,7 +256219,7 @@ async function ssoEnableAction({ isNonInteractive, runTask: runTask2 }, options)
256275
256219
  }
256276
256220
  let clientSecret;
256277
256221
  if (merged.envFile && !merged.clientSecret) {
256278
- const secrets2 = await parseEnvFile(resolve6(merged.envFile));
256222
+ const secrets2 = await parseEnvFile(resolve5(merged.envFile));
256279
256223
  const value = secrets2.sso_client_secret;
256280
256224
  if (!value) {
256281
256225
  throw new InvalidInputError(`Key "sso_client_secret" not found in ${merged.envFile}.`);
@@ -256913,19 +256857,19 @@ var baseOpen = async (options) => {
256913
256857
  }
256914
256858
  const subprocess = childProcess3.spawn(command2, cliArguments, childProcessOptions);
256915
256859
  if (options.wait) {
256916
- return new Promise((resolve7, reject) => {
256860
+ return new Promise((resolve6, reject) => {
256917
256861
  subprocess.once("error", reject);
256918
256862
  subprocess.once("close", (exitCode) => {
256919
256863
  if (!options.allowNonzeroExitCode && exitCode !== 0) {
256920
256864
  reject(new Error(`Exited with code ${exitCode}`));
256921
256865
  return;
256922
256866
  }
256923
- resolve7(subprocess);
256867
+ resolve6(subprocess);
256924
256868
  });
256925
256869
  });
256926
256870
  }
256927
256871
  if (isFallbackAttempt) {
256928
- return new Promise((resolve7, reject) => {
256872
+ return new Promise((resolve6, reject) => {
256929
256873
  subprocess.once("error", reject);
256930
256874
  subprocess.once("spawn", () => {
256931
256875
  subprocess.once("close", (exitCode) => {
@@ -256935,17 +256879,17 @@ var baseOpen = async (options) => {
256935
256879
  return;
256936
256880
  }
256937
256881
  subprocess.unref();
256938
- resolve7(subprocess);
256882
+ resolve6(subprocess);
256939
256883
  });
256940
256884
  });
256941
256885
  });
256942
256886
  }
256943
256887
  subprocess.unref();
256944
- return new Promise((resolve7, reject) => {
256888
+ return new Promise((resolve6, reject) => {
256945
256889
  subprocess.once("error", reject);
256946
256890
  subprocess.once("spawn", () => {
256947
256891
  subprocess.off("error", reject);
256948
- resolve7(subprocess);
256892
+ resolve6(subprocess);
256949
256893
  });
256950
256894
  });
256951
256895
  };
@@ -257208,10 +257152,10 @@ function getConnectorsListAvailableCommand() {
257208
257152
  }
257209
257153
 
257210
257154
  // src/cli/commands/connectors/pull.ts
257211
- import { dirname as dirname16, join as join23, resolve as resolve7 } from "node:path";
257155
+ import { dirname as dirname16, join as join23, resolve as resolve6 } from "node:path";
257212
257156
  async function resolveConnectorsDir(options) {
257213
257157
  if (!getAppContext().projectRoot) {
257214
- return resolve7(options.dir ?? "connectors");
257158
+ return resolve6(options.dir ?? "connectors");
257215
257159
  }
257216
257160
  const { project: project2 } = await readProjectConfig();
257217
257161
  return join23(dirname16(project2.configPath), project2.connectorsDir);
@@ -257255,10 +257199,10 @@ function getConnectorsPullCommand() {
257255
257199
  }
257256
257200
 
257257
257201
  // src/cli/commands/connectors/push.ts
257258
- import { resolve as resolve8 } from "node:path";
257202
+ import { resolve as resolve7 } from "node:path";
257259
257203
  async function readConnectorsToPush(options) {
257260
257204
  if (!getAppContext().projectRoot) {
257261
- return readAllConnectors(resolve8(options.dir ?? "connectors"));
257205
+ return readAllConnectors(resolve7(options.dir ?? "connectors"));
257262
257206
  }
257263
257207
  const { connectors } = await readProjectConfig();
257264
257208
  return connectors;
@@ -257759,7 +257703,7 @@ function getBuildCommand() {
257759
257703
  }
257760
257704
 
257761
257705
  // src/cli/commands/project/create.ts
257762
- import { basename as basename5, resolve as resolve9 } from "node:path";
257706
+ import { basename as basename5, resolve as resolve8 } from "node:path";
257763
257707
  var import_kebabCase = __toESM(require_kebabCase(), 1);
257764
257708
 
257765
257709
  // src/cli/commands/project/scaffold-shared.ts
@@ -257951,7 +257895,7 @@ async function createInteractive(options, ctx) {
257951
257895
  }, ctx);
257952
257896
  }
257953
257897
  async function createNonInteractive(options, ctx) {
257954
- ctx.log.info(`Creating a new project at ${resolve9(options.path)}`);
257898
+ ctx.log.info(`Creating a new project at ${resolve8(options.path)}`);
257955
257899
  const template2 = await getTemplateById(options.template ?? DEFAULT_TEMPLATE_ID);
257956
257900
  return await executeCreate({
257957
257901
  template: template2,
@@ -257975,7 +257919,7 @@ async function executeCreate({
257975
257919
  }, ctx) {
257976
257920
  const { log, runTask: runTask2 } = ctx;
257977
257921
  const name2 = rawName.trim();
257978
- const resolvedPath = resolve9(projectPath);
257922
+ const resolvedPath = resolve8(projectPath);
257979
257923
  const organizationId = await resolveWorkspaceId(ctx, flagWorkspaceId, isInteractive);
257980
257924
  const { projectId } = await runTask2("Setting up your project...", async () => {
257981
257925
  return await createProjectFiles({
@@ -258382,7 +258326,7 @@ async function followLogs(functionNames, options, availableFunctionNames, jsonMo
258382
258326
  for (const entry of fresh)
258383
258327
  writeFollowLine(entry, jsonMode);
258384
258328
  first = false;
258385
- await new Promise((resolve10) => setTimeout(resolve10, 2000));
258329
+ await new Promise((resolve9) => setTimeout(resolve9, 2000));
258386
258330
  }
258387
258331
  }
258388
258332
  function formatLogs(entries, env3) {
@@ -258496,7 +258440,7 @@ function getLogsCommand() {
258496
258440
  }
258497
258441
 
258498
258442
  // src/cli/commands/project/scaffold.ts
258499
- import { basename as basename6, resolve as resolve10 } from "node:path";
258443
+ import { basename as basename6, resolve as resolve9 } from "node:path";
258500
258444
  function resolveAppId(options) {
258501
258445
  const appId = options.appId;
258502
258446
  if (!appId) {
@@ -258512,7 +258456,7 @@ function resolveAppId(options) {
258512
258456
  async function scaffoldAction(ctx, name2, options, command2) {
258513
258457
  const { log, runTask: runTask2 } = ctx;
258514
258458
  const appId = resolveAppId(command2.optsWithGlobals());
258515
- const resolvedPath = resolve10("./");
258459
+ const resolvedPath = resolve9("./");
258516
258460
  const projectName = (name2 ?? basename6(resolvedPath)).trim();
258517
258461
  const template2 = await getTemplateById("backend-only");
258518
258462
  log.info(`Scaffolding project at ${resolvedPath}`);
@@ -258909,7 +258853,7 @@ function getSecretsListCommand() {
258909
258853
  }
258910
258854
 
258911
258855
  // src/cli/commands/secrets/set.ts
258912
- import { resolve as resolve11 } from "node:path";
258856
+ import { resolve as resolve10 } from "node:path";
258913
258857
  function parseEntries(entries) {
258914
258858
  const secrets = {};
258915
258859
  for (const entry of entries) {
@@ -258940,7 +258884,7 @@ async function setSecretsAction({ log, runTask: runTask2 }, entries, options) {
258940
258884
  validateInput(entries, options);
258941
258885
  let secrets;
258942
258886
  if (options.envFile) {
258943
- secrets = await parseEnvFile(resolve11(options.envFile));
258887
+ secrets = await parseEnvFile(resolve10(options.envFile));
258944
258888
  if (Object.keys(secrets).length === 0) {
258945
258889
  throw new InvalidInputError("The env file contains no valid KEY=VALUE entries.");
258946
258890
  }
@@ -258968,49 +258912,8 @@ function getSecretsCommand() {
258968
258912
  return new Command("secrets").description("Manage project secrets (environment variables)").addCommand(getSecretsListCommand()).addCommand(getSecretsSetCommand()).addCommand(getSecretsDeleteCommand());
258969
258913
  }
258970
258914
 
258971
- // src/cli/commands/site/run-app-deploy.ts
258972
- var TASK_LABELS = {
258973
- "static-deployment": {
258974
- start: "Deploying site...",
258975
- success: "Site deployed",
258976
- error: "Site deploy failed"
258977
- },
258978
- static: {
258979
- start: "Creating archive and deploying site...",
258980
- success: "Site deployed successfully",
258981
- error: "Deployment failed"
258982
- }
258983
- };
258984
- async function runAppSiteDeploy({ runTask: runTask2, log, staticDeployments }, target, options = {}) {
258985
- const kind = detectAppDeployKind(target, { staticDeployments });
258986
- if (kind === "none")
258987
- return { kind: "none" };
258988
- const labels = TASK_LABELS[kind];
258989
- const progressLines = [];
258990
- const result = await runTask2(labels.start, async (updateMessage) => await deployAppSite(target, {
258991
- staticDeployments,
258992
- gitHash: options.gitHash,
258993
- progress: {
258994
- onAssets: ({ totalAssets, newAssets }) => {
258995
- const line = `Found ${totalAssets} static assets (${newAssets} new)`;
258996
- progressLines.push(line);
258997
- updateMessage(line);
258998
- },
258999
- onAssetUpload: ({ uploadedFiles, totalFiles }) => {
259000
- updateMessage(`Uploaded ${uploadedFiles} of ${totalFiles} assets`);
259001
- }
259002
- }
259003
- }), {
259004
- successMessage: labels.success,
259005
- errorMessage: labels.error
259006
- });
259007
- for (const line of progressLines) {
259008
- log.message(theme.styles.dim(line));
259009
- }
259010
- return result;
259011
- }
259012
-
259013
258915
  // src/cli/commands/site/deploy.ts
258916
+ import { resolve as resolve11 } from "node:path";
259014
258917
  async function deployAction2(ctx, options) {
259015
258918
  const { isNonInteractive } = ctx;
259016
258919
  if (isNonInteractive && !options.yes) {
@@ -259036,25 +258939,45 @@ async function deployAction2(ctx, options) {
259036
258939
  }
259037
258940
  }
259038
258941
  await maybeBuildBeforeDeploy(ctx, project2, options.build);
259039
- const result = await runAppSiteDeploy(ctx, project2, {
259040
- gitHash: options.gitHash
259041
- });
259042
- if (result.kind === "static-deployment") {
259043
- return {
259044
- outroMessage: `Deployment ${result.deploymentId} (commit ${result.gitHash.slice(0, 12)})`,
259045
- stdout: ctx.jsonMode ? `${JSON.stringify({ deploymentId: result.deploymentId, gitHash: result.gitHash }, null, 2)}
259046
- ` : undefined
259047
- };
259048
- }
259049
- if (result.kind === "static") {
259050
- return { outroMessage: `Visit your site at: ${result.appUrl}` };
258942
+ const outputDir = resolve11(project2.root, outputDirectory);
258943
+ return options.gitHash ? await deployToDeploymentsApi(ctx, outputDir, options.gitHash) : await deployTarball(ctx, outputDir);
258944
+ }
258945
+ async function deployToDeploymentsApi({ runTask: runTask2, log, jsonMode }, outputDir, gitHash) {
258946
+ const progressLines = [];
258947
+ const { deploymentId } = await runTask2("Deploying site...", async (updateMessage) => await deployStaticSite({
258948
+ outputDir,
258949
+ gitHash,
258950
+ progress: {
258951
+ onAssets: ({ totalAssets, newAssets }) => {
258952
+ const line = `Found ${totalAssets} static assets (${newAssets} new)`;
258953
+ progressLines.push(line);
258954
+ updateMessage(line);
258955
+ },
258956
+ onAssetUpload: ({ uploadedFiles, totalFiles }) => {
258957
+ updateMessage(`Uploaded ${uploadedFiles} of ${totalFiles} assets`);
258958
+ }
258959
+ }
258960
+ }), { successMessage: "Site deployed", errorMessage: "Site deploy failed" });
258961
+ for (const line of progressLines) {
258962
+ log.message(theme.styles.dim(line));
259051
258963
  }
259052
- return { outroMessage: "Nothing to deploy" };
258964
+ return {
258965
+ outroMessage: `Deployment ${deploymentId} (commit ${gitHash.slice(0, 12)})`,
258966
+ stdout: jsonMode ? `${JSON.stringify({ deploymentId, gitHash }, null, 2)}
258967
+ ` : undefined
258968
+ };
258969
+ }
258970
+ async function deployTarball({ runTask: runTask2 }, outputDir) {
258971
+ const { appUrl } = await runTask2("Creating archive and deploying site...", async () => await deploySite(outputDir), {
258972
+ successMessage: "Site deployed successfully",
258973
+ errorMessage: "Deployment failed"
258974
+ });
258975
+ return { outroMessage: `Visit your site at: ${appUrl}` };
259053
258976
  }
259054
258977
  function getSiteDeployCommand() {
259055
258978
  const command2 = 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)");
259056
258979
  if (staticDeploymentsEnabled()) {
259057
- command2.addOption(new Option("--git-hash <hash>", "Commit the build came from (defaults to the checkout's HEAD)"));
258980
+ command2.addOption(new Option("--git-hash <hash>", "Commit the build came from deploys through the deployments API"));
259058
258981
  }
259059
258982
  return command2.action(deployAction2);
259060
258983
  }
@@ -267850,4 +267773,4 @@ export {
267850
267773
  CLIExitError
267851
267774
  };
267852
267775
 
267853
- //# debugId=2A92EE13E93D45AB64756E2164756E21
267776
+ //# debugId=7E09388401C6A22064756E2164756E21