@base44-preview/cli 0.0.32-pr.271.5d60e7b → 0.0.33-pr.259.052dce4

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
@@ -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,21 @@ class FileReadError extends SystemError {
178629
178641
  });
178630
178642
  }
178631
178643
  }
178644
+
178645
+ class InternalError extends SystemError {
178646
+ code = "INTERNAL_ERROR";
178647
+ constructor(message, options) {
178648
+ super(message, {
178649
+ hints: options?.hints ?? [
178650
+ {
178651
+ message: "This is an unexpected error. Please report it if it persists."
178652
+ }
178653
+ ],
178654
+ cause: options?.cause
178655
+ });
178656
+ }
178657
+ }
178658
+
178632
178659
  class TypeGenerationError extends SystemError {
178633
178660
  code = "TYPE_GENERATION_ERROR";
178634
178661
  constructor(message, entityName, cause) {
@@ -185915,6 +185942,118 @@ async function pushEntities(entities) {
185915
185942
  }
185916
185943
  return syncEntities(entities);
185917
185944
  }
185945
+ // src/core/resources/entity/records-schema.ts
185946
+ var EntityRecordSchema = exports_external.looseObject({
185947
+ id: exports_external.string(),
185948
+ created_date: exports_external.string(),
185949
+ updated_date: exports_external.string(),
185950
+ created_by: exports_external.string().optional()
185951
+ });
185952
+ var DeleteRecordResponseSchema = exports_external.object({
185953
+ success: exports_external.boolean()
185954
+ });
185955
+
185956
+ // src/core/resources/entity/records-api.ts
185957
+ async function listRecords(entityName, options = {}) {
185958
+ const appClient = getAppClient();
185959
+ const searchParams = new URLSearchParams;
185960
+ if (options.filter) {
185961
+ searchParams.set("q", options.filter);
185962
+ }
185963
+ if (options.sort) {
185964
+ searchParams.set("sort", options.sort);
185965
+ }
185966
+ if (options.limit !== undefined) {
185967
+ searchParams.set("limit", String(options.limit));
185968
+ }
185969
+ if (options.skip !== undefined) {
185970
+ searchParams.set("skip", String(options.skip));
185971
+ }
185972
+ if (options.fields) {
185973
+ searchParams.set("fields", options.fields);
185974
+ }
185975
+ let response;
185976
+ try {
185977
+ response = await appClient.get(`admin/entities/${entityName}`, {
185978
+ searchParams
185979
+ });
185980
+ } catch (error48) {
185981
+ throw await ApiError.fromHttpError(error48, "listing records");
185982
+ }
185983
+ const json2 = await response.json();
185984
+ const records = Array.isArray(json2) ? json2 : [];
185985
+ return records.map((record2) => {
185986
+ const result = EntityRecordSchema.safeParse(record2);
185987
+ if (!result.success) {
185988
+ throw new SchemaValidationError("Invalid record in response", result.error);
185989
+ }
185990
+ return result.data;
185991
+ });
185992
+ }
185993
+ async function getRecord(entityName, recordId) {
185994
+ const appClient = getAppClient();
185995
+ let response;
185996
+ try {
185997
+ response = await appClient.get(`admin/entities/${entityName}/${recordId}`);
185998
+ } catch (error48) {
185999
+ throw await ApiError.fromHttpError(error48, "getting record");
186000
+ }
186001
+ const json2 = await response.json();
186002
+ const result = EntityRecordSchema.safeParse(json2);
186003
+ if (!result.success) {
186004
+ throw new SchemaValidationError("Invalid record response", result.error);
186005
+ }
186006
+ return result.data;
186007
+ }
186008
+ async function createRecord(entityName, data) {
186009
+ const appClient = getAppClient();
186010
+ let response;
186011
+ try {
186012
+ response = await appClient.post(`admin/entities/${entityName}`, {
186013
+ json: data
186014
+ });
186015
+ } catch (error48) {
186016
+ throw await ApiError.fromHttpError(error48, "creating record");
186017
+ }
186018
+ const json2 = await response.json();
186019
+ const result = EntityRecordSchema.safeParse(json2);
186020
+ if (!result.success) {
186021
+ throw new SchemaValidationError("Invalid record in create response", result.error);
186022
+ }
186023
+ return result.data;
186024
+ }
186025
+ async function updateRecord(entityName, recordId, data) {
186026
+ const appClient = getAppClient();
186027
+ let response;
186028
+ try {
186029
+ response = await appClient.put(`admin/entities/${entityName}/${recordId}`, {
186030
+ json: data
186031
+ });
186032
+ } catch (error48) {
186033
+ throw await ApiError.fromHttpError(error48, "updating record");
186034
+ }
186035
+ const json2 = await response.json();
186036
+ const result = EntityRecordSchema.safeParse(json2);
186037
+ if (!result.success) {
186038
+ throw new SchemaValidationError("Invalid record in update response", result.error);
186039
+ }
186040
+ return result.data;
186041
+ }
186042
+ async function deleteRecord(entityName, recordId) {
186043
+ const appClient = getAppClient();
186044
+ let response;
186045
+ try {
186046
+ response = await appClient.delete(`admin/entities/${entityName}/${recordId}`);
186047
+ } catch (error48) {
186048
+ throw await ApiError.fromHttpError(error48, "deleting record");
186049
+ }
186050
+ const json2 = await response.json();
186051
+ const result = DeleteRecordResponseSchema.safeParse(json2);
186052
+ if (!result.success) {
186053
+ throw new SchemaValidationError("Invalid delete response", result.error);
186054
+ }
186055
+ return result.data;
186056
+ }
185918
186057
  // src/core/resources/entity/resource.ts
185919
186058
  var entityResource = {
185920
186059
  readAll: readAllEntities,
@@ -187064,7 +187203,9 @@ var theme = {
187064
187203
  styles: {
187065
187204
  header: source_default.dim,
187066
187205
  bold: source_default.bold,
187067
- dim: source_default.dim
187206
+ dim: source_default.dim,
187207
+ error: source_default.red,
187208
+ warn: source_default.yellow
187068
187209
  },
187069
187210
  format: {
187070
187211
  errorContext(ctx) {
@@ -193846,7 +193987,7 @@ var {
193846
193987
  // package.json
193847
193988
  var package_default = {
193848
193989
  name: "base44",
193849
- version: "0.0.32",
193990
+ version: "0.0.33",
193850
193991
  description: "Base44 CLI - Unified interface for managing Base44 applications",
193851
193992
  type: "module",
193852
193993
  bin: {
@@ -193887,6 +194028,7 @@ var package_default = {
193887
194028
  "@types/bun": "^1.2.15",
193888
194029
  "@types/common-tags": "^1.8.4",
193889
194030
  "@types/cors": "^2.8.19",
194031
+ "@types/deno": "^2.5.0",
193890
194032
  "@types/ejs": "^3.1.5",
193891
194033
  "@types/express": "^5.0.6",
193892
194034
  "@types/json-schema": "^7.0.15",
@@ -194982,9 +195124,152 @@ async function pushEntitiesAction() {
194982
195124
  return { outroMessage: "Entities pushed to Base44" };
194983
195125
  }
194984
195126
  function getEntitiesPushCommand(context) {
194985
- return new Command("entities").description("Manage project entities").addCommand(new Command("push").description("Push local entities to Base44").action(async () => {
195127
+ return new Command("push").description("Push local entity schemas to Base44").action(async () => {
194986
195128
  await runCommand(pushEntitiesAction, { requireAuth: true }, context);
194987
- }));
195129
+ });
195130
+ }
195131
+
195132
+ // src/cli/commands/entities/records/parseRecordData.ts
195133
+ var import_json52 = __toESM(require_lib(), 1);
195134
+ async function parseRecordData(options, exampleHint) {
195135
+ if (options.data && options.file) {
195136
+ throw new InvalidInputError("Cannot use both --data and --file. Choose one.", {
195137
+ hints: [
195138
+ {
195139
+ message: `Pass --data for inline JSON or --file for a JSON file path, not both.`
195140
+ }
195141
+ ]
195142
+ });
195143
+ }
195144
+ if (options.data) {
195145
+ try {
195146
+ return import_json52.default.parse(options.data);
195147
+ } catch {
195148
+ throw new InvalidInputError("Invalid JSON in --data flag. Provide valid JSON.", {
195149
+ hints: [{ message: `Example: --data '${exampleHint}'` }]
195150
+ });
195151
+ }
195152
+ }
195153
+ if (options.file) {
195154
+ return readJsonFile(options.file);
195155
+ }
195156
+ throw new InvalidInputError("Provide record data with --data or --file flag", {
195157
+ hints: [
195158
+ {
195159
+ message: `Example: --data '${exampleHint}' or --file record.json`
195160
+ }
195161
+ ]
195162
+ });
195163
+ }
195164
+
195165
+ // src/cli/commands/entities/records/create.ts
195166
+ async function createRecordAction(entityName, options) {
195167
+ const data = await parseRecordData(options, '{"name": "John", "email": "john@example.com"}');
195168
+ const record2 = await runTask(`Creating ${entityName} record...`, async () => {
195169
+ return await createRecord(entityName, data);
195170
+ }, {
195171
+ successMessage: `Created ${entityName} record`,
195172
+ errorMessage: `Failed to create ${entityName} record`
195173
+ });
195174
+ R2.info(JSON.stringify(record2, null, 2));
195175
+ return { outroMessage: `Record created with ID: ${record2.id}` };
195176
+ }
195177
+ function getRecordsCreateCommand(context) {
195178
+ return new Command("create").description("Create a new entity record").argument("<entity-name>", "Name of the entity (e.g. Users, Products)").option("-d, --data <json>", "JSON object with record data").option("--file <path>", "Read record data from a JSON/JSONC file").action(async (entityName, options) => {
195179
+ await runCommand(() => createRecordAction(entityName, options), { requireAuth: true }, context);
195180
+ });
195181
+ }
195182
+
195183
+ // src/cli/commands/entities/records/delete.ts
195184
+ async function deleteRecordAction(entityName, recordId, options) {
195185
+ if (!options.yes) {
195186
+ const confirmed = await Re({
195187
+ message: `Delete ${entityName} record ${recordId}?`
195188
+ });
195189
+ if (confirmed !== true) {
195190
+ throw new CLIExitError(0);
195191
+ }
195192
+ }
195193
+ await runTask(`Deleting ${entityName} record...`, async () => {
195194
+ return await deleteRecord(entityName, recordId);
195195
+ }, {
195196
+ successMessage: `Deleted ${entityName} record`,
195197
+ errorMessage: `Failed to delete ${entityName} record`
195198
+ });
195199
+ return { outroMessage: `Record ${recordId} deleted` };
195200
+ }
195201
+ function getRecordsDeleteCommand(context) {
195202
+ return new Command("delete").description("Delete an entity record").argument("<entity-name>", "Name of the entity (e.g. Users, Products)").argument("<record-id>", "ID of the record to delete").option("-y, --yes", "Skip confirmation prompt").action(async (entityName, recordId, options) => {
195203
+ await runCommand(() => deleteRecordAction(entityName, recordId, options), { requireAuth: true }, context);
195204
+ });
195205
+ }
195206
+
195207
+ // src/cli/commands/entities/records/get.ts
195208
+ async function getRecordAction(entityName, recordId) {
195209
+ const record2 = await runTask(`Fetching ${entityName} record...`, async () => {
195210
+ return await getRecord(entityName, recordId);
195211
+ }, {
195212
+ successMessage: `Fetched ${entityName} record`,
195213
+ errorMessage: `Failed to fetch ${entityName} record`
195214
+ });
195215
+ R2.info(JSON.stringify(record2, null, 2));
195216
+ return {};
195217
+ }
195218
+ function getRecordsGetCommand(context) {
195219
+ return new Command("get").description("Get a single entity record by ID").argument("<entity-name>", "Name of the entity (e.g. Users, Products)").argument("<record-id>", "ID of the record").action(async (entityName, recordId) => {
195220
+ await runCommand(() => getRecordAction(entityName, recordId), { requireAuth: true }, context);
195221
+ });
195222
+ }
195223
+
195224
+ // src/cli/commands/entities/records/list.ts
195225
+ async function listRecordsAction(entityName, options) {
195226
+ const records = await runTask(`Fetching ${entityName} records...`, async () => {
195227
+ return await listRecords(entityName, {
195228
+ filter: options.filter,
195229
+ sort: options.sort,
195230
+ limit: options.limit ? Number(options.limit) : 50,
195231
+ skip: options.skip ? Number(options.skip) : undefined,
195232
+ fields: options.fields
195233
+ });
195234
+ }, {
195235
+ successMessage: `Fetched ${entityName} records`,
195236
+ errorMessage: `Failed to fetch ${entityName} records`
195237
+ });
195238
+ R2.info(JSON.stringify(records, null, 2));
195239
+ return { outroMessage: `Found ${records.length} ${entityName} record(s)` };
195240
+ }
195241
+ function getRecordsListCommand(context) {
195242
+ return new Command("list").description("List entity records").argument("<entity-name>", "Name of the entity (e.g. Users, Products)").option("-f, --filter <json>", `JSON filter object (e.g. '{"status":"active"}' or '{"age":{"$gt":18}}')`).option("-s, --sort <field>", "Sort field name, prefix with - for descending (e.g. -created_date)").option("-l, --limit <n>", "Max number of records to return", "50").option("--skip <n>", "Number of records to skip (for pagination)").option("--fields <fields>", "Comma-separated list of fields to return (e.g. id,name,email)").action(async (entityName, options) => {
195243
+ await runCommand(() => listRecordsAction(entityName, options), { requireAuth: true }, context);
195244
+ });
195245
+ }
195246
+
195247
+ // src/cli/commands/entities/records/update.ts
195248
+ async function updateRecordAction(entityName, recordId, options) {
195249
+ const data = await parseRecordData(options, '{"status": "active"}');
195250
+ const record2 = await runTask(`Updating ${entityName} record...`, async () => {
195251
+ return await updateRecord(entityName, recordId, data);
195252
+ }, {
195253
+ successMessage: `Updated ${entityName} record`,
195254
+ errorMessage: `Failed to update ${entityName} record`
195255
+ });
195256
+ R2.info(JSON.stringify(record2, null, 2));
195257
+ return { outroMessage: `Record ${recordId} updated` };
195258
+ }
195259
+ function getRecordsUpdateCommand(context) {
195260
+ return new Command("update").description("Update an entity record").argument("<entity-name>", "Name of the entity (e.g. Users, Products)").argument("<record-id>", "ID of the record to update").option("-d, --data <json>", "JSON object with fields to update").option("--file <path>", "Read update data from a JSON/JSONC file").action(async (entityName, recordId, options) => {
195261
+ await runCommand(() => updateRecordAction(entityName, recordId, options), { requireAuth: true }, context);
195262
+ });
195263
+ }
195264
+
195265
+ // src/cli/commands/entities/records/index.ts
195266
+ function getRecordsCommand(context) {
195267
+ return new Command("records").description("CRUD operations on entity records").addCommand(getRecordsListCommand(context)).addCommand(getRecordsGetCommand(context)).addCommand(getRecordsCreateCommand(context)).addCommand(getRecordsUpdateCommand(context)).addCommand(getRecordsDeleteCommand(context));
195268
+ }
195269
+
195270
+ // src/cli/commands/entities/index.ts
195271
+ function getEntitiesCommand(context) {
195272
+ return new Command("entities").description("Manage project entities").addCommand(getEntitiesPushCommand(context)).addCommand(getRecordsCommand(context));
194988
195273
  }
194989
195274
 
194990
195275
  // src/cli/commands/functions/deploy.ts
@@ -195610,9 +195895,12 @@ function getTypesCommand(context) {
195610
195895
  return new Command("types").description("Manage TypeScript type generation").addCommand(getTypesGenerateCommand(context));
195611
195896
  }
195612
195897
 
195898
+ // src/cli/commands/dev.ts
195899
+ import { dirname as dirname12, join as join16 } from "node:path";
195900
+
195613
195901
  // src/cli/dev/dev-server/main.ts
195614
195902
  var import_cors = __toESM(require_lib4(), 1);
195615
- var import_express = __toESM(require_express(), 1);
195903
+ var import_express2 = __toESM(require_express(), 1);
195616
195904
 
195617
195905
  // node_modules/get-port/index.js
195618
195906
  import net from "node:net";
@@ -195729,13 +196017,232 @@ async function getPorts(options8) {
195729
196017
  }
195730
196018
 
195731
196019
  // src/cli/dev/dev-server/main.ts
196020
+ var import_http_proxy_middleware2 = __toESM(require_dist2(), 1);
196021
+
196022
+ // src/cli/dev/createDevLogger.ts
196023
+ var colorByType = {
196024
+ error: theme.styles.error,
196025
+ warn: theme.styles.warn,
196026
+ log: (text) => text
196027
+ };
196028
+ function createDevLogger() {
196029
+ const print = (type, msg) => {
196030
+ const colorize = colorByType[type];
196031
+ console[type](colorize(msg));
196032
+ };
196033
+ return {
196034
+ log: (msg) => print("log", msg),
196035
+ error: (msg, err) => {
196036
+ print("error", msg);
196037
+ if (err) {
196038
+ print("error", String(err));
196039
+ }
196040
+ },
196041
+ warn: (msg) => print("warn", msg)
196042
+ };
196043
+ }
196044
+
196045
+ // src/cli/dev/dev-server/function-manager.ts
196046
+ import { spawn as spawn2, spawnSync as spawnSync2 } from "node:child_process";
196047
+ import { dirname as dirname11, join as join15 } from "node:path";
196048
+ import { fileURLToPath as fileURLToPath7 } from "node:url";
196049
+ var __dirname5 = dirname11(fileURLToPath7(import.meta.url));
196050
+ var WRAPPER_PATH = join15(__dirname5, "../deno-runtime/main.js");
196051
+ var READY_TIMEOUT = 30000;
196052
+
196053
+ class FunctionManager {
196054
+ functions;
196055
+ running = new Map;
196056
+ starting = new Map;
196057
+ logger;
196058
+ constructor(functions, logger) {
196059
+ this.functions = new Map(functions.map((f7) => [f7.name, f7]));
196060
+ this.logger = logger;
196061
+ if (functions.length > 0) {
196062
+ this.verifyDenoIsInstalled();
196063
+ }
196064
+ }
196065
+ verifyDenoIsInstalled() {
196066
+ const result = spawnSync2("deno", ["--version"]);
196067
+ if (result.error) {
196068
+ throw new DependencyNotFoundError("Deno is required to run functions", {
196069
+ hints: [{ message: "Install Deno from https://deno.com/download" }]
196070
+ });
196071
+ }
196072
+ }
196073
+ getFunctionNames() {
196074
+ return Array.from(this.functions.keys());
196075
+ }
196076
+ async ensureRunning(name2) {
196077
+ const backendFunction = this.functions.get(name2);
196078
+ if (!backendFunction) {
196079
+ throw new InvalidInputError(`Function "${name2}" not found`, {
196080
+ hints: [{ message: "Check available functions in your project" }]
196081
+ });
196082
+ }
196083
+ const existing = this.running.get(name2);
196084
+ if (existing?.ready) {
196085
+ return existing.port;
196086
+ }
196087
+ const pending = this.starting.get(name2);
196088
+ if (pending) {
196089
+ return pending;
196090
+ }
196091
+ const promise2 = this.startFunction(name2, backendFunction);
196092
+ this.starting.set(name2, promise2);
196093
+ try {
196094
+ return await promise2;
196095
+ } finally {
196096
+ this.starting.delete(name2);
196097
+ }
196098
+ }
196099
+ async startFunction(name2, backendFunction) {
196100
+ const port = await this.allocatePort();
196101
+ const process21 = this.spawnFunction(backendFunction, port);
196102
+ const runningFunc = {
196103
+ process: process21,
196104
+ port,
196105
+ ready: false
196106
+ };
196107
+ this.running.set(name2, runningFunc);
196108
+ this.setupProcessHandlers(name2, process21);
196109
+ return this.waitForReady(name2, runningFunc);
196110
+ }
196111
+ stopAll() {
196112
+ for (const [name2, { process: process21 }] of this.running) {
196113
+ this.logger.log(`[dev-server] Stopping function: ${name2}`);
196114
+ process21.kill();
196115
+ }
196116
+ this.running.clear();
196117
+ this.starting.clear();
196118
+ }
196119
+ async allocatePort() {
196120
+ const usedPorts = Array.from(this.running.values()).map((r5) => r5.port);
196121
+ return getPorts({ exclude: usedPorts });
196122
+ }
196123
+ spawnFunction(func, port) {
196124
+ this.logger.log(`[dev-server] Spawning function "${func.name}" on port ${port}`);
196125
+ const process21 = spawn2("deno", ["run", "--allow-all", WRAPPER_PATH], {
196126
+ env: {
196127
+ ...globalThis.process.env,
196128
+ FUNCTION_PATH: func.entryPath,
196129
+ FUNCTION_PORT: String(port),
196130
+ FUNCTION_NAME: func.name
196131
+ },
196132
+ stdio: ["pipe", "pipe", "pipe"]
196133
+ });
196134
+ return process21;
196135
+ }
196136
+ setupProcessHandlers(name2, process21) {
196137
+ process21.stdout?.on("data", (data) => {
196138
+ const lines = data.toString().trim().split(`
196139
+ `);
196140
+ for (const line3 of lines) {
196141
+ this.logger.log(line3);
196142
+ }
196143
+ });
196144
+ process21.stderr?.on("data", (data) => {
196145
+ const lines = data.toString().trim().split(`
196146
+ `);
196147
+ for (const line3 of lines) {
196148
+ this.logger.error(line3);
196149
+ }
196150
+ });
196151
+ process21.on("exit", (code2) => {
196152
+ this.logger.log(`[dev-server] Function "${name2}" exited with code ${code2}`);
196153
+ this.running.delete(name2);
196154
+ });
196155
+ process21.on("error", (error48) => {
196156
+ this.logger.error(`[dev-server] Function "${name2}" error:`, error48);
196157
+ this.running.delete(name2);
196158
+ });
196159
+ }
196160
+ waitForReady(name2, runningFunc) {
196161
+ return new Promise((resolve5, reject) => {
196162
+ runningFunc.process.on("exit", (code2) => {
196163
+ if (!runningFunc.ready) {
196164
+ clearTimeout(timeout3);
196165
+ reject(new InternalError(`Function "${name2}" exited with code ${code2}`, {
196166
+ hints: [{ message: "Check the function code for errors" }]
196167
+ }));
196168
+ }
196169
+ });
196170
+ const timeout3 = setTimeout(() => {
196171
+ runningFunc.process.kill();
196172
+ reject(new InternalError(`Function "${name2}" failed to start within ${READY_TIMEOUT / 1000}s timeout`, {
196173
+ hints: [
196174
+ { message: "Check the function code for startup errors" }
196175
+ ]
196176
+ }));
196177
+ }, READY_TIMEOUT);
196178
+ const onData = (data) => {
196179
+ const output = data.toString();
196180
+ if (output.includes("Listening on")) {
196181
+ runningFunc.ready = true;
196182
+ clearTimeout(timeout3);
196183
+ runningFunc.process.stdout?.off("data", onData);
196184
+ resolve5(runningFunc.port);
196185
+ }
196186
+ };
196187
+ runningFunc.process.stdout?.on("data", onData);
196188
+ });
196189
+ }
196190
+ }
196191
+
196192
+ // src/cli/dev/dev-server/routes/functions.ts
196193
+ var import_express = __toESM(require_express(), 1);
195732
196194
  var import_http_proxy_middleware = __toESM(require_dist2(), 1);
196195
+ import { ServerResponse } from "node:http";
196196
+ function createFunctionRouter(manager, logger) {
196197
+ const router = import_express.Router({ mergeParams: true });
196198
+ const portsByRequest = new WeakMap;
196199
+ const proxy = import_http_proxy_middleware.createProxyMiddleware({
196200
+ router: (req) => `http://localhost:${portsByRequest.get(req)}`,
196201
+ changeOrigin: true,
196202
+ on: {
196203
+ proxyReq: (proxyReq, req) => {
196204
+ const xAppId = req.headers["x-app-id"];
196205
+ if (xAppId) {
196206
+ proxyReq.setHeader("Base44-App-Id", xAppId);
196207
+ }
196208
+ proxyReq.setHeader("Base44-Api-Url", `${req.protocol}://${req.headers.host}`);
196209
+ },
196210
+ error: (err, _req, res) => {
196211
+ logger.error("Function proxy error:", err);
196212
+ if (res instanceof ServerResponse && !res.headersSent) {
196213
+ res.writeHead(502, { "Content-Type": "application/json" });
196214
+ res.end(JSON.stringify({
196215
+ error: "Failed to proxy request to function",
196216
+ details: err.message
196217
+ }));
196218
+ }
196219
+ }
196220
+ }
196221
+ });
196222
+ router.all("/:functionName", async (req, res, next) => {
196223
+ const { functionName } = req.params;
196224
+ try {
196225
+ const port = await manager.ensureRunning(functionName);
196226
+ portsByRequest.set(req, port);
196227
+ next();
196228
+ } catch (error48) {
196229
+ logger.error("Function error:", error48);
196230
+ const message = error48 instanceof Error ? error48.message : String(error48);
196231
+ res.status(500).json({ error: message });
196232
+ }
196233
+ }, proxy);
196234
+ return router;
196235
+ }
196236
+
196237
+ // src/cli/dev/dev-server/main.ts
195733
196238
  var DEFAULT_PORT = 4400;
195734
196239
  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({
196240
+ async function createDevServer(options8) {
196241
+ const { port: userPort } = options8;
196242
+ const port = userPort ?? await getPorts({ port: DEFAULT_PORT });
196243
+ const { functions } = await options8.loadResources();
196244
+ const app = import_express2.default();
196245
+ const remoteProxy = import_http_proxy_middleware2.createProxyMiddleware({
195739
196246
  target: BASE44_APP_URL,
195740
196247
  changeOrigin: true
195741
196248
  });
@@ -195751,6 +196258,13 @@ async function createDevServer(options8 = {}) {
195751
196258
  }
195752
196259
  next();
195753
196260
  });
196261
+ const devLogger = createDevLogger();
196262
+ const functionManager = new FunctionManager(functions, devLogger);
196263
+ if (functionManager.getFunctionNames().length > 0) {
196264
+ R2.info(`Loaded functions: ${functionManager.getFunctionNames().join(", ")}`);
196265
+ const functionRoutes = createFunctionRouter(functionManager, devLogger);
196266
+ app.use("/api/apps/:appId/functions", functionRoutes);
196267
+ }
195754
196268
  app.use((req, res, next) => {
195755
196269
  return remoteProxy(req, res, next);
195756
196270
  });
@@ -195763,6 +196277,12 @@ async function createDevServer(options8 = {}) {
195763
196277
  reject(err);
195764
196278
  }
195765
196279
  } else {
196280
+ const shutdown = () => {
196281
+ functionManager.stopAll();
196282
+ server.close();
196283
+ };
196284
+ process.on("SIGINT", shutdown);
196285
+ process.on("SIGTERM", shutdown);
195766
196286
  resolve5({
195767
196287
  port,
195768
196288
  server
@@ -195775,7 +196295,15 @@ async function createDevServer(options8 = {}) {
195775
196295
  // src/cli/commands/dev.ts
195776
196296
  async function devAction(options8) {
195777
196297
  const port = options8.port ? Number(options8.port) : undefined;
195778
- const { port: resolvedPort } = await createDevServer({ port });
196298
+ const { port: resolvedPort } = await createDevServer({
196299
+ port,
196300
+ loadResources: async () => {
196301
+ const { project: project2 } = await readProjectConfig();
196302
+ const configDir = dirname12(project2.configPath);
196303
+ const functions = await functionResource.readAll(join16(configDir, project2.functionsDir));
196304
+ return { functions };
196305
+ }
196306
+ });
195779
196307
  return {
195780
196308
  outroMessage: `Dev server is available at ${theme.colors.links(`http://localhost:${resolvedPort}`)}`
195781
196309
  };
@@ -195892,7 +196420,7 @@ function createProgram(context) {
195892
196420
  program2.addCommand(getDeployCommand(context));
195893
196421
  program2.addCommand(getLinkCommand(context));
195894
196422
  program2.addCommand(getEjectCommand(context));
195895
- program2.addCommand(getEntitiesPushCommand(context));
196423
+ program2.addCommand(getEntitiesCommand(context));
195896
196424
  program2.addCommand(getAgentsCommand(context));
195897
196425
  program2.addCommand(getConnectorsCommand(context));
195898
196426
  program2.addCommand(getFunctionsDeployCommand(context));
@@ -195937,7 +196465,7 @@ function nanoid3(size = 21) {
195937
196465
  }
195938
196466
 
195939
196467
  // node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
195940
- import { dirname as dirname11, posix, sep } from "path";
196468
+ import { dirname as dirname13, posix, sep } from "path";
195941
196469
  function createModulerModifier() {
195942
196470
  const getModuleFromFileName = createGetModuleFromFilename();
195943
196471
  return async (frames) => {
@@ -195946,7 +196474,7 @@ function createModulerModifier() {
195946
196474
  return frames;
195947
196475
  };
195948
196476
  }
195949
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname11(process.argv[1]) : process.cwd(), isWindows4 = sep === "\\") {
196477
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname13(process.argv[1]) : process.cwd(), isWindows4 = sep === "\\") {
195950
196478
  const normalizedBase = isWindows4 ? normalizeWindowsPath2(basePath) : basePath;
195951
196479
  return (filename) => {
195952
196480
  if (!filename)
@@ -200163,4 +200691,4 @@ export {
200163
200691
  CLIExitError
200164
200692
  };
200165
200693
 
200166
- //# debugId=8FF06F66318A4ACC64756E2164756E21
200694
+ //# debugId=CC4F575130E0CA5564756E2164756E21