@base44-preview/cli 0.0.32-pr.271.5d60e7b → 0.0.33-pr.225.299669a

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
@@ -136896,12 +136896,12 @@ var require_linker = __commonJS((exports) => {
136896
136896
  var require_optionValidator = __commonJS((exports) => {
136897
136897
  Object.defineProperty(exports, "__esModule", { value: true });
136898
136898
  exports.validateOptions = undefined;
136899
- function validateOptions2({ maxItems }) {
136899
+ function validateOptions3({ maxItems }) {
136900
136900
  if (maxItems !== undefined && maxItems < -1) {
136901
136901
  throw RangeError(`Expected options.maxItems to be >= -1, but was given ${maxItems}.`);
136902
136902
  }
136903
136903
  }
136904
- exports.validateOptions = validateOptions2;
136904
+ exports.validateOptions = validateOptions3;
136905
136905
  });
136906
136906
 
136907
136907
  // node_modules/json-schema-to-typescript/dist/src/index.js
@@ -178514,6 +178514,18 @@ class InvalidInputError extends UserError {
178514
178514
  code = "INVALID_INPUT";
178515
178515
  }
178516
178516
 
178517
+ class DependencyNotFoundError extends UserError {
178518
+ code = "DEPENDENCY_NOT_FOUND";
178519
+ constructor(message, options) {
178520
+ super(message, {
178521
+ hints: options?.hints ?? [
178522
+ { message: "Install the required dependency and try again" }
178523
+ ],
178524
+ cause: options?.cause
178525
+ });
178526
+ }
178527
+ }
178528
+
178517
178529
  class ApiError extends SystemError {
178518
178530
  code = "API_ERROR";
178519
178531
  statusCode;
@@ -178629,6 +178641,39 @@ class FileReadError extends SystemError {
178629
178641
  });
178630
178642
  }
178631
178643
  }
178644
+
178645
+ class FunctionNotFoundError extends ApiError {
178646
+ constructor(functionName, cause) {
178647
+ super(`Function "${functionName}" was not found in this app`, {
178648
+ statusCode: 404,
178649
+ cause,
178650
+ hints: [
178651
+ {
178652
+ message: "Make sure the function name is correct and has been deployed",
178653
+ command: "base44 functions deploy"
178654
+ },
178655
+ {
178656
+ message: "List project functions by checking the base44/functions/ directory"
178657
+ }
178658
+ ]
178659
+ });
178660
+ }
178661
+ }
178662
+
178663
+ class InternalError extends SystemError {
178664
+ code = "INTERNAL_ERROR";
178665
+ constructor(message, options) {
178666
+ super(message, {
178667
+ hints: options?.hints ?? [
178668
+ {
178669
+ message: "This is an unexpected error. Please report it if it persists."
178670
+ }
178671
+ ],
178672
+ cause: options?.cause
178673
+ });
178674
+ }
178675
+ }
178676
+
178632
178677
  class TypeGenerationError extends SystemError {
178633
178678
  code = "TYPE_GENERATION_ERROR";
178634
178679
  constructor(message, entityName, cause) {
@@ -185985,6 +186030,13 @@ var DeployFunctionsResponseSchema = exports_external.object({
185985
186030
  skipped: exports_external.array(exports_external.string()).optional().nullable(),
185986
186031
  errors: exports_external.array(exports_external.object({ name: exports_external.string(), message: exports_external.string() })).nullable()
185987
186032
  });
186033
+ var LogLevelSchema = exports_external.enum(["log", "info", "warn", "error", "debug"]);
186034
+ var FunctionLogEntrySchema = exports_external.object({
186035
+ time: exports_external.string(),
186036
+ level: LogLevelSchema,
186037
+ message: exports_external.string()
186038
+ });
186039
+ var FunctionLogsResponseSchema = exports_external.array(FunctionLogEntrySchema);
185988
186040
 
185989
186041
  // src/core/resources/function/api.ts
185990
186042
  function toDeployPayloadItem(fn) {
@@ -186015,6 +186067,55 @@ async function deployFunctions(functions) {
186015
186067
  }
186016
186068
  return result.data;
186017
186069
  }
186070
+ function buildLogsQueryString(filters) {
186071
+ const params = new URLSearchParams;
186072
+ if (filters.since) {
186073
+ params.set("since", filters.since);
186074
+ }
186075
+ if (filters.until) {
186076
+ params.set("until", filters.until);
186077
+ }
186078
+ if (filters.level) {
186079
+ params.set("level", filters.level);
186080
+ }
186081
+ if (filters.limit !== undefined) {
186082
+ params.set("limit", String(filters.limit));
186083
+ }
186084
+ if (filters.order) {
186085
+ params.set("order", filters.order);
186086
+ }
186087
+ const queryString = params.toString();
186088
+ return queryString ? `?${queryString}` : "";
186089
+ }
186090
+ async function fetchFunctionLogs(functionName, filters = {}) {
186091
+ const appClient = getAppClient();
186092
+ const queryString = buildLogsQueryString(filters);
186093
+ let response;
186094
+ try {
186095
+ response = await appClient.get(`functions-mgmt/${functionName}/logs${queryString}`);
186096
+ } catch (error48) {
186097
+ if (error48 instanceof HTTPError) {
186098
+ if (error48.response.status === 404) {
186099
+ throw new FunctionNotFoundError(functionName, error48);
186100
+ }
186101
+ try {
186102
+ const body = await error48.response.clone().json();
186103
+ if (body.error_type === "KeyError") {
186104
+ throw new FunctionNotFoundError(functionName, error48);
186105
+ }
186106
+ } catch (parseError) {
186107
+ if (parseError instanceof ApiError)
186108
+ throw parseError;
186109
+ }
186110
+ }
186111
+ throw await ApiError.fromHttpError(error48, `fetching function logs: '${functionName}'`);
186112
+ }
186113
+ const result = FunctionLogsResponseSchema.safeParse(await response.json());
186114
+ if (!result.success) {
186115
+ throw new SchemaValidationError("Invalid function logs response from server", result.error);
186116
+ }
186117
+ return result.data;
186118
+ }
186018
186119
  // src/core/resources/function/config.ts
186019
186120
  import { dirname as dirname4, join as join5 } from "node:path";
186020
186121
  async function readFunctionConfig(configPath) {
@@ -187064,7 +187165,9 @@ var theme = {
187064
187165
  styles: {
187065
187166
  header: source_default.dim,
187066
187167
  bold: source_default.bold,
187067
- dim: source_default.dim
187168
+ dim: source_default.dim,
187169
+ error: source_default.red,
187170
+ warn: source_default.yellow
187068
187171
  },
187069
187172
  format: {
187070
187173
  errorContext(ctx) {
@@ -193846,7 +193949,7 @@ var {
193846
193949
  // package.json
193847
193950
  var package_default = {
193848
193951
  name: "base44",
193849
- version: "0.0.32",
193952
+ version: "0.0.33",
193850
193953
  description: "Base44 CLI - Unified interface for managing Base44 applications",
193851
193954
  type: "module",
193852
193955
  bin: {
@@ -193887,6 +193990,7 @@ var package_default = {
193887
193990
  "@types/bun": "^1.2.15",
193888
193991
  "@types/common-tags": "^1.8.4",
193889
193992
  "@types/cors": "^2.8.19",
193993
+ "@types/deno": "^2.5.0",
193890
193994
  "@types/ejs": "^3.1.5",
193891
193995
  "@types/express": "^5.0.6",
193892
193996
  "@types/json-schema": "^7.0.15",
@@ -193973,7 +194077,6 @@ async function printUpgradeNotificationIfAvailable() {
193973
194077
 
193974
194078
  // src/cli/utils/runCommand.ts
193975
194079
  async function runCommand(commandFn, options, context) {
193976
- console.log();
193977
194080
  if (options?.fullBanner) {
193978
194081
  await printBanner(context.isNonInteractive);
193979
194082
  We("");
@@ -193999,8 +194102,11 @@ async function runCommand(commandFn, options, context) {
193999
194102
  const appConfig = await initAppConfig();
194000
194103
  context.errorReporter.setContext({ appId: appConfig.id });
194001
194104
  }
194002
- const { outroMessage } = await commandFn();
194003
- Le(outroMessage || "");
194105
+ const result = await commandFn();
194106
+ Le(result.outroMessage || "");
194107
+ if (result.stdout) {
194108
+ process.stdout.write(result.stdout);
194109
+ }
194004
194110
  } catch (error48) {
194005
194111
  const errorMessage = error48 instanceof Error ? error48.message : String(error48);
194006
194112
  R2.error(errorMessage);
@@ -195027,6 +195133,147 @@ function getFunctionsDeployCommand(context) {
195027
195133
  }));
195028
195134
  }
195029
195135
 
195136
+ // src/cli/commands/logs/index.ts
195137
+ var VALID_LEVELS = ["log", "info", "warn", "error", "debug"];
195138
+ function parseFunctionFilters(options) {
195139
+ const filters = {};
195140
+ if (options.since) {
195141
+ filters.since = options.since;
195142
+ }
195143
+ if (options.until) {
195144
+ filters.until = options.until;
195145
+ }
195146
+ if (options.level) {
195147
+ filters.level = options.level;
195148
+ }
195149
+ if (options.limit) {
195150
+ filters.limit = Number.parseInt(options.limit, 10);
195151
+ }
195152
+ if (options.order) {
195153
+ filters.order = options.order.toLowerCase();
195154
+ }
195155
+ return filters;
195156
+ }
195157
+ function parseFunctionNames(option) {
195158
+ if (!option)
195159
+ return [];
195160
+ return option.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
195161
+ }
195162
+ function normalizeDatetime(value) {
195163
+ if (/Z$|[+-]\d{2}:\d{2}$/.test(value))
195164
+ return value;
195165
+ return `${value}Z`;
195166
+ }
195167
+ function validateOptions2(options) {
195168
+ if (options.level && !VALID_LEVELS.includes(options.level)) {
195169
+ throw new InvalidInputError(`Invalid level: "${options.level}". Must be one of: ${VALID_LEVELS.join(", ")}.`);
195170
+ }
195171
+ if (options.limit) {
195172
+ const limit = Number.parseInt(options.limit, 10);
195173
+ if (Number.isNaN(limit) || limit < 1 || limit > 1000) {
195174
+ throw new InvalidInputError(`Invalid limit: "${options.limit}". Must be a number between 1 and 1000.`);
195175
+ }
195176
+ }
195177
+ if (options.order) {
195178
+ const order = options.order.toUpperCase();
195179
+ if (order !== "ASC" && order !== "DESC") {
195180
+ throw new InvalidInputError(`Invalid order: "${options.order}". Must be "ASC" or "DESC".`);
195181
+ }
195182
+ }
195183
+ }
195184
+ function formatEntry(entry) {
195185
+ const time3 = entry.time.substring(0, 19).replace("T", " ");
195186
+ const level = entry.level.toUpperCase().padEnd(5);
195187
+ const message = entry.message.trim();
195188
+ return `${time3} ${level} ${message}
195189
+ `;
195190
+ }
195191
+ function formatLogs(entries) {
195192
+ if (entries.length === 0) {
195193
+ return `No logs found matching the filters.
195194
+ `;
195195
+ }
195196
+ let output = `Showing ${entries.length} function log entries
195197
+
195198
+ `;
195199
+ for (const entry of entries) {
195200
+ output += formatEntry(entry);
195201
+ }
195202
+ return output;
195203
+ }
195204
+ function normalizeLogEntry(entry, functionName) {
195205
+ return {
195206
+ time: entry.time,
195207
+ level: entry.level,
195208
+ message: `[${functionName}] ${entry.message}`,
195209
+ source: functionName
195210
+ };
195211
+ }
195212
+ async function fetchLogsForFunctions(functionNames, options, availableFunctionNames) {
195213
+ const filters = parseFunctionFilters(options);
195214
+ const allEntries = [];
195215
+ for (const functionName of functionNames) {
195216
+ let logs;
195217
+ try {
195218
+ logs = await fetchFunctionLogs(functionName, filters);
195219
+ } catch (error48) {
195220
+ if (error48 instanceof FunctionNotFoundError && availableFunctionNames.length > 0) {
195221
+ const available = availableFunctionNames.join(", ");
195222
+ throw new InvalidInputError(`Function "${functionName}" was not found in this app`, {
195223
+ hints: [
195224
+ {
195225
+ message: `Available functions in this project: ${available}`
195226
+ },
195227
+ {
195228
+ message: "Make sure the function has been deployed before fetching logs",
195229
+ command: "base44 functions deploy"
195230
+ }
195231
+ ]
195232
+ });
195233
+ }
195234
+ throw error48;
195235
+ }
195236
+ const entries = logs.map((entry) => normalizeLogEntry(entry, functionName));
195237
+ allEntries.push(...entries);
195238
+ }
195239
+ if (functionNames.length > 1) {
195240
+ const order = options.order?.toUpperCase() === "ASC" ? 1 : -1;
195241
+ allEntries.sort((a2, b) => order * a2.time.localeCompare(b.time));
195242
+ }
195243
+ return allEntries;
195244
+ }
195245
+ async function getAllFunctionNames() {
195246
+ const { functions } = await readProjectConfig();
195247
+ return functions.map((fn) => fn.name);
195248
+ }
195249
+ async function logsAction(options) {
195250
+ if (options.since)
195251
+ options.since = normalizeDatetime(options.since);
195252
+ if (options.until)
195253
+ options.until = normalizeDatetime(options.until);
195254
+ validateOptions2(options);
195255
+ const specifiedFunctions = parseFunctionNames(options.function);
195256
+ const allProjectFunctions = await getAllFunctionNames();
195257
+ const functionNames = specifiedFunctions.length > 0 ? specifiedFunctions : allProjectFunctions;
195258
+ if (functionNames.length === 0) {
195259
+ return { stdout: `No functions found in this project.
195260
+ ` };
195261
+ }
195262
+ let entries = await fetchLogsForFunctions(functionNames, options, allProjectFunctions);
195263
+ const limit = options.limit ? Number.parseInt(options.limit, 10) : undefined;
195264
+ if (limit !== undefined && entries.length > limit) {
195265
+ entries = entries.slice(0, limit);
195266
+ }
195267
+ const stdout = options.json ? `${JSON.stringify(entries, null, 2)}
195268
+ ` : formatLogs(entries);
195269
+ return { stdout };
195270
+ }
195271
+ function getLogsCommand(context) {
195272
+ return new Command("logs").description("Fetch function logs for this app").option("--function <names>", "Filter by function name(s), comma-separated. If omitted, fetches logs for all project functions").option("--since <datetime>", "Show logs from this time (ISO format)").option("--until <datetime>", "Show logs until this time (ISO format)").option("--level <level>", "Filter by log level: log, info, warn, error, debug").option("-n, --limit <n>", "Results per page (1-1000, default: 50)").option("--order <order>", "Sort order: ASC|DESC (default: DESC)").option("--json", "Output raw JSON").action(async (options) => {
195273
+ await runCommand(() => logsAction(options), { requireAuth: true }, context);
195274
+ });
195275
+ }
195276
+
195030
195277
  // src/cli/commands/project/create.ts
195031
195278
  import { basename as basename3, join as join11, resolve as resolve2 } from "node:path";
195032
195279
  var import_lodash = __toESM(require_lodash(), 1);
@@ -195610,9 +195857,12 @@ function getTypesCommand(context) {
195610
195857
  return new Command("types").description("Manage TypeScript type generation").addCommand(getTypesGenerateCommand(context));
195611
195858
  }
195612
195859
 
195860
+ // src/cli/commands/dev.ts
195861
+ import { dirname as dirname12, join as join16 } from "node:path";
195862
+
195613
195863
  // src/cli/dev/dev-server/main.ts
195614
195864
  var import_cors = __toESM(require_lib4(), 1);
195615
- var import_express = __toESM(require_express(), 1);
195865
+ var import_express2 = __toESM(require_express(), 1);
195616
195866
 
195617
195867
  // node_modules/get-port/index.js
195618
195868
  import net from "node:net";
@@ -195729,13 +195979,232 @@ async function getPorts(options8) {
195729
195979
  }
195730
195980
 
195731
195981
  // src/cli/dev/dev-server/main.ts
195982
+ var import_http_proxy_middleware2 = __toESM(require_dist2(), 1);
195983
+
195984
+ // src/cli/dev/createDevLogger.ts
195985
+ var colorByType = {
195986
+ error: theme.styles.error,
195987
+ warn: theme.styles.warn,
195988
+ log: (text) => text
195989
+ };
195990
+ function createDevLogger() {
195991
+ const print = (type, msg) => {
195992
+ const colorize = colorByType[type];
195993
+ console[type](colorize(msg));
195994
+ };
195995
+ return {
195996
+ log: (msg) => print("log", msg),
195997
+ error: (msg, err) => {
195998
+ print("error", msg);
195999
+ if (err) {
196000
+ print("error", String(err));
196001
+ }
196002
+ },
196003
+ warn: (msg) => print("warn", msg)
196004
+ };
196005
+ }
196006
+
196007
+ // src/cli/dev/dev-server/function-manager.ts
196008
+ import { spawn as spawn2, spawnSync as spawnSync2 } from "node:child_process";
196009
+ import { dirname as dirname11, join as join15 } from "node:path";
196010
+ import { fileURLToPath as fileURLToPath7 } from "node:url";
196011
+ var __dirname5 = dirname11(fileURLToPath7(import.meta.url));
196012
+ var WRAPPER_PATH = join15(__dirname5, "../deno-runtime/main.js");
196013
+ var READY_TIMEOUT = 30000;
196014
+
196015
+ class FunctionManager {
196016
+ functions;
196017
+ running = new Map;
196018
+ starting = new Map;
196019
+ logger;
196020
+ constructor(functions, logger) {
196021
+ this.functions = new Map(functions.map((f7) => [f7.name, f7]));
196022
+ this.logger = logger;
196023
+ if (functions.length > 0) {
196024
+ this.verifyDenoIsInstalled();
196025
+ }
196026
+ }
196027
+ verifyDenoIsInstalled() {
196028
+ const result = spawnSync2("deno", ["--version"]);
196029
+ if (result.error) {
196030
+ throw new DependencyNotFoundError("Deno is required to run functions", {
196031
+ hints: [{ message: "Install Deno from https://deno.com/download" }]
196032
+ });
196033
+ }
196034
+ }
196035
+ getFunctionNames() {
196036
+ return Array.from(this.functions.keys());
196037
+ }
196038
+ async ensureRunning(name2) {
196039
+ const backendFunction = this.functions.get(name2);
196040
+ if (!backendFunction) {
196041
+ throw new InvalidInputError(`Function "${name2}" not found`, {
196042
+ hints: [{ message: "Check available functions in your project" }]
196043
+ });
196044
+ }
196045
+ const existing = this.running.get(name2);
196046
+ if (existing?.ready) {
196047
+ return existing.port;
196048
+ }
196049
+ const pending = this.starting.get(name2);
196050
+ if (pending) {
196051
+ return pending;
196052
+ }
196053
+ const promise2 = this.startFunction(name2, backendFunction);
196054
+ this.starting.set(name2, promise2);
196055
+ try {
196056
+ return await promise2;
196057
+ } finally {
196058
+ this.starting.delete(name2);
196059
+ }
196060
+ }
196061
+ async startFunction(name2, backendFunction) {
196062
+ const port = await this.allocatePort();
196063
+ const process21 = this.spawnFunction(backendFunction, port);
196064
+ const runningFunc = {
196065
+ process: process21,
196066
+ port,
196067
+ ready: false
196068
+ };
196069
+ this.running.set(name2, runningFunc);
196070
+ this.setupProcessHandlers(name2, process21);
196071
+ return this.waitForReady(name2, runningFunc);
196072
+ }
196073
+ stopAll() {
196074
+ for (const [name2, { process: process21 }] of this.running) {
196075
+ this.logger.log(`[dev-server] Stopping function: ${name2}`);
196076
+ process21.kill();
196077
+ }
196078
+ this.running.clear();
196079
+ this.starting.clear();
196080
+ }
196081
+ async allocatePort() {
196082
+ const usedPorts = Array.from(this.running.values()).map((r5) => r5.port);
196083
+ return getPorts({ exclude: usedPorts });
196084
+ }
196085
+ spawnFunction(func, port) {
196086
+ this.logger.log(`[dev-server] Spawning function "${func.name}" on port ${port}`);
196087
+ const process21 = spawn2("deno", ["run", "--allow-all", WRAPPER_PATH], {
196088
+ env: {
196089
+ ...globalThis.process.env,
196090
+ FUNCTION_PATH: func.entryPath,
196091
+ FUNCTION_PORT: String(port),
196092
+ FUNCTION_NAME: func.name
196093
+ },
196094
+ stdio: ["pipe", "pipe", "pipe"]
196095
+ });
196096
+ return process21;
196097
+ }
196098
+ setupProcessHandlers(name2, process21) {
196099
+ process21.stdout?.on("data", (data) => {
196100
+ const lines = data.toString().trim().split(`
196101
+ `);
196102
+ for (const line3 of lines) {
196103
+ this.logger.log(line3);
196104
+ }
196105
+ });
196106
+ process21.stderr?.on("data", (data) => {
196107
+ const lines = data.toString().trim().split(`
196108
+ `);
196109
+ for (const line3 of lines) {
196110
+ this.logger.error(line3);
196111
+ }
196112
+ });
196113
+ process21.on("exit", (code2) => {
196114
+ this.logger.log(`[dev-server] Function "${name2}" exited with code ${code2}`);
196115
+ this.running.delete(name2);
196116
+ });
196117
+ process21.on("error", (error48) => {
196118
+ this.logger.error(`[dev-server] Function "${name2}" error:`, error48);
196119
+ this.running.delete(name2);
196120
+ });
196121
+ }
196122
+ waitForReady(name2, runningFunc) {
196123
+ return new Promise((resolve5, reject) => {
196124
+ runningFunc.process.on("exit", (code2) => {
196125
+ if (!runningFunc.ready) {
196126
+ clearTimeout(timeout3);
196127
+ reject(new InternalError(`Function "${name2}" exited with code ${code2}`, {
196128
+ hints: [{ message: "Check the function code for errors" }]
196129
+ }));
196130
+ }
196131
+ });
196132
+ const timeout3 = setTimeout(() => {
196133
+ runningFunc.process.kill();
196134
+ reject(new InternalError(`Function "${name2}" failed to start within ${READY_TIMEOUT / 1000}s timeout`, {
196135
+ hints: [
196136
+ { message: "Check the function code for startup errors" }
196137
+ ]
196138
+ }));
196139
+ }, READY_TIMEOUT);
196140
+ const onData = (data) => {
196141
+ const output = data.toString();
196142
+ if (output.includes("Listening on")) {
196143
+ runningFunc.ready = true;
196144
+ clearTimeout(timeout3);
196145
+ runningFunc.process.stdout?.off("data", onData);
196146
+ resolve5(runningFunc.port);
196147
+ }
196148
+ };
196149
+ runningFunc.process.stdout?.on("data", onData);
196150
+ });
196151
+ }
196152
+ }
196153
+
196154
+ // src/cli/dev/dev-server/routes/functions.ts
196155
+ var import_express = __toESM(require_express(), 1);
195732
196156
  var import_http_proxy_middleware = __toESM(require_dist2(), 1);
196157
+ import { ServerResponse } from "node:http";
196158
+ function createFunctionRouter(manager, logger) {
196159
+ const router = import_express.Router({ mergeParams: true });
196160
+ const portsByRequest = new WeakMap;
196161
+ const proxy = import_http_proxy_middleware.createProxyMiddleware({
196162
+ router: (req) => `http://localhost:${portsByRequest.get(req)}`,
196163
+ changeOrigin: true,
196164
+ on: {
196165
+ proxyReq: (proxyReq, req) => {
196166
+ const xAppId = req.headers["x-app-id"];
196167
+ if (xAppId) {
196168
+ proxyReq.setHeader("Base44-App-Id", xAppId);
196169
+ }
196170
+ proxyReq.setHeader("Base44-Api-Url", `${req.protocol}://${req.headers.host}`);
196171
+ },
196172
+ error: (err, _req, res) => {
196173
+ logger.error("Function proxy error:", err);
196174
+ if (res instanceof ServerResponse && !res.headersSent) {
196175
+ res.writeHead(502, { "Content-Type": "application/json" });
196176
+ res.end(JSON.stringify({
196177
+ error: "Failed to proxy request to function",
196178
+ details: err.message
196179
+ }));
196180
+ }
196181
+ }
196182
+ }
196183
+ });
196184
+ router.all("/:functionName", async (req, res, next) => {
196185
+ const { functionName } = req.params;
196186
+ try {
196187
+ const port = await manager.ensureRunning(functionName);
196188
+ portsByRequest.set(req, port);
196189
+ next();
196190
+ } catch (error48) {
196191
+ logger.error("Function error:", error48);
196192
+ const message = error48 instanceof Error ? error48.message : String(error48);
196193
+ res.status(500).json({ error: message });
196194
+ }
196195
+ }, proxy);
196196
+ return router;
196197
+ }
196198
+
196199
+ // src/cli/dev/dev-server/main.ts
195733
196200
  var DEFAULT_PORT = 4400;
195734
196201
  var BASE44_APP_URL = "https://base44.app";
195735
- async function createDevServer(options8 = {}) {
195736
- const port = options8.port ?? await getPorts({ port: DEFAULT_PORT });
195737
- const app = import_express.default();
195738
- const remoteProxy = import_http_proxy_middleware.createProxyMiddleware({
196202
+ async function createDevServer(options8) {
196203
+ const { port: userPort } = options8;
196204
+ const port = userPort ?? await getPorts({ port: DEFAULT_PORT });
196205
+ const { functions } = await options8.loadResources();
196206
+ const app = import_express2.default();
196207
+ const remoteProxy = import_http_proxy_middleware2.createProxyMiddleware({
195739
196208
  target: BASE44_APP_URL,
195740
196209
  changeOrigin: true
195741
196210
  });
@@ -195751,6 +196220,13 @@ async function createDevServer(options8 = {}) {
195751
196220
  }
195752
196221
  next();
195753
196222
  });
196223
+ const devLogger = createDevLogger();
196224
+ const functionManager = new FunctionManager(functions, devLogger);
196225
+ if (functionManager.getFunctionNames().length > 0) {
196226
+ R2.info(`Loaded functions: ${functionManager.getFunctionNames().join(", ")}`);
196227
+ const functionRoutes = createFunctionRouter(functionManager, devLogger);
196228
+ app.use("/api/apps/:appId/functions", functionRoutes);
196229
+ }
195754
196230
  app.use((req, res, next) => {
195755
196231
  return remoteProxy(req, res, next);
195756
196232
  });
@@ -195763,6 +196239,12 @@ async function createDevServer(options8 = {}) {
195763
196239
  reject(err);
195764
196240
  }
195765
196241
  } else {
196242
+ const shutdown = () => {
196243
+ functionManager.stopAll();
196244
+ server.close();
196245
+ };
196246
+ process.on("SIGINT", shutdown);
196247
+ process.on("SIGTERM", shutdown);
195766
196248
  resolve5({
195767
196249
  port,
195768
196250
  server
@@ -195775,7 +196257,15 @@ async function createDevServer(options8 = {}) {
195775
196257
  // src/cli/commands/dev.ts
195776
196258
  async function devAction(options8) {
195777
196259
  const port = options8.port ? Number(options8.port) : undefined;
195778
- const { port: resolvedPort } = await createDevServer({ port });
196260
+ const { port: resolvedPort } = await createDevServer({
196261
+ port,
196262
+ loadResources: async () => {
196263
+ const { project: project2 } = await readProjectConfig();
196264
+ const configDir = dirname12(project2.configPath);
196265
+ const functions = await functionResource.readAll(join16(configDir, project2.functionsDir));
196266
+ return { functions };
196267
+ }
196268
+ });
195779
196269
  return {
195780
196270
  outroMessage: `Dev server is available at ${theme.colors.links(`http://localhost:${resolvedPort}`)}`
195781
196271
  };
@@ -195899,6 +196389,7 @@ function createProgram(context) {
195899
196389
  program2.addCommand(getSiteCommand(context));
195900
196390
  program2.addCommand(getTypesCommand(context));
195901
196391
  program2.addCommand(getDevCommand(context), { hidden: true });
196392
+ program2.addCommand(getLogsCommand(context));
195902
196393
  return program2;
195903
196394
  }
195904
196395
 
@@ -195937,7 +196428,7 @@ function nanoid3(size = 21) {
195937
196428
  }
195938
196429
 
195939
196430
  // node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
195940
- import { dirname as dirname11, posix, sep } from "path";
196431
+ import { dirname as dirname13, posix, sep } from "path";
195941
196432
  function createModulerModifier() {
195942
196433
  const getModuleFromFileName = createGetModuleFromFilename();
195943
196434
  return async (frames) => {
@@ -195946,7 +196437,7 @@ function createModulerModifier() {
195946
196437
  return frames;
195947
196438
  };
195948
196439
  }
195949
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname11(process.argv[1]) : process.cwd(), isWindows4 = sep === "\\") {
196440
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname13(process.argv[1]) : process.cwd(), isWindows4 = sep === "\\") {
195950
196441
  const normalizedBase = isWindows4 ? normalizeWindowsPath2(basePath) : basePath;
195951
196442
  return (filename) => {
195952
196443
  if (!filename)
@@ -200163,4 +200654,4 @@ export {
200163
200654
  CLIExitError
200164
200655
  };
200165
200656
 
200166
- //# debugId=8FF06F66318A4ACC64756E2164756E21
200657
+ //# debugId=00151F47FED4FE2F64756E2164756E21