@base44-preview/cli 0.0.32-pr.269.2da16d6 → 0.0.33-pr.259.6920cd1

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.object({
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
+ }).passthrough();
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,189 @@ 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/create.ts
195133
+ var import_json52 = __toESM(require_lib(), 1);
195134
+ async function parseRecordData(options) {
195135
+ if (options.data) {
195136
+ try {
195137
+ return import_json52.default.parse(options.data);
195138
+ } catch {
195139
+ throw new InvalidInputError("Invalid JSON in --data flag. Provide valid JSON.", {
195140
+ hints: [
195141
+ {
195142
+ message: `Example: --data '{"name": "John", "email": "john@example.com"}'`
195143
+ }
195144
+ ]
195145
+ });
195146
+ }
195147
+ }
195148
+ if (options.file) {
195149
+ const content = await readTextFile(options.file);
195150
+ try {
195151
+ return import_json52.default.parse(content);
195152
+ } catch {
195153
+ throw new InvalidInputError(`Invalid JSON in file ${options.file}. Provide a valid JSON/JSONC file.`);
195154
+ }
195155
+ }
195156
+ throw new InvalidInputError("Provide record data with --data or --file flag", {
195157
+ hints: [
195158
+ {
195159
+ message: `Example: --data '{"name": "John"}' or --file record.json`
195160
+ }
195161
+ ]
195162
+ });
195163
+ }
195164
+ async function createRecordAction(entityName, options) {
195165
+ const data = await parseRecordData(options);
195166
+ const record2 = await runTask(`Creating ${entityName} record...`, async () => {
195167
+ return await createRecord(entityName, data);
195168
+ }, {
195169
+ successMessage: `Created ${entityName} record`,
195170
+ errorMessage: `Failed to create ${entityName} record`
195171
+ });
195172
+ R2.success(`Record created with ID: ${record2.id}`);
195173
+ process.stdout.write(`${JSON.stringify(record2, null, 2)}
195174
+ `);
195175
+ return {};
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
+ R2.success(`Record ${recordId} deleted`);
195200
+ return {};
195201
+ }
195202
+ function getRecordsDeleteCommand(context) {
195203
+ 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) => {
195204
+ await runCommand(() => deleteRecordAction(entityName, recordId, options), { requireAuth: true }, context);
195205
+ });
195206
+ }
195207
+
195208
+ // src/cli/commands/entities/records/get.ts
195209
+ async function getRecordAction(entityName, recordId) {
195210
+ const record2 = await runTask(`Fetching ${entityName} record...`, async () => {
195211
+ return await getRecord(entityName, recordId);
195212
+ }, {
195213
+ successMessage: `Fetched ${entityName} record`,
195214
+ errorMessage: `Failed to fetch ${entityName} record`
195215
+ });
195216
+ process.stdout.write(`${JSON.stringify(record2, null, 2)}
195217
+ `);
195218
+ return {};
195219
+ }
195220
+ function getRecordsGetCommand(context) {
195221
+ 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) => {
195222
+ await runCommand(() => getRecordAction(entityName, recordId), { requireAuth: true }, context);
195223
+ });
195224
+ }
195225
+
195226
+ // src/cli/commands/entities/records/list.ts
195227
+ async function listRecordsAction(entityName, options) {
195228
+ const records = await runTask(`Fetching ${entityName} records...`, async () => {
195229
+ return await listRecords(entityName, {
195230
+ filter: options.filter,
195231
+ sort: options.sort,
195232
+ limit: options.limit ? Number(options.limit) : 50,
195233
+ skip: options.skip ? Number(options.skip) : undefined,
195234
+ fields: options.fields
195235
+ });
195236
+ }, {
195237
+ successMessage: `Fetched ${entityName} records`,
195238
+ errorMessage: `Failed to fetch ${entityName} records`
195239
+ });
195240
+ R2.info(`Found ${records.length} record(s)`);
195241
+ process.stdout.write(`${JSON.stringify(records, null, 2)}
195242
+ `);
195243
+ return {};
195244
+ }
195245
+ function getRecordsListCommand(context) {
195246
+ return new Command("list").description("List entity records").argument("<entity-name>", "Name of the entity (e.g. Users, Products)").option("-f, --filter <json>", "JSON query filter").option("-s, --sort <field>", "Sort field (prefix with - for descending)").option("-l, --limit <n>", "Max records to return", "50").option("--skip <n>", "Number of records to skip").option("--fields <fields>", "Comma-separated fields to return").action(async (entityName, options) => {
195247
+ await runCommand(() => listRecordsAction(entityName, options), { requireAuth: true }, context);
195248
+ });
195249
+ }
195250
+
195251
+ // src/cli/commands/entities/records/update.ts
195252
+ var import_json53 = __toESM(require_lib(), 1);
195253
+ async function parseUpdateData(options) {
195254
+ if (options.data) {
195255
+ try {
195256
+ return import_json53.default.parse(options.data);
195257
+ } catch {
195258
+ throw new InvalidInputError("Invalid JSON in --data flag. Provide valid JSON.", {
195259
+ hints: [
195260
+ {
195261
+ message: `Example: --data '{"status": "active"}'`
195262
+ }
195263
+ ]
195264
+ });
195265
+ }
195266
+ }
195267
+ if (options.file) {
195268
+ const content = await readTextFile(options.file);
195269
+ try {
195270
+ return import_json53.default.parse(content);
195271
+ } catch {
195272
+ throw new InvalidInputError(`Invalid JSON in file ${options.file}. Provide a valid JSON/JSONC file.`);
195273
+ }
195274
+ }
195275
+ throw new InvalidInputError("Provide update data with --data or --file flag", {
195276
+ hints: [
195277
+ {
195278
+ message: `Example: --data '{"status": "active"}' or --file update.json`
195279
+ }
195280
+ ]
195281
+ });
195282
+ }
195283
+ async function updateRecordAction(entityName, recordId, options) {
195284
+ const data = await parseUpdateData(options);
195285
+ const record2 = await runTask(`Updating ${entityName} record...`, async () => {
195286
+ return await updateRecord(entityName, recordId, data);
195287
+ }, {
195288
+ successMessage: `Updated ${entityName} record`,
195289
+ errorMessage: `Failed to update ${entityName} record`
195290
+ });
195291
+ R2.success(`Record ${recordId} updated`);
195292
+ process.stdout.write(`${JSON.stringify(record2, null, 2)}
195293
+ `);
195294
+ return {};
195295
+ }
195296
+ function getRecordsUpdateCommand(context) {
195297
+ 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) => {
195298
+ await runCommand(() => updateRecordAction(entityName, recordId, options), { requireAuth: true }, context);
195299
+ });
195300
+ }
195301
+
195302
+ // src/cli/commands/entities/records/index.ts
195303
+ function getRecordsCommand(context) {
195304
+ 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));
195305
+ }
195306
+
195307
+ // src/cli/commands/entities/index.ts
195308
+ function getEntitiesCommand(context) {
195309
+ return new Command("entities").description("Manage project entities").addCommand(getEntitiesPushCommand(context)).addCommand(getRecordsCommand(context));
194988
195310
  }
194989
195311
 
194990
195312
  // src/cli/commands/functions/deploy.ts
@@ -195610,9 +195932,12 @@ function getTypesCommand(context) {
195610
195932
  return new Command("types").description("Manage TypeScript type generation").addCommand(getTypesGenerateCommand(context));
195611
195933
  }
195612
195934
 
195935
+ // src/cli/commands/dev.ts
195936
+ import { dirname as dirname12, join as join16 } from "node:path";
195937
+
195613
195938
  // src/cli/dev/dev-server/main.ts
195614
195939
  var import_cors = __toESM(require_lib4(), 1);
195615
- var import_express = __toESM(require_express(), 1);
195940
+ var import_express2 = __toESM(require_express(), 1);
195616
195941
 
195617
195942
  // node_modules/get-port/index.js
195618
195943
  import net from "node:net";
@@ -195729,13 +196054,232 @@ async function getPorts(options8) {
195729
196054
  }
195730
196055
 
195731
196056
  // src/cli/dev/dev-server/main.ts
196057
+ var import_http_proxy_middleware2 = __toESM(require_dist2(), 1);
196058
+
196059
+ // src/cli/dev/createDevLogger.ts
196060
+ var colorByType = {
196061
+ error: theme.styles.error,
196062
+ warn: theme.styles.warn,
196063
+ log: (text) => text
196064
+ };
196065
+ function createDevLogger() {
196066
+ const print = (type, msg) => {
196067
+ const colorize = colorByType[type];
196068
+ console[type](colorize(msg));
196069
+ };
196070
+ return {
196071
+ log: (msg) => print("log", msg),
196072
+ error: (msg, err) => {
196073
+ print("error", msg);
196074
+ if (err) {
196075
+ print("error", String(err));
196076
+ }
196077
+ },
196078
+ warn: (msg) => print("warn", msg)
196079
+ };
196080
+ }
196081
+
196082
+ // src/cli/dev/dev-server/function-manager.ts
196083
+ import { spawn as spawn2, spawnSync as spawnSync2 } from "node:child_process";
196084
+ import { dirname as dirname11, join as join15 } from "node:path";
196085
+ import { fileURLToPath as fileURLToPath7 } from "node:url";
196086
+ var __dirname5 = dirname11(fileURLToPath7(import.meta.url));
196087
+ var WRAPPER_PATH = join15(__dirname5, "../deno-runtime/main.js");
196088
+ var READY_TIMEOUT = 30000;
196089
+
196090
+ class FunctionManager {
196091
+ functions;
196092
+ running = new Map;
196093
+ starting = new Map;
196094
+ logger;
196095
+ constructor(functions, logger) {
196096
+ this.functions = new Map(functions.map((f7) => [f7.name, f7]));
196097
+ this.logger = logger;
196098
+ if (functions.length > 0) {
196099
+ this.verifyDenoIsInstalled();
196100
+ }
196101
+ }
196102
+ verifyDenoIsInstalled() {
196103
+ const result = spawnSync2("deno", ["--version"]);
196104
+ if (result.error) {
196105
+ throw new DependencyNotFoundError("Deno is required to run functions", {
196106
+ hints: [{ message: "Install Deno from https://deno.com/download" }]
196107
+ });
196108
+ }
196109
+ }
196110
+ getFunctionNames() {
196111
+ return Array.from(this.functions.keys());
196112
+ }
196113
+ async ensureRunning(name2) {
196114
+ const backendFunction = this.functions.get(name2);
196115
+ if (!backendFunction) {
196116
+ throw new InvalidInputError(`Function "${name2}" not found`, {
196117
+ hints: [{ message: "Check available functions in your project" }]
196118
+ });
196119
+ }
196120
+ const existing = this.running.get(name2);
196121
+ if (existing?.ready) {
196122
+ return existing.port;
196123
+ }
196124
+ const pending = this.starting.get(name2);
196125
+ if (pending) {
196126
+ return pending;
196127
+ }
196128
+ const promise2 = this.startFunction(name2, backendFunction);
196129
+ this.starting.set(name2, promise2);
196130
+ try {
196131
+ return await promise2;
196132
+ } finally {
196133
+ this.starting.delete(name2);
196134
+ }
196135
+ }
196136
+ async startFunction(name2, backendFunction) {
196137
+ const port = await this.allocatePort();
196138
+ const process21 = this.spawnFunction(backendFunction, port);
196139
+ const runningFunc = {
196140
+ process: process21,
196141
+ port,
196142
+ ready: false
196143
+ };
196144
+ this.running.set(name2, runningFunc);
196145
+ this.setupProcessHandlers(name2, process21);
196146
+ return this.waitForReady(name2, runningFunc);
196147
+ }
196148
+ stopAll() {
196149
+ for (const [name2, { process: process21 }] of this.running) {
196150
+ this.logger.log(`[dev-server] Stopping function: ${name2}`);
196151
+ process21.kill();
196152
+ }
196153
+ this.running.clear();
196154
+ this.starting.clear();
196155
+ }
196156
+ async allocatePort() {
196157
+ const usedPorts = Array.from(this.running.values()).map((r5) => r5.port);
196158
+ return getPorts({ exclude: usedPorts });
196159
+ }
196160
+ spawnFunction(func, port) {
196161
+ this.logger.log(`[dev-server] Spawning function "${func.name}" on port ${port}`);
196162
+ const process21 = spawn2("deno", ["run", "--allow-all", WRAPPER_PATH], {
196163
+ env: {
196164
+ ...globalThis.process.env,
196165
+ FUNCTION_PATH: func.entryPath,
196166
+ FUNCTION_PORT: String(port),
196167
+ FUNCTION_NAME: func.name
196168
+ },
196169
+ stdio: ["pipe", "pipe", "pipe"]
196170
+ });
196171
+ return process21;
196172
+ }
196173
+ setupProcessHandlers(name2, process21) {
196174
+ process21.stdout?.on("data", (data) => {
196175
+ const lines = data.toString().trim().split(`
196176
+ `);
196177
+ for (const line3 of lines) {
196178
+ this.logger.log(line3);
196179
+ }
196180
+ });
196181
+ process21.stderr?.on("data", (data) => {
196182
+ const lines = data.toString().trim().split(`
196183
+ `);
196184
+ for (const line3 of lines) {
196185
+ this.logger.error(line3);
196186
+ }
196187
+ });
196188
+ process21.on("exit", (code2) => {
196189
+ this.logger.log(`[dev-server] Function "${name2}" exited with code ${code2}`);
196190
+ this.running.delete(name2);
196191
+ });
196192
+ process21.on("error", (error48) => {
196193
+ this.logger.error(`[dev-server] Function "${name2}" error:`, error48);
196194
+ this.running.delete(name2);
196195
+ });
196196
+ }
196197
+ waitForReady(name2, runningFunc) {
196198
+ return new Promise((resolve5, reject) => {
196199
+ runningFunc.process.on("exit", (code2) => {
196200
+ if (!runningFunc.ready) {
196201
+ clearTimeout(timeout3);
196202
+ reject(new InternalError(`Function "${name2}" exited with code ${code2}`, {
196203
+ hints: [{ message: "Check the function code for errors" }]
196204
+ }));
196205
+ }
196206
+ });
196207
+ const timeout3 = setTimeout(() => {
196208
+ runningFunc.process.kill();
196209
+ reject(new InternalError(`Function "${name2}" failed to start within ${READY_TIMEOUT / 1000}s timeout`, {
196210
+ hints: [
196211
+ { message: "Check the function code for startup errors" }
196212
+ ]
196213
+ }));
196214
+ }, READY_TIMEOUT);
196215
+ const onData = (data) => {
196216
+ const output = data.toString();
196217
+ if (output.includes("Listening on")) {
196218
+ runningFunc.ready = true;
196219
+ clearTimeout(timeout3);
196220
+ runningFunc.process.stdout?.off("data", onData);
196221
+ resolve5(runningFunc.port);
196222
+ }
196223
+ };
196224
+ runningFunc.process.stdout?.on("data", onData);
196225
+ });
196226
+ }
196227
+ }
196228
+
196229
+ // src/cli/dev/dev-server/routes/functions.ts
196230
+ var import_express = __toESM(require_express(), 1);
195732
196231
  var import_http_proxy_middleware = __toESM(require_dist2(), 1);
196232
+ import { ServerResponse } from "node:http";
196233
+ function createFunctionRouter(manager, logger) {
196234
+ const router = import_express.Router({ mergeParams: true });
196235
+ const portsByRequest = new WeakMap;
196236
+ const proxy = import_http_proxy_middleware.createProxyMiddleware({
196237
+ router: (req) => `http://localhost:${portsByRequest.get(req)}`,
196238
+ changeOrigin: true,
196239
+ on: {
196240
+ proxyReq: (proxyReq, req) => {
196241
+ const xAppId = req.headers["x-app-id"];
196242
+ if (xAppId) {
196243
+ proxyReq.setHeader("Base44-App-Id", xAppId);
196244
+ }
196245
+ proxyReq.setHeader("Base44-Api-Url", `${req.protocol}://${req.headers.host}`);
196246
+ },
196247
+ error: (err, _req, res) => {
196248
+ logger.error("Function proxy error:", err);
196249
+ if (res instanceof ServerResponse && !res.headersSent) {
196250
+ res.writeHead(502, { "Content-Type": "application/json" });
196251
+ res.end(JSON.stringify({
196252
+ error: "Failed to proxy request to function",
196253
+ details: err.message
196254
+ }));
196255
+ }
196256
+ }
196257
+ }
196258
+ });
196259
+ router.all("/:functionName", async (req, res, next) => {
196260
+ const { functionName } = req.params;
196261
+ try {
196262
+ const port = await manager.ensureRunning(functionName);
196263
+ portsByRequest.set(req, port);
196264
+ next();
196265
+ } catch (error48) {
196266
+ logger.error("Function error:", error48);
196267
+ const message = error48 instanceof Error ? error48.message : String(error48);
196268
+ res.status(500).json({ error: message });
196269
+ }
196270
+ }, proxy);
196271
+ return router;
196272
+ }
196273
+
196274
+ // src/cli/dev/dev-server/main.ts
195733
196275
  var DEFAULT_PORT = 4400;
195734
196276
  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({
196277
+ async function createDevServer(options8) {
196278
+ const { port: userPort } = options8;
196279
+ const port = userPort ?? await getPorts({ port: DEFAULT_PORT });
196280
+ const { functions } = await options8.loadResources();
196281
+ const app = import_express2.default();
196282
+ const remoteProxy = import_http_proxy_middleware2.createProxyMiddleware({
195739
196283
  target: BASE44_APP_URL,
195740
196284
  changeOrigin: true
195741
196285
  });
@@ -195751,6 +196295,13 @@ async function createDevServer(options8 = {}) {
195751
196295
  }
195752
196296
  next();
195753
196297
  });
196298
+ const devLogger = createDevLogger();
196299
+ const functionManager = new FunctionManager(functions, devLogger);
196300
+ if (functionManager.getFunctionNames().length > 0) {
196301
+ R2.info(`Loaded functions: ${functionManager.getFunctionNames().join(", ")}`);
196302
+ const functionRoutes = createFunctionRouter(functionManager, devLogger);
196303
+ app.use("/api/apps/:appId/functions", functionRoutes);
196304
+ }
195754
196305
  app.use((req, res, next) => {
195755
196306
  return remoteProxy(req, res, next);
195756
196307
  });
@@ -195763,6 +196314,12 @@ async function createDevServer(options8 = {}) {
195763
196314
  reject(err);
195764
196315
  }
195765
196316
  } else {
196317
+ const shutdown = () => {
196318
+ functionManager.stopAll();
196319
+ server.close();
196320
+ };
196321
+ process.on("SIGINT", shutdown);
196322
+ process.on("SIGTERM", shutdown);
195766
196323
  resolve5({
195767
196324
  port,
195768
196325
  server
@@ -195775,7 +196332,15 @@ async function createDevServer(options8 = {}) {
195775
196332
  // src/cli/commands/dev.ts
195776
196333
  async function devAction(options8) {
195777
196334
  const port = options8.port ? Number(options8.port) : undefined;
195778
- const { port: resolvedPort } = await createDevServer({ port });
196335
+ const { port: resolvedPort } = await createDevServer({
196336
+ port,
196337
+ loadResources: async () => {
196338
+ const { project: project2 } = await readProjectConfig();
196339
+ const configDir = dirname12(project2.configPath);
196340
+ const functions = await functionResource.readAll(join16(configDir, project2.functionsDir));
196341
+ return { functions };
196342
+ }
196343
+ });
195779
196344
  return {
195780
196345
  outroMessage: `Dev server is available at ${theme.colors.links(`http://localhost:${resolvedPort}`)}`
195781
196346
  };
@@ -195892,7 +196457,7 @@ function createProgram(context) {
195892
196457
  program2.addCommand(getDeployCommand(context));
195893
196458
  program2.addCommand(getLinkCommand(context));
195894
196459
  program2.addCommand(getEjectCommand(context));
195895
- program2.addCommand(getEntitiesPushCommand(context));
196460
+ program2.addCommand(getEntitiesCommand(context));
195896
196461
  program2.addCommand(getAgentsCommand(context));
195897
196462
  program2.addCommand(getConnectorsCommand(context));
195898
196463
  program2.addCommand(getFunctionsDeployCommand(context));
@@ -195937,7 +196502,7 @@ function nanoid3(size = 21) {
195937
196502
  }
195938
196503
 
195939
196504
  // node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
195940
- import { dirname as dirname11, posix, sep } from "path";
196505
+ import { dirname as dirname13, posix, sep } from "path";
195941
196506
  function createModulerModifier() {
195942
196507
  const getModuleFromFileName = createGetModuleFromFilename();
195943
196508
  return async (frames) => {
@@ -195946,7 +196511,7 @@ function createModulerModifier() {
195946
196511
  return frames;
195947
196512
  };
195948
196513
  }
195949
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname11(process.argv[1]) : process.cwd(), isWindows4 = sep === "\\") {
196514
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname13(process.argv[1]) : process.cwd(), isWindows4 = sep === "\\") {
195950
196515
  const normalizedBase = isWindows4 ? normalizeWindowsPath2(basePath) : basePath;
195951
196516
  return (filename) => {
195952
196517
  if (!filename)
@@ -200163,4 +200728,4 @@ export {
200163
200728
  CLIExitError
200164
200729
  };
200165
200730
 
200166
- //# debugId=8FF06F66318A4ACC64756E2164756E21
200731
+ //# debugId=4D663D484D24768B64756E2164756E21