@base44-preview/cli 0.0.44-pr.417.2c58950 → 0.0.45-pr.370.7a9aac7

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
@@ -16459,7 +16459,7 @@ var require_lodash = __commonJS((exports, module) => {
16459
16459
  }
16460
16460
  return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined2, comparator) : [];
16461
16461
  });
16462
- function join10(array2, separator) {
16462
+ function join11(array2, separator) {
16463
16463
  return array2 == null ? "" : nativeJoin.call(array2, separator);
16464
16464
  }
16465
16465
  function last(array2) {
@@ -16481,7 +16481,7 @@ var require_lodash = __commonJS((exports, module) => {
16481
16481
  function nth(array2, n2) {
16482
16482
  return array2 && array2.length ? baseNth(array2, toInteger(n2)) : undefined2;
16483
16483
  }
16484
- var pull2 = baseRest(pullAll);
16484
+ var pull3 = baseRest(pullAll);
16485
16485
  function pullAll(array2, values2) {
16486
16486
  return array2 && array2.length && values2 && values2.length ? basePullAll(array2, values2) : array2;
16487
16487
  }
@@ -18246,7 +18246,7 @@ __p += '`;
18246
18246
  lodash.pickBy = pickBy;
18247
18247
  lodash.property = property;
18248
18248
  lodash.propertyOf = propertyOf;
18249
- lodash.pull = pull2;
18249
+ lodash.pull = pull3;
18250
18250
  lodash.pullAll = pullAll;
18251
18251
  lodash.pullAllBy = pullAllBy;
18252
18252
  lodash.pullAllWith = pullAllWith;
@@ -18391,7 +18391,7 @@ __p += '`;
18391
18391
  lodash.isUndefined = isUndefined;
18392
18392
  lodash.isWeakMap = isWeakMap;
18393
18393
  lodash.isWeakSet = isWeakSet;
18394
- lodash.join = join10;
18394
+ lodash.join = join11;
18395
18395
  lodash.kebabCase = kebabCase;
18396
18396
  lodash.last = last;
18397
18397
  lodash.lastIndexOf = lastIndexOf;
@@ -27503,7 +27503,7 @@ function cleanDoc(doc2) {
27503
27503
  return mapDoc(doc2, (currentDoc) => cleanDocFn(currentDoc));
27504
27504
  }
27505
27505
  function replaceEndOfLine(doc2, replacement = literalline) {
27506
- return mapDoc(doc2, (currentDoc) => typeof currentDoc === "string" ? join13(replacement, currentDoc.split(`
27506
+ return mapDoc(doc2, (currentDoc) => typeof currentDoc === "string" ? join15(replacement, currentDoc.split(`
27507
27507
  `)) : currentDoc);
27508
27508
  }
27509
27509
  function canBreakFn(doc2) {
@@ -27583,7 +27583,7 @@ function indentIfBreak(contents, options) {
27583
27583
  negate: options.negate
27584
27584
  };
27585
27585
  }
27586
- function join13(separator, docs) {
27586
+ function join15(separator, docs) {
27587
27587
  assertDoc(separator);
27588
27588
  assertDocArray(docs);
27589
27589
  const parts = [];
@@ -28294,7 +28294,7 @@ var init_doc = __esm(() => {
28294
28294
  MODE_FLAT = Symbol("MODE_FLAT");
28295
28295
  DOC_FILL_PRINTED_LENGTH = Symbol("DOC_FILL_PRINTED_LENGTH");
28296
28296
  builders = {
28297
- join: join13,
28297
+ join: join15,
28298
28298
  line,
28299
28299
  softline,
28300
28300
  hardline,
@@ -133208,7 +133208,7 @@ Expected it to be ${EXPECTED_TYPE_VALUES}.`;
133208
133208
  return mapDoc2(doc2, (currentDoc) => cleanDocFn2(currentDoc));
133209
133209
  }
133210
133210
  function replaceEndOfLine2(doc2, replacement = literalline2) {
133211
- return mapDoc2(doc2, (currentDoc) => typeof currentDoc === "string" ? join15(replacement, currentDoc.split(`
133211
+ return mapDoc2(doc2, (currentDoc) => typeof currentDoc === "string" ? join17(replacement, currentDoc.split(`
133212
133212
  `)) : currentDoc);
133213
133213
  }
133214
133214
  function canBreakFn2(doc2) {
@@ -133294,7 +133294,7 @@ Expected it to be ${EXPECTED_TYPE_VALUES}.`;
133294
133294
  negate: options8.negate
133295
133295
  };
133296
133296
  }
133297
- function join15(separator, docs) {
133297
+ function join17(separator, docs) {
133298
133298
  assertDoc2(separator);
133299
133299
  assertDocArray2(docs);
133300
133300
  const parts = [];
@@ -133959,7 +133959,7 @@ Expected it to be ${EXPECTED_TYPE_VALUES}.`;
133959
133959
  }
133960
133960
  }
133961
133961
  var builders2 = {
133962
- join: join15,
133962
+ join: join17,
133963
133963
  line: line3,
133964
133964
  softline: softline2,
133965
133965
  hardline: hardline4,
@@ -160399,10 +160399,10 @@ var require_view = __commonJS((exports, module) => {
160399
160399
  var debug = require_src4()("express:view");
160400
160400
  var path18 = __require("node:path");
160401
160401
  var fs28 = __require("node:fs");
160402
- var dirname11 = path18.dirname;
160402
+ var dirname12 = path18.dirname;
160403
160403
  var basename4 = path18.basename;
160404
160404
  var extname2 = path18.extname;
160405
- var join16 = path18.join;
160405
+ var join18 = path18.join;
160406
160406
  var resolve6 = path18.resolve;
160407
160407
  module.exports = View;
160408
160408
  function View(name2, options8) {
@@ -160438,7 +160438,7 @@ var require_view = __commonJS((exports, module) => {
160438
160438
  for (var i5 = 0;i5 < roots.length && !path19; i5++) {
160439
160439
  var root2 = roots[i5];
160440
160440
  var loc = resolve6(root2, name2);
160441
- var dir = dirname11(loc);
160441
+ var dir = dirname12(loc);
160442
160442
  var file2 = basename4(loc);
160443
160443
  path19 = this.resolve(dir, file2);
160444
160444
  }
@@ -160464,12 +160464,12 @@ var require_view = __commonJS((exports, module) => {
160464
160464
  };
160465
160465
  View.prototype.resolve = function resolve7(dir, file2) {
160466
160466
  var ext = this.ext;
160467
- var path19 = join16(dir, file2);
160467
+ var path19 = join18(dir, file2);
160468
160468
  var stat2 = tryStat(path19);
160469
160469
  if (stat2 && stat2.isFile()) {
160470
160470
  return path19;
160471
160471
  }
160472
- path19 = join16(dir, basename4(file2, ext), "index" + ext);
160472
+ path19 = join18(dir, basename4(file2, ext), "index" + ext);
160473
160473
  stat2 = tryStat(path19);
160474
160474
  if (stat2 && stat2.isFile()) {
160475
160475
  return path19;
@@ -164164,7 +164164,7 @@ var require_send = __commonJS((exports, module) => {
164164
164164
  var Stream2 = __require("stream");
164165
164165
  var util2 = __require("util");
164166
164166
  var extname2 = path18.extname;
164167
- var join16 = path18.join;
164167
+ var join18 = path18.join;
164168
164168
  var normalize = path18.normalize;
164169
164169
  var resolve6 = path18.resolve;
164170
164170
  var sep = path18.sep;
@@ -164336,7 +164336,7 @@ var require_send = __commonJS((exports, module) => {
164336
164336
  return res;
164337
164337
  }
164338
164338
  parts = path19.split(sep);
164339
- path19 = normalize(join16(root2, path19));
164339
+ path19 = normalize(join18(root2, path19));
164340
164340
  } else {
164341
164341
  if (UP_PATH_REGEXP.test(path19)) {
164342
164342
  debug('malicious path "%s"', path19);
@@ -164476,7 +164476,7 @@ var require_send = __commonJS((exports, module) => {
164476
164476
  return self2.onStatError(err);
164477
164477
  return self2.error(404);
164478
164478
  }
164479
- var p4 = join16(path19, self2._index[i5]);
164479
+ var p4 = join18(path19, self2._index[i5]);
164480
164480
  debug('stat "%s"', p4);
164481
164481
  fs28.stat(p4, function(err2, stat2) {
164482
164482
  if (err2)
@@ -211071,7 +211071,7 @@ var require_buffer_list = __commonJS((exports, module) => {
211071
211071
  }
211072
211072
  }, {
211073
211073
  key: "join",
211074
- value: function join16(s5) {
211074
+ value: function join18(s5) {
211075
211075
  if (this.length === 0)
211076
211076
  return "";
211077
211077
  var p4 = this.head;
@@ -214782,7 +214782,7 @@ var require_dist5 = __commonJS((exports, module) => {
214782
214782
  });
214783
214783
 
214784
214784
  // src/cli/index.ts
214785
- import { dirname as dirname15, join as join19 } from "node:path";
214785
+ import { dirname as dirname16, join as join21 } from "node:path";
214786
214786
  import { fileURLToPath as fileURLToPath6 } from "node:url";
214787
214787
 
214788
214788
  // ../../node_modules/commander/esm.mjs
@@ -214802,7 +214802,7 @@ var {
214802
214802
  } = import__.default;
214803
214803
 
214804
214804
  // src/cli/commands/agents/pull.ts
214805
- import { dirname as dirname7, join as join10 } from "node:path";
214805
+ import { dirname as dirname7, join as join11 } from "node:path";
214806
214806
 
214807
214807
  // ../../node_modules/@clack/core/dist/index.mjs
214808
214808
  var import_picocolors = __toESM(require_picocolors(), 1);
@@ -230321,11 +230321,15 @@ var SiteConfigSchema = exports_external.object({
230321
230321
  outputDirectory: exports_external.string().optional(),
230322
230322
  installCommand: exports_external.string().optional()
230323
230323
  });
230324
+ var VisibilitySchema = exports_external.enum(["public", "private"], {
230325
+ error: 'Invalid visibility value. Allowed values: "public", "private"'
230326
+ });
230324
230327
  var ProjectConfigSchema = exports_external.object({
230325
230328
  name: exports_external.string({
230326
230329
  error: "App name cannot be empty"
230327
230330
  }).min(1, "App name cannot be empty"),
230328
230331
  description: exports_external.string().optional(),
230332
+ visibility: VisibilitySchema.optional(),
230329
230333
  site: SiteConfigSchema.optional(),
230330
230334
  entitiesDir: exports_external.string().optional().default("entities"),
230331
230335
  functionsDir: exports_external.string().optional().default("functions"),
@@ -236365,7 +236369,7 @@ async function createProject(projectName, description) {
236365
236369
  name: projectName,
236366
236370
  user_description: description ?? `Backend for '${projectName}'`,
236367
236371
  is_managed_source_code: false,
236368
- public_settings: "public_without_login"
236372
+ public_settings: "private"
236369
236373
  }
236370
236374
  });
236371
236375
  } catch (error48) {
@@ -236379,6 +236383,22 @@ async function createProject(projectName, description) {
236379
236383
  projectId: result.data.id
236380
236384
  };
236381
236385
  }
236386
+ var VISIBILITY_TO_PUBLIC_SETTINGS = {
236387
+ public: "public_without_login",
236388
+ private: "private"
236389
+ };
236390
+ async function updateProjectVisibility(visibility) {
236391
+ const appClient = getAppClient();
236392
+ try {
236393
+ await appClient.patch("", {
236394
+ json: {
236395
+ public_settings: VISIBILITY_TO_PUBLIC_SETTINGS[visibility]
236396
+ }
236397
+ });
236398
+ } catch (error48) {
236399
+ throw await ApiError.fromHttpError(error48, "updating project visibility");
236400
+ }
236401
+ }
236382
236402
  async function listProjects() {
236383
236403
  let response;
236384
236404
  try {
@@ -237317,7 +237337,7 @@ var generateGlobTasks = normalizeArguments(generateTasks);
237317
237337
  var generateGlobTasksSync = normalizeArgumentsSync(generateTasksSync);
237318
237338
 
237319
237339
  // src/core/project/config.ts
237320
- import { dirname as dirname5, join as join6 } from "node:path";
237340
+ import { dirname as dirname5, join as join7 } from "node:path";
237321
237341
 
237322
237342
  // src/core/resources/agent/schema.ts
237323
237343
  var EntityOperationSchema = exports_external.enum(["create", "update", "delete", "read"]);
@@ -238100,7 +238120,7 @@ var FieldRLSSchema = exports_external.looseObject({
238100
238120
  delete: RLSRuleSchema.optional()
238101
238121
  });
238102
238122
  var PropertyDefinitionSchema = exports_external.looseObject({
238103
- type: exports_external.string().optional(),
238123
+ type: exports_external.string(),
238104
238124
  title: exports_external.string().optional(),
238105
238125
  description: exports_external.string().optional(),
238106
238126
  minLength: exports_external.number().int().min(0).optional(),
@@ -238249,11 +238269,24 @@ var BackendFunctionSchema = FunctionConfigSchema.extend({
238249
238269
  entryPath: exports_external.string().min(1, "Entry path cannot be empty"),
238250
238270
  filePaths: exports_external.array(exports_external.string()).min(1, "Function must have at least one file")
238251
238271
  });
238252
- var DeployFunctionsResponseSchema = exports_external.object({
238253
- deployed: exports_external.array(exports_external.string()),
238254
- deleted: exports_external.array(exports_external.string()),
238255
- skipped: exports_external.array(exports_external.string()).optional().nullable(),
238256
- errors: exports_external.array(exports_external.object({ name: exports_external.string(), message: exports_external.string() })).nullable()
238272
+ var DeploySingleFunctionResponseSchema = exports_external.object({
238273
+ status: exports_external.enum(["deployed", "unchanged"])
238274
+ });
238275
+ var FunctionInfoSchema = exports_external.object({
238276
+ name: exports_external.string(),
238277
+ deployment_id: exports_external.string(),
238278
+ entry: exports_external.string(),
238279
+ files: exports_external.array(FunctionFileSchema),
238280
+ automations: exports_external.array(AutomationSchema)
238281
+ }).transform((data) => ({
238282
+ name: data.name,
238283
+ deploymentId: data.deployment_id,
238284
+ entry: data.entry,
238285
+ files: data.files,
238286
+ automations: data.automations
238287
+ }));
238288
+ var ListFunctionsResponseSchema = exports_external.object({
238289
+ functions: exports_external.array(FunctionInfoSchema)
238257
238290
  });
238258
238291
  var LogLevelSchema = exports_external.enum(["info", "warning", "error", "debug"]);
238259
238292
  var FunctionLogEntrySchema = exports_external.object({
@@ -238264,29 +238297,39 @@ var FunctionLogEntrySchema = exports_external.object({
238264
238297
  var FunctionLogsResponseSchema = exports_external.array(FunctionLogEntrySchema);
238265
238298
 
238266
238299
  // src/core/resources/function/api.ts
238267
- function toDeployPayloadItem(fn) {
238268
- return {
238269
- name: fn.name,
238270
- entry: fn.entry,
238271
- files: fn.files,
238272
- automations: fn.automations
238273
- };
238274
- }
238275
- async function deployFunctions(functions) {
238300
+ async function deploySingleFunction(name2, payload) {
238276
238301
  const appClient = getAppClient();
238277
- const payload = {
238278
- functions: functions.map(toDeployPayloadItem)
238279
- };
238280
238302
  let response;
238281
238303
  try {
238282
- response = await appClient.put("backend-functions", {
238283
- json: payload,
238284
- timeout: false
238304
+ response = await appClient.put(`backend-functions/${encodeURIComponent(name2)}`, { json: payload, timeout: false });
238305
+ } catch (error48) {
238306
+ throw await ApiError.fromHttpError(error48, `deploying function "${name2}"`);
238307
+ }
238308
+ const result = DeploySingleFunctionResponseSchema.safeParse(await response.json());
238309
+ if (!result.success) {
238310
+ throw new SchemaValidationError("Invalid response from server", result.error);
238311
+ }
238312
+ return result.data;
238313
+ }
238314
+ async function deleteSingleFunction(name2) {
238315
+ const appClient = getAppClient();
238316
+ try {
238317
+ await appClient.delete(`backend-functions/${encodeURIComponent(name2)}`, {
238318
+ timeout: 60000
238285
238319
  });
238286
238320
  } catch (error48) {
238287
- throw await ApiError.fromHttpError(error48, "deploying functions");
238321
+ throw await ApiError.fromHttpError(error48, `deleting function "${name2}"`);
238288
238322
  }
238289
- const result = DeployFunctionsResponseSchema.safeParse(await response.json());
238323
+ }
238324
+ async function listDeployedFunctions() {
238325
+ const appClient = getAppClient();
238326
+ let response;
238327
+ try {
238328
+ response = await appClient.get("backend-functions", { timeout: 30000 });
238329
+ } catch (error48) {
238330
+ throw await ApiError.fromHttpError(error48, "listing deployed functions");
238331
+ }
238332
+ const result = ListFunctionsResponseSchema.safeParse(await response.json());
238290
238333
  if (!result.success) {
238291
238334
  throw new SchemaValidationError("Invalid response from server", result.error);
238292
238335
  }
@@ -238409,24 +238452,135 @@ async function readAllFunctions(functionsDir) {
238409
238452
  import { dirname as dirname4, relative as relative2 } from "node:path";
238410
238453
  async function loadFunctionCode(fn) {
238411
238454
  const functionDir = dirname4(fn.entryPath);
238412
- const loadedFiles = await Promise.all(fn.filePaths.map(async (filePath) => {
238455
+ const resolvedFiles = await Promise.all(fn.filePaths.map(async (filePath) => {
238413
238456
  const content = await readTextFile(filePath);
238414
238457
  const path11 = relative2(functionDir, filePath).split(/[/\\]/).join("/");
238415
238458
  return { path: path11, content };
238416
238459
  }));
238417
- return { ...fn, files: loadedFiles };
238460
+ return { ...fn, files: resolvedFiles };
238418
238461
  }
238419
- async function pushFunctions(functions) {
238420
- if (functions.length === 0) {
238421
- return { deployed: [], deleted: [], skipped: [], errors: null };
238462
+ async function deployOne(fn) {
238463
+ const start = Date.now();
238464
+ try {
238465
+ const functionWithCode = await loadFunctionCode(fn);
238466
+ const response = await deploySingleFunction(functionWithCode.name, {
238467
+ entry: functionWithCode.entry,
238468
+ files: functionWithCode.files,
238469
+ automations: functionWithCode.automations
238470
+ });
238471
+ return {
238472
+ name: functionWithCode.name,
238473
+ status: response.status,
238474
+ durationMs: Date.now() - start
238475
+ };
238476
+ } catch (error48) {
238477
+ return {
238478
+ name: fn.name,
238479
+ status: "error",
238480
+ error: error48 instanceof Error ? error48.message : String(error48)
238481
+ };
238482
+ }
238483
+ }
238484
+ async function deployFunctionsSequentially(functions, options) {
238485
+ if (functions.length === 0)
238486
+ return [];
238487
+ const results = [];
238488
+ for (const fn of functions) {
238489
+ options?.onStart?.([fn.name]);
238490
+ const result = await deployOne(fn);
238491
+ results.push(result);
238492
+ options?.onResult?.(result);
238493
+ }
238494
+ return results;
238495
+ }
238496
+ async function pruneRemovedFunctions(localFunctionNames, options) {
238497
+ const remote = await listDeployedFunctions();
238498
+ const localSet = new Set(localFunctionNames);
238499
+ const toDelete = remote.functions.filter((f) => !localSet.has(f.name));
238500
+ options?.onStart?.(toDelete.length);
238501
+ const results = [];
238502
+ for (const fn of toDelete) {
238503
+ options?.onBeforeDelete?.(fn.name);
238504
+ let result;
238505
+ try {
238506
+ await deleteSingleFunction(fn.name);
238507
+ result = { name: fn.name, deleted: true };
238508
+ } catch (error48) {
238509
+ result = {
238510
+ name: fn.name,
238511
+ deleted: false,
238512
+ error: error48 instanceof Error ? error48.message : String(error48)
238513
+ };
238514
+ }
238515
+ results.push(result);
238516
+ options?.onResult?.(result);
238517
+ }
238518
+ return results;
238519
+ }
238520
+ // src/core/resources/function/pull.ts
238521
+ import { join as join6 } from "node:path";
238522
+ import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
238523
+ async function writeFunctions(functionsDir, functions) {
238524
+ const written = [];
238525
+ const skipped = [];
238526
+ for (const fn of functions) {
238527
+ const functionDir = join6(functionsDir, fn.name);
238528
+ const configPath = join6(functionDir, "function.jsonc");
238529
+ if (await isFunctionUnchanged(functionDir, fn)) {
238530
+ skipped.push(fn.name);
238531
+ continue;
238532
+ }
238533
+ const config5 = {
238534
+ name: fn.name,
238535
+ entry: fn.entry
238536
+ };
238537
+ if (fn.automations.length > 0) {
238538
+ config5.automations = fn.automations;
238539
+ }
238540
+ await writeJsonFile(configPath, config5);
238541
+ for (const file2 of fn.files) {
238542
+ await writeFile(join6(functionDir, file2.path), file2.content);
238543
+ }
238544
+ written.push(fn.name);
238545
+ }
238546
+ return { written, skipped };
238547
+ }
238548
+ async function isFunctionUnchanged(functionDir, fn) {
238549
+ if (!await pathExists(functionDir)) {
238550
+ return false;
238551
+ }
238552
+ const configPath = join6(functionDir, "function.jsonc");
238553
+ try {
238554
+ const localConfig = await readJsonFile(configPath);
238555
+ if (localConfig.entry !== fn.entry) {
238556
+ return false;
238557
+ }
238558
+ if (!isDeepStrictEqual3(localConfig.automations ?? [], fn.automations)) {
238559
+ return false;
238560
+ }
238561
+ } catch {
238562
+ return false;
238563
+ }
238564
+ for (const file2 of fn.files) {
238565
+ const filePath = join6(functionDir, file2.path);
238566
+ if (!await pathExists(filePath)) {
238567
+ return false;
238568
+ }
238569
+ try {
238570
+ const localContent = await readTextFile(filePath);
238571
+ if (localContent !== file2.content) {
238572
+ return false;
238573
+ }
238574
+ } catch {
238575
+ return false;
238576
+ }
238422
238577
  }
238423
- const functionsWithCode = await Promise.all(functions.map(loadFunctionCode));
238424
- return deployFunctions(functionsWithCode);
238578
+ return true;
238425
238579
  }
238426
238580
  // src/core/resources/function/resource.ts
238427
238581
  var functionResource = {
238428
238582
  readAll: readAllFunctions,
238429
- push: pushFunctions
238583
+ push: (functions) => deployFunctionsSequentially(functions)
238430
238584
  };
238431
238585
  // src/core/project/config.ts
238432
238586
  async function findConfigInDir(dir) {
@@ -238467,10 +238621,10 @@ async function readProjectConfig(projectRoot) {
238467
238621
  const project = result.data;
238468
238622
  const configDir = dirname5(configPath);
238469
238623
  const [entities, functions, agents, connectors] = await Promise.all([
238470
- entityResource.readAll(join6(configDir, project.entitiesDir)),
238471
- functionResource.readAll(join6(configDir, project.functionsDir)),
238472
- agentResource.readAll(join6(configDir, project.agentsDir)),
238473
- connectorResource.readAll(join6(configDir, project.connectorsDir))
238624
+ entityResource.readAll(join7(configDir, project.entitiesDir)),
238625
+ functionResource.readAll(join7(configDir, project.functionsDir)),
238626
+ agentResource.readAll(join7(configDir, project.agentsDir)),
238627
+ connectorResource.readAll(join7(configDir, project.connectorsDir))
238474
238628
  ]);
238475
238629
  return {
238476
238630
  project: { ...project, root, configPath },
@@ -238567,16 +238721,16 @@ async function readAppConfig(projectRoot) {
238567
238721
  // src/core/project/template.ts
238568
238722
  var import_ejs = __toESM(require_ejs(), 1);
238569
238723
  var import_front_matter = __toESM(require_front_matter(), 1);
238570
- import { dirname as dirname6, join as join8 } from "node:path";
238724
+ import { dirname as dirname6, join as join9 } from "node:path";
238571
238725
 
238572
238726
  // src/core/assets.ts
238573
238727
  import { cpSync, existsSync } from "node:fs";
238574
238728
  import { homedir as homedir2 } from "node:os";
238575
- import { join as join7 } from "node:path";
238729
+ import { join as join8 } from "node:path";
238576
238730
  // package.json
238577
238731
  var package_default = {
238578
238732
  name: "base44",
238579
- version: "0.0.44",
238733
+ version: "0.0.45",
238580
238734
  description: "Base44 CLI - Unified interface for managing Base44 applications",
238581
238735
  type: "module",
238582
238736
  bin: {
@@ -238665,15 +238819,15 @@ var package_default = {
238665
238819
  };
238666
238820
 
238667
238821
  // src/core/assets.ts
238668
- var ASSETS_DIR = join7(homedir2(), ".base44", "assets", package_default.version);
238822
+ var ASSETS_DIR = join8(homedir2(), ".base44", "assets", package_default.version);
238669
238823
  function getTemplatesDir() {
238670
- return join7(ASSETS_DIR, "templates");
238824
+ return join8(ASSETS_DIR, "templates");
238671
238825
  }
238672
238826
  function getTemplatesIndexPath() {
238673
- return join7(ASSETS_DIR, "templates", "templates.json");
238827
+ return join8(ASSETS_DIR, "templates", "templates.json");
238674
238828
  }
238675
238829
  function getDenoWrapperPath() {
238676
- return join7(ASSETS_DIR, "deno-runtime", "main.js");
238830
+ return join8(ASSETS_DIR, "deno-runtime", "main.js");
238677
238831
  }
238678
238832
  function ensureNpmAssets(sourceDir) {
238679
238833
  if (existsSync(ASSETS_DIR))
@@ -238694,23 +238848,23 @@ async function listTemplates() {
238694
238848
  return result.data.templates;
238695
238849
  }
238696
238850
  async function renderTemplate(template, destPath, data) {
238697
- const templateDir = join8(getTemplatesDir(), template.path);
238851
+ const templateDir = join9(getTemplatesDir(), template.path);
238698
238852
  const files = await globby("**/*", {
238699
238853
  cwd: templateDir,
238700
238854
  dot: true,
238701
238855
  onlyFiles: true
238702
238856
  });
238703
238857
  for (const file2 of files) {
238704
- const srcPath = join8(templateDir, file2);
238858
+ const srcPath = join9(templateDir, file2);
238705
238859
  try {
238706
238860
  if (file2.endsWith(".ejs")) {
238707
238861
  const rendered = await import_ejs.default.renderFile(srcPath, data);
238708
238862
  const { attributes, body } = import_front_matter.default(rendered);
238709
- const destFile = attributes.outputFileName ? join8(dirname6(file2), attributes.outputFileName) : file2.replace(/\.ejs$/, "");
238710
- const destFilePath = join8(destPath, destFile);
238863
+ const destFile = attributes.outputFileName ? join9(dirname6(file2), attributes.outputFileName) : file2.replace(/\.ejs$/, "");
238864
+ const destFilePath = join9(destPath, destFile);
238711
238865
  await writeFile(destFilePath, body);
238712
238866
  } else {
238713
- const destFilePath = join8(destPath, file2);
238867
+ const destFilePath = join9(destPath, file2);
238714
238868
  await copyFile(srcPath, destFilePath);
238715
238869
  }
238716
238870
  } catch (error48) {
@@ -238809,7 +238963,7 @@ async function getSiteFilePaths(outputDir) {
238809
238963
  // src/core/site/deploy.ts
238810
238964
  import { randomUUID } from "node:crypto";
238811
238965
  import { tmpdir } from "node:os";
238812
- import { join as join9 } from "node:path";
238966
+ import { join as join10 } from "node:path";
238813
238967
  async function deploySite(siteOutputDir) {
238814
238968
  if (!await pathExists(siteOutputDir)) {
238815
238969
  throw new InvalidInputError(`Output directory does not exist: ${siteOutputDir}. Make sure to build your project first.`, {
@@ -238826,7 +238980,7 @@ async function deploySite(siteOutputDir) {
238826
238980
  ]
238827
238981
  });
238828
238982
  }
238829
- const archivePath = join9(tmpdir(), `base44-site-${randomUUID()}.tar.gz`);
238983
+ const archivePath = join10(tmpdir(), `base44-site-${randomUUID()}.tar.gz`);
238830
238984
  try {
238831
238985
  await createArchive(siteOutputDir, archivePath);
238832
238986
  return await uploadSite(archivePath);
@@ -238851,12 +239005,18 @@ function hasResourcesToDeploy(projectData) {
238851
239005
  const hasConnectors = connectors.length > 0;
238852
239006
  return hasEntities || hasFunctions || hasAgents || hasConnectors || hasSite;
238853
239007
  }
238854
- async function deployAll(projectData) {
239008
+ async function deployAll(projectData, options) {
238855
239009
  const { project, entities, functions, agents, connectors } = projectData;
238856
239010
  await entityResource.push(entities);
238857
- await functionResource.push(functions);
239011
+ await deployFunctionsSequentially(functions, {
239012
+ onStart: options?.onFunctionStart,
239013
+ onResult: options?.onFunctionResult
239014
+ });
238858
239015
  await agentResource.push(agents);
238859
239016
  const { results: connectorResults } = await pushConnectors(connectors);
239017
+ if (project.visibility) {
239018
+ await updateProjectVisibility(project.visibility);
239019
+ }
238860
239020
  if (project.site?.outputDirectory) {
238861
239021
  const outputDir = resolve(project.root, project.site.outputDirectory);
238862
239022
  const { appUrl } = await deploySite(outputDir);
@@ -246611,7 +246771,7 @@ function formatYaml(data, options = {}) {
246611
246771
  async function pullAgentsAction() {
246612
246772
  const { project: project2 } = await readProjectConfig();
246613
246773
  const configDir = dirname7(project2.configPath);
246614
- const agentsDir = join10(configDir, project2.agentsDir);
246774
+ const agentsDir = join11(configDir, project2.agentsDir);
246615
246775
  const remoteAgents = await runTask("Fetching agents from Base44", async () => {
246616
246776
  return await fetchAgents();
246617
246777
  }, {
@@ -246733,11 +246893,11 @@ function getConnectorsListAvailableCommand(context) {
246733
246893
  }
246734
246894
 
246735
246895
  // src/cli/commands/connectors/pull.ts
246736
- import { dirname as dirname8, join as join11 } from "node:path";
246896
+ import { dirname as dirname8, join as join12 } from "node:path";
246737
246897
  async function pullConnectorsAction() {
246738
246898
  const { project: project2 } = await readProjectConfig();
246739
246899
  const configDir = dirname8(project2.configPath);
246740
- const connectorsDir = join11(configDir, project2.connectorsDir);
246900
+ const connectorsDir = join12(configDir, project2.connectorsDir);
246741
246901
  const remoteConnectors = await runTask("Fetching connectors from Base44", async () => {
246742
246902
  return await pullAllConnectors();
246743
246903
  }, {
@@ -247606,46 +247766,242 @@ function getEntitiesPushCommand(context) {
247606
247766
  }));
247607
247767
  }
247608
247768
 
247769
+ // src/cli/commands/functions/delete.ts
247770
+ async function deleteFunctionsAction(names) {
247771
+ let deleted = 0;
247772
+ let notFound = 0;
247773
+ let errors5 = 0;
247774
+ for (const name2 of names) {
247775
+ try {
247776
+ await runTask(`Deleting ${name2}...`, () => deleteSingleFunction(name2), {
247777
+ successMessage: `${name2} deleted`,
247778
+ errorMessage: `Failed to delete ${name2}`
247779
+ });
247780
+ deleted++;
247781
+ } catch (error48) {
247782
+ if (error48 instanceof ApiError && error48.statusCode === 404) {
247783
+ notFound++;
247784
+ } else {
247785
+ errors5++;
247786
+ }
247787
+ }
247788
+ }
247789
+ if (names.length === 1) {
247790
+ if (deleted)
247791
+ return { outroMessage: `Function "${names[0]}" deleted` };
247792
+ if (notFound)
247793
+ return { outroMessage: `Function "${names[0]}" not found` };
247794
+ return { outroMessage: `Failed to delete "${names[0]}"` };
247795
+ }
247796
+ const total = names.length;
247797
+ const parts = [];
247798
+ if (deleted > 0)
247799
+ parts.push(`${deleted}/${total} deleted`);
247800
+ if (notFound > 0)
247801
+ parts.push(`${notFound} not found`);
247802
+ if (errors5 > 0)
247803
+ parts.push(`${errors5} error${errors5 !== 1 ? "s" : ""}`);
247804
+ return { outroMessage: parts.join(", ") };
247805
+ }
247806
+ function parseNames(args) {
247807
+ return args.flatMap((arg) => arg.split(",")).map((n2) => n2.trim()).filter(Boolean);
247808
+ }
247809
+ function validateNames(command) {
247810
+ const names = parseNames(command.args);
247811
+ if (names.length === 0) {
247812
+ command.error("At least one function name is required");
247813
+ }
247814
+ }
247815
+ function getDeleteCommand(context) {
247816
+ return new Command("delete").description("Delete deployed functions").argument("<names...>", "Function names to delete").hook("preAction", validateNames).action(async (rawNames) => {
247817
+ const names = parseNames(rawNames);
247818
+ await runCommand(() => deleteFunctionsAction(names), { requireAuth: true }, context);
247819
+ });
247820
+ }
247821
+
247822
+ // src/cli/commands/functions/formatDeployResult.ts
247823
+ function formatDuration(ms) {
247824
+ return `${(ms / 1000).toFixed(1)}s`;
247825
+ }
247826
+ function formatDeployResult(result) {
247827
+ const label = result.name.padEnd(25);
247828
+ if (result.status === "deployed") {
247829
+ const timing = result.durationMs ? theme.styles.dim(` (${formatDuration(result.durationMs)})`) : "";
247830
+ R2.success(`${label} deployed${timing}`);
247831
+ } else if (result.status === "unchanged") {
247832
+ R2.success(`${label} unchanged`);
247833
+ } else {
247834
+ R2.error(`${label} error: ${result.error}`);
247835
+ }
247836
+ }
247837
+
247838
+ // src/cli/commands/functions/parseNames.ts
247839
+ function parseNames2(args) {
247840
+ return args.flatMap((arg) => arg.split(",")).map((n2) => n2.trim()).filter(Boolean);
247841
+ }
247842
+
247609
247843
  // src/cli/commands/functions/deploy.ts
247610
- async function deployFunctionsAction() {
247844
+ function resolveFunctionsToDeploy(names, allFunctions) {
247845
+ if (names.length === 0)
247846
+ return allFunctions;
247847
+ const notFound = names.filter((n2) => !allFunctions.some((f) => f.name === n2));
247848
+ if (notFound.length > 0) {
247849
+ throw new InvalidInputError(`Function${notFound.length > 1 ? "s" : ""} not found in project: ${notFound.join(", ")}`);
247850
+ }
247851
+ return allFunctions.filter((f) => names.includes(f.name));
247852
+ }
247853
+ function formatPruneResult(pruneResult) {
247854
+ if (pruneResult.deleted) {
247855
+ R2.success(`${pruneResult.name.padEnd(25)} deleted`);
247856
+ } else {
247857
+ R2.error(`${pruneResult.name.padEnd(25)} error: ${pruneResult.error}`);
247858
+ }
247859
+ }
247860
+ function formatPruneSummary(pruneResults) {
247861
+ if (pruneResults.length > 0) {
247862
+ const pruned = pruneResults.filter((r) => r.deleted).length;
247863
+ R2.info(`${pruned} deleted`);
247864
+ }
247865
+ }
247866
+ function buildDeploySummary(results) {
247867
+ const deployed = results.filter((r) => r.status === "deployed").length;
247868
+ const unchanged = results.filter((r) => r.status === "unchanged").length;
247869
+ const failed = results.filter((r) => r.status === "error").length;
247870
+ const parts = [];
247871
+ if (deployed > 0)
247872
+ parts.push(`${deployed} deployed`);
247873
+ if (unchanged > 0)
247874
+ parts.push(`${unchanged} unchanged`);
247875
+ if (failed > 0)
247876
+ parts.push(`${failed} error${failed !== 1 ? "s" : ""}`);
247877
+ return parts.join(", ") || "No functions deployed";
247878
+ }
247879
+ async function deployFunctionsAction(names, options) {
247880
+ if (options.force && names.length > 0) {
247881
+ throw new InvalidInputError("--force cannot be used when specifying function names");
247882
+ }
247611
247883
  const { functions } = await readProjectConfig();
247612
- if (functions.length === 0) {
247884
+ const toDeploy = resolveFunctionsToDeploy(names, functions);
247885
+ if (toDeploy.length === 0) {
247613
247886
  return {
247614
247887
  outroMessage: "No functions found. Create functions in the 'functions' directory."
247615
247888
  };
247616
247889
  }
247617
- R2.info(`Found ${functions.length} ${functions.length === 1 ? "function" : "functions"} to deploy`);
247618
- const result = await runTask("Deploying functions to Base44", async () => {
247619
- return await pushFunctions(functions);
247890
+ R2.info(`Found ${toDeploy.length} ${toDeploy.length === 1 ? "function" : "functions"} to deploy`);
247891
+ let completed = 0;
247892
+ const total = toDeploy.length;
247893
+ const results = await deployFunctionsSequentially(toDeploy, {
247894
+ onStart: (startNames) => {
247895
+ const label = startNames.length === 1 ? startNames[0] : `${startNames.length} functions`;
247896
+ R2.step(theme.styles.dim(`[${completed + 1}/${total}] Deploying ${label}...`));
247897
+ },
247898
+ onResult: (result) => {
247899
+ completed++;
247900
+ formatDeployResult(result);
247901
+ }
247902
+ });
247903
+ if (options.force) {
247904
+ const allLocalNames = functions.map((f) => f.name);
247905
+ let pruneCompleted = 0;
247906
+ let pruneTotal = 0;
247907
+ const pruneResults = await pruneRemovedFunctions(allLocalNames, {
247908
+ onStart: (total2) => {
247909
+ pruneTotal = total2;
247910
+ if (total2 > 0) {
247911
+ R2.info(`Found ${total2} remote ${total2 === 1 ? "function" : "functions"} to delete`);
247912
+ }
247913
+ },
247914
+ onBeforeDelete: (name2) => {
247915
+ pruneCompleted++;
247916
+ R2.step(theme.styles.dim(`[${pruneCompleted}/${pruneTotal}] Deleting ${name2}...`));
247917
+ },
247918
+ onResult: formatPruneResult
247919
+ });
247920
+ formatPruneSummary(pruneResults);
247921
+ }
247922
+ return { outroMessage: buildDeploySummary(results) };
247923
+ }
247924
+ function getDeployCommand(context) {
247925
+ return new Command("deploy").description("Deploy functions to Base44").argument("[names...]", "Function names to deploy (deploys all if omitted)").option("--force", "Delete remote functions not found locally").action(async (rawNames, options) => {
247926
+ await runCommand(() => {
247927
+ const names = parseNames2(rawNames);
247928
+ return deployFunctionsAction(names, options);
247929
+ }, { requireAuth: true }, context);
247930
+ });
247931
+ }
247932
+
247933
+ // src/cli/commands/functions/list.ts
247934
+ async function listFunctionsAction() {
247935
+ const { functions } = await runTask("Fetching functions...", async () => listDeployedFunctions(), { errorMessage: "Failed to fetch functions" });
247936
+ if (functions.length === 0) {
247937
+ return { outroMessage: "No functions on remote" };
247938
+ }
247939
+ for (const fn of functions) {
247940
+ const automationCount = fn.automations.length;
247941
+ const automationLabel = automationCount > 0 ? theme.styles.dim(` (${automationCount} automation${automationCount > 1 ? "s" : ""})`) : "";
247942
+ R2.message(` ${fn.name}${automationLabel}`);
247943
+ }
247944
+ return {
247945
+ outroMessage: `${functions.length} function${functions.length !== 1 ? "s" : ""} on remote`
247946
+ };
247947
+ }
247948
+ function getListCommand(context) {
247949
+ return new Command("list").description("List all deployed functions").action(async () => {
247950
+ await runCommand(listFunctionsAction, { requireAuth: true }, context);
247951
+ });
247952
+ }
247953
+
247954
+ // src/cli/commands/functions/pull.ts
247955
+ import { dirname as dirname9, join as join13 } from "node:path";
247956
+ async function pullFunctionsAction(name2) {
247957
+ const { project: project2 } = await readProjectConfig();
247958
+ const configDir = dirname9(project2.configPath);
247959
+ const functionsDir = join13(configDir, project2.functionsDir);
247960
+ const remoteFunctions = await runTask("Fetching functions from Base44", async () => {
247961
+ const { functions } = await listDeployedFunctions();
247962
+ return functions;
247620
247963
  }, {
247621
- successMessage: "Functions deployed successfully",
247622
- errorMessage: "Failed to deploy functions"
247964
+ successMessage: "Functions fetched successfully",
247965
+ errorMessage: "Failed to fetch functions"
247623
247966
  });
247624
- if (result.deployed.length > 0) {
247625
- R2.success(`Deployed: ${result.deployed.join(", ")}`);
247967
+ const toPull = name2 ? remoteFunctions.filter((f) => f.name === name2) : remoteFunctions;
247968
+ if (name2 && toPull.length === 0) {
247969
+ return {
247970
+ outroMessage: `Function "${name2}" not found on remote`
247971
+ };
247626
247972
  }
247627
- if (result.deleted.length > 0) {
247628
- R2.warn(`Deleted: ${result.deleted.join(", ")}`);
247973
+ if (toPull.length === 0) {
247974
+ return { outroMessage: "No functions found on remote" };
247629
247975
  }
247630
- if (result.errors && result.errors.length > 0) {
247631
- throw new ApiError("Function deployment errors", {
247632
- details: result.errors.map((e2) => `'${e2.name}': ${e2.message}`),
247633
- hints: [
247634
- { message: "Check the function code for syntax errors" },
247635
- { message: "Ensure all imports are valid" }
247636
- ]
247637
- });
247976
+ const { written, skipped } = await runTask("Writing function files", async () => {
247977
+ return await writeFunctions(functionsDir, toPull);
247978
+ }, {
247979
+ successMessage: "Function files written successfully",
247980
+ errorMessage: "Failed to write function files"
247981
+ });
247982
+ for (const name3 of written) {
247983
+ R2.success(`${name3.padEnd(25)} written`);
247638
247984
  }
247639
- return { outroMessage: "Functions deployed to Base44" };
247985
+ for (const name3 of skipped) {
247986
+ R2.info(`${name3.padEnd(25)} unchanged`);
247987
+ }
247988
+ return {
247989
+ outroMessage: `Pulled ${toPull.length} function${toPull.length !== 1 ? "s" : ""} to ${functionsDir}`
247990
+ };
247640
247991
  }
247641
- function getFunctionsDeployCommand(context) {
247642
- return new Command("functions").description("Manage project functions").addCommand(new Command("deploy").description("Deploy local functions to Base44").action(async () => {
247643
- await runCommand(deployFunctionsAction, { requireAuth: true }, context);
247644
- }));
247992
+ function getPullCommand(context) {
247993
+ return new Command("pull").description("Pull deployed functions from Base44").argument("[name]", "Function name to pull (pulls all if omitted)").action(async (name2) => {
247994
+ await runCommand(() => pullFunctionsAction(name2), { requireAuth: true }, context);
247995
+ });
247996
+ }
247997
+
247998
+ // src/cli/commands/functions/index.ts
247999
+ function getFunctionsCommand(context) {
248000
+ return new Command("functions").description("Manage backend functions").addCommand(getDeployCommand(context)).addCommand(getDeleteCommand(context)).addCommand(getListCommand(context)).addCommand(getPullCommand(context));
247645
248001
  }
247646
248002
 
247647
248003
  // src/cli/commands/project/create.ts
247648
- import { basename as basename3, join as join12, resolve as resolve2 } from "node:path";
248004
+ import { basename as basename3, join as join14, resolve as resolve2 } from "node:path";
247649
248005
  var import_kebabCase = __toESM(require_kebabCase(), 1);
247650
248006
  var DEFAULT_TEMPLATE_ID = "backend-only";
247651
248007
  async function getTemplateById(templateId) {
@@ -247782,7 +248138,7 @@ async function executeCreate({
247782
248138
  updateMessage("Building project...");
247783
248139
  await execa({ cwd: resolvedPath, shell: true })`${buildCommand}`;
247784
248140
  updateMessage("Deploying site...");
247785
- return await deploySite(join12(resolvedPath, outputDirectory));
248141
+ return await deploySite(join14(resolvedPath, outputDirectory));
247786
248142
  }, {
247787
248143
  successMessage: theme.colors.base44Orange("Site deployed successfully"),
247788
248144
  errorMessage: "Failed to deploy site"
@@ -247869,11 +248225,17 @@ ${summaryLines.join(`
247869
248225
  ${summaryLines.join(`
247870
248226
  `)}`);
247871
248227
  }
247872
- const result = await runTask("Deploying your app...", async () => {
247873
- return await deployAll(projectData);
247874
- }, {
247875
- successMessage: theme.colors.base44Orange("Deployment completed"),
247876
- errorMessage: "Deployment failed"
248228
+ let functionCompleted = 0;
248229
+ const functionTotal = functions.length;
248230
+ const result = await deployAll(projectData, {
248231
+ onFunctionStart: (names) => {
248232
+ const label = names.length === 1 ? names[0] : `${names.length} functions`;
248233
+ R2.step(theme.styles.dim(`[${functionCompleted + 1}/${functionTotal}] Deploying ${label}...`));
248234
+ },
248235
+ onFunctionResult: (r) => {
248236
+ functionCompleted++;
248237
+ formatDeployResult(r);
248238
+ }
247877
248239
  });
247878
248240
  const connectorResults = result.connectorResults ?? [];
247879
248241
  await handleOAuthConnectors(connectorResults, options);
@@ -247887,7 +248249,7 @@ ${summaryLines.join(`
247887
248249
  }
247888
248250
  return { outroMessage: "App deployed successfully" };
247889
248251
  }
247890
- function getDeployCommand(context) {
248252
+ function getDeployCommand2(context) {
247891
248253
  return new Command("deploy").description("Deploy all project resources (entities, functions, agents, connectors, and site)").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
247892
248254
  await runCommand(() => deployAction({
247893
248255
  ...options,
@@ -248432,10 +248794,10 @@ function toPascalCase(name2) {
248432
248794
  return name2.split(/[-_\s]+/).map((w8) => w8.charAt(0).toUpperCase() + w8.slice(1)).join("");
248433
248795
  }
248434
248796
  // src/core/types/update-project.ts
248435
- import { join as join15 } from "node:path";
248797
+ import { join as join17 } from "node:path";
248436
248798
  var TYPES_INCLUDE_PATH = `${PROJECT_SUBDIR}/${TYPES_OUTPUT_SUBDIR}/*.d.ts`;
248437
248799
  async function updateProjectConfig(projectRoot) {
248438
- const tsconfigPath = join15(projectRoot, "tsconfig.json");
248800
+ const tsconfigPath = join17(projectRoot, "tsconfig.json");
248439
248801
  if (!await pathExists(tsconfigPath)) {
248440
248802
  return false;
248441
248803
  }
@@ -248478,7 +248840,7 @@ function getTypesCommand(context) {
248478
248840
  }
248479
248841
 
248480
248842
  // src/cli/dev/dev-server/main.ts
248481
- import { dirname as dirname13, join as join18 } from "node:path";
248843
+ import { dirname as dirname14, join as join20 } from "node:path";
248482
248844
  var import_cors = __toESM(require_lib4(), 1);
248483
248845
  var import_express4 = __toESM(require_express(), 1);
248484
248846
 
@@ -248835,14 +249197,163 @@ function createFunctionRouter(manager, logger) {
248835
249197
  return router;
248836
249198
  }
248837
249199
 
248838
- // src/cli/dev/dev-server/database.ts
249200
+ // src/cli/dev/dev-server/db/database.ts
248839
249201
  var import_nedb = __toESM(require_nedb(), 1);
248840
249202
 
249203
+ // src/cli/dev/dev-server/db/validator.ts
249204
+ var fieldTypes = [
249205
+ "string",
249206
+ "integer",
249207
+ "number",
249208
+ "boolean",
249209
+ "array",
249210
+ "object"
249211
+ ];
249212
+
249213
+ class Validator {
249214
+ filterFields(record2, entitySchema) {
249215
+ const filteredRecord = {};
249216
+ for (const [key2, value] of Object.entries(record2)) {
249217
+ if (entitySchema.properties[key2]) {
249218
+ filteredRecord[key2] = value;
249219
+ }
249220
+ }
249221
+ return filteredRecord;
249222
+ }
249223
+ applyDefaults(record2, entitySchema) {
249224
+ const result = {};
249225
+ for (const [key2, property] of Object.entries(entitySchema.properties)) {
249226
+ if (property.default !== undefined) {
249227
+ result[key2] = property.default;
249228
+ }
249229
+ }
249230
+ return {
249231
+ ...result,
249232
+ ...record2
249233
+ };
249234
+ }
249235
+ validate(record2, entitySchema, partial2 = false) {
249236
+ if (!partial2) {
249237
+ const requiredFieldsResponse = this.validateRequiredFields(record2, entitySchema);
249238
+ if (requiredFieldsResponse.hasError) {
249239
+ return requiredFieldsResponse;
249240
+ }
249241
+ }
249242
+ const fieldTypesResponse = this.validateFieldTypes(record2, entitySchema);
249243
+ if (fieldTypesResponse.hasError) {
249244
+ return fieldTypesResponse;
249245
+ }
249246
+ return {
249247
+ hasError: false
249248
+ };
249249
+ }
249250
+ createValidationError(message) {
249251
+ return {
249252
+ error_type: "ValidationError",
249253
+ message,
249254
+ request_id: null,
249255
+ traceback: ""
249256
+ };
249257
+ }
249258
+ validateFieldTypes(record2, entitySchema) {
249259
+ for (const [key2, value] of Object.entries(record2)) {
249260
+ const property = entitySchema.properties[key2];
249261
+ const result = this.validateValue(value, property, key2);
249262
+ if (result.hasError)
249263
+ return result;
249264
+ }
249265
+ return {
249266
+ hasError: false
249267
+ };
249268
+ }
249269
+ validateValue(value, property, fieldPath) {
249270
+ if (!property) {
249271
+ return { hasError: false };
249272
+ }
249273
+ const propertyType = property.type;
249274
+ if (!fieldTypes.includes(propertyType)) {
249275
+ return {
249276
+ hasError: true,
249277
+ error: this.createValidationError(`Error in field ${fieldPath}: Unsupported field type ${propertyType}`)
249278
+ };
249279
+ }
249280
+ switch (propertyType) {
249281
+ case "array":
249282
+ if (!Array.isArray(value)) {
249283
+ return {
249284
+ hasError: true,
249285
+ error: this.createValidationError(`Error in field ${fieldPath}: Input should be a valid array`)
249286
+ };
249287
+ }
249288
+ if (property.items) {
249289
+ for (let i5 = 0;i5 < value.length; i5++) {
249290
+ const itemResult = this.validateValue(value[i5], property.items, `${fieldPath}[${i5}]`);
249291
+ if (itemResult.hasError)
249292
+ return itemResult;
249293
+ }
249294
+ }
249295
+ break;
249296
+ case "object":
249297
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
249298
+ return {
249299
+ hasError: true,
249300
+ error: this.createValidationError(`Error in field ${fieldPath}: Input should be a valid object`)
249301
+ };
249302
+ }
249303
+ if (property.properties) {
249304
+ for (const [subKey, subValue] of Object.entries(value)) {
249305
+ if (property.properties[subKey]) {
249306
+ const subResult = this.validateValue(subValue, property.properties[subKey], `${fieldPath}.${subKey}`);
249307
+ if (subResult.hasError)
249308
+ return subResult;
249309
+ }
249310
+ }
249311
+ }
249312
+ break;
249313
+ case "integer":
249314
+ if (!Number.isInteger(value)) {
249315
+ return {
249316
+ hasError: true,
249317
+ error: this.createValidationError(`Error in field ${fieldPath}: Input should be a valid integer`)
249318
+ };
249319
+ }
249320
+ break;
249321
+ default:
249322
+ if (typeof value !== propertyType) {
249323
+ return {
249324
+ hasError: true,
249325
+ error: this.createValidationError(`Error in field ${fieldPath}: Input should be a valid ${propertyType}`)
249326
+ };
249327
+ }
249328
+ }
249329
+ return { hasError: false };
249330
+ }
249331
+ validateRequiredFields(record2, entitySchema) {
249332
+ if (entitySchema.required && entitySchema.required.length > 0) {
249333
+ for (const required2 of entitySchema.required) {
249334
+ if (record2[required2] == null) {
249335
+ return {
249336
+ hasError: true,
249337
+ error: this.createValidationError(`Error in field ${required2}: Field required`)
249338
+ };
249339
+ }
249340
+ }
249341
+ }
249342
+ return {
249343
+ hasError: false
249344
+ };
249345
+ }
249346
+ }
249347
+
249348
+ // src/cli/dev/dev-server/db/database.ts
248841
249349
  class Database {
248842
249350
  collections = new Map;
249351
+ schemas = new Map;
249352
+ validator = new Validator;
248843
249353
  load(entities) {
248844
249354
  for (const entity2 of entities) {
248845
249355
  this.collections.set(entity2.name, new import_nedb.default);
249356
+ this.schemas.set(entity2.name, entity2);
248846
249357
  }
248847
249358
  }
248848
249359
  getCollection(name2) {
@@ -248856,6 +249367,25 @@ class Database {
248856
249367
  collection.remove({}, { multi: true });
248857
249368
  }
248858
249369
  this.collections.clear();
249370
+ this.schemas.clear();
249371
+ }
249372
+ validate(entityName, record2, partial2 = false) {
249373
+ const schema9 = this.schemas.get(entityName);
249374
+ if (!schema9) {
249375
+ throw new Error(`Entity "${entityName}" not found`);
249376
+ }
249377
+ return this.validator.validate(record2, schema9, partial2);
249378
+ }
249379
+ prepareRecord(entityName, record2, partial2 = false) {
249380
+ const schema9 = this.schemas.get(entityName);
249381
+ if (!schema9) {
249382
+ throw new Error(`Entity "${entityName}" not found`);
249383
+ }
249384
+ const filteredRecord = this.validator.filterFields(record2, schema9);
249385
+ if (partial2) {
249386
+ return filteredRecord;
249387
+ }
249388
+ return this.validator.applyDefaults(filteredRecord, schema9);
248859
249389
  }
248860
249390
  }
248861
249391
 
@@ -249047,8 +249577,14 @@ function createEntityRoutes(db2, logger, remoteProxy, broadcast) {
249047
249577
  try {
249048
249578
  const now = new Date().toISOString();
249049
249579
  const { _id, ...body } = req.body;
249580
+ const filteredBody = db2.prepareRecord(entityName, body);
249581
+ const validation = db2.validate(entityName, filteredBody);
249582
+ if (validation.hasError) {
249583
+ res.status(422).json(validation.error);
249584
+ return;
249585
+ }
249050
249586
  const record2 = {
249051
- ...body,
249587
+ ...filteredBody,
249052
249588
  id: nanoid3(),
249053
249589
  created_date: now,
249054
249590
  updated_date: now
@@ -249069,12 +249605,21 @@ function createEntityRoutes(db2, logger, remoteProxy, broadcast) {
249069
249605
  }
249070
249606
  try {
249071
249607
  const now = new Date().toISOString();
249072
- const records = req.body.map((item) => ({
249073
- ...item,
249074
- id: nanoid3(),
249075
- created_date: now,
249076
- updated_date: now
249077
- }));
249608
+ const records = [];
249609
+ for (const record2 of req.body) {
249610
+ const filteredRecord = db2.prepareRecord(entityName, record2);
249611
+ const validation = db2.validate(entityName, filteredRecord);
249612
+ if (validation.hasError) {
249613
+ res.status(422).json(validation.error);
249614
+ return;
249615
+ }
249616
+ records.push({
249617
+ ...filteredRecord,
249618
+ id: nanoid3(),
249619
+ created_date: now,
249620
+ updated_date: now
249621
+ });
249622
+ }
249078
249623
  const inserted = stripInternalFields(await collection.insertAsync(records));
249079
249624
  emit(appId, entityName, "create", inserted);
249080
249625
  res.status(201).json(inserted);
@@ -249087,8 +249632,14 @@ function createEntityRoutes(db2, logger, remoteProxy, broadcast) {
249087
249632
  const { appId, entityName, id: id2 } = req.params;
249088
249633
  const { id: _id, created_date: _created_date, ...body } = req.body;
249089
249634
  try {
249635
+ const filteredBody = db2.prepareRecord(entityName, body, true);
249636
+ const validation = db2.validate(entityName, filteredBody, true);
249637
+ if (validation.hasError) {
249638
+ res.status(422).json(validation.error);
249639
+ return;
249640
+ }
249090
249641
  const updateData = {
249091
- ...body,
249642
+ ...filteredBody,
249092
249643
  updated_date: new Date().toISOString()
249093
249644
  };
249094
249645
  const result = await collection.updateAsync({ id: id2 }, { $set: updateData }, { returnUpdatedDocs: true });
@@ -249958,9 +250509,9 @@ class NodeFsHandler {
249958
250509
  if (this.fsw.closed) {
249959
250510
  return;
249960
250511
  }
249961
- const dirname12 = sp2.dirname(file2);
250512
+ const dirname13 = sp2.dirname(file2);
249962
250513
  const basename5 = sp2.basename(file2);
249963
- const parent = this.fsw._getWatchedDir(dirname12);
250514
+ const parent = this.fsw._getWatchedDir(dirname13);
249964
250515
  let prevStats = stats;
249965
250516
  if (parent.has(basename5))
249966
250517
  return;
@@ -249987,7 +250538,7 @@ class NodeFsHandler {
249987
250538
  prevStats = newStats2;
249988
250539
  }
249989
250540
  } catch (error48) {
249990
- this.fsw._remove(dirname12, basename5);
250541
+ this.fsw._remove(dirname13, basename5);
249991
250542
  }
249992
250543
  } else if (parent.has(basename5)) {
249993
250544
  const at13 = newStats.atimeMs;
@@ -251008,8 +251559,8 @@ async function createDevServer(options8) {
251008
251559
  broadcastEntityEvent(io6, appId, entityName, event);
251009
251560
  };
251010
251561
  const base44ConfigWatcher = new WatchBase44({
251011
- functions: join18(dirname13(project2.configPath), project2.functionsDir),
251012
- entities: join18(dirname13(project2.configPath), project2.entitiesDir)
251562
+ functions: join20(dirname14(project2.configPath), project2.functionsDir),
251563
+ entities: join20(dirname14(project2.configPath), project2.entitiesDir)
251013
251564
  }, devLogger);
251014
251565
  base44ConfigWatcher.on("change", async (name2) => {
251015
251566
  try {
@@ -251179,13 +251730,13 @@ function createProgram(context) {
251179
251730
  program2.addCommand(getLogoutCommand(context));
251180
251731
  program2.addCommand(getCreateCommand(context));
251181
251732
  program2.addCommand(getDashboardCommand(context));
251182
- program2.addCommand(getDeployCommand(context));
251733
+ program2.addCommand(getDeployCommand2(context));
251183
251734
  program2.addCommand(getLinkCommand(context));
251184
251735
  program2.addCommand(getEjectCommand(context));
251185
251736
  program2.addCommand(getEntitiesPushCommand(context));
251186
251737
  program2.addCommand(getAgentsCommand(context));
251187
251738
  program2.addCommand(getConnectorsCommand(context));
251188
- program2.addCommand(getFunctionsDeployCommand(context));
251739
+ program2.addCommand(getFunctionsCommand(context));
251189
251740
  program2.addCommand(getSecretsCommand(context));
251190
251741
  program2.addCommand(getSiteCommand(context));
251191
251742
  program2.addCommand(getTypesCommand(context));
@@ -251199,7 +251750,7 @@ var import_detect_agent = __toESM(require_dist5(), 1);
251199
251750
  import { release, type } from "node:os";
251200
251751
 
251201
251752
  // ../../node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
251202
- import { dirname as dirname14, posix, sep } from "path";
251753
+ import { dirname as dirname15, posix, sep } from "path";
251203
251754
  function createModulerModifier() {
251204
251755
  const getModuleFromFileName = createGetModuleFromFilename();
251205
251756
  return async (frames) => {
@@ -251208,7 +251759,7 @@ function createModulerModifier() {
251208
251759
  return frames;
251209
251760
  };
251210
251761
  }
251211
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname14(process.argv[1]) : process.cwd(), isWindows5 = sep === "\\") {
251762
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname15(process.argv[1]) : process.cwd(), isWindows5 = sep === "\\") {
251212
251763
  const normalizedBase = isWindows5 ? normalizeWindowsPath2(basePath) : basePath;
251213
251764
  return (filename) => {
251214
251765
  if (!filename)
@@ -255397,9 +255948,9 @@ function addCommandInfoToErrorReporter(program2, errorReporter) {
255397
255948
  });
255398
255949
  }
255399
255950
  // src/cli/index.ts
255400
- var __dirname4 = dirname15(fileURLToPath6(import.meta.url));
255951
+ var __dirname4 = dirname16(fileURLToPath6(import.meta.url));
255401
255952
  async function runCLI(options8) {
255402
- ensureNpmAssets(join19(__dirname4, "../assets"));
255953
+ ensureNpmAssets(join21(__dirname4, "../assets"));
255403
255954
  const errorReporter = new ErrorReporter;
255404
255955
  errorReporter.registerProcessErrorHandlers();
255405
255956
  const isNonInteractive = !process.stdin.isTTY || !process.stdout.isTTY;
@@ -255432,4 +255983,4 @@ export {
255432
255983
  CLIExitError
255433
255984
  };
255434
255985
 
255435
- //# debugId=3630160A15E12A6F64756E2164756E21
255986
+ //# debugId=0547AD962333BF6464756E2164756E21