@base44-preview/cli 0.0.33-pr.286.941c114 → 0.0.33-pr.331.bcfcc1c

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
@@ -17446,7 +17446,7 @@ var require_lodash2 = __commonJS((exports, module) => {
17446
17446
  }
17447
17447
  return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined2, comparator) : [];
17448
17448
  });
17449
- function join12(array2, separator) {
17449
+ function join15(array2, separator) {
17450
17450
  return array2 == null ? "" : nativeJoin.call(array2, separator);
17451
17451
  }
17452
17452
  function last(array2) {
@@ -17468,7 +17468,7 @@ var require_lodash2 = __commonJS((exports, module) => {
17468
17468
  function nth(array2, n2) {
17469
17469
  return array2 && array2.length ? baseNth(array2, toInteger(n2)) : undefined2;
17470
17470
  }
17471
- var pull = baseRest(pullAll);
17471
+ var pull2 = baseRest(pullAll);
17472
17472
  function pullAll(array2, values2) {
17473
17473
  return array2 && array2.length && values2 && values2.length ? basePullAll(array2, values2) : array2;
17474
17474
  }
@@ -19233,7 +19233,7 @@ __p += '`;
19233
19233
  lodash.pickBy = pickBy;
19234
19234
  lodash.property = property;
19235
19235
  lodash.propertyOf = propertyOf;
19236
- lodash.pull = pull;
19236
+ lodash.pull = pull2;
19237
19237
  lodash.pullAll = pullAll;
19238
19238
  lodash.pullAllBy = pullAllBy;
19239
19239
  lodash.pullAllWith = pullAllWith;
@@ -19378,7 +19378,7 @@ __p += '`;
19378
19378
  lodash.isUndefined = isUndefined;
19379
19379
  lodash.isWeakMap = isWeakMap;
19380
19380
  lodash.isWeakSet = isWeakSet;
19381
- lodash.join = join12;
19381
+ lodash.join = join15;
19382
19382
  lodash.kebabCase = kebabCase2;
19383
19383
  lodash.last = last;
19384
19384
  lodash.lastIndexOf = lastIndexOf;
@@ -20007,7 +20007,7 @@ function cleanDoc(doc2) {
20007
20007
  return mapDoc(doc2, (currentDoc) => cleanDocFn(currentDoc));
20008
20008
  }
20009
20009
  function replaceEndOfLine(doc2, replacement = literalline) {
20010
- return mapDoc(doc2, (currentDoc) => typeof currentDoc === "string" ? join12(replacement, currentDoc.split(`
20010
+ return mapDoc(doc2, (currentDoc) => typeof currentDoc === "string" ? join15(replacement, currentDoc.split(`
20011
20011
  `)) : currentDoc);
20012
20012
  }
20013
20013
  function canBreakFn(doc2) {
@@ -20087,7 +20087,7 @@ function indentIfBreak(contents, options) {
20087
20087
  negate: options.negate
20088
20088
  };
20089
20089
  }
20090
- function join12(separator, docs) {
20090
+ function join15(separator, docs) {
20091
20091
  assertDoc(separator);
20092
20092
  assertDocArray(docs);
20093
20093
  const parts = [];
@@ -20798,7 +20798,7 @@ var init_doc = __esm(() => {
20798
20798
  MODE_FLAT = Symbol("MODE_FLAT");
20799
20799
  DOC_FILL_PRINTED_LENGTH = Symbol("DOC_FILL_PRINTED_LENGTH");
20800
20800
  builders = {
20801
- join: join12,
20801
+ join: join15,
20802
20802
  line,
20803
20803
  softline,
20804
20804
  hardline,
@@ -125712,7 +125712,7 @@ Expected it to be ${EXPECTED_TYPE_VALUES}.`;
125712
125712
  return mapDoc2(doc2, (currentDoc) => cleanDocFn2(currentDoc));
125713
125713
  }
125714
125714
  function replaceEndOfLine2(doc2, replacement = literalline2) {
125715
- return mapDoc2(doc2, (currentDoc) => typeof currentDoc === "string" ? join14(replacement, currentDoc.split(`
125715
+ return mapDoc2(doc2, (currentDoc) => typeof currentDoc === "string" ? join17(replacement, currentDoc.split(`
125716
125716
  `)) : currentDoc);
125717
125717
  }
125718
125718
  function canBreakFn2(doc2) {
@@ -125798,7 +125798,7 @@ Expected it to be ${EXPECTED_TYPE_VALUES}.`;
125798
125798
  negate: options8.negate
125799
125799
  };
125800
125800
  }
125801
- function join14(separator, docs) {
125801
+ function join17(separator, docs) {
125802
125802
  assertDoc2(separator);
125803
125803
  assertDocArray2(docs);
125804
125804
  const parts = [];
@@ -126463,7 +126463,7 @@ Expected it to be ${EXPECTED_TYPE_VALUES}.`;
126463
126463
  }
126464
126464
  }
126465
126465
  var builders2 = {
126466
- join: join14,
126466
+ join: join17,
126467
126467
  line: line3,
126468
126468
  softline: softline2,
126469
126469
  hardline: hardline4,
@@ -155678,10 +155678,10 @@ var require_view = __commonJS((exports, module) => {
155678
155678
  var debug = require_src4()("express:view");
155679
155679
  var path18 = __require("node:path");
155680
155680
  var fs28 = __require("node:fs");
155681
- var dirname11 = path18.dirname;
155681
+ var dirname13 = path18.dirname;
155682
155682
  var basename4 = path18.basename;
155683
155683
  var extname2 = path18.extname;
155684
- var join15 = path18.join;
155684
+ var join18 = path18.join;
155685
155685
  var resolve5 = path18.resolve;
155686
155686
  module.exports = View;
155687
155687
  function View(name2, options8) {
@@ -155717,7 +155717,7 @@ var require_view = __commonJS((exports, module) => {
155717
155717
  for (var i5 = 0;i5 < roots.length && !path19; i5++) {
155718
155718
  var root2 = roots[i5];
155719
155719
  var loc = resolve5(root2, name2);
155720
- var dir = dirname11(loc);
155720
+ var dir = dirname13(loc);
155721
155721
  var file2 = basename4(loc);
155722
155722
  path19 = this.resolve(dir, file2);
155723
155723
  }
@@ -155743,12 +155743,12 @@ var require_view = __commonJS((exports, module) => {
155743
155743
  };
155744
155744
  View.prototype.resolve = function resolve6(dir, file2) {
155745
155745
  var ext = this.ext;
155746
- var path19 = join15(dir, file2);
155746
+ var path19 = join18(dir, file2);
155747
155747
  var stat2 = tryStat(path19);
155748
155748
  if (stat2 && stat2.isFile()) {
155749
155749
  return path19;
155750
155750
  }
155751
- path19 = join15(dir, basename4(file2, ext), "index" + ext);
155751
+ path19 = join18(dir, basename4(file2, ext), "index" + ext);
155752
155752
  stat2 = tryStat(path19);
155753
155753
  if (stat2 && stat2.isFile()) {
155754
155754
  return path19;
@@ -159443,7 +159443,7 @@ var require_send = __commonJS((exports, module) => {
159443
159443
  var Stream2 = __require("stream");
159444
159444
  var util2 = __require("util");
159445
159445
  var extname2 = path18.extname;
159446
- var join15 = path18.join;
159446
+ var join18 = path18.join;
159447
159447
  var normalize = path18.normalize;
159448
159448
  var resolve5 = path18.resolve;
159449
159449
  var sep = path18.sep;
@@ -159615,7 +159615,7 @@ var require_send = __commonJS((exports, module) => {
159615
159615
  return res;
159616
159616
  }
159617
159617
  parts = path19.split(sep);
159618
- path19 = normalize(join15(root2, path19));
159618
+ path19 = normalize(join18(root2, path19));
159619
159619
  } else {
159620
159620
  if (UP_PATH_REGEXP.test(path19)) {
159621
159621
  debug('malicious path "%s"', path19);
@@ -159755,7 +159755,7 @@ var require_send = __commonJS((exports, module) => {
159755
159755
  return self2.onStatError(err);
159756
159756
  return self2.error(404);
159757
159757
  }
159758
- var p4 = join15(path19, self2._index[i5]);
159758
+ var p4 = join18(path19, self2._index[i5]);
159759
159759
  debug('stat "%s"', p4);
159760
159760
  fs28.stat(p4, function(err2, stat2) {
159761
159761
  if (err2)
@@ -162834,7 +162834,7 @@ var {
162834
162834
  } = import__.default;
162835
162835
 
162836
162836
  // src/cli/commands/agents/pull.ts
162837
- import { dirname as dirname7, join as join9 } from "node:path";
162837
+ import { dirname as dirname7, join as join10 } from "node:path";
162838
162838
 
162839
162839
  // node_modules/@clack/core/dist/index.mjs
162840
162840
  var import_picocolors = __toESM(require_picocolors(), 1);
@@ -185309,7 +185309,7 @@ var generateGlobTasks = normalizeArguments(generateTasks);
185309
185309
  var generateGlobTasksSync = normalizeArgumentsSync(generateTasksSync);
185310
185310
 
185311
185311
  // src/core/project/config.ts
185312
- import { dirname as dirname5, join as join6 } from "node:path";
185312
+ import { dirname as dirname5, join as join7 } from "node:path";
185313
185313
 
185314
185314
  // src/core/resources/agent/schema.ts
185315
185315
  var EntityOperationSchema = exports_external.enum(["create", "update", "delete", "read"]);
@@ -186012,6 +186012,26 @@ var DeployFunctionsResponseSchema = exports_external.object({
186012
186012
  skipped: exports_external.array(exports_external.string()).optional().nullable(),
186013
186013
  errors: exports_external.array(exports_external.object({ name: exports_external.string(), message: exports_external.string() })).nullable()
186014
186014
  });
186015
+ var DeploySingleFunctionResponseSchema = exports_external.object({
186016
+ status: exports_external.enum(["deployed", "unchanged", "error"]),
186017
+ error: exports_external.string().optional().nullable(),
186018
+ duration_ms: exports_external.number().optional().nullable()
186019
+ });
186020
+ var FunctionAutomationInfoSchema = exports_external.object({
186021
+ name: exports_external.string(),
186022
+ type: exports_external.string(),
186023
+ is_active: exports_external.boolean()
186024
+ });
186025
+ var FunctionInfoSchema = exports_external.object({
186026
+ name: exports_external.string(),
186027
+ deployment_id: exports_external.string(),
186028
+ entry: exports_external.string(),
186029
+ files: exports_external.array(FunctionFileSchema),
186030
+ automations: exports_external.array(FunctionAutomationInfoSchema)
186031
+ });
186032
+ var ListFunctionsResponseSchema = exports_external.object({
186033
+ functions: exports_external.array(FunctionInfoSchema)
186034
+ });
186015
186035
 
186016
186036
  // src/core/resources/function/api.ts
186017
186037
  function toDeployPayloadItem(fn) {
@@ -186042,6 +186062,42 @@ async function deployFunctions(functions) {
186042
186062
  }
186043
186063
  return result.data;
186044
186064
  }
186065
+ async function deploySingleFunction(name2, payload) {
186066
+ const appClient = getAppClient();
186067
+ let response;
186068
+ try {
186069
+ response = await appClient.put(`backend-functions/${encodeURIComponent(name2)}`, { json: payload, timeout: false });
186070
+ } catch (error48) {
186071
+ throw await ApiError.fromHttpError(error48, `deploying function "${name2}"`);
186072
+ }
186073
+ const result = DeploySingleFunctionResponseSchema.safeParse(await response.json());
186074
+ if (!result.success) {
186075
+ throw new SchemaValidationError("Invalid response from server", result.error);
186076
+ }
186077
+ return result.data;
186078
+ }
186079
+ async function deleteSingleFunction(name2) {
186080
+ const appClient = getAppClient();
186081
+ try {
186082
+ await appClient.delete(`backend-functions/${encodeURIComponent(name2)}`, { timeout: 60000 });
186083
+ } catch (error48) {
186084
+ throw await ApiError.fromHttpError(error48, `deleting function "${name2}"`);
186085
+ }
186086
+ }
186087
+ async function listDeployedFunctions() {
186088
+ const appClient = getAppClient();
186089
+ let response;
186090
+ try {
186091
+ response = await appClient.get("backend-functions", { timeout: 30000 });
186092
+ } catch (error48) {
186093
+ throw await ApiError.fromHttpError(error48, "listing deployed functions");
186094
+ }
186095
+ const result = ListFunctionsResponseSchema.safeParse(await response.json());
186096
+ if (!result.success) {
186097
+ throw new SchemaValidationError("Invalid response from server", result.error);
186098
+ }
186099
+ return result.data;
186100
+ }
186045
186101
  // src/core/resources/function/config.ts
186046
186102
  import { dirname as dirname4, join as join5 } from "node:path";
186047
186103
  async function readFunctionConfig(configPath) {
@@ -186100,6 +186156,115 @@ async function pushFunctions(functions) {
186100
186156
  const functionsWithCode = await Promise.all(functions.map(loadFunctionCode));
186101
186157
  return deployFunctions(functionsWithCode);
186102
186158
  }
186159
+ async function deployOne(fn) {
186160
+ try {
186161
+ const loaded = await loadFunctionCode(fn);
186162
+ const resp = await deploySingleFunction(loaded.name, {
186163
+ entry: loaded.entry,
186164
+ files: loaded.files,
186165
+ automations: loaded.automations
186166
+ });
186167
+ return { name: loaded.name, ...resp };
186168
+ } catch (error48) {
186169
+ return {
186170
+ name: fn.name,
186171
+ status: "error",
186172
+ error: error48 instanceof Error ? error48.message : String(error48)
186173
+ };
186174
+ }
186175
+ }
186176
+ async function pushFunctionsSingle(functions, options) {
186177
+ if (functions.length === 0)
186178
+ return [];
186179
+ const concurrency = options?.concurrency ?? 1;
186180
+ if (concurrency <= 1) {
186181
+ const results2 = [];
186182
+ for (const fn of functions) {
186183
+ options?.onStart?.([fn.name]);
186184
+ const result = await deployOne(fn);
186185
+ results2.push(result);
186186
+ options?.onResult?.(result);
186187
+ }
186188
+ return results2;
186189
+ }
186190
+ const results = [];
186191
+ for (let i = 0;i < functions.length; i += concurrency) {
186192
+ const batch = functions.slice(i, i + concurrency);
186193
+ options?.onStart?.(batch.map((fn) => fn.name));
186194
+ const batchResults = await Promise.all(batch.map(deployOne));
186195
+ for (const result of batchResults) {
186196
+ results.push(result);
186197
+ options?.onResult?.(result);
186198
+ }
186199
+ }
186200
+ return results;
186201
+ }
186202
+ async function pruneRemovedFunctions(localFunctionNames) {
186203
+ const remote = await listDeployedFunctions();
186204
+ const localSet = new Set(localFunctionNames);
186205
+ const toDelete = remote.functions.filter((f) => !localSet.has(f.name));
186206
+ const results = [];
186207
+ for (const fn of toDelete) {
186208
+ try {
186209
+ await deleteSingleFunction(fn.name);
186210
+ results.push({ name: fn.name, deleted: true });
186211
+ } catch (error48) {
186212
+ results.push({
186213
+ name: fn.name,
186214
+ deleted: false,
186215
+ error: error48 instanceof Error ? error48.message : String(error48)
186216
+ });
186217
+ }
186218
+ }
186219
+ return results;
186220
+ }
186221
+ // src/core/resources/function/pull.ts
186222
+ import { join as join6 } from "node:path";
186223
+ async function writeFunctions(functionsDir, functions) {
186224
+ const written = [];
186225
+ const skipped = [];
186226
+ for (const fn of functions) {
186227
+ const functionDir = join6(functionsDir, fn.name);
186228
+ const configPath = join6(functionDir, "function.jsonc");
186229
+ if (await isFunctionUnchanged(functionDir, fn)) {
186230
+ skipped.push(fn.name);
186231
+ continue;
186232
+ }
186233
+ const config5 = {
186234
+ name: fn.name,
186235
+ entry: fn.entry
186236
+ };
186237
+ if (fn.automations.length > 0) {
186238
+ config5.automations = fn.automations;
186239
+ }
186240
+ await writeJsonFile(configPath, config5);
186241
+ for (const file2 of fn.files) {
186242
+ await writeFile(join6(functionDir, file2.path), file2.content);
186243
+ }
186244
+ written.push(fn.name);
186245
+ }
186246
+ return { written, skipped };
186247
+ }
186248
+ async function isFunctionUnchanged(functionDir, fn) {
186249
+ if (!await pathExists(functionDir)) {
186250
+ return false;
186251
+ }
186252
+ for (const file2 of fn.files) {
186253
+ const filePath = join6(functionDir, file2.path);
186254
+ if (!await pathExists(filePath)) {
186255
+ return false;
186256
+ }
186257
+ try {
186258
+ const localContent = await readTextFile(filePath);
186259
+ if (localContent !== file2.content) {
186260
+ return false;
186261
+ }
186262
+ } catch {
186263
+ return false;
186264
+ }
186265
+ }
186266
+ return true;
186267
+ }
186103
186268
  // src/core/resources/function/resource.ts
186104
186269
  var functionResource = {
186105
186270
  readAll: readAllFunctions,
@@ -186144,10 +186309,10 @@ async function readProjectConfig(projectRoot) {
186144
186309
  const project = result.data;
186145
186310
  const configDir = dirname5(configPath);
186146
186311
  const [entities, functions, agents, connectors] = await Promise.all([
186147
- entityResource.readAll(join6(configDir, project.entitiesDir)),
186148
- functionResource.readAll(join6(configDir, project.functionsDir)),
186149
- agentResource.readAll(join6(configDir, project.agentsDir)),
186150
- connectorResource.readAll(join6(configDir, project.connectorsDir))
186312
+ entityResource.readAll(join7(configDir, project.entitiesDir)),
186313
+ functionResource.readAll(join7(configDir, project.functionsDir)),
186314
+ agentResource.readAll(join7(configDir, project.agentsDir)),
186315
+ connectorResource.readAll(join7(configDir, project.connectorsDir))
186151
186316
  ]);
186152
186317
  return {
186153
186318
  project: { ...project, root, configPath },
@@ -186244,7 +186409,7 @@ async function readAppConfig(projectRoot) {
186244
186409
  // src/core/project/template.ts
186245
186410
  var import_ejs = __toESM(require_ejs(), 1);
186246
186411
  var import_front_matter = __toESM(require_front_matter(), 1);
186247
- import { dirname as dirname6, join as join7 } from "node:path";
186412
+ import { dirname as dirname6, join as join8 } from "node:path";
186248
186413
  async function listTemplates() {
186249
186414
  const parsed = await readJsonFile(getTemplatesIndexPath());
186250
186415
  const result = TemplatesConfigSchema.safeParse(parsed);
@@ -186254,23 +186419,23 @@ async function listTemplates() {
186254
186419
  return result.data.templates;
186255
186420
  }
186256
186421
  async function renderTemplate(template, destPath, data) {
186257
- const templateDir = join7(getTemplatesDir(), template.path);
186422
+ const templateDir = join8(getTemplatesDir(), template.path);
186258
186423
  const files = await globby("**/*", {
186259
186424
  cwd: templateDir,
186260
186425
  dot: true,
186261
186426
  onlyFiles: true
186262
186427
  });
186263
186428
  for (const file2 of files) {
186264
- const srcPath = join7(templateDir, file2);
186429
+ const srcPath = join8(templateDir, file2);
186265
186430
  try {
186266
186431
  if (file2.endsWith(".ejs")) {
186267
186432
  const rendered = await import_ejs.default.renderFile(srcPath, data);
186268
186433
  const { attributes, body } = import_front_matter.default(rendered);
186269
- const destFile = attributes.outputFileName ? join7(dirname6(file2), attributes.outputFileName) : file2.replace(/\.ejs$/, "");
186270
- const destFilePath = join7(destPath, destFile);
186434
+ const destFile = attributes.outputFileName ? join8(dirname6(file2), attributes.outputFileName) : file2.replace(/\.ejs$/, "");
186435
+ const destFilePath = join8(destPath, destFile);
186271
186436
  await writeFile(destFilePath, body);
186272
186437
  } else {
186273
- const destFilePath = join7(destPath, file2);
186438
+ const destFilePath = join8(destPath, file2);
186274
186439
  await copyFile(srcPath, destFilePath);
186275
186440
  }
186276
186441
  } catch (error48) {
@@ -186373,7 +186538,7 @@ async function getSiteFilePaths(outputDir) {
186373
186538
  // src/core/site/deploy.ts
186374
186539
  import { randomUUID } from "node:crypto";
186375
186540
  import { tmpdir } from "node:os";
186376
- import { join as join8 } from "node:path";
186541
+ import { join as join9 } from "node:path";
186377
186542
  async function deploySite(siteOutputDir) {
186378
186543
  if (!await pathExists(siteOutputDir)) {
186379
186544
  throw new FileNotFoundError(`Output directory does not exist: ${siteOutputDir}. Make sure to build your project first.`, {
@@ -186390,7 +186555,7 @@ async function deploySite(siteOutputDir) {
186390
186555
  ]
186391
186556
  });
186392
186557
  }
186393
- const archivePath = join8(tmpdir(), `base44-site-${randomUUID()}.tar.gz`);
186558
+ const archivePath = join9(tmpdir(), `base44-site-${randomUUID()}.tar.gz`);
186394
186559
  try {
186395
186560
  await createArchive(siteOutputDir, archivePath);
186396
186561
  return await uploadSite(archivePath);
@@ -194071,7 +194236,7 @@ function getDashboardUrl(projectId) {
194071
194236
  async function pullAgentsAction() {
194072
194237
  const { project: project2 } = await readProjectConfig();
194073
194238
  const configDir = dirname7(project2.configPath);
194074
- const agentsDir = join9(configDir, project2.agentsDir);
194239
+ const agentsDir = join10(configDir, project2.agentsDir);
194075
194240
  const remoteAgents = await runTask("Fetching agents from Base44", async () => {
194076
194241
  return await fetchAgents();
194077
194242
  }, {
@@ -194165,11 +194330,11 @@ function getWhoamiCommand(context) {
194165
194330
  }
194166
194331
 
194167
194332
  // src/cli/commands/connectors/pull.ts
194168
- import { dirname as dirname8, join as join10 } from "node:path";
194333
+ import { dirname as dirname8, join as join11 } from "node:path";
194169
194334
  async function pullConnectorsAction() {
194170
194335
  const { project: project2 } = await readProjectConfig();
194171
194336
  const configDir = dirname8(project2.configPath);
194172
- const connectorsDir = join10(configDir, project2.connectorsDir);
194337
+ const connectorsDir = join11(configDir, project2.connectorsDir);
194173
194338
  const remoteConnectors = await runTask("Fetching connectors from Base44", async () => {
194174
194339
  return await listConnectors();
194175
194340
  }, {
@@ -195017,48 +195182,218 @@ function getEntitiesPushCommand(context) {
195017
195182
  }));
195018
195183
  }
195019
195184
 
195185
+ // src/cli/commands/functions/delete.ts
195186
+ async function deleteFunctionAction(name2) {
195187
+ try {
195188
+ await deleteSingleFunction(name2);
195189
+ R2.success(`${name2} deleted`);
195190
+ return { outroMessage: `Function "${name2}" deleted` };
195191
+ } catch (error48) {
195192
+ if (error48 instanceof ApiError && error48.statusCode === 404) {
195193
+ R2.warn(`Function "${name2}" not found on remote`);
195194
+ return { outroMessage: `Function "${name2}" not found` };
195195
+ }
195196
+ throw error48;
195197
+ }
195198
+ }
195199
+ function getDeleteCommand(context) {
195200
+ return new Command("delete").description("Delete a deployed backend function").argument("<name>", "Name of the function to delete").action(async (name2) => {
195201
+ await runCommand(() => deleteFunctionAction(name2), { requireAuth: true }, context);
195202
+ });
195203
+ }
195204
+
195020
195205
  // src/cli/commands/functions/deploy.ts
195021
- async function deployFunctionsAction() {
195206
+ function formatDuration(ms) {
195207
+ return `${(ms / 1000).toFixed(1)}s`;
195208
+ }
195209
+ function formatResult(r) {
195210
+ const label = r.name.padEnd(25);
195211
+ if (r.status === "deployed") {
195212
+ const timing = r.duration_ms ? theme.styles.dim(` (${formatDuration(r.duration_ms)})`) : "";
195213
+ R2.success(`${label} deployed${timing}`);
195214
+ } else if (r.status === "unchanged") {
195215
+ R2.success(`${label} unchanged`);
195216
+ } else {
195217
+ R2.error(`${label} error: ${r.error}`);
195218
+ }
195219
+ }
195220
+ async function deployFunctionsAction(name2, options) {
195022
195221
  const { functions } = await readProjectConfig();
195023
- if (functions.length === 0) {
195222
+ const toDeploy = name2 ? functions.filter((f) => f.name === name2) : functions;
195223
+ if (toDeploy.length === 0) {
195224
+ if (name2) {
195225
+ throw new InvalidInputError(`Function "${name2}" not found in project`);
195226
+ }
195024
195227
  return {
195025
195228
  outroMessage: "No functions found. Create functions in the 'functions' directory."
195026
195229
  };
195027
195230
  }
195028
- R2.info(`Found ${functions.length} ${functions.length === 1 ? "function" : "functions"} to deploy`);
195029
- const result = await runTask("Deploying functions to Base44", async () => {
195030
- return await pushFunctions(functions);
195231
+ R2.info(`Found ${toDeploy.length} ${toDeploy.length === 1 ? "function" : "functions"} to deploy`);
195232
+ let completed = 0;
195233
+ const total = toDeploy.length;
195234
+ const results = await pushFunctionsSingle(toDeploy, {
195235
+ concurrency: options.concurrency,
195236
+ onStart: (names) => {
195237
+ const label = names.length === 1 ? names[0] : `${names.length} functions`;
195238
+ R2.step(theme.styles.dim(`[${completed}/${total}] Deploying ${label}...`));
195239
+ },
195240
+ onResult: (r) => {
195241
+ completed++;
195242
+ formatResult(r);
195243
+ }
195244
+ });
195245
+ const succeeded = results.filter((r) => r.status !== "error").length;
195246
+ const failed = results.filter((r) => r.status === "error").length;
195247
+ if (options.prune) {
195248
+ R2.info("Pruning remote functions not found locally...");
195249
+ const allLocalNames = functions.map((f) => f.name);
195250
+ const pruneResults = await pruneRemovedFunctions(allLocalNames);
195251
+ for (const pr of pruneResults) {
195252
+ if (pr.deleted) {
195253
+ R2.success(`${pr.name.padEnd(25)} deleted`);
195254
+ } else {
195255
+ R2.error(`${pr.name.padEnd(25)} error: ${pr.error}`);
195256
+ }
195257
+ }
195258
+ if (pruneResults.length > 0) {
195259
+ const pruned = pruneResults.filter((r) => r.deleted).length;
195260
+ R2.info(`${pruned} function${pruned !== 1 ? "s" : ""} pruned`);
195261
+ }
195262
+ }
195263
+ const parts = [];
195264
+ if (succeeded > 0)
195265
+ parts.push(`${succeeded}/${results.length} succeeded`);
195266
+ if (failed > 0)
195267
+ parts.push(`${failed} error${failed !== 1 ? "s" : ""}`);
195268
+ const summary = parts.join(", ") || "No functions deployed";
195269
+ return { outroMessage: summary };
195270
+ }
195271
+ function getDeployCommand(context) {
195272
+ return new Command("deploy").description("Deploy local functions to Base44").argument("[name]", "Deploy a single function by name").option("--prune", "Delete remote functions not found locally").option("-c, --concurrency <n>", "Number of functions to deploy in parallel").action(async (name2, options) => {
195273
+ await runCommand(() => {
195274
+ let concurrency;
195275
+ if (options.concurrency !== undefined) {
195276
+ const n2 = parseInt(options.concurrency, 10);
195277
+ if (Number.isNaN(n2) || n2 < 1) {
195278
+ throw new InvalidInputError("--concurrency must be a positive integer");
195279
+ }
195280
+ concurrency = n2;
195281
+ }
195282
+ return deployFunctionsAction(name2, { prune: options.prune, concurrency });
195283
+ }, { requireAuth: true }, context);
195284
+ });
195285
+ }
195286
+
195287
+ // src/cli/commands/functions/list.ts
195288
+ async function listFunctionsAction() {
195289
+ const { functions } = await listDeployedFunctions();
195290
+ if (functions.length === 0) {
195291
+ return { outroMessage: "No functions deployed" };
195292
+ }
195293
+ for (const fn of functions) {
195294
+ const autoCount = fn.automations.length;
195295
+ const autoLabel = autoCount > 0 ? theme.styles.dim(` (${autoCount} automation${autoCount > 1 ? "s" : ""})`) : "";
195296
+ R2.message(` ${fn.name}${autoLabel}`);
195297
+ }
195298
+ return {
195299
+ outroMessage: `${functions.length} function${functions.length !== 1 ? "s" : ""} deployed`
195300
+ };
195301
+ }
195302
+ function getListCommand(context) {
195303
+ return new Command("list").description("List deployed backend functions").action(async () => {
195304
+ await runCommand(listFunctionsAction, { requireAuth: true }, context);
195305
+ });
195306
+ }
195307
+
195308
+ // src/cli/commands/functions/new.ts
195309
+ import { dirname as dirname9, join as join12 } from "node:path";
195310
+ var FUNCTION_TEMPLATE = `Deno.serve(async (req: Request) => {
195311
+ return new Response(JSON.stringify({ message: "Hello from {{name}}!" }), {
195312
+ headers: { "Content-Type": "application/json" },
195313
+ });
195314
+ });
195315
+ `;
195316
+ async function newFunctionAction(name2) {
195317
+ if (name2.includes(".")) {
195318
+ throw new InvalidInputError("Function name cannot contain dots");
195319
+ }
195320
+ const { project: project2, functions } = await readProjectConfig();
195321
+ if (functions.some((f) => f.name === name2)) {
195322
+ throw new InvalidInputError(`Function "${name2}" already exists in this project`);
195323
+ }
195324
+ const configDir = dirname9(project2.configPath);
195325
+ const functionsDir = join12(configDir, project2.functionsDir);
195326
+ const functionDir = join12(functionsDir, name2);
195327
+ if (await pathExists(functionDir)) {
195328
+ throw new InvalidInputError(`Directory "${functionDir}" already exists`);
195329
+ }
195330
+ const configPath = join12(functionDir, "function.jsonc");
195331
+ const entryPath = join12(functionDir, "index.ts");
195332
+ await writeJsonFile(configPath, { name: name2, entry: "index.ts" });
195333
+ await writeFile(entryPath, FUNCTION_TEMPLATE.replace("{{name}}", name2));
195334
+ R2.success(`Created ${configPath}`);
195335
+ R2.success(`Created ${entryPath}`);
195336
+ return {
195337
+ outroMessage: `Function "${name2}" created. Deploy with: base44 functions deploy ${name2}`
195338
+ };
195339
+ }
195340
+ function getNewCommand(context) {
195341
+ return new Command("new").description("Create a new backend function from template").argument("<name>", "Name for the new function").action(async (name2) => {
195342
+ await runCommand(() => newFunctionAction(name2), { requireAuth: false }, context);
195343
+ });
195344
+ }
195345
+
195346
+ // src/cli/commands/functions/pull.ts
195347
+ import { dirname as dirname10, join as join13 } from "node:path";
195348
+ async function pullFunctionsAction(name2) {
195349
+ const { project: project2 } = await readProjectConfig();
195350
+ const configDir = dirname10(project2.configPath);
195351
+ const functionsDir = join13(configDir, project2.functionsDir);
195352
+ const remoteFunctions = await runTask("Fetching functions from Base44", async () => {
195353
+ const { functions } = await listDeployedFunctions();
195354
+ return functions;
195031
195355
  }, {
195032
- successMessage: "Functions deployed successfully",
195033
- errorMessage: "Failed to deploy functions"
195356
+ successMessage: "Functions fetched successfully",
195357
+ errorMessage: "Failed to fetch functions"
195034
195358
  });
195035
- if (result.deployed.length > 0) {
195036
- R2.success(`Deployed: ${result.deployed.join(", ")}`);
195359
+ const toPull = name2 ? remoteFunctions.filter((f) => f.name === name2) : remoteFunctions;
195360
+ if (name2 && toPull.length === 0) {
195361
+ return {
195362
+ outroMessage: `Function "${name2}" not found on remote`
195363
+ };
195037
195364
  }
195038
- if (result.deleted.length > 0) {
195039
- R2.warn(`Deleted: ${result.deleted.join(", ")}`);
195365
+ if (toPull.length === 0) {
195366
+ return { outroMessage: "No functions found on remote" };
195040
195367
  }
195041
- if (result.errors && result.errors.length > 0) {
195042
- const errorMessages = result.errors.map((e2) => `'${e2.name}' function: ${e2.message}`).join(`
195043
- `);
195044
- throw new ApiError(`Function deployment errors:
195045
- ${errorMessages}`, {
195046
- hints: [
195047
- { message: "Check the function code for syntax errors" },
195048
- { message: "Ensure all imports are valid" }
195049
- ]
195050
- });
195368
+ const { written, skipped } = await runTask("Writing function files", async () => {
195369
+ return await writeFunctions(functionsDir, toPull);
195370
+ }, {
195371
+ successMessage: "Function files written successfully",
195372
+ errorMessage: "Failed to write function files"
195373
+ });
195374
+ if (written.length > 0) {
195375
+ R2.success(`Written: ${written.join(", ")}`);
195051
195376
  }
195052
- return { outroMessage: "Functions deployed to Base44" };
195377
+ if (skipped.length > 0) {
195378
+ R2.info(`Skipped (unchanged): ${skipped.join(", ")}`);
195379
+ }
195380
+ return {
195381
+ outroMessage: `Pulled ${toPull.length} function${toPull.length !== 1 ? "s" : ""} to ${functionsDir}`
195382
+ };
195053
195383
  }
195054
- function getFunctionsDeployCommand(context) {
195055
- return new Command("functions").description("Manage project functions").addCommand(new Command("deploy").description("Deploy local functions to Base44").action(async () => {
195056
- await runCommand(deployFunctionsAction, { requireAuth: true }, context);
195057
- }));
195384
+ function getPullCommand(context) {
195385
+ return new Command("pull").description("Pull deployed functions from Base44 to local files").argument("[name]", "Pull a single function by name").action(async (name2) => {
195386
+ await runCommand(() => pullFunctionsAction(name2), { requireAuth: true }, context);
195387
+ });
195388
+ }
195389
+
195390
+ // src/cli/commands/functions/index.ts
195391
+ function getFunctionsCommand(context) {
195392
+ return new Command("functions").description("Manage backend functions").addCommand(getNewCommand(context)).addCommand(getDeployCommand(context)).addCommand(getPullCommand(context)).addCommand(getListCommand(context)).addCommand(getDeleteCommand(context));
195058
195393
  }
195059
195394
 
195060
195395
  // src/cli/commands/project/create.ts
195061
- import { basename as basename3, join as join11, resolve as resolve2 } from "node:path";
195396
+ import { basename as basename3, join as join14, resolve as resolve2 } from "node:path";
195062
195397
  var import_lodash = __toESM(require_lodash(), 1);
195063
195398
  var DEFAULT_TEMPLATE_ID = "backend-only";
195064
195399
  async function getTemplateById(templateId) {
@@ -195194,7 +195529,7 @@ async function executeCreate({
195194
195529
  updateMessage("Building project...");
195195
195530
  await execa({ cwd: resolvedPath, shell: true })`${buildCommand}`;
195196
195531
  updateMessage("Deploying site...");
195197
- return await deploySite(join11(resolvedPath, outputDirectory));
195532
+ return await deploySite(join14(resolvedPath, outputDirectory));
195198
195533
  }, {
195199
195534
  successMessage: theme.colors.base44Orange("Site deployed successfully"),
195200
195535
  errorMessage: "Failed to deploy site"
@@ -195296,7 +195631,7 @@ ${summaryLines.join(`
195296
195631
  }
195297
195632
  return { outroMessage: "App deployed successfully" };
195298
195633
  }
195299
- function getDeployCommand(context) {
195634
+ function getDeployCommand2(context) {
195300
195635
  return new Command("deploy").description("Deploy all project resources (entities, functions, agents, connectors, and site)").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
195301
195636
  await runCommand(() => deployAction({
195302
195637
  ...options,
@@ -195595,10 +195930,10 @@ function toPascalCase(name2) {
195595
195930
  return name2.split(/[-_\s]+/).map((w8) => w8.charAt(0).toUpperCase() + w8.slice(1)).join("");
195596
195931
  }
195597
195932
  // src/core/types/update-project.ts
195598
- import { join as join14 } from "node:path";
195933
+ import { join as join17 } from "node:path";
195599
195934
  var TYPES_INCLUDE_PATH = `${PROJECT_SUBDIR}/${TYPES_OUTPUT_SUBDIR}/*.d.ts`;
195600
195935
  async function updateProjectConfig(projectRoot) {
195601
- const tsconfigPath = join14(projectRoot, "tsconfig.json");
195936
+ const tsconfigPath = join17(projectRoot, "tsconfig.json");
195602
195937
  if (!await pathExists(tsconfigPath)) {
195603
195938
  return false;
195604
195939
  }
@@ -195641,7 +195976,7 @@ function getTypesCommand(context) {
195641
195976
  }
195642
195977
 
195643
195978
  // src/cli/commands/dev.ts
195644
- import { dirname as dirname12, join as join16 } from "node:path";
195979
+ import { dirname as dirname14, join as join19 } from "node:path";
195645
195980
 
195646
195981
  // src/cli/dev/dev-server/main.ts
195647
195982
  var import_cors = __toESM(require_lib4(), 1);
@@ -195789,10 +196124,10 @@ function createDevLogger() {
195789
196124
 
195790
196125
  // src/cli/dev/dev-server/function-manager.ts
195791
196126
  import { spawn as spawn2, spawnSync as spawnSync2 } from "node:child_process";
195792
- import { dirname as dirname11, join as join15 } from "node:path";
196127
+ import { dirname as dirname13, join as join18 } from "node:path";
195793
196128
  import { fileURLToPath as fileURLToPath7 } from "node:url";
195794
- var __dirname5 = dirname11(fileURLToPath7(import.meta.url));
195795
- var WRAPPER_PATH = join15(__dirname5, "../deno-runtime/main.js");
196129
+ var __dirname5 = dirname13(fileURLToPath7(import.meta.url));
196130
+ var WRAPPER_PATH = join18(__dirname5, "../deno-runtime/main.js");
195796
196131
  var READY_TIMEOUT = 30000;
195797
196132
 
195798
196133
  class FunctionManager {
@@ -196044,8 +196379,8 @@ async function devAction(options8) {
196044
196379
  port,
196045
196380
  loadResources: async () => {
196046
196381
  const { project: project2 } = await readProjectConfig();
196047
- const configDir = dirname12(project2.configPath);
196048
- const functions = await functionResource.readAll(join16(configDir, project2.functionsDir));
196382
+ const configDir = dirname14(project2.configPath);
196383
+ const functions = await functionResource.readAll(join19(configDir, project2.functionsDir));
196049
196384
  return { functions };
196050
196385
  }
196051
196386
  });
@@ -196162,13 +196497,13 @@ function createProgram(context) {
196162
196497
  program2.addCommand(getLogoutCommand(context));
196163
196498
  program2.addCommand(getCreateCommand(context));
196164
196499
  program2.addCommand(getDashboardCommand(context));
196165
- program2.addCommand(getDeployCommand(context));
196500
+ program2.addCommand(getDeployCommand2(context));
196166
196501
  program2.addCommand(getLinkCommand(context));
196167
196502
  program2.addCommand(getEjectCommand(context));
196168
196503
  program2.addCommand(getEntitiesPushCommand(context));
196169
196504
  program2.addCommand(getAgentsCommand(context));
196170
196505
  program2.addCommand(getConnectorsCommand(context));
196171
- program2.addCommand(getFunctionsDeployCommand(context));
196506
+ program2.addCommand(getFunctionsCommand(context));
196172
196507
  program2.addCommand(getSiteCommand(context));
196173
196508
  program2.addCommand(getTypesCommand(context));
196174
196509
  program2.addCommand(getDevCommand(context), { hidden: true });
@@ -196210,7 +196545,7 @@ function nanoid3(size = 21) {
196210
196545
  }
196211
196546
 
196212
196547
  // node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
196213
- import { dirname as dirname13, posix, sep } from "path";
196548
+ import { dirname as dirname15, posix, sep } from "path";
196214
196549
  function createModulerModifier() {
196215
196550
  const getModuleFromFileName = createGetModuleFromFilename();
196216
196551
  return async (frames) => {
@@ -196219,7 +196554,7 @@ function createModulerModifier() {
196219
196554
  return frames;
196220
196555
  };
196221
196556
  }
196222
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname13(process.argv[1]) : process.cwd(), isWindows4 = sep === "\\") {
196557
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname15(process.argv[1]) : process.cwd(), isWindows4 = sep === "\\") {
196223
196558
  const normalizedBase = isWindows4 ? normalizeWindowsPath2(basePath) : basePath;
196224
196559
  return (filename) => {
196225
196560
  if (!filename)
@@ -200436,4 +200771,4 @@ export {
200436
200771
  CLIExitError
200437
200772
  };
200438
200773
 
200439
- //# debugId=DF6807EB90E6667564756E2164756E21
200774
+ //# debugId=F8CDDD826B08FA8A64756E2164756E21