@base44-preview/cli 0.1.33-pr.667.b65bd0b → 0.2.0-pr.671.556605b

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
@@ -239376,7 +239376,7 @@ import { join as join13 } from "node:path";
239376
239376
  // package.json
239377
239377
  var package_default = {
239378
239378
  name: "base44",
239379
- version: "0.1.33",
239379
+ version: "0.2.0",
239380
239380
  description: "Base44 CLI - Unified interface for managing Base44 applications",
239381
239381
  type: "module",
239382
239382
  bin: {
@@ -239681,6 +239681,21 @@ async function finalizeDeployment(deploymentId, sessionId, payload) {
239681
239681
  }
239682
239682
  return result.data;
239683
239683
  }
239684
+ async function publishDeployment(gitHash) {
239685
+ const appClient = getAppClient();
239686
+ try {
239687
+ await appClient.post("deploy", {
239688
+ json: { git_commit_hash: gitHash },
239689
+ timeout: 120000
239690
+ });
239691
+ } catch (error) {
239692
+ throw await ApiError.fromHttpError(error, "publishing deployment");
239693
+ }
239694
+ const appUrl = await getSiteUrl().catch(() => {
239695
+ return;
239696
+ });
239697
+ return { gitHash, appUrl };
239698
+ }
239684
239699
  // src/core/site/config.ts
239685
239700
  async function getSiteFilePaths(outputDir) {
239686
239701
  return await globby("**/*", {
@@ -240264,11 +240279,6 @@ async function putPresignedBody(upload, body) {
240264
240279
 
240265
240280
  // src/core/site/deployment.ts
240266
240281
  var NO_ASSETS = { manifest: {}, filesByHash: new Map };
240267
- var DEPLOYMENTS_API_ENV = "BASE44_DEPLOYMENTS_API";
240268
- function deploymentsApiEnabled(env = process.env) {
240269
- const value = env[DEPLOYMENTS_API_ENV];
240270
- return value === "1" || value === "true";
240271
- }
240272
240282
  async function deployToDeployments(options) {
240273
240283
  const { projectRoot, outputDir, gitHash, concurrency, progress } = options;
240274
240284
  const worker = await resolveWorkerBuild(projectRoot, progress);
@@ -246843,22 +246853,21 @@ function isGitCommitHash(value) {
246843
246853
  }
246844
246854
 
246845
246855
  // src/core/site/git-hash.ts
246846
- async function resolveGitHash(projectRoot, explicit) {
246847
- const hash = explicit ?? await gitHead(projectRoot);
246848
- if (!hash || !isGitCommitHash(hash)) {
246849
- 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.", {
246850
- hints: [
246851
- {
246852
- message: "Run the deploy from a git checkout, or pass the commit explicitly with --git-hash."
246853
- }
246854
- ]
246855
- });
246856
- }
246857
- return hash;
246856
+ function workerBuildNeedsGitHashError() {
246857
+ return new InvalidInputError("A full-stack build deploys by the commit that produced it, and none was given.", {
246858
+ hints: [
246859
+ {
246860
+ message: "Pass it with --git-hash, e.g. --git-hash $(git rev-parse HEAD)."
246861
+ }
246862
+ ]
246863
+ });
246858
246864
  }
246859
246865
  async function resolveProvenanceCommit(projectRoot, explicit) {
246860
246866
  if (explicit) {
246861
- return await resolveGitHash(projectRoot, explicit);
246867
+ if (!isGitCommitHash(explicit)) {
246868
+ throw new InvalidInputError(`'${explicit}' is not a git commit hash.`);
246869
+ }
246870
+ return explicit;
246862
246871
  }
246863
246872
  const hash = await gitHead(projectRoot);
246864
246873
  return hash && isGitCommitHash(hash) ? hash : undefined;
@@ -246874,7 +246883,7 @@ async function gitHead(projectRoot) {
246874
246883
  }
246875
246884
  }
246876
246885
  // src/core/project/deploy.ts
246877
- function hasResourcesToDeploy(projectData) {
246886
+ async function hasResourcesToDeploy(projectData) {
246878
246887
  const {
246879
246888
  project,
246880
246889
  entities,
@@ -246885,7 +246894,7 @@ function hasResourcesToDeploy(projectData) {
246885
246894
  connectors,
246886
246895
  authConfig
246887
246896
  } = projectData;
246888
- const hasSite = Boolean(project.site?.outputDirectory);
246897
+ const hasSite = Boolean(project.site?.outputDirectory) || Boolean(await detectFullStackArtifact(project.root));
246889
246898
  const hasEntities = entities.length > 0;
246890
246899
  const hasFunctions = functions.length > 0;
246891
246900
  const hasActors = actors.length > 0;
@@ -246907,6 +246916,9 @@ async function deployAll(projectData, options) {
246907
246916
  connectors,
246908
246917
  authConfig
246909
246918
  } = projectData;
246919
+ if (!options?.gitHash && await detectFullStackArtifact(project.root)) {
246920
+ throw workerBuildNeedsGitHashError();
246921
+ }
246910
246922
  await setAppVisibility(project.visibility);
246911
246923
  if (project.visibility) {
246912
246924
  options?.onVisibilitySet?.(project.visibility);
@@ -246944,12 +246956,49 @@ async function deployAll(projectData, options) {
246944
246956
  await authConfigResource.push(authConfig);
246945
246957
  const skipConnectorSync = connectors.length === 0 && hasWorkspaceApiKeyAuth();
246946
246958
  const connectorResults = skipConnectorSync ? [] : (await pushConnectors(connectors)).results;
246947
- if (project.site?.outputDirectory) {
246948
- const outputDir = resolve5(project.root, project.site.outputDirectory);
246949
- const { appUrl } = await deploySite(outputDir);
246950
- return { appUrl, connectorResults };
246959
+ const appUrl = await deployProjectSite(project, options);
246960
+ return appUrl ? { appUrl, connectorResults } : { connectorResults };
246961
+ }
246962
+ async function deployProjectSite(project, options) {
246963
+ const outputDirectory = project.site?.outputDirectory;
246964
+ const outputDir = outputDirectory ? resolve5(project.root, outputDirectory) : null;
246965
+ const gitHash = options?.gitHash;
246966
+ if (gitHash && (outputDir || await detectFullStackArtifact(project.root))) {
246967
+ return shipCommit(project.root, outputDir, gitHash, options);
246968
+ }
246969
+ if (!outputDir) {
246970
+ return;
246971
+ }
246972
+ const { appUrl } = await deploySite(outputDir);
246973
+ return appUrl;
246974
+ }
246975
+ async function shipCommit(projectRoot, outputDir, gitHash, options) {
246976
+ await deployToDeployments({
246977
+ projectRoot,
246978
+ outputDir,
246979
+ gitHash,
246980
+ progress: {
246981
+ onWarning: (message) => options?.onSiteProgress?.(message),
246982
+ onAssets: ({ totalAssets, newAssets }) => options?.onSiteProgress?.(`Found ${totalAssets} static assets (${newAssets} new)`)
246983
+ }
246984
+ });
246985
+ try {
246986
+ const { appUrl } = await publishDeployment(gitHash);
246987
+ return appUrl;
246988
+ } catch (error) {
246989
+ if (!publishesFromBuilder(error)) {
246990
+ throw error;
246991
+ }
246992
+ options?.onSiteProgress?.("Site deployed. This app is published from the Base44 builder, so production was left where it was.");
246993
+ return;
246994
+ }
246995
+ }
246996
+ function publishesFromBuilder(error) {
246997
+ if (!(error instanceof ApiError)) {
246998
+ return false;
246951
246999
  }
246952
- return { connectorResults };
247000
+ const body = error.responseBody;
247001
+ return body?.error?.code === "git_commit_hash_not_supported";
246953
247002
  }
246954
247003
  // src/core/project/target.ts
246955
247004
  import { dirname as dirname13, join as join19, resolve as resolve6 } from "node:path";
@@ -247587,6 +247636,13 @@ function normalizeDatetime(value) {
247587
247636
  return value;
247588
247637
  return `${value}Z`;
247589
247638
  }
247639
+ // src/cli/utils/git-hash.ts
247640
+ function parseGitHash(value) {
247641
+ if (!isGitCommitHash(value)) {
247642
+ throw new InvalidArgumentError2("Expected a git commit hash (7-64 hex chars).");
247643
+ }
247644
+ return value;
247645
+ }
247590
247646
  // src/cli/utils/json.ts
247591
247647
  function toJsonStdout(result, options = {}) {
247592
247648
  return `${JSON.stringify(result, null, options.compact ? undefined : 2)}
@@ -251942,7 +251998,7 @@ async function deployAction(ctx, options = {}) {
251942
251998
  throw new InvalidInputError("--yes is required in non-interactive mode");
251943
251999
  }
251944
252000
  const projectData = await readProjectConfig(options.projectRoot);
251945
- if (!hasResourcesToDeploy(projectData)) {
252001
+ if (!await hasResourcesToDeploy(projectData)) {
251946
252002
  return {
251947
252003
  outroMessage: "No resources found to deploy"
251948
252004
  };
@@ -252001,6 +252057,10 @@ ${summaryLines.join(`
252001
252057
  const functionTotal = functions.length;
252002
252058
  let actorCompleted = 0;
252003
252059
  const result = await deployAll(projectData, {
252060
+ gitHash: options.gitHash,
252061
+ onSiteProgress: (message) => {
252062
+ log.message(theme.styles.dim(message));
252063
+ },
252004
252064
  onVisibilitySet: (level) => {
252005
252065
  log.success(`App visibility set to ${level}`);
252006
252066
  },
@@ -252036,7 +252096,7 @@ ${summaryLines.join(`
252036
252096
  return { outroMessage: "App deployed successfully" };
252037
252097
  }
252038
252098
  function getDeployCommand3() {
252039
- return new Base44Command("deploy").description("Deploy all project resources (entities, functions, actors, agents, connectors, and site)").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)").action(deployAction);
252099
+ return new Base44Command("deploy").description("Deploy all project resources (entities, functions, actors, agents, connectors, and site)").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)").addOption(new Option2("--git-hash <hash>", "Deploy by the commit the build came from, through the deployments API").argParser(parseGitHash)).action(deployAction);
252040
252100
  }
252041
252101
  async function handleOAuthConnectors(connectorResults, isNonInteractive, options, log) {
252042
252102
  const needsOAuth = filterPendingOAuth(connectorResults);
@@ -262868,64 +262928,6 @@ function logEvent(level, event, fields = {}) {
262868
262928
  sink(level, event, fields);
262869
262929
  }
262870
262930
 
262871
- // ../functions-compiler/src/fetch-guard.ts
262872
- var ALLOWED_HOST_SUFFIXES = ["npmjs.org", "jsr.io", "esm.sh", "deno.land"];
262873
- var MAX_RESPONSE_BYTES = 30 * 1024 * 1024;
262874
- function requestUrl(input) {
262875
- if (input instanceof URL)
262876
- return input;
262877
- if (typeof input === "string")
262878
- return new URL(input);
262879
- return new URL(input.url);
262880
- }
262881
- function isDependencyHost(hostname) {
262882
- return ALLOWED_HOST_SUFFIXES.some((suffix) => hostname === suffix || hostname.endsWith(`.${suffix}`));
262883
- }
262884
-
262885
- // ../functions-compiler/src/dependency-fetch-retry.ts
262886
- var RETRY_DELAYS_MS = [250, 1000];
262887
- var installed = false;
262888
- function installDependencyFetchRetry() {
262889
- if (installed)
262890
- return;
262891
- installed = true;
262892
- globalThis.fetch = createRetryingFetch(globalThis.fetch.bind(globalThis));
262893
- }
262894
- function createRetryingFetch(originalFetch, delaysMs = RETRY_DELAYS_MS) {
262895
- return async (input, init) => {
262896
- const url = requestUrl(input);
262897
- const method = init?.method ?? (input instanceof Request ? input.method : "GET");
262898
- if (method.toUpperCase() !== "GET" || !isDependencyHost(url.hostname)) {
262899
- return originalFetch(input, init);
262900
- }
262901
- for (let attempt = 0;; attempt++) {
262902
- const delay = delaysMs[attempt];
262903
- let response;
262904
- let error;
262905
- try {
262906
- response = await originalFetch(input, init);
262907
- if (response.status !== 429 && response.status < 500)
262908
- return response;
262909
- } catch (err) {
262910
- error = err;
262911
- }
262912
- logEvent(delay === undefined ? "error" : "warn", "base44.bundler.dependency_fetch_failed", {
262913
- url: url.href,
262914
- attempt: attempt + 1,
262915
- http_status: response?.status,
262916
- error: response ? undefined : String(error?.cause ?? error)
262917
- });
262918
- if (delay === undefined) {
262919
- if (response)
262920
- return response;
262921
- throw error;
262922
- }
262923
- await response?.body?.cancel();
262924
- await new Promise((resolve) => setTimeout(resolve, delay));
262925
- }
262926
- };
262927
- }
262928
-
262929
262931
  // ../functions-compiler/src/esbuild/deno-resolver.ts
262930
262932
  var NAMESPACES = ["file", "http", "https", "data", "npm", "jsr"];
262931
262933
  var RESOLVE_NAMESPACES = [...NAMESPACES, USER_NAMESPACE];
@@ -262934,7 +262936,6 @@ function denoResolverPlugin(options = {}) {
262934
262936
  return {
262935
262937
  name: "deno-resolver",
262936
262938
  async setup(build) {
262937
- installDependencyFetchRetry();
262938
262939
  deno = await lazyDenoLoader();
262939
262940
  const baseDir = options.configPath ? path20.dirname(options.configPath) : undefined;
262940
262941
  const depRoots = [denoCacheRoot(), baseDir].filter((d) => Boolean(d)).map(canonicalPath);
@@ -263799,6 +263800,8 @@ function denoCompatErrorOrThrow(e) {
263799
263800
  function denoCompatErrorItem(e) {
263800
263801
  return { message: e.message, file: e.file };
263801
263802
  }
263803
+ // ../functions-compiler/src/fetch-guard.ts
263804
+ var MAX_RESPONSE_BYTES = 30 * 1024 * 1024;
263802
263805
  // ../functions-compiler/src/static-egress-marker.ts
263803
263806
  var STATIC_EGRESS_ARTIFACT_MARKER = "base44.static-egress.request-env.v2";
263804
263807
 
@@ -264278,12 +264281,7 @@ function targetOption() {
264278
264281
  return new Option2("--target <name>", "Environment to serve the version at");
264279
264282
  }
264280
264283
  function gitHashOption() {
264281
- return new Option2("--git-hash <hash>", "Commit the build came from (defaults to the checkout's HEAD)").argParser((value) => {
264282
- if (!isGitCommitHash(value)) {
264283
- throw new InvalidArgumentError2("Expected a git commit hash (7-64 hex chars).");
264284
- }
264285
- return value;
264286
- });
264284
+ return new Option2("--git-hash <hash>", "Commit the build came from (defaults to the checkout's HEAD)").argParser(parseGitHash);
264287
264285
  }
264288
264286
  function concurrencyOption() {
264289
264287
  return new Option2("--concurrency <n>", "Parallel file uploads").default(DEFAULT_VERSION_UPLOAD_CONCURRENCY).argParser((value) => {
@@ -264795,17 +264793,24 @@ async function deployAction2(ctx, options) {
264795
264793
  return { outroMessage: "Deployment cancelled" };
264796
264794
  }
264797
264795
  }
264798
- return deploymentsApiEnabled() ? await deployToDeploymentsApi(ctx, project, options) : await deployTarball(ctx, project);
264796
+ return deployToDeploymentsApi(ctx, project, options);
264799
264797
  }
264800
264798
  async function deployToDeploymentsApi(ctx, project, options) {
264801
264799
  const { runTask, log, jsonMode } = ctx;
264802
264800
  const projectRoot = project.root;
264803
- const gitHash = await resolveGitHash(projectRoot, options.gitHash);
264801
+ const outputDir = siteOutputDir(project);
264802
+ const gitHash = options.gitHash;
264803
+ if (!gitHash) {
264804
+ if (await detectFullStackArtifact(projectRoot)) {
264805
+ throw workerBuildNeedsGitHashError();
264806
+ }
264807
+ return deployArchive(ctx, outputDir);
264808
+ }
264804
264809
  const progressLines = [];
264805
264810
  const warnings = [];
264806
264811
  const { deploymentId } = await runTask("Deploying site...", async (updateMessage) => await deployToDeployments({
264807
264812
  projectRoot,
264808
- outputDir: siteOutputDir(project),
264813
+ outputDir,
264809
264814
  gitHash,
264810
264815
  concurrency: options.concurrency,
264811
264816
  progress: {
@@ -264831,37 +264836,35 @@ async function deployToDeploymentsApi(ctx, project, options) {
264831
264836
  for (const warning of warnings) {
264832
264837
  log.warn(warning);
264833
264838
  }
264839
+ const published = options.publish ? await runTask("Publishing site...", async () => await publishDeployment(gitHash), { successMessage: "Site published", errorMessage: "Publish failed" }) : undefined;
264840
+ if (published?.appUrl) {
264841
+ log.message(`${theme.styles.header("App URL")}: ${theme.colors.links(published.appUrl)}`);
264842
+ } else if (!published) {
264843
+ log.info("Not published: production still serves its previous build. Run again with --publish to serve this one.");
264844
+ }
264834
264845
  return {
264835
264846
  outroMessage: `Deployment ${deploymentId} (commit ${gitHash.slice(0, 12)})`,
264836
- stdout: jsonMode ? `${JSON.stringify({ deploymentId, gitHash }, null, 2)}
264847
+ stdout: jsonMode ? `${JSON.stringify({ deploymentId, gitHash, published: Boolean(published) }, null, 2)}
264837
264848
  ` : undefined
264838
264849
  };
264839
264850
  }
264840
- async function deployTarball({ runTask }, project) {
264841
- const outputDir = siteOutputDir(project);
264851
+ async function deployArchive({ runTask, jsonMode }, outputDir) {
264842
264852
  const { appUrl } = await runTask("Creating archive and deploying site...", async () => await deploySite(outputDir), {
264843
264853
  successMessage: "Site deployed successfully",
264844
264854
  errorMessage: "Deployment failed"
264845
264855
  });
264846
- return { outroMessage: `Visit your site at: ${appUrl}` };
264856
+ return {
264857
+ outroMessage: `Visit your site at: ${appUrl}`,
264858
+ stdout: jsonMode ? `${JSON.stringify({ appUrl, published: true }, null, 2)}
264859
+ ` : undefined
264860
+ };
264847
264861
  }
264848
264862
  function siteOutputDir(project) {
264849
264863
  const { outputDirectory = DEFAULT_SITE.outputDirectory } = siteOrDefault(project);
264850
264864
  return resolve16(project.root, outputDirectory);
264851
264865
  }
264852
264866
  function getSiteDeployCommand() {
264853
- const command = new Base44Command("deploy").description("Deploy built site files to Base44 hosting").option("-y, --yes", "Skip confirmation prompt").option("--build", "Build the site before deploying (skips the prompt)").option("--no-build", "Deploy without building (skips the prompt)");
264854
- if (deploymentsApiEnabled()) {
264855
- command.addOption(new Option2("--git-hash <hash>", "Commit the build came from (defaults to the checkout's HEAD)").argParser(parseGitHash));
264856
- command.addOption(new Option2("--concurrency <n>", "Parallel asset uploads").default(DEFAULT_UPLOAD_CONCURRENCY).argParser(parseConcurrency));
264857
- }
264858
- return command.action(deployAction2);
264859
- }
264860
- function parseGitHash(value) {
264861
- if (!isGitCommitHash(value)) {
264862
- throw new InvalidArgumentError2("Expected a git commit hash (7-64 hex chars).");
264863
- }
264864
- return value;
264867
+ return 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)").option("--publish", "Serve this build in production once it is deployed").addOption(new Option2("--git-hash <hash>", "Deploy by the commit the build came from, through the deployments API").argParser(parseGitHash)).addOption(new Option2("--concurrency <n>", "Parallel asset uploads").default(DEFAULT_UPLOAD_CONCURRENCY).argParser(parseConcurrency)).action(deployAction2);
264865
264868
  }
264866
264869
  function parseConcurrency(value) {
264867
264870
  const parsed = Number(value);
@@ -274006,4 +274009,4 @@ export {
274006
274009
  runCLI
274007
274010
  };
274008
274011
 
274009
- //# debugId=41D501CA10C9A0AA64756E2164756E21
274012
+ //# debugId=B539C7BB9AAE429D64756E2164756E21