@base44-preview/cli 0.1.24-pr.646.09ee9f4 → 0.1.25-pr.643.86a7bb6

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
@@ -236596,6 +236596,15 @@ var FinalizeDeploymentResponseSchema = object({
236596
236596
  }).transform((data) => ({
236597
236597
  deploymentId: data.deployment_id
236598
236598
  }));
236599
+ var PublishDeploymentResponseSchema = object({
236600
+ git_hash: string2(),
236601
+ deployed_at: string2(),
236602
+ app_url: string2()
236603
+ }).transform((data) => ({
236604
+ gitHash: data.git_hash,
236605
+ deployedAt: data.deployed_at,
236606
+ appUrl: data.app_url
236607
+ }));
236599
236608
 
236600
236609
  // src/core/project/api.ts
236601
236610
  var PUBLIC_SETTINGS = {
@@ -239265,7 +239274,7 @@ import { join as join13 } from "node:path";
239265
239274
  // package.json
239266
239275
  var package_default = {
239267
239276
  name: "base44",
239268
- version: "0.1.24",
239277
+ version: "0.1.25",
239269
239278
  description: "Base44 CLI - Unified interface for managing Base44 applications",
239270
239279
  type: "module",
239271
239280
  bin: {
@@ -239568,6 +239577,22 @@ async function finalizeDeployment(deploymentId, sessionId, payload) {
239568
239577
  }
239569
239578
  return result.data;
239570
239579
  }
239580
+ async function publishDeployment(gitHash) {
239581
+ const appClient = getAppClient();
239582
+ let response;
239583
+ try {
239584
+ response = await appClient.post(`deployments/${gitHash}/publish`, {
239585
+ timeout: 120000
239586
+ });
239587
+ } catch (error) {
239588
+ throw await ApiError.fromHttpError(error, "publishing deployment");
239589
+ }
239590
+ const result = PublishDeploymentResponseSchema.safeParse(await response.json());
239591
+ if (!result.success) {
239592
+ throw new SchemaValidationError("Invalid response from server", result.error);
239593
+ }
239594
+ return result.data;
239595
+ }
239571
239596
  // src/core/site/config.ts
239572
239597
  async function getSiteFilePaths(outputDir) {
239573
239598
  return await globby("**/*", {
@@ -240149,11 +240174,6 @@ async function putPresigned(upload, absolutePath) {
240149
240174
 
240150
240175
  // src/core/site/deployment.ts
240151
240176
  var NO_ASSETS = { manifest: {}, filesByHash: new Map };
240152
- var DEPLOYMENTS_API_ENV = "BASE44_DEPLOYMENTS_API";
240153
- function deploymentsApiEnabled(env = process.env) {
240154
- const value = env[DEPLOYMENTS_API_ENV];
240155
- return value === "1" || value === "true";
240156
- }
240157
240177
  async function deployToDeployments(options) {
240158
240178
  const { projectRoot, outputDir, gitHash, concurrency, progress } = options;
240159
240179
  const worker = await resolveWorkerBuild(projectRoot, progress);
@@ -246759,7 +246779,7 @@ async function gitHead(projectRoot) {
246759
246779
  }
246760
246780
  }
246761
246781
  // src/core/project/deploy.ts
246762
- function hasResourcesToDeploy(projectData) {
246782
+ async function hasResourcesToDeploy(projectData) {
246763
246783
  const {
246764
246784
  project,
246765
246785
  entities,
@@ -246770,7 +246790,7 @@ function hasResourcesToDeploy(projectData) {
246770
246790
  connectors,
246771
246791
  authConfig
246772
246792
  } = projectData;
246773
- const hasSite = Boolean(project.site?.outputDirectory);
246793
+ const hasSite = Boolean(project.site?.outputDirectory) || Boolean(await detectFullStackArtifact(project.root));
246774
246794
  const hasEntities = entities.length > 0;
246775
246795
  const hasFunctions = functions.length > 0;
246776
246796
  const hasActors = actors.length > 0;
@@ -246829,12 +246849,59 @@ async function deployAll(projectData, options) {
246829
246849
  await authConfigResource.push(authConfig);
246830
246850
  const skipConnectorSync = connectors.length === 0 && hasWorkspaceApiKeyAuth();
246831
246851
  const connectorResults = skipConnectorSync ? [] : (await pushConnectors(connectors)).results;
246832
- if (project.site?.outputDirectory) {
246833
- const outputDir = resolve5(project.root, project.site.outputDirectory);
246852
+ const appUrl = await deployProjectSite(project, options);
246853
+ return appUrl ? { appUrl, connectorResults } : { connectorResults };
246854
+ }
246855
+ async function deployProjectSite(project, options) {
246856
+ const outputDirectory = project.site?.outputDirectory;
246857
+ const outputDir = outputDirectory ? resolve5(project.root, outputDirectory) : null;
246858
+ if (!outputDir) {
246859
+ if (!await detectFullStackArtifact(project.root)) {
246860
+ return;
246861
+ }
246862
+ const gitHash = await resolveGitHash(project.root, options?.gitHash);
246863
+ return shipCommit(project.root, null, gitHash, options);
246864
+ }
246865
+ const gitHash = await resolveGitHash(project.root, options?.gitHash).catch(() => {
246866
+ return;
246867
+ });
246868
+ if (!gitHash) {
246869
+ options?.onSiteProgress?.("No commit found for this build, so it was deployed without one. Commit your work to address deployments by it.");
246834
246870
  const { appUrl } = await deploySite(outputDir);
246835
- return { appUrl, connectorResults };
246871
+ return appUrl;
246872
+ }
246873
+ return shipCommit(project.root, outputDir, gitHash, options);
246874
+ }
246875
+ async function shipCommit(projectRoot, outputDir, gitHash, options) {
246876
+ await deployToDeployments({
246877
+ projectRoot,
246878
+ outputDir,
246879
+ gitHash,
246880
+ progress: {
246881
+ onWarning: (message) => options?.onSiteProgress?.(message),
246882
+ onAssets: ({ totalAssets, newAssets }) => options?.onSiteProgress?.(`Found ${totalAssets} static assets (${newAssets} new)`)
246883
+ }
246884
+ });
246885
+ if (options?.publish === false) {
246886
+ return;
246887
+ }
246888
+ try {
246889
+ const { appUrl } = await publishDeployment(gitHash);
246890
+ return appUrl;
246891
+ } catch (error) {
246892
+ if (!publishesFromBuilder(error)) {
246893
+ throw error;
246894
+ }
246895
+ options?.onSiteProgress?.("Site deployed. This app is published from the Base44 builder, so production was left where it was.");
246896
+ return;
246836
246897
  }
246837
- return { connectorResults };
246898
+ }
246899
+ function publishesFromBuilder(error) {
246900
+ if (!(error instanceof ApiError)) {
246901
+ return false;
246902
+ }
246903
+ const body = error.responseBody;
246904
+ return body?.extra_data?.code === "app_publishes_from_builder";
246838
246905
  }
246839
246906
  // src/core/project/target.ts
246840
246907
  import { dirname as dirname13, join as join19, resolve as resolve6 } from "node:path";
@@ -249991,7 +250058,7 @@ async function deployAction(ctx, options = {}) {
249991
250058
  throw new InvalidInputError("--yes is required in non-interactive mode");
249992
250059
  }
249993
250060
  const projectData = await readProjectConfig(options.projectRoot);
249994
- if (!hasResourcesToDeploy(projectData)) {
250061
+ if (!await hasResourcesToDeploy(projectData)) {
249995
250062
  return {
249996
250063
  outroMessage: "No resources found to deploy"
249997
250064
  };
@@ -250050,6 +250117,11 @@ ${summaryLines.join(`
250050
250117
  const functionTotal = functions.length;
250051
250118
  let actorCompleted = 0;
250052
250119
  const result = await deployAll(projectData, {
250120
+ gitHash: options.gitHash,
250121
+ publish: options.publish,
250122
+ onSiteProgress: (message) => {
250123
+ log.message(theme.styles.dim(message));
250124
+ },
250053
250125
  onVisibilitySet: (level) => {
250054
250126
  log.success(`App visibility set to ${level}`);
250055
250127
  },
@@ -250085,7 +250157,7 @@ ${summaryLines.join(`
250085
250157
  return { outroMessage: "App deployed successfully" };
250086
250158
  }
250087
250159
  function getDeployCommand3() {
250088
- 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);
250160
+ 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)").option("--no-publish", "Deploy the site without serving it in production yet").addOption(new Option2("--git-hash <hash>", "Commit the built site came from (defaults to the checkout's HEAD)").argParser(parseGitHash)).action(deployAction);
250089
250161
  }
250090
250162
  async function handleOAuthConnectors(connectorResults, isNonInteractive, options, log) {
250091
250163
  const needsOAuth = filterPendingOAuth(connectorResults);
@@ -250106,6 +250178,12 @@ function printStripeResult(r, log) {
250106
250178
  }
250107
250179
  log.info(` Connectors dashboard: ${theme.colors.links(getConnectorsUrl())}`);
250108
250180
  }
250181
+ function parseGitHash(value) {
250182
+ if (!isGitCommitHash(value)) {
250183
+ throw new InvalidArgumentError2("Expected a git commit hash (7-64 hex chars).");
250184
+ }
250185
+ return value;
250186
+ }
250109
250187
 
250110
250188
  // src/cli/commands/project/app-id-options.ts
250111
250189
  function readExplicitAppId(command) {
@@ -251410,11 +251488,20 @@ async function deployAction2(ctx, options) {
251410
251488
  return { outroMessage: "Deployment cancelled" };
251411
251489
  }
251412
251490
  }
251413
- return deploymentsApiEnabled() ? await deployToDeploymentsApi(ctx, project, options) : await deployTarball(ctx, project);
251491
+ return deployToDeploymentsApi(ctx, project, options);
251414
251492
  }
251415
251493
  async function deployToDeploymentsApi(ctx, project, options) {
251416
251494
  const { runTask, log, jsonMode } = ctx;
251417
251495
  const projectRoot = project.root;
251496
+ if (!siteOutputDir(project) && !await detectFullStackArtifact(projectRoot)) {
251497
+ throw new ConfigNotFoundError("No site configuration found.", {
251498
+ hints: [
251499
+ {
251500
+ message: `Add 'site.outputDirectory' to your config.jsonc (e.g., "site": { "outputDirectory": "dist" })`
251501
+ }
251502
+ ]
251503
+ });
251504
+ }
251418
251505
  const gitHash = await resolveGitHash(projectRoot, options.gitHash);
251419
251506
  const progressLines = [];
251420
251507
  const warnings = [];
@@ -251446,42 +251533,24 @@ async function deployToDeploymentsApi(ctx, project, options) {
251446
251533
  for (const warning of warnings) {
251447
251534
  log.warn(warning);
251448
251535
  }
251536
+ const published = options.publish ? await runTask("Publishing site...", async () => await publishDeployment(gitHash), { successMessage: "Site published", errorMessage: "Publish failed" }) : undefined;
251537
+ if (published) {
251538
+ log.message(`${theme.styles.header("App URL")}: ${theme.colors.links(published.appUrl)}`);
251539
+ }
251449
251540
  return {
251450
251541
  outroMessage: `Deployment ${deploymentId} (commit ${gitHash.slice(0, 12)})`,
251451
- stdout: jsonMode ? `${JSON.stringify({ deploymentId, gitHash }, null, 2)}
251542
+ stdout: jsonMode ? `${JSON.stringify({ deploymentId, gitHash, published: Boolean(published) }, null, 2)}
251452
251543
  ` : undefined
251453
251544
  };
251454
251545
  }
251455
- async function deployTarball({ runTask }, project) {
251456
- const outputDir = siteOutputDir(project);
251457
- if (!outputDir) {
251458
- throw new ConfigNotFoundError("No site configuration found.", {
251459
- hints: [
251460
- {
251461
- message: `Add 'site.outputDirectory' to your config.jsonc (e.g., "site": { "outputDirectory": "dist" })`
251462
- }
251463
- ]
251464
- });
251465
- }
251466
- const { appUrl } = await runTask("Creating archive and deploying site...", async () => await deploySite(outputDir), {
251467
- successMessage: "Site deployed successfully",
251468
- errorMessage: "Deployment failed"
251469
- });
251470
- return { outroMessage: `Visit your site at: ${appUrl}` };
251471
- }
251472
251546
  function siteOutputDir(project) {
251473
251547
  const outputDirectory = project.site?.outputDirectory;
251474
251548
  return outputDirectory ? resolve15(project.root, outputDirectory) : null;
251475
251549
  }
251476
251550
  function getSiteDeployCommand() {
251477
- 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)");
251478
- if (deploymentsApiEnabled()) {
251479
- command.addOption(new Option2("--git-hash <hash>", "Commit the build came from (defaults to the checkout's HEAD)").argParser(parseGitHash));
251480
- command.addOption(new Option2("--concurrency <n>", "Parallel asset uploads").default(DEFAULT_UPLOAD_CONCURRENCY).argParser(parseConcurrency));
251481
- }
251482
- return command.action(deployAction2);
251551
+ 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>", "Commit the build came from (defaults to the checkout's HEAD)").argParser(parseGitHash2)).addOption(new Option2("--concurrency <n>", "Parallel asset uploads").default(DEFAULT_UPLOAD_CONCURRENCY).argParser(parseConcurrency)).action(deployAction2);
251483
251552
  }
251484
- function parseGitHash(value) {
251553
+ function parseGitHash2(value) {
251485
251554
  if (!isGitCommitHash(value)) {
251486
251555
  throw new InvalidArgumentError2("Expected a git commit hash (7-64 hex chars).");
251487
251556
  }
@@ -251535,12 +251604,17 @@ function createDevLogger(label, labelColor = theme.styles.dim) {
251535
251604
  // src/cli/dev/dev-server/serve-runner.ts
251536
251605
  import { spawn as spawn2 } from "node:child_process";
251537
251606
  import process21 from "node:process";
251607
+ var ANSI_PATTERN = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
251608
+ var LOCAL_ORIGIN_PATTERN = /https?:\/\/(?:localhost|127\.0\.0\.1|\[::1\]):(\d+)/g;
251538
251609
 
251539
251610
  class ServeRunner {
251540
251611
  command;
251541
251612
  cwd;
251542
251613
  env;
251543
251614
  logger;
251615
+ onOrigin;
251616
+ ignorePort;
251617
+ originReported = false;
251544
251618
  child;
251545
251619
  stopping = false;
251546
251620
  stopPromise;
@@ -251550,6 +251624,8 @@ class ServeRunner {
251550
251624
  this.cwd = options.cwd;
251551
251625
  this.env = options.env;
251552
251626
  this.logger = options.logger;
251627
+ this.onOrigin = options.onOrigin;
251628
+ this.ignorePort = options.ignorePort;
251553
251629
  }
251554
251630
  start() {
251555
251631
  if (this.child) {
@@ -251626,6 +251702,7 @@ class ServeRunner {
251626
251702
  const lines = data.toString().trimEnd().split(`
251627
251703
  `);
251628
251704
  for (const line of lines) {
251705
+ this.reportOrigin(line);
251629
251706
  if (type === "error") {
251630
251707
  this.logger.error(line);
251631
251708
  } else {
@@ -251633,6 +251710,20 @@ class ServeRunner {
251633
251710
  }
251634
251711
  }
251635
251712
  }
251713
+ reportOrigin(line) {
251714
+ if (this.originReported || !this.onOrigin) {
251715
+ return;
251716
+ }
251717
+ const matches = line.replace(ANSI_PATTERN, "").matchAll(LOCAL_ORIGIN_PATTERN);
251718
+ for (const [origin, port] of matches) {
251719
+ if (Number(port) === this.ignorePort) {
251720
+ continue;
251721
+ }
251722
+ this.originReported = true;
251723
+ this.onOrigin(origin);
251724
+ return;
251725
+ }
251726
+ }
251636
251727
  }
251637
251728
 
251638
251729
  // src/cli/dev/serve-command-runner.ts
@@ -251640,7 +251731,9 @@ function createServeCommandRunner({
251640
251731
  serveCommand,
251641
251732
  projectRoot,
251642
251733
  appId,
251643
- appBaseUrl
251734
+ appBaseUrl,
251735
+ onOrigin,
251736
+ ignorePort
251644
251737
  }) {
251645
251738
  return new ServeRunner({
251646
251739
  command: serveCommand,
@@ -251649,7 +251742,9 @@ function createServeCommandRunner({
251649
251742
  VITE_BASE44_APP_ID: appId,
251650
251743
  ...appBaseUrl ? { VITE_BASE44_APP_BASE_URL: appBaseUrl } : {}
251651
251744
  },
251652
- logger: createDevLogger("frontend", theme.colors.base44Orange)
251745
+ logger: createDevLogger("frontend", theme.colors.base44Orange),
251746
+ onOrigin,
251747
+ ignorePort
251653
251748
  });
251654
251749
  }
251655
251750
 
@@ -252428,7 +252523,7 @@ async function getPorts(options) {
252428
252523
  }
252429
252524
 
252430
252525
  // src/cli/dev/dev-server/main.ts
252431
- var import_http_proxy_middleware2 = __toESM(require_dist2(), 1);
252526
+ var import_http_proxy_middleware3 = __toESM(require_dist2(), 1);
252432
252527
 
252433
252528
  // ../../node_modules/tmp-promise/index.js
252434
252529
  var { promisify: promisify11 } = __require("util");
@@ -252993,8 +253088,7 @@ async function createFunctionRuntime(functions, logger, denoWrapperPath) {
252993
253088
  return new FunctionManager(functions, logger, denoWrapperPath);
252994
253089
  }
252995
253090
 
252996
- // src/cli/dev/dev-server/routes/functions.ts
252997
- var import_express = __toESM(require_express(), 1);
253091
+ // src/cli/dev/dev-server/routes/app-server.ts
252998
253092
  var import_http_proxy_middleware = __toESM(require_dist2(), 1);
252999
253093
  import { ServerResponse } from "node:http";
253000
253094
 
@@ -253011,11 +253105,86 @@ var createServiceToken = () => createJwtToken(SERVICE_ROLE_EMAIL);
253011
253105
  var createServiceAuthorizationHeader = () => `Bearer ${createServiceToken()}`;
253012
253106
  var isServiceSubject = (subject) => subject === SERVICE_ROLE_EMAIL;
253013
253107
 
253108
+ // src/cli/dev/dev-server/routes/app-server.ts
253109
+ var PLATFORM_OWNED_SDK_HEADERS = [
253110
+ "base44-app-id",
253111
+ "base44-api-url",
253112
+ "base44-service-authorization",
253113
+ "base44-state",
253114
+ "base44-functions-version",
253115
+ "x-base44-app-url",
253116
+ "x-data-env"
253117
+ ];
253118
+ var FORWARDED_HEADER = "base44-dev-forwarded";
253119
+ var PROXY_LOOP_MESSAGE = [
253120
+ "The app dev server sent this request back to the Base44 dev server instead of handling it.",
253121
+ "Its Vite proxy is forwarding all of /api; only /api/apps belongs to the backend.",
253122
+ "Update @base44/vite-plugin, or narrow the proxy in vite.config.js to /api/apps."
253123
+ ].join(" ");
253124
+ function createAppServerProxy(target, logger) {
253125
+ let origin = "http://127.0.0.1:0";
253126
+ const proxy = import_http_proxy_middleware.createProxyMiddleware({
253127
+ router: () => origin,
253128
+ changeOrigin: true,
253129
+ ws: true,
253130
+ on: {
253131
+ proxyReq: (proxyReq, req) => {
253132
+ for (const header of PLATFORM_OWNED_SDK_HEADERS) {
253133
+ proxyReq.removeHeader(header);
253134
+ }
253135
+ proxyReq.setHeader("Base44-App-Id", target.appId);
253136
+ proxyReq.setHeader("Base44-Api-Url", `${req.protocol}://${req.headers.host}`);
253137
+ proxyReq.setHeader("Base44-Service-Authorization", createServiceAuthorizationHeader());
253138
+ proxyReq.setHeader(FORWARDED_HEADER, "1");
253139
+ },
253140
+ error: (err, _req, res) => {
253141
+ logger.error("App dev server proxy error:", err);
253142
+ if (res instanceof ServerResponse && !res.headersSent) {
253143
+ res.writeHead(502, { "Content-Type": "application/json" });
253144
+ res.end(JSON.stringify({
253145
+ error: "Failed to proxy request to the app dev server",
253146
+ details: err.message
253147
+ }));
253148
+ }
253149
+ }
253150
+ }
253151
+ });
253152
+ const resolveOrigin = async () => {
253153
+ origin = await target.waitForOrigin();
253154
+ };
253155
+ const middleware = async (req, res, next) => {
253156
+ if (req.headers[FORWARDED_HEADER]) {
253157
+ logger.error(PROXY_LOOP_MESSAGE);
253158
+ res.status(508).json({ error: PROXY_LOOP_MESSAGE });
253159
+ return;
253160
+ }
253161
+ try {
253162
+ await resolveOrigin();
253163
+ } catch (error) {
253164
+ const message = error instanceof Error ? error.message : String(error);
253165
+ logger.error(message);
253166
+ res.status(502).json({ error: message });
253167
+ return;
253168
+ }
253169
+ await proxy(req, res, next);
253170
+ };
253171
+ const upgrade = (req, socket, head) => {
253172
+ resolveOrigin().then(() => proxy.upgrade(req, socket, head), (error) => {
253173
+ logger.error(error instanceof Error ? error.message : String(error));
253174
+ socket.destroy();
253175
+ });
253176
+ };
253177
+ return { middleware, upgrade };
253178
+ }
253179
+
253014
253180
  // src/cli/dev/dev-server/routes/functions.ts
253181
+ var import_express = __toESM(require_express(), 1);
253182
+ var import_http_proxy_middleware2 = __toESM(require_dist2(), 1);
253183
+ import { ServerResponse as ServerResponse2 } from "node:http";
253015
253184
  function createFunctionRouter(manager, logger) {
253016
253185
  const router = import_express.Router({ mergeParams: true });
253017
253186
  const portsByRequest = new WeakMap;
253018
- const proxy = import_http_proxy_middleware.createProxyMiddleware({
253187
+ const proxy = import_http_proxy_middleware2.createProxyMiddleware({
253019
253188
  router: (req) => `http://localhost:${portsByRequest.get(req)}`,
253020
253189
  changeOrigin: true,
253021
253190
  on: {
@@ -253029,7 +253198,7 @@ function createFunctionRouter(manager, logger) {
253029
253198
  },
253030
253199
  error: (err, _req, res) => {
253031
253200
  logger.error("Function proxy error:", err);
253032
- if (res instanceof ServerResponse && !res.headersSent) {
253201
+ if (res instanceof ServerResponse2 && !res.headersSent) {
253033
253202
  res.writeHead(502, { "Content-Type": "application/json" });
253034
253203
  res.end(JSON.stringify({
253035
253204
  error: "Failed to proxy request to function",
@@ -253375,9 +253544,10 @@ var import_dist = __toESM(require_dist4(), 1);
253375
253544
  var { Server, Namespace, Socket } = import_dist.default;
253376
253545
 
253377
253546
  // src/cli/dev/dev-server/realtime.ts
253547
+ var REALTIME_PATH = "/ws-user-apps/socket.io/";
253378
253548
  function createRealtimeServer(httpServer) {
253379
253549
  const io = new Server(httpServer, {
253380
- path: "/ws-user-apps/socket.io/",
253550
+ path: REALTIME_PATH,
253381
253551
  cors: {
253382
253552
  origin: /^http:\/\/localhost(:\d+)?$/,
253383
253553
  credentials: true
@@ -255910,6 +256080,7 @@ class WatchBase44 extends EventEmitter4 {
255910
256080
  // src/cli/dev/dev-server/main.ts
255911
256081
  var DEFAULT_PORT = 4400;
255912
256082
  var BASE44_APP_URL = "https://base44.app";
256083
+ var PLATFORM_PATH_PATTERN = /^\/api\/apps(\/|$)/;
255913
256084
  async function createDevServer(options) {
255914
256085
  const { port: userPort } = options;
255915
256086
  const port = userPort ?? await getPorts({
@@ -255918,7 +256089,7 @@ async function createDevServer(options) {
255918
256089
  const baseUrl = `http://localhost:${port}`;
255919
256090
  const { functions, entities, project, siteUrl } = await options.loadResources();
255920
256091
  const app = import_express6.default();
255921
- const remoteProxy = import_http_proxy_middleware2.createProxyMiddleware({
256092
+ const remoteProxy = import_http_proxy_middleware3.createProxyMiddleware({
255922
256093
  target: BASE44_APP_URL,
255923
256094
  changeOrigin: true
255924
256095
  });
@@ -255980,7 +256151,11 @@ async function createDevServer(options) {
255980
256151
  app.use("/api/apps/:appId/integration-endpoints", integrationRoutes);
255981
256152
  const customIntegrationRoutes = createCustomIntegrationRoutes(remoteProxy, devLogger);
255982
256153
  app.use("/api/apps/:appId/integrations/custom", customIntegrationRoutes);
256154
+ const appServerProxy = options.appServer ? createAppServerProxy(options.appServer, devLogger) : undefined;
255983
256155
  app.use((req, res, next) => {
256156
+ if (appServerProxy && !PLATFORM_PATH_PATTERN.test(req.path)) {
256157
+ return appServerProxy.middleware(req, res, next);
256158
+ }
255984
256159
  if (siteUrl && (req.path === "/login" || req.path.startsWith("/login/"))) {
255985
256160
  const targetUrl = new URL(req.originalUrl, siteUrl);
255986
256161
  devLogger.warn(`"${req.originalUrl}" requires hosted login, redirecting to ${targetUrl.toString()}`);
@@ -256005,6 +256180,13 @@ async function createDevServer(options) {
256005
256180
  }
256006
256181
  });
256007
256182
  });
256183
+ if (appServerProxy) {
256184
+ server.on("upgrade", (req, socket, head) => {
256185
+ if (!req.url?.startsWith(REALTIME_PATH)) {
256186
+ appServerProxy.upgrade(req, socket, head);
256187
+ }
256188
+ });
256189
+ }
256008
256190
  const io = createRealtimeServer(server);
256009
256191
  emitEntityEvent = (appId, entityName, event) => {
256010
256192
  broadcastEntityEvent(io, appId, entityName, event);
@@ -256078,9 +256260,24 @@ async function createDevServer(options) {
256078
256260
  }
256079
256261
 
256080
256262
  // src/cli/commands/dev.ts
256263
+ var APP_SERVER_START_TIMEOUT_MS = 120000;
256081
256264
  function localServerUrl(port) {
256082
256265
  return `http://localhost:${port}`;
256083
256266
  }
256267
+ function createAppServerOrigin() {
256268
+ let report;
256269
+ const announced = new Promise((resolve) => {
256270
+ report = resolve;
256271
+ });
256272
+ const timedOut = new Promise((_, reject) => {
256273
+ const timer = setTimeout(() => reject(new Error("The app dev server did not print a local URL, so requests cannot be forwarded to it.")), APP_SERVER_START_TIMEOUT_MS);
256274
+ timer.unref();
256275
+ });
256276
+ return {
256277
+ waitForOrigin: () => Promise.race([announced, timedOut]),
256278
+ report
256279
+ };
256280
+ }
256084
256281
  function validateDevOptions(command) {
256085
256282
  const { appId } = command.optsWithGlobals();
256086
256283
  if (appId !== undefined) {
@@ -256133,10 +256330,12 @@ async function localDevAction(ctx, app, options) {
256133
256330
  const siteUrlPromise = getSiteUrl().catch(() => {
256134
256331
  return;
256135
256332
  });
256333
+ const appServerOrigin = createAppServerOrigin();
256136
256334
  const backend = await createDevServer({
256137
256335
  log: ctx.log,
256138
256336
  port: options.port ? Number(options.port) : undefined,
256139
256337
  denoWrapperPath: getDenoWrapperPath(),
256338
+ appServer: site ? { appId: app.id, waitForOrigin: appServerOrigin.waitForOrigin } : undefined,
256140
256339
  loadResources: async () => {
256141
256340
  const { functions, entities, project } = await readProjectConfig();
256142
256341
  const siteUrl = await siteUrlPromise;
@@ -256148,11 +256347,13 @@ async function localDevAction(ctx, app, options) {
256148
256347
  const runner = createServeCommandRunner({
256149
256348
  ...site,
256150
256349
  appId: app.id,
256151
- appBaseUrl: backendUrl
256350
+ appBaseUrl: backendUrl,
256351
+ onOrigin: appServerOrigin.report,
256352
+ ignorePort: backend.port
256152
256353
  });
256153
256354
  startServeCommand(runner, { url: backendUrl, shutdown: backend.shutdown });
256154
256355
  }
256155
- const outroMessage = site ? "Open your app using the frontend dev server URL" : `Dev server is available at ${theme.colors.links(backendUrl)}`;
256356
+ const outroMessage = site ? `Your app is available at ${theme.colors.links(backendUrl)}` : `Dev server is available at ${theme.colors.links(backendUrl)}`;
256156
256357
  return { outroMessage };
256157
256358
  }
256158
256359
  async function devAction(ctx, options) {
@@ -260579,4 +260780,4 @@ export {
260579
260780
  runCLI
260580
260781
  };
260581
260782
 
260582
- //# debugId=9978A4087157AD8F64756E2164756E21
260783
+ //# debugId=3589FFC17FD03B1464756E2164756E21