@base44-preview/cli 0.0.44-pr.382.bab01f6 → 0.0.44-pr.383.39531ce

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
@@ -238249,11 +238249,8 @@ var BackendFunctionSchema = FunctionConfigSchema.extend({
238249
238249
  entryPath: exports_external.string().min(1, "Entry path cannot be empty"),
238250
238250
  filePaths: exports_external.array(exports_external.string()).min(1, "Function must have at least one file")
238251
238251
  });
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()
238252
+ var DeploySingleFunctionResponseSchema = exports_external.object({
238253
+ status: exports_external.enum(["deployed", "unchanged"])
238257
238254
  });
238258
238255
  var FunctionInfoSchema = exports_external.object({
238259
238256
  name: exports_external.string(),
@@ -238280,29 +238277,15 @@ var FunctionLogEntrySchema = exports_external.object({
238280
238277
  var FunctionLogsResponseSchema = exports_external.array(FunctionLogEntrySchema);
238281
238278
 
238282
238279
  // src/core/resources/function/api.ts
238283
- function toDeployPayloadItem(fn) {
238284
- return {
238285
- name: fn.name,
238286
- entry: fn.entry,
238287
- files: fn.files,
238288
- automations: fn.automations
238289
- };
238290
- }
238291
- async function deployFunctions(functions) {
238280
+ async function deploySingleFunction(name2, payload) {
238292
238281
  const appClient = getAppClient();
238293
- const payload = {
238294
- functions: functions.map(toDeployPayloadItem)
238295
- };
238296
238282
  let response;
238297
238283
  try {
238298
- response = await appClient.put("backend-functions", {
238299
- json: payload,
238300
- timeout: false
238301
- });
238284
+ response = await appClient.put(`backend-functions/${encodeURIComponent(name2)}`, { json: payload, timeout: false });
238302
238285
  } catch (error48) {
238303
- throw await ApiError.fromHttpError(error48, "deploying functions");
238286
+ throw await ApiError.fromHttpError(error48, `deploying function "${name2}"`);
238304
238287
  }
238305
- const result = DeployFunctionsResponseSchema.safeParse(await response.json());
238288
+ const result = DeploySingleFunctionResponseSchema.safeParse(await response.json());
238306
238289
  if (!result.success) {
238307
238290
  throw new SchemaValidationError("Invalid response from server", result.error);
238308
238291
  }
@@ -238318,6 +238301,20 @@ async function deleteSingleFunction(name2) {
238318
238301
  throw await ApiError.fromHttpError(error48, `deleting function "${name2}"`);
238319
238302
  }
238320
238303
  }
238304
+ async function listDeployedFunctions() {
238305
+ const appClient = getAppClient();
238306
+ let response;
238307
+ try {
238308
+ response = await appClient.get("backend-functions", { timeout: 30000 });
238309
+ } catch (error48) {
238310
+ throw await ApiError.fromHttpError(error48, "listing deployed functions");
238311
+ }
238312
+ const result = ListFunctionsResponseSchema.safeParse(await response.json());
238313
+ if (!result.success) {
238314
+ throw new SchemaValidationError("Invalid response from server", result.error);
238315
+ }
238316
+ return result.data;
238317
+ }
238321
238318
  function buildLogsQueryString(filters) {
238322
238319
  const params = new URLSearchParams;
238323
238320
  if (filters.since) {
@@ -238354,20 +238351,6 @@ async function fetchFunctionLogs(functionName, filters = {}) {
238354
238351
  }
238355
238352
  return result.data;
238356
238353
  }
238357
- async function listDeployedFunctions() {
238358
- const appClient = getAppClient();
238359
- let response;
238360
- try {
238361
- response = await appClient.get("backend-functions", { timeout: 30000 });
238362
- } catch (error48) {
238363
- throw await ApiError.fromHttpError(error48, "listing deployed functions");
238364
- }
238365
- const result = ListFunctionsResponseSchema.safeParse(await response.json());
238366
- if (!result.success) {
238367
- throw new SchemaValidationError("Invalid response from server", result.error);
238368
- }
238369
- return result.data;
238370
- }
238371
238354
  // src/core/resources/function/config.ts
238372
238355
  import { basename as basename2, dirname as dirname3, join as join5, relative } from "node:path";
238373
238356
  async function readFunctionConfig(configPath) {
@@ -238449,19 +238432,65 @@ async function readAllFunctions(functionsDir) {
238449
238432
  import { dirname as dirname4, relative as relative2 } from "node:path";
238450
238433
  async function loadFunctionCode(fn) {
238451
238434
  const functionDir = dirname4(fn.entryPath);
238452
- const loadedFiles = await Promise.all(fn.filePaths.map(async (filePath) => {
238435
+ const resolvedFiles = await Promise.all(fn.filePaths.map(async (filePath) => {
238453
238436
  const content = await readTextFile(filePath);
238454
238437
  const path11 = relative2(functionDir, filePath).split(/[/\\]/).join("/");
238455
238438
  return { path: path11, content };
238456
238439
  }));
238457
- return { ...fn, files: loadedFiles };
238440
+ return { ...fn, files: resolvedFiles };
238458
238441
  }
238459
- async function pushFunctions(functions) {
238460
- if (functions.length === 0) {
238461
- return { deployed: [], deleted: [], skipped: [], errors: null };
238442
+ async function deployOne(fn) {
238443
+ const start = Date.now();
238444
+ try {
238445
+ const functionWithCode = await loadFunctionCode(fn);
238446
+ const response = await deploySingleFunction(functionWithCode.name, {
238447
+ entry: functionWithCode.entry,
238448
+ files: functionWithCode.files,
238449
+ automations: functionWithCode.automations
238450
+ });
238451
+ return {
238452
+ name: functionWithCode.name,
238453
+ status: response.status,
238454
+ durationMs: Date.now() - start
238455
+ };
238456
+ } catch (error48) {
238457
+ return {
238458
+ name: fn.name,
238459
+ status: "error",
238460
+ error: error48 instanceof Error ? error48.message : String(error48)
238461
+ };
238462
238462
  }
238463
- const functionsWithCode = await Promise.all(functions.map(loadFunctionCode));
238464
- return deployFunctions(functionsWithCode);
238463
+ }
238464
+ async function deployFunctionsSequentially(functions, options) {
238465
+ if (functions.length === 0)
238466
+ return [];
238467
+ const results = [];
238468
+ for (const fn of functions) {
238469
+ options?.onStart?.([fn.name]);
238470
+ const result = await deployOne(fn);
238471
+ results.push(result);
238472
+ options?.onResult?.(result);
238473
+ }
238474
+ return results;
238475
+ }
238476
+ async function pruneRemovedFunctions(localFunctionNames) {
238477
+ const remote = await listDeployedFunctions();
238478
+ const localSet = new Set(localFunctionNames);
238479
+ const toDelete = remote.functions.filter((f) => !localSet.has(f.name));
238480
+ const results = [];
238481
+ for (const fn of toDelete) {
238482
+ try {
238483
+ await deleteSingleFunction(fn.name);
238484
+ results.push({ name: fn.name, deleted: true });
238485
+ } catch (error48) {
238486
+ results.push({
238487
+ name: fn.name,
238488
+ deleted: false,
238489
+ error: error48 instanceof Error ? error48.message : String(error48)
238490
+ });
238491
+ }
238492
+ }
238493
+ return results;
238465
238494
  }
238466
238495
  // src/core/resources/function/pull.ts
238467
238496
  import { join as join6 } from "node:path";
@@ -238526,7 +238555,7 @@ async function isFunctionUnchanged(functionDir, fn) {
238526
238555
  // src/core/resources/function/resource.ts
238527
238556
  var functionResource = {
238528
238557
  readAll: readAllFunctions,
238529
- push: pushFunctions
238558
+ push: (functions) => deployFunctionsSequentially(functions)
238530
238559
  };
238531
238560
  // src/core/project/config.ts
238532
238561
  async function findConfigInDir(dir) {
@@ -247759,41 +247788,101 @@ function getDeleteCommand(context) {
247759
247788
  });
247760
247789
  }
247761
247790
 
247791
+ // src/cli/commands/functions/formatDeployResult.ts
247792
+ function formatDuration(ms) {
247793
+ return `${(ms / 1000).toFixed(1)}s`;
247794
+ }
247795
+ function formatDeployResult(result) {
247796
+ const label = result.name.padEnd(25);
247797
+ if (result.status === "deployed") {
247798
+ const timing = result.durationMs ? theme.styles.dim(` (${formatDuration(result.durationMs)})`) : "";
247799
+ R2.success(`${label} deployed${timing}`);
247800
+ } else if (result.status === "unchanged") {
247801
+ R2.success(`${label} unchanged`);
247802
+ } else {
247803
+ R2.error(`${label} error: ${result.error}`);
247804
+ }
247805
+ }
247806
+
247807
+ // src/cli/commands/functions/parseNames.ts
247808
+ function parseNames2(args) {
247809
+ return args.flatMap((arg) => arg.split(",")).map((n2) => n2.trim()).filter(Boolean);
247810
+ }
247811
+
247762
247812
  // src/cli/commands/functions/deploy.ts
247763
- async function deployFunctionsAction() {
247813
+ function resolveFunctionsToDeploy(names, allFunctions) {
247814
+ if (names.length === 0)
247815
+ return allFunctions;
247816
+ const notFound = names.filter((n2) => !allFunctions.some((f) => f.name === n2));
247817
+ if (notFound.length > 0) {
247818
+ throw new InvalidInputError(`Function${notFound.length > 1 ? "s" : ""} not found in project: ${notFound.join(", ")}`);
247819
+ }
247820
+ return allFunctions.filter((f) => names.includes(f.name));
247821
+ }
247822
+ function formatPruneResults(pruneResults) {
247823
+ for (const pruneResult of pruneResults) {
247824
+ if (pruneResult.deleted) {
247825
+ R2.success(`${pruneResult.name.padEnd(25)} deleted`);
247826
+ } else {
247827
+ R2.error(`${pruneResult.name.padEnd(25)} error: ${pruneResult.error}`);
247828
+ }
247829
+ }
247830
+ if (pruneResults.length > 0) {
247831
+ const pruned = pruneResults.filter((r) => r.deleted).length;
247832
+ R2.info(`${pruned} function${pruned !== 1 ? "s" : ""} removed`);
247833
+ }
247834
+ }
247835
+ function buildDeploySummary(results) {
247836
+ const deployed = results.filter((r) => r.status === "deployed").length;
247837
+ const unchanged = results.filter((r) => r.status === "unchanged").length;
247838
+ const failed = results.filter((r) => r.status === "error").length;
247839
+ const parts = [];
247840
+ if (deployed > 0)
247841
+ parts.push(`${deployed} deployed`);
247842
+ if (unchanged > 0)
247843
+ parts.push(`${unchanged} unchanged`);
247844
+ if (failed > 0)
247845
+ parts.push(`${failed} error${failed !== 1 ? "s" : ""}`);
247846
+ return parts.join(", ") || "No functions deployed";
247847
+ }
247848
+ async function deployFunctionsAction(names, options) {
247849
+ if (options.force && names.length > 0) {
247850
+ throw new InvalidInputError("--force cannot be used when specifying function names");
247851
+ }
247764
247852
  const { functions } = await readProjectConfig();
247765
- if (functions.length === 0) {
247853
+ const toDeploy = resolveFunctionsToDeploy(names, functions);
247854
+ if (toDeploy.length === 0) {
247766
247855
  return {
247767
247856
  outroMessage: "No functions found. Create functions in the 'functions' directory."
247768
247857
  };
247769
247858
  }
247770
- R2.info(`Found ${functions.length} ${functions.length === 1 ? "function" : "functions"} to deploy`);
247771
- const result = await runTask("Deploying functions to Base44", async () => {
247772
- return await pushFunctions(functions);
247773
- }, {
247774
- successMessage: "Functions deployed successfully",
247775
- errorMessage: "Failed to deploy functions"
247859
+ R2.info(`Found ${toDeploy.length} ${toDeploy.length === 1 ? "function" : "functions"} to deploy`);
247860
+ let completed = 0;
247861
+ const total = toDeploy.length;
247862
+ const results = await deployFunctionsSequentially(toDeploy, {
247863
+ onStart: (startNames) => {
247864
+ const label = startNames.length === 1 ? startNames[0] : `${startNames.length} functions`;
247865
+ R2.step(theme.styles.dim(`[${completed + 1}/${total}] Deploying ${label}...`));
247866
+ },
247867
+ onResult: (result) => {
247868
+ completed++;
247869
+ formatDeployResult(result);
247870
+ }
247776
247871
  });
247777
- if (result.deployed.length > 0) {
247778
- R2.success(`Deployed: ${result.deployed.join(", ")}`);
247779
- }
247780
- if (result.deleted.length > 0) {
247781
- R2.warn(`Deleted: ${result.deleted.join(", ")}`);
247782
- }
247783
- if (result.errors && result.errors.length > 0) {
247784
- throw new ApiError("Function deployment errors", {
247785
- details: result.errors.map((e2) => `'${e2.name}': ${e2.message}`),
247786
- hints: [
247787
- { message: "Check the function code for syntax errors" },
247788
- { message: "Ensure all imports are valid" }
247789
- ]
247790
- });
247872
+ if (options.force) {
247873
+ R2.info("Removing remote functions not found locally...");
247874
+ const allLocalNames = functions.map((f) => f.name);
247875
+ const pruneResults = await pruneRemovedFunctions(allLocalNames);
247876
+ formatPruneResults(pruneResults);
247791
247877
  }
247792
- return { outroMessage: "Functions deployed to Base44" };
247878
+ return { outroMessage: buildDeploySummary(results) };
247793
247879
  }
247794
247880
  function getDeployCommand(context) {
247795
- return new Command("deploy").description("Deploy local functions to Base44").action(async () => {
247796
- await runCommand(deployFunctionsAction, { requireAuth: true }, context);
247881
+ 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) => {
247882
+ await runCommand(() => {
247883
+ const names = parseNames2(rawNames);
247884
+ return deployFunctionsAction(names, options);
247885
+ }, { requireAuth: true }, context);
247797
247886
  });
247798
247887
  }
247799
247888
 
@@ -255655,4 +255744,4 @@ export {
255655
255744
  CLIExitError
255656
255745
  };
255657
255746
 
255658
- //# debugId=6D7955D702A30EFA64756E2164756E21
255747
+ //# debugId=E5A92FA7C3FBB16864756E2164756E21