@base44-preview/cli 0.1.14-pr.625.c566f53 → 0.1.14-pr.626.0acc5e4

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
@@ -31177,7 +31177,7 @@ function cleanDoc(doc) {
31177
31177
  return mapDoc(doc, (currentDoc) => cleanDocFn(currentDoc));
31178
31178
  }
31179
31179
  function replaceEndOfLine(doc, replacement = literalline) {
31180
- return mapDoc(doc, (currentDoc) => typeof currentDoc === "string" ? join28(replacement, currentDoc.split(`
31180
+ return mapDoc(doc, (currentDoc) => typeof currentDoc === "string" ? join29(replacement, currentDoc.split(`
31181
31181
  `)) : currentDoc);
31182
31182
  }
31183
31183
  function canBreakFn(doc) {
@@ -31257,7 +31257,7 @@ function indentIfBreak(contents, options) {
31257
31257
  negate: options.negate
31258
31258
  };
31259
31259
  }
31260
- function join28(separator, docs) {
31260
+ function join29(separator, docs) {
31261
31261
  assertDoc(separator);
31262
31262
  assertDocArray(docs);
31263
31263
  const parts = [];
@@ -31968,7 +31968,7 @@ var init_doc = __esm(() => {
31968
31968
  MODE_FLAT = Symbol("MODE_FLAT");
31969
31969
  DOC_FILL_PRINTED_LENGTH = Symbol("DOC_FILL_PRINTED_LENGTH");
31970
31970
  builders = {
31971
- join: join28,
31971
+ join: join29,
31972
31972
  line,
31973
31973
  softline,
31974
31974
  hardline,
@@ -228634,10 +228634,6 @@ class InternalError extends SystemError {
228634
228634
  }
228635
228635
  }
228636
228636
 
228637
- class ResourceDeploymentError extends SystemError {
228638
- code = "RESOURCE_DEPLOYMENT_FAILED";
228639
- }
228640
-
228641
228637
  class TypeGenerationError extends SystemError {
228642
228638
  code = "TYPE_GENERATION_ERROR";
228643
228639
  constructor(message, entityName, cause) {
@@ -228783,7 +228779,7 @@ function normalizeBase44Env() {
228783
228779
  loadProjectEnvFiles();
228784
228780
 
228785
228781
  // src/cli/index.ts
228786
- import { dirname as dirname28, join as join37 } from "node:path";
228782
+ import { dirname as dirname27, join as join38 } from "node:path";
228787
228783
  import { fileURLToPath as fileURLToPath6 } from "node:url";
228788
228784
 
228789
228785
  // ../../node_modules/@clack/core/dist/index.mjs
@@ -229909,10 +229905,8 @@ var {
229909
229905
  Help: Help2
229910
229906
  } = exports_commander;
229911
229907
 
229912
- // src/cli/commands/functions/parseNames.ts
229913
- function parseNames(args) {
229914
- return args.flatMap((arg) => arg.split(",")).map((n) => n.trim()).filter(Boolean);
229915
- }
229908
+ // src/cli/commands/agent-skills/pull.ts
229909
+ import { dirname as dirname11, join as join18 } from "node:path";
229916
229910
  // ../../node_modules/chalk/source/vendor/ansi-styles/index.js
229917
229911
  var ANSI_BACKGROUND_OFFSET = 10;
229918
229912
  var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
@@ -230726,7 +230720,6 @@ var ProjectConfigSchema = object({
230726
230720
  site: SiteConfigSchema.optional(),
230727
230721
  entitiesDir: string2().optional().default("entities"),
230728
230722
  functionsDir: string2().optional().default("functions"),
230729
- actorsDir: string2().optional().default("actors"),
230730
230723
  agentsDir: string2().optional().default("agents"),
230731
230724
  agentSkillsDir: string2().optional().default("agent-skills"),
230732
230725
  connectorsDir: string2().optional().default("connectors"),
@@ -236679,7 +236672,7 @@ async function getSiteUrl() {
236679
236672
  return result.data.url;
236680
236673
  }
236681
236674
  // src/core/project/config.ts
236682
- import { dirname as dirname10, join as join12 } from "node:path";
236675
+ import { dirname as dirname8, join as join11 } from "node:path";
236683
236676
 
236684
236677
  // src/core/project/plugins.ts
236685
236678
  import { createRequire as createRequire2 } from "node:module";
@@ -236717,159 +236710,6 @@ function markPluginEntities(entities, pluginNamespace) {
236717
236710
  }));
236718
236711
  }
236719
236712
 
236720
- // src/core/resources/actor/schema.ts
236721
- var RESERVED_NAMES = new Set(("await break case catch class const continue debugger default delete do else " + "enum export extends false finally for function if import in instanceof let " + "new null return static super switch this throw true try typeof var void " + "while with yield implements interface package private protected public " + "eval arguments").split(" "));
236722
- var ActorNameSchema = string2().regex(/^[A-Za-z_][A-Za-z0-9_]{0,127}$(?![\s\S])/, "Actor names must be JavaScript identifiers of at most 128 characters (letters, digits, and underscores)").refine((name) => !RESERVED_NAMES.has(name), {
236723
- message: "Actor names cannot be JavaScript reserved words"
236724
- });
236725
- function validateActorName(name) {
236726
- const result = ActorNameSchema.safeParse(name);
236727
- if (!result.success) {
236728
- throw new SchemaValidationError(`Invalid actor name '${name}'`, result.error);
236729
- }
236730
- }
236731
- var ActorDefinitionSchema = object({
236732
- name: ActorNameSchema,
236733
- entry: _enum(["entry.ts", "entry.js"]),
236734
- entryPath: string2().min(1),
236735
- filePaths: array(string2()).min(1),
236736
- source: object({ type: literal("project") })
236737
- });
236738
- var ActorDeployPayloadSchema = object({
236739
- entry: _enum(["entry.ts", "entry.js"]),
236740
- files: array(object({ path: string2().min(1), content: string2() })).min(1)
236741
- });
236742
- var DeployActorResponseSchema = object({
236743
- status: _enum(["deployed", "unchanged"]),
236744
- warnings: array(string2()).optional().default([])
236745
- });
236746
- var DeleteActorResponseSchema = object({ status: literal("deleted"), handler_name: ActorNameSchema }).transform((data) => ({
236747
- status: data.status,
236748
- handlerName: data.handler_name
236749
- }));
236750
-
236751
- // src/core/resources/actor/api.ts
236752
- async function deploySingleActor(name, payload) {
236753
- validateActorName(name);
236754
- const input = ActorDeployPayloadSchema.safeParse(payload);
236755
- if (!input.success)
236756
- throw new SchemaValidationError("Invalid actor deployment", input.error);
236757
- let response;
236758
- try {
236759
- response = await getAppClient().put(`actors/${encodeURIComponent(name)}`, {
236760
- json: input.data,
236761
- timeout: false
236762
- });
236763
- } catch (error) {
236764
- throw await ApiError.fromHttpError(error, `deploying actor "${name}"`);
236765
- }
236766
- const result = DeployActorResponseSchema.safeParse(await response.json());
236767
- if (!result.success)
236768
- throw new SchemaValidationError("Invalid actor deployment response", result.error);
236769
- return result.data;
236770
- }
236771
- async function deleteSingleActor(name) {
236772
- validateActorName(name);
236773
- let response;
236774
- try {
236775
- response = await getAppClient().delete(`actors/${encodeURIComponent(name)}`, { timeout: 60000 });
236776
- } catch (error) {
236777
- throw await ApiError.fromHttpError(error, `deleting actor "${name}"`);
236778
- }
236779
- const result = DeleteActorResponseSchema.safeParse(await response.json());
236780
- if (!result.success)
236781
- throw new SchemaValidationError("Invalid actor deletion response", result.error);
236782
- return result.data;
236783
- }
236784
- // src/core/resources/actor/config.ts
236785
- import { basename as basename3, dirname as dirname6, join as join5, relative } from "node:path";
236786
- async function readAllActors(actorsDir) {
236787
- if (!await pathExists(actorsDir))
236788
- return [];
236789
- const entries = await globby(ENTRY_FILE_GLOB, {
236790
- cwd: actorsDir,
236791
- absolute: true,
236792
- ignore: ENTRY_IGNORE_DOT_PATHS
236793
- });
236794
- const actors = [];
236795
- const names = new Set;
236796
- for (const entryPath of entries.sort()) {
236797
- const actorDir = dirname6(entryPath);
236798
- const name = relative(actorsDir, actorDir).split(/[/\\]/).join("/");
236799
- if (!name) {
236800
- throw new InvalidInputError("entry.ts or entry.js found directly in the actors directory — it must be inside a named subfolder");
236801
- }
236802
- if (name.includes("/")) {
236803
- throw new InvalidInputError(`Invalid actor name '${name}' — actors cannot be nested`);
236804
- }
236805
- validateActorName(name);
236806
- if (names.has(name)) {
236807
- throw new ConfigInvalidError(`Duplicate actor name "${name}" in ${actorsDir}`, actorsDir);
236808
- }
236809
- names.add(name);
236810
- const filePaths = (await globby(BACKEND_FILE_GLOB, { cwd: actorDir, absolute: true })).sort();
236811
- const entry = basename3(entryPath) === "entry.js" ? "entry.js" : "entry.ts";
236812
- actors.push({
236813
- name,
236814
- entry,
236815
- entryPath: join5(actorDir, entry),
236816
- filePaths,
236817
- source: { type: "project" }
236818
- });
236819
- }
236820
- return actors;
236821
- }
236822
- // src/core/resources/actor/deploy.ts
236823
- import { dirname as dirname7, relative as relative2 } from "node:path";
236824
- function actorOperationError(name, error) {
236825
- return {
236826
- name,
236827
- status: "error",
236828
- error: error instanceof Error ? error.message : String(error),
236829
- ...error instanceof ApiError ? { statusCode: error.statusCode, requestId: error.requestId } : {}
236830
- };
236831
- }
236832
- function describeActorResult(result) {
236833
- if (result.status !== "error")
236834
- return `${result.name}: ${result.status}`;
236835
- const context = [
236836
- result.statusCode === undefined ? undefined : `HTTP ${result.statusCode}`,
236837
- result.requestId ? `request ${result.requestId}` : undefined
236838
- ].filter(Boolean).join(", ");
236839
- return `${result.name}: error — ${result.error}${context ? ` (${context})` : ""}`;
236840
- }
236841
- async function deployOne(actor) {
236842
- const start = Date.now();
236843
- try {
236844
- const actorDir = dirname7(actor.entryPath);
236845
- const files = await Promise.all(actor.filePaths.map(async (filePath) => ({
236846
- path: relative2(actorDir, filePath).split(/[/\\]/).join("/"),
236847
- content: await readTextFile(filePath)
236848
- })));
236849
- const response = await deploySingleActor(actor.name, {
236850
- entry: actor.entry,
236851
- files
236852
- });
236853
- return { name: actor.name, ...response, durationMs: Date.now() - start };
236854
- } catch (error) {
236855
- return actorOperationError(actor.name, error);
236856
- }
236857
- }
236858
- async function deployActorsSequentially(actors, options) {
236859
- const results = [];
236860
- for (const actor of actors) {
236861
- options?.onStart?.(actor.name);
236862
- const result = await deployOne(actor);
236863
- results.push(result);
236864
- options?.onResult?.(result);
236865
- }
236866
- return results;
236867
- }
236868
- // src/core/resources/actor/resource.ts
236869
- var actorResource = {
236870
- readAll: readAllActors,
236871
- push: deployActorsSequentially
236872
- };
236873
236713
  // src/core/resources/agent/schema.ts
236874
236714
  var EntityOperationSchema = _enum(["create", "update", "delete", "read"]);
236875
236715
  var EntityToolConfigSchema = object({
@@ -236948,7 +236788,7 @@ async function fetchAgents() {
236948
236788
  return result.data;
236949
236789
  }
236950
236790
  // src/core/resources/agent/config.ts
236951
- import { join as join6, normalize } from "node:path";
236791
+ import { join as join5, normalize } from "node:path";
236952
236792
  import { isDeepStrictEqual } from "node:util";
236953
236793
  async function readAgentFile(agentPath) {
236954
236794
  const raw = await readJsonFile(agentPath);
@@ -236993,12 +236833,12 @@ async function readAllAgents(agentsDir) {
236993
236833
  return [...nameToEntry.values()].map((e) => e.data);
236994
236834
  }
236995
236835
  function findAvailablePath(agentsDir, name, claimedPaths) {
236996
- const base = join6(agentsDir, `${name}.${CONFIG_FILE_EXTENSION}`);
236836
+ const base = join5(agentsDir, `${name}.${CONFIG_FILE_EXTENSION}`);
236997
236837
  if (!claimedPaths.has(base)) {
236998
236838
  return base;
236999
236839
  }
237000
236840
  for (let i = 1;; i++) {
237001
- const candidate = join6(agentsDir, `${name}_${i}.${CONFIG_FILE_EXTENSION}`);
236841
+ const candidate = join5(agentsDir, `${name}_${i}.${CONFIG_FILE_EXTENSION}`);
237002
236842
  if (!claimedPaths.has(candidate)) {
237003
236843
  return candidate;
237004
236844
  }
@@ -237113,7 +236953,7 @@ async function pushAgentSkills(skills) {
237113
236953
  }
237114
236954
  // src/core/resources/agent-skill/config.ts
237115
236955
  var import_front_matter = __toESM(require_front_matter(), 1);
237116
- import { join as join7 } from "node:path";
236956
+ import { join as join6 } from "node:path";
237117
236957
 
237118
236958
  // ../../node_modules/yaml/dist/index.js
237119
236959
  var composer = require_composer();
@@ -237199,7 +237039,7 @@ async function writeAgentSkills(dir, remote) {
237199
237039
  const deleted = [];
237200
237040
  for (const skill of existing) {
237201
237041
  if (!remoteNames.has(skill.name)) {
237202
- await deleteFile(join7(dir, `${skill.name}.md`));
237042
+ await deleteFile(join6(dir, `${skill.name}.md`));
237203
237043
  deleted.push(skill.name);
237204
237044
  }
237205
237045
  }
@@ -237210,7 +237050,7 @@ async function writeAgentSkills(dir, remote) {
237210
237050
  if (prev && prev.description === skill.description && prev.body === skill.body) {
237211
237051
  continue;
237212
237052
  }
237213
- await writeFile(join7(dir, `${skill.name}.md`), serializeSkillFile(skill));
237053
+ await writeFile(join6(dir, `${skill.name}.md`), serializeSkillFile(skill));
237214
237054
  written.push(skill.name);
237215
237055
  }
237216
237056
  return { written, deleted };
@@ -237336,7 +237176,7 @@ async function pushAuthConfigToApi(config) {
237336
237176
  return result.data.authConfig;
237337
237177
  }
237338
237178
  // src/core/resources/auth-config/config.ts
237339
- import { join as join8 } from "node:path";
237179
+ import { join as join7 } from "node:path";
237340
237180
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
237341
237181
  var AUTH_CONFIG_FILENAME = `config.${CONFIG_FILE_EXTENSION}`;
237342
237182
  var DEFAULT_AUTH_CONFIG = {
@@ -237352,7 +237192,7 @@ var DEFAULT_AUTH_CONFIG = {
237352
237192
  useWorkspaceSSO: false
237353
237193
  };
237354
237194
  function getAuthConfigPath(authDir) {
237355
- return join8(authDir, AUTH_CONFIG_FILENAME);
237195
+ return join7(authDir, AUTH_CONFIG_FILENAME);
237356
237196
  }
237357
237197
  async function readAuthConfig(authDir) {
237358
237198
  const filePath = getAuthConfigPath(authDir);
@@ -238004,7 +237844,7 @@ async function removeStripe() {
238004
237844
  return result.data;
238005
237845
  }
238006
237846
  // src/core/resources/connector/config.ts
238007
- import { join as join9 } from "node:path";
237847
+ import { join as join8 } from "node:path";
238008
237848
  import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
238009
237849
  async function readConnectorFile(connectorPath) {
238010
237850
  const parsed = await readJsonFile(connectorPath);
@@ -238065,7 +237905,7 @@ async function writeConnectors(connectorsDir, remoteConnectors) {
238065
237905
  if (existing && isDeepStrictEqual3(existing.data, connector)) {
238066
237906
  continue;
238067
237907
  }
238068
- const filePath = existing?.filePath ?? join9(connectorsDir, `${connector.type}.${CONFIG_FILE_EXTENSION}`);
237908
+ const filePath = existing?.filePath ?? join8(connectorsDir, `${connector.type}.${CONFIG_FILE_EXTENSION}`);
238069
237909
  await writeJsonFile(filePath, connector);
238070
237910
  written.push(connector.type);
238071
237911
  }
@@ -238671,7 +238511,7 @@ async function fetchFunctionLogs(functionName, filters = {}) {
238671
238511
  return result.data;
238672
238512
  }
238673
238513
  // src/core/resources/function/config.ts
238674
- import { basename as basename4, dirname as dirname8, join as join10, relative as relative3, resolve as resolve2 } from "node:path";
238514
+ import { basename as basename3, dirname as dirname6, join as join9, relative, resolve as resolve2 } from "node:path";
238675
238515
  async function readSharedFiles(functionsDir) {
238676
238516
  const sharedDir = resolve2(functionsDir, "..", "shared");
238677
238517
  if (!await pathExists(sharedDir)) {
@@ -238689,8 +238529,8 @@ async function readFunctionConfig(configPath) {
238689
238529
  }
238690
238530
  async function readFunction(configPath, sharedFiles) {
238691
238531
  const config = await readFunctionConfig(configPath);
238692
- const functionDir = dirname8(configPath);
238693
- const entryPath = join10(functionDir, config.entry);
238532
+ const functionDir = dirname6(configPath);
238533
+ const entryPath = join9(functionDir, config.entry);
238694
238534
  if (!await pathExists(entryPath)) {
238695
238535
  throw new InvalidInputError(`Function entry file not found: ${entryPath} (referenced in ${configPath})`, {
238696
238536
  hints: [{ message: "Check the 'entry' field in your function config" }]
@@ -238722,18 +238562,18 @@ async function readAllFunctions(functionsDir) {
238722
238562
  absolute: true,
238723
238563
  ignore: ENTRY_IGNORE_DOT_PATHS
238724
238564
  });
238725
- const configFilesDirs = new Set(configFiles.map((f) => dirname8(f)));
238726
- const entryFilesWithoutConfig = entryFiles.filter((entryFile) => !configFilesDirs.has(dirname8(entryFile)));
238565
+ const configFilesDirs = new Set(configFiles.map((f) => dirname6(f)));
238566
+ const entryFilesWithoutConfig = entryFiles.filter((entryFile) => !configFilesDirs.has(dirname6(entryFile)));
238727
238567
  const sharedFiles = await readSharedFiles(functionsDir);
238728
238568
  const functionsFromConfig = await Promise.all(configFiles.map((configPath) => readFunction(configPath, sharedFiles)));
238729
238569
  const functionsWithoutConfig = await Promise.all(entryFilesWithoutConfig.map(async (entryFile) => {
238730
- const functionDir = dirname8(entryFile);
238570
+ const functionDir = dirname6(entryFile);
238731
238571
  const filePaths = await globby(BACKEND_FILE_GLOB, {
238732
238572
  cwd: functionDir,
238733
238573
  absolute: true
238734
238574
  });
238735
238575
  const allFilePaths = [...new Set([...filePaths, ...sharedFiles])];
238736
- const name = relative3(functionsDir, functionDir).split(/[/\\]/).join("/");
238576
+ const name = relative(functionsDir, functionDir).split(/[/\\]/).join("/");
238737
238577
  if (!name) {
238738
238578
  throw new InvalidInputError("entry.ts found directly in the functions directory — it must be inside a named subfolder", {
238739
238579
  hints: [
@@ -238743,7 +238583,7 @@ async function readAllFunctions(functionsDir) {
238743
238583
  ]
238744
238584
  });
238745
238585
  }
238746
- const entry = basename4(entryFile);
238586
+ const entry = basename3(entryFile);
238747
238587
  const functionData = {
238748
238588
  name,
238749
238589
  entry,
@@ -238770,17 +238610,17 @@ async function readAllFunctions(functionsDir) {
238770
238610
  return functions;
238771
238611
  }
238772
238612
  // src/core/resources/function/deploy.ts
238773
- import { dirname as dirname9, relative as relative4 } from "node:path";
238613
+ import { dirname as dirname7, relative as relative2 } from "node:path";
238774
238614
  async function loadFunctionCode(fn) {
238775
- const functionDir = dirname9(fn.entryPath);
238615
+ const functionDir = dirname7(fn.entryPath);
238776
238616
  const resolvedFiles = await Promise.all(fn.filePaths.map(async (filePath) => {
238777
238617
  const content = await readTextFile(filePath);
238778
- const path = relative4(functionDir, filePath).split(/[/\\]/).join("/");
238618
+ const path = relative2(functionDir, filePath).split(/[/\\]/).join("/");
238779
238619
  return { path, content };
238780
238620
  }));
238781
238621
  return { ...fn, files: resolvedFiles };
238782
238622
  }
238783
- async function deployOne2(fn) {
238623
+ async function deployOne(fn) {
238784
238624
  const start = Date.now();
238785
238625
  try {
238786
238626
  const functionWithCode = await loadFunctionCode(fn);
@@ -238808,7 +238648,7 @@ async function deployFunctionsSequentially(functions, options) {
238808
238648
  const results = [];
238809
238649
  for (const fn of functions) {
238810
238650
  options?.onStart?.([fn.name]);
238811
- const result = await deployOne2(fn);
238651
+ const result = await deployOne(fn);
238812
238652
  results.push(result);
238813
238653
  options?.onResult?.(result);
238814
238654
  }
@@ -238839,14 +238679,14 @@ async function pruneRemovedFunctions(localFunctionNames, options) {
238839
238679
  return results;
238840
238680
  }
238841
238681
  // src/core/resources/function/pull.ts
238842
- import { join as join11 } from "node:path";
238682
+ import { join as join10 } from "node:path";
238843
238683
  import { isDeepStrictEqual as isDeepStrictEqual4 } from "node:util";
238844
238684
  async function writeFunctions(functionsDir, functions) {
238845
238685
  const written = [];
238846
238686
  const skipped = [];
238847
238687
  for (const fn of functions) {
238848
- const functionDir = join11(functionsDir, fn.name);
238849
- const configPath = join11(functionDir, "function.jsonc");
238688
+ const functionDir = join10(functionsDir, fn.name);
238689
+ const configPath = join10(functionDir, "function.jsonc");
238850
238690
  if (await isFunctionUnchanged(functionDir, fn)) {
238851
238691
  skipped.push(fn.name);
238852
238692
  continue;
@@ -238860,7 +238700,7 @@ async function writeFunctions(functionsDir, functions) {
238860
238700
  }
238861
238701
  await writeJsonFile(configPath, config);
238862
238702
  for (const file of fn.files) {
238863
- await writeFile(join11(functionDir, file.path), file.content);
238703
+ await writeFile(join10(functionDir, file.path), file.content);
238864
238704
  }
238865
238705
  written.push(fn.name);
238866
238706
  }
@@ -238870,7 +238710,7 @@ async function isFunctionUnchanged(functionDir, fn) {
238870
238710
  if (!await pathExists(functionDir)) {
238871
238711
  return false;
238872
238712
  }
238873
- const configPath = join11(functionDir, "function.jsonc");
238713
+ const configPath = join10(functionDir, "function.jsonc");
238874
238714
  try {
238875
238715
  const localConfig = await readJsonFile(configPath);
238876
238716
  if (localConfig.entry !== fn.entry) {
@@ -238883,7 +238723,7 @@ async function isFunctionUnchanged(functionDir, fn) {
238883
238723
  return false;
238884
238724
  }
238885
238725
  for (const file of fn.files) {
238886
- const filePath = join11(functionDir, file.path);
238726
+ const filePath = join10(functionDir, file.path);
238887
238727
  if (!await pathExists(filePath)) {
238888
238728
  return false;
238889
238729
  }
@@ -239055,17 +238895,10 @@ class ProjectConfigReader {
239055
238895
  ...pluginResources.functions
239056
238896
  ];
239057
238897
  this.validateFunctionNames(functions, configPath);
239058
- const functionNames = new Set(functions.map((fn) => fn.name));
239059
- for (const actor of localResources.actors) {
239060
- if (functionNames.has(actor.name)) {
239061
- throw new ConfigInvalidError(`'${actor.name}' exists as both a backend function and an actor`, configPath);
239062
- }
239063
- }
239064
238898
  return {
239065
238899
  project,
239066
238900
  entities,
239067
238901
  functions,
239068
- actors: localResources.actors,
239069
238902
  agents: localResources.agents,
239070
238903
  agentSkills: localResources.agentSkills,
239071
238904
  connectors: localResources.connectors,
@@ -239093,34 +238926,17 @@ class ProjectConfigReader {
239093
238926
  }
239094
238927
  return result.data;
239095
238928
  }
239096
- async readProjectResources(configPath, project, includeActors = true) {
239097
- const configDir = dirname10(configPath);
239098
- const [
239099
- entities,
239100
- functions,
239101
- actors,
239102
- agents,
239103
- agentSkills,
239104
- connectors,
239105
- authConfig
239106
- ] = await Promise.all([
239107
- entityResource.readAll(join12(configDir, project.entitiesDir)),
239108
- functionResource.readAll(join12(configDir, project.functionsDir)),
239109
- includeActors ? actorResource.readAll(join12(configDir, project.actorsDir)) : Promise.resolve([]),
239110
- agentResource.readAll(join12(configDir, project.agentsDir)),
239111
- agentSkillResource.readAll(join12(configDir, project.agentSkillsDir)),
239112
- connectorResource.readAll(join12(configDir, project.connectorsDir)),
239113
- authConfigResource.readAll(join12(configDir, project.authDir))
238929
+ async readProjectResources(configPath, project) {
238930
+ const configDir = dirname8(configPath);
238931
+ const [entities, functions, agents, agentSkills, connectors, authConfig] = await Promise.all([
238932
+ entityResource.readAll(join11(configDir, project.entitiesDir)),
238933
+ functionResource.readAll(join11(configDir, project.functionsDir)),
238934
+ agentResource.readAll(join11(configDir, project.agentsDir)),
238935
+ agentSkillResource.readAll(join11(configDir, project.agentSkillsDir)),
238936
+ connectorResource.readAll(join11(configDir, project.connectorsDir)),
238937
+ authConfigResource.readAll(join11(configDir, project.authDir))
239114
238938
  ]);
239115
- return {
239116
- entities,
239117
- functions,
239118
- actors,
239119
- agents,
239120
- agentSkills,
239121
- connectors,
239122
- authConfig
239123
- };
238939
+ return { entities, functions, agents, agentSkills, connectors, authConfig };
239124
238940
  }
239125
238941
  assertPluginProjectDoesNotLoadPlugins(project, configPath) {
239126
238942
  if (project.plugin && project.plugins.length > 0) {
@@ -239141,7 +238957,7 @@ class ProjectConfigReader {
239141
238957
  this.pluginSourceByNamespace.set(namespace, source);
239142
238958
  }
239143
238959
  async readPluginConfig(plugin, hostConfigPath) {
239144
- const pluginRoot = resolvePluginRoot(plugin.source, dirname10(hostConfigPath));
238960
+ const pluginRoot = resolvePluginRoot(plugin.source, dirname8(hostConfigPath));
239145
238961
  const { configPath } = await this.findConfigOrThrow(pluginRoot);
239146
238962
  const project = await this.readConfigFile(configPath);
239147
238963
  const namespace = requirePluginNamespace(project, plugin.source, configPath);
@@ -239149,11 +238965,10 @@ class ProjectConfigReader {
239149
238965
  return { configPath, namespace, project, source: plugin.source };
239150
238966
  }
239151
238967
  async readPluginResources(project, configPath, namespace) {
239152
- const resources = await this.readProjectResources(configPath, project, false);
238968
+ const resources = await this.readProjectResources(configPath, project);
239153
238969
  return {
239154
238970
  entities: markPluginEntities(resources.entities, namespace),
239155
238971
  functions: namespacePluginFunctions(resources.functions, namespace),
239156
- actors: [],
239157
238972
  agents: [],
239158
238973
  agentSkills: [],
239159
238974
  connectors: [],
@@ -239192,7 +239007,6 @@ class ProjectConfigReader {
239192
239007
  return {
239193
239008
  entities,
239194
239009
  functions,
239195
- actors: [],
239196
239010
  agents: [],
239197
239011
  agentSkills: [],
239198
239012
  connectors: [],
@@ -239227,12 +239041,12 @@ async function readProjectSettings(projectRoot) {
239227
239041
  // src/core/project/template.ts
239228
239042
  var import_ejs = __toESM(require_ejs(), 1);
239229
239043
  var import_front_matter2 = __toESM(require_front_matter(), 1);
239230
- import { dirname as dirname11, join as join14 } from "node:path";
239044
+ import { dirname as dirname9, join as join13 } from "node:path";
239231
239045
 
239232
239046
  // src/core/assets.ts
239233
239047
  import { cpSync, existsSync } from "node:fs";
239234
239048
  import { homedir as homedir2 } from "node:os";
239235
- import { join as join13 } from "node:path";
239049
+ import { join as join12 } from "node:path";
239236
239050
  // package.json
239237
239051
  var package_default = {
239238
239052
  name: "base44",
@@ -239339,21 +239153,21 @@ var package_default = {
239339
239153
  };
239340
239154
 
239341
239155
  // src/core/assets.ts
239342
- var ASSETS_DIR = join13(homedir2(), ".base44", "assets", package_default.version);
239156
+ var ASSETS_DIR = join12(homedir2(), ".base44", "assets", package_default.version);
239343
239157
  function getTemplatesDir() {
239344
- return join13(ASSETS_DIR, "templates");
239158
+ return join12(ASSETS_DIR, "templates");
239345
239159
  }
239346
239160
  function getTemplatesIndexPath() {
239347
- return join13(ASSETS_DIR, "templates", "templates.json");
239161
+ return join12(ASSETS_DIR, "templates", "templates.json");
239348
239162
  }
239349
239163
  function getBackendRuntimeDir() {
239350
- return join13(ASSETS_DIR, "backend-runtime");
239164
+ return join12(ASSETS_DIR, "backend-runtime");
239351
239165
  }
239352
239166
  function getDenoWrapperPath() {
239353
- return join13(getBackendRuntimeDir(), "main.ts");
239167
+ return join12(getBackendRuntimeDir(), "main.ts");
239354
239168
  }
239355
239169
  function getExecWrapperPath() {
239356
- return join13(getBackendRuntimeDir(), "exec.ts");
239170
+ return join12(getBackendRuntimeDir(), "exec.ts");
239357
239171
  }
239358
239172
  function ensureNpmAssets(sourceDir) {
239359
239173
  if (existsSync(ASSETS_DIR) && existsSync(getBackendRuntimeDir()))
@@ -239375,7 +239189,7 @@ async function listTemplates() {
239375
239189
  }
239376
239190
  async function renderTemplate(template, destPath, data, options = {}) {
239377
239191
  const { skipExisting = false } = options;
239378
- const templateDir = join14(getTemplatesDir(), template.path);
239192
+ const templateDir = join13(getTemplatesDir(), template.path);
239379
239193
  const files = await globby("**/*", {
239380
239194
  cwd: templateDir,
239381
239195
  dot: true,
@@ -239383,20 +239197,20 @@ async function renderTemplate(template, destPath, data, options = {}) {
239383
239197
  });
239384
239198
  const skipped = [];
239385
239199
  for (const file of files) {
239386
- const srcPath = join14(templateDir, file);
239200
+ const srcPath = join13(templateDir, file);
239387
239201
  try {
239388
239202
  if (file.endsWith(".ejs")) {
239389
239203
  const rendered = await import_ejs.default.renderFile(srcPath, data);
239390
239204
  const { attributes, body } = import_front_matter2.default(rendered);
239391
- const destFile = attributes.outputFileName ? join14(dirname11(file), attributes.outputFileName) : file.replace(/\.ejs$/, "");
239392
- const destFilePath = join14(destPath, destFile);
239205
+ const destFile = attributes.outputFileName ? join13(dirname9(file), attributes.outputFileName) : file.replace(/\.ejs$/, "");
239206
+ const destFilePath = join13(destPath, destFile);
239393
239207
  if (skipExisting && await pathExists(destFilePath)) {
239394
239208
  skipped.push(destFile);
239395
239209
  continue;
239396
239210
  }
239397
239211
  await writeFile(destFilePath, body);
239398
239212
  } else {
239399
- const destFilePath = join14(destPath, file);
239213
+ const destFilePath = join13(destPath, file);
239400
239214
  if (skipExisting && await pathExists(destFilePath)) {
239401
239215
  skipped.push(file);
239402
239216
  continue;
@@ -239550,7 +239364,7 @@ async function getSiteFilePaths(outputDir) {
239550
239364
  // src/core/site/deploy.ts
239551
239365
  import { randomUUID } from "node:crypto";
239552
239366
  import { tmpdir } from "node:os";
239553
- import { join as join15 } from "node:path";
239367
+ import { join as join14 } from "node:path";
239554
239368
  async function deploySite(siteOutputDir) {
239555
239369
  if (!await pathExists(siteOutputDir)) {
239556
239370
  throw new InvalidInputError(`Output directory does not exist: ${siteOutputDir}. Make sure to build your project first.`, {
@@ -239571,7 +239385,7 @@ async function deploySite(siteOutputDir) {
239571
239385
  ]
239572
239386
  });
239573
239387
  }
239574
- const archivePath = join15(tmpdir(), `base44-site-${randomUUID()}.tar.gz`);
239388
+ const archivePath = join14(tmpdir(), `base44-site-${randomUUID()}.tar.gz`);
239575
239389
  try {
239576
239390
  await createArchive(siteOutputDir, archivePath);
239577
239391
  return await uploadSite(archivePath);
@@ -239588,13 +239402,13 @@ async function createArchive(pathToArchive, targetArchivePath) {
239588
239402
  }
239589
239403
  // src/core/site/deployment.ts
239590
239404
  import { readFile as readFile3 } from "node:fs/promises";
239591
- import { join as join18 } from "node:path";
239405
+ import { join as join17 } from "node:path";
239592
239406
 
239593
239407
  // src/core/site/manifest.ts
239594
239408
  import { createHash } from "node:crypto";
239595
239409
  import { createReadStream } from "node:fs";
239596
239410
  import { stat } from "node:fs/promises";
239597
- import { basename as basename5, extname, join as join16 } from "node:path";
239411
+ import { basename as basename4, extname, join as join15 } from "node:path";
239598
239412
  var MAX_ASSET_COUNT = 1e5;
239599
239413
  var ASSETS_IGNORE_FILE = ".assetsignore";
239600
239414
  var ALWAYS_IGNORED = new Set([
@@ -239652,12 +239466,12 @@ async function buildAssetManifest(assetsDir, appId) {
239652
239466
  followSymbolicLinks: false,
239653
239467
  ignoreFiles: [ASSETS_IGNORE_FILE]
239654
239468
  });
239655
- const relativeFilePaths = found.filter((path) => !ALWAYS_IGNORED.has(basename5(path)));
239469
+ const relativeFilePaths = found.filter((path) => !ALWAYS_IGNORED.has(basename4(path)));
239656
239470
  if (relativeFilePaths.length > MAX_ASSET_COUNT) {
239657
239471
  throw new InvalidInputError(`Too many static assets: found ${relativeFilePaths.length}, the limit is ${MAX_ASSET_COUNT} files.`);
239658
239472
  }
239659
239473
  for (const relativePath of relativeFilePaths.sort()) {
239660
- const absolutePath = join16(assetsDir, ...relativePath.split("/"));
239474
+ const absolutePath = join15(assetsDir, ...relativePath.split("/"));
239661
239475
  const { size } = await stat(absolutePath);
239662
239476
  const hash = await hashAssetFile(appId, absolutePath);
239663
239477
  manifest[`/${relativePath}`] = { hash, size };
@@ -239675,7 +239489,7 @@ async function buildAssetManifest(assetsDir, appId) {
239675
239489
 
239676
239490
  // src/core/site/modules.ts
239677
239491
  import { stat as stat2 } from "node:fs/promises";
239678
- import { relative as relative5, resolve as resolve3, sep } from "node:path";
239492
+ import { relative as relative3, resolve as resolve3, sep } from "node:path";
239679
239493
  var MAX_TOTAL_MODULE_BYTES = 40 * 1024 * 1024;
239680
239494
  var MODULE_IGNORE = ["wrangler.json", ".dev.vars"];
239681
239495
  var RULE_TYPE_TO_MODULE_TYPE = {
@@ -239695,7 +239509,7 @@ async function collectModules(config) {
239695
239509
  });
239696
239510
  }
239697
239511
  const modulesByName = new Map;
239698
- const entryName = toPosix(relative5(config.configDir, entryPath));
239512
+ const entryName = toPosix(relative3(config.configDir, entryPath));
239699
239513
  modulesByName.set(entryName, {
239700
239514
  name: entryName,
239701
239515
  absolutePath: entryPath,
@@ -239704,7 +239518,7 @@ async function collectModules(config) {
239704
239518
  });
239705
239519
  const ignore = [...MODULE_IGNORE];
239706
239520
  if (config.assetsDirectory?.startsWith(config.configDir + sep)) {
239707
- ignore.push(`${toPosix(relative5(config.configDir, config.assetsDirectory))}/**`);
239521
+ ignore.push(`${toPosix(relative3(config.configDir, config.assetsDirectory))}/**`);
239708
239522
  }
239709
239523
  for (const rule of config.rules) {
239710
239524
  const type = RULE_TYPE_TO_MODULE_TYPE[rule.type];
@@ -239998,7 +239812,10 @@ async function uploadPresignedAsset(upload, assets) {
239998
239812
  try {
239999
239813
  await distribution_default.put(upload.url, {
240000
239814
  body: new Uint8Array(content),
240001
- headers: { "Content-Type": upload.contentType },
239815
+ headers: {
239816
+ "Content-Type": upload.contentType,
239817
+ ...upload.checksumSha256 ? { "x-amz-checksum-sha256": upload.checksumSha256 } : {}
239818
+ },
240002
239819
  timeout: 120000,
240003
239820
  retry: UPLOAD_RETRY
240004
239821
  });
@@ -240008,8 +239825,8 @@ async function uploadPresignedAsset(upload, assets) {
240008
239825
  }
240009
239826
 
240010
239827
  // src/core/site/wrangler-config.ts
240011
- import { dirname as dirname12, join as join17, resolve as resolve4 } from "node:path";
240012
- var WRANGLER_REDIRECT_PATH = join17(".wrangler", "deploy", "config.json");
239828
+ import { dirname as dirname10, join as join16, resolve as resolve4 } from "node:path";
239829
+ var WRANGLER_REDIRECT_PATH = join16(".wrangler", "deploy", "config.json");
240013
239830
  var RedirectConfigSchema = looseObject({
240014
239831
  configPath: string2().min(1)
240015
239832
  });
@@ -240031,7 +239848,7 @@ var WranglerConfigSchema = looseObject({
240031
239848
  upload_source_maps: boolean2().optional()
240032
239849
  });
240033
239850
  async function detectFullStackArtifact(projectRoot) {
240034
- const redirectPath = join17(projectRoot, WRANGLER_REDIRECT_PATH);
239851
+ const redirectPath = join16(projectRoot, WRANGLER_REDIRECT_PATH);
240035
239852
  return await pathExists(redirectPath) ? redirectPath : null;
240036
239853
  }
240037
239854
  async function resolveWranglerConfig(redirectPath) {
@@ -240045,7 +239862,7 @@ async function resolveWranglerConfig(redirectPath) {
240045
239862
  if (config.no_bundle !== true) {
240046
239863
  throw new InvalidInputError("This framework's output requires bundling; not yet supported. Base44 only deploys pre-bundled Workers output (no_bundle: true).");
240047
239864
  }
240048
- const configDir = dirname12(configPath);
239865
+ const configDir = dirname10(configPath);
240049
239866
  const assetsDirectory = config.assets?.directory ? resolve4(configDir, config.assets.directory) : null;
240050
239867
  return {
240051
239868
  configPath,
@@ -240068,7 +239885,7 @@ async function resolveRedirectedConfigPath(redirectPath) {
240068
239885
  if (!result.success) {
240069
239886
  throw new ConfigInvalidError(`Invalid deploy redirect file: ${prettifyError(result.error)}`, redirectPath);
240070
239887
  }
240071
- const configPath = resolve4(dirname12(redirectPath), result.data.configPath);
239888
+ const configPath = resolve4(dirname10(redirectPath), result.data.configPath);
240072
239889
  if (!await pathExists(configPath)) {
240073
239890
  throw new ConfigInvalidError(`Wrangler config referenced by ${redirectPath} does not exist: ${configPath}`, redirectPath, {
240074
239891
  hints: [{ message: "Rebuild the project to regenerate the artifact" }]
@@ -240133,7 +239950,7 @@ async function readIndexHtml(assetsDir, assets) {
240133
239950
  if (!assetsDir || !assets.manifest["/index.html"]) {
240134
239951
  throw new InvalidInputError(`No index.html found in "${assetsDir ?? "the site output directory"}" — a static site needs one at the output directory root.`);
240135
239952
  }
240136
- return new Uint8Array(await readFile3(join18(assetsDir, "index.html")));
239953
+ return new Uint8Array(await readFile3(join17(assetsDir, "index.html")));
240137
239954
  }
240138
239955
  function buildAssetsConfig(assetsConfig, progress) {
240139
239956
  if (!assetsConfig)
@@ -246669,6 +246486,13 @@ async function resolveGitHash(projectRoot, explicit) {
246669
246486
  }
246670
246487
  return hash;
246671
246488
  }
246489
+ async function resolveProvenanceCommit(projectRoot, explicit) {
246490
+ if (explicit) {
246491
+ return await resolveGitHash(projectRoot, explicit);
246492
+ }
246493
+ const hash = await gitHead(projectRoot);
246494
+ return hash && isGitCommitHash(hash) ? hash : undefined;
246495
+ }
246672
246496
  async function gitHead(projectRoot) {
246673
246497
  try {
246674
246498
  const { stdout } = await execa("git", ["rev-parse", "HEAD"], {
@@ -246685,7 +246509,6 @@ function hasResourcesToDeploy(projectData) {
246685
246509
  project,
246686
246510
  entities,
246687
246511
  functions,
246688
- actors,
246689
246512
  agents,
246690
246513
  agentSkills,
246691
246514
  connectors,
@@ -246694,20 +246517,18 @@ function hasResourcesToDeploy(projectData) {
246694
246517
  const hasSite = Boolean(project.site?.outputDirectory);
246695
246518
  const hasEntities = entities.length > 0;
246696
246519
  const hasFunctions = functions.length > 0;
246697
- const hasActors = actors.length > 0;
246698
246520
  const hasAgents = agents.length > 0;
246699
246521
  const hasAgentSkills = agentSkills.length > 0;
246700
246522
  const hasConnectors = connectors.length > 0;
246701
246523
  const hasAuthConfig = authConfig.length > 0;
246702
246524
  const hasVisibility = Boolean(project.visibility);
246703
- return hasEntities || hasFunctions || hasActors || hasAgents || hasAgentSkills || hasConnectors || hasAuthConfig || hasVisibility || hasSite;
246525
+ return hasEntities || hasFunctions || hasAgents || hasAgentSkills || hasConnectors || hasAuthConfig || hasVisibility || hasSite;
246704
246526
  }
246705
246527
  async function deployAll(projectData, options) {
246706
246528
  const {
246707
246529
  project,
246708
246530
  entities,
246709
246531
  functions,
246710
- actors,
246711
246532
  agents,
246712
246533
  agentSkills,
246713
246534
  connectors,
@@ -246718,33 +246539,10 @@ async function deployAll(projectData, options) {
246718
246539
  options?.onVisibilitySet?.(project.visibility);
246719
246540
  }
246720
246541
  await entityResource.push(entities);
246721
- const functionResults = await deployFunctionsSequentially(functions, {
246542
+ await deployFunctionsSequentially(functions, {
246722
246543
  onStart: options?.onFunctionStart,
246723
246544
  onResult: options?.onFunctionResult
246724
246545
  });
246725
- const completedStages = [
246726
- ...project.visibility ? [`Visibility set to ${project.visibility}`] : [],
246727
- ...entities.length ? [`Entities synced: ${entities.length}`] : []
246728
- ];
246729
- const functionDetails = functionResults.map((result) => `Function ${result.name}: ${result.status}${result.error ? ` — ${result.error}` : ""}`);
246730
- if (functionResults.some((result) => result.status === "error")) {
246731
- throw new ResourceDeploymentError("Function deployment failed; remaining deploy stages were not run", {
246732
- details: [...completedStages, ...functionDetails]
246733
- });
246734
- }
246735
- const actorResults = await deployActorsSequentially(actors, {
246736
- onStart: options?.onActorStart,
246737
- onResult: options?.onActorResult
246738
- });
246739
- if (actorResults.some((result) => result.status === "error")) {
246740
- throw new ResourceDeploymentError("Actor deployment failed; remaining deploy stages were not run", {
246741
- details: [
246742
- ...completedStages,
246743
- ...functionDetails,
246744
- ...actorResults.map(describeActorResult)
246745
- ]
246746
- });
246747
- }
246748
246546
  await agentSkillResource.push(agentSkills);
246749
246547
  await agentResource.push(agents);
246750
246548
  await authConfigResource.push(authConfig);
@@ -247204,6 +247002,136 @@ async function resolveBranchName(name) {
247204
247002
  return matches[0].id;
247205
247003
  }
247206
247004
 
247005
+ // src/core/version/publish.ts
247006
+ import { randomUUID as randomUUID4 } from "node:crypto";
247007
+
247008
+ // src/core/version/schema.ts
247009
+ var DeclareVersionResponseSchema = object({
247010
+ session_id: string2(),
247011
+ uploads: array(object({
247012
+ path: string2(),
247013
+ url: string2(),
247014
+ content_type: string2(),
247015
+ content_length: number2(),
247016
+ checksum_sha256: string2()
247017
+ }))
247018
+ }).transform((data) => ({
247019
+ sessionId: data.session_id,
247020
+ uploads: data.uploads.map((upload) => ({
247021
+ path: upload.path,
247022
+ url: upload.url,
247023
+ contentType: upload.content_type,
247024
+ contentLength: upload.content_length,
247025
+ checksumSha256: upload.checksum_sha256
247026
+ }))
247027
+ }));
247028
+ var CreateVersionResponseSchema = object({
247029
+ version_id: string2(),
247030
+ manifest_hash: string2(),
247031
+ deduplicated: boolean2()
247032
+ }).transform((data) => ({
247033
+ versionId: data.version_id,
247034
+ manifestHash: data.manifest_hash,
247035
+ deduplicated: data.deduplicated
247036
+ }));
247037
+ var DeployVersionResponseSchema = object({
247038
+ deployment_id: string2(),
247039
+ manifest_hash: string2(),
247040
+ revision: number2()
247041
+ }).transform((data) => ({
247042
+ deploymentId: data.deployment_id,
247043
+ manifestHash: data.manifest_hash,
247044
+ revision: data.revision
247045
+ }));
247046
+
247047
+ // src/core/version/api.ts
247048
+ var DEFAULT_VERSION_UPLOAD_CONCURRENCY = 8;
247049
+ var MAX_VERSION_UPLOAD_CONCURRENCY = 16;
247050
+ async function post(path, json, doing) {
247051
+ try {
247052
+ return await getAppClient().post(path, { json, timeout: 180000 });
247053
+ } catch (error) {
247054
+ throw await ApiError.fromHttpError(error, doing);
247055
+ }
247056
+ }
247057
+ function parse10(schema, body, what) {
247058
+ const result = schema.safeParse(body);
247059
+ if (!result.success) {
247060
+ throw new SchemaValidationError(`Invalid ${what} response from server`, result.error);
247061
+ }
247062
+ return result.data;
247063
+ }
247064
+ async function createVersion(artifacts, options = {}) {
247065
+ const declared = parse10(DeclareVersionResponseSchema, await (await post("versions", {
247066
+ static_bundle: artifacts.files.map(({ path, size, digest }) => ({
247067
+ path,
247068
+ size,
247069
+ digest
247070
+ })),
247071
+ entities: artifacts.entities,
247072
+ agents: artifacts.agents,
247073
+ source_commit: options.sourceCommit,
247074
+ frontend_commit: options.sourceCommit
247075
+ }, "declaring a version")).json(), "declare");
247076
+ options.progress?.onDeclared?.({
247077
+ fileCount: artifacts.files.length,
247078
+ owedFiles: declared.uploads.length
247079
+ });
247080
+ await uploadPresignedAssets(declared.uploads, {
247081
+ manifest: Object.fromEntries(artifacts.files.map((file) => [
247082
+ file.path,
247083
+ { hash: file.digest, size: file.size }
247084
+ ])),
247085
+ filesByHash: new Map(artifacts.files.map((file) => [
247086
+ file.digest,
247087
+ {
247088
+ absolutePath: file.absolutePath,
247089
+ hash: file.digest,
247090
+ size: file.size,
247091
+ contentType: "application/octet-stream"
247092
+ }
247093
+ ]))
247094
+ }, {
247095
+ concurrency: options.concurrency ?? DEFAULT_VERSION_UPLOAD_CONCURRENCY,
247096
+ onProgress: options.progress?.onUpload
247097
+ });
247098
+ return parse10(CreateVersionResponseSchema, await (await post(`versions/${encodeURIComponent(declared.sessionId)}/finalize`, {}, "creating a version")).json(), "create version");
247099
+ }
247100
+ async function deployVersion(versionId, options = {}) {
247101
+ return parse10(DeployVersionResponseSchema, await (await post(`versions/${encodeURIComponent(versionId)}/deployments`, {
247102
+ ...options.target ? { target: options.target } : {},
247103
+ ...options.idempotencyKey ? { idempotency_key: options.idempotencyKey } : {}
247104
+ }, "deploying a version")).json(), "deploy");
247105
+ }
247106
+
247107
+ // src/core/version/publish.ts
247108
+ var STEP = Symbol.for("base44.publishStep");
247109
+ async function tagStep(step, run) {
247110
+ try {
247111
+ return await run();
247112
+ } catch (error) {
247113
+ if (error !== null && typeof error === "object" && !(STEP in error)) {
247114
+ Object.defineProperty(error, STEP, { value: step, enumerable: false });
247115
+ }
247116
+ throw error;
247117
+ }
247118
+ }
247119
+ function stepOf(error) {
247120
+ return error !== null && typeof error === "object" && STEP in error ? error[STEP] : undefined;
247121
+ }
247122
+ async function publishVersion(artifacts, options = {}) {
247123
+ const version = await tagStep("create_version", () => createVersion(artifacts, {
247124
+ sourceCommit: options.sourceCommit,
247125
+ concurrency: options.concurrency,
247126
+ progress: options.progress
247127
+ }));
247128
+ const deployment = await tagStep("deploy", () => deployVersion(version.versionId, {
247129
+ target: options.target,
247130
+ idempotencyKey: randomUUID4()
247131
+ }));
247132
+ return { ...version, ...deployment };
247133
+ }
247134
+
247207
247135
  // src/cli/utils/command/Base44Command.ts
247208
247136
  function writeJsonSuccess(result) {
247209
247137
  if (result.stdout) {
@@ -247221,6 +247149,10 @@ function writeJsonError(error) {
247221
247149
  const envelope = {
247222
247150
  error: error instanceof Error ? error.message : String(error)
247223
247151
  };
247152
+ const step = stepOf(error);
247153
+ if (step !== undefined) {
247154
+ envelope.step = step;
247155
+ }
247224
247156
  if (isCLIError(error)) {
247225
247157
  envelope.code = error.code;
247226
247158
  if (error.details.length > 0) {
@@ -247479,118 +247411,6 @@ function formatYaml(data, options = {}) {
247479
247411
  const replacer = stripEmpty ? stripEmptyReplacer : undefined;
247480
247412
  return $stringify(data, replacer, { indent: YAML_INDENT }).trimEnd();
247481
247413
  }
247482
- // src/cli/commands/actors/delete.ts
247483
- async function deleteActorsAction({ log, jsonMode, runTask }, rawNames) {
247484
- const names = [...new Set(parseNames(rawNames))];
247485
- if (!names.length)
247486
- throw new InvalidInputError("At least one actor name is required");
247487
- names.forEach(validateActorName);
247488
- const results = [];
247489
- for (const name of names) {
247490
- try {
247491
- await runTask(`Deleting ${name}...`, () => deleteSingleActor(name), {
247492
- successMessage: `${name} deleted`,
247493
- errorMessage: `Failed to delete ${name}`
247494
- });
247495
- results.push({ name, status: "deleted" });
247496
- } catch (error) {
247497
- if (error instanceof ApiError && error.statusCode === 404) {
247498
- results.push({ name, status: "not_found" });
247499
- log.info(`${name} not found`);
247500
- } else {
247501
- const result = actorOperationError(name, error);
247502
- results.push(result);
247503
- log.error(describeActorResult(result));
247504
- }
247505
- }
247506
- }
247507
- const summary = {
247508
- deleted: results.filter((result) => result.status === "deleted").length,
247509
- notFound: results.filter((result) => result.status === "not_found").length,
247510
- failed: results.filter((result) => result.status === "error").length
247511
- };
247512
- if (summary.failed)
247513
- throw new ResourceDeploymentError("Actor deletion failed", {
247514
- details: results.map(describeActorResult)
247515
- });
247516
- return {
247517
- outroMessage: names.length === 1 ? `Actor "${names[0]}" ${summary.deleted ? "deleted" : "not found"}` : `${summary.deleted} deleted, ${summary.notFound} not found`,
247518
- stdout: jsonMode ? `${JSON.stringify({ actors: results, summary })}
247519
- ` : undefined
247520
- };
247521
- }
247522
- function getDeleteCommand() {
247523
- return new Base44Command("delete").description("Delete deployed actors").argument("[names...]", "Actor names to delete (required)").action(deleteActorsAction);
247524
- }
247525
-
247526
- // src/cli/commands/functions/formatDeployResult.ts
247527
- function formatDuration(ms) {
247528
- return `${(ms / 1000).toFixed(1)}s`;
247529
- }
247530
- function formatDeployResult(result, log) {
247531
- const label = result.name.padEnd(25);
247532
- if (result.status === "deployed") {
247533
- const timing = result.durationMs ? theme.styles.dim(` (${formatDuration(result.durationMs)})`) : "";
247534
- log.success(`${label} deployed${timing}`);
247535
- } else if (result.status === "unchanged") {
247536
- log.success(`${label} unchanged`);
247537
- } else {
247538
- log.error(`${label} error: ${result.error}`);
247539
- }
247540
- }
247541
-
247542
- // src/cli/commands/actors/deploy.ts
247543
- async function deployActorsAction({ log, jsonMode }, rawNames) {
247544
- const names = [...new Set(parseNames(rawNames))];
247545
- if (rawNames.length && !names.length)
247546
- throw new InvalidInputError("At least one actor name is required");
247547
- names.forEach(validateActorName);
247548
- const { actors, project } = await readProjectConfig();
247549
- const notFound = names.filter((name) => !actors.some((actor) => actor.name === name));
247550
- if (notFound.length)
247551
- throw new InvalidInputError(`Actor not found in project: ${notFound.join(", ")}`);
247552
- const selected = names.length ? actors.filter((actor) => names.includes(actor.name)) : actors;
247553
- let completed = 0;
247554
- if (selected.length)
247555
- log.info(`Found ${selected.length} ${selected.length === 1 ? "actor" : "actors"} to deploy`);
247556
- const results = await deployActorsSequentially(selected, {
247557
- onStart: (name) => log.step(theme.styles.dim(`[${completed + 1}/${selected.length}] Deploying ${name}...`)),
247558
- onResult: (result) => {
247559
- completed++;
247560
- formatDeployResult(result, log);
247561
- if (result.status !== "error")
247562
- for (const warning of result.warnings)
247563
- log.warn(`${result.name}: ${warning}`);
247564
- }
247565
- });
247566
- const summary = {
247567
- deployed: results.filter((result) => result.status === "deployed").length,
247568
- unchanged: results.filter((result) => result.status === "unchanged").length,
247569
- failed: results.filter((result) => result.status === "error").length
247570
- };
247571
- const message = Object.entries(summary).filter(([, count]) => count > 0).map(([status, count]) => `${count} ${status}`).join(", ");
247572
- if (summary.failed) {
247573
- throw new ResourceDeploymentError(message, {
247574
- details: results.map(describeActorResult)
247575
- });
247576
- }
247577
- return {
247578
- outroMessage: message || `No actors found. Create actors in the '${project.actorsDir}' directory.`,
247579
- stdout: jsonMode ? `${JSON.stringify({ actors: results, summary })}
247580
- ` : undefined
247581
- };
247582
- }
247583
- function getDeployCommand() {
247584
- return new Base44Command("deploy").description("Deploy actors to Base44").argument("[names...]", "Actor names to deploy (deploys all if omitted)").action(deployActorsAction);
247585
- }
247586
-
247587
- // src/cli/commands/actors/index.ts
247588
- function getActorsCommand() {
247589
- return new Command2("actors").description("Manage realtime actors").addCommand(getDeployCommand()).addCommand(getDeleteCommand());
247590
- }
247591
-
247592
- // src/cli/commands/agent-skills/pull.ts
247593
- import { dirname as dirname13, join as join19 } from "node:path";
247594
247414
  // src/core/utils/dependencies.ts
247595
247415
  import { spawnSync as spawnSync2 } from "node:child_process";
247596
247416
  function verifyDenoInstalled(context) {
@@ -247679,7 +247499,7 @@ async function pullAction({
247679
247499
  runTask
247680
247500
  }) {
247681
247501
  const { project } = await readProjectConfig();
247682
- const dir = join19(dirname13(project.configPath), project.agentSkillsDir);
247502
+ const dir = join18(dirname11(project.configPath), project.agentSkillsDir);
247683
247503
  const remote = await runTask("Fetching agent skills from Base44", () => fetchAgentSkills(), {
247684
247504
  successMessage: "Agent skills fetched successfully",
247685
247505
  errorMessage: "Failed to fetch agent skills"
@@ -247735,14 +247555,14 @@ function getAgentSkillsCommand() {
247735
247555
  }
247736
247556
 
247737
247557
  // src/cli/commands/agents/pull.ts
247738
- import { dirname as dirname14, join as join20 } from "node:path";
247558
+ import { dirname as dirname12, join as join19 } from "node:path";
247739
247559
  async function pullAgentsAction({
247740
247560
  log,
247741
247561
  runTask
247742
247562
  }) {
247743
247563
  const { project } = await readProjectConfig();
247744
- const configDir = dirname14(project.configPath);
247745
- const agentsDir = join20(configDir, project.agentsDir);
247564
+ const configDir = dirname12(project.configPath);
247565
+ const agentsDir = join19(configDir, project.agentsDir);
247746
247566
  const remoteAgents = await runTask("Fetching agents from Base44", async () => {
247747
247567
  return await fetchAgents();
247748
247568
  }, {
@@ -247812,12 +247632,12 @@ function getAgentsCommand() {
247812
247632
  }
247813
247633
 
247814
247634
  // src/cli/commands/auth/password-login.ts
247815
- import { dirname as dirname15, join as join21 } from "node:path";
247635
+ import { dirname as dirname13, join as join20 } from "node:path";
247816
247636
  async function passwordLoginAction({ log, runTask }, action) {
247817
247637
  const shouldEnable = action === "enable";
247818
247638
  const { project } = await readProjectConfig();
247819
- const configDir = dirname15(project.configPath);
247820
- const authDir = join21(configDir, project.authDir);
247639
+ const configDir = dirname13(project.configPath);
247640
+ const authDir = join20(configDir, project.authDir);
247821
247641
  const updated = await runTask("Updating local auth config", async () => {
247822
247642
  const current = await readAuthConfig(authDir) ?? DEFAULT_AUTH_CONFIG;
247823
247643
  const merged = { ...current, enableUsernamePassword: shouldEnable };
@@ -247837,14 +247657,14 @@ function getPasswordLoginCommand() {
247837
247657
  }
247838
247658
 
247839
247659
  // src/cli/commands/auth/pull.ts
247840
- import { dirname as dirname16, join as join22 } from "node:path";
247660
+ import { dirname as dirname14, join as join21 } from "node:path";
247841
247661
  async function pullAuthAction({
247842
247662
  log,
247843
247663
  runTask
247844
247664
  }) {
247845
247665
  const { project } = await readProjectConfig();
247846
- const configDir = dirname16(project.configPath);
247847
- const authDir = join22(configDir, project.authDir);
247666
+ const configDir = dirname14(project.configPath);
247667
+ const authDir = join21(configDir, project.authDir);
247848
247668
  const remoteConfig = await runTask("Fetching auth config from Base44", async () => {
247849
247669
  return await pullAuthConfig();
247850
247670
  }, {
@@ -247908,7 +247728,7 @@ function getAuthPushCommand() {
247908
247728
  }
247909
247729
 
247910
247730
  // src/cli/commands/auth/social-login.ts
247911
- import { dirname as dirname17, join as join23, resolve as resolve6 } from "node:path";
247731
+ import { dirname as dirname15, join as join22, resolve as resolve6 } from "node:path";
247912
247732
  var PROVIDER_LABELS = {
247913
247733
  google: "Google",
247914
247734
  microsoft: "Microsoft",
@@ -247978,8 +247798,8 @@ async function socialLoginAction({ log, isNonInteractive, runTask }, provider, a
247978
247798
  }
247979
247799
  }
247980
247800
  const { project } = await readProjectConfig();
247981
- const configDir = dirname17(project.configPath);
247982
- const authDir = join23(configDir, project.authDir);
247801
+ const configDir = dirname15(project.configPath);
247802
+ const authDir = join22(configDir, project.authDir);
247983
247803
  const { config: updated } = await runTask("Updating local auth config", async () => updateSocialLoginConfig(authDir, provider, shouldEnable, useCustomOAuth && options.clientId ? { clientId: options.clientId } : undefined));
247984
247804
  if (clientSecret) {
247985
247805
  await runTask("Saving client secret", async () => pushCustomOAuthSecret(provider, clientSecret));
@@ -248004,7 +247824,7 @@ function getSocialLoginCommand() {
248004
247824
  }
248005
247825
 
248006
247826
  // src/cli/commands/auth/sso.ts
248007
- import { dirname as dirname18, join as join24, resolve as resolve7 } from "node:path";
247827
+ import { dirname as dirname16, join as join23, resolve as resolve7 } from "node:path";
248008
247828
  var SSOConfigFileSchema = object({
248009
247829
  provider: _enum(Object.values(KNOWN_SSO_PROVIDERS)),
248010
247830
  clientId: string2(),
@@ -248167,8 +247987,8 @@ async function ssoEnableAction({ isNonInteractive, runTask }, options) {
248167
247987
  throw error;
248168
247988
  }
248169
247989
  const { project } = await readProjectConfig();
248170
- const configDir = dirname18(project.configPath);
248171
- const authDir = join24(configDir, project.authDir);
247990
+ const configDir = dirname16(project.configPath);
247991
+ const authDir = join23(configDir, project.authDir);
248172
247992
  await runTask("Updating local auth config", async () => updateSSOConfig(authDir, provider, true));
248173
247993
  await runTask("Saving SSO credentials", async () => pushSSOSecrets(secrets));
248174
247994
  return {
@@ -248183,8 +248003,8 @@ async function ssoDisableAction({ log, runTask }, options) {
248183
248003
  throw new InvalidInputError("Configuration options cannot be used with disable. To disable SSO: base44 auth sso disable");
248184
248004
  }
248185
248005
  const { project } = await readProjectConfig();
248186
- const configDir = dirname18(project.configPath);
248187
- const authDir = join24(configDir, project.authDir);
248006
+ const configDir = dirname16(project.configPath);
248007
+ const authDir = join23(configDir, project.authDir);
248188
248008
  const updated = await runTask("Updating local auth config", async () => updateSSOConfig(authDir, null, false));
248189
248009
  await runTask("Removing SSO credentials", async () => deleteSSOSecrets());
248190
248010
  if (!hasAnyLoginMethod(updated)) {
@@ -249066,13 +248886,13 @@ function getConnectorsListAvailableCommand() {
249066
248886
  }
249067
248887
 
249068
248888
  // src/cli/commands/connectors/pull.ts
249069
- import { dirname as dirname19, join as join25, resolve as resolve8 } from "node:path";
248889
+ import { dirname as dirname17, join as join24, resolve as resolve8 } from "node:path";
249070
248890
  async function resolveConnectorsDir(options) {
249071
248891
  if (!getAppContext().projectRoot) {
249072
248892
  return resolve8(options.dir ?? "connectors");
249073
248893
  }
249074
248894
  const { project } = await readProjectConfig();
249075
- return join25(dirname19(project.configPath), project.connectorsDir);
248895
+ return join24(dirname17(project.configPath), project.connectorsDir);
249076
248896
  }
249077
248897
  async function pullConnectorsAction({ log, runTask, jsonMode }, options) {
249078
248898
  const connectorsDir = await resolveConnectorsDir(options);
@@ -249327,22 +249147,43 @@ async function deleteFunctionsAction({ runTask }, names) {
249327
249147
  parts.push(`${errors} error${errors !== 1 ? "s" : ""}`);
249328
249148
  return { outroMessage: parts.join(", ") };
249329
249149
  }
249330
- function parseNames2(args) {
249150
+ function parseNames(args) {
249331
249151
  return args.flatMap((arg) => arg.split(",")).map((n) => n.trim()).filter(Boolean);
249332
249152
  }
249333
249153
  function validateNames(command) {
249334
- const names = parseNames2(command.args);
249154
+ const names = parseNames(command.args);
249335
249155
  if (names.length === 0) {
249336
249156
  command.error("At least one function name is required");
249337
249157
  }
249338
249158
  }
249339
- function getDeleteCommand2() {
249159
+ function getDeleteCommand() {
249340
249160
  return new Base44Command("delete").description("Delete deployed functions").argument("<names...>", "Function names to delete").hook("preAction", validateNames).action(async (ctx, rawNames) => {
249341
- const names = parseNames2(rawNames);
249161
+ const names = parseNames(rawNames);
249342
249162
  return deleteFunctionsAction(ctx, names);
249343
249163
  });
249344
249164
  }
249345
249165
 
249166
+ // src/cli/commands/functions/formatDeployResult.ts
249167
+ function formatDuration(ms) {
249168
+ return `${(ms / 1000).toFixed(1)}s`;
249169
+ }
249170
+ function formatDeployResult(result, log) {
249171
+ const label = result.name.padEnd(25);
249172
+ if (result.status === "deployed") {
249173
+ const timing = result.durationMs ? theme.styles.dim(` (${formatDuration(result.durationMs)})`) : "";
249174
+ log.success(`${label} deployed${timing}`);
249175
+ } else if (result.status === "unchanged") {
249176
+ log.success(`${label} unchanged`);
249177
+ } else {
249178
+ log.error(`${label} error: ${result.error}`);
249179
+ }
249180
+ }
249181
+
249182
+ // src/cli/commands/functions/parseNames.ts
249183
+ function parseNames2(args) {
249184
+ return args.flatMap((arg) => arg.split(",")).map((n) => n.trim()).filter(Boolean);
249185
+ }
249186
+
249346
249187
  // src/cli/commands/functions/deploy.ts
249347
249188
  function resolveFunctionsToDeploy(names, allFunctions) {
249348
249189
  if (names.length === 0)
@@ -249429,9 +249270,9 @@ async function deployFunctionsAction({ log }, names, options) {
249429
249270
  }
249430
249271
  return { outroMessage: buildDeploySummary(results) };
249431
249272
  }
249432
- function getDeployCommand2() {
249273
+ function getDeployCommand() {
249433
249274
  return new Base44Command("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 (ctx, rawNames, options) => {
249434
- const names = parseNames(rawNames);
249275
+ const names = parseNames2(rawNames);
249435
249276
  return deployFunctionsAction(ctx, names, options);
249436
249277
  });
249437
249278
  }
@@ -249459,11 +249300,11 @@ function getListCommand() {
249459
249300
  }
249460
249301
 
249461
249302
  // src/cli/commands/functions/pull.ts
249462
- import { dirname as dirname20, join as join26 } from "node:path";
249303
+ import { dirname as dirname18, join as join25 } from "node:path";
249463
249304
  async function pullFunctionsAction({ log, runTask }, name) {
249464
249305
  const { project, functions } = await readProjectConfig();
249465
- const configDir = dirname20(project.configPath);
249466
- const functionsDir = join26(configDir, project.functionsDir);
249306
+ const configDir = dirname18(project.configPath);
249307
+ const functionsDir = join25(configDir, project.functionsDir);
249467
249308
  const pluginFunctionNames = new Set(functions.filter((fn) => fn.source.type === "plugin").map((fn) => fn.name));
249468
249309
  const remoteFunctions = await runTask("Fetching functions from Base44", async () => {
249469
249310
  const { functions } = await listDeployedFunctions();
@@ -249518,7 +249359,7 @@ function getPullCommand() {
249518
249359
 
249519
249360
  // src/cli/commands/functions/index.ts
249520
249361
  function getFunctionsCommand() {
249521
- return new Command2("functions").description("Manage backend functions").addCommand(getDeployCommand2()).addCommand(getDeleteCommand2()).addCommand(getListCommand()).addCommand(getPullCommand());
249362
+ return new Command2("functions").description("Manage backend functions").addCommand(getDeployCommand()).addCommand(getDeleteCommand()).addCommand(getListCommand()).addCommand(getPullCommand());
249522
249363
  }
249523
249364
 
249524
249365
  // src/cli/commands/project/site-build.ts
@@ -249563,33 +249404,154 @@ async function maybeAskToBuild(isNonInteractive, buildCommand) {
249563
249404
  });
249564
249405
  return !Ct(answer) && answer;
249565
249406
  }
249566
-
249407
+ // src/core/version/artifacts.ts
249408
+ import { createHash as createHash2 } from "node:crypto";
249409
+ import { createReadStream as createReadStream3 } from "node:fs";
249410
+ import { stat as stat3 } from "node:fs/promises";
249411
+ import { basename as basename5, join as join26 } from "node:path";
249412
+ var MAX_FILE_COUNT = 1e5;
249413
+ var ASSETS_IGNORE_FILE2 = ".assetsignore";
249414
+ var ALWAYS_IGNORED2 = new Set([
249415
+ ASSETS_IGNORE_FILE2,
249416
+ "wrangler.json",
249417
+ ".dev.vars"
249418
+ ]);
249419
+ var ENTRY2 = "index.html";
249420
+ async function digestFile(absolutePath) {
249421
+ const hash = createHash2("sha256");
249422
+ for await (const chunk of createReadStream3(absolutePath)) {
249423
+ hash.update(chunk);
249424
+ }
249425
+ return `sha256:${hash.digest("hex")}`;
249426
+ }
249427
+ async function collectBuildOutput(outputDir) {
249428
+ const found = await globby("**/*", {
249429
+ cwd: outputDir,
249430
+ dot: true,
249431
+ onlyFiles: true,
249432
+ followSymbolicLinks: false,
249433
+ ignoreFiles: [ASSETS_IGNORE_FILE2]
249434
+ });
249435
+ const relativePaths = found.filter((path) => !ALWAYS_IGNORED2.has(basename5(path))).sort();
249436
+ if (relativePaths.length === 0) {
249437
+ throw new InvalidInputError(`No files found in ${outputDir}. Build the site before creating a version.`, {
249438
+ hints: [
249439
+ { message: "Run 'base44 build' first", command: "base44 build" }
249440
+ ]
249441
+ });
249442
+ }
249443
+ if (relativePaths.length > MAX_FILE_COUNT) {
249444
+ throw new InvalidInputError(`Too many files: found ${relativePaths.length}, the limit is ${MAX_FILE_COUNT}.`);
249445
+ }
249446
+ if (!relativePaths.includes(ENTRY2)) {
249447
+ throw new InvalidInputError(`${outputDir} has no ${ENTRY2}, so nothing could enter the site.`);
249448
+ }
249449
+ return await Promise.all(relativePaths.map(async (path) => {
249450
+ const absolutePath = join26(outputDir, ...path.split("/"));
249451
+ const { size } = await stat3(absolutePath);
249452
+ return {
249453
+ path,
249454
+ absolutePath,
249455
+ size,
249456
+ digest: await digestFile(absolutePath)
249457
+ };
249458
+ }));
249459
+ }
249460
+ async function readRawResources(dir) {
249461
+ if (!await pathExists(dir)) {
249462
+ return {};
249463
+ }
249464
+ const files = await globby(`**/*.${CONFIG_FILE_EXTENSION_GLOB}`, {
249465
+ cwd: dir,
249466
+ onlyFiles: true,
249467
+ followSymbolicLinks: false
249468
+ });
249469
+ const payloads = {};
249470
+ for (const relativePath of files.sort()) {
249471
+ const name = relativePath.replace(/\.jsonc?$/, "");
249472
+ payloads[name] = await readJsonFile(join26(dir, ...relativePath.split("/")));
249473
+ }
249474
+ return payloads;
249475
+ }
249476
+ async function collectResources(configDir, dirs) {
249477
+ const [entities, agents] = await Promise.all([
249478
+ readRawResources(join26(configDir, dirs.entitiesDir)),
249479
+ readRawResources(join26(configDir, dirs.agentsDir))
249480
+ ]);
249481
+ return { entities, agents };
249482
+ }
249483
+ // src/core/version/gate.ts
249484
+ var VERSIONS_API_ENV = "BASE44_VERSIONS_API";
249485
+ function versionsApiEnabled(env = process.env) {
249486
+ const value = env[VERSIONS_API_ENV];
249487
+ return value === "1" || value === "true";
249488
+ }
249489
+ // src/core/version/project.ts
249490
+ import { dirname as dirname19, join as join27, resolve as resolve10 } from "node:path";
249491
+ var DEFAULT_BUILD_COMMAND = "npm run build";
249492
+ var DEFAULT_OUTPUT_DIRECTORY = "dist";
249493
+ async function resolvePublishTarget(projectRoot, overrides = {}) {
249494
+ const project = await readSettingsIfPresent(projectRoot);
249495
+ const root = project?.root ?? projectRoot ?? process.cwd();
249496
+ return {
249497
+ root,
249498
+ configDir: project ? dirname19(project.configPath) : join27(root, PROJECT_SUBDIR),
249499
+ buildCommand: project ? project.site?.buildCommand : DEFAULT_BUILD_COMMAND,
249500
+ outputDir: outputDirectory(project, root, overrides.outputDir),
249501
+ entitiesDir: project?.entitiesDir ?? "entities",
249502
+ agentsDir: project?.agentsDir ?? "agents"
249503
+ };
249504
+ }
249505
+ function outputDirectory(project, root, override) {
249506
+ const configured = override ?? (project ? project.site?.outputDirectory : DEFAULT_OUTPUT_DIRECTORY);
249507
+ return configured ? resolve10(root, configured) : null;
249508
+ }
249509
+ function requireOutputDir(target) {
249510
+ if (target.outputDir === null) {
249511
+ throw new ConfigNotFoundError("No site configuration found.", {
249512
+ hints: [
249513
+ {
249514
+ message: `Add 'site.outputDirectory' to your config.jsonc (e.g., "site": { "outputDirectory": "dist" })`
249515
+ },
249516
+ { message: `Or pass --output-dir <dir>, relative to ${target.root}` }
249517
+ ]
249518
+ });
249519
+ }
249520
+ return target.outputDir;
249521
+ }
249522
+ async function readSettingsIfPresent(projectRoot) {
249523
+ try {
249524
+ return await readProjectSettings(projectRoot);
249525
+ } catch (error) {
249526
+ if (error instanceof ConfigNotFoundError) {
249527
+ return null;
249528
+ }
249529
+ throw error;
249530
+ }
249531
+ }
249567
249532
  // src/cli/commands/project/build.ts
249568
249533
  async function buildAction(ctx) {
249569
249534
  const { app } = ctx;
249570
- if (!app?.projectRoot) {
249571
- throw new ConfigInvalidError("base44 build requires a linked local project. Run it from a project with base44/.app.jsonc.");
249572
- }
249573
- const { project } = await readProjectConfig(app.projectRoot);
249535
+ const target = await resolvePublishTarget(app?.projectRoot);
249574
249536
  await runSiteBuild(ctx, {
249575
- root: project.root,
249576
- buildCommand: project.site?.buildCommand,
249577
- appId: app.id
249537
+ root: target.root,
249538
+ buildCommand: target.buildCommand,
249539
+ appId: app?.id ?? ""
249578
249540
  });
249579
249541
  return {
249580
- outroMessage: `Site built with app id ${theme.styles.bold(app.id)}`
249542
+ outroMessage: `Site built with app id ${theme.styles.bold(app?.id ?? "")}`
249581
249543
  };
249582
249544
  }
249583
249545
  function getBuildCommand() {
249584
- return new Base44Command("build").description("Build the site with the Base44 app id injected").action(buildAction);
249546
+ return new Base44Command("build", { requireAuth: false }).description("Build the site with the Base44 app id injected").action(buildAction);
249585
249547
  }
249586
249548
 
249587
249549
  // src/cli/commands/project/create.ts
249588
- import { basename as basename6, resolve as resolve10 } from "node:path";
249550
+ import { basename as basename6, resolve as resolve11 } from "node:path";
249589
249551
  var import_kebabCase = __toESM(require_kebabCase(), 1);
249590
249552
 
249591
249553
  // src/cli/commands/project/scaffold-shared.ts
249592
- import { join as join27 } from "node:path";
249554
+ import { join as join28 } from "node:path";
249593
249555
  var DEFAULT_TEMPLATE_ID = "backend-only";
249594
249556
  async function getTemplateById(templateId) {
249595
249557
  const templates = await listTemplates();
@@ -249652,7 +249614,7 @@ async function completeProjectSetup({
249652
249614
  env: { VITE_BASE44_APP_ID: projectId }
249653
249615
  })`${buildCommand}`;
249654
249616
  updateMessage("Deploying site...");
249655
- return await deploySite(join27(resolvedPath, outputDirectory));
249617
+ return await deploySite(join28(resolvedPath, outputDirectory));
249656
249618
  }, {
249657
249619
  successMessage: theme.colors.base44Orange("Site deployed successfully"),
249658
249620
  errorMessage: "Failed to deploy site"
@@ -249781,7 +249743,7 @@ async function createInteractive(options, ctx) {
249781
249743
  }, ctx);
249782
249744
  }
249783
249745
  async function createNonInteractive(options, ctx) {
249784
- ctx.log.info(`Creating a new project at ${resolve10(options.path)}`);
249746
+ ctx.log.info(`Creating a new project at ${resolve11(options.path)}`);
249785
249747
  const template = await getTemplateById(options.template ?? DEFAULT_TEMPLATE_ID);
249786
249748
  return await executeCreate({
249787
249749
  template,
@@ -249805,7 +249767,7 @@ async function executeCreate({
249805
249767
  }, ctx) {
249806
249768
  const { log, runTask } = ctx;
249807
249769
  const name = rawName.trim();
249808
- const resolvedPath = resolve10(projectPath);
249770
+ const resolvedPath = resolve11(projectPath);
249809
249771
  const organizationId = await resolveWorkspaceId(ctx, flagWorkspaceId, isInteractive);
249810
249772
  const { projectId } = await runTask("Setting up your project...", async () => {
249811
249773
  return await createProjectFiles({
@@ -249867,15 +249829,7 @@ async function deployAction(ctx, options = {}) {
249867
249829
  outroMessage: "No resources found to deploy"
249868
249830
  };
249869
249831
  }
249870
- const {
249871
- project,
249872
- entities,
249873
- functions,
249874
- actors,
249875
- agents,
249876
- connectors,
249877
- authConfig
249878
- } = projectData;
249832
+ const { project, entities, functions, agents, connectors, authConfig } = projectData;
249879
249833
  const summaryLines = [];
249880
249834
  if (entities.length > 0) {
249881
249835
  summaryLines.push(` - ${entities.length} ${entities.length === 1 ? "entity" : "entities"}`);
@@ -249883,9 +249837,6 @@ async function deployAction(ctx, options = {}) {
249883
249837
  if (functions.length > 0) {
249884
249838
  summaryLines.push(` - ${functions.length} ${functions.length === 1 ? "function" : "functions"}`);
249885
249839
  }
249886
- if (actors.length > 0) {
249887
- summaryLines.push(` - ${actors.length} ${actors.length === 1 ? "actor" : "actors"}`);
249888
- }
249889
249840
  if (agents.length > 0) {
249890
249841
  summaryLines.push(` - ${agents.length} ${agents.length === 1 ? "agent" : "agents"}`);
249891
249842
  }
@@ -249919,7 +249870,6 @@ ${summaryLines.join(`
249919
249870
  await maybeBuildBeforeDeploy(ctx, project, options.build);
249920
249871
  let functionCompleted = 0;
249921
249872
  const functionTotal = functions.length;
249922
- let actorCompleted = 0;
249923
249873
  const result = await deployAll(projectData, {
249924
249874
  onVisibilitySet: (level) => {
249925
249875
  log.success(`App visibility set to ${level}`);
@@ -249931,16 +249881,6 @@ ${summaryLines.join(`
249931
249881
  onFunctionResult: (r) => {
249932
249882
  functionCompleted++;
249933
249883
  formatDeployResult(r, log);
249934
- },
249935
- onActorStart: (name) => {
249936
- log.step(theme.styles.dim(`[${actorCompleted + 1}/${actors.length}] Deploying ${name}...`));
249937
- },
249938
- onActorResult: (result) => {
249939
- actorCompleted++;
249940
- formatDeployResult(result, log);
249941
- if (result.status !== "error")
249942
- for (const warning of result.warnings)
249943
- log.warn(`${result.name}: ${warning}`);
249944
249884
  }
249945
249885
  });
249946
249886
  const connectorResults = result.connectorResults ?? [];
@@ -249955,8 +249895,8 @@ ${summaryLines.join(`
249955
249895
  }
249956
249896
  return { outroMessage: "App deployed successfully" };
249957
249897
  }
249958
- function getDeployCommand3() {
249959
- return new Base44Command("deploy").description("Deploy all project resources (entities, functions, actors, agents, connectors, and site)").option("-y, --yes", "Skip confirmation prompt").option("--build", "Build the site before deploying (skips the prompt)").option("--no-build", "Deploy without building (skips the prompt)").action(deployAction);
249898
+ function getDeployCommand2() {
249899
+ return new Base44Command("deploy").description("Deploy all project resources (entities, functions, agents, connectors, and site)").option("-y, --yes", "Skip confirmation prompt").option("--build", "Build the site before deploying (skips the prompt)").option("--no-build", "Deploy without building (skips the prompt)").action(deployAction);
249960
249900
  }
249961
249901
  async function handleOAuthConnectors(connectorResults, isNonInteractive, options, log) {
249962
249902
  const needsOAuth = filterPendingOAuth(connectorResults);
@@ -250446,7 +250386,7 @@ function getLogsCommand() {
250446
250386
  }
250447
250387
 
250448
250388
  // src/cli/commands/project/scaffold.ts
250449
- import { basename as basename7, resolve as resolve11 } from "node:path";
250389
+ import { basename as basename7, resolve as resolve12 } from "node:path";
250450
250390
  function resolveAppId(options) {
250451
250391
  const appId = options.appId;
250452
250392
  if (!appId) {
@@ -250462,7 +250402,7 @@ function resolveAppId(options) {
250462
250402
  async function scaffoldAction(ctx, name, options, command) {
250463
250403
  const { log, runTask } = ctx;
250464
250404
  const appId = resolveAppId(command.optsWithGlobals());
250465
- const resolvedPath = resolve11("./");
250405
+ const resolvedPath = resolve12("./");
250466
250406
  const projectName = (name ?? basename7(resolvedPath)).trim();
250467
250407
  const template = await getTemplateById("backend-only");
250468
250408
  log.info(`Scaffolding project at ${resolvedPath}`);
@@ -250510,6 +250450,62 @@ function getVisibilityCommand() {
250510
250450
  ])).action(setVisibility);
250511
250451
  }
250512
250452
 
250453
+ // src/cli/commands/publish.ts
250454
+ async function publishAction(ctx, options) {
250455
+ const { runTask, log, jsonMode, app } = ctx;
250456
+ const target = await resolvePublishTarget(app?.projectRoot, {
250457
+ outputDir: options.outputDir
250458
+ });
250459
+ if (options.build !== false) {
250460
+ await tagStep("build", () => runSiteBuild(ctx, {
250461
+ root: target.root,
250462
+ buildCommand: target.buildCommand,
250463
+ appId: app?.id ?? ""
250464
+ }));
250465
+ }
250466
+ const outputDir = requireOutputDir(target);
250467
+ const gitHash = await resolveProvenanceCommit(target.root, options.gitHash);
250468
+ const result = await runTask("Publishing...", async (updateMessage) => {
250469
+ const artifacts = {
250470
+ files: await collectBuildOutput(outputDir),
250471
+ ...await collectResources(target.configDir, target)
250472
+ };
250473
+ return await publishVersion(artifacts, {
250474
+ sourceCommit: gitHash,
250475
+ target: options.target,
250476
+ concurrency: options.concurrency,
250477
+ progress: {
250478
+ onDeclared: ({ fileCount, owedFiles }) => updateMessage(`Uploading ${owedFiles} of ${fileCount} files`),
250479
+ onUpload: ({ uploadedFiles, totalFiles }) => updateMessage(`Uploaded ${uploadedFiles} of ${totalFiles} files`)
250480
+ }
250481
+ });
250482
+ }, { successMessage: "Published", errorMessage: "Publish failed" });
250483
+ if (!jsonMode) {
250484
+ log.message(theme.styles.dim(`version ${result.versionId}${result.deduplicated ? " (existing content)" : ""}`));
250485
+ }
250486
+ return {
250487
+ outroMessage: `Deployment ${result.deploymentId} at revision ${result.revision}`,
250488
+ stdout: jsonMode ? `${JSON.stringify(result, null, 2)}
250489
+ ` : undefined
250490
+ };
250491
+ }
250492
+ function getPublishCommand() {
250493
+ return new Base44Command("publish").description("Build the app, record it as a version, and serve that version").option("--no-build", "Publish the existing build output without rebuilding").option("--output-dir <dir>", "Build output directory (defaults to the project's, else dist)").option("--target <name>", "Environment to serve the version at").addOption(new Option2("--git-hash <hash>", "Commit the build came from (defaults to the checkout's HEAD)").argParser(parseGitHash)).addOption(new Option2("--concurrency <n>", "Parallel file uploads").default(DEFAULT_VERSION_UPLOAD_CONCURRENCY).argParser(parseConcurrency)).action(publishAction);
250494
+ }
250495
+ function parseGitHash(value) {
250496
+ if (!isGitCommitHash(value)) {
250497
+ throw new InvalidArgumentError2("Expected a git commit hash (7-64 hex chars).");
250498
+ }
250499
+ return value;
250500
+ }
250501
+ function parseConcurrency(value) {
250502
+ const parsed = Number(value);
250503
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_VERSION_UPLOAD_CONCURRENCY) {
250504
+ throw new InvalidArgumentError2(`Expected a whole number between 1 and ${MAX_VERSION_UPLOAD_CONCURRENCY}.`);
250505
+ }
250506
+ return parsed;
250507
+ }
250508
+
250513
250509
  // src/core/resources/sandbox/schema.ts
250514
250510
  var FileErrorSchema = object({
250515
250511
  code: string2(),
@@ -250879,7 +250875,7 @@ function getSecretsListCommand() {
250879
250875
  }
250880
250876
 
250881
250877
  // src/cli/commands/secrets/set.ts
250882
- import { resolve as resolve12 } from "node:path";
250878
+ import { resolve as resolve13 } from "node:path";
250883
250879
  function parseEntries(entries) {
250884
250880
  const secrets = {};
250885
250881
  for (const entry of entries) {
@@ -250910,7 +250906,7 @@ async function setSecretsAction({ log, runTask }, entries, options) {
250910
250906
  validateInput(entries, options);
250911
250907
  let secrets;
250912
250908
  if (options.envFile) {
250913
- secrets = await parseEnvFile(resolve12(options.envFile));
250909
+ secrets = await parseEnvFile(resolve13(options.envFile));
250914
250910
  if (Object.keys(secrets).length === 0) {
250915
250911
  throw new InvalidInputError("The env file contains no valid KEY=VALUE entries.");
250916
250912
  }
@@ -250939,7 +250935,7 @@ function getSecretsCommand() {
250939
250935
  }
250940
250936
 
250941
250937
  // src/cli/commands/site/deploy.ts
250942
- import { resolve as resolve13 } from "node:path";
250938
+ import { resolve as resolve14 } from "node:path";
250943
250939
  async function deployAction2(ctx, options) {
250944
250940
  const { isNonInteractive } = ctx;
250945
250941
  if (isNonInteractive && !options.yes) {
@@ -251017,23 +251013,23 @@ async function deployTarball({ runTask }, project) {
251017
251013
  }
251018
251014
  function siteOutputDir(project) {
251019
251015
  const outputDirectory = project.site?.outputDirectory;
251020
- return outputDirectory ? resolve13(project.root, outputDirectory) : null;
251016
+ return outputDirectory ? resolve14(project.root, outputDirectory) : null;
251021
251017
  }
251022
251018
  function getSiteDeployCommand() {
251023
251019
  const command = new Base44Command("deploy").description("Deploy built site files to Base44 hosting").option("-y, --yes", "Skip confirmation prompt").option("--build", "Build the site before deploying (skips the prompt)").option("--no-build", "Deploy without building (skips the prompt)");
251024
251020
  if (deploymentsApiEnabled()) {
251025
- command.addOption(new Option2("--git-hash <hash>", "Commit the build came from (defaults to the checkout's HEAD)").argParser(parseGitHash));
251026
- command.addOption(new Option2("--concurrency <n>", "Parallel asset uploads").default(DEFAULT_UPLOAD_CONCURRENCY).argParser(parseConcurrency));
251021
+ command.addOption(new Option2("--git-hash <hash>", "Commit the build came from (defaults to the checkout's HEAD)").argParser(parseGitHash2));
251022
+ command.addOption(new Option2("--concurrency <n>", "Parallel asset uploads").default(DEFAULT_UPLOAD_CONCURRENCY).argParser(parseConcurrency2));
251027
251023
  }
251028
251024
  return command.action(deployAction2);
251029
251025
  }
251030
- function parseGitHash(value) {
251026
+ function parseGitHash2(value) {
251031
251027
  if (!isGitCommitHash(value)) {
251032
251028
  throw new InvalidArgumentError2("Expected a git commit hash (7-64 hex chars).");
251033
251029
  }
251034
251030
  return value;
251035
251031
  }
251036
- function parseConcurrency(value) {
251032
+ function parseConcurrency2(value) {
251037
251033
  const parsed = Number(value);
251038
251034
  if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_UPLOAD_CONCURRENCY) {
251039
251035
  throw new InvalidArgumentError2(`Expected a whole number between 1 and ${MAX_UPLOAD_CONCURRENCY}.`);
@@ -251071,12 +251067,10 @@ var EMPTY_TEMPLATE = import_common_tags.stripIndent`
251071
251067
  // Auto-generated by Base44 CLI - DO NOT EDIT
251072
251068
  // Regenerate with: base44 types
251073
251069
  //
251074
- // No entities, functions, actors, agents, or connectors found in project.
251075
- // Add resources to base44/entities/, base44/functions/, base44/actors/, base44/agents/, or base44/connectors/
251070
+ // No entities, functions, agents, or connectors found in project.
251071
+ // Add resources to base44/entities/, base44/functions/, base44/agents/, or base44/connectors/
251076
251072
  // and run \`base44 types generate\` again.
251077
251073
 
251078
- import '@base44/sdk';
251079
-
251080
251074
  declare module '@base44/sdk' {
251081
251075
  // No types to augment - add resources and regenerate
251082
251076
  }
@@ -251086,8 +251080,8 @@ async function generateTypesFile(input) {
251086
251080
  await writeFile(getTypesOutputPath(input.projectRoot), content);
251087
251081
  }
251088
251082
  async function generateContent(input) {
251089
- const { entities, functions, actors, agents, connectors } = input;
251090
- if (!entities.length && !functions.length && !actors.length && !agents.length && !connectors.length) {
251083
+ const { entities, functions, agents, connectors } = input;
251084
+ if (!entities.length && !functions.length && !agents.length && !connectors.length) {
251091
251085
  return EMPTY_TEMPLATE;
251092
251086
  }
251093
251087
  const entityInterfaces = await Promise.all(entities.map((e) => compileEntity(e)));
@@ -251097,14 +251091,12 @@ async function generateContent(input) {
251097
251091
  entities.map((e) => `"${e.name}": ${toPascalCase(e.name)};`)
251098
251092
  ],
251099
251093
  ["FunctionNameRegistry", functions.map((f) => `"${f.name}": true;`)],
251100
- ["ActorNameRegistry", actors.map((actor) => `"${actor.name}": true;`)],
251101
251094
  ["AgentNameRegistry", agents.map((a) => `"${a.name}": true;`)],
251102
251095
  ["ConnectorTypeRegistry", connectors.map((c) => `"${c.type}": true;`)]
251103
251096
  ];
251104
251097
  const registries = registryEntries.filter(([, entries]) => entries.length > 0).map(([name, entries]) => registry2(name, entries));
251105
251098
  return [
251106
251099
  HEADER2,
251107
- "import '@base44/sdk';",
251108
251100
  entityInterfaces.join(`
251109
251101
 
251110
251102
  `),
@@ -251149,10 +251141,10 @@ function toPascalCase(name) {
251149
251141
  return name.split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
251150
251142
  }
251151
251143
  // src/core/types/update-project.ts
251152
- import { join as join30 } from "node:path";
251144
+ import { join as join31 } from "node:path";
251153
251145
  var TYPES_INCLUDE_PATH = `${PROJECT_SUBDIR}/${TYPES_OUTPUT_SUBDIR}/*.d.ts`;
251154
251146
  async function updateProjectConfig(projectRoot) {
251155
- const tsconfigPath = join30(projectRoot, "tsconfig.json");
251147
+ const tsconfigPath = join31(projectRoot, "tsconfig.json");
251156
251148
  if (!await pathExists(tsconfigPath)) {
251157
251149
  return false;
251158
251150
  }
@@ -251176,13 +251168,12 @@ var TYPES_FILE_PATH = "base44/.types/types.d.ts";
251176
251168
  async function generateTypesAction({
251177
251169
  runTask
251178
251170
  }) {
251179
- const { entities, functions, actors, agents, connectors, project } = await readProjectConfig();
251171
+ const { entities, functions, agents, connectors, project } = await readProjectConfig();
251180
251172
  await runTask("Generating types", async () => {
251181
251173
  await generateTypesFile({
251182
251174
  projectRoot: project.root,
251183
251175
  entities,
251184
251176
  functions,
251185
- actors,
251186
251177
  agents,
251187
251178
  connectors
251188
251179
  });
@@ -251201,6 +251192,69 @@ function getTypesCommand() {
251201
251192
  return new Command2("types").description("Manage TypeScript type generation").addCommand(getTypesGenerateCommand());
251202
251193
  }
251203
251194
 
251195
+ // src/cli/commands/versions/create.ts
251196
+ async function createAction2({ runTask, jsonMode, app }, options) {
251197
+ const target = await resolvePublishTarget(app?.projectRoot, {
251198
+ outputDir: options.outputDir
251199
+ });
251200
+ const gitHash = await resolveProvenanceCommit(target.root, options.gitHash);
251201
+ const version = await runTask("Creating version...", async (updateMessage) => await createVersion({
251202
+ files: await collectBuildOutput(requireOutputDir(target)),
251203
+ ...await collectResources(target.configDir, target)
251204
+ }, {
251205
+ sourceCommit: gitHash,
251206
+ concurrency: options.concurrency,
251207
+ progress: {
251208
+ onDeclared: ({ fileCount, owedFiles }) => updateMessage(`Uploading ${owedFiles} of ${fileCount} files`),
251209
+ onUpload: ({ uploadedFiles, totalFiles }) => updateMessage(`Uploaded ${uploadedFiles} of ${totalFiles} files`)
251210
+ }
251211
+ }), {
251212
+ successMessage: "Version created",
251213
+ errorMessage: "Create version failed"
251214
+ });
251215
+ return {
251216
+ outroMessage: `Version ${version.versionId} (${version.manifestHash})`,
251217
+ stdout: jsonMode ? `${JSON.stringify(version, null, 2)}
251218
+ ` : undefined
251219
+ };
251220
+ }
251221
+ function getVersionCreateCommand() {
251222
+ return new Base44Command("create").description("Record the built output as a version, without deploying it").option("--output-dir <dir>", "Build output directory (defaults to the project's, else dist)").addOption(new Option2("--git-hash <hash>", "Commit the build came from (defaults to the checkout's HEAD)").argParser((value) => {
251223
+ if (!isGitCommitHash(value)) {
251224
+ throw new InvalidArgumentError2("Expected a git commit hash (7-64 hex chars).");
251225
+ }
251226
+ return value;
251227
+ })).addOption(new Option2("--concurrency <n>", "Parallel file uploads").default(DEFAULT_VERSION_UPLOAD_CONCURRENCY).argParser((value) => {
251228
+ const parsed = Number(value);
251229
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_VERSION_UPLOAD_CONCURRENCY) {
251230
+ throw new InvalidArgumentError2(`Expected a whole number between 1 and ${MAX_VERSION_UPLOAD_CONCURRENCY}.`);
251231
+ }
251232
+ return parsed;
251233
+ })).action(createAction2);
251234
+ }
251235
+
251236
+ // src/cli/commands/versions/deploy.ts
251237
+ import { randomUUID as randomUUID5 } from "node:crypto";
251238
+ async function deployAction3({ runTask, jsonMode }, versionId, options) {
251239
+ const deployment = await runTask(`Deploying version ${versionId}...`, async () => await deployVersion(versionId, {
251240
+ target: options.target,
251241
+ idempotencyKey: randomUUID5()
251242
+ }), { successMessage: "Version deployed", errorMessage: "Deploy failed" });
251243
+ return {
251244
+ outroMessage: `Deployment ${deployment.deploymentId} at revision ${deployment.revision}`,
251245
+ stdout: jsonMode ? `${JSON.stringify(deployment, null, 2)}
251246
+ ` : undefined
251247
+ };
251248
+ }
251249
+ function getVersionDeployCommand() {
251250
+ return new Base44Command("deploy").description("Serve an already-recorded version (also how a rollback is done)").argument("<version-id>", "The version to serve").option("--target <name>", "Environment to serve the version at").action(deployAction3);
251251
+ }
251252
+
251253
+ // src/cli/commands/versions/index.ts
251254
+ function getVersionsCommand() {
251255
+ return new Command2("versions").description("Record app versions and serve them").addCommand(getVersionCreateCommand()).addCommand(getVersionDeployCommand());
251256
+ }
251257
+
251204
251258
  // src/core/resources/workflow/schema.ts
251205
251259
  var WorkflowRunStatusSchema = _enum([
251206
251260
  "running",
@@ -251617,7 +251671,7 @@ function createDevLogger(label, labelColor = theme.styles.dim) {
251617
251671
  // src/cli/dev/dev-server/main.ts
251618
251672
  var import_cors = __toESM(require_lib4(), 1);
251619
251673
  var import_express6 = __toESM(require_express(), 1);
251620
- import { dirname as dirname26, join as join36 } from "node:path";
251674
+ import { dirname as dirname25, join as join37 } from "node:path";
251621
251675
 
251622
251676
  // ../../node_modules/get-port/index.js
251623
251677
  import net from "node:net";
@@ -251747,7 +251801,7 @@ var $tmpName = promisify11(tmp.tmpName);
251747
251801
 
251748
251802
  // src/cli/dev/dev-server/function-manager.ts
251749
251803
  import { spawn as spawn2 } from "node:child_process";
251750
- import { dirname as dirname23, join as join31 } from "node:path";
251804
+ import { dirname as dirname22, join as join33 } from "node:path";
251751
251805
  import { pathToFileURL } from "node:url";
251752
251806
 
251753
251807
  // src/cli/dev/dev-server/base-function-manager.ts
@@ -251852,7 +251906,7 @@ class FunctionManager extends BaseFunctionManager {
251852
251906
  }
251853
251907
  spawnFunction(func, port) {
251854
251908
  this.logger.log(`Spawning function "${func.name}" on port ${port}`);
251855
- const importMapPath = join31(dirname23(this.wrapperPath), "import-map.json");
251909
+ const importMapPath = join33(dirname22(this.wrapperPath), "import-map.json");
251856
251910
  const process2 = spawn2("deno", ["run", "--allow-all", "--import-map", importMapPath, this.wrapperPath], {
251857
251911
  env: {
251858
251912
  ...globalThis.process.env,
@@ -251926,7 +251980,7 @@ class FunctionManager extends BaseFunctionManager {
251926
251980
  import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "node:fs";
251927
251981
  import { isBuiltin } from "node:module";
251928
251982
  import { homedir as homedir3 } from "node:os";
251929
- import { join as join33 } from "node:path";
251983
+ import { join as join34 } from "node:path";
251930
251984
  import { pathToFileURL as pathToFileURL6 } from "node:url";
251931
251985
  var depsPromise;
251932
251986
  function loadDeps() {
@@ -252047,9 +252101,9 @@ export default {
252047
252101
  };
252048
252102
  `;
252049
252103
  function ensureBundlerConfig() {
252050
- const dir = join33(homedir3(), ".base44", "function-bundler");
252104
+ const dir = join34(homedir3(), ".base44", "function-bundler");
252051
252105
  mkdirSync2(dir, { recursive: true });
252052
- const configPath = join33(dir, "deno.json");
252106
+ const configPath = join34(dir, "deno.json");
252053
252107
  writeFileSync2(configPath, `${JSON.stringify({ nodeModulesDir: "auto" }, null, 2)}
252054
252108
  `);
252055
252109
  return configPath;
@@ -253430,11 +253484,11 @@ async function createEntityRoutes(db, logger, broadcast) {
253430
253484
  // src/cli/dev/dev-server/routes/integrations.ts
253431
253485
  var import_express5 = __toESM(require_express(), 1);
253432
253486
  var import_multer = __toESM(require_multer(), 1);
253433
- import { createHash as createHash2, randomUUID as randomUUID4 } from "node:crypto";
253487
+ import { createHash as createHash3, randomUUID as randomUUID6 } from "node:crypto";
253434
253488
  import fs28 from "node:fs";
253435
253489
  import path18 from "node:path";
253436
253490
  function createFileToken(fileUri) {
253437
- return createHash2("sha256").update(fileUri).digest("hex");
253491
+ return createHash3("sha256").update(fileUri).digest("hex");
253438
253492
  }
253439
253493
  function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger) {
253440
253494
  const router = import_express5.Router({ mergeParams: true });
@@ -253447,14 +253501,14 @@ function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger) {
253447
253501
  destination: mediaFilesDir,
253448
253502
  filename: (_req, file, cb) => {
253449
253503
  const ext = path18.extname(file.originalname);
253450
- cb(null, `${randomUUID4()}${ext}`);
253504
+ cb(null, `${randomUUID6()}${ext}`);
253451
253505
  }
253452
253506
  });
253453
253507
  const privateStorage = import_multer.default.diskStorage({
253454
253508
  destination: privateFilesDir,
253455
253509
  filename: (_req, file, cb) => {
253456
253510
  const ext = path18.extname(file.originalname);
253457
- cb(null, `${randomUUID4()}${ext}`);
253511
+ cb(null, `${randomUUID6()}${ext}`);
253458
253512
  }
253459
253513
  });
253460
253514
  const upload = import_multer.default({ storage, limits: { fileSize: MAX_FILE_SIZE } });
@@ -253519,16 +253573,16 @@ function createCustomIntegrationRoutes(remoteProxy, logger) {
253519
253573
 
253520
253574
  // src/cli/dev/dev-server/watcher.ts
253521
253575
  import { EventEmitter as EventEmitter4 } from "node:events";
253522
- import { relative as relative9 } from "node:path";
253576
+ import { relative as relative7 } from "node:path";
253523
253577
 
253524
253578
  // ../../node_modules/chokidar/index.js
253525
253579
  import { EventEmitter as EventEmitter3 } from "node:events";
253526
253580
  import { stat as statcb, Stats } from "node:fs";
253527
- import { readdir as readdir3, stat as stat6 } from "node:fs/promises";
253581
+ import { readdir as readdir3, stat as stat7 } from "node:fs/promises";
253528
253582
  import * as sp3 from "node:path";
253529
253583
 
253530
253584
  // ../../node_modules/readdirp/index.js
253531
- import { lstat as lstat2, readdir as readdir2, realpath, stat as stat4 } from "node:fs/promises";
253585
+ import { lstat as lstat2, readdir as readdir2, realpath, stat as stat5 } from "node:fs/promises";
253532
253586
  import { join as pjoin, relative as prelative, resolve as presolve, sep as psep } from "node:path";
253533
253587
  import { Readable as Readable6 } from "node:stream";
253534
253588
  var EntryTypes = {
@@ -253610,7 +253664,7 @@ class ReaddirpStream extends Readable6 {
253610
253664
  const { root, type } = opts;
253611
253665
  this._fileFilter = normalizeFilter(opts.fileFilter);
253612
253666
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
253613
- const statMethod = opts.lstat ? lstat2 : stat4;
253667
+ const statMethod = opts.lstat ? lstat2 : stat5;
253614
253668
  if (wantBigintFsStats) {
253615
253669
  this._stat = (path) => statMethod(path, { bigint: true });
253616
253670
  } else {
@@ -253763,7 +253817,7 @@ function readdirp(root, options = {}) {
253763
253817
 
253764
253818
  // ../../node_modules/chokidar/handler.js
253765
253819
  import { watch as fs_watch, unwatchFile, watchFile } from "node:fs";
253766
- import { realpath as fsrealpath, lstat as lstat3, open as open2, stat as stat5 } from "node:fs/promises";
253820
+ import { realpath as fsrealpath, lstat as lstat3, open as open2, stat as stat6 } from "node:fs/promises";
253767
253821
  import { type as osType } from "node:os";
253768
253822
  import * as sp2 from "node:path";
253769
253823
  var STR_DATA = "data";
@@ -253789,7 +253843,7 @@ var EVENTS = {
253789
253843
  };
253790
253844
  var EV = EVENTS;
253791
253845
  var THROTTLE_MODE_WATCH = "watch";
253792
- var statMethods = { lstat: lstat3, stat: stat5 };
253846
+ var statMethods = { lstat: lstat3, stat: stat6 };
253793
253847
  var KEY_LISTENERS = "listeners";
253794
253848
  var KEY_ERR = "errHandlers";
253795
253849
  var KEY_RAW = "rawEmitters";
@@ -254260,7 +254314,7 @@ class NodeFsHandler {
254260
254314
  return;
254261
254315
  if (!newStats || newStats.mtimeMs === 0) {
254262
254316
  try {
254263
- const newStats = await stat5(file);
254317
+ const newStats = await stat6(file);
254264
254318
  if (this.fsw.closed)
254265
254319
  return;
254266
254320
  const at = newStats.atimeMs;
@@ -254932,7 +254986,7 @@ class FSWatcher extends EventEmitter3 {
254932
254986
  const fullPath = opts.cwd ? sp3.join(opts.cwd, path) : path;
254933
254987
  let stats;
254934
254988
  try {
254935
- stats = await stat6(fullPath);
254989
+ stats = await stat7(fullPath);
254936
254990
  } catch (err) {}
254937
254991
  if (!stats || this.closed)
254938
254992
  return;
@@ -255204,7 +255258,7 @@ class WatchBase44 extends EventEmitter4 {
255204
255258
  ignoreInitial: true
255205
255259
  });
255206
255260
  watcher.on("all", import_debounce.default(async (_event, path) => {
255207
- this.emit("change", name, relative9(targetPath, path));
255261
+ this.emit("change", name, relative7(targetPath, path));
255208
255262
  }, WATCH_DEBOUNCE_MS));
255209
255263
  watcher.on("error", (err) => {
255210
255264
  this.logger.error(`Watch handler failed for ${targetPath}`, err);
@@ -255241,11 +255295,6 @@ async function createDevServer(options) {
255241
255295
  next();
255242
255296
  });
255243
255297
  const devLogger = createDevLogger("backend", theme.styles.info);
255244
- app.use("/api/apps/:appId/actors", (_req, res) => {
255245
- const message = "Actors are not available in local development";
255246
- devLogger.error(message);
255247
- res.status(500).json({ error: message });
255248
- });
255249
255298
  const functionManager = await createFunctionRuntime(functions, devLogger, options.denoWrapperPath);
255250
255299
  const functionRoutes = createFunctionRouter(functionManager, devLogger);
255251
255300
  app.use("/api/apps/:appId/functions", functionRoutes);
@@ -255316,8 +255365,8 @@ async function createDevServer(options) {
255316
255365
  broadcastEntityEvent(io, appId, entityName, event);
255317
255366
  };
255318
255367
  const base44ConfigWatcher = new WatchBase44({
255319
- functions: join36(dirname26(project.configPath), project.functionsDir),
255320
- entities: join36(dirname26(project.configPath), project.entitiesDir)
255368
+ functions: join37(dirname25(project.configPath), project.functionsDir),
255369
+ entities: join37(dirname25(project.configPath), project.entitiesDir)
255321
255370
  }, devLogger);
255322
255371
  base44ConfigWatcher.on("change", async (name) => {
255323
255372
  try {
@@ -255714,7 +255763,7 @@ Examples:
255714
255763
  }
255715
255764
 
255716
255765
  // src/cli/commands/project/eject.ts
255717
- import { resolve as resolve17 } from "node:path";
255766
+ import { resolve as resolve18 } from "node:path";
255718
255767
  var import_kebabCase2 = __toESM(require_kebabCase(), 1);
255719
255768
  async function eject(ctx, options, command) {
255720
255769
  const { log, runTask, isNonInteractive } = ctx;
@@ -255778,7 +255827,7 @@ async function eject(ctx, options, command) {
255778
255827
  Ne("Operation cancelled.");
255779
255828
  throw new CLIExitError(0);
255780
255829
  }
255781
- const resolvedPath = resolve17(selectedPath);
255830
+ const resolvedPath = resolve18(selectedPath);
255782
255831
  await runTask("Downloading your project's code...", async (updateMessage) => {
255783
255832
  await createProjectFilesForExistingProject({
255784
255833
  projectId,
@@ -255845,7 +255894,7 @@ function createProgram(context) {
255845
255894
  program.addCommand(getScaffoldCommand());
255846
255895
  program.addCommand(getDashboardCommand());
255847
255896
  program.addCommand(getBuildCommand());
255848
- program.addCommand(getDeployCommand3());
255897
+ program.addCommand(getDeployCommand2());
255849
255898
  program.addCommand(getVisibilityCommand());
255850
255899
  program.addCommand(getLinkCommand());
255851
255900
  program.addCommand(getEjectCommand());
@@ -255855,13 +255904,16 @@ function createProgram(context) {
255855
255904
  program.addCommand(getAgentSkillsCommand());
255856
255905
  program.addCommand(getConnectorsCommand());
255857
255906
  program.addCommand(getFunctionsCommand());
255858
- program.addCommand(getActorsCommand());
255859
255907
  program.addCommand(getWorkflowsCommand());
255860
255908
  program.addCommand(getSecretsCommand());
255861
255909
  program.addCommand(getSandboxCommand());
255862
255910
  program.addCommand(getBranchesCommand());
255863
255911
  program.addCommand(getAuthCommand());
255864
255912
  program.addCommand(getSiteCommand());
255913
+ if (versionsApiEnabled()) {
255914
+ program.addCommand(getPublishCommand());
255915
+ program.addCommand(getVersionsCommand());
255916
+ }
255865
255917
  program.addCommand(getTypesCommand());
255866
255918
  program.addCommand(getExecCommand());
255867
255919
  program.addCommand(getDevCommand());
@@ -255874,7 +255926,7 @@ var import_detect_agent = __toESM(require_dist5(), 1);
255874
255926
  import { release, type } from "node:os";
255875
255927
 
255876
255928
  // ../../node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
255877
- import { dirname as dirname27, posix, sep as sep2 } from "path";
255929
+ import { dirname as dirname26, posix, sep as sep2 } from "path";
255878
255930
  function createModulerModifier() {
255879
255931
  const getModuleFromFileName = createGetModuleFromFilename();
255880
255932
  return async (frames) => {
@@ -255883,7 +255935,7 @@ function createModulerModifier() {
255883
255935
  return frames;
255884
255936
  };
255885
255937
  }
255886
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname27(process.argv[1]) : process.cwd(), isWindows = sep2 === "\\") {
255938
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname26(process.argv[1]) : process.cwd(), isWindows = sep2 === "\\") {
255887
255939
  const normalizedBase = isWindows ? normalizeWindowsPath2(basePath) : basePath;
255888
255940
  return (filename) => {
255889
255941
  if (!filename)
@@ -257918,7 +257970,7 @@ class ReduceableCache {
257918
257970
  }
257919
257971
  }
257920
257972
  // ../../node_modules/posthog-node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs
257921
- import { createReadStream as createReadStream3 } from "node:fs";
257973
+ import { createReadStream as createReadStream4 } from "node:fs";
257922
257974
  import { createInterface as createInterface2 } from "node:readline";
257923
257975
  var LRU_FILE_CONTENTS_CACHE = new ReduceableCache(25);
257924
257976
  var LRU_FILE_CONTENTS_FS_READ_FAILED = new ReduceableCache(20);
@@ -257962,7 +258014,7 @@ async function addSourceContext(frames) {
257962
258014
  }
257963
258015
  function getContextLinesFromFile(path, ranges, output) {
257964
258016
  return new Promise((resolve) => {
257965
- const stream = createReadStream3(path);
258017
+ const stream = createReadStream4(path);
257966
258018
  const lineReaded = createInterface2({
257967
258019
  input: stream
257968
258020
  });
@@ -259872,9 +259924,9 @@ function addCommandInfoToErrorReporter(program, errorReporter) {
259872
259924
  });
259873
259925
  }
259874
259926
  // src/cli/index.ts
259875
- var __dirname4 = dirname28(fileURLToPath6(import.meta.url));
259927
+ var __dirname4 = dirname27(fileURLToPath6(import.meta.url));
259876
259928
  async function runCLI(options) {
259877
- ensureNpmAssets(join37(__dirname4, "../assets"));
259929
+ ensureNpmAssets(join38(__dirname4, "../assets"));
259878
259930
  const errorReporter = new ErrorReporter;
259879
259931
  errorReporter.registerProcessErrorHandlers();
259880
259932
  const jsonMode = process.argv.includes("--json");
@@ -259913,4 +259965,4 @@ export {
259913
259965
  runCLI
259914
259966
  };
259915
259967
 
259916
- //# debugId=B6FD4E544C62B70764756E2164756E21
259968
+ //# debugId=FEA39F6748E8A4DB64756E2164756E21