@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 +253 -52
- package/dist/cli/index.js.map +16 -15
- package/package.json +1 -1
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.
|
|
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
|
-
|
|
246833
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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/
|
|
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 =
|
|
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
|
|
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:
|
|
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 =
|
|
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 ?
|
|
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=
|
|
260783
|
+
//# debugId=3589FFC17FD03B1464756E2164756E21
|