@base44-preview/cli 0.0.55-pr.545.e6bf97b → 0.0.55-pr.547.7e43787

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/README.md CHANGED
@@ -60,6 +60,13 @@ The CLI will guide you through project setup. For step-by-step tutorials, see th
60
60
  | [`secrets list`](https://docs.base44.com/developers/references/cli/commands/secrets-list) | List project secret names |
61
61
  | [`secrets set`](https://docs.base44.com/developers/references/cli/commands/secrets-set) | Set one or more project secrets |
62
62
  | [`secrets delete`](https://docs.base44.com/developers/references/cli/commands/secrets-delete) | Delete a project secret |
63
+ | [`sandbox list-directory`](https://docs.base44.com/developers/references/cli/commands/sandbox-list-directory) | List directory entries in an app's remote sandbox |
64
+ | [`sandbox read-file`](https://docs.base44.com/developers/references/cli/commands/sandbox-read-file) | Read file contents from an app's remote sandbox |
65
+ | [`sandbox write-file`](https://docs.base44.com/developers/references/cli/commands/sandbox-write-file) | Create or overwrite a file in an app's remote sandbox |
66
+ | [`sandbox edit-file`](https://docs.base44.com/developers/references/cli/commands/sandbox-edit-file) | Apply exact old→new string edits to a file in the sandbox |
67
+ | [`sandbox grep`](https://docs.base44.com/developers/references/cli/commands/sandbox-grep) | Search files for a pattern in an app's remote sandbox |
68
+ | [`sandbox run-command`](https://docs.base44.com/developers/references/cli/commands/sandbox-run-command) | Run a shell command in an app's remote sandbox |
69
+ | [`sandbox release`](https://docs.base44.com/developers/references/cli/commands/sandbox-release) | Release the external-agent session so the in-app builder can resume |
63
70
  | [`site deploy`](https://docs.base44.com/developers/references/cli/commands/site-deploy) | Deploy built site files to Base44 hosting |
64
71
  | [`site open`](https://docs.base44.com/developers/references/cli/commands/site-open) | Open the published site in your browser |
65
72
  | [`types generate`](https://docs.base44.com/developers/references/cli/commands/types-generate) | Generate TypeScript types from project resources |
package/dist/cli/index.js CHANGED
@@ -120878,7 +120878,7 @@ function parse42(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
120878
120878
  }
120879
120879
  return res;
120880
120880
  }
120881
- async function readFile2(file2) {
120881
+ async function readFile3(file2) {
120882
120882
  if (isUrlString(file2)) {
120883
120883
  file2 = new URL(file2);
120884
120884
  }
@@ -134672,7 +134672,7 @@ ${codeblock}`, options8);
134672
134672
  "\\": "\\"
134673
134673
  };
134674
134674
  KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
134675
- read_file_default = readFile2;
134675
+ read_file_default = readFile3;
134676
134676
  loadConfigFromPackageJson = process.versions.bun ? async function loadConfigFromBunPackageJson(file2) {
134677
134677
  const { prettier } = await readBunPackageJson(file2);
134678
134678
  return prettier;
@@ -143907,7 +143907,7 @@ var require_parse7 = __commonJS((exports) => {
143907
143907
  extension: url3.getExtension(path18)
143908
143908
  };
143909
143909
  try {
143910
- const resolver = await readFile3(file2, options8, $refs);
143910
+ const resolver = await readFile4(file2, options8, $refs);
143911
143911
  $ref.pathType = resolver.plugin.name;
143912
143912
  file2.data = resolver.result;
143913
143913
  const parser2 = await parseFile(file2, options8, $refs);
@@ -143920,7 +143920,7 @@ var require_parse7 = __commonJS((exports) => {
143920
143920
  throw err;
143921
143921
  }
143922
143922
  }
143923
- async function readFile3(file2, options8, $refs) {
143923
+ async function readFile4(file2, options8, $refs) {
143924
143924
  let resolvers = plugins.all(options8.resolve);
143925
143925
  resolvers = plugins.filter(resolvers, "canRead", file2);
143926
143926
  plugins.sort(resolvers);
@@ -244242,6 +244242,11 @@ function getAppClient() {
244242
244242
  prefixUrl: new URL(`/api/apps/${id}/`, getBase44ApiUrl()).href
244243
244243
  });
244244
244244
  }
244245
+ function getSandboxClient(appId) {
244246
+ return base44Client.extend({
244247
+ prefixUrl: new URL(`/api/apps/${appId}/sandbox-bridge/`, getBase44ApiUrl()).href
244248
+ });
244249
+ }
244245
244250
  // src/core/clients/oauth-client.ts
244246
244251
  import { randomUUID as randomUUID3 } from "node:crypto";
244247
244252
  var oauthClient = distribution_default.create({
@@ -251176,7 +251181,7 @@ function createSimpleRunTask(log) {
251176
251181
  };
251177
251182
  }
251178
251183
  // src/cli/utils/stdin.ts
251179
- async function readStdin(flagName = "--stdin") {
251184
+ async function readStdin(flagName = "--stdin", options = {}) {
251180
251185
  if (process.stdin.isTTY) {
251181
251186
  throw new InvalidInputError(`${flagName} requires piped input (e.g., echo <value> | base44 ...)`);
251182
251187
  }
@@ -251184,7 +251189,8 @@ async function readStdin(flagName = "--stdin") {
251184
251189
  for await (const chunk of process.stdin) {
251185
251190
  chunks.push(chunk);
251186
251191
  }
251187
- return Buffer.concat(chunks).toString("utf-8").trim();
251192
+ const text = Buffer.concat(chunks).toString("utf-8");
251193
+ return options.trim === false ? text : text.trim();
251188
251194
  }
251189
251195
 
251190
251196
  // src/cli/utils/secret-input.ts
@@ -253602,6 +253608,302 @@ Examples:
253602
253608
  $ base44 scaffold my-app --app-id app_123 Scaffolds the current dir, named "my-app"`).action(scaffoldAction);
253603
253609
  }
253604
253610
 
253611
+ // src/core/resources/sandbox/schema.ts
253612
+ var FileErrorSchema = exports_external.object({
253613
+ code: exports_external.string(),
253614
+ message: exports_external.string()
253615
+ });
253616
+ var ReadFileEntrySchema = exports_external.object({
253617
+ path: exports_external.string(),
253618
+ content: exports_external.string().optional(),
253619
+ start_line: exports_external.number().optional(),
253620
+ end_line: exports_external.number().optional(),
253621
+ total_lines: exports_external.number().optional(),
253622
+ truncated: exports_external.boolean().optional(),
253623
+ error: FileErrorSchema.optional()
253624
+ }).transform((data) => ({
253625
+ path: data.path,
253626
+ content: data.content,
253627
+ startLine: data.start_line,
253628
+ endLine: data.end_line,
253629
+ totalLines: data.total_lines,
253630
+ truncated: data.truncated,
253631
+ error: data.error
253632
+ }));
253633
+ var ReadFileResponseSchema = exports_external.object({
253634
+ files: exports_external.array(ReadFileEntrySchema)
253635
+ });
253636
+ var WriteFileResponseSchema = exports_external.object({
253637
+ path: exports_external.string(),
253638
+ bytes_written: exports_external.number(),
253639
+ created: exports_external.boolean(),
253640
+ overwritten: exports_external.boolean()
253641
+ }).transform((data) => ({
253642
+ path: data.path,
253643
+ bytesWritten: data.bytes_written,
253644
+ created: data.created,
253645
+ overwritten: data.overwritten
253646
+ }));
253647
+ var EditFileResponseSchema = exports_external.object({
253648
+ path: exports_external.string(),
253649
+ diff: exports_external.string(),
253650
+ applied: exports_external.boolean()
253651
+ });
253652
+ var GrepMatchSchema = exports_external.object({
253653
+ path: exports_external.string().nullable(),
253654
+ line: exports_external.number().nullable(),
253655
+ text: exports_external.string()
253656
+ });
253657
+ var GrepResponseSchema = exports_external.object({
253658
+ matches: exports_external.array(GrepMatchSchema),
253659
+ truncated: exports_external.boolean(),
253660
+ returned_matches: exports_external.number()
253661
+ }).transform((data) => ({
253662
+ matches: data.matches,
253663
+ truncated: data.truncated,
253664
+ returnedMatches: data.returned_matches
253665
+ }));
253666
+ var DirectoryEntrySchema = exports_external.object({
253667
+ name: exports_external.string(),
253668
+ path: exports_external.string(),
253669
+ type: exports_external.enum(["file", "directory"]),
253670
+ size: exports_external.number().optional()
253671
+ });
253672
+ var ListDirectoryResponseSchema = exports_external.object({
253673
+ entries: exports_external.array(DirectoryEntrySchema),
253674
+ truncated: exports_external.boolean()
253675
+ });
253676
+ var RunCommandResponseSchema = exports_external.object({
253677
+ stdout: exports_external.string(),
253678
+ stderr: exports_external.string(),
253679
+ exit_code: exports_external.number(),
253680
+ truncated: exports_external.boolean(),
253681
+ duration_ms: exports_external.number()
253682
+ }).transform((data) => ({
253683
+ stdout: data.stdout,
253684
+ stderr: data.stderr,
253685
+ exitCode: data.exit_code,
253686
+ truncated: data.truncated,
253687
+ durationMs: data.duration_ms
253688
+ }));
253689
+ var ReleaseResponseSchema = exports_external.object({
253690
+ app_id: exports_external.string(),
253691
+ released: exports_external.boolean()
253692
+ }).transform((data) => ({
253693
+ appId: data.app_id,
253694
+ released: data.released
253695
+ }));
253696
+
253697
+ // src/core/resources/sandbox/api.ts
253698
+ async function callTool(appId, tool, payload, schema10, context, timeout2 = 60000) {
253699
+ const client = getSandboxClient(appId);
253700
+ let response;
253701
+ try {
253702
+ response = await client.post(tool, { json: payload, timeout: timeout2 });
253703
+ } catch (error48) {
253704
+ throw await ApiError.fromHttpError(error48, context);
253705
+ }
253706
+ const result = schema10.safeParse(await response.json());
253707
+ if (!result.success) {
253708
+ throw new SchemaValidationError("Invalid response from server", result.error);
253709
+ }
253710
+ return result.data;
253711
+ }
253712
+ function listDirectory(appId, params) {
253713
+ return callTool(appId, "list_directory", { ...params }, ListDirectoryResponseSchema, "listing directory");
253714
+ }
253715
+ function readFile2(appId, params) {
253716
+ return callTool(appId, "read_file", { ...params }, ReadFileResponseSchema, "reading file");
253717
+ }
253718
+ function writeFile2(appId, params) {
253719
+ return callTool(appId, "write_file", { ...params }, WriteFileResponseSchema, `writing file "${params.path}"`);
253720
+ }
253721
+ function editFile(appId, params) {
253722
+ return callTool(appId, "edit_file", { ...params }, EditFileResponseSchema, `editing file "${params.path}"`);
253723
+ }
253724
+ function grep(appId, params) {
253725
+ return callTool(appId, "grep", { ...params }, GrepResponseSchema, "searching files");
253726
+ }
253727
+ function runCommand(appId, params) {
253728
+ return callTool(appId, "run_command", { ...params }, RunCommandResponseSchema, "running command", false);
253729
+ }
253730
+ function releaseSession(appId) {
253731
+ return callTool(appId, "release", {}, ReleaseResponseSchema, "releasing sandbox session");
253732
+ }
253733
+
253734
+ // src/cli/commands/sandbox/shared.ts
253735
+ async function resolveAppId2(options) {
253736
+ const explicit = options.appId ?? process.env.BASE44_APP_ID;
253737
+ if (explicit) {
253738
+ return explicit;
253739
+ }
253740
+ try {
253741
+ const { id } = await initAppContext();
253742
+ return id;
253743
+ } catch {
253744
+ throw new InvalidInputError("No app ID found. Sandbox commands operate on a remote app.", {
253745
+ hints: [
253746
+ { message: "Pass it explicitly with --app-id <id>" },
253747
+ { message: "Or run from a linked Base44 project directory" }
253748
+ ]
253749
+ });
253750
+ }
253751
+ }
253752
+ async function resolveFlagOrStdin(flagValue, flagName) {
253753
+ if (flagValue !== undefined) {
253754
+ return flagValue;
253755
+ }
253756
+ if (process.stdin.isTTY) {
253757
+ throw new InvalidInputError(`Provide ${flagName} or pipe the value via stdin (e.g. echo <value> | base44 sandbox ...).`);
253758
+ }
253759
+ return readStdin(flagName, { trim: false });
253760
+ }
253761
+ function toJsonStdout(result) {
253762
+ return `${JSON.stringify(result, null, 2)}
253763
+ `;
253764
+ }
253765
+ function parsePositiveInt(value, flagName) {
253766
+ if (value === undefined) {
253767
+ return;
253768
+ }
253769
+ const n2 = Number.parseInt(value, 10);
253770
+ if (!Number.isInteger(n2) || n2 < 1) {
253771
+ throw new InvalidInputError(`${flagName} must be a positive integer.`);
253772
+ }
253773
+ return n2;
253774
+ }
253775
+
253776
+ // src/cli/commands/sandbox/edit-file.ts
253777
+ var EditsInputSchema = exports_external.array(exports_external.object({
253778
+ old_text: exports_external.string().min(1),
253779
+ new_text: exports_external.string(),
253780
+ replace_all: exports_external.boolean().optional()
253781
+ })).min(1);
253782
+ function parseEdits(raw2) {
253783
+ let parsed;
253784
+ try {
253785
+ parsed = JSON.parse(raw2);
253786
+ } catch {
253787
+ throw new InvalidInputError("--edits-json must be valid JSON (an array of { old_text, new_text, replace_all? }).");
253788
+ }
253789
+ const result = EditsInputSchema.safeParse(parsed);
253790
+ if (!result.success) {
253791
+ throw new InvalidInputError("Invalid edits: expected a non-empty array of { old_text (non-empty string), new_text (string), replace_all? (boolean) }.");
253792
+ }
253793
+ return result.data;
253794
+ }
253795
+ async function editFileAction({ runTask: runTask2 }, path17, options) {
253796
+ const appId = await resolveAppId2(options);
253797
+ const raw2 = await resolveFlagOrStdin(options.editsJson, "--edits-json");
253798
+ const edits = parseEdits(raw2);
253799
+ const result = await runTask2(options.dryRun ? "Previewing edit" : "Editing file", () => editFile(appId, { path: path17, edits, dry_run: options.dryRun }));
253800
+ return {
253801
+ outroMessage: options.dryRun ? "Previewed edit" : "Edited file",
253802
+ stdout: toJsonStdout(result)
253803
+ };
253804
+ }
253805
+ function getSandboxEditFileCommand() {
253806
+ return new Base44Command("edit-file", { requireAppContext: false }).description("Apply exact old→new string edits to a file in the sandbox").argument("<path>", "File path relative to the app root").option("--edits-json <json>", "JSON array of edits (if omitted, read from stdin)").option("--dry-run", "Return the unified diff without writing").option("--app-id <id>", "Target app ID (defaults to the current app)").addHelpText("after", `
253807
+ Each edit is { "old_text": "...", "new_text": "...", "replace_all"?: true }.
253808
+
253809
+ Examples:
253810
+ $ echo '[{"old_text":"foo","new_text":"bar"}]' | base44 sandbox edit-file src/x.ts
253811
+ $ base44 sandbox edit-file src/x.ts --dry-run --edits-json '[{"old_text":"a","new_text":"b","replace_all":true}]'`).action(editFileAction);
253812
+ }
253813
+
253814
+ // src/cli/commands/sandbox/grep.ts
253815
+ async function grepAction({ runTask: runTask2 }, pattern, options) {
253816
+ const appId = await resolveAppId2(options);
253817
+ const maxResults = parsePositiveInt(options.maxResults, "--max-results");
253818
+ const result = await runTask2("Searching files", () => grep(appId, {
253819
+ pattern,
253820
+ path: options.path,
253821
+ is_regex: options.regex,
253822
+ case_sensitive: options.caseSensitive,
253823
+ glob: options.glob,
253824
+ max_results: maxResults
253825
+ }));
253826
+ return { outroMessage: "Searched files", stdout: toJsonStdout(result) };
253827
+ }
253828
+ function getSandboxGrepCommand() {
253829
+ return new Base44Command("grep", { requireAppContext: false }).description("Search files for a pattern in an app's remote sandbox").argument("<pattern>", "Search pattern").option("--path <path>", "Subtree to search, relative to the app root").option("--no-regex", "Treat the pattern as a literal string, not a regex").option("--case-sensitive", "Case-sensitive match").option("--glob <glob>", 'File glob filter, e.g. "*.tsx"').option("--max-results <n>", "Maximum number of match lines to return").option("--app-id <id>", "Target app ID (defaults to the current app)").action(grepAction);
253830
+ }
253831
+
253832
+ // src/cli/commands/sandbox/list-directory.ts
253833
+ async function listDirectoryAction({ runTask: runTask2 }, path17, options) {
253834
+ const appId = await resolveAppId2(options);
253835
+ const maxDepth = parsePositiveInt(options.maxDepth, "--max-depth");
253836
+ const result = await runTask2("Listing directory", () => listDirectory(appId, {
253837
+ path: path17,
253838
+ recursive: options.recursive,
253839
+ max_depth: maxDepth,
253840
+ include_hidden: options.includeHidden
253841
+ }));
253842
+ return { outroMessage: "Listed directory", stdout: toJsonStdout(result) };
253843
+ }
253844
+ function getSandboxListDirectoryCommand() {
253845
+ return new Base44Command("list-directory", { requireAppContext: false }).description("List directory entries in an app's remote sandbox").argument("[path]", "Directory relative to the app root (default: app root)").option("--recursive", "List nested entries").option("--max-depth <n>", "Max depth when recursive (1-10, default 3)").option("--include-hidden", "Include dotfiles").option("--app-id <id>", "Target app ID (defaults to the current app)").action(listDirectoryAction);
253846
+ }
253847
+
253848
+ // src/cli/commands/sandbox/read-file.ts
253849
+ async function readFileAction({ runTask: runTask2 }, paths, options) {
253850
+ const appId = await resolveAppId2(options);
253851
+ const offset = parsePositiveInt(options.offset, "--offset");
253852
+ const limit = parsePositiveInt(options.limit, "--limit");
253853
+ const result = await runTask2("Reading file", () => readFile2(appId, { paths, offset, limit }));
253854
+ return { outroMessage: "Read file", stdout: toJsonStdout(result) };
253855
+ }
253856
+ function getSandboxReadFileCommand() {
253857
+ return new Base44Command("read-file", { requireAppContext: false }).description("Read file contents from an app's remote sandbox").argument("<paths...>", "One or more file paths relative to the app root").option("--offset <n>", "1-based start line").option("--limit <n>", "Max lines to return from offset").option("--app-id <id>", "Target app ID (defaults to the current app)").action(readFileAction);
253858
+ }
253859
+
253860
+ // src/cli/commands/sandbox/release.ts
253861
+ async function releaseAction({ runTask: runTask2 }, options) {
253862
+ const appId = await resolveAppId2(options);
253863
+ const result = await runTask2("Releasing sandbox session", () => releaseSession(appId));
253864
+ return {
253865
+ outroMessage: "Released sandbox session",
253866
+ stdout: toJsonStdout(result)
253867
+ };
253868
+ }
253869
+ function getSandboxReleaseCommand() {
253870
+ return new Base44Command("release", { requireAppContext: false }).description("Release the external-agent session so the in-app builder can resume").option("--app-id <id>", "Target app ID (defaults to the current app)").action(releaseAction);
253871
+ }
253872
+
253873
+ // src/cli/commands/sandbox/run-command.ts
253874
+ async function runCommandAction({ runTask: runTask2 }, commandParts, options) {
253875
+ const appId = await resolveAppId2(options);
253876
+ const timeoutMs = parsePositiveInt(options.timeoutMs, "--timeout-ms");
253877
+ const command2 = commandParts.join(" ");
253878
+ const result = await runTask2("Running command", () => runCommand(appId, { command: command2, cwd: options.cwd, timeout_ms: timeoutMs }));
253879
+ return { outroMessage: "Ran command", stdout: toJsonStdout(result) };
253880
+ }
253881
+ function getSandboxRunCommandCommand() {
253882
+ return new Base44Command("run-command", { requireAppContext: false }).description("Run a shell command in an app's remote sandbox").argument("<command...>", "Shell command to execute (quote to keep as one)").option("--cwd <path>", "Working directory relative to the app root").option("--timeout-ms <n>", "Timeout in milliseconds (default 120000, max 600000)").option("--app-id <id>", "Target app ID (defaults to the current app)").addHelpText("after", `
253883
+ Examples:
253884
+ $ base44 sandbox run-command "npm test"
253885
+ $ base44 sandbox run-command ls -la --cwd src`).action(runCommandAction);
253886
+ }
253887
+
253888
+ // src/cli/commands/sandbox/write-file.ts
253889
+ async function writeFileAction({ runTask: runTask2 }, path17, options) {
253890
+ const appId = await resolveAppId2(options);
253891
+ const content = await resolveFlagOrStdin(options.content, "--content");
253892
+ const result = await runTask2("Writing file", () => writeFile2(appId, { path: path17, content, overwrite: options.overwrite }));
253893
+ return { outroMessage: "Wrote file", stdout: toJsonStdout(result) };
253894
+ }
253895
+ function getSandboxWriteFileCommand() {
253896
+ return new Base44Command("write-file", { requireAppContext: false }).description("Create or overwrite a file in an app's remote sandbox").argument("<path>", "File path relative to the app root").option("--content <content>", "File content (if omitted, read from stdin)").option("--overwrite", "Overwrite the file if it already exists").option("--app-id <id>", "Target app ID (defaults to the current app)").addHelpText("after", `
253897
+ Examples:
253898
+ $ echo "hello" | base44 sandbox write-file notes.txt
253899
+ $ base44 sandbox write-file notes.txt --content "hello" --overwrite`).action(writeFileAction);
253900
+ }
253901
+
253902
+ // src/cli/commands/sandbox/index.ts
253903
+ function getSandboxCommand() {
253904
+ return new Command("sandbox").description("Develop an app remotely via its server-side sandbox").addCommand(getSandboxListDirectoryCommand()).addCommand(getSandboxReadFileCommand()).addCommand(getSandboxWriteFileCommand()).addCommand(getSandboxEditFileCommand()).addCommand(getSandboxGrepCommand()).addCommand(getSandboxRunCommandCommand()).addCommand(getSandboxReleaseCommand());
253905
+ }
253906
+
253605
253907
  // src/cli/commands/secrets/delete.ts
253606
253908
  async function deleteSecretAction({ runTask: runTask2 }, key) {
253607
253909
  await runTask2(`Deleting secret "${key}"`, async () => {
@@ -253898,6 +254200,7 @@ function getTypesCommand() {
253898
254200
 
253899
254201
  // src/cli/commands/dev.ts
253900
254202
  import { join as join28 } from "node:path";
254203
+ import process21 from "node:process";
253901
254204
 
253902
254205
  // src/cli/dev/dev-server/main.ts
253903
254206
  var import_cors = __toESM(require_lib4(), 1);
@@ -254054,11 +254357,12 @@ var stringify = (item) => {
254054
254357
  return String(item);
254055
254358
  }
254056
254359
  };
254057
- function createDevLogger(label2, labelColor = theme.styles.dim) {
254058
- const prefix = label2 ? `${labelColor(`[${label2}]`)} ` : "";
254360
+ function createDevLogger() {
254059
254361
  const print = (type, ...args) => {
254060
254362
  const colorize = colorByType[type];
254061
- console[type](prefix + args.map((item) => colorize(stringify(item))).join(" "));
254363
+ console[type](...args.map((item) => {
254364
+ return colorize(stringify(item));
254365
+ }));
254062
254366
  };
254063
254367
  return {
254064
254368
  log: (...args) => print("log", ...args),
@@ -255425,92 +255729,6 @@ function createCustomIntegrationRoutes(remoteProxy, logger2) {
255425
255729
  return router;
255426
255730
  }
255427
255731
 
255428
- // src/cli/dev/dev-server/serve-runner.ts
255429
- import { spawn as spawn3 } from "node:child_process";
255430
- import process21 from "node:process";
255431
-
255432
- class ServeRunner {
255433
- command;
255434
- cwd;
255435
- env;
255436
- logger;
255437
- child;
255438
- stopping = false;
255439
- exitListeners = [];
255440
- constructor(options8) {
255441
- this.command = options8.command;
255442
- this.cwd = options8.cwd;
255443
- this.env = options8.env;
255444
- this.logger = options8.logger;
255445
- }
255446
- start() {
255447
- if (this.child) {
255448
- return;
255449
- }
255450
- const child = spawn3(this.command, {
255451
- cwd: this.cwd,
255452
- shell: true,
255453
- detached: process21.platform !== "win32",
255454
- env: { ...process21.env, ...this.env },
255455
- stdio: ["inherit", "pipe", "pipe"]
255456
- });
255457
- this.child = child;
255458
- this.setupHandlers(child);
255459
- }
255460
- onExit(listener) {
255461
- this.exitListeners.push(listener);
255462
- }
255463
- async stop() {
255464
- const child = this.child;
255465
- if (!child || child.exitCode !== null) {
255466
- return;
255467
- }
255468
- this.stopping = true;
255469
- const exited = new Promise((resolve10) => child.once("exit", () => resolve10()));
255470
- if (process21.platform === "win32" && child.pid) {
255471
- spawn3("taskkill", ["/pid", String(child.pid), "/T", "/F"]);
255472
- } else if (child.pid) {
255473
- try {
255474
- process21.kill(-child.pid, "SIGTERM");
255475
- } catch {
255476
- child.kill();
255477
- }
255478
- }
255479
- await exited;
255480
- }
255481
- setupHandlers(child) {
255482
- child.stdout?.on("data", (data) => this.emitLines(data, "log"));
255483
- child.stderr?.on("data", (data) => this.emitLines(data, "error"));
255484
- child.on("error", (error48) => {
255485
- this.logger.error("Frontend dev server failed to start:", error48);
255486
- this.notifyExit(null);
255487
- });
255488
- child.on("exit", (code2) => {
255489
- if (this.stopping) {
255490
- return;
255491
- }
255492
- this.logger.error(`Frontend dev server exited with code ${code2}`);
255493
- this.notifyExit(code2);
255494
- });
255495
- }
255496
- notifyExit(code2) {
255497
- for (const listener of this.exitListeners) {
255498
- listener(code2);
255499
- }
255500
- }
255501
- emitLines(data, type) {
255502
- const lines = data.toString().trimEnd().split(`
255503
- `);
255504
- for (const line3 of lines) {
255505
- if (type === "error") {
255506
- this.logger.error(line3);
255507
- } else {
255508
- this.logger.log(line3);
255509
- }
255510
- }
255511
- }
255512
- }
255513
-
255514
255732
  // src/cli/dev/dev-server/watcher.ts
255515
255733
  import { EventEmitter as EventEmitter4 } from "node:events";
255516
255734
  import { relative as relative6 } from "node:path";
@@ -257234,7 +257452,7 @@ async function createDevServer(options8) {
257234
257452
  }
257235
257453
  next();
257236
257454
  });
257237
- const devLogger = createDevLogger("backend", theme.styles.info);
257455
+ const devLogger = createDevLogger();
257238
257456
  const functionManager = new FunctionManager(functions, devLogger, options8.denoWrapperPath);
257239
257457
  const functionRoutes = createFunctionRouter(functionManager, devLogger);
257240
257458
  app.use("/api/apps/:appId/functions", functionRoutes);
@@ -257332,31 +257550,14 @@ async function createDevServer(options8) {
257332
257550
  }
257333
257551
  });
257334
257552
  await base44ConfigWatcher.start();
257335
- let serveRunner;
257336
- if (options8.serve && project2.site?.serveCommand) {
257337
- serveRunner = new ServeRunner({
257338
- command: project2.site.serveCommand,
257339
- cwd: project2.root,
257340
- env: {
257341
- VITE_BASE44_APP_ID: options8.serve.appId,
257342
- VITE_BASE44_APP_BASE_URL: baseUrl
257343
- },
257344
- logger: createDevLogger("frontend", theme.colors.base44Orange)
257345
- });
257346
- }
257347
257553
  const shutdown = async () => {
257348
257554
  base44ConfigWatcher.close();
257349
257555
  io6.close();
257350
257556
  await functionManager.stopAll();
257351
- await serveRunner?.stop();
257352
257557
  server.close();
257353
257558
  };
257354
257559
  process.on("SIGINT", shutdown);
257355
257560
  process.on("SIGTERM", shutdown);
257356
- serveRunner?.onExit(() => {
257357
- shutdown().finally(() => process.exit(1));
257358
- });
257359
- serveRunner?.start();
257360
257561
  return { port, server };
257361
257562
  }
257362
257563
 
@@ -257364,42 +257565,44 @@ async function createDevServer(options8) {
257364
257565
  function localServerUrl(port) {
257365
257566
  return `http://localhost:${port}`;
257366
257567
  }
257367
- async function writeEnvLocal(projectRoot, port, appId, log) {
257568
+ async function writeEnvLocalIfMissing(projectRoot, port, log) {
257368
257569
  const envLocalPath = join28(projectRoot, ".env.local");
257570
+ if (await pathExists(envLocalPath)) {
257571
+ return;
257572
+ }
257573
+ const { id: appId } = await initAppContext();
257369
257574
  await writeFile(envLocalPath, `VITE_BASE44_APP_ID=${appId}
257370
257575
  VITE_BASE44_APP_BASE_URL=${localServerUrl(port)}
257371
257576
  `);
257372
- log.info("Wrote .env.local with app ID and dev server URL");
257577
+ log.info("Created .env.local with app ID and dev server URL");
257373
257578
  }
257374
257579
  async function devAction({ log }, options8) {
257375
257580
  const port = options8.port ? Number(options8.port) : undefined;
257376
- const serveEnabled = options8.serve !== false;
257377
257581
  let projectRoot;
257378
- const appId = serveEnabled || options8.writeEnv ? (await initAppContext()).id : undefined;
257379
257582
  const { port: resolvedPort } = await createDevServer({
257380
257583
  log,
257381
257584
  port,
257585
+ cwd: process21.cwd(),
257382
257586
  denoWrapperPath: getDenoWrapperPath(),
257383
- serve: serveEnabled && appId ? { appId } : undefined,
257384
257587
  loadResources: async () => {
257385
257588
  const { functions, entities, project: project2 } = await readProjectConfig();
257386
257589
  projectRoot = project2.root;
257387
257590
  return { functions, entities, project: project2 };
257388
257591
  }
257389
257592
  });
257390
- if (options8.writeEnv && projectRoot && appId) {
257391
- await writeEnvLocal(projectRoot, resolvedPort, appId, log);
257593
+ if (projectRoot) {
257594
+ await writeEnvLocalIfMissing(projectRoot, resolvedPort, log);
257392
257595
  }
257393
257596
  return {
257394
257597
  outroMessage: `Dev server is available at ${theme.colors.links(localServerUrl(resolvedPort))}`
257395
257598
  };
257396
257599
  }
257397
257600
  function getDevCommand() {
257398
- return new Base44Command("dev").description("Start the development server").option("-p, --port <number>", "Port for the development server").option("--no-serve", "Do not start the frontend dev server (serveCommand)").option("--write-env", "Write the app ID and dev server URL to .env.local").action(devAction);
257601
+ return new Base44Command("dev").description("Start the development server").option("-p, --port <number>", "Port for the development server").action(devAction);
257399
257602
  }
257400
257603
 
257401
257604
  // src/core/exec/run-script.ts
257402
- import { spawn as spawn4 } from "node:child_process";
257605
+ import { spawn as spawn3 } from "node:child_process";
257403
257606
  import { copyFileSync, writeFileSync as writeFileSync2 } from "node:fs";
257404
257607
  async function runScript(options8) {
257405
257608
  const { appId, code: code2 } = options8;
@@ -257418,7 +257621,7 @@ async function runScript(options8) {
257418
257621
  copyFileSync(getExecWrapperPath(), tempWrapper.path);
257419
257622
  try {
257420
257623
  const exitCode = await new Promise((resolvePromise) => {
257421
- const child = spawn4("deno", ["run", "--allow-all", "--node-modules-dir=auto", tempWrapper.path], {
257624
+ const child = spawn3("deno", ["run", "--allow-all", "--node-modules-dir=auto", tempWrapper.path], {
257422
257625
  env: {
257423
257626
  ...process.env,
257424
257627
  SCRIPT_PATH: scriptPath,
@@ -257610,6 +257813,7 @@ function createProgram(context) {
257610
257813
  program2.addCommand(getConnectorsCommand());
257611
257814
  program2.addCommand(getFunctionsCommand());
257612
257815
  program2.addCommand(getSecretsCommand());
257816
+ program2.addCommand(getSandboxCommand());
257613
257817
  program2.addCommand(getAuthCommand());
257614
257818
  program2.addCommand(getSiteCommand());
257615
257819
  program2.addCommand(getTypesCommand());
@@ -261861,4 +262065,4 @@ export {
261861
262065
  CLIExitError
261862
262066
  };
261863
262067
 
261864
- //# debugId=A582415BD965E2EA64756E2164756E21
262068
+ //# debugId=61B9F8E330C194E064756E2164756E21