@base44-preview/cli 0.1.17-pr.626.a210a49 → 0.1.17-pr.635.7aa76fd

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
@@ -31177,7 +31177,7 @@ function cleanDoc(doc) {
31177
31177
  return mapDoc(doc, (currentDoc) => cleanDocFn(currentDoc));
31178
31178
  }
31179
31179
  function replaceEndOfLine(doc, replacement = literalline) {
31180
- return mapDoc(doc, (currentDoc) => typeof currentDoc === "string" ? join30(replacement, currentDoc.split(`
31180
+ return mapDoc(doc, (currentDoc) => typeof currentDoc === "string" ? join28(replacement, currentDoc.split(`
31181
31181
  `)) : currentDoc);
31182
31182
  }
31183
31183
  function canBreakFn(doc) {
@@ -31257,7 +31257,7 @@ function indentIfBreak(contents, options) {
31257
31257
  negate: options.negate
31258
31258
  };
31259
31259
  }
31260
- function join30(separator, docs) {
31260
+ function join28(separator, docs) {
31261
31261
  assertDoc(separator);
31262
31262
  assertDocArray(docs);
31263
31263
  const parts = [];
@@ -31968,7 +31968,7 @@ var init_doc = __esm(() => {
31968
31968
  MODE_FLAT = Symbol("MODE_FLAT");
31969
31969
  DOC_FILL_PRINTED_LENGTH = Symbol("DOC_FILL_PRINTED_LENGTH");
31970
31970
  builders = {
31971
- join: join30,
31971
+ join: join28,
31972
31972
  line,
31973
31973
  softline,
31974
31974
  hardline,
@@ -119090,7 +119090,7 @@ import path52 from "path";
119090
119090
  import * as path42 from "path";
119091
119091
  import * as fs26 from "fs/promises";
119092
119092
  import * as path22 from "path";
119093
- import process22 from "process";
119093
+ import process23 from "process";
119094
119094
  import * as path32 from "path";
119095
119095
  import process32 from "process";
119096
119096
  import path92 from "path";
@@ -119622,7 +119622,7 @@ function partition2(array2, predicate) {
119622
119622
  return result;
119623
119623
  }
119624
119624
  async function findInDirectory(nameOrNames, { typeCheck, cwd, allowSymlinks = true, filter: filter2 }) {
119625
- const directory = toAbsolutePath(cwd) ?? process22.cwd();
119625
+ const directory = toAbsolutePath(cwd) ?? process23.cwd();
119626
119626
  const names = Array.isArray(nameOrNames) ? nameOrNames : [nameOrNames];
119627
119627
  for (const name of names) {
119628
119628
  const fileOrDirectory = path22.join(directory, name);
@@ -146002,10 +146002,10 @@ __export(exports_supports_color, {
146002
146002
  createSupportsColor: () => createSupportsColor2,
146003
146003
  default: () => supports_color_default2
146004
146004
  });
146005
- import process21 from "node:process";
146005
+ import process24 from "node:process";
146006
146006
  import os9 from "node:os";
146007
146007
  import tty4 from "node:tty";
146008
- function hasFlag2(flag, argv = globalThis.Deno ? globalThis.Deno.args : process21.argv) {
146008
+ function hasFlag2(flag, argv = globalThis.Deno ? globalThis.Deno.args : process24.argv) {
146009
146009
  const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
146010
146010
  const position = argv.indexOf(prefix + flag);
146011
146011
  const terminatorPosition = argv.indexOf("--");
@@ -146068,7 +146068,7 @@ function _supportsColor2(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
146068
146068
  if (env3.TERM === "dumb") {
146069
146069
  return min;
146070
146070
  }
146071
- if (process21.platform === "win32") {
146071
+ if (process24.platform === "win32") {
146072
146072
  const osRelease = os9.release().split(".");
146073
146073
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
146074
146074
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
@@ -146130,7 +146130,7 @@ function createSupportsColor2(stream, options = {}) {
146130
146130
  }
146131
146131
  var env3, flagForceColor2, supportsColor2, supports_color_default2;
146132
146132
  var init_supports_color = __esm(() => {
146133
- ({ env: env3 } = process21);
146133
+ ({ env: env3 } = process24);
146134
146134
  if (hasFlag2("no-color") || hasFlag2("no-colors") || hasFlag2("color=false") || hasFlag2("color=never")) {
146135
146135
  flagForceColor2 = 0;
146136
146136
  } else if (hasFlag2("color") || hasFlag2("colors") || hasFlag2("color=true") || hasFlag2("color=always")) {
@@ -228670,20 +228670,6 @@ function isCLIError(error) {
228670
228670
  function isUserError(error) {
228671
228671
  return error instanceof UserError;
228672
228672
  }
228673
- var STEP = Symbol.for("base44.commandStep");
228674
- async function tagStep(step, run) {
228675
- try {
228676
- return await run();
228677
- } catch (error) {
228678
- if (error !== null && typeof error === "object" && !(STEP in error) && Object.isExtensible(error)) {
228679
- Object.defineProperty(error, STEP, { value: step, enumerable: false });
228680
- }
228681
- throw error;
228682
- }
228683
- }
228684
- function stepOf(error) {
228685
- return error !== null && typeof error === "object" && STEP in error ? error[STEP] : undefined;
228686
- }
228687
228673
 
228688
228674
  // src/core/utils/fs.ts
228689
228675
  async function pathExists(path) {
@@ -228810,7 +228796,7 @@ function normalizeBase44Env() {
228810
228796
  loadProjectEnvFiles();
228811
228797
 
228812
228798
  // src/cli/index.ts
228813
- import { dirname as dirname29, join as join39 } from "node:path";
228799
+ import { dirname as dirname28, join as join37 } from "node:path";
228814
228800
  import { fileURLToPath as fileURLToPath6 } from "node:url";
228815
228801
 
228816
228802
  // ../../node_modules/@clack/core/dist/index.mjs
@@ -230735,7 +230721,10 @@ var SiteConfigSchema = object({
230735
230721
  buildCommand: string2().default("npm run build"),
230736
230722
  serveCommand: string2().optional(),
230737
230723
  outputDirectory: string2().optional(),
230738
- installCommand: string2().default("npm install")
230724
+ installCommand: string2().default("npm install"),
230725
+ devHostFlag: string2().default("--host"),
230726
+ devHost: string2().default("0.0.0.0"),
230727
+ devPort: number2().int().min(1).max(65535).default(5173)
230739
230728
  });
230740
230729
  var PluginMetadataSchema = object({
230741
230730
  namespace: string2().min(1, "Plugin namespace cannot be empty").regex(/^[a-zA-Z0-9_-]+$/, "Plugin namespace can only contain letters, numbers, underscores, and dashes")
@@ -239619,325 +239608,11 @@ async function createArchive(pathToArchive, targetArchivePath) {
239619
239608
  import { readFile as readFile3 } from "node:fs/promises";
239620
239609
  import { join as join18 } from "node:path";
239621
239610
 
239622
- // src/core/site/modules.ts
239623
- import { stat } from "node:fs/promises";
239624
- import { relative as relative5, resolve as resolve3, sep } from "node:path";
239625
- var MAX_TOTAL_MODULE_BYTES = 40 * 1024 * 1024;
239626
- var MODULE_IGNORE = ["wrangler.json", ".dev.vars"];
239627
- var RULE_TYPE_TO_MODULE_TYPE = {
239628
- ESModule: "esm",
239629
- CompiledWasm: "wasm",
239630
- Text: "text",
239631
- Data: "data"
239632
- };
239633
- function toPosix(path) {
239634
- return path.split(sep).join("/");
239635
- }
239636
- async function collectModules(config) {
239637
- const entryPath = resolve3(config.configDir, config.main);
239638
- if (!await pathExists(entryPath)) {
239639
- throw new InvalidInputError(`Worker entry module does not exist: ${entryPath} (from "main" in ${config.configPath})`, {
239640
- hints: [{ message: "Rebuild the project to regenerate the artifact" }]
239641
- });
239642
- }
239643
- const modulesByName = new Map;
239644
- const entryName = toPosix(relative5(config.configDir, entryPath));
239645
- modulesByName.set(entryName, {
239646
- name: entryName,
239647
- absolutePath: entryPath,
239648
- size: 0,
239649
- type: "esm"
239650
- });
239651
- const ignore = [...MODULE_IGNORE];
239652
- if (config.assetsDirectory?.startsWith(config.configDir + sep)) {
239653
- ignore.push(`${toPosix(relative5(config.configDir, config.assetsDirectory))}/**`);
239654
- }
239655
- for (const rule of config.rules) {
239656
- const type = RULE_TYPE_TO_MODULE_TYPE[rule.type];
239657
- if (!type) {
239658
- throw new InvalidInputError(`Unsupported module rule type "${rule.type}" in ${config.configPath}. Supported: ${Object.keys(RULE_TYPE_TO_MODULE_TYPE).join(", ")}.`);
239659
- }
239660
- const matches = await globby(rule.globs, {
239661
- cwd: config.configDir,
239662
- onlyFiles: true,
239663
- dot: true,
239664
- ignore
239665
- });
239666
- for (const match of matches.sort()) {
239667
- if (!modulesByName.has(match)) {
239668
- modulesByName.set(match, {
239669
- name: match,
239670
- absolutePath: resolve3(config.configDir, match),
239671
- size: 0,
239672
- type
239673
- });
239674
- }
239675
- }
239676
- }
239677
- if (config.uploadSourceMaps) {
239678
- const maps = await globby("**/*.map", {
239679
- cwd: config.configDir,
239680
- onlyFiles: true,
239681
- dot: true,
239682
- ignore
239683
- });
239684
- for (const map of maps.sort()) {
239685
- addSourcemap(modulesByName, config.configDir, map);
239686
- }
239687
- } else {
239688
- for (const name of [...modulesByName.keys()]) {
239689
- const mapName = `${name}.map`;
239690
- if (await pathExists(resolve3(config.configDir, mapName))) {
239691
- addSourcemap(modulesByName, config.configDir, mapName);
239692
- }
239693
- }
239694
- }
239695
- const modules = [...modulesByName.values()];
239696
- let totalBytes = 0;
239697
- for (const module of modules) {
239698
- module.size = (await stat(module.absolutePath)).size;
239699
- totalBytes += module.size;
239700
- }
239701
- if (totalBytes > MAX_TOTAL_MODULE_BYTES) {
239702
- throw new InvalidInputError(`Worker modules total ${totalBytes} bytes, which exceeds the 40 MB limit for a Base44 deploy.`);
239703
- }
239704
- return modules;
239705
- }
239706
- function addSourcemap(modulesByName, configDir, name) {
239707
- if (modulesByName.has(name))
239708
- return;
239709
- modulesByName.set(name, {
239710
- name,
239711
- absolutePath: resolve3(configDir, name),
239712
- size: 0,
239713
- type: "sourcemap"
239714
- });
239715
- }
239716
-
239717
- // src/core/site/wrangler-config.ts
239718
- import { dirname as dirname12, join as join16, resolve as resolve4 } from "node:path";
239719
- var WRANGLER_REDIRECT_PATH = join16(".wrangler", "deploy", "config.json");
239720
- var RedirectConfigSchema = looseObject({
239721
- configPath: string2().min(1)
239722
- });
239723
- var WranglerConfigSchema = looseObject({
239724
- main: string2().min(1, "wrangler config is missing a 'main' entry module"),
239725
- no_bundle: boolean2().optional(),
239726
- rules: array(looseObject({ type: string2(), globs: array(string2()) })).optional(),
239727
- assets: looseObject({
239728
- directory: string2().optional(),
239729
- html_handling: string2().optional(),
239730
- not_found_handling: string2().optional(),
239731
- run_worker_first: union([boolean2(), array(string2())]).optional(),
239732
- headers: string2().optional(),
239733
- redirects: string2().optional()
239734
- }).optional(),
239735
- compatibility_date: string2().optional(),
239736
- compatibility_flags: array(string2()).optional(),
239737
- vars: record(string2(), unknown()).optional(),
239738
- upload_source_maps: boolean2().optional()
239739
- });
239740
- async function detectFullStackArtifact(projectRoot) {
239741
- const redirectPath = join16(projectRoot, WRANGLER_REDIRECT_PATH);
239742
- return await pathExists(redirectPath) ? redirectPath : null;
239743
- }
239744
- async function resolveWranglerConfig(redirectPath) {
239745
- const configPath = await resolveRedirectedConfigPath(redirectPath);
239746
- const parsed = await readJsonFile(configPath);
239747
- const result = WranglerConfigSchema.safeParse(parsed);
239748
- if (!result.success) {
239749
- throw new ConfigInvalidError(`Invalid wrangler config: ${prettifyError(result.error)}`, configPath);
239750
- }
239751
- const config = result.data;
239752
- if (config.no_bundle !== true) {
239753
- throw new InvalidInputError("This framework's output requires bundling; not yet supported. Base44 only deploys pre-bundled Workers output (no_bundle: true).");
239754
- }
239755
- const configDir = dirname12(configPath);
239756
- const assetsDirectory = config.assets?.directory ? resolve4(configDir, config.assets.directory) : null;
239757
- return {
239758
- configPath,
239759
- configDir,
239760
- main: config.main,
239761
- assetsDirectory,
239762
- assetsConfig: config.assets ? toResolvedAssetsConfig(config.assets) : null,
239763
- compatibilityDate: config.compatibility_date ?? null,
239764
- compatibilityFlags: config.compatibility_flags ?? [],
239765
- rules: (config.rules ?? []).map((rule) => ({
239766
- type: rule.type,
239767
- globs: rule.globs
239768
- })),
239769
- uploadSourceMaps: config.upload_source_maps ?? false
239770
- };
239771
- }
239772
- async function resolveRedirectedConfigPath(redirectPath) {
239773
- const parsed = await readJsonFile(redirectPath);
239774
- const result = RedirectConfigSchema.safeParse(parsed);
239775
- if (!result.success) {
239776
- throw new ConfigInvalidError(`Invalid deploy redirect file: ${prettifyError(result.error)}`, redirectPath);
239777
- }
239778
- const configPath = resolve4(dirname12(redirectPath), result.data.configPath);
239779
- if (!await pathExists(configPath)) {
239780
- throw new ConfigInvalidError(`Wrangler config referenced by ${redirectPath} does not exist: ${configPath}`, redirectPath, {
239781
- hints: [{ message: "Rebuild the project to regenerate the artifact" }]
239782
- });
239783
- }
239784
- return configPath;
239785
- }
239786
- function toResolvedAssetsConfig(assets) {
239787
- return {
239788
- htmlHandling: assets.html_handling,
239789
- notFoundHandling: assets.not_found_handling,
239790
- runWorkerFirst: assets.run_worker_first,
239791
- headers: assets.headers,
239792
- redirects: assets.redirects
239793
- };
239794
- }
239795
-
239796
- // src/core/site/full-stack.ts
239797
- async function resolveFullStackBuild(projectRoot) {
239798
- const redirectPath = await detectFullStackArtifact(projectRoot);
239799
- if (!redirectPath) {
239800
- return null;
239801
- }
239802
- const config = await resolveWranglerConfig(redirectPath);
239803
- return {
239804
- config,
239805
- modules: await collectModules(config),
239806
- assetsDir: config.assetsDirectory && await pathExists(config.assetsDirectory) ? config.assetsDirectory : null
239807
- };
239808
- }
239809
-
239810
239611
  // src/core/site/manifest.ts
239811
239612
  import { createHash } from "node:crypto";
239812
239613
  import { createReadStream } from "node:fs";
239813
- import { stat as stat2 } from "node:fs/promises";
239814
- import { basename as basename5, extname, join as join17 } from "node:path";
239815
-
239816
- // ../../node_modules/p-map/index.js
239817
- async function pMap(iterable, mapper, {
239818
- concurrency = Number.POSITIVE_INFINITY,
239819
- stopOnError = true,
239820
- signal
239821
- } = {}) {
239822
- return new Promise((resolve_, reject_) => {
239823
- if (iterable[Symbol.iterator] === undefined && iterable[Symbol.asyncIterator] === undefined) {
239824
- throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`);
239825
- }
239826
- if (typeof mapper !== "function") {
239827
- throw new TypeError("Mapper function is required");
239828
- }
239829
- if (!(Number.isSafeInteger(concurrency) && concurrency >= 1 || concurrency === Number.POSITIVE_INFINITY)) {
239830
- throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
239831
- }
239832
- const result = [];
239833
- const errors = [];
239834
- const skippedIndexesMap = new Map;
239835
- let isRejected = false;
239836
- let isResolved = false;
239837
- let isIterableDone = false;
239838
- let resolvingCount = 0;
239839
- let currentIndex = 0;
239840
- const iterator = iterable[Symbol.iterator] === undefined ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
239841
- const signalListener = () => {
239842
- reject(signal.reason);
239843
- };
239844
- const cleanup = () => {
239845
- signal?.removeEventListener("abort", signalListener);
239846
- };
239847
- const resolve = (value) => {
239848
- resolve_(value);
239849
- cleanup();
239850
- };
239851
- const reject = (reason) => {
239852
- isRejected = true;
239853
- isResolved = true;
239854
- reject_(reason);
239855
- cleanup();
239856
- };
239857
- if (signal) {
239858
- if (signal.aborted) {
239859
- reject(signal.reason);
239860
- return;
239861
- }
239862
- signal.addEventListener("abort", signalListener, { once: true });
239863
- }
239864
- const next = async () => {
239865
- if (isResolved) {
239866
- return;
239867
- }
239868
- const nextItem = await iterator.next();
239869
- const index = currentIndex;
239870
- currentIndex++;
239871
- if (nextItem.done) {
239872
- isIterableDone = true;
239873
- if (resolvingCount === 0 && !isResolved) {
239874
- if (!stopOnError && errors.length > 0) {
239875
- reject(new AggregateError(errors));
239876
- return;
239877
- }
239878
- isResolved = true;
239879
- if (skippedIndexesMap.size === 0) {
239880
- resolve(result);
239881
- return;
239882
- }
239883
- const pureResult = [];
239884
- for (const [index, value] of result.entries()) {
239885
- if (skippedIndexesMap.get(index) === pMapSkip) {
239886
- continue;
239887
- }
239888
- pureResult.push(value);
239889
- }
239890
- resolve(pureResult);
239891
- }
239892
- return;
239893
- }
239894
- resolvingCount++;
239895
- (async () => {
239896
- try {
239897
- const element = await nextItem.value;
239898
- if (isResolved) {
239899
- return;
239900
- }
239901
- const value = await mapper(element, index);
239902
- if (value === pMapSkip) {
239903
- skippedIndexesMap.set(index, value);
239904
- }
239905
- result[index] = value;
239906
- resolvingCount--;
239907
- await next();
239908
- } catch (error) {
239909
- if (stopOnError) {
239910
- reject(error);
239911
- } else {
239912
- errors.push(error);
239913
- resolvingCount--;
239914
- try {
239915
- await next();
239916
- } catch (error) {
239917
- reject(error);
239918
- }
239919
- }
239920
- }
239921
- })();
239922
- };
239923
- (async () => {
239924
- for (let index = 0;index < concurrency; index++) {
239925
- try {
239926
- await next();
239927
- } catch (error) {
239928
- reject(error);
239929
- break;
239930
- }
239931
- if (isIterableDone || isRejected) {
239932
- break;
239933
- }
239934
- }
239935
- })();
239936
- });
239937
- }
239938
- var pMapSkip = Symbol("skip");
239939
-
239940
- // src/core/site/manifest.ts
239614
+ import { stat } from "node:fs/promises";
239615
+ import { basename as basename5, extname, join as join16 } from "node:path";
239941
239616
  var MAX_ASSET_COUNT = 1e5;
239942
239617
  var ASSETS_IGNORE_FILE = ".assetsignore";
239943
239618
  var ALWAYS_IGNORED = new Set([
@@ -239978,42 +239653,30 @@ var MIME_TYPES = {
239978
239653
  function getAssetContentType(filePath) {
239979
239654
  return MIME_TYPES[extname(filePath).toLowerCase()] ?? "application/octet-stream";
239980
239655
  }
239981
- async function walkBuildOutput(outputDir) {
239982
- const found = await globby("**/*", {
239983
- cwd: outputDir,
239984
- dot: true,
239985
- onlyFiles: true,
239986
- followSymbolicLinks: false,
239987
- ignoreFiles: [ASSETS_IGNORE_FILE]
239988
- });
239989
- return found.filter((path) => !ALWAYS_IGNORED.has(basename5(path))).sort();
239990
- }
239991
- var STAT_CONCURRENCY = 32;
239992
- async function describeBuildOutput(outputDir) {
239993
- const relativePaths = await walkBuildOutput(outputDir);
239994
- return await pMap(relativePaths, async (path) => {
239995
- const absolutePath = join17(outputDir, ...path.split("/"));
239996
- return { path, absolutePath, size: (await stat2(absolutePath)).size };
239997
- }, { concurrency: STAT_CONCURRENCY });
239998
- }
239999
- async function hashFileInto(hash, absolutePath) {
239656
+ async function hashAssetFile(appId, absolutePath) {
239657
+ const hash = createHash("sha256").update(Buffer.from(appId, "utf8"));
240000
239658
  for await (const chunk of createReadStream(absolutePath)) {
240001
239659
  hash.update(chunk);
240002
239660
  }
240003
- return hash;
240004
- }
240005
- async function hashAssetFile(appId, absolutePath) {
240006
- const hash = await hashFileInto(createHash("sha256").update(Buffer.from(appId, "utf8")), absolutePath);
240007
239661
  return hash.digest("hex").slice(0, 32);
240008
239662
  }
240009
239663
  async function buildAssetManifest(assetsDir, appId) {
240010
239664
  const manifest = {};
240011
239665
  const filesByHash = new Map;
240012
- const files = await describeBuildOutput(assetsDir);
240013
- if (files.length > MAX_ASSET_COUNT) {
240014
- throw new InvalidInputError(`Too many static assets: found ${files.length}, the limit is ${MAX_ASSET_COUNT} files.`);
239666
+ const found = await globby("**/*", {
239667
+ cwd: assetsDir,
239668
+ dot: true,
239669
+ onlyFiles: true,
239670
+ followSymbolicLinks: false,
239671
+ ignoreFiles: [ASSETS_IGNORE_FILE]
239672
+ });
239673
+ const relativeFilePaths = found.filter((path) => !ALWAYS_IGNORED.has(basename5(path)));
239674
+ if (relativeFilePaths.length > MAX_ASSET_COUNT) {
239675
+ throw new InvalidInputError(`Too many static assets: found ${relativeFilePaths.length}, the limit is ${MAX_ASSET_COUNT} files.`);
240015
239676
  }
240016
- for (const { path: relativePath, absolutePath, size } of files) {
239677
+ for (const relativePath of relativeFilePaths.sort()) {
239678
+ const absolutePath = join16(assetsDir, ...relativePath.split("/"));
239679
+ const { size } = await stat(absolutePath);
240017
239680
  const hash = await hashAssetFile(appId, absolutePath);
240018
239681
  manifest[`/${relativePath}`] = { hash, size };
240019
239682
  if (!filesByHash.has(hash)) {
@@ -240028,8 +239691,229 @@ async function buildAssetManifest(assetsDir, appId) {
240028
239691
  return { manifest, filesByHash };
240029
239692
  }
240030
239693
 
239694
+ // src/core/site/modules.ts
239695
+ import { stat as stat2 } from "node:fs/promises";
239696
+ import { relative as relative5, resolve as resolve3, sep } from "node:path";
239697
+ var MAX_TOTAL_MODULE_BYTES = 40 * 1024 * 1024;
239698
+ var MODULE_IGNORE = ["wrangler.json", ".dev.vars"];
239699
+ var RULE_TYPE_TO_MODULE_TYPE = {
239700
+ ESModule: "esm",
239701
+ CompiledWasm: "wasm",
239702
+ Text: "text",
239703
+ Data: "data"
239704
+ };
239705
+ function toPosix(path) {
239706
+ return path.split(sep).join("/");
239707
+ }
239708
+ async function collectModules(config) {
239709
+ const entryPath = resolve3(config.configDir, config.main);
239710
+ if (!await pathExists(entryPath)) {
239711
+ throw new InvalidInputError(`Worker entry module does not exist: ${entryPath} (from "main" in ${config.configPath})`, {
239712
+ hints: [{ message: "Rebuild the project to regenerate the artifact" }]
239713
+ });
239714
+ }
239715
+ const modulesByName = new Map;
239716
+ const entryName = toPosix(relative5(config.configDir, entryPath));
239717
+ modulesByName.set(entryName, {
239718
+ name: entryName,
239719
+ absolutePath: entryPath,
239720
+ size: 0,
239721
+ type: "esm"
239722
+ });
239723
+ const ignore = [...MODULE_IGNORE];
239724
+ if (config.assetsDirectory?.startsWith(config.configDir + sep)) {
239725
+ ignore.push(`${toPosix(relative5(config.configDir, config.assetsDirectory))}/**`);
239726
+ }
239727
+ for (const rule of config.rules) {
239728
+ const type = RULE_TYPE_TO_MODULE_TYPE[rule.type];
239729
+ if (!type) {
239730
+ throw new InvalidInputError(`Unsupported module rule type "${rule.type}" in ${config.configPath}. Supported: ${Object.keys(RULE_TYPE_TO_MODULE_TYPE).join(", ")}.`);
239731
+ }
239732
+ const matches = await globby(rule.globs, {
239733
+ cwd: config.configDir,
239734
+ onlyFiles: true,
239735
+ dot: true,
239736
+ ignore
239737
+ });
239738
+ for (const match of matches.sort()) {
239739
+ if (!modulesByName.has(match)) {
239740
+ modulesByName.set(match, {
239741
+ name: match,
239742
+ absolutePath: resolve3(config.configDir, match),
239743
+ size: 0,
239744
+ type
239745
+ });
239746
+ }
239747
+ }
239748
+ }
239749
+ if (config.uploadSourceMaps) {
239750
+ const maps = await globby("**/*.map", {
239751
+ cwd: config.configDir,
239752
+ onlyFiles: true,
239753
+ dot: true,
239754
+ ignore
239755
+ });
239756
+ for (const map of maps.sort()) {
239757
+ addSourcemap(modulesByName, config.configDir, map);
239758
+ }
239759
+ } else {
239760
+ for (const name of [...modulesByName.keys()]) {
239761
+ const mapName = `${name}.map`;
239762
+ if (await pathExists(resolve3(config.configDir, mapName))) {
239763
+ addSourcemap(modulesByName, config.configDir, mapName);
239764
+ }
239765
+ }
239766
+ }
239767
+ const modules = [...modulesByName.values()];
239768
+ let totalBytes = 0;
239769
+ for (const module of modules) {
239770
+ module.size = (await stat2(module.absolutePath)).size;
239771
+ totalBytes += module.size;
239772
+ }
239773
+ if (totalBytes > MAX_TOTAL_MODULE_BYTES) {
239774
+ throw new InvalidInputError(`Worker modules total ${totalBytes} bytes, which exceeds the 40 MB limit for a Base44 deploy.`);
239775
+ }
239776
+ return modules;
239777
+ }
239778
+ function addSourcemap(modulesByName, configDir, name) {
239779
+ if (modulesByName.has(name))
239780
+ return;
239781
+ modulesByName.set(name, {
239782
+ name,
239783
+ absolutePath: resolve3(configDir, name),
239784
+ size: 0,
239785
+ type: "sourcemap"
239786
+ });
239787
+ }
239788
+
240031
239789
  // src/core/site/upload.ts
240032
239790
  import { readFile as readFile2 } from "node:fs/promises";
239791
+
239792
+ // ../../node_modules/p-map/index.js
239793
+ async function pMap(iterable, mapper, {
239794
+ concurrency = Number.POSITIVE_INFINITY,
239795
+ stopOnError = true,
239796
+ signal
239797
+ } = {}) {
239798
+ return new Promise((resolve_, reject_) => {
239799
+ if (iterable[Symbol.iterator] === undefined && iterable[Symbol.asyncIterator] === undefined) {
239800
+ throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`);
239801
+ }
239802
+ if (typeof mapper !== "function") {
239803
+ throw new TypeError("Mapper function is required");
239804
+ }
239805
+ if (!(Number.isSafeInteger(concurrency) && concurrency >= 1 || concurrency === Number.POSITIVE_INFINITY)) {
239806
+ throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
239807
+ }
239808
+ const result = [];
239809
+ const errors = [];
239810
+ const skippedIndexesMap = new Map;
239811
+ let isRejected = false;
239812
+ let isResolved = false;
239813
+ let isIterableDone = false;
239814
+ let resolvingCount = 0;
239815
+ let currentIndex = 0;
239816
+ const iterator = iterable[Symbol.iterator] === undefined ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
239817
+ const signalListener = () => {
239818
+ reject(signal.reason);
239819
+ };
239820
+ const cleanup = () => {
239821
+ signal?.removeEventListener("abort", signalListener);
239822
+ };
239823
+ const resolve = (value) => {
239824
+ resolve_(value);
239825
+ cleanup();
239826
+ };
239827
+ const reject = (reason) => {
239828
+ isRejected = true;
239829
+ isResolved = true;
239830
+ reject_(reason);
239831
+ cleanup();
239832
+ };
239833
+ if (signal) {
239834
+ if (signal.aborted) {
239835
+ reject(signal.reason);
239836
+ return;
239837
+ }
239838
+ signal.addEventListener("abort", signalListener, { once: true });
239839
+ }
239840
+ const next = async () => {
239841
+ if (isResolved) {
239842
+ return;
239843
+ }
239844
+ const nextItem = await iterator.next();
239845
+ const index = currentIndex;
239846
+ currentIndex++;
239847
+ if (nextItem.done) {
239848
+ isIterableDone = true;
239849
+ if (resolvingCount === 0 && !isResolved) {
239850
+ if (!stopOnError && errors.length > 0) {
239851
+ reject(new AggregateError(errors));
239852
+ return;
239853
+ }
239854
+ isResolved = true;
239855
+ if (skippedIndexesMap.size === 0) {
239856
+ resolve(result);
239857
+ return;
239858
+ }
239859
+ const pureResult = [];
239860
+ for (const [index, value] of result.entries()) {
239861
+ if (skippedIndexesMap.get(index) === pMapSkip) {
239862
+ continue;
239863
+ }
239864
+ pureResult.push(value);
239865
+ }
239866
+ resolve(pureResult);
239867
+ }
239868
+ return;
239869
+ }
239870
+ resolvingCount++;
239871
+ (async () => {
239872
+ try {
239873
+ const element = await nextItem.value;
239874
+ if (isResolved) {
239875
+ return;
239876
+ }
239877
+ const value = await mapper(element, index);
239878
+ if (value === pMapSkip) {
239879
+ skippedIndexesMap.set(index, value);
239880
+ }
239881
+ result[index] = value;
239882
+ resolvingCount--;
239883
+ await next();
239884
+ } catch (error) {
239885
+ if (stopOnError) {
239886
+ reject(error);
239887
+ } else {
239888
+ errors.push(error);
239889
+ resolvingCount--;
239890
+ try {
239891
+ await next();
239892
+ } catch (error) {
239893
+ reject(error);
239894
+ }
239895
+ }
239896
+ }
239897
+ })();
239898
+ };
239899
+ (async () => {
239900
+ for (let index = 0;index < concurrency; index++) {
239901
+ try {
239902
+ await next();
239903
+ } catch (error) {
239904
+ reject(error);
239905
+ break;
239906
+ }
239907
+ if (isIterableDone || isRejected) {
239908
+ break;
239909
+ }
239910
+ }
239911
+ })();
239912
+ });
239913
+ }
239914
+ var pMapSkip = Symbol("skip");
239915
+
239916
+ // src/core/site/upload.ts
240033
239917
  var DEFAULT_UPLOAD_CONCURRENCY = 3;
240034
239918
  var MAX_UPLOAD_CONCURRENCY = 50;
240035
239919
  var MAX_UPLOAD_ATTEMPTS = 3;
@@ -240128,17 +240012,11 @@ async function uploadPresignedAsset(upload, assets) {
240128
240012
  if (!file) {
240129
240013
  throw new InternalError(`Server requested upload of unknown asset path: ${upload.path}`);
240130
240014
  }
240131
- await putPresigned(upload, file.absolutePath);
240132
- }
240133
- async function putPresigned(upload, absolutePath) {
240134
- const content = await readFile2(absolutePath);
240015
+ const content = await readFile2(file.absolutePath);
240135
240016
  try {
240136
240017
  await distribution_default.put(upload.url, {
240137
240018
  body: new Uint8Array(content),
240138
- headers: {
240139
- "Content-Type": upload.contentType,
240140
- ...upload.checksumSha256 ? { "x-amz-checksum-sha256": upload.checksumSha256 } : {}
240141
- },
240019
+ headers: { "Content-Type": upload.contentType },
240142
240020
  timeout: 120000,
240143
240021
  retry: UPLOAD_RETRY
240144
240022
  });
@@ -240147,6 +240025,85 @@ async function putPresigned(upload, absolutePath) {
240147
240025
  }
240148
240026
  }
240149
240027
 
240028
+ // src/core/site/wrangler-config.ts
240029
+ import { dirname as dirname12, join as join17, resolve as resolve4 } from "node:path";
240030
+ var WRANGLER_REDIRECT_PATH = join17(".wrangler", "deploy", "config.json");
240031
+ var RedirectConfigSchema = looseObject({
240032
+ configPath: string2().min(1)
240033
+ });
240034
+ var WranglerConfigSchema = looseObject({
240035
+ main: string2().min(1, "wrangler config is missing a 'main' entry module"),
240036
+ no_bundle: boolean2().optional(),
240037
+ rules: array(looseObject({ type: string2(), globs: array(string2()) })).optional(),
240038
+ assets: looseObject({
240039
+ directory: string2().optional(),
240040
+ html_handling: string2().optional(),
240041
+ not_found_handling: string2().optional(),
240042
+ run_worker_first: union([boolean2(), array(string2())]).optional(),
240043
+ headers: string2().optional(),
240044
+ redirects: string2().optional()
240045
+ }).optional(),
240046
+ compatibility_date: string2().optional(),
240047
+ compatibility_flags: array(string2()).optional(),
240048
+ vars: record(string2(), unknown()).optional(),
240049
+ upload_source_maps: boolean2().optional()
240050
+ });
240051
+ async function detectFullStackArtifact(projectRoot) {
240052
+ const redirectPath = join17(projectRoot, WRANGLER_REDIRECT_PATH);
240053
+ return await pathExists(redirectPath) ? redirectPath : null;
240054
+ }
240055
+ async function resolveWranglerConfig(redirectPath) {
240056
+ const configPath = await resolveRedirectedConfigPath(redirectPath);
240057
+ const parsed = await readJsonFile(configPath);
240058
+ const result = WranglerConfigSchema.safeParse(parsed);
240059
+ if (!result.success) {
240060
+ throw new ConfigInvalidError(`Invalid wrangler config: ${prettifyError(result.error)}`, configPath);
240061
+ }
240062
+ const config = result.data;
240063
+ if (config.no_bundle !== true) {
240064
+ throw new InvalidInputError("This framework's output requires bundling; not yet supported. Base44 only deploys pre-bundled Workers output (no_bundle: true).");
240065
+ }
240066
+ const configDir = dirname12(configPath);
240067
+ const assetsDirectory = config.assets?.directory ? resolve4(configDir, config.assets.directory) : null;
240068
+ return {
240069
+ configPath,
240070
+ configDir,
240071
+ main: config.main,
240072
+ assetsDirectory,
240073
+ assetsConfig: config.assets ? toResolvedAssetsConfig(config.assets) : null,
240074
+ compatibilityDate: config.compatibility_date ?? null,
240075
+ compatibilityFlags: config.compatibility_flags ?? [],
240076
+ rules: (config.rules ?? []).map((rule) => ({
240077
+ type: rule.type,
240078
+ globs: rule.globs
240079
+ })),
240080
+ uploadSourceMaps: config.upload_source_maps ?? false
240081
+ };
240082
+ }
240083
+ async function resolveRedirectedConfigPath(redirectPath) {
240084
+ const parsed = await readJsonFile(redirectPath);
240085
+ const result = RedirectConfigSchema.safeParse(parsed);
240086
+ if (!result.success) {
240087
+ throw new ConfigInvalidError(`Invalid deploy redirect file: ${prettifyError(result.error)}`, redirectPath);
240088
+ }
240089
+ const configPath = resolve4(dirname12(redirectPath), result.data.configPath);
240090
+ if (!await pathExists(configPath)) {
240091
+ throw new ConfigInvalidError(`Wrangler config referenced by ${redirectPath} does not exist: ${configPath}`, redirectPath, {
240092
+ hints: [{ message: "Rebuild the project to regenerate the artifact" }]
240093
+ });
240094
+ }
240095
+ return configPath;
240096
+ }
240097
+ function toResolvedAssetsConfig(assets) {
240098
+ return {
240099
+ htmlHandling: assets.html_handling,
240100
+ notFoundHandling: assets.not_found_handling,
240101
+ runWorkerFirst: assets.run_worker_first,
240102
+ headers: assets.headers,
240103
+ redirects: assets.redirects
240104
+ };
240105
+ }
240106
+
240150
240107
  // src/core/site/deployment.ts
240151
240108
  var NO_ASSETS = { manifest: {}, filesByHash: new Map };
240152
240109
  var DEPLOYMENTS_API_ENV = "BASE44_DEPLOYMENTS_API";
@@ -240176,11 +240133,12 @@ async function deployToDeployments(options) {
240176
240133
  return { deploymentId: finalized.deploymentId, gitHash };
240177
240134
  }
240178
240135
  async function resolveWorkerBuild(projectRoot, progress) {
240179
- const built = await resolveFullStackBuild(projectRoot);
240180
- if (!built) {
240136
+ const redirectPath = await detectFullStackArtifact(projectRoot);
240137
+ if (!redirectPath) {
240181
240138
  return null;
240182
240139
  }
240183
- const { config, modules, assetsDir } = built;
240140
+ const config = await resolveWranglerConfig(redirectPath);
240141
+ const assetsDir = config.assetsDirectory && await pathExists(config.assetsDirectory) ? config.assetsDirectory : null;
240184
240142
  return {
240185
240143
  config: {
240186
240144
  main: config.main,
@@ -240188,7 +240146,7 @@ async function resolveWorkerBuild(projectRoot, progress) {
240188
240146
  compatibility_flags: config.compatibilityFlags,
240189
240147
  assets: buildAssetsConfig(config.assetsConfig, progress)
240190
240148
  },
240191
- modules,
240149
+ modules: await collectModules(config),
240192
240150
  assetsDir
240193
240151
  };
240194
240152
  }
@@ -246741,13 +246699,6 @@ async function resolveGitHash(projectRoot, explicit) {
246741
246699
  }
246742
246700
  return hash;
246743
246701
  }
246744
- async function resolveProvenanceCommit(projectRoot, explicit) {
246745
- if (explicit) {
246746
- return await resolveGitHash(projectRoot, explicit);
246747
- }
246748
- const hash = await gitHead(projectRoot);
246749
- return hash && isGitCommitHash(hash) ? hash : undefined;
246750
- }
246751
246702
  async function gitHead(projectRoot) {
246752
246703
  try {
246753
246704
  const { stdout } = await execa("git", ["rev-parse", "HEAD"], {
@@ -246758,6 +246709,35 @@ async function gitHead(projectRoot) {
246758
246709
  return null;
246759
246710
  }
246760
246711
  }
246712
+ // src/core/site/serve-command.ts
246713
+ var DEFAULT_SERVE_COMMAND = "npm run dev";
246714
+ var SCRIPT = "[A-Za-z0-9:_.-]+";
246715
+ var PREFIX2 = "[A-Za-z0-9._/-]+";
246716
+ var SCRIPT_RUNNERS = [
246717
+ {
246718
+ pattern: new RegExp(String.raw`^npm(\s+--prefix\s+${PREFIX2})?\s+run\s+${SCRIPT}$`),
246719
+ separator: " -- "
246720
+ },
246721
+ {
246722
+ pattern: new RegExp(String.raw`^(?:pnpm|yarn|bun)(\s+run)?\s+${SCRIPT}$`),
246723
+ separator: " "
246724
+ }
246725
+ ];
246726
+ function runnerFor(serveCommand) {
246727
+ return SCRIPT_RUNNERS.find((runner) => runner.pattern.test(serveCommand));
246728
+ }
246729
+ function withServeAddress(serveCommand, { host, port, hostFlag }) {
246730
+ const command = serveCommand.trim();
246731
+ const args = [hostFlag, host, "--port", String(port)];
246732
+ const runner = runnerFor(command);
246733
+ if (!runner) {
246734
+ return { command, droppedAddress: true };
246735
+ }
246736
+ return {
246737
+ command: `${command}${runner.separator}${args.join(" ")}`,
246738
+ droppedAddress: false
246739
+ };
246740
+ }
246761
246741
  // src/core/project/deploy.ts
246762
246742
  function hasResourcesToDeploy(projectData) {
246763
246743
  const {
@@ -246836,49 +246816,6 @@ async function deployAll(projectData, options) {
246836
246816
  }
246837
246817
  return { connectorResults };
246838
246818
  }
246839
- // src/core/project/target.ts
246840
- import { dirname as dirname13, join as join19, resolve as resolve6 } from "node:path";
246841
- var DEFAULT_BUILD_COMMAND = "npm run build";
246842
- var DEFAULT_OUTPUT_DIRECTORY = "dist";
246843
- async function resolveBuildTarget(projectRoot, overrides = {}) {
246844
- const project = await readSettingsIfPresent(projectRoot);
246845
- const root = project?.root ?? projectRoot ?? process.cwd();
246846
- return {
246847
- root,
246848
- configDir: project ? dirname13(project.configPath) : join19(root, PROJECT_SUBDIR),
246849
- buildCommand: project ? project.site?.buildCommand : DEFAULT_BUILD_COMMAND,
246850
- outputDir: outputDirectory(project, root, overrides.outputDir),
246851
- entitiesDir: project?.entitiesDir ?? "entities",
246852
- agentsDir: project?.agentsDir ?? "agents"
246853
- };
246854
- }
246855
- function outputDirectory(project, root, override) {
246856
- const configured = override ?? (project ? project.site?.outputDirectory : DEFAULT_OUTPUT_DIRECTORY);
246857
- return configured ? resolve6(root, configured) : null;
246858
- }
246859
- function requireOutputDir(target) {
246860
- if (target.outputDir === null) {
246861
- throw new ConfigNotFoundError("No site configuration found.", {
246862
- hints: [
246863
- {
246864
- message: `Add 'site.outputDirectory' to your config.jsonc (e.g., "site": { "outputDirectory": "dist" })`
246865
- },
246866
- { message: `Or pass --output-dir <dir>, relative to ${target.root}` }
246867
- ]
246868
- });
246869
- }
246870
- return target.outputDir;
246871
- }
246872
- async function readSettingsIfPresent(projectRoot) {
246873
- try {
246874
- return await readProjectSettings(projectRoot);
246875
- } catch (error) {
246876
- if (error instanceof ConfigNotFoundError) {
246877
- return null;
246878
- }
246879
- throw error;
246880
- }
246881
- }
246882
246819
  // src/core/clients/base44-client.ts
246883
246820
  var retriedRequests = new WeakSet;
246884
246821
  async function captureRequestBody(request, options) {
@@ -247160,12 +247097,6 @@ async function ensureAppContext(ctx, options = {}) {
247160
247097
  ctx.app = appContext;
247161
247098
  ctx.errorReporter.setContext({ appId: appContext.id });
247162
247099
  }
247163
- function requireApp(ctx) {
247164
- if (!ctx.app) {
247165
- throw new InternalError("This command read an app context it never resolved — it is declared with requireAppContext: false.");
247166
- }
247167
- return ctx.app;
247168
- }
247169
247100
 
247170
247101
  // src/cli/utils/version-check.ts
247171
247102
  async function checkForUpgrade() {
@@ -247349,10 +247280,6 @@ function writeJsonError(error) {
247349
247280
  const envelope = {
247350
247281
  error: error instanceof Error ? error.message : String(error)
247351
247282
  };
247352
- const step = stepOf(error);
247353
- if (step !== undefined) {
247354
- envelope.step = step;
247355
- }
247356
247283
  if (isCLIError(error)) {
247357
247284
  envelope.code = error.code;
247358
247285
  if (error.details.length > 0) {
@@ -247722,7 +247649,7 @@ function getActorsCommand() {
247722
247649
  }
247723
247650
 
247724
247651
  // src/cli/commands/agent-skills/pull.ts
247725
- import { dirname as dirname14, join as join20 } from "node:path";
247652
+ import { dirname as dirname13, join as join19 } from "node:path";
247726
247653
  // src/core/utils/dependencies.ts
247727
247654
  import { spawnSync as spawnSync2 } from "node:child_process";
247728
247655
  function verifyDenoInstalled(context) {
@@ -247811,7 +247738,7 @@ async function pullAction({
247811
247738
  runTask
247812
247739
  }) {
247813
247740
  const { project } = await readProjectConfig();
247814
- const dir = join20(dirname14(project.configPath), project.agentSkillsDir);
247741
+ const dir = join19(dirname13(project.configPath), project.agentSkillsDir);
247815
247742
  const remote = await runTask("Fetching agent skills from Base44", () => fetchAgentSkills(), {
247816
247743
  successMessage: "Agent skills fetched successfully",
247817
247744
  errorMessage: "Failed to fetch agent skills"
@@ -247867,14 +247794,14 @@ function getAgentSkillsCommand() {
247867
247794
  }
247868
247795
 
247869
247796
  // src/cli/commands/agents/pull.ts
247870
- import { dirname as dirname15, join as join21 } from "node:path";
247797
+ import { dirname as dirname14, join as join20 } from "node:path";
247871
247798
  async function pullAgentsAction({
247872
247799
  log,
247873
247800
  runTask
247874
247801
  }) {
247875
247802
  const { project } = await readProjectConfig();
247876
- const configDir = dirname15(project.configPath);
247877
- const agentsDir = join21(configDir, project.agentsDir);
247803
+ const configDir = dirname14(project.configPath);
247804
+ const agentsDir = join20(configDir, project.agentsDir);
247878
247805
  const remoteAgents = await runTask("Fetching agents from Base44", async () => {
247879
247806
  return await fetchAgents();
247880
247807
  }, {
@@ -247944,12 +247871,12 @@ function getAgentsCommand() {
247944
247871
  }
247945
247872
 
247946
247873
  // src/cli/commands/auth/password-login.ts
247947
- import { dirname as dirname16, join as join22 } from "node:path";
247874
+ import { dirname as dirname15, join as join21 } from "node:path";
247948
247875
  async function passwordLoginAction({ log, runTask }, action) {
247949
247876
  const shouldEnable = action === "enable";
247950
247877
  const { project } = await readProjectConfig();
247951
- const configDir = dirname16(project.configPath);
247952
- const authDir = join22(configDir, project.authDir);
247878
+ const configDir = dirname15(project.configPath);
247879
+ const authDir = join21(configDir, project.authDir);
247953
247880
  const updated = await runTask("Updating local auth config", async () => {
247954
247881
  const current = await readAuthConfig(authDir) ?? DEFAULT_AUTH_CONFIG;
247955
247882
  const merged = { ...current, enableUsernamePassword: shouldEnable };
@@ -247969,14 +247896,14 @@ function getPasswordLoginCommand() {
247969
247896
  }
247970
247897
 
247971
247898
  // src/cli/commands/auth/pull.ts
247972
- import { dirname as dirname17, join as join23 } from "node:path";
247899
+ import { dirname as dirname16, join as join22 } from "node:path";
247973
247900
  async function pullAuthAction({
247974
247901
  log,
247975
247902
  runTask
247976
247903
  }) {
247977
247904
  const { project } = await readProjectConfig();
247978
- const configDir = dirname17(project.configPath);
247979
- const authDir = join23(configDir, project.authDir);
247905
+ const configDir = dirname16(project.configPath);
247906
+ const authDir = join22(configDir, project.authDir);
247980
247907
  const remoteConfig = await runTask("Fetching auth config from Base44", async () => {
247981
247908
  return await pullAuthConfig();
247982
247909
  }, {
@@ -248040,7 +247967,7 @@ function getAuthPushCommand() {
248040
247967
  }
248041
247968
 
248042
247969
  // src/cli/commands/auth/social-login.ts
248043
- import { dirname as dirname18, join as join24, resolve as resolve7 } from "node:path";
247970
+ import { dirname as dirname17, join as join23, resolve as resolve6 } from "node:path";
248044
247971
  var PROVIDER_LABELS = {
248045
247972
  google: "Google",
248046
247973
  microsoft: "Microsoft",
@@ -248080,7 +248007,7 @@ async function socialLoginAction({ log, isNonInteractive, runTask }, provider, a
248080
248007
  let clientSecret;
248081
248008
  if (useCustomOAuth && oauth && oauthCli && hasSecretOptions(options)) {
248082
248009
  if (options.envFile) {
248083
- const secrets = await parseEnvFile(resolve7(options.envFile));
248010
+ const secrets = await parseEnvFile(resolve6(options.envFile));
248084
248011
  const value = secrets[oauthCli.envVar];
248085
248012
  if (!value) {
248086
248013
  throw new InvalidInputError(`Key "${oauthCli.envVar}" not found in ${options.envFile}.`);
@@ -248110,8 +248037,8 @@ async function socialLoginAction({ log, isNonInteractive, runTask }, provider, a
248110
248037
  }
248111
248038
  }
248112
248039
  const { project } = await readProjectConfig();
248113
- const configDir = dirname18(project.configPath);
248114
- const authDir = join24(configDir, project.authDir);
248040
+ const configDir = dirname17(project.configPath);
248041
+ const authDir = join23(configDir, project.authDir);
248115
248042
  const { config: updated } = await runTask("Updating local auth config", async () => updateSocialLoginConfig(authDir, provider, shouldEnable, useCustomOAuth && options.clientId ? { clientId: options.clientId } : undefined));
248116
248043
  if (clientSecret) {
248117
248044
  await runTask("Saving client secret", async () => pushCustomOAuthSecret(provider, clientSecret));
@@ -248136,7 +248063,7 @@ function getSocialLoginCommand() {
248136
248063
  }
248137
248064
 
248138
248065
  // src/cli/commands/auth/sso.ts
248139
- import { dirname as dirname19, join as join25, resolve as resolve8 } from "node:path";
248066
+ import { dirname as dirname18, join as join24, resolve as resolve7 } from "node:path";
248140
248067
  var SSOConfigFileSchema = object({
248141
248068
  provider: _enum(Object.values(KNOWN_SSO_PROVIDERS)),
248142
248069
  clientId: string2(),
@@ -248152,7 +248079,7 @@ var SSOConfigFileSchema = object({
248152
248079
  ssoName: string2().optional()
248153
248080
  });
248154
248081
  async function loadSSOConfigFile(filePath) {
248155
- const resolved = resolve8(filePath);
248082
+ const resolved = resolve7(filePath);
248156
248083
  const raw = await readJsonFile(resolved);
248157
248084
  const result = SSOConfigFileSchema.safeParse(raw);
248158
248085
  if (!result.success) {
@@ -248240,7 +248167,7 @@ async function ssoEnableAction({ isNonInteractive, runTask }, options) {
248240
248167
  }
248241
248168
  let clientSecret;
248242
248169
  if (merged.envFile && !merged.clientSecret) {
248243
- const secrets = await parseEnvFile(resolve8(merged.envFile));
248170
+ const secrets = await parseEnvFile(resolve7(merged.envFile));
248244
248171
  const value = secrets.sso_client_secret;
248245
248172
  if (!value) {
248246
248173
  throw new InvalidInputError(`Key "sso_client_secret" not found in ${merged.envFile}.`);
@@ -248299,8 +248226,8 @@ async function ssoEnableAction({ isNonInteractive, runTask }, options) {
248299
248226
  throw error;
248300
248227
  }
248301
248228
  const { project } = await readProjectConfig();
248302
- const configDir = dirname19(project.configPath);
248303
- const authDir = join25(configDir, project.authDir);
248229
+ const configDir = dirname18(project.configPath);
248230
+ const authDir = join24(configDir, project.authDir);
248304
248231
  await runTask("Updating local auth config", async () => updateSSOConfig(authDir, provider, true));
248305
248232
  await runTask("Saving SSO credentials", async () => pushSSOSecrets(secrets));
248306
248233
  return {
@@ -248315,8 +248242,8 @@ async function ssoDisableAction({ log, runTask }, options) {
248315
248242
  throw new InvalidInputError("Configuration options cannot be used with disable. To disable SSO: base44 auth sso disable");
248316
248243
  }
248317
248244
  const { project } = await readProjectConfig();
248318
- const configDir = dirname19(project.configPath);
248319
- const authDir = join25(configDir, project.authDir);
248245
+ const configDir = dirname18(project.configPath);
248246
+ const authDir = join24(configDir, project.authDir);
248320
248247
  const updated = await runTask("Updating local auth config", async () => updateSSOConfig(authDir, null, false));
248321
248248
  await runTask("Removing SSO credentials", async () => deleteSSOSecrets());
248322
248249
  if (!hasAnyLoginMethod(updated)) {
@@ -249198,13 +249125,13 @@ function getConnectorsListAvailableCommand() {
249198
249125
  }
249199
249126
 
249200
249127
  // src/cli/commands/connectors/pull.ts
249201
- import { dirname as dirname20, join as join26, resolve as resolve9 } from "node:path";
249128
+ import { dirname as dirname19, join as join25, resolve as resolve8 } from "node:path";
249202
249129
  async function resolveConnectorsDir(options) {
249203
249130
  if (!getAppContext().projectRoot) {
249204
- return resolve9(options.dir ?? "connectors");
249131
+ return resolve8(options.dir ?? "connectors");
249205
249132
  }
249206
249133
  const { project } = await readProjectConfig();
249207
- return join26(dirname20(project.configPath), project.connectorsDir);
249134
+ return join25(dirname19(project.configPath), project.connectorsDir);
249208
249135
  }
249209
249136
  async function pullConnectorsAction({ log, runTask, jsonMode }, options) {
249210
249137
  const connectorsDir = await resolveConnectorsDir(options);
@@ -249245,10 +249172,10 @@ function getConnectorsPullCommand() {
249245
249172
  }
249246
249173
 
249247
249174
  // src/cli/commands/connectors/push.ts
249248
- import { resolve as resolve10 } from "node:path";
249175
+ import { resolve as resolve9 } from "node:path";
249249
249176
  async function readConnectorsToPush(options) {
249250
249177
  if (!getAppContext().projectRoot) {
249251
- return readAllConnectors(resolve10(options.dir ?? "connectors"));
249178
+ return readAllConnectors(resolve9(options.dir ?? "connectors"));
249252
249179
  }
249253
249180
  const { connectors } = await readProjectConfig();
249254
249181
  return connectors;
@@ -249591,11 +249518,11 @@ function getListCommand() {
249591
249518
  }
249592
249519
 
249593
249520
  // src/cli/commands/functions/pull.ts
249594
- import { dirname as dirname21, join as join27 } from "node:path";
249521
+ import { dirname as dirname20, join as join26 } from "node:path";
249595
249522
  async function pullFunctionsAction({ log, runTask }, name) {
249596
249523
  const { project, functions } = await readProjectConfig();
249597
- const configDir = dirname21(project.configPath);
249598
- const functionsDir = join27(configDir, project.functionsDir);
249524
+ const configDir = dirname20(project.configPath);
249525
+ const functionsDir = join26(configDir, project.functionsDir);
249599
249526
  const pluginFunctionNames = new Set(functions.filter((fn) => fn.source.type === "plugin").map((fn) => fn.name));
249600
249527
  const remoteFunctions = await runTask("Fetching functions from Base44", async () => {
249601
249528
  const { functions } = await listDeployedFunctions();
@@ -249698,11 +249625,14 @@ async function maybeAskToBuild(isNonInteractive, buildCommand) {
249698
249625
 
249699
249626
  // src/cli/commands/project/build.ts
249700
249627
  async function buildAction(ctx) {
249701
- const app = requireApp(ctx);
249702
- const target = await resolveBuildTarget(app.projectRoot);
249628
+ const { app } = ctx;
249629
+ if (!app?.projectRoot) {
249630
+ throw new ConfigInvalidError("base44 build requires a linked local project. Run it from a project with base44/.app.jsonc.");
249631
+ }
249632
+ const { project } = await readProjectConfig(app.projectRoot);
249703
249633
  await runSiteBuild(ctx, {
249704
- root: target.root,
249705
- buildCommand: target.buildCommand,
249634
+ root: project.root,
249635
+ buildCommand: project.site?.buildCommand,
249706
249636
  appId: app.id
249707
249637
  });
249708
249638
  return {
@@ -249714,11 +249644,11 @@ function getBuildCommand() {
249714
249644
  }
249715
249645
 
249716
249646
  // src/cli/commands/project/create.ts
249717
- import { basename as basename6, resolve as resolve11 } from "node:path";
249647
+ import { basename as basename6, resolve as resolve10 } from "node:path";
249718
249648
  var import_kebabCase = __toESM(require_kebabCase(), 1);
249719
249649
 
249720
249650
  // src/cli/commands/project/scaffold-shared.ts
249721
- import { join as join28 } from "node:path";
249651
+ import { join as join27 } from "node:path";
249722
249652
  var DEFAULT_TEMPLATE_ID = "backend-only";
249723
249653
  async function getTemplateById(templateId) {
249724
249654
  const templates = await listTemplates();
@@ -249781,7 +249711,7 @@ async function completeProjectSetup({
249781
249711
  env: { VITE_BASE44_APP_ID: projectId }
249782
249712
  })`${buildCommand}`;
249783
249713
  updateMessage("Deploying site...");
249784
- return await deploySite(join28(resolvedPath, outputDirectory));
249714
+ return await deploySite(join27(resolvedPath, outputDirectory));
249785
249715
  }, {
249786
249716
  successMessage: theme.colors.base44Orange("Site deployed successfully"),
249787
249717
  errorMessage: "Failed to deploy site"
@@ -249910,7 +249840,7 @@ async function createInteractive(options, ctx) {
249910
249840
  }, ctx);
249911
249841
  }
249912
249842
  async function createNonInteractive(options, ctx) {
249913
- ctx.log.info(`Creating a new project at ${resolve11(options.path)}`);
249843
+ ctx.log.info(`Creating a new project at ${resolve10(options.path)}`);
249914
249844
  const template = await getTemplateById(options.template ?? DEFAULT_TEMPLATE_ID);
249915
249845
  return await executeCreate({
249916
249846
  template,
@@ -249934,7 +249864,7 @@ async function executeCreate({
249934
249864
  }, ctx) {
249935
249865
  const { log, runTask } = ctx;
249936
249866
  const name = rawName.trim();
249937
- const resolvedPath = resolve11(projectPath);
249867
+ const resolvedPath = resolve10(projectPath);
249938
249868
  const organizationId = await resolveWorkspaceId(ctx, flagWorkspaceId, isInteractive);
249939
249869
  const { projectId } = await runTask("Setting up your project...", async () => {
249940
249870
  return await createProjectFiles({
@@ -250107,6 +250037,36 @@ function printStripeResult(r, log) {
250107
250037
  log.info(` Connectors dashboard: ${theme.colors.links(getConnectorsUrl())}`);
250108
250038
  }
250109
250039
 
250040
+ // src/cli/commands/project/install.ts
250041
+ async function installAction({
250042
+ runTask
250043
+ }) {
250044
+ const { project } = await readProjectConfig();
250045
+ const installCommand = project.site?.installCommand;
250046
+ if (!installCommand) {
250047
+ throw new ConfigNotFoundError("No site install command found.", {
250048
+ hints: [
250049
+ {
250050
+ message: `Add a 'site' block to your config.jsonc (e.g., "site": { "installCommand": "npm ci" }). Inside one, installCommand defaults to "npm install".`
250051
+ }
250052
+ ]
250053
+ });
250054
+ }
250055
+ await runTask("Installing site dependencies...", () => execa({ cwd: project.root, shell: true })`${installCommand}`, {
250056
+ successMessage: "Dependencies installed",
250057
+ errorMessage: "Install failed"
250058
+ });
250059
+ return {
250060
+ outroMessage: `Installed with ${theme.styles.bold(installCommand)}`
250061
+ };
250062
+ }
250063
+ function getInstallCommand() {
250064
+ return new Base44Command("install", {
250065
+ requireAuth: false,
250066
+ requireAppContext: false
250067
+ }).description("Install the site's dependencies with its configured command").action(installAction);
250068
+ }
250069
+
250110
250070
  // src/cli/commands/project/app-id-options.ts
250111
250071
  function readExplicitAppId(command) {
250112
250072
  const { appId } = command.optsWithGlobals();
@@ -250575,7 +250535,7 @@ function getLogsCommand() {
250575
250535
  }
250576
250536
 
250577
250537
  // src/cli/commands/project/scaffold.ts
250578
- import { basename as basename7, resolve as resolve12 } from "node:path";
250538
+ import { basename as basename7, resolve as resolve11 } from "node:path";
250579
250539
  function resolveAppId(options) {
250580
250540
  const appId = options.appId;
250581
250541
  if (!appId) {
@@ -250591,7 +250551,7 @@ function resolveAppId(options) {
250591
250551
  async function scaffoldAction(ctx, name, options, command) {
250592
250552
  const { log, runTask } = ctx;
250593
250553
  const appId = resolveAppId(command.optsWithGlobals());
250594
- const resolvedPath = resolve12("./");
250554
+ const resolvedPath = resolve11("./");
250595
250555
  const projectName = (name ?? basename7(resolvedPath)).trim();
250596
250556
  const template = await getTemplateById("backend-only");
250597
250557
  log.info(`Scaffolding project at ${resolvedPath}`);
@@ -250639,315 +250599,6 @@ function getVisibilityCommand() {
250639
250599
  ])).action(setVisibility);
250640
250600
  }
250641
250601
 
250642
- // src/core/version/schema.ts
250643
- var DeclareVersionResponseSchema = object({
250644
- session_id: string2(),
250645
- uploads: array(object({
250646
- path: string2(),
250647
- url: string2(),
250648
- content_type: string2(),
250649
- content_length: number2(),
250650
- checksum_sha256: string2()
250651
- }))
250652
- }).transform((data) => ({
250653
- sessionId: data.session_id,
250654
- uploads: data.uploads.map((upload) => ({
250655
- path: upload.path,
250656
- url: upload.url,
250657
- contentType: upload.content_type,
250658
- contentLength: upload.content_length,
250659
- checksumSha256: upload.checksum_sha256
250660
- }))
250661
- }));
250662
- var CreateVersionResponseSchema = object({
250663
- version_id: string2(),
250664
- manifest_hash: string2()
250665
- }).transform((data) => ({
250666
- versionId: data.version_id,
250667
- manifestHash: data.manifest_hash
250668
- }));
250669
- var EnvironmentResponseSchema = object({
250670
- name: string2(),
250671
- version_id: string2(),
250672
- manifest_hash: string2(),
250673
- deployment_id: string2()
250674
- }).transform((data) => ({
250675
- name: data.name,
250676
- versionId: data.version_id,
250677
- manifestHash: data.manifest_hash,
250678
- deploymentId: data.deployment_id
250679
- }));
250680
-
250681
- // src/core/version/api.ts
250682
- var DEFAULT_VERSION_UPLOAD_CONCURRENCY = 8;
250683
- var MAX_VERSION_UPLOAD_CONCURRENCY = 16;
250684
- function declaredFile({ path, size, digest }) {
250685
- return { path, size, digest };
250686
- }
250687
- function declaredModule(module) {
250688
- return { ...declaredFile(module), type: module.type };
250689
- }
250690
- function declaredServingConfig(config) {
250691
- const stated = {
250692
- html_handling: config?.htmlHandling ?? null,
250693
- not_found_handling: config?.notFoundHandling ?? null,
250694
- run_worker_first: config?.runWorkerFirst ?? null,
250695
- headers: config?.headers ?? null,
250696
- redirects: config?.redirects ?? null
250697
- };
250698
- return Object.values(stated).every((v) => v === null) ? null : stated;
250699
- }
250700
- async function post(path, json, doing) {
250701
- try {
250702
- return await getAppClient().post(path, { json, timeout: 180000 });
250703
- } catch (error) {
250704
- throw await ApiError.fromHttpError(error, doing);
250705
- }
250706
- }
250707
- var KEYED_RETRY = {
250708
- limit: 3,
250709
- methods: ["patch"],
250710
- statusCodes: [408, 500, 502, 503, 504],
250711
- retryOnTimeout: true
250712
- };
250713
- async function patch(path, json, doing, retry) {
250714
- try {
250715
- return await getAppClient().patch(path, {
250716
- json,
250717
- timeout: 180000,
250718
- ...retry ? { retry } : {}
250719
- });
250720
- } catch (error) {
250721
- throw await ApiError.fromHttpError(error, doing);
250722
- }
250723
- }
250724
- function parse10(schema, body, what) {
250725
- const result = schema.safeParse(body);
250726
- if (!result.success) {
250727
- throw new SchemaValidationError(`Invalid ${what} response from server`, result.error);
250728
- }
250729
- return result.data;
250730
- }
250731
- async function createVersion(artifacts, options = {}) {
250732
- const declared = parse10(DeclareVersionResponseSchema, await (await post("versions", {
250733
- assets: artifacts.assets.map(declaredFile),
250734
- ...artifacts.siteWorker ? {
250735
- site_worker: {
250736
- main: artifacts.siteWorker.main,
250737
- modules: artifacts.siteWorker.modules.map(declaredModule),
250738
- compatibility_date: artifacts.siteWorker.compatibilityDate,
250739
- compatibility_flags: artifacts.siteWorker.compatibilityFlags,
250740
- serving_config: declaredServingConfig(artifacts.siteWorker.servingConfig)
250741
- }
250742
- } : {},
250743
- entities: artifacts.entities,
250744
- agents: artifacts.agents,
250745
- source_commit: options.sourceCommit
250746
- }, "declaring a version")).json(), "declare");
250747
- const declaredFiles = [
250748
- ...artifacts.assets,
250749
- ...artifacts.siteWorker?.modules ?? []
250750
- ];
250751
- options.progress?.onDeclared?.({ fileCount: declaredFiles.length });
250752
- if (declared.uploads.length !== declaredFiles.length) {
250753
- throw new InternalError(`Declared ${declaredFiles.length} files but the server signed ${declared.uploads.length} upload URLs.`);
250754
- }
250755
- const drifted = declared.uploads.findIndex((upload, index) => upload.path !== declaredFiles[index].path);
250756
- if (drifted !== -1) {
250757
- throw new InternalError(`Upload ${drifted} is signed for ${declared.uploads[drifted].path}, but that slot declared ${declaredFiles[drifted].path}.`);
250758
- }
250759
- let uploadedFiles = 0;
250760
- await pMap(declared.uploads, async (upload, index) => {
250761
- await putPresigned(upload, declaredFiles[index].absolutePath);
250762
- uploadedFiles++;
250763
- options.progress?.onUpload?.({
250764
- uploadedFiles,
250765
- totalFiles: declared.uploads.length
250766
- });
250767
- }, { concurrency: options.concurrency ?? DEFAULT_VERSION_UPLOAD_CONCURRENCY });
250768
- return parse10(CreateVersionResponseSchema, await (await post(`versions/${encodeURIComponent(declared.sessionId)}/finalize`, {}, "creating a version")).json(), "create version");
250769
- }
250770
- async function setEnvironmentVersion(environment, versionId, options = {}) {
250771
- return parse10(EnvironmentResponseSchema, await (await patch(`environments/${encodeURIComponent(environment)}`, {
250772
- version_id: versionId,
250773
- ...options.idempotencyKey ? { idempotency_key: options.idempotencyKey } : {}
250774
- }, "setting the environment's version", options.idempotencyKey ? KEYED_RETRY : undefined)).json(), "environment");
250775
- }
250776
- // src/core/version/artifacts.ts
250777
- import { createHash as createHash2 } from "node:crypto";
250778
- import { join as join29, resolve as resolve13 } from "node:path";
250779
- var MAX_FILE_COUNT = 50000;
250780
- var HASH_CONCURRENCY = 32;
250781
- var ENTRY2 = "index.html";
250782
- async function digestFile(absolutePath) {
250783
- const hash = await hashFileInto(createHash2("sha256"), absolutePath);
250784
- return `sha256:${hash.digest("hex")}`;
250785
- }
250786
- async function collectBuildOutput(outputDir, options = {}) {
250787
- const found = await describeBuildOutput(outputDir);
250788
- if (found.length > MAX_FILE_COUNT) {
250789
- throw new InvalidInputError(`Too many files: found ${found.length}, the limit is ${MAX_FILE_COUNT}.`);
250790
- }
250791
- if (options.entryFile) {
250792
- if (found.length === 0) {
250793
- throw new InvalidInputError(`No files found in ${outputDir}. Build the site before creating a version.`, {
250794
- hints: [
250795
- { message: "Run 'base44 build' first", command: "base44 build" }
250796
- ]
250797
- });
250798
- }
250799
- if (!found.some((f) => f.path === options.entryFile)) {
250800
- throw new InvalidInputError(`${outputDir} has no ${options.entryFile}, so nothing could enter the site.`);
250801
- }
250802
- }
250803
- return await pMap(found, async (file) => ({ ...file, digest: await digestFile(file.absolutePath) }), { concurrency: HASH_CONCURRENCY });
250804
- }
250805
- async function describeSiteWorker(built) {
250806
- const { config, modules } = built;
250807
- const entry = resolve13(config.configDir, config.main);
250808
- const main = modules.find((m) => m.absolutePath === entry)?.name;
250809
- if (!main) {
250810
- throw new InvalidInputError(`The Worker's entry module ${config.main} is not among the ${modules.length} modules collected from ${config.configDir}.`);
250811
- }
250812
- return {
250813
- main,
250814
- modules: await pMap(modules, async ({ name, absolutePath, size, type }) => ({
250815
- path: name,
250816
- absolutePath,
250817
- size,
250818
- digest: await digestFile(absolutePath),
250819
- type
250820
- }), { concurrency: HASH_CONCURRENCY }),
250821
- compatibilityDate: config.compatibilityDate,
250822
- compatibilityFlags: config.compatibilityFlags,
250823
- servingConfig: config.assetsConfig
250824
- };
250825
- }
250826
- async function readRawResources(dir) {
250827
- if (!await pathExists(dir)) {
250828
- return {};
250829
- }
250830
- const files = await globby(`**/*.${CONFIG_FILE_EXTENSION_GLOB}`, {
250831
- cwd: dir,
250832
- onlyFiles: true,
250833
- followSymbolicLinks: false
250834
- });
250835
- const payloads = {};
250836
- for (const relativePath of files.sort()) {
250837
- const name = relativePath.replace(/\.jsonc?$/, "");
250838
- payloads[name] = await readJsonFile(join29(dir, ...relativePath.split("/")));
250839
- }
250840
- return payloads;
250841
- }
250842
- async function collectResources(configDir, dirs) {
250843
- const [entities, agents] = await Promise.all([
250844
- readRawResources(join29(configDir, dirs.entitiesDir)),
250845
- readRawResources(join29(configDir, dirs.agentsDir))
250846
- ]);
250847
- return { entities, agents };
250848
- }
250849
- async function collectArtifacts(target) {
250850
- const built = await resolveFullStackBuild(target.root);
250851
- const siteWorker = built ? await describeSiteWorker(built) : null;
250852
- return {
250853
- assets: built ? built.assetsDir ? await collectBuildOutput(built.assetsDir) : [] : await collectBuildOutput(requireOutputDir(target), {
250854
- entryFile: ENTRY2
250855
- }),
250856
- ...siteWorker ? { siteWorker } : {},
250857
- ...await collectResources(target.configDir, target)
250858
- };
250859
- }
250860
- // src/core/version/gate.ts
250861
- var VERSIONS_API_ENV = "BASE44_VERSIONS_API";
250862
- function versionsApiEnabled(env = process.env) {
250863
- const value = env[VERSIONS_API_ENV];
250864
- return value === "1" || value === "true";
250865
- }
250866
- // src/core/version/publish.ts
250867
- import { randomUUID as randomUUID4 } from "node:crypto";
250868
- var DEFAULT_ENVIRONMENT = "production";
250869
- async function tagStep2(step, run) {
250870
- return await tagStep(step, run);
250871
- }
250872
- async function publishVersion(artifacts, options = {}) {
250873
- const version = await tagStep2("create_version", () => createVersion(artifacts, {
250874
- sourceCommit: options.sourceCommit,
250875
- concurrency: options.concurrency,
250876
- progress: options.progress
250877
- }));
250878
- const environment = await tagStep2("deploy", () => setEnvironmentVersion(options.target ?? DEFAULT_ENVIRONMENT, version.versionId, {
250879
- idempotencyKey: randomUUID4()
250880
- }));
250881
- return {
250882
- environment: environment.name,
250883
- versionId: environment.versionId,
250884
- manifestHash: environment.manifestHash,
250885
- deploymentId: environment.deploymentId
250886
- };
250887
- }
250888
- // src/cli/commands/versions/options.ts
250889
- function outputDirOption() {
250890
- return new Option2("--output-dir <dir>", "Build output directory (defaults to the project's, else dist)");
250891
- }
250892
- function targetOption() {
250893
- return new Option2("--target <name>", "Environment to serve the version at");
250894
- }
250895
- function gitHashOption() {
250896
- return new Option2("--git-hash <hash>", "Commit the build came from (defaults to the checkout's HEAD)").argParser((value) => {
250897
- if (!isGitCommitHash(value)) {
250898
- throw new InvalidArgumentError2("Expected a git commit hash (7-64 hex chars).");
250899
- }
250900
- return value;
250901
- });
250902
- }
250903
- function concurrencyOption() {
250904
- return new Option2("--concurrency <n>", "Parallel file uploads").default(DEFAULT_VERSION_UPLOAD_CONCURRENCY).argParser((value) => {
250905
- const parsed = Number(value);
250906
- if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_VERSION_UPLOAD_CONCURRENCY) {
250907
- throw new InvalidArgumentError2(`Expected a whole number between 1 and ${MAX_VERSION_UPLOAD_CONCURRENCY}.`);
250908
- }
250909
- return parsed;
250910
- });
250911
- }
250912
-
250913
- // src/cli/commands/publish.ts
250914
- async function publishAction(ctx, options) {
250915
- const { runTask, log, jsonMode } = ctx;
250916
- const app = requireApp(ctx);
250917
- const target = await tagStep2("create_version", () => resolveBuildTarget(app.projectRoot, { outputDir: options.outputDir }));
250918
- if (options.build !== false) {
250919
- await tagStep2("build", () => runSiteBuild(ctx, {
250920
- root: target.root,
250921
- buildCommand: target.buildCommand,
250922
- appId: app.id
250923
- }));
250924
- }
250925
- const gitHash = await resolveProvenanceCommit(target.root, options.gitHash);
250926
- const result = await runTask("Publishing...", async (updateMessage) => {
250927
- const artifacts = await tagStep2("create_version", () => collectArtifacts(target));
250928
- return await publishVersion(artifacts, {
250929
- sourceCommit: gitHash,
250930
- target: options.target,
250931
- concurrency: options.concurrency,
250932
- progress: {
250933
- onDeclared: ({ fileCount }) => updateMessage(`Uploading ${fileCount} files`),
250934
- onUpload: ({ uploadedFiles, totalFiles }) => updateMessage(`Uploaded ${uploadedFiles} of ${totalFiles} files`)
250935
- }
250936
- });
250937
- }, { successMessage: "Published", errorMessage: "Publish failed" });
250938
- if (!jsonMode) {
250939
- log.message(theme.styles.dim(`version ${result.versionId}`));
250940
- }
250941
- return {
250942
- outroMessage: `${result.environment} now serves ${result.versionId}`,
250943
- stdout: jsonMode ? `${JSON.stringify(result, null, 2)}
250944
- ` : undefined
250945
- };
250946
- }
250947
- function getPublishCommand() {
250948
- return new Base44Command("publish").description("Build the app, record it as a version, and serve that version").option("--no-build", "Publish the existing build output without rebuilding").addOption(outputDirOption()).addOption(targetOption()).addOption(gitHashOption()).addOption(concurrencyOption()).action(publishAction);
250949
- }
250950
-
250951
250602
  // src/core/resources/sandbox/schema.ts
250952
250603
  var FileErrorSchema = object({
250953
250604
  code: string2(),
@@ -251333,7 +250984,7 @@ function getSecretsListCommand() {
251333
250984
  }
251334
250985
 
251335
250986
  // src/cli/commands/secrets/set.ts
251336
- import { resolve as resolve14 } from "node:path";
250987
+ import { resolve as resolve12 } from "node:path";
251337
250988
  function parseEntries(entries) {
251338
250989
  const secrets = {};
251339
250990
  for (const entry of entries) {
@@ -251364,7 +251015,7 @@ async function setSecretsAction({ log, runTask }, entries, options) {
251364
251015
  validateInput(entries, options);
251365
251016
  let secrets;
251366
251017
  if (options.envFile) {
251367
- secrets = await parseEnvFile(resolve14(options.envFile));
251018
+ secrets = await parseEnvFile(resolve12(options.envFile));
251368
251019
  if (Object.keys(secrets).length === 0) {
251369
251020
  throw new InvalidInputError("The env file contains no valid KEY=VALUE entries.");
251370
251021
  }
@@ -251393,7 +251044,7 @@ function getSecretsCommand() {
251393
251044
  }
251394
251045
 
251395
251046
  // src/cli/commands/site/deploy.ts
251396
- import { resolve as resolve15 } from "node:path";
251047
+ import { resolve as resolve13 } from "node:path";
251397
251048
  async function deployAction2(ctx, options) {
251398
251049
  const { isNonInteractive } = ctx;
251399
251050
  if (isNonInteractive && !options.yes) {
@@ -251471,7 +251122,7 @@ async function deployTarball({ runTask }, project) {
251471
251122
  }
251472
251123
  function siteOutputDir(project) {
251473
251124
  const outputDirectory = project.site?.outputDirectory;
251474
- return outputDirectory ? resolve15(project.root, outputDirectory) : null;
251125
+ return outputDirectory ? resolve13(project.root, outputDirectory) : null;
251475
251126
  }
251476
251127
  function getSiteDeployCommand() {
251477
251128
  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)");
@@ -251495,6 +251146,209 @@ function parseConcurrency(value) {
251495
251146
  return parsed;
251496
251147
  }
251497
251148
 
251149
+ // src/cli/dev/createDevLogger.ts
251150
+ var colorByType = {
251151
+ error: theme.styles.error,
251152
+ warn: theme.styles.warn,
251153
+ log: (input) => input
251154
+ };
251155
+ var stringify = (item) => {
251156
+ if (typeof item === "string") {
251157
+ return item;
251158
+ }
251159
+ if (item instanceof Error) {
251160
+ return item.toString();
251161
+ }
251162
+ try {
251163
+ return JSON.stringify(item, null, 2) ?? String(item);
251164
+ } catch {
251165
+ return String(item);
251166
+ }
251167
+ };
251168
+ function createDevLogger(label, labelColor = theme.styles.dim) {
251169
+ const prefix = label ? `${labelColor(`[${label}]`)} ` : "";
251170
+ const print = (type, ...args) => {
251171
+ const colorize = colorByType[type];
251172
+ console[type](prefix + args.map((item) => colorize(stringify(item))).join(" "));
251173
+ };
251174
+ return {
251175
+ log: (...args) => print("log", ...args),
251176
+ error: (msg, err) => {
251177
+ print("error", msg);
251178
+ if (err) {
251179
+ print("error", err);
251180
+ }
251181
+ },
251182
+ warn: (...args) => print("warn", ...args)
251183
+ };
251184
+ }
251185
+
251186
+ // src/cli/dev/dev-server/serve-runner.ts
251187
+ import { spawn as spawn2 } from "node:child_process";
251188
+ import process21 from "node:process";
251189
+
251190
+ class ServeRunner {
251191
+ command;
251192
+ cwd;
251193
+ env;
251194
+ logger;
251195
+ child;
251196
+ stopping = false;
251197
+ stopPromise;
251198
+ exitListeners = [];
251199
+ constructor(options) {
251200
+ this.command = options.command;
251201
+ this.cwd = options.cwd;
251202
+ this.env = options.env;
251203
+ this.logger = options.logger;
251204
+ }
251205
+ start() {
251206
+ if (this.child) {
251207
+ return;
251208
+ }
251209
+ const stdin = process21.platform === "win32" ? "ignore" : "inherit";
251210
+ const child = spawn2(this.command, {
251211
+ cwd: this.cwd,
251212
+ shell: true,
251213
+ detached: process21.platform !== "win32",
251214
+ env: { ...process21.env, ...this.env },
251215
+ stdio: [stdin, "pipe", "pipe"],
251216
+ windowsHide: true
251217
+ });
251218
+ this.child = child;
251219
+ this.setupHandlers(child);
251220
+ }
251221
+ onExit(listener) {
251222
+ this.exitListeners.push(listener);
251223
+ }
251224
+ async stop() {
251225
+ if (this.stopPromise) {
251226
+ return this.stopPromise;
251227
+ }
251228
+ this.stopPromise = this.stopChild();
251229
+ return this.stopPromise;
251230
+ }
251231
+ async stopChild() {
251232
+ const child = this.child;
251233
+ if (!child || child.exitCode !== null) {
251234
+ return;
251235
+ }
251236
+ this.stopping = true;
251237
+ const exited = new Promise((resolve) => child.once("exit", () => resolve()));
251238
+ if (process21.platform === "win32" && child.pid) {
251239
+ const taskkill = spawn2("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
251240
+ stdio: "ignore",
251241
+ windowsHide: true
251242
+ });
251243
+ await new Promise((resolve) => {
251244
+ taskkill.once("exit", () => resolve());
251245
+ taskkill.once("error", () => resolve());
251246
+ });
251247
+ } else if (child.pid) {
251248
+ try {
251249
+ process21.kill(-child.pid, "SIGTERM");
251250
+ } catch {
251251
+ child.kill();
251252
+ }
251253
+ }
251254
+ await exited;
251255
+ }
251256
+ setupHandlers(child) {
251257
+ child.stdout?.on("data", (data) => this.emitLines(data, "log"));
251258
+ child.stderr?.on("data", (data) => this.emitLines(data, "error"));
251259
+ child.on("error", (error) => {
251260
+ this.logger.error("Frontend dev server failed to start:", error);
251261
+ this.notifyExit(null);
251262
+ });
251263
+ child.on("exit", (code) => {
251264
+ if (this.stopping) {
251265
+ return;
251266
+ }
251267
+ this.logger.error(`Frontend dev server exited with code ${code}`);
251268
+ this.notifyExit(code);
251269
+ });
251270
+ }
251271
+ notifyExit(code) {
251272
+ for (const listener of this.exitListeners) {
251273
+ listener(code);
251274
+ }
251275
+ }
251276
+ emitLines(data, type) {
251277
+ const lines = data.toString().trimEnd().split(`
251278
+ `);
251279
+ for (const line of lines) {
251280
+ if (type === "error") {
251281
+ this.logger.error(line);
251282
+ } else {
251283
+ this.logger.log(line);
251284
+ }
251285
+ }
251286
+ }
251287
+ }
251288
+
251289
+ // src/cli/dev/serve-command-runner.ts
251290
+ function createServeCommandRunner({
251291
+ serveCommand,
251292
+ projectRoot,
251293
+ appId,
251294
+ appBaseUrl
251295
+ }) {
251296
+ return new ServeRunner({
251297
+ command: serveCommand,
251298
+ cwd: projectRoot,
251299
+ env: {
251300
+ VITE_BASE44_APP_ID: appId,
251301
+ ...appBaseUrl ? { VITE_BASE44_APP_BASE_URL: appBaseUrl } : {}
251302
+ },
251303
+ logger: createDevLogger("frontend", theme.colors.base44Orange)
251304
+ });
251305
+ }
251306
+
251307
+ // src/cli/dev/stop-runner-on-signals.ts
251308
+ import process22 from "node:process";
251309
+ function stopRunnerOnProcessSignals(runner) {
251310
+ const stop = () => void runner.stop();
251311
+ process22.on("SIGINT", stop);
251312
+ process22.on("SIGTERM", stop);
251313
+ }
251314
+
251315
+ // src/cli/commands/site/dev.ts
251316
+ async function siteDevAction(ctx, options) {
251317
+ const { app } = ctx;
251318
+ if (!app?.projectRoot) {
251319
+ throw new ConfigInvalidError("base44 site dev requires a linked local project. Run it from a project with base44/.app.jsonc.");
251320
+ }
251321
+ const { project } = await readProjectConfig(app.projectRoot);
251322
+ const site = project.site;
251323
+ if (!site) {
251324
+ throw new InvalidInputError(`This project has no 'site' block in base44/config.jsonc, so there is no frontend to serve. Add one naming its serveCommand; site dev falls back to "npm run dev".`);
251325
+ }
251326
+ const serveCommand = site.serveCommand ?? DEFAULT_SERVE_COMMAND;
251327
+ const { command, droppedAddress } = withServeAddress(serveCommand, {
251328
+ host: site.devHost,
251329
+ port: site.devPort,
251330
+ hostFlag: site.devHostFlag
251331
+ });
251332
+ if (droppedAddress) {
251333
+ throw new InvalidInputError(`serveCommand '${serveCommand}' takes no forwarded arguments, so the bind address cannot be passed to it. Bind it inside serveCommand itself, or use an 'npm run', 'pnpm', 'yarn' or 'bun run' script.`);
251334
+ }
251335
+ const runner = createServeCommandRunner({
251336
+ serveCommand: command,
251337
+ projectRoot: project.root,
251338
+ appId: app.id,
251339
+ appBaseUrl: options.backendUrl
251340
+ });
251341
+ stopRunnerOnProcessSignals(runner);
251342
+ runner.onExit((code) => process.exit(code ?? 1));
251343
+ runner.start();
251344
+ return {
251345
+ outroMessage: options.backendUrl ? `Frontend dev server running '${command}' against ${theme.styles.bold(options.backendUrl)}` : `Frontend dev server running '${command}'`
251346
+ };
251347
+ }
251348
+ function getSiteDevCommand() {
251349
+ return new Base44Command("dev", { requireAuth: false }).description("Run the site's dev server against a given backend (no local backend)").option("--backend-url <url>", "Backend the frontend should call, injected as VITE_BASE44_APP_BASE_URL. Omit for a frontend that reaches its backend same-origin.").action(siteDevAction);
251350
+ }
251351
+
251498
251352
  // src/cli/commands/site/open.ts
251499
251353
  async function openAction({
251500
251354
  isNonInteractive
@@ -251511,7 +251365,7 @@ function getSiteOpenCommand() {
251511
251365
 
251512
251366
  // src/cli/commands/site/index.ts
251513
251367
  function getSiteCommand() {
251514
- return new Command2("site").description("Manage app site (frontend app)").addCommand(getSiteDeployCommand()).addCommand(getSiteOpenCommand());
251368
+ return new Command2("site").description("Manage app site (frontend app)").addCommand(getSiteDeployCommand()).addCommand(getSiteDevCommand()).addCommand(getSiteOpenCommand());
251515
251369
  }
251516
251370
 
251517
251371
  // src/core/types/generator.ts
@@ -251603,10 +251457,10 @@ function toPascalCase(name) {
251603
251457
  return name.split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
251604
251458
  }
251605
251459
  // src/core/types/update-project.ts
251606
- import { join as join33 } from "node:path";
251460
+ import { join as join30 } from "node:path";
251607
251461
  var TYPES_INCLUDE_PATH = `${PROJECT_SUBDIR}/${TYPES_OUTPUT_SUBDIR}/*.d.ts`;
251608
251462
  async function updateProjectConfig(projectRoot) {
251609
- const tsconfigPath = join33(projectRoot, "tsconfig.json");
251463
+ const tsconfigPath = join30(projectRoot, "tsconfig.json");
251610
251464
  if (!await pathExists(tsconfigPath)) {
251611
251465
  return false;
251612
251466
  }
@@ -251655,59 +251509,6 @@ function getTypesCommand() {
251655
251509
  return new Command2("types").description("Manage TypeScript type generation").addCommand(getTypesGenerateCommand());
251656
251510
  }
251657
251511
 
251658
- // src/cli/commands/versions/create.ts
251659
- async function createAction2(ctx, options) {
251660
- const { runTask, jsonMode } = ctx;
251661
- const target = await resolveBuildTarget(requireApp(ctx).projectRoot, {
251662
- outputDir: options.outputDir
251663
- });
251664
- const gitHash = await resolveProvenanceCommit(target.root, options.gitHash);
251665
- const version = await runTask("Creating version...", async (updateMessage) => await createVersion(await collectArtifacts(target), {
251666
- sourceCommit: gitHash,
251667
- concurrency: options.concurrency,
251668
- progress: {
251669
- onDeclared: ({ fileCount }) => updateMessage(`Uploading ${fileCount} files`),
251670
- onUpload: ({ uploadedFiles, totalFiles }) => updateMessage(`Uploaded ${uploadedFiles} of ${totalFiles} files`)
251671
- }
251672
- }), {
251673
- successMessage: "Version created",
251674
- errorMessage: "Create version failed"
251675
- });
251676
- return {
251677
- outroMessage: `Version ${version.versionId} (${version.manifestHash})`,
251678
- stdout: jsonMode ? `${JSON.stringify(version, null, 2)}
251679
- ` : undefined
251680
- };
251681
- }
251682
- function getVersionCreateCommand() {
251683
- return new Base44Command("create").description("Record the built output as a version, without deploying it").addOption(outputDirOption()).addOption(gitHashOption()).addOption(concurrencyOption()).action(createAction2);
251684
- }
251685
-
251686
- // src/cli/commands/versions/deploy.ts
251687
- import { randomUUID as randomUUID5 } from "node:crypto";
251688
- async function deployAction3({ runTask, jsonMode }, versionId, options) {
251689
- const environment = options.target ?? DEFAULT_ENVIRONMENT;
251690
- const result = await runTask(`Pointing ${environment} at ${versionId}...`, async () => await setEnvironmentVersion(environment, versionId, {
251691
- idempotencyKey: randomUUID5()
251692
- }), {
251693
- successMessage: "Environment updated",
251694
- errorMessage: "Could not update the environment"
251695
- });
251696
- return {
251697
- outroMessage: `${result.name} now serves ${result.versionId}`,
251698
- stdout: jsonMode ? `${JSON.stringify(result, null, 2)}
251699
- ` : undefined
251700
- };
251701
- }
251702
- function getVersionDeployCommand() {
251703
- return new Base44Command("deploy").description("Point an environment at an already-recorded version (also the rollback)").argument("<version-id>", "The version to serve").addOption(targetOption()).action(deployAction3);
251704
- }
251705
-
251706
- // src/cli/commands/versions/index.ts
251707
- function getVersionsCommand() {
251708
- return new Command2("versions").description("Record app versions and serve them").addCommand(getVersionCreateCommand()).addCommand(getVersionDeployCommand());
251709
- }
251710
-
251711
251512
  // src/core/resources/workflow/schema.ts
251712
251513
  var WorkflowRunStatusSchema = _enum([
251713
251514
  "running",
@@ -252084,47 +251885,10 @@ function getWorkspaceCommand() {
252084
251885
  return new Command2("workspace").description("List workspaces, inspect one, and move apps between them").addCommand(getWorkspaceListCommand()).addCommand(getWorkspaceGetCommand()).addCommand(getWorkspaceMoveCommand());
252085
251886
  }
252086
251887
 
252087
- // src/cli/dev/createDevLogger.ts
252088
- var colorByType = {
252089
- error: theme.styles.error,
252090
- warn: theme.styles.warn,
252091
- log: (input) => input
252092
- };
252093
- var stringify = (item) => {
252094
- if (typeof item === "string") {
252095
- return item;
252096
- }
252097
- if (item instanceof Error) {
252098
- return item.toString();
252099
- }
252100
- try {
252101
- return JSON.stringify(item, null, 2) ?? String(item);
252102
- } catch {
252103
- return String(item);
252104
- }
252105
- };
252106
- function createDevLogger(label, labelColor = theme.styles.dim) {
252107
- const prefix = label ? `${labelColor(`[${label}]`)} ` : "";
252108
- const print = (type, ...args) => {
252109
- const colorize = colorByType[type];
252110
- console[type](prefix + args.map((item) => colorize(stringify(item))).join(" "));
252111
- };
252112
- return {
252113
- log: (...args) => print("log", ...args),
252114
- error: (msg, err) => {
252115
- print("error", msg);
252116
- if (err) {
252117
- print("error", err);
252118
- }
252119
- },
252120
- warn: (...args) => print("warn", ...args)
252121
- };
252122
- }
252123
-
252124
251888
  // src/cli/dev/dev-server/main.ts
252125
251889
  var import_cors = __toESM(require_lib4(), 1);
252126
251890
  var import_express6 = __toESM(require_express(), 1);
252127
- import { dirname as dirname27, join as join38 } from "node:path";
251891
+ import { dirname as dirname26, join as join36 } from "node:path";
252128
251892
 
252129
251893
  // ../../node_modules/get-port/index.js
252130
251894
  import net from "node:net";
@@ -252253,8 +252017,8 @@ var $dir = async (options) => dirWithOptions(options);
252253
252017
  var $tmpName = promisify11(tmp.tmpName);
252254
252018
 
252255
252019
  // src/cli/dev/dev-server/function-manager.ts
252256
- import { spawn as spawn2 } from "node:child_process";
252257
- import { dirname as dirname24, join as join34 } from "node:path";
252020
+ import { spawn as spawn3 } from "node:child_process";
252021
+ import { dirname as dirname23, join as join31 } from "node:path";
252258
252022
  import { pathToFileURL } from "node:url";
252259
252023
 
252260
252024
  // src/cli/dev/dev-server/base-function-manager.ts
@@ -252351,7 +252115,7 @@ class FunctionManager extends BaseFunctionManager {
252351
252115
  async stopFunction(_name, { process: proc }) {
252352
252116
  const exited = new Promise((r) => proc.once("exit", () => r()));
252353
252117
  if (process.platform === "win32" && proc.pid) {
252354
- spawn2("taskkill", ["/pid", String(proc.pid), "/T", "/F"]);
252118
+ spawn3("taskkill", ["/pid", String(proc.pid), "/T", "/F"]);
252355
252119
  } else {
252356
252120
  proc.kill();
252357
252121
  }
@@ -252359,8 +252123,8 @@ class FunctionManager extends BaseFunctionManager {
252359
252123
  }
252360
252124
  spawnFunction(func, port) {
252361
252125
  this.logger.log(`Spawning function "${func.name}" on port ${port}`);
252362
- const importMapPath = join34(dirname24(this.wrapperPath), "import-map.json");
252363
- const process2 = spawn2("deno", ["run", "--allow-all", "--import-map", importMapPath, this.wrapperPath], {
252126
+ const importMapPath = join31(dirname23(this.wrapperPath), "import-map.json");
252127
+ const process2 = spawn3("deno", ["run", "--allow-all", "--import-map", importMapPath, this.wrapperPath], {
252364
252128
  env: {
252365
252129
  ...globalThis.process.env,
252366
252130
  FUNCTION_PATH: pathToFileURL(func.entryPath).href,
@@ -252433,7 +252197,7 @@ class FunctionManager extends BaseFunctionManager {
252433
252197
  import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "node:fs";
252434
252198
  import { isBuiltin } from "node:module";
252435
252199
  import { homedir as homedir3 } from "node:os";
252436
- import { join as join35 } from "node:path";
252200
+ import { join as join33 } from "node:path";
252437
252201
  import { pathToFileURL as pathToFileURL6 } from "node:url";
252438
252202
  var depsPromise;
252439
252203
  function loadDeps() {
@@ -252554,9 +252318,9 @@ export default {
252554
252318
  };
252555
252319
  `;
252556
252320
  function ensureBundlerConfig() {
252557
- const dir = join35(homedir3(), ".base44", "function-bundler");
252321
+ const dir = join33(homedir3(), ".base44", "function-bundler");
252558
252322
  mkdirSync2(dir, { recursive: true });
252559
- const configPath = join35(dir, "deno.json");
252323
+ const configPath = join33(dir, "deno.json");
252560
252324
  writeFileSync2(configPath, `${JSON.stringify({ nodeModulesDir: "auto" }, null, 2)}
252561
252325
  `);
252562
252326
  return configPath;
@@ -253937,11 +253701,11 @@ async function createEntityRoutes(db, logger, broadcast) {
253937
253701
  // src/cli/dev/dev-server/routes/integrations.ts
253938
253702
  var import_express5 = __toESM(require_express(), 1);
253939
253703
  var import_multer = __toESM(require_multer(), 1);
253940
- import { createHash as createHash3, randomUUID as randomUUID6 } from "node:crypto";
253704
+ import { createHash as createHash2, randomUUID as randomUUID4 } from "node:crypto";
253941
253705
  import fs28 from "node:fs";
253942
253706
  import path18 from "node:path";
253943
253707
  function createFileToken(fileUri) {
253944
- return createHash3("sha256").update(fileUri).digest("hex");
253708
+ return createHash2("sha256").update(fileUri).digest("hex");
253945
253709
  }
253946
253710
  function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger) {
253947
253711
  const router = import_express5.Router({ mergeParams: true });
@@ -253954,14 +253718,14 @@ function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger) {
253954
253718
  destination: mediaFilesDir,
253955
253719
  filename: (_req, file, cb) => {
253956
253720
  const ext = path18.extname(file.originalname);
253957
- cb(null, `${randomUUID6()}${ext}`);
253721
+ cb(null, `${randomUUID4()}${ext}`);
253958
253722
  }
253959
253723
  });
253960
253724
  const privateStorage = import_multer.default.diskStorage({
253961
253725
  destination: privateFilesDir,
253962
253726
  filename: (_req, file, cb) => {
253963
253727
  const ext = path18.extname(file.originalname);
253964
- cb(null, `${randomUUID6()}${ext}`);
253728
+ cb(null, `${randomUUID4()}${ext}`);
253965
253729
  }
253966
253730
  });
253967
253731
  const upload = import_multer.default({ storage, limits: { fileSize: MAX_FILE_SIZE } });
@@ -255823,8 +255587,8 @@ async function createDevServer(options) {
255823
255587
  broadcastEntityEvent(io, appId, entityName, event);
255824
255588
  };
255825
255589
  const base44ConfigWatcher = new WatchBase44({
255826
- functions: join38(dirname27(project.configPath), project.functionsDir),
255827
- entities: join38(dirname27(project.configPath), project.entitiesDir)
255590
+ functions: join36(dirname26(project.configPath), project.functionsDir),
255591
+ entities: join36(dirname26(project.configPath), project.entitiesDir)
255828
255592
  }, devLogger);
255829
255593
  base44ConfigWatcher.on("change", async (name) => {
255830
255594
  try {
@@ -255890,127 +255654,6 @@ async function createDevServer(options) {
255890
255654
  return { port, server, shutdown };
255891
255655
  }
255892
255656
 
255893
- // src/cli/dev/dev-server/serve-runner.ts
255894
- import { spawn as spawn3 } from "node:child_process";
255895
- import process23 from "node:process";
255896
-
255897
- class ServeRunner {
255898
- command;
255899
- cwd;
255900
- env;
255901
- logger;
255902
- child;
255903
- stopping = false;
255904
- stopPromise;
255905
- exitListeners = [];
255906
- constructor(options) {
255907
- this.command = options.command;
255908
- this.cwd = options.cwd;
255909
- this.env = options.env;
255910
- this.logger = options.logger;
255911
- }
255912
- start() {
255913
- if (this.child) {
255914
- return;
255915
- }
255916
- const stdin = process23.platform === "win32" ? "ignore" : "inherit";
255917
- const child = spawn3(this.command, {
255918
- cwd: this.cwd,
255919
- shell: true,
255920
- detached: process23.platform !== "win32",
255921
- env: { ...process23.env, ...this.env },
255922
- stdio: [stdin, "pipe", "pipe"],
255923
- windowsHide: true
255924
- });
255925
- this.child = child;
255926
- this.setupHandlers(child);
255927
- }
255928
- onExit(listener) {
255929
- this.exitListeners.push(listener);
255930
- }
255931
- async stop() {
255932
- if (this.stopPromise) {
255933
- return this.stopPromise;
255934
- }
255935
- this.stopPromise = this.stopChild();
255936
- return this.stopPromise;
255937
- }
255938
- async stopChild() {
255939
- const child = this.child;
255940
- if (!child || child.exitCode !== null) {
255941
- return;
255942
- }
255943
- this.stopping = true;
255944
- const exited = new Promise((resolve) => child.once("exit", () => resolve()));
255945
- if (process23.platform === "win32" && child.pid) {
255946
- const taskkill = spawn3("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
255947
- stdio: "ignore",
255948
- windowsHide: true
255949
- });
255950
- await new Promise((resolve) => {
255951
- taskkill.once("exit", () => resolve());
255952
- taskkill.once("error", () => resolve());
255953
- });
255954
- } else if (child.pid) {
255955
- try {
255956
- process23.kill(-child.pid, "SIGTERM");
255957
- } catch {
255958
- child.kill();
255959
- }
255960
- }
255961
- await exited;
255962
- }
255963
- setupHandlers(child) {
255964
- child.stdout?.on("data", (data) => this.emitLines(data, "log"));
255965
- child.stderr?.on("data", (data) => this.emitLines(data, "error"));
255966
- child.on("error", (error) => {
255967
- this.logger.error("Frontend dev server failed to start:", error);
255968
- this.notifyExit(null);
255969
- });
255970
- child.on("exit", (code) => {
255971
- if (this.stopping) {
255972
- return;
255973
- }
255974
- this.logger.error(`Frontend dev server exited with code ${code}`);
255975
- this.notifyExit(code);
255976
- });
255977
- }
255978
- notifyExit(code) {
255979
- for (const listener of this.exitListeners) {
255980
- listener(code);
255981
- }
255982
- }
255983
- emitLines(data, type) {
255984
- const lines = data.toString().trimEnd().split(`
255985
- `);
255986
- for (const line of lines) {
255987
- if (type === "error") {
255988
- this.logger.error(line);
255989
- } else {
255990
- this.logger.log(line);
255991
- }
255992
- }
255993
- }
255994
- }
255995
-
255996
- // src/cli/dev/serve-command-runner.ts
255997
- function createServeCommandRunner({
255998
- serveCommand,
255999
- projectRoot,
256000
- appId,
256001
- appBaseUrl
256002
- }) {
256003
- return new ServeRunner({
256004
- command: serveCommand,
256005
- cwd: projectRoot,
256006
- env: {
256007
- VITE_BASE44_APP_ID: appId,
256008
- VITE_BASE44_APP_BASE_URL: appBaseUrl
256009
- },
256010
- logger: createDevLogger("frontend", theme.colors.base44Orange)
256011
- });
256012
- }
256013
-
256014
255657
  // src/cli/commands/dev.ts
256015
255658
  function localServerUrl(port) {
256016
255659
  return `http://localhost:${port}`;
@@ -256036,11 +255679,6 @@ async function resolveConfiguredSite(app) {
256036
255679
  const serveCommand = project.site?.serveCommand;
256037
255680
  return serveCommand ? { serveCommand, projectRoot: project.root } : undefined;
256038
255681
  }
256039
- function stopRunnerOnProcessSignals(runner) {
256040
- const stop = () => void runner.stop();
256041
- process.on("SIGINT", stop);
256042
- process.on("SIGTERM", stop);
256043
- }
256044
255682
  function startServeCommand(runner, backend) {
256045
255683
  stopRunnerOnProcessSignals(runner);
256046
255684
  runner.onExit(() => {
@@ -256221,7 +255859,7 @@ Examples:
256221
255859
  }
256222
255860
 
256223
255861
  // src/cli/commands/project/eject.ts
256224
- import { resolve as resolve19 } from "node:path";
255862
+ import { resolve as resolve17 } from "node:path";
256225
255863
  var import_kebabCase2 = __toESM(require_kebabCase(), 1);
256226
255864
  async function eject(ctx, options, command) {
256227
255865
  const { log, runTask, isNonInteractive } = ctx;
@@ -256285,7 +255923,7 @@ async function eject(ctx, options, command) {
256285
255923
  Ne("Operation cancelled.");
256286
255924
  throw new CLIExitError(0);
256287
255925
  }
256288
- const resolvedPath = resolve19(selectedPath);
255926
+ const resolvedPath = resolve17(selectedPath);
256289
255927
  await runTask("Downloading your project's code...", async (updateMessage) => {
256290
255928
  await createProjectFilesForExistingProject({
256291
255929
  projectId,
@@ -256356,6 +255994,7 @@ function createProgram(context) {
256356
255994
  program.addCommand(getCreateCommand());
256357
255995
  program.addCommand(getScaffoldCommand());
256358
255996
  program.addCommand(getDashboardCommand());
255997
+ program.addCommand(getInstallCommand());
256359
255998
  program.addCommand(getBuildCommand());
256360
255999
  program.addCommand(getDeployCommand3());
256361
256000
  program.addCommand(getVisibilityCommand());
@@ -256374,10 +256013,6 @@ function createProgram(context) {
256374
256013
  program.addCommand(getBranchesCommand());
256375
256014
  program.addCommand(getAuthCommand());
256376
256015
  program.addCommand(getSiteCommand());
256377
- if (versionsApiEnabled()) {
256378
- program.addCommand(getPublishCommand());
256379
- program.addCommand(getVersionsCommand());
256380
- }
256381
256016
  program.addCommand(getTypesCommand());
256382
256017
  program.addCommand(getExecCommand());
256383
256018
  program.addCommand(getDevCommand());
@@ -256390,7 +256025,7 @@ var import_detect_agent = __toESM(require_dist5(), 1);
256390
256025
  import { release, type } from "node:os";
256391
256026
 
256392
256027
  // ../../node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
256393
- import { dirname as dirname28, posix, sep as sep2 } from "path";
256028
+ import { dirname as dirname27, posix, sep as sep2 } from "path";
256394
256029
  function createModulerModifier() {
256395
256030
  const getModuleFromFileName = createGetModuleFromFilename();
256396
256031
  return async (frames) => {
@@ -256399,7 +256034,7 @@ function createModulerModifier() {
256399
256034
  return frames;
256400
256035
  };
256401
256036
  }
256402
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname28(process.argv[1]) : process.cwd(), isWindows = sep2 === "\\") {
256037
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname27(process.argv[1]) : process.cwd(), isWindows = sep2 === "\\") {
256403
256038
  const normalizedBase = isWindows ? normalizeWindowsPath2(basePath) : basePath;
256404
256039
  return (filename) => {
256405
256040
  if (!filename)
@@ -260388,9 +260023,9 @@ function addCommandInfoToErrorReporter(program, errorReporter) {
260388
260023
  });
260389
260024
  }
260390
260025
  // src/cli/index.ts
260391
- var __dirname4 = dirname29(fileURLToPath6(import.meta.url));
260026
+ var __dirname4 = dirname28(fileURLToPath6(import.meta.url));
260392
260027
  async function runCLI(options) {
260393
- ensureNpmAssets(join39(__dirname4, "../assets"));
260028
+ ensureNpmAssets(join37(__dirname4, "../assets"));
260394
260029
  const errorReporter = new ErrorReporter;
260395
260030
  errorReporter.registerProcessErrorHandlers();
260396
260031
  const jsonMode = process.argv.includes("--json");
@@ -260429,4 +260064,4 @@ export {
260429
260064
  runCLI
260430
260065
  };
260431
260066
 
260432
- //# debugId=53FA3E8A10325F7E64756E2164756E21
260067
+ //# debugId=8C0EDF181791840B64756E2164756E21